gigafibre-fsm/docs/LEGACY-FIELD-GAP-ANALYSIS.md
louispaulb bfffed2b41 feat: ONT diagnostics — grouped mesh topology, signal RSSI, management link
- EquipmentDetail: collapsible node groups (clients grouped by mesh node)
- Signal strength as RSSI % (0-255 per 802.11-2020) with 10-tone color scale
- Management IP clickable link to device web GUI (/superadmin/)
- Fibre status compact top bar (status + Rx/Tx power when available)
- targo-hub: WAN IP detection across all VLAN interfaces
- targo-hub: full WiFi client count (direct + EasyMesh mesh repeaters)
- targo-hub: /devices/:id/hosts endpoint with client-to-node mapping
- ClientsPage: start empty, load only on search (no auto-load all)
- nginx: dynamic ollama resolver (won't crash if ollama is down)
- Cleanup: remove unused BillingKPIs.vue and TagInput.vue
- New docs and migration scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 21:26:14 -04:00

257 lines
12 KiB
Markdown

# Legacy → ERPNext Field Gap Analysis
Complete audit of every legacy database field against current ERPNext doctypes.
Goal: **Zero data loss** — every meaningful field must have a home in ERPNext.
---
## 1. Customer (legacy `account` table)
### Already Migrated
| Legacy Field | ERPNext Field | Doctype | Script |
|---|---|---|---|
| id | legacy_account_id | Customer | migrate_direct.py |
| first_name + last_name | customer_name | Customer | migrate_direct.py |
| email | email_billing | Customer (custom) | import_customer_details.py |
| customer_id | legacy_customer_id | Customer | migrate_direct.py |
| address1, city, state, zip | address_line, city, province, postal_code | Service Location | migrate_locations.py |
| invoice_delivery | invoice_delivery_method | Customer (custom) | import_customer_details.py |
| commercial | is_commercial | Customer (custom) | import_customer_details.py |
| mauvais_payeur | is_bad_payer | Customer (custom) | import_customer_details.py |
| tax_group | tax_category_legacy | Customer (custom) | import_customer_details.py |
| contact | contact_name_legacy | Customer (custom) | import_customer_details.py |
| mandataire | mandataire | Customer (custom) | import_customer_details.py |
| tel_home | tel_home | Customer (custom) | import_customer_details.py |
| tel_office | tel_office | Customer (custom) | import_customer_details.py |
| cell | cell_phone | Customer (custom) | import_customer_details.py |
| fax | fax | Customer (custom) | import_customer_details.py |
| misc | notes_internal | Customer (custom) | import_customer_details.py |
| frais | exclude_fees | Customer (custom) | import_customer_details.py |
| email_autre | email_publipostage | Customer (custom) | import_customer_details.py |
| date_orig | date_created_legacy | Customer (custom) | import_customer_details.py |
### GAP — Missing Fields (need custom fields + migration)
| Legacy Field | Values/Stats | Proposed ERPNext Field | Priority |
|---|---|---|---|
| middle_name | Free text | `middle_name` Data | LOW |
| title | "M.", "Mme", etc. | `salutation_legacy` Data | LOW |
| ppa | 1,249 accounts | `ppa_enabled` Check | HIGH |
| ppa_name | Payer name | `ppa_name` Data | HIGH |
| ppa_code | Bank transit | `ppa_code` Data | HIGH |
| ppa_branch | Bank branch | `ppa_branch` Data | HIGH |
| ppa_account | Bank account | `ppa_account` Data | HIGH |
| ppa_amount | Amount | `ppa_amount` Currency | HIGH |
| ppa_amount_buffer | Buffer | `ppa_amount_buffer` Currency | MEDIUM |
| ppa_fixed | Fixed payment flag | `ppa_fixed` Check | MEDIUM |
| ppa_cc | PPA via credit card | `ppa_cc` Check | MEDIUM |
| ppa_all_invoice | Apply to all invoices | `ppa_all_invoice` Check | MEDIUM |
| vip | 28 accounts | `is_vip` Check | MEDIUM |
| stripe_id | 785 accounts | `stripe_customer_id` Data | HIGH |
| stripe_ppa | Stripe auto-pay flag | `stripe_ppa_enabled` Check | HIGH |
| land_owner | Property owner flag | `is_land_owner` Check | LOW |
| keyword | Search keyword | `search_keyword` Data | LOW |
| pub | Marketing opt-in | `marketing_optin` Check | MEDIUM |
| call | Call contact flag | `call_contact` Check | LOW |
| username | Portal login | `portal_username` Data | LOW |
| password | Portal password (MD5) | `portal_password_hash` Data | LOW |
| terminate_reason | Reason for termination | `terminate_reason` Small Text | MEDIUM |
| terminate_cie | Competitor they left for | `terminate_cie` Data | MEDIUM |
| terminate_note | Termination notes | `terminate_note` Small Text | MEDIUM |
| terminate_date | Date terminated | `terminate_date` Date | MEDIUM |
| notes_client | Client-visible notes | `notes_client` Small Text | MEDIUM |
| address2 | Address line 2 | *Already in Service Location* | — |
---
## 2. Service Subscription (legacy `service` table)
### Already Migrated
| Legacy Field | ERPNext Field | Script |
|---|---|---|
| id | legacy_service_id | import_services_and_enrich_customers.py |
| delivery_id | service_location (via map) | import_services_and_enrich_customers.py |
| device_id | device (Link to Service Equipment) | import_services_and_enrich_customers.py |
| product_id | product_sku | import_services_and_enrich_customers.py |
| status | status (mapped to Actif/Suspendu/Annulé) | import_services_and_enrich_customers.py |
| comment | notes | import_services_and_enrich_customers.py |
| payment_recurrence | billing_cycle | import_services_and_enrich_customers.py |
| hijack_price | monthly_price (when hijack=1) | import_services_and_enrich_customers.py |
| hijack_download_speed | speed_down (when hijack=1) | import_services_and_enrich_customers.py |
| hijack_upload_speed | speed_up (when hijack=1) | import_services_and_enrich_customers.py |
| date_orig | start_date | import_services_and_enrich_customers.py |
| date_end_contract | end_date | import_services_and_enrich_customers.py |
| radius_user | radius_user | import_services_and_enrich_customers.py |
| radius_pwd | radius_password | import_services_and_enrich_customers.py |
### GAP — Missing Fields
| Legacy Field | Values/Stats | Proposed ERPNext Field | Priority |
|---|---|---|---|
| hijack | Override flag (bool) | `is_custom_pricing` Check | MEDIUM |
| hijack_desc | Override description | `custom_pricing_desc` Data | MEDIUM |
| hijack_quota_day | Day bandwidth quota | `quota_day_gb` Float | LOW |
| hijack_quota_night | Night bandwidth quota | `quota_night_gb` Float | LOW |
| date_suspended | Suspension date | `date_suspended` Date | HIGH |
| actif_until | Active-until date | `active_until` Date | MEDIUM |
| date_next_invoice | Next invoice date | `next_invoice_date` Date | HIGH |
| forfait_internet | Internet bundle flag | `forfait_internet` Check | LOW |
| radius_conso | RADIUS consumption tracking | `radius_consumption` Data | LOW |
| ip_fixe | Static IP address | `static_ip` Data | MEDIUM |
---
## 3. Service Equipment (legacy `device` table)
### Already Migrated
| Legacy Field | ERPNext Field | Script |
|---|---|---|
| id | legacy_device_id | import_devices_and_enrich.py |
| delivery_id | service_location (via map) | import_devices_and_enrich.py |
| category | equipment_type (mapped) | import_devices_and_enrich.py |
| sn | serial_number | import_devices_and_enrich.py |
| mac | mac_address | import_devices_and_enrich.py |
| manufacturier | brand | import_devices_and_enrich.py |
| model | model | import_devices_and_enrich.py |
| manage / manage_cli | ip_address | import_devices_and_enrich.py |
| user | login_user | import_devices_and_enrich.py |
| pass | login_password | import_devices_and_enrich.py |
### GAP — Missing Fields
| Legacy Field | Values/Stats | Proposed ERPNext Field | Priority |
|---|---|---|---|
| manage | Full management URL/IP | `manage_url` Data | HIGH |
| port | Management port | `manage_port` Int | HIGH |
| protocol | Management protocol (http/https/ssh) | `manage_protocol` Select | HIGH |
| manage_cli | CLI access IP | `cli_ip` Data | HIGH |
| port_cli | CLI port | `cli_port` Int | HIGH |
| protocol_cli | CLI protocol (ssh/telnet) | `cli_protocol` Select | HIGH |
| parent | Parent device ID | `parent_device` Link (Service Equipment) | HIGH |
| category | Exact legacy category string | `legacy_category` Data | MEDIUM |
| name (legacy) | Device display name | `device_name` Data | LOW |
### GAP — Provisioning Fields (from GenieACS MariaDB)
| Source | Field | Proposed ERPNext Field | Priority |
|---|---|---|---|
| GenieACS wifi table | ssid | `wifi_ssid` Data | HIGH |
| GenieACS wifi table | password | `wifi_password` Password | HIGH |
| GenieACS voip table | username | `sip_username` Data | HIGH |
| GenieACS voip table | password | `sip_password` Password | HIGH |
| GenieACS devices | CWMP serial | `cwmp_serial` Data | HIGH |
| GenieACS devices | GPON serial | `gpon_serial` Data | HIGH |
| Fibre table | line_profile | `fibre_line_profile` Data | MEDIUM |
| Fibre table | service_profile | `fibre_service_profile` Data | MEDIUM |
### GAP — ACS Integration Fields
| Purpose | Proposed ERPNext Field | Priority |
|---|---|---|
| GenieACS/Oktopus device ID | `acs_device_id` Data | HIGH |
| Last ACS inform time | `acs_last_inform` Datetime | MEDIUM |
| ACS online status | `acs_online` Check | MEDIUM |
| WAN IP from ACS | `wan_ip` Data | MEDIUM |
---
## 4. Service Location (legacy `delivery` + `fibre` tables)
### Already Migrated
| Legacy Field | ERPNext Field | Script |
|---|---|---|
| delivery.id | legacy_delivery_id | migrate_locations.py |
| delivery.address1 | address_line | migrate_locations.py |
| delivery.city | city | migrate_locations.py |
| delivery.state | province | migrate_locations.py |
| delivery.zip | postal_code | migrate_locations.py |
| delivery.account_id | customer (via map) | migrate_locations.py |
| fibre.frame/slot/port/ontid | olt_port | import_devices_and_enrich.py |
| fibre.vlan_* | network_id (concatenated) | import_devices_and_enrich.py |
| *connection_type inferred* | connection_type | import_devices_and_enrich.py |
### GAP — Missing Fields from `delivery`
| Legacy Field | Proposed ERPNext Field | Priority |
|---|---|---|
| address2 | `address_line_2` Data | MEDIUM |
| contact | `contact_name` (already exists) | — |
| phone | `contact_phone` (already exists) | — |
| note | `delivery_notes` Small Text | MEDIUM |
| appartement | `apartment_number` Data | MEDIUM |
### GAP — Missing Fields from `fibre`
| Legacy Field | Values/Stats | Proposed ERPNext Field | Priority |
|---|---|---|---|
| id | 16,056 entries | `legacy_fibre_id` Int | MEDIUM |
| sn | ONT serial number | `ont_serial` Data | HIGH |
| olt_ip (info_connect) | OLT management IP | `olt_ip` Data | HIGH |
| olt_name (from fibre_olt) | OLT display name | `olt_name` Data | MEDIUM |
| ontid | ONT ID on OLT port | `ont_id` Int | HIGH |
| terrain | Property type | `terrain_type` Data | LOW |
| distance | Distance from OLT | `fibre_distance_m` Float | LOW |
| nb_portees | Number of spans | `fibre_spans` Int | LOW |
| temps_estim | Estimated install time | `install_time_estimate` Data | LOW |
| suite | Apartment indicator | `is_apartment` Check | LOW |
| boitier_pas_install | Box not installed flag | `box_not_installed` Check | LOW |
| vlan_manage | Management VLAN (individual) | `vlan_manage` Int | MEDIUM |
| vlan_internet | Internet VLAN | `vlan_internet` Int | MEDIUM |
| vlan_telephone | Telephone VLAN | `vlan_telephone` Int | MEDIUM |
| vlan_tele | TV VLAN | `vlan_tv` Int | MEDIUM |
| manage_service_id | Mgmt service link | `manage_service_id` Int | LOW |
| internet_service_id | Internet service link | `internet_service_id` Int | LOW |
| telephone_service_id | Phone service link | `telephone_service_id` Int | LOW |
| tele_service_id | TV service link | `tv_service_id` Int | LOW |
| placemarks_id | Map placement ID | `placemarks_id` Data | LOW |
| appartements_id | Apartment building ID | `apartment_building_id` Data | LOW |
---
## 5. device_attr (key-value pairs, 497 entries)
No ERPNext equivalent exists. Contains per-device extended attributes:
- **MAC addresses per interface** (eth0 through eth5) — multiple MACs per device
- **stb_id** — Ministra/IPTV subscription ID
- **Custom OLT references**
- **Router routes** (static routes configured on device)
### Proposed Solution
| Attribute Key | Proposed ERPNext Field | On Doctype | Priority |
|---|---|---|---|
| mac_ethX | `mac_addresses_json` Long Text (JSON) | Service Equipment | MEDIUM |
| stb_id | `iptv_subscription_id` Data | Service Equipment | HIGH |
| OLT refs | Already captured via fibre table | Service Location | — |
---
## 6. Dispatch Job (legacy `bon_travail` table)
### Already Migrated
Dispatch Job doctype exists with custom FSM fields. However:
### GAP — Missing Fields from `bon_travail`
| Legacy Field | Proposed ERPNext Field | Priority |
|---|---|---|
| tech1_id | Already `assigned_to` on Dispatch Job | — |
| tech2_id | `second_technician` Data | MEDIUM |
| tech1_arrive | `tech1_arrival` Datetime | MEDIUM |
| tech1_depart | `tech1_departure` Datetime | MEDIUM |
| tech2_arrive | `tech2_arrival` Datetime | MEDIUM |
| tech2_depart | `tech2_departure` Datetime | MEDIUM |
| line items (bon_travail_item) | Already `equipment_items` + `materials_used` child tables | — |
---
## Summary: Custom Fields to Add
### Customer — 23 new fields
PPA section (8), Stripe (2), Termination (4), VIP/flags (3), Portal (2), Other (4)
### Service Subscription — 10 new fields
Custom pricing (3), Dates (3), Quotas (2), IP (1), Other (1)
### Service Equipment — 17 new fields
Management (6), Provisioning (8), ACS (4), Legacy (1)
### Service Location — 18 new fields
Fibre infrastructure (10), VLANs (4), Legacy IDs (4)
### Dispatch Job — 5 new fields
Second tech + time tracking (5)
**Total: ~73 custom fields across 5 doctypes**