Skip to main content

Pipeline des Bills — architecture et ajout d’un nouveau type

Comment ça fonctionne

Le système de bills traverse la configuration, le backend Node.js/BrainCloud, la sérialisation, les données Unity et l'UI. Ajouter un nouveau bill seulement dans un de ces endroits produit typiquement un bill qui n'est jamais généré, qui ne peut pas être désérialisé, ou qui s'affiche avec le mauvais template.

Cette page décrit le pipeline complet et sert surtout de checklist lorsqu'un nouveau type de bill est ajouté.

1. Architecture complète

flowchart LR
    DEF[bills_settings_definitions.json] --> WIZ[Configuration module / wizard]
    MOD[modules_settings_definitions.json] --> WIZ
    WIZ --> CFG[bills_type_data + bills_category_settings]

    CFG --> CREATE[createBills()]
    CREATE --> CTX[BillCreationContext]
    CTX --> FACTORY[BillFactory.BILL_MAPPING]
    FACTORY --> CLASS[Classe Bill JS concrète]
    CLASS --> BCTX[BillContext]
    BCTX --> SERIAL[Serialized billsData + billsOrder + partners]

    SERIAL --> TMTD[Unity TeamModuleTypeData]
    TMTD --> BILL[Bill.cs]
    BILL --> DATA[BillDataBase.CreateBillData]
    DATA --> WINDOW[BillWindowControl]
    WINDOW --> TEMPLATE[BillTemplateType / BillControlBase]
    TEMPLATE --> USER[Bill affiché à l'utilisateur]

2. Phase A — configuration

La configuration d'un bill commence dans bills_settings_definitions.json. Chaque clé représente un bill configurable et décrit notamment son category, son num_bills, ses conditions de visibilité et ses champs supplémentaires.

modules_settings_definitions.json choisit ensuite quelles definitions de bills sont disponibles pour chaque type de module. Les valeurs réellement choisies finissent dans les settings du module sous bills_type_data. Les options communes à une famille sont dans bills_category_settings.

flowchart TD
    BSD[bills_settings_definitions.json] --> BILLDEF[Definition du type]
    MSD[modules_settings_definitions.json] --> EXPOSE[Expose le type dans le module]
    BILLDEF --> WIZ[BillsDataWizardPageControl]
    EXPOSE --> WIZ
    WIZ --> BTD[bills_type_data]
    WIZ --> BCS[bills_category_settings]
    BTD --> SERVER[Backend de génération]
    BCS --> SERVER

3. Phase B — génération backend

Le point de départ serveur est createBills() dans byModule_utils_create_module_type_data_functions.js. Il initialise BillCreationContext, regroupe la configuration par type, applique les catégories aléatoires, puis génère les types dans un ordre déterministe.

Ordre de calcul

BillCreationContext._billTypeComputingOrder n'est pas décoratif. Plusieurs bills dépendent de bills créés avant eux : checks, credit notes, reports, notes receivable, régularisations, etc. Un nouveau type qui dépend d'un autre doit donc être placé après sa dépendance.

sequenceDiagram
    participant C as createBills()
    participant BC as BillCreationContext
    participant F as BillFactory
    participant B as Classe Bill
    participant X as BillContext

    C->>BC: init(random, settings, context, dates)
    C->>C: groupe bills_type_data par type
    loop _billTypeComputingOrder
        C->>F: createBills(billTypeData)
        F->>F: BILL_MAPPING[type]
        F->>B: new ConcreteBill(...)
        B-->>BC: addBill(uid, bill)
    end
    C->>X: init(... bills générés ...)
    X->>X: post-processing / tri / sérialisation
    X-->>C: billsData + billsOrder + partners + taxes

Factory backend

BillFactory.BILL_MAPPING est le dispatch principal string type → fonction de création. Une entrée peut pointer directement vers une fonction ou passer par conditionallyCreateBills(...) pour respecter une feature flag/préférence comme employés, taxes, banking, immobilisations ou forme juridique.

Les fonctions de création choisissent les partenaires, dates, produits/services, montants et objets dépendants, construisent la classe de bill puis appellent BillCreationContext.addBill().

4. Phase C — classes et sérialisation serveur

Les classes serveur se trouvent sous :

master/node.js/backend/braincloud/server_scripts/_utils/by_module/classes/bills/

Il existe des classes de base et des familles spécialisées : checks, reports, contracts, immobilizations, etc. Une classe concrète est nécessaire lorsqu'un type possède une structure, un calcul ou des références spécifiques qui ne peuvent pas être représentés par une classe existante.

flowchart TD
    BASE[BillBase JS] --> EXIST{Structure existante suffisante ?}
    EXIST -->|Oui| REUSE[Réutiliser classe existante]
    EXIST -->|Non| NEW[Créer ConcreteBill.js]
    NEW --> SER[serialize()]
    NEW --> DES[deserialize()]
    NEW --> CALC[calculs / références spécifiques]
    REUSE --> CTX[BillContext]
    SER --> CTX
    CTX --> JSON[bills.billsData]

BillContext._deserializeBills() utilise utilsByModule.getBillClassFromType() pour reconstruire les bonnes classes à partir de JSON déjà sérialisé. C'est donc un deuxième mapping backend à ne pas oublier lorsqu'un nouveau type nécessite une classe.

5. Phase D — chargement dans Unity

TeamModuleTypeData.Deserialize() charge d'abord les partenaires, services, dépenses, contrats, immobilisations, taxes et autres dépendances. Ensuite il parcourt bills.billsData et construit chaque Bill.

Bill.Deserialize() lit le billType, puis appelle BillDataBase.CreateBillData(billType) afin de créer la bonne structure de données Unity avant de désérialiser billData.

sequenceDiagram
    participant JSON as Team module JSON
    participant T as TeamModuleTypeData
    participant B as Bill
    participant F as BillDataBase.CreateBillData
    participant D as Concrete BillData

    JSON->>T: billsData + partners + dépendances
    T->>B: new Bill + Deserialize(...)
    B->>B: BillBase.Deserialize billType
    B->>F: CreateBillData(billType)
    F-->>B: instance Concrete BillData
    B->>D: Deserialize(billData, dependencies...)
    B-->>T: Bill complet
    T->>T: bills[uid] + billsOrder

6. Phase E — affichage Unity

BillWindowControl.GetBillTemplateTypeFromBillType() choisit le template UI à utiliser. Plusieurs types partagent le même template : Sales, Check, OperatingCost, Memo, Letter, Payslip, CreditNote, etc.

Le template est ensuite alloué depuis un pool et reçoit le bill via BillControlBase.SetData(). Les contrôles spécialisés castent le billData lorsque des champs spécifiques doivent être affichés.

flowchart LR
    B[Bill + BillData] --> MAP[BillWindowControl.GetBillTemplateTypeFromBillType]
    MAP --> SALES[Sales]
    MAP --> CHECK[Check]
    MAP --> OP[OperatingCost]
    MAP --> LETTER[Letter]
    MAP --> MEMO[Memo]
    MAP --> REPORT[Report spécialisé]
    SALES --> SET[BillControlBase.SetData]
    CHECK --> SET
    OP --> SET
    LETTER --> SET
    MEMO --> SET
    REPORT --> SET
    SET --> UI[UI finale]

7. État « finished »

Le fait qu'un étudiant ait terminé de traiter un bill est séparé du bill lui-même. Unity conserve finishedBills dans TeamModuleTypeData. BillWindowControl permet de modifier l'état et le backend persiste la liste via la custom command gérée par saveTeamModuleFinishedBills().

8. Ajouter un nouveau type de bill — checklist obligatoire

Exemple : ajout d'un type serveur new_bill.

# Fichier / zone Modification Obligatoire ?
1 Assets/.../data_byModule/bills_settings_definitions.json Créer la definition new_bill avec category, num_bills, visibilité et champs nécessaires. Oui si le bill est configurable/généré par settings.
2 modules_settings_definitions.json Ajouter new_bill dans la liste bills des types de modules qui doivent pouvoir le configurer. Oui pour l'exposer dans le wizard concerné.
3 BillCreationContext.js Ajouter new_bill dans _billTypeComputingOrder, à l'endroit correct selon ses dépendances. Oui pour un bill généré par le pipeline standard.
4 BillFactory.js Ajouter BILL_MAPPING["new_bill"] et implémenter/réutiliser la fonction de création. Oui.
5 classes/bills/.../*.js Créer une classe JS si le bill ne peut pas réutiliser une classe existante; implémenter sérialisation/désérialisation et logique spécifique. Conditionnel.
6 BillFactory.js includes Inclure la nouvelle classe serveur si une nouvelle classe est créée. Conditionnel.
7 byModule_utils.js → getBillClassFromType() Mapper new_bill vers la classe JS utilisée pour désérialiser les bills existants/contextes. Oui si nouvelle classe/type sérialisé.
8 Assets/Src/Game/Data/ByModule/BillBase.cs Ajouter le nom string, l'enum BillType, GetBillNameFromType(), GetBillTypeFromName() et vérifier les switches de taxes/partenaires/type simplifié. Oui.
9 Assets/Src/UI/SimByModule/Data/Runtime/BillDataBase.cs Ajouter le mapping dans CreateBillData() vers une classe existante ou une nouvelle classe BillData.... Oui.
10 Assets/Src/UI/SimByModule/Data/Runtime/BillData*.cs Créer la classe data Unity si le JSON billData a une forme ou des calculs propres. Conditionnel.
11 Assets/Src/UI/SimByModule/UI/BillWindowControl.cs Mapper le nouveau BillType vers le bon BillTemplateType. Oui.
12 BillControlBase.cs / contrôle spécialisé Vérifier titre, sender/receiver, taxes, total et raw data. Créer/modifier un contrôle si le template existant ne suffit pas. Conditionnel mais à vérifier systématiquement.
13 Prefab/template Unity du bill Créer ou brancher un prefab si un nouveau BillTemplateType ou une mise en page spécifique est nécessaire. Conditionnel.
14 Textes/localisation Ajouter les clés utilisées par GetSimplifiedBillTypeName(), titre, memo, descriptions ou labels spécialisés. Selon UI.
15 Accounting switches / Utils Rechercher le nouveau type dans les règles de taxes, partenaires, journaux, inventory, regularizations, reports et autres traitements. À auditer systématiquement.

9. Fichiers critiques — ne pas oublier

Backend Node.js / BrainCloud

  • backend/braincloud/server_scripts/_utils/by_module/functions/byModule_utils_create_module_type_data_functions.js — orchestration createBills().
  • backend/braincloud/server_scripts/_utils/by_module/contexts/BillCreationContext.js — contexte global, ordre de calcul, partenaires/dates/dépendances.
  • backend/braincloud/server_scripts/_utils/by_module/factories/BillFactory.js — mapping type → création et includes des classes.
  • backend/braincloud/server_scripts/_utils/by_module/contexts/BillContext.js — post-processing, désérialisation, ordre et sérialisation finale.
  • backend/braincloud/server_scripts/_utils/by_module/byModule_utils.js — getBillClassFromType() et plusieurs règles Accounting transversales.
  • backend/braincloud/server_scripts/_utils/by_module/classes/bills/ — implémentations concrètes.
  • backend/braincloud/server_scripts/_utils/command/utils_custom_command_by_module.js — actions runtime persistées, notamment finishedBills et autres mutations de module.

Unity / Game

  • Assets/Src/Game/Data/ByModule/BillBase.cs — enum et conversion string/type, taxes et helpers communs.
  • Assets/Src/Game/Data/ByModule/TeamModuleTypeData.cs — désérialisation du payload complet de bills.
  • Assets/Src/UI/SimByModule/Data/Runtime/Bill.cs — objet runtime principal.
  • Assets/Src/UI/SimByModule/Data/Runtime/BillDataBase.cs — factory du billData.
  • Assets/Src/UI/SimByModule/Data/Runtime/BillData*.cs — structures spécifiques.
  • Assets/Src/UI/SimByModule/UI/BillWindowControl.cs — sélection du template et affichage/finalisation.
  • Assets/Src/UI/SimByModule/UI/BillControlBase.cs — affichage commun, taxes/total, titres et raw data.
  • Assets/Src/UI/SimByModule/UI/*BillControl.cs — contrôles spécialisés.
  • Assets/Src/Game/Data/ByModule/ModuleSettingsBase.cs — settings runtime des bills.
  • Assets/Src/UI/SimByModule/Data/BillsDataWizardPageControl.cs — configuration dans l'éditeur.

Configuration

  • Assets/GameSpecific/byModule/Resources/data_byModule/bills_settings_definitions.json
  • Assets/GameSpecific/byModule/Resources/data_byModule/bills_category_settings_definitions.json
  • Assets/GameSpecific/byModule/Resources/data_byModule/modules_settings_definitions.json
  • Assets/GameSpecific/byModule/Resources/data_byModule/modules_settings.json pour les defaults applicables.
  • accounts.json, taxes.json, interests.json, immobilizations.json, contract_regularizations.json lorsque le nouveau bill dépend de ces domaines.

10. Audit obligatoire après ajout

Après avoir ajouté le string du nouveau type, faire une recherche globale sur les endroits qui switchent sur les bill types. Le code actuel contient plusieurs décisions distribuées qui ne passent pas toutes par une factory unique.

git grep -n "new_bill" master/game master/node.js

git grep -n "BillType.eNewBill" master/game

git grep -n "switch.*billType|switch.*bill.billType" master/game master/node.js

Les hotspots les plus importants sont : taxes, sélection du partenaire fiscal, type simplifié/titre, mapping du template, génération d'entrées comptables, stock/inventaire, reports/régularisations et dépendances entre bills.

11. Test mental minimal d’un nouveau bill

flowchart TD
    CFG[Le wizard peut le configurer ?] --> GEN[Le serveur le génère ?]
    GEN --> SER[Il se serialize puis se deserialize ?]
    SER --> UNITY[Unity reconnait son BillType ?]
    UNITY --> DATA[CreateBillData retourne le bon data ?]
    DATA --> UI[BillWindow choisit le bon template ?]
    UI --> NUM[Totaux/taxes/entries corrects ?]
    NUM --> STATE[Finished state et reload corrects ?]
    STATE --> MULTI[Reload / autre client / contexte précédent correct ?]

Si une seule étape échoue, le nouveau bill n'est pas réellement intégré de bout en bout.