gigafibre-fsm/docs/ARCHITECTURE-COMPARE.md
louispaulb 93dd7a525f feat: migration legacy → ERPNext phases 1-4 complete
Phase 1: 833 Items + 34 Item Groups + custom fields (ISP speeds, RADIUS, legacy IDs)
Phase 2: 6,667 Customers + Contacts + Addresses via direct PG (~30s)
Phase 3: Tax template QC TPS+TVQ + 92 Subscription Plans
Phase 4: 21,876 Subscriptions with RADIUS data

CRITICAL: ERPNext scheduler is PAUSED — do not reactivate without explicit go.

Includes:
- ARCHITECTURE-COMPARE.md: full schema mapping legacy vs ERPNext
- CHANGELOG.md: detailed migration log
- MIGRATION-PLAN.md: strategy and next steps
- scripts/migration/: idempotent Python scripts (direct PG method)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:35:02 -04:00

28 KiB

Architecture comparative — Legacy vs ERPNext

1. Schéma relationnel Legacy (gestionclient / MariaDB)

┌─────────────────────────────────────────────────────────────────────┐
│                         CLIENTS & ADRESSES                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  account (15,303)                    delivery (17,114)              │
│  ├─ id (PK)                          ├─ id (PK)                    │
│  ├─ customer_id (ex: DR2)            ├─ account_id → account.id    │
│  ├─ first_name, last_name            ├─ name (label)               │
│  ├─ company                          ├─ address1, city, zip        │
│  ├─ email, tel_home, cell            ├─ longitude, latitude        │
│  ├─ address1, city, zip              └─ contact, email             │
│  ├─ status (1=actif,4=terminé)                                     │
│  ├─ group_id (5=rés, 8=com)                                       │
│  ├─ ppa, ppa_code, ppa_account   ← PPA AccesD Desjardins          │
│  ├─ stripe_id                     ← Paiement carte                 │
│  ├─ tax_group                                                      │
│  └─ language_id                                                     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     SERVICES & FORFAITS                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  service (66,879)                    product (833)                  │
│  ├─ id (PK)                          ├─ id (PK)                    │
│  ├─ delivery_id → delivery.id        ├─ sku (ex: FTTH150I)        │
│  ├─ device_id → device.id            ├─ price                      │
│  ├─ product_id → product.id          ├─ active                     │
│  ├─ status (1=actif, 0=inactif)      ├─ category → product_cat.id │
│  ├─ date_orig, date_next_invoice     ├─ download_speed (Kbps)      │
│  ├─ payment_recurrence               ├─ upload_speed (Kbps)        │
│  ├─ hijack (prix spécial)            ├─ quota_day, quota_night     │
│  ├─ hijack_price, hijack_desc        ├─ fibre_lineprofile          │
│  ├─ radius_user, radius_pwd          └─ fibre_serviceprofile       │
│  ├─ date_end_contract                                              │
│  └─ actif_until                      product_cat (34)              │
│                                       ├─ id, name                  │
│  Note: service EST l'abonnement.      ├─ num_compte (→ compta)     │
│  Un client a N services actifs.       └─ combo_dispo               │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     FACTURATION & PAIEMENTS                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  invoice (629,944)                   payment (540,522)             │
│  ├─ id (PK)                          ├─ id (PK)                    │
│  ├─ account_id → account.id          ├─ account_id → account.id   │
│  ├─ date_orig (unix timestamp)       ├─ date_orig                  │
│  ├─ total_amt, billed_amt            ├─ amount                     │
│  ├─ billing_status (0=draft,1=ok)    ├─ type (chèque,PPA,CC...)   │
│  ├─ process_status                   ├─ reference                  │
│  ├─ due_date                         └─ applied_amt               │
│  ├─ notes, template_message                                        │
│  └─ ppa_charge                       payment_item (684,778)        │
│                                       ├─ payment_id → payment.id   │
│  invoice_item (1,859,260)             ├─ invoice_id → invoice.id   │
│  ├─ invoice_id → invoice.id          └─ amount                    │
│  ├─ service_id → service.id                                        │
│  ├─ sku → product.sku               invoice_tax (par facture)      │
│  ├─ quantity, unitary_price           ├─ invoice_id                │
│  └─ product_name                      ├─ tax_id → tax.id          │
│                                       └─ amount                    │
│  tax (4)                                                            │
│  ├─ TPS 5%, TVQ 8.925/9.975%                                      │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     COMPTABILITÉ                                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  compta_comptes (48)                 compta_journal_ecriture (1.2M)│
│  ├─ id, num_compte (ex: 4020)       ├─ id                         │
│  ├─ category (Actif/Passif/Rev)      ├─ date                      │
│  └─ desc                             ├─ compta_id → comptes.id    │
│                                       ├─ debit, credit             │
│  compta_setup                         └─ desc                      │
│  └─ month_closed (fermeture)                                       │
│                                                                     │
│  LOGIQUE: product_cat.num_compte lie chaque catégorie              │
│  de produit à un compte de revenus (ex: cat 32 → 4020)            │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     RÉSEAU & ÉQUIPEMENTS                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  device (10,377)                     fibre (16,057)                │
│  ├─ id (PK)                          ├─ id (PK)                    │
│  ├─ delivery_id → delivery.id        ├─ service_id → service.id   │
│  ├─ category, name                   ├─ terrain, rue, ville        │
│  ├─ sn (serial number)              ├─ frame, slot, port          │
│  ├─ mac                              ├─ vlan_manage/internet/tel   │
│  ├─ model, manufacturier             ├─ ontid, sn                  │
│  ├─ manage (IP admin)                ├─ info_connect (IP OLT)     │
│  ├─ user, pass                       ├─ latitude, longitude       │
│  └─ parent (device hiérarchie)       └─ placemarks_id             │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     TICKETS & SUPPORT                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ticket (242,618)                    ticket_msg (784,290)          │
│  ├─ id (PK)                          ├─ id                         │
│  ├─ account_id → account.id          ├─ ticket_id → ticket.id     │
│  ├─ delivery_id → delivery.id        ├─ msg (mediumtext, base64)  │
│  ├─ subject                          └─ unread_csv                 │
│  ├─ dept_id → ticket_dept.id                                       │
│  ├─ assign_to → staff.id            ticket_dept (21)              │
│  ├─ status (open/pending/closed)     ├─ Support, Facturation       │
│  ├─ due_date, priority               ├─ Installation, Réparation  │
│  ├─ wizard (JSON install data)       └─ Vente, SysAdmin, etc.     │
│  └─ wizard_fibre                                                    │
│                                                                     │
│  bon_travail (14,472)                staff (155)                   │
│  ├─ account_id, tech1, tech2         ├─ username, password         │
│  ├─ heure_arrive/depart              ├─ first_name, last_name     │
│  └─ subtotal, tps, tvq, total        ├─ email, cell, ext          │
│                                       ├─ rights (serialized PHP)   │
│                                       └─ dept_list                  │
└─────────────────────────────────────────────────────────────────────┘

2. Schéma ERPNext cible

┌─────────────────────────────────────────────────────────────────────┐
│                         CLIENTS & ADRESSES                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Customer                            Address                        │
│  ├─ name (PK, auto)                 ├─ name (PK, auto)            │
│  ├─ customer_name                    ├─ address_title              │
│  ├─ customer_type (Ind/Company)      ├─ address_line1, city        │
│  ├─ customer_group                   ├─ state, pincode, country    │
│  ├─ territory (Canada)              ├─ latitude, longitude         │
│  ├─ *legacy_account_id    ← NEW     ├─ links[] → Customer         │
│  ├─ *legacy_customer_id   ← NEW     └─ address_type               │
│  ├─ *ppa_enabled          ← NEW                                   │
│  ├─ *stripe_id            ← NEW     Contact                       │
│  └─ disabled                         ├─ first_name, last_name     │
│                                       ├─ email_ids[], phone_nos[] │
│  Note: Customer est SÉPARÉ de         └─ links[] → Customer       │
│  Address et Contact (pattern ERPNext)                              │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     SERVICES & FORFAITS                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Item (type=Service)                 Subscription                  │
│  ├─ item_code (= legacy SKU)        ├─ party_type = Customer       │
│  ├─ item_name                        ├─ party → Customer           │
│  ├─ item_group → Item Group          ├─ plans[] → Subscription Plan│
│  ├─ standard_rate                    ├─ start_date, end_date       │
│  ├─ *legacy_product_id    ← NEW     ├─ status (Active/Cancelled)  │
│  ├─ *download_speed       ← NEW     ├─ generate_invoice_at        │
│  ├─ *upload_speed         ← NEW     ├─ sales_tax_template         │
│  ├─ *quota_day_gb         ← NEW     ├─ *radius_user       ← NEW  │
│  ├─ *quota_night_gb       ← NEW     ├─ *radius_pwd        ← NEW  │
│  ├─ *fibre_lineprofile    ← NEW     └─ *legacy_service_id ← NEW  │
│  └─ *fibre_serviceprofile ← NEW                                   │
│                                       Subscription Plan            │
│  Item Group (34)                      ├─ plan_name                 │
│  ├─ Services/                         ├─ item → Item               │
│  │   ├─ Mensualités fibre            ├─ cost (prix fixe)          │
│  │   ├─ Mensualités sans fil         ├─ billing_interval = Month  │
│  │   ├─ Téléphonie                   └─ currency = CAD            │
│  │   └─ ...16 sous-groupes                                        │
│  ├─ Products/                                                      │
│  │   ├─ Équipement fibre            Note: hijack_price du legacy  │
│  │   ├─ Quincaillerie               → additional_discount sur     │
│  │   └─ ...8 sous-groupes             la Subscription              │
│  └─ Frais et ajustements/                                          │
│      └─ ...10 sous-groupes                                         │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     FACTURATION & PAIEMENTS                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Sales Invoice                       Payment Entry                 │
│  ├─ customer → Customer              ├─ party → Customer           │
│  ├─ posting_date                     ├─ posting_date               │
│  ├─ items[] (child table)            ├─ paid_amount                │
│  │   ├─ item_code → Item             ├─ references[] (child)      │
│  │   ├─ qty, rate                    │   ├─ reference_name → SINV │
│  │   └─ amount                       │   └─ allocated_amount      │
│  ├─ taxes[] → Tax Template           ├─ mode_of_payment           │
│  ├─ grand_total                      └─ reference_no              │
│  ├─ status (Draft/Submitted/Paid)                                  │
│  └─ is_return (pour crédits)        Payment Reconciliation        │
│                                       └─ auto-match paiements     │
│  Sales Taxes Template                                              │
│  ├─ TPS 5%                           Journal Entry                │
│  └─ TVQ 9.975%                       └─ Opening balance           │
│                                                                     │
│  NATIF: Subscription génère auto les Sales Invoice chaque mois    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     RÉSEAU & ÉQUIPEMENTS (FSM)                      │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Service Location (custom)           Service Equipment (custom)    │
│  ├─ name (LOC-#####)                ├─ name (EQP-#####)           │
│  ├─ customer → Customer              ├─ location → Service Loc    │
│  ├─ address → Address                ├─ serial_number (SN)        │
│  ├─ gps_lat, gps_lon                ├─ mac_address               │
│  ├─ connection_type (FTTH/Wireless)  ├─ equipment_type            │
│  ├─ olt_ip, olt_frame/slot/port     ├─ status                    │
│  └─ vlan_internet/tele/manage        └─ model, manufacturer      │
│                                                                     │
│  Dispatch Job (custom)               Dispatch Technician (custom) │
│  ├─ customer, service_location       ├─ full_name, phone          │
│  ├─ job_type (Install/Repair/...)    ├─ traccar_device_id         │
│  ├─ assigned_tech                    └─ status                    │
│  ├─ scheduled_date/time                                            │
│  └─ equipment[], checklist[]                                       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                     TICKETS & SUPPORT                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Issue (natif ERPNext HD)            Employee (natif ERPNext HR)   │
│  ├─ subject                          ├─ employee_name              │
│  ├─ customer → Customer              ├─ department                 │
│  ├─ issue_type → ticket_dept         ├─ user_id → User            │
│  ├─ priority                         └─ cell_phone, email         │
│  ├─ status (Open/Replied/Closed)                                   │
│  ├─ description (HTML)              Note: staff.rights (PHP)      │
│  └─ resolution_details              → Rôles ERPNext               │
│                                                                     │
│  Issue peut contenir des Comments (Communication)                  │
│  → ticket_msg.msg migré ici (base64 images → fichiers)            │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3. Mapping table par table

Legacy Table Records ERPNext DocType Custom Fields Notes
account 15,303 Customer legacy_account_id, legacy_customer_id, ppa_enabled, stripe_id status 1→enabled, 4→disabled
account (contact) Contact email, tel, cell séparés
delivery 17,114 Address + Service Location latitude, longitude GPS dans Address natif
product 833 Item legacy_product_id, download/upload_speed, quota_gb, fibre_profiles FAIT
product_cat 34 Item Group FAIT
service 66,879 Subscription radius_user, radius_pwd, legacy_service_id hijack → discount
invoice 629,944 Sales Invoice Opening balance pour historique
invoice_item 1,859,260 Sales Invoice Item Idem
payment 540,522 Payment Entry Opening balance pour historique
payment_item 684,778 Payment Entry Reference Idem
tax 4 Sales Taxes Template TPS 5% + TVQ 9.975%
compta_comptes 48 Account (Chart) Map → plan comptable canadien existant
compta_journal 1.2M Journal Entry Opening balance seulement
device 10,377 Service Equipment FSM custom doctype
fibre 16,057 Service Location (champs OLT) FSM custom doctype
ticket 242,618 Issue AI knowledge base
ticket_msg 784,290 Communication base64 → File uploads
bon_travail 14,472 Dispatch Job FSM custom doctype
staff 155 Employee rights → Roles
ticket_dept 21 Issue Type Support, Facturation, etc.

4. Différences d'architecture clés

Ce qui change fondamentalement

Aspect Legacy ERPNext
Nommage ID numérique auto-inc Naming series (CUST-.YYYY.-, etc.)
Client/Adresse Tout dans account Séparé : Customer + Address + Contact
Abonnement service = ligne active Subscription génère auto les factures
Prix spécial hijack_price sur service additional_discount sur Subscription ou Pricing Rule
Taxes Calculées dans PHP Template TPS+TVQ auto-appliqué
Comptabilité Écritures manuelles PHP GL Entry auto depuis Sales Invoice
Permissions staff.rights (PHP serialize) Rôles + DocType permissions
Fichiers Base64 dans mediumtext File doctype → /files/ directory
RADIUS Champs sur service Custom fields sur Subscription
Dates Unix timestamp (bigint) ISO date (YYYY-MM-DD)

Ce qui reste pareil

  • SKU des produits
  • Structure client → N adresses → N services
  • Facturation mensuelle récurrente
  • Système de tickets/support

5. Flux opérationnels comparés

Facturation mensuelle

Legacy :

CRON → task_charge_recurrent.php
  → SELECT services WHERE date_next_invoice < NOW()
  → INSERT invoice + invoice_items
  → UPDATE service.date_next_invoice + 1 month
  → task_generate_statement.php (PDF)
  → task_mail.php (envoi email)

ERPNext :

Scheduler → Subscription.process()
  → Auto-génère Sales Invoice (draft ou submitted)
  → Taxes auto-appliquées via template
  → Email via Print Format + Email Account
  → Payment Entry (PPA/Stripe) auto-réconcilié

Nouveau client

Legacy :

account_add.php → INSERT account
delivery_add.php → INSERT delivery
service_add.php → INSERT service + UPDATE radius
invoice_add.php → première facture manuelle

ERPNext :

Customer (create) → Address (link) → Contact (link)
Subscription (create, plans=[Item]) → auto-generates invoices
Webhook → n8n → FreeRADIUS (create user)

Ticket support

Legacy :

ticket_new.php → INSERT ticket
ticket_view.php → INSERT ticket_msg (avec base64 images)
Assignation manuelle (assign_to → staff.id)

ERPNext :

Issue (create) → Communication (messages)
Assignment Rule (auto-assignation par type)
SLA tracking natif
File upload pour images (pas de base64)

6. État de la migration

Phase Statut Détail
1a. Item Groups Fait 34 groupes, 3 parents
1b. Items Fait 833 items, vitesses, quotas, legacy IDs
1c. Custom Fields Fait Item (8), Customer (4), Subscription (3)
2. Customers + Contacts + Addresses Fait 6,667 Customers + ~6,600 Contacts + ~6,700 Addresses via direct PG (migrate_direct.py, ~30s)
3. Tax Templates + Subscription Plans Fait QC TPS 5% + TVQ 9.975%, 92 Subscription Plans
4. Subscriptions Fait 21,876 Subscriptions avec RADIUS data. Scheduler PAUSED
5. Opening Balance Planifié Soldes calculés legacy — prochaine étape
6. Tickets → Issues Phase 2 242K tickets, extraction base64
7. Sync bidirectionnelle Phase 2 n8n ETL nightly

⚠ ATTENTION : Le scheduler ERPNext est PAUSED. Ne pas réactiver sans instruction explicite — cela déclencherait la facturation automatique des 21,876 abonnements.