docs
This commit is contained in:
@@ -69,6 +69,10 @@ Guide rapide pour les agents qui codent dans ce repository.
|
|||||||
- `notes/business_rules.md`
|
- `notes/business_rules.md`
|
||||||
- Regles metier locales `purchase_trade`:
|
- Regles metier locales `purchase_trade`:
|
||||||
- `modules/purchase_trade/docs/business-rules.md`
|
- `modules/purchase_trade/docs/business-rules.md`
|
||||||
|
- `modules/purchase_trade/docs_source/business/` pour les sources de verite
|
||||||
|
des pages business publiees dans le wiki
|
||||||
|
- `modules/purchase_trade/docs/business/` pour les pages generees lues par le
|
||||||
|
wiki
|
||||||
- Decisions templates / reports:
|
- Decisions templates / reports:
|
||||||
- `notes/template_business_rules.md`
|
- `notes/template_business_rules.md`
|
||||||
- Documentation comptable et reporting:
|
- Documentation comptable et reporting:
|
||||||
@@ -80,6 +84,7 @@ Guide rapide pour les agents qui codent dans ce repository.
|
|||||||
- Regles sensibles `purchase_trade` a relire avant de toucher lots, quantites
|
- Regles sensibles `purchase_trade` a relire avant de toucher lots, quantites
|
||||||
ou fees:
|
ou fees:
|
||||||
- `modules/purchase_trade/AGENTS.md`
|
- `modules/purchase_trade/AGENTS.md`
|
||||||
|
- `modules/purchase_trade/docs_source/business/lots-and-quantities.md`
|
||||||
- `modules/purchase_trade/docs/business-rules.md` BR-PT-020 / BR-PT-021
|
- `modules/purchase_trade/docs/business-rules.md` BR-PT-020 / BR-PT-021
|
||||||
(`quantity_theorical`, `lot.qt`, lots physiques, fees et PnL fee).
|
(`quantity_theorical`, `lot.qt`, lots physiques, fees et PnL fee).
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ de negoce physique:
|
|||||||
|
|
||||||
- Regles metier:
|
- Regles metier:
|
||||||
- `modules/purchase_trade/docs/business-rules.md`
|
- `modules/purchase_trade/docs/business-rules.md`
|
||||||
|
- Documentation business publiee dans le wiki:
|
||||||
|
- `modules/purchase_trade/docs/business/*.md`
|
||||||
|
- Sources de verite de la documentation business generee:
|
||||||
|
- `modules/purchase_trade/docs_source/business/*.md`
|
||||||
- Regles templates:
|
- Regles templates:
|
||||||
- `modules/purchase_trade/docs/template-rules.md`
|
- `modules/purchase_trade/docs/template-rules.md`
|
||||||
- Catalogue des proprietes templates:
|
- Catalogue des proprietes templates:
|
||||||
@@ -179,6 +183,23 @@ de negoce physique:
|
|||||||
|
|
||||||
## 5) Conventions de modification
|
## 5) Conventions de modification
|
||||||
|
|
||||||
|
### Documentation business
|
||||||
|
|
||||||
|
- Ne pas modifier directement une page generee sous
|
||||||
|
`modules/purchase_trade/docs/business/` si elle contient le commentaire
|
||||||
|
`Generated from docs_source/business`.
|
||||||
|
- Toute regle business nouvelle ou modifiee doit etre editee dans
|
||||||
|
`modules/purchase_trade/docs_source/business/`.
|
||||||
|
- Apres modification des sources business, regenerer le wiki avec:
|
||||||
|
`python modules/purchase_trade/docs/tools/render_business_docs.py`
|
||||||
|
- Avant de rendre une modification documentaire, verifier que le rendu publie
|
||||||
|
est synchronise avec:
|
||||||
|
`python modules/purchase_trade/docs/tools/render_business_docs.py --check`
|
||||||
|
- Les pages francaises et anglaises miroir doivent rester synchronisees.
|
||||||
|
- Le rendu publie doit rester lisible dans MkDocs meme sans extensions
|
||||||
|
optionnelles: eviter les marqueurs bruts `!!!` et `:material-...:` dans les
|
||||||
|
fichiers publies.
|
||||||
|
|
||||||
1. Modifier la logique metier dans le fichier pivot le plus proche.
|
1. Modifier la logique metier dans le fichier pivot le plus proche.
|
||||||
2. Si un template `.fodt` devient complexe, deplacer la logique dans une
|
2. Si un template `.fodt` devient complexe, deplacer la logique dans une
|
||||||
propriete Python `report_*`.
|
propriete Python `report_*`.
|
||||||
|
|||||||
@@ -1,48 +1,91 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Index thematique des regles business
|
# Index thematique des regles business
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
|
|
||||||
## Comment chercher une regle
|
## Comment chercher une regle
|
||||||
|
|
||||||
- Contrats, dates, lieux, banques: [contracts.md](contracts.md)
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Lots virtuels, lots physiques, `lot.qt`, weighing: [FR](lots-and-quantities.md) / [EN](lots-and-quantities.en.md)
|
<li style="margin:0.38rem 0;">Contrats, dates, lieux, banques: <a href="contracts.md">contracts.md</a>
|
||||||
- Matching, Create Contracts, back-to-back: [matching.md](matching.md)
|
</li>
|
||||||
- Shipments, controllers, SLA, weight reports: [shipments-execution.md](shipments-execution.md)
|
<li style="margin:0.38rem 0;">Lots virtuels, lots physiques, <code>lot.qt</code>, weighing: <a href="lots-and-quantities.md">FR</a> / <a href="lots-and-quantities.en.md">EN</a>
|
||||||
- Pricing manuel, basis, premium, linked currency: [pricing.md](pricing.md)
|
</li>
|
||||||
- Fees, freight, lots effectifs, `% rate`: [fees.md](fees.md)
|
<li style="margin:0.38rem 0;">Matching, Create Contracts, back-to-back: <a href="matching.md">matching.md</a>
|
||||||
- Valuation, PnL, MTM, derivatives: [valuation-pnl-mtm.md](valuation-pnl-mtm.md)
|
</li>
|
||||||
- Factures provisoires/finales, padding: [invoicing.md](invoicing.md)
|
<li style="margin:0.38rem 0;">Shipments, controllers, SLA, weight reports: <a href="shipments-execution.md">shipments-execution.md</a>
|
||||||
- Impacts `account.move`, validate/post: [accounting-bridge.md](accounting-bridge.md)
|
</li>
|
||||||
- Comptes bancaires, payment terms, payment orders: [payments-banking.md](payments-banking.md)
|
<li style="margin:0.38rem 0;">Pricing manuel, basis, premium, linked currency: <a href="pricing.md">pricing.md</a>
|
||||||
- Relatorio, `.fodt`, proprietes `report_*`: [reports-templates.md](reports-templates.md)
|
</li>
|
||||||
- Risque, credit, forex: [risk-credit-forex.md](risk-credit-forex.md)
|
<li style="margin:0.38rem 0;">Fees, freight, lots effectifs, <code>% rate</code>: <a href="fees.md">fees.md</a>
|
||||||
- Rapport Lots Management: [lots-management.md](lots-management.md)
|
</li>
|
||||||
- Diagnostics SQL des invariants: [sql/README.md](sql/README.md)
|
<li style="margin:0.38rem 0;">Valuation, PnL, MTM, derivatives: <a href="valuation-pnl-mtm.md">valuation-pnl-mtm.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Factures provisoires/finales, padding: <a href="invoicing.md">invoicing.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Impacts <code>account.move</code>, validate/post: <a href="accounting-bridge.md">accounting-bridge.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Comptes bancaires, payment terms, payment orders: <a href="payments-banking.md">payments-banking.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Relatorio, <code>.fodt</code>, proprietes <code>report_*</code>: <a href="reports-templates.md">reports-templates.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Risque, credit, forex: <a href="risk-credit-forex.md">risk-credit-forex.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Rapport Lots Management: <a href="lots-management.md">lots-management.md</a>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Diagnostics SQL des invariants: <a href="sql/README.md">sql/README.md</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Regles migrees dans cette premiere passe
|
## Regles migrees dans cette premiere passe
|
||||||
|
|
||||||
- `BR-PT-CON-001`: texte par defaut de pricing rule.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `BR-PT-CON-002`: delivery period coherent.
|
<li style="margin:0.38rem 0;"><code>BR-PT-CON-001</code>: texte par defaut de pricing rule.
|
||||||
- `BR-PT-CON-003`: lieux stock propages dans Create Contracts.
|
</li>
|
||||||
- `BR-PT-LOT-001`: cycle de vie des lots et des quantites.
|
<li style="margin:0.38rem 0;"><code>BR-PT-CON-002</code>: delivery period coherent.
|
||||||
- `BR-PT-LOT-002`: quantity contractuelle, execute physique et ligne finie.
|
</li>
|
||||||
- `BR-PT-LOT-003`: garde-fous Python et diagnostics SQL des invariants de
|
<li style="margin:0.38rem 0;"><code>BR-PT-CON-003</code>: lieux stock propages dans Create Contracts.
|
||||||
quantite.
|
</li>
|
||||||
- `BR-PT-MAT-001`: Create Contracts multi-lots.
|
<li style="margin:0.38rem 0;"><code>BR-PT-LOT-001</code>: cycle de vie des lots et des quantites.
|
||||||
- `BR-PT-SHP-001`: affectation controller.
|
</li>
|
||||||
- `BR-PT-SHP-002`: couts SLA controller.
|
<li style="margin:0.38rem 0;"><code>BR-PT-LOT-002</code>: quantity contractuelle, execute physique et ligne finie.
|
||||||
- `BR-PT-SHP-003`: weight reports distants.
|
</li>
|
||||||
- `BR-PT-PRI-001`: premium dans priced et basis.
|
<li style="margin:0.38rem 0;"><code>BR-PT-LOT-003</code>: garde-fous Python et diagnostics SQL des invariants de quantite.
|
||||||
- `BR-PT-PRI-002`: linked currency.
|
</li>
|
||||||
- `BR-PT-PRI-003`: pricing manuel.
|
<li style="margin:0.38rem 0;"><code>BR-PT-MAT-001</code>: Create Contracts multi-lots.
|
||||||
- `BR-PT-FEE-001`: maritime freight depuis fee shipment.
|
</li>
|
||||||
- `BR-PT-FEE-002`: lots effectifs des fees.
|
<li style="margin:0.38rem 0;"><code>BR-PT-SHP-001</code>: affectation controller.
|
||||||
- `BR-PT-FEE-003`: `% rate` via delta de financement.
|
</li>
|
||||||
- `BR-PT-VAL-001`: valuation achat/vente et sale-first.
|
<li style="margin:0.38rem 0;"><code>BR-PT-SHP-002</code>: couts SLA controller.
|
||||||
- `BR-PT-VAL-002`: references de valuation.
|
</li>
|
||||||
- `BR-PT-VAL-003`: MTM hors fees.
|
<li style="margin:0.38rem 0;"><code>BR-PT-SHP-003</code>: weight reports distants.
|
||||||
- `BR-PT-INV-001`: padding facture provisoire vente.
|
</li>
|
||||||
- `BR-PT-ACC-001`: Validate facture client attribue le numero.
|
<li style="margin:0.38rem 0;"><code>BR-PT-PRI-001</code>: premium dans priced et basis.
|
||||||
- `BR-PT-PAY-001`: comptes bancaires tiers vs compagnie.
|
</li>
|
||||||
- `BR-PT-RPT-001`: templates trade via proprietes Python.
|
<li style="margin:0.38rem 0;"><code>BR-PT-PRI-002</code>: linked currency.
|
||||||
- `BR-PT-LOTMGT-001`: filtres Lots Management.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-PRI-003</code>: pricing manuel.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-FEE-001</code>: maritime freight depuis fee shipment.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-FEE-002</code>: lots effectifs des fees.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-FEE-003</code>: <code>% rate</code> via delta de financement.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-VAL-001</code>: valuation achat/vente et sale-first.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-VAL-002</code>: references de valuation.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-VAL-003</code>: MTM hors fees.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-INV-001</code>: padding facture provisoire vente.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-ACC-001</code>: Validate facture client attribue le numero.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-PAY-001</code>: comptes bancaires tiers vs compagnie.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-RPT-001</code>: templates trade via proprietes Python.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>BR-PT-LOTMGT-001</code>: filtres Lots Management.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Guide de lecture des règles business
|
# Guide de lecture des règles business
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -6,32 +8,44 @@ Dernière mise à jour: `2026-05-13`
|
|||||||
Ce dossier devient la source de lecture thématique publiée dans le wiki pour les
|
Ce dossier devient la source de lecture thématique publiée dans le wiki pour les
|
||||||
règles business du module `purchase_trade`.
|
règles business du module `purchase_trade`.
|
||||||
|
|
||||||
Certaines pages peuvent être générées depuis une source de vérité plus sobre,
|
Toutes les pages business publiées dans `modules/purchase_trade/docs/business/`
|
||||||
rangée hors du dossier wiki dans `modules/purchase_trade/docs_source/`. Dans ce
|
sont générées depuis une source de vérité plus sobre, rangée hors du dossier
|
||||||
cas, la page publiée dans `modules/purchase_trade/docs/` porte un commentaire
|
wiki dans `modules/purchase_trade/docs_source/business/`.
|
||||||
`Generated from ...` en tête de fichier et ne doit pas être modifiée
|
|
||||||
directement.
|
Les pages publiées portent un commentaire `Generated from ...` en tête de
|
||||||
|
fichier et ne doivent pas être modifiées directement. Aucun contenu business ne
|
||||||
|
doit être ajouté ou modifié sans passer par cette source puis par le script de
|
||||||
|
génération.
|
||||||
|
|
||||||
Chaque page doit rester lisible par deux publics:
|
Chaque page doit rester lisible par deux publics:
|
||||||
|
|
||||||
- les consultants, qui ont besoin d'une règle fonctionnelle stable sans détail
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
de code inutile;
|
<li style="margin:0.38rem 0;">les consultants, qui ont besoin d'une règle fonctionnelle stable sans détail de code inutile;
|
||||||
- les développeurs, qui ont besoin des champs, modèles, fichiers et tests
|
</li>
|
||||||
concernés pour appliquer la règle sans l'interpréter.
|
<li style="margin:0.38rem 0;">les développeurs, qui ont besoin des champs, modèles, fichiers et tests concernés pour appliquer la règle sans l'interpréter.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Convention de langues
|
## Convention de langues
|
||||||
|
|
||||||
Chaque page thématique durable doit exister en deux versions maintenues
|
Chaque page thématique durable doit exister en deux versions maintenues
|
||||||
ensemble:
|
ensemble:
|
||||||
|
|
||||||
- une page française, rédigée en français correct avec accents, typographie et
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
formulations naturelles pour le wiki consultant;
|
<li style="margin:0.38rem 0;">une page française, rédigée en français correct avec accents, typographie et formulations naturelles pour le wiki consultant;
|
||||||
- une page anglaise miroir, portant le même contenu fonctionnel et technique.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">une page anglaise miroir, portant le même contenu fonctionnel et technique.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
Convention de nommage:
|
Convention de nommage:
|
||||||
|
|
||||||
- page française principale: `theme.md`;
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- page anglaise miroir: `theme.en.md`.
|
<li style="margin:0.38rem 0;">page française principale: <code>theme.md</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">page anglaise miroir: <code>theme.en.md</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
Toute modification d'une règle business, d'un statut, d'un champ technique ou
|
Toute modification d'une règle business, d'un statut, d'un champ technique ou
|
||||||
d'un point de vigilance doit être reportée dans les deux pages au même moment.
|
d'un point de vigilance doit être reportée dans les deux pages au même moment.
|
||||||
@@ -39,50 +53,61 @@ Les deux pages doivent indiquer leur page miroir en en-tête.
|
|||||||
|
|
||||||
## Convention source / wiki
|
## Convention source / wiki
|
||||||
|
|
||||||
Pour les pages qui ont besoin d'une présentation riche dans MkDocs:
|
Pour toute page business:
|
||||||
|
|
||||||
- éditer la source de vérité dans `modules/purchase_trade/docs_source/`;
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- régénérer la version wiki avec:
|
<li style="margin:0.38rem 0;">éditer la source de vérité dans <code>modules/purchase_trade/docs_source/business/</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">régénérer la version wiki avec:
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
```bash
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>python modules/purchase_trade/docs/tools/render_business_docs.py</code></pre>
|
||||||
python modules/purchase_trade/docs/tools/render_business_docs.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Le rendu wiki privilégie du HTML simple et portable plutôt que des extensions
|
Le rendu wiki privilégie du HTML simple et portable plutôt que des extensions
|
||||||
MkDocs optionnelles. Cela évite d'exposer dans le wiki des marqueurs non rendus
|
MkDocs optionnelles. Cela évite d'exposer dans le wiki des marqueurs non rendus
|
||||||
comme `!!!` ou `:material-...:`.
|
comme `!!!` ou `:material-...:`.
|
||||||
|
|
||||||
|
Les fichiers générés dans `modules/purchase_trade/docs/business/` sont des
|
||||||
|
artefacts de publication: ils peuvent être relus, mais toute correction doit
|
||||||
|
être reportée dans `docs_source/business/` avant régénération.
|
||||||
|
|
||||||
|
Avant de livrer une modification documentaire, vérifier que les pages publiées
|
||||||
|
sont à jour avec:
|
||||||
|
|
||||||
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>python modules/purchase_trade/docs/tools/render_business_docs.py --check</code></pre>
|
||||||
|
|
||||||
## Convention de rédaction
|
## Convention de rédaction
|
||||||
|
|
||||||
Pour chaque règle durable, utiliser autant que possible ce format:
|
Pour chaque règle durable, utiliser autant que possible ce format:
|
||||||
|
|
||||||
```md
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>### BR-PT-THEME-001 - Titre court
|
||||||
### BR-PT-THEME-001 - Titre court
|
|
||||||
|
|
||||||
Statut: active
|
Statut: active
|
||||||
Source: business-rules.md / note de session / décision projet
|
Source: business-rules.md / note de session / décision projet
|
||||||
|
|
||||||
#### Règle consultant
|
#### Règle consultant
|
||||||
|
|
||||||
Texte fonctionnel, sans nom de champ si ce n'est pas nécessaire.
|
Texte fonctionnel, sans nom de champ si ce n'est pas nécessaire.
|
||||||
|
|
||||||
#### Notes développeur
|
#### Notes développeur
|
||||||
|
|
||||||
- Modèles/champs:
|
- Modèles/champs:
|
||||||
- Fichiers:
|
- Fichiers:
|
||||||
- Tests:
|
- Tests:
|
||||||
- Points de vigilance:
|
- Points de vigilance:</code></pre>
|
||||||
```
|
|
||||||
|
|
||||||
## Convention de validation
|
## Convention de validation
|
||||||
|
|
||||||
Quand une règle business devient structurante pour l'intégrité des données, elle
|
Quand une règle business devient structurante pour l'intégrité des données, elle
|
||||||
doit être accompagnée autant que possible de deux garde-fous:
|
doit être accompagnée autant que possible de deux garde-fous:
|
||||||
|
|
||||||
- un check applicatif bloquant dans le code Python, appelé à la fin des flux qui
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
modifient les données concernées;
|
<li style="margin:0.38rem 0;">un check applicatif bloquant dans le code Python, appelé à la fin des flux qui modifient les données concernées;
|
||||||
- un diagnostic SQL en lecture seule pour auditer les bases existantes ou les
|
</li>
|
||||||
bases de test.
|
<li style="margin:0.38rem 0;">un diagnostic SQL en lecture seule pour auditer les bases existantes ou les bases de test.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
Les diagnostics SQL du module sont rangés dans `business/sql/`. Ils ne
|
Les diagnostics SQL du module sont rangés dans `business/sql/`. Ils ne
|
||||||
remplacent pas les règles applicatives: ils servent à retrouver et qualifier les
|
remplacent pas les règles applicatives: ils servent à retrouver et qualifier les
|
||||||
@@ -94,10 +119,19 @@ Les anciennes pages ne sont pas supprimées à cette étape. Elles restent des
|
|||||||
sources de vérification jusqu'à ce que chaque décision soit promue dans une
|
sources de vérification jusqu'à ce que chaque décision soit promue dans une
|
||||||
page thématique:
|
page thématique:
|
||||||
|
|
||||||
- `modules/purchase_trade/docs/business-rules.md`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `modules/purchase_trade/docs/fees.md`
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/business-rules.md</code>
|
||||||
- `modules/purchase_trade/docs/padding-invoice-accounting.md`
|
</li>
|
||||||
- `modules/purchase_trade/docs/template-rules.md`
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/fees.md</code>
|
||||||
- `modules/purchase_trade/docs/template-properties.md`
|
</li>
|
||||||
- `notes/business_rules.md`
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/padding-invoice-accounting.md</code>
|
||||||
- `notes/template_business_rules.md`
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/template-rules.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/template-properties.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>notes/business_rules.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>notes/template_business_rules.md</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Pont comptable
|
# Pont comptable
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,13 +15,16 @@ validation, comme une facture fournisseur.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Cible: `account.invoice` avec `type = out`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Workflow `Validate`: creer `account.move` et attribuer `number`.
|
<li style="margin:0.38rem 0;">Cible: <code>account.invoice</code> avec <code>type = out</code>.
|
||||||
- Workflow `Post`: ne doit pas reintroduire une session fraiche specifique au
|
</li>
|
||||||
flux client.
|
<li style="margin:0.38rem 0;">Workflow <code>Validate</code>: creer <code>account.move</code> et attribuer <code>number</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Workflow <code>Post</code>: ne doit pas reintroduire une session fraiche specifique au flux client.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Notes de migration
|
## Notes de migration
|
||||||
|
|
||||||
Les notes comptables detaillees restent dans `notes/accounting/` tant qu'elles
|
Les notes comptables detaillees restent dans `notes/accounting/` tant qu'elles
|
||||||
n'ont pas ete promues ici.
|
n'ont pas ete promues ici.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Contrats achat / vente
|
# Contrats achat / vente
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,9 +15,14 @@ repris automatiquement sur les nouvelles lignes achat et vente.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Configuration: `purchase_trade.configuration.pricing_rule`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Cibles: `purchase.line.pricing_rule`, `sale.line.pricing_rule`.
|
<li style="margin:0.38rem 0;">Configuration: <code>purchase_trade.configuration.pricing_rule</code>.
|
||||||
- Les lignes existantes ne sont pas modifiees retroactivement.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Cibles: <code>purchase.line.pricing_rule</code>, <code>sale.line.pricing_rule</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Les lignes existantes ne sont pas modifiees retroactivement.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-CON-002 - Delivery period coherent
|
## BR-PT-CON-002 - Delivery period coherent
|
||||||
|
|
||||||
@@ -28,9 +35,12 @@ borne renseignee reste acceptee.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Champs: `purchase.line.from_del`, `purchase.line.to_del`,
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
`sale.line.from_del`, `sale.line.to_del`.
|
<li style="margin:0.38rem 0;">Champs: <code>purchase.line.from_del</code>, <code>purchase.line.to_del</code>, <code>sale.line.from_del</code>, <code>sale.line.to_del</code>.
|
||||||
- Validation attendue: bloquer si `from_del > to_del`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Validation attendue: bloquer si <code>from_del > to_del</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-CON-003 - Propagation des lieux stock dans Create Contracts
|
## BR-PT-CON-003 - Propagation des lieux stock dans Create Contracts
|
||||||
|
|
||||||
@@ -43,8 +53,13 @@ logistiques doivent etre proposes selon le flux source pour eviter la ressaisie.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Champs: `from_location`, `to_location`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Flux fournisseur vers client: recopier le couple source.
|
<li style="margin:0.38rem 0;">Champs: <code>from_location</code>, <code>to_location</code>.
|
||||||
- Achat vers stock puis vente: `sale.from_location = purchase.to_location`.
|
</li>
|
||||||
- Vente depuis stock puis achat: `purchase.to_location = sale.from_location`.
|
<li style="margin:0.38rem 0;">Flux fournisseur vers client: recopier le couple source.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Achat vers stock puis vente: <code>sale.from_location = purchase.to_location</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Vente depuis stock puis achat: <code>purchase.to_location = sale.from_location</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Fees
|
# Fees
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -15,10 +17,16 @@ shipment, pas d'un champ direct de la facture.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Retrouver le lot physique depuis la facture.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Retrouver son `shipment_in`.
|
<li style="margin:0.38rem 0;">Retrouver le lot physique depuis la facture.
|
||||||
- Chercher le `fee.fee` avec `product.name = 'Maritime freight'`.
|
</li>
|
||||||
- Utiliser `fee.get_amount()`.
|
<li style="margin:0.38rem 0;">Retrouver son <code>shipment_in</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Chercher le <code>fee.fee</code> avec <code>product.name = 'Maritime freight'</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Utiliser <code>fee.get_amount()</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-FEE-002 - Les fees lies aux lots privilegient les physiques
|
## BR-PT-FEE-002 - Les fees lies aux lots privilegient les physiques
|
||||||
|
|
||||||
@@ -31,12 +39,18 @@ physique est lie, les lots physiques deviennent la base de calcul du fee.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Ne pas supprimer le lien virtuel: il reste le fallback.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Quantite `ppack`: somme de `lot.lot_qt` des physiques.
|
<li style="margin:0.38rem 0;">Ne pas supprimer le lien virtuel: il reste le fallback.
|
||||||
- Modes quantitatifs: quantites courantes converties des physiques.
|
</li>
|
||||||
- La meme selection s'applique au PnL fee.
|
<li style="margin:0.38rem 0;">Quantite <code>ppack</code>: somme de <code>lot.lot_qt</code> des physiques.
|
||||||
- Points de synchronisation: creation fee, lien `fee.lots`, changement de
|
</li>
|
||||||
`quantity_theorical`, weighing, suppression de physique.
|
<li style="margin:0.38rem 0;">Modes quantitatifs: quantites courantes converties des physiques.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">La meme selection s'applique au PnL fee.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Points de synchronisation: creation fee, lien <code>fee.lots</code>, changement de <code>quantity_theorical</code>, weighing, suppression de physique.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-FEE-003 - Fees `% rate` via delta de financement
|
## BR-PT-FEE-003 - Fees `% rate` via delta de financement
|
||||||
|
|
||||||
@@ -49,7 +63,11 @@ de la ligne d'estimation `BL date`, pas avec la date du jour.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Formule: `amount = unit_price * quantity * (price / 100) * fin_int_delta / 360`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Source du delta: ligne `Estimated date` avec `trigger = bldate`.
|
<li style="margin:0.38rem 0;">Formule: <code>amount = unit_price * quantity * (price / 100) * fin_int_delta / 360</code>.
|
||||||
- Si aucune ligne `bldate` n'existe, ne pas calculer de montant `% rate`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Source du delta: ligne <code>Estimated date</code> avec <code>trigger = bldate</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Si aucune ligne <code>bldate</code> n'existe, ne pas calculer de montant <code>% rate</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,22 +1,42 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Glossaire purchase_trade
|
# Glossaire purchase_trade
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
|
|
||||||
- `Purchase Line`: ligne d'achat.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `Sale Line`: ligne de vente.
|
<li style="margin:0.38rem 0;"><code>Purchase Line</code>: ligne d'achat.
|
||||||
- `quantity_theorical`: quantite contractuelle theorique d'une ligne.
|
</li>
|
||||||
- `Virtual Lot`: lot de type `virtual`, representant un reliquat ouvert.
|
<li style="margin:0.38rem 0;"><code>Sale Line</code>: ligne de vente.
|
||||||
- `Physical Lot`: lot de type `physic`, representant une quantite executee.
|
</li>
|
||||||
- `lot.qt`: ligne de quantite ouverte, matchee ou rattachee a un shipment.
|
<li style="margin:0.38rem 0;"><code>quantity_theorical</code>: quantite contractuelle theorique d'une ligne.
|
||||||
- `lot.qt ouvert`: `lot.qt` libre, sans lot oppose et sans shipment.
|
</li>
|
||||||
- `Shipment In`: shipment entrant utilise aussi pour les flux dropship dans ce module.
|
<li style="margin:0.38rem 0;"><code>Virtual Lot</code>: lot de type <code>virtual</code>, representant un reliquat ouvert.
|
||||||
- `Dropship`: flux fournisseur vers client, sans passage par stock interne.
|
</li>
|
||||||
- `Inbound`: flux entrant classique qui ne correspond pas au dropship.
|
<li style="margin:0.38rem 0;"><code>Physical Lot</code>: lot de type <code>physic</code>, representant une quantite executee.
|
||||||
- `Basis`: mode de prix construit a partir d'un prix de marche et d'un premium.
|
</li>
|
||||||
- `Premium`: prime ou discount commercial ajoute au prix economique.
|
<li style="margin:0.38rem 0;"><code>lot.qt</code>: ligne de quantite ouverte, matchee ou rattachee a un shipment.
|
||||||
- `Linked currency`: saisie d'un prix dans une devise/unite liee, par exemple `USC/LB`.
|
</li>
|
||||||
- `Valuation`: lignes de PnL generees pour prix, fees, derivatives et MTM.
|
<li style="margin:0.38rem 0;"><code>lot.qt ouvert</code>: <code>lot.qt</code> libre, sans lot oppose et sans shipment.
|
||||||
- `MTM`: mark-to-market applique aux lignes valorisables au marche.
|
</li>
|
||||||
- `Fee`: frais commercial ou logistique rattache a une ligne, un lot ou un shipment.
|
<li style="margin:0.38rem 0;"><code>Shipment In</code>: shipment entrant utilise aussi pour les flux dropship dans ce module.
|
||||||
- `Report property`: propriete Python exposee pour simplifier un template Relatorio.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Dropship</code>: flux fournisseur vers client, sans passage par stock interne.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Inbound</code>: flux entrant classique qui ne correspond pas au dropship.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Basis</code>: mode de prix construit a partir d'un prix de marche et d'un premium.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Premium</code>: prime ou discount commercial ajoute au prix economique.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Linked currency</code>: saisie d'un prix dans une devise/unite liee, par exemple <code>USC/LB</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Valuation</code>: lignes de PnL generees pour prix, fees, derivatives et MTM.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>MTM</code>: mark-to-market applique aux lignes valorisables au marche.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Fee</code>: frais commercial ou logistique rattache a une ligne, un lot ou un shipment.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Report property</code>: propriete Python exposee pour simplifier un template Relatorio.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Invariants structurants
|
# Invariants structurants
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -15,11 +17,14 @@ contrats et l'execution logistique.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Source historique: `BR-PT-002`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Voir aussi: [lots-and-quantities.md](lots-and-quantities.md),
|
<li style="margin:0.38rem 0;">Source historique: <code>BR-PT-002</code>.
|
||||||
[matching.md](matching.md), [reports-templates.md](reports-templates.md).
|
</li>
|
||||||
- Champs frequents: `lot.line`, `lot.sale_line`, `lot_shipment_in`,
|
<li style="margin:0.38rem 0;">Voir aussi: <a href="lots-and-quantities.md">lots-and-quantities.md</a>, <a href="matching.md">matching.md</a>, <a href="reports-templates.md">reports-templates.md</a>.
|
||||||
`lot_shipment_internal`, `lot_shipment_out`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Champs frequents: <code>lot.line</code>, <code>lot.sale_line</code>, <code>lot_shipment_in</code>, <code>lot_shipment_internal</code>, <code>lot_shipment_out</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## INV-PT-002 - Le reliquat ouvert ne doit pas doubler les lots physiques
|
## INV-PT-002 - Le reliquat ouvert ne doit pas doubler les lots physiques
|
||||||
|
|
||||||
@@ -31,19 +36,22 @@ executer.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Source historique: `BR-PT-020`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Le calcul doit tenir compte de la quantite contractuelle, des lots physiques
|
<li style="margin:0.38rem 0;">Source historique: <code>BR-PT-020</code>.
|
||||||
existants et des `lot.qt` deja matches ou shippes.
|
</li>
|
||||||
- Regle de conservation:
|
<li style="margin:0.38rem 0;">Le calcul doit tenir compte de la quantite contractuelle, des lots physiques existants et des <code>lot.qt</code> deja matches ou shippes.
|
||||||
`sum(lots physiques) + lot virtuel = quantity_theorical`.
|
</li>
|
||||||
- Regle du forecast ouvert:
|
<li style="margin:0.38rem 0;">Regle de conservation: <code>sum(lots physiques) + lot virtuel = quantity_theorical</code>.
|
||||||
`sum(lot.qt non zero) = max(lot virtuel, 0)`.
|
</li>
|
||||||
- Les lignes `lot.qt` a zero sont ignorees par les checks: elles peuvent servir
|
<li style="margin:0.38rem 0;">Regle du forecast ouvert: <code>sum(lot.qt non zero) = max(lot virtuel, 0)</code>.
|
||||||
de memoire d'une prevision consommee.
|
</li>
|
||||||
- Le check applicatif est centralise dans
|
<li style="margin:0.38rem 0;">Les lignes <code>lot.qt</code> a zero sont ignorees par les checks: elles peuvent servir de memoire d'une prevision consommee.
|
||||||
`lot.lot.assert_lines_quantity_consistency()`.
|
</li>
|
||||||
- Le diagnostic SQL correspondant est
|
<li style="margin:0.38rem 0;">Le check applicatif est centralise dans <code>lot.lot.assert_lines_quantity_consistency()</code>.
|
||||||
[sql/quantity_consistency_checks.sql](sql/quantity_consistency_checks.sql).
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Le diagnostic SQL correspondant est <a href="sql/quantity_consistency_checks.sql">sql/quantity_consistency_checks.sql</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## INV-PT-003 - Les fees utilisent leurs lots effectifs
|
## INV-PT-003 - Les fees utilisent leurs lots effectifs
|
||||||
|
|
||||||
@@ -55,10 +63,14 @@ effective de calcul.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Source historique: `BR-PT-021`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Ne pas supprimer le lien virtuel: il reste le fallback si les physiques sont
|
<li style="margin:0.38rem 0;">Source historique: <code>BR-PT-021</code>.
|
||||||
retires.
|
</li>
|
||||||
- Voir [fees.md](fees.md).
|
<li style="margin:0.38rem 0;">Ne pas supprimer le lien virtuel: il reste le fallback si les physiques sont retires.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Voir <a href="fees.md">fees.md</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## INV-PT-004 - Les templates doivent rester simples
|
## INV-PT-004 - Les templates doivent rester simples
|
||||||
|
|
||||||
@@ -69,7 +81,11 @@ chemin technique pour les retrouver est complexe.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Preferer des proprietes Python `report_*` aux expressions Genshi complexes.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Ne pas supposer qu'une variable locale comme `shipment` existe partout dans
|
<li style="margin:0.38rem 0;">Preferer des proprietes Python <code>report_*</code> aux expressions Genshi complexes.
|
||||||
un `.fodt`.
|
</li>
|
||||||
- Voir [reports-templates.md](reports-templates.md).
|
<li style="margin:0.38rem 0;">Ne pas supposer qu'une variable locale comme <code>shipment</code> existe partout dans un <code>.fodt</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Voir <a href="reports-templates.md">reports-templates.md</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Facturation trade
|
# Facturation trade
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,12 +15,15 @@ constituer une provision, sans modifier la quantite physique du lot.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Le padding global du wizard `lot.invoice` est reparti entre les lots
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
selectionnes.
|
<li style="margin:0.38rem 0;">Le padding global du wizard <code>lot.invoice</code> est reparti entre les lots selectionnes.
|
||||||
- La ligne facture expose `Inc. padding`.
|
</li>
|
||||||
- Le lot conserve sa part dans `sale_invoice_padding`.
|
<li style="margin:0.38rem 0;">La ligne facture expose <code>Inc. padding</code>.
|
||||||
- La facture finale retire le padding de la quantite provisoire avant de
|
</li>
|
||||||
calculer le delta.
|
<li style="margin:0.38rem 0;">Le lot conserve sa part dans <code>sale_invoice_padding</code>.
|
||||||
- Les ecritures d'extourne doivent relire la provisoire depuis
|
</li>
|
||||||
`lot.sale_invoice_line_prov`.
|
<li style="margin:0.38rem 0;">La facture finale retire le padding de la quantite provisoire avant de calculer le delta.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Les ecritures d'extourne doivent relire la provisoire depuis <code>lot.sale_invoice_line_prov</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -296,174 +296,379 @@ them with Python guards and SQL diagnostics.
|
|||||||
|
|
||||||
### Key Fields
|
### Key Fields
|
||||||
|
|
||||||
- Purchase line: `purchase.line`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Sale line: `sale.line`
|
<li style="margin:0.38rem 0;">Purchase line: <code>purchase.line</code>
|
||||||
- Lot: `lot.lot`
|
</li>
|
||||||
- Forecast: `lot.qt`
|
<li style="margin:0.38rem 0;">Sale line: <code>sale.line</code>
|
||||||
- History: `lot.qt.hist`
|
</li>
|
||||||
- Purchase business quantity: `purchase.line.quantity_theorical`
|
<li style="margin:0.38rem 0;">Lot: <code>lot.lot</code>
|
||||||
- Sale business quantity: `sale.line.quantity_theorical`
|
</li>
|
||||||
- Technical counter: `quantity`
|
<li style="margin:0.38rem 0;">Forecast: <code>lot.qt</code>
|
||||||
- Finished line: `purchase.line.finished`, `sale.line.finished`
|
</li>
|
||||||
- Virtual / physical lot: `lot.lot.lot_type = virtual / physic`
|
<li style="margin:0.38rem 0;">History: <code>lot.qt.hist</code>
|
||||||
- Purchase link: `lot.lot.line`
|
</li>
|
||||||
- Sale link: `lot.lot.sale_line`
|
<li style="margin:0.38rem 0;">Purchase business quantity: <code>purchase.line.quantity_theorical</code>
|
||||||
- Purchase forecast: `lot.qt.lot_p`
|
</li>
|
||||||
- Sale forecast: `lot.qt.lot_s`
|
<li style="margin:0.38rem 0;">Sale business quantity: <code>sale.line.quantity_theorical</code>
|
||||||
- Forecast quantity: `lot.qt.lot_quantity`
|
</li>
|
||||||
- Weight basis: `purchase.purchase.wb`, `sale.sale.wb`
|
<li style="margin:0.38rem 0;">Technical counter: <code>quantity</code>
|
||||||
- Weight basis state: `purchase.weight.basis.qt_type`
|
</li>
|
||||||
- Packing: `lot.lot.lot_qt`, `lot.lot.lot_unit`
|
<li style="margin:0.38rem 0;">Finished line: <code>purchase.line.finished</code>, <code>sale.line.finished</code>
|
||||||
- Tolerances: `tol_min`, `tol_max`, `tol_min_qt`, `tol_max_qt`,
|
</li>
|
||||||
`tol_min_v`, `tol_max_v`
|
<li style="margin:0.38rem 0;">Virtual / physical lot: <code>lot.lot.lot_type = virtual / physic</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Purchase link: <code>lot.lot.line</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Sale link: <code>lot.lot.sale_line</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Purchase forecast: <code>lot.qt.lot_p</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Sale forecast: <code>lot.qt.lot_s</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Forecast quantity: <code>lot.qt.lot_quantity</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Weight basis: <code>purchase.purchase.wb</code>, <code>sale.sale.wb</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Weight basis state: <code>purchase.weight.basis.qt_type</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Packing: <code>lot.lot.lot_qt</code>, <code>lot.lot.lot_unit</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Tolerances: <code>tol_min</code>, <code>tol_max</code>, <code>tol_min_qt</code>, <code>tol_max_qt</code>, <code>tol_min_v</code>, <code>tol_max_v</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Line / Virtual Lot Creation
|
### Line / Virtual Lot Creation
|
||||||
|
|
||||||
- Purchase: `purchase.py`, `Line.validate`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Sale: `sale.py`, `SaleLine.validate`
|
<li style="margin:0.38rem 0;">Purchase: <code>purchase.py</code>, <code>Line.validate</code>
|
||||||
- If `quantity_theorical` is entered and `quantity` is empty or zero:
|
</li>
|
||||||
- `quantity` is initialized from `quantity_theorical`;
|
<li style="margin:0.38rem 0;">Sale: <code>sale.py</code>, <code>SaleLine.validate</code>
|
||||||
- only if no physical lot exists.
|
</li>
|
||||||
- If the line is eligible:
|
<li style="margin:0.38rem 0;">If <code>quantity_theorical</code> is entered and <code>quantity</code> is empty or zero:
|
||||||
- not `created_by_code`;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- no lot yet;
|
<li style="margin:0.38rem 0;"><code>quantity</code> is initialized from <code>quantity_theorical</code>;
|
||||||
- non-service product;
|
</li>
|
||||||
- `quantity_theorical != 0`;
|
<li style="margin:0.38rem 0;">only if no physical lot exists.
|
||||||
- create one `virtual` lot.
|
</li>
|
||||||
- The virtual lot receives a first `lot.qt.hist` entry.
|
</ul>
|
||||||
- `Lot.validate` creates the open `lot.qt` through `createVirtualPart`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">If the line is eligible:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">not <code>created_by_code</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">no lot yet;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">non-service product;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity_theorical != 0</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">create one <code>virtual</code> lot.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">The virtual lot receives a first <code>lot.qt.hist</code> entry.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Lot.validate</code> creates the open <code>lot.qt</code> through <code>createVirtualPart</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Updating `quantity_theorical`
|
### Updating `quantity_theorical`
|
||||||
|
|
||||||
- Purchase: `purchase.py`, `Line.write`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Sale: `sale.py`, `SaleLine.write`
|
<li style="margin:0.38rem 0;">Purchase: <code>purchase.py</code>, <code>Line.write</code>
|
||||||
- Virtual lot target:
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Sale: <code>sale.py</code>, <code>SaleLine.write</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Virtual lot target:
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>target_quantity = quantity_theorical - sum(converted physical lots)</code></pre>
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>target_quantity = quantity_theorical - sum(converted physical lots)</code></pre>
|
||||||
|
|
||||||
- If `target_quantity < 0`:
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- block with `Please unlink or unmatch lot`.
|
<li style="margin:0.38rem 0;">If <code>target_quantity < 0</code>:
|
||||||
- Free `lot.qt` target:
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">block with <code>Please unlink or unmatch lot</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Free <code>lot.qt</code> target:
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>free_quantity = target_quantity - sum(already matched or shipped lot.qt)</code></pre>
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>free_quantity = target_quantity - sum(already matched or shipped lot.qt)</code></pre>
|
||||||
|
|
||||||
- If `free_quantity < 0`:
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- block with `Please unlink or unmatch lot`.
|
<li style="margin:0.38rem 0;">If <code>free_quantity < 0</code>:
|
||||||
- If a free `lot.qt` exists:
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- replace its quantity.
|
<li style="margin:0.38rem 0;">block with <code>Please unlink or unmatch lot</code>.
|
||||||
- If no free `lot.qt` exists and `free_quantity > 0`:
|
</li>
|
||||||
- create a new `lot.qt`.
|
</ul>
|
||||||
- Line fees are resynchronized.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">If a free <code>lot.qt</code> exists:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">replace its quantity.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">If no free <code>lot.qt</code> exists and <code>free_quantity > 0</code>:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">create a new <code>lot.qt</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Line fees are resynchronized.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Adding Physical Lots
|
### Adding Physical Lots
|
||||||
|
|
||||||
- Wizard: `lot.add`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Methods:
|
<li style="margin:0.38rem 0;">Wizard: <code>lot.add</code>
|
||||||
- `LotQt.add_physical_lots`
|
</li>
|
||||||
- `LotQt.add_physical_lot`
|
<li style="margin:0.38rem 0;">Methods:
|
||||||
- Mandatory source: one `lot.qt` line.
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- Direct add from a physical lot is refused.
|
<li style="margin:0.38rem 0;"><code>LotQt.add_physical_lots</code>
|
||||||
- Physical add on sale side through this wizard is refused: use
|
</li>
|
||||||
`Apply matching`.
|
<li style="margin:0.38rem 0;"><code>LotQt.add_physical_lot</code>
|
||||||
- The physical lot inherits:
|
</li>
|
||||||
- purchase line;
|
</ul>
|
||||||
- matched sale, if any;
|
</li>
|
||||||
- shipment;
|
<li style="margin:0.38rem 0;">Mandatory source: one <code>lot.qt</code> line.
|
||||||
- product;
|
</li>
|
||||||
- unit;
|
<li style="margin:0.38rem 0;">Direct add from a physical lot is refused.
|
||||||
- quantities;
|
</li>
|
||||||
- premium;
|
<li style="margin:0.38rem 0;">Physical add on sale side through this wizard is refused: use <code>Apply matching</code>.
|
||||||
- chunk key.
|
</li>
|
||||||
- After creation:
|
<li style="margin:0.38rem 0;">The physical lot inherits:
|
||||||
- source `lot.qt` is reduced;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `lot.qt` cannot become negative;
|
<li style="margin:0.38rem 0;">purchase line;
|
||||||
- virtual lot is recalculated;
|
</li>
|
||||||
- `quantity` is recalculated;
|
<li style="margin:0.38rem 0;">matched sale, if any;
|
||||||
- moves and fees are updated when needed.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">shipment;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">product;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">unit;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">quantities;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">premium;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">chunk key.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">After creation:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">source <code>lot.qt</code> is reduced;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>lot.qt</code> cannot become negative;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">virtual lot is recalculated;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity</code> is recalculated;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">moves and fees are updated when needed.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Removing Physical Lots
|
### Removing Physical Lots
|
||||||
|
|
||||||
- Wizard: `lot.remove`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Open lot: removal forbidden.
|
<li style="margin:0.38rem 0;">Wizard: <code>lot.remove</code>
|
||||||
- Lot with `stock.move`:
|
</li>
|
||||||
- move must be `draft`.
|
<li style="margin:0.38rem 0;">Open lot: removal forbidden.
|
||||||
- Matched or shipped lot:
|
</li>
|
||||||
- confirmable warning.
|
<li style="margin:0.38rem 0;">Lot with <code>stock.move</code>:
|
||||||
- Effects:
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- draft move deletion;
|
<li style="margin:0.38rem 0;">move must be <code>draft</code>.
|
||||||
- restore quantity into `lot.qt`;
|
</li>
|
||||||
- restore context through shipment, `getVlot_p()`, `getVlot_s()`;
|
</ul>
|
||||||
- recalculate virtual lot, `quantity`, fees.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Matched or shipped lot:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">confirmable warning.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Effects:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">draft move deletion;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">restore quantity into <code>lot.qt</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">restore context through shipment, <code>getVlot_p()</code>, <code>getVlot_s()</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">recalculate virtual lot, <code>quantity</code>, fees.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Weighing / Quantity States
|
### Weighing / Quantity States
|
||||||
|
|
||||||
- Wizard: `lot.weighing`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- UI action: `Do weighing`
|
<li style="margin:0.38rem 0;">Wizard: <code>lot.weighing</code>
|
||||||
- Writes or updates `lot.qt.hist`.
|
</li>
|
||||||
- May update `lot_state`.
|
<li style="margin:0.38rem 0;">UI action: <code>Do weighing</code>
|
||||||
- Synchronizes:
|
</li>
|
||||||
- lot;
|
<li style="margin:0.38rem 0;">Writes or updates <code>lot.qt.hist</code>.
|
||||||
- open quantities;
|
</li>
|
||||||
- fees.
|
<li style="margin:0.38rem 0;">May update <code>lot_state</code>.
|
||||||
- `lot.qt.hist` views are consultative.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Synchronizes:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">lot;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">open quantities;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">fees.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>lot.qt.hist</code> views are consultative.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Quantity Counter `quantity`
|
### Quantity Counter `quantity`
|
||||||
|
|
||||||
- Method: `Lot._recalc_line_quantity`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Without physical lots:
|
<li style="margin:0.38rem 0;">Method: <code>Lot._recalc_line_quantity</code>
|
||||||
- `quantity` follows the virtual lot.
|
</li>
|
||||||
- With physical lots:
|
<li style="margin:0.38rem 0;">Without physical lots:
|
||||||
- `quantity` sums physical lots only.
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `quantity` is readonly on trade lines.
|
<li style="margin:0.38rem 0;"><code>quantity</code> follows the virtual lot.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">With physical lots:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity</code> sums physical lots only.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity</code> is readonly on trade lines.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Line Amount
|
### Line Amount
|
||||||
|
|
||||||
- Purchase: `purchase.line.on_change_with_amount()`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Sale: `sale.line.on_change_with_amount()`
|
<li style="margin:0.38rem 0;">Purchase: <code>purchase.line.on_change_with_amount()</code>
|
||||||
- Helpers:
|
</li>
|
||||||
- `_get_amount_quantity()`
|
<li style="margin:0.38rem 0;">Sale: <code>sale.line.on_change_with_amount()</code>
|
||||||
- `_get_weight_basis_quantity()`
|
</li>
|
||||||
- Priorities:
|
<li style="margin:0.38rem 0;">Helpers:
|
||||||
- `finished = False`: `quantity_theorical`
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `finished = True` + usable Weight basis: physical sum in that state
|
<li style="margin:0.38rem 0;"><code>_get_amount_quantity()</code>
|
||||||
- `finished = True` without usable Weight basis: `quantity`
|
</li>
|
||||||
- legacy fallback: `quantity` if `quantity_theorical` is empty
|
<li style="margin:0.38rem 0;"><code>_get_weight_basis_quantity()</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Priorities:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;"><code>finished = False</code>: <code>quantity_theorical</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>finished = True</code> + usable Weight basis: physical sum in that state
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>finished = True</code> without usable Weight basis: <code>quantity</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">legacy fallback: <code>quantity</code> if <code>quantity_theorical</code> is empty
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Python Guards
|
### Python Guards
|
||||||
|
|
||||||
- Central check:
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `lot.lot.assert_lines_quantity_consistency()`
|
<li style="margin:0.38rem 0;">Central check:
|
||||||
- Non-zero orphan `lot.qt` block:
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `lot.qt.validate`
|
<li style="margin:0.38rem 0;"><code>lot.lot.assert_lines_quantity_consistency()</code>
|
||||||
- Called after:
|
</li>
|
||||||
- `quantity_theorical` update;
|
</ul>
|
||||||
- physical lot creation / deletion;
|
</li>
|
||||||
- matching / unmatching;
|
<li style="margin:0.38rem 0;">Non-zero orphan <code>lot.qt</code> block:
|
||||||
- shipping / unshipping;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- weighing.
|
<li style="margin:0.38rem 0;"><code>lot.qt.validate</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Called after:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity_theorical</code> update;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">physical lot creation / deletion;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">matching / unmatching;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">shipping / unshipping;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">weighing.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### SQL Diagnostic
|
### SQL Diagnostic
|
||||||
|
|
||||||
- Script:
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- [sql/quantity_consistency_checks.sql](sql/quantity_consistency_checks.sql)
|
<li style="margin:0.38rem 0;">Script:
|
||||||
- Use:
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- test database audit;
|
<li style="margin:0.38rem 0;"><a href="sql/quantity_consistency_checks.sql">sql/quantity_consistency_checks.sql</a>
|
||||||
- historical data audit;
|
</li>
|
||||||
- qualification before repair.
|
</ul>
|
||||||
- The script completely ignores `lot.qt = 0`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Use:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">test database audit;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">historical data audit;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">qualification before repair.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">The script completely ignores <code>lot.qt = 0</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Nearby Tests
|
## Nearby Tests
|
||||||
|
|
||||||
- `modules/purchase_trade/tests/test_module.py`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Existing coverage:
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/tests/test_module.py</code>
|
||||||
- readonly `quantity`;
|
</li>
|
||||||
- initialization from `quantity_theorical`;
|
<li style="margin:0.38rem 0;">Existing coverage:
|
||||||
- protection when physical lots exist;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- amount on theoretical / physical / Weight basis;
|
<li style="margin:0.38rem 0;">readonly <code>quantity</code>;
|
||||||
- virtual lot resynchronization;
|
</li>
|
||||||
- blocking when open quantity is not enough.
|
<li style="margin:0.38rem 0;">initialization from <code>quantity_theorical</code>;
|
||||||
- Tests to add:
|
</li>
|
||||||
- readonly `lot_hist`;
|
<li style="margin:0.38rem 0;">protection when physical lots exist;
|
||||||
- `Do weighing` creates or updates a state;
|
</li>
|
||||||
- virtual lot without direct `lot_qt` / `lot_unit` entry;
|
<li style="margin:0.38rem 0;">amount on theoretical / physical / Weight basis;
|
||||||
- SQL checks replayed on inconsistent datasets.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">virtual lot resynchronization;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">blocking when open quantity is not enough.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Tests to add:
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">readonly <code>lot_hist</code>;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Do weighing</code> creates or updates a state;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">virtual lot without direct <code>lot_qt</code> / <code>lot_unit</code> entry;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">SQL checks replayed on inconsistent datasets.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -295,173 +295,379 @@ puis les sécuriser par des checks Python et des diagnostics SQL.
|
|||||||
|
|
||||||
### Champs clés
|
### Champs clés
|
||||||
|
|
||||||
- Ligne achat : `purchase.line`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Ligne vente : `sale.line`
|
<li style="margin:0.38rem 0;">Ligne achat : <code>purchase.line</code>
|
||||||
- Lot : `lot.lot`
|
</li>
|
||||||
- Forecast : `lot.qt`
|
<li style="margin:0.38rem 0;">Ligne vente : <code>sale.line</code>
|
||||||
- Historique : `lot.qt.hist`
|
</li>
|
||||||
- Quantité métier achat : `purchase.line.quantity_theorical`
|
<li style="margin:0.38rem 0;">Lot : <code>lot.lot</code>
|
||||||
- Quantité métier vente : `sale.line.quantity_theorical`
|
</li>
|
||||||
- Compteur technique : `quantity`
|
<li style="margin:0.38rem 0;">Forecast : <code>lot.qt</code>
|
||||||
- Ligne finie : `purchase.line.finished`, `sale.line.finished`
|
</li>
|
||||||
- Lot virtuel / physique : `lot.lot.lot_type = virtual / physic`
|
<li style="margin:0.38rem 0;">Historique : <code>lot.qt.hist</code>
|
||||||
- Lien achat : `lot.lot.line`
|
</li>
|
||||||
- Lien vente : `lot.lot.sale_line`
|
<li style="margin:0.38rem 0;">Quantité métier achat : <code>purchase.line.quantity_theorical</code>
|
||||||
- Forecast achat : `lot.qt.lot_p`
|
</li>
|
||||||
- Forecast vente : `lot.qt.lot_s`
|
<li style="margin:0.38rem 0;">Quantité métier vente : <code>sale.line.quantity_theorical</code>
|
||||||
- Quantité forecast : `lot.qt.lot_quantity`
|
</li>
|
||||||
- Weight basis : `purchase.purchase.wb`, `sale.sale.wb`
|
<li style="margin:0.38rem 0;">Compteur technique : <code>quantity</code>
|
||||||
- État Weight basis : `purchase.weight.basis.qt_type`
|
</li>
|
||||||
- Packing : `lot.lot.lot_qt`, `lot.lot.lot_unit`
|
<li style="margin:0.38rem 0;">Ligne finie : <code>purchase.line.finished</code>, <code>sale.line.finished</code>
|
||||||
- Tolerances : `tol_min`, `tol_max`, `tol_min_qt`, `tol_max_qt`,
|
</li>
|
||||||
`tol_min_v`, `tol_max_v`
|
<li style="margin:0.38rem 0;">Lot virtuel / physique : <code>lot.lot.lot_type = virtual / physic</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Lien achat : <code>lot.lot.line</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Lien vente : <code>lot.lot.sale_line</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Forecast achat : <code>lot.qt.lot_p</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Forecast vente : <code>lot.qt.lot_s</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Quantité forecast : <code>lot.qt.lot_quantity</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Weight basis : <code>purchase.purchase.wb</code>, <code>sale.sale.wb</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">État Weight basis : <code>purchase.weight.basis.qt_type</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Packing : <code>lot.lot.lot_qt</code>, <code>lot.lot.lot_unit</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Tolerances : <code>tol_min</code>, <code>tol_max</code>, <code>tol_min_qt</code>, <code>tol_max_qt</code>, <code>tol_min_v</code>, <code>tol_max_v</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Création ligne / lot virtuel
|
### Création ligne / lot virtuel
|
||||||
|
|
||||||
- Achat : `purchase.py`, `Line.validate`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Vente : `sale.py`, `SaleLine.validate`
|
<li style="margin:0.38rem 0;">Achat : <code>purchase.py</code>, <code>Line.validate</code>
|
||||||
- Si `quantity_theorical` est saisi et que `quantity` est vide ou zéro :
|
</li>
|
||||||
- `quantity` est initialisée depuis `quantity_theorical` ;
|
<li style="margin:0.38rem 0;">Vente : <code>sale.py</code>, <code>SaleLine.validate</code>
|
||||||
- seulement si aucun lot physique n'existe.
|
</li>
|
||||||
- Si la ligne est éligible :
|
<li style="margin:0.38rem 0;">Si <code>quantity_theorical</code> est saisi et que <code>quantity</code> est vide ou zéro :
|
||||||
- pas `created_by_code` ;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- pas encore de lot ;
|
<li style="margin:0.38rem 0;"><code>quantity</code> est initialisée depuis <code>quantity_theorical</code> ;
|
||||||
- produit non service ;
|
</li>
|
||||||
- `quantity_theorical != 0` ;
|
<li style="margin:0.38rem 0;">seulement si aucun lot physique n'existe.
|
||||||
- création d'un lot `virtual`.
|
</li>
|
||||||
- Le lot virtuel reçoit une première entrée `lot.qt.hist`.
|
</ul>
|
||||||
- `Lot.validate` crée le `lot.qt` ouvert via `createVirtualPart`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Si la ligne est éligible :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">pas <code>created_by_code</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">pas encore de lot ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">produit non service ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity_theorical != 0</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">création d'un lot <code>virtual</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Le lot virtuel reçoit une première entrée <code>lot.qt.hist</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Lot.validate</code> crée le <code>lot.qt</code> ouvert via <code>createVirtualPart</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Modification de `quantity_theorical`
|
### Modification de `quantity_theorical`
|
||||||
|
|
||||||
- Achat : `purchase.py`, `Line.write`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Vente : `sale.py`, `SaleLine.write`
|
<li style="margin:0.38rem 0;">Achat : <code>purchase.py</code>, <code>Line.write</code>
|
||||||
- Cible lot virtuel :
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Vente : <code>sale.py</code>, <code>SaleLine.write</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Cible lot virtuel :
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>target_quantity = quantity_theorical - somme(lots physiques convertis)</code></pre>
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>target_quantity = quantity_theorical - somme(lots physiques convertis)</code></pre>
|
||||||
|
|
||||||
- Si `target_quantity < 0` :
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- blocage : `Please unlink or unmatch lot`.
|
<li style="margin:0.38rem 0;">Si <code>target_quantity < 0</code> :
|
||||||
- Cible `lot.qt` libre :
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">blocage : <code>Please unlink or unmatch lot</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Cible <code>lot.qt</code> libre :
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>free_quantity = target_quantity - somme(lot.qt déjà matchés ou shippés)</code></pre>
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>free_quantity = target_quantity - somme(lot.qt déjà matchés ou shippés)</code></pre>
|
||||||
|
|
||||||
- Si `free_quantity < 0` :
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- blocage : `Please unlink or unmatch lot`.
|
<li style="margin:0.38rem 0;">Si <code>free_quantity < 0</code> :
|
||||||
- Si un `lot.qt` libre existe :
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- sa quantité est remplacée.
|
<li style="margin:0.38rem 0;">blocage : <code>Please unlink or unmatch lot</code>.
|
||||||
- Si aucun `lot.qt` libre n'existe et `free_quantity > 0` :
|
</li>
|
||||||
- création d'un nouveau `lot.qt`.
|
</ul>
|
||||||
- Les fees de ligne sont resynchronisés.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Si un <code>lot.qt</code> libre existe :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">sa quantité est remplacée.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Si aucun <code>lot.qt</code> libre n'existe et <code>free_quantity > 0</code> :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">création d'un nouveau <code>lot.qt</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Les fees de ligne sont resynchronisés.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Ajout de lots physiques
|
### Ajout de lots physiques
|
||||||
|
|
||||||
- Wizard : `lot.add`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Méthodes :
|
<li style="margin:0.38rem 0;">Wizard : <code>lot.add</code>
|
||||||
- `LotQt.add_physical_lots`
|
</li>
|
||||||
- `LotQt.add_physical_lot`
|
<li style="margin:0.38rem 0;">Méthodes :
|
||||||
- Source obligatoire : une ligne `lot.qt`.
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- Ajout direct depuis un lot physique refusé.
|
<li style="margin:0.38rem 0;"><code>LotQt.add_physical_lots</code>
|
||||||
- Ajout physique côté vente par ce wizard refusé : utiliser `Apply matching`.
|
</li>
|
||||||
- Le lot physique reprend :
|
<li style="margin:0.38rem 0;"><code>LotQt.add_physical_lot</code>
|
||||||
- ligne achat ;
|
</li>
|
||||||
- vente matchée si présente ;
|
</ul>
|
||||||
- shipment ;
|
</li>
|
||||||
- produit ;
|
<li style="margin:0.38rem 0;">Source obligatoire : une ligne <code>lot.qt</code>.
|
||||||
- unité ;
|
</li>
|
||||||
- quantités ;
|
<li style="margin:0.38rem 0;">Ajout direct depuis un lot physique refusé.
|
||||||
- premium ;
|
</li>
|
||||||
- chunk key.
|
<li style="margin:0.38rem 0;">Ajout physique côté vente par ce wizard refusé : utiliser <code>Apply matching</code>.
|
||||||
- Après création :
|
</li>
|
||||||
- réduction de la ligne `lot.qt` source ;
|
<li style="margin:0.38rem 0;">Le lot physique reprend :
|
||||||
- pas de quantité `lot.qt` négative ;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- recalcul du lot virtuel ;
|
<li style="margin:0.38rem 0;">ligne achat ;
|
||||||
- recalcul de `quantity` ;
|
</li>
|
||||||
- mise à jour moves et fees si nécessaire.
|
<li style="margin:0.38rem 0;">vente matchée si présente ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">shipment ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">produit ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">unité ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">quantités ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">premium ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">chunk key.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Après création :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">réduction de la ligne <code>lot.qt</code> source ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">pas de quantité <code>lot.qt</code> négative ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">recalcul du lot virtuel ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">recalcul de <code>quantity</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">mise à jour moves et fees si nécessaire.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Retrait de lots physiques
|
### Retrait de lots physiques
|
||||||
|
|
||||||
- Wizard : `lot.remove`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Lot ouvert : retrait interdit.
|
<li style="margin:0.38rem 0;">Wizard : <code>lot.remove</code>
|
||||||
- Lot avec `stock.move` :
|
</li>
|
||||||
- move obligatoire en `draft`.
|
<li style="margin:0.38rem 0;">Lot ouvert : retrait interdit.
|
||||||
- Lot matché ou shippé :
|
</li>
|
||||||
- warning confirmable.
|
<li style="margin:0.38rem 0;">Lot avec <code>stock.move</code> :
|
||||||
- Effets :
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- suppression du move draft ;
|
<li style="margin:0.38rem 0;">move obligatoire en <code>draft</code>.
|
||||||
- restauration de la quantité dans `lot.qt` ;
|
</li>
|
||||||
- contexte restauré via shipment, `getVlot_p()`, `getVlot_s()` ;
|
</ul>
|
||||||
- recalcul lot virtuel, `quantity`, fees.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Lot matché ou shippé :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">warning confirmable.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Effets :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">suppression du move draft ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">restauration de la quantité dans <code>lot.qt</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">contexte restauré via shipment, <code>getVlot_p()</code>, <code>getVlot_s()</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">recalcul lot virtuel, <code>quantity</code>, fees.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Weighing / états de quantité
|
### Weighing / états de quantité
|
||||||
|
|
||||||
- Wizard : `lot.weighing`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Action UI : `Do weighing`
|
<li style="margin:0.38rem 0;">Wizard : <code>lot.weighing</code>
|
||||||
- Écrit ou met à jour `lot.qt.hist`.
|
</li>
|
||||||
- Peut mettre à jour `lot_state`.
|
<li style="margin:0.38rem 0;">Action UI : <code>Do weighing</code>
|
||||||
- Synchronise :
|
</li>
|
||||||
- lot ;
|
<li style="margin:0.38rem 0;">Écrit ou met à jour <code>lot.qt.hist</code>.
|
||||||
- quantités ouvertes ;
|
</li>
|
||||||
- fees.
|
<li style="margin:0.38rem 0;">Peut mettre à jour <code>lot_state</code>.
|
||||||
- Les vues `lot.qt.hist` sont consultatives.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Synchronise :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">lot ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">quantités ouvertes ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">fees.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Les vues <code>lot.qt.hist</code> sont consultatives.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Quantité compteur `quantity`
|
### Quantité compteur `quantity`
|
||||||
|
|
||||||
- Méthode : `Lot._recalc_line_quantity`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Sans physique :
|
<li style="margin:0.38rem 0;">Méthode : <code>Lot._recalc_line_quantity</code>
|
||||||
- `quantity` suit le lot virtuel.
|
</li>
|
||||||
- Avec physiques :
|
<li style="margin:0.38rem 0;">Sans physique :
|
||||||
- `quantity` somme uniquement les lots physiques.
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `quantity` est readonly côté ligne trade.
|
<li style="margin:0.38rem 0;"><code>quantity</code> suit le lot virtuel.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Avec physiques :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity</code> somme uniquement les lots physiques.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>quantity</code> est readonly côté ligne trade.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Montant de ligne
|
### Montant de ligne
|
||||||
|
|
||||||
- Achat : `purchase.line.on_change_with_amount()`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Vente : `sale.line.on_change_with_amount()`
|
<li style="margin:0.38rem 0;">Achat : <code>purchase.line.on_change_with_amount()</code>
|
||||||
- Helper :
|
</li>
|
||||||
- `_get_amount_quantity()`
|
<li style="margin:0.38rem 0;">Vente : <code>sale.line.on_change_with_amount()</code>
|
||||||
- `_get_weight_basis_quantity()`
|
</li>
|
||||||
- Priorités :
|
<li style="margin:0.38rem 0;">Helper :
|
||||||
- `finished = False` : `quantity_theorical`
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `finished = True` + Weight basis disponible : somme physique dans cet état
|
<li style="margin:0.38rem 0;"><code>_get_amount_quantity()</code>
|
||||||
- `finished = True` sans Weight basis exploitable : `quantity`
|
</li>
|
||||||
- fallback legacy : `quantity` si `quantity_theorical` vide
|
<li style="margin:0.38rem 0;"><code>_get_weight_basis_quantity()</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Priorités :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;"><code>finished = False</code> : <code>quantity_theorical</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>finished = True</code> + Weight basis disponible : somme physique dans cet état
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>finished = True</code> sans Weight basis exploitable : <code>quantity</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">fallback legacy : <code>quantity</code> si <code>quantity_theorical</code> vide
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Garde-fous Python
|
### Garde-fous Python
|
||||||
|
|
||||||
- Check central :
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `lot.lot.assert_lines_quantity_consistency()`
|
<li style="margin:0.38rem 0;">Check central :
|
||||||
- Blocage `lot.qt` orphelin non zéro :
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- `lot.qt.validate`
|
<li style="margin:0.38rem 0;"><code>lot.lot.assert_lines_quantity_consistency()</code>
|
||||||
- Appels après :
|
</li>
|
||||||
- modification `quantity_theorical` ;
|
</ul>
|
||||||
- création / suppression de lots physiques ;
|
</li>
|
||||||
- matching / unmatching ;
|
<li style="margin:0.38rem 0;">Blocage <code>lot.qt</code> orphelin non zéro :
|
||||||
- shipping / unshipping ;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- weighing.
|
<li style="margin:0.38rem 0;"><code>lot.qt.validate</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Appels après :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">modification <code>quantity_theorical</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">création / suppression de lots physiques ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">matching / unmatching ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">shipping / unshipping ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">weighing.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
### Diagnostic SQL
|
### Diagnostic SQL
|
||||||
|
|
||||||
- Script :
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- [sql/quantity_consistency_checks.sql](sql/quantity_consistency_checks.sql)
|
<li style="margin:0.38rem 0;">Script :
|
||||||
- Usage :
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- audit des bases de test ;
|
<li style="margin:0.38rem 0;"><a href="sql/quantity_consistency_checks.sql">sql/quantity_consistency_checks.sql</a>
|
||||||
- audit des données historiques ;
|
</li>
|
||||||
- qualification avant correction.
|
</ul>
|
||||||
- Le script ignore totalement les `lot.qt = 0`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Usage :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;">audit des bases de test ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">audit des données historiques ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">qualification avant correction.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Le script ignore totalement les <code>lot.qt = 0</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Tests proches
|
## Tests proches
|
||||||
|
|
||||||
- `modules/purchase_trade/tests/test_module.py`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Couverture existante :
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/tests/test_module.py</code>
|
||||||
- `quantity` readonly ;
|
</li>
|
||||||
- initialisation depuis `quantity_theorical` ;
|
<li style="margin:0.38rem 0;">Couverture existante :
|
||||||
- protection si lots physiques ;
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
- amount sur théorique / physique / Weight basis ;
|
<li style="margin:0.38rem 0;"><code>quantity</code> readonly ;
|
||||||
- resynchronisation des lots virtuels ;
|
</li>
|
||||||
- blocages quand l'open ne suffit plus.
|
<li style="margin:0.38rem 0;">initialisation depuis <code>quantity_theorical</code> ;
|
||||||
- Tests à ajouter :
|
</li>
|
||||||
- `lot_hist` readonly ;
|
<li style="margin:0.38rem 0;">protection si lots physiques ;
|
||||||
- `Do weighing` crée ou met à jour un état ;
|
</li>
|
||||||
- lot virtuel sans saisie directe `lot_qt` / `lot_unit` ;
|
<li style="margin:0.38rem 0;">amount sur théorique / physique / Weight basis ;
|
||||||
- contrôles SQL rejoués sur jeux de données incohérents.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">resynchronisation des lots virtuels ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">blocages quand l'open ne suffit plus.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Tests à ajouter :
|
||||||
|
<ul style="margin:0.65rem 0 1rem 1.35rem; padding-left:1rem; list-style-type:circle;">
|
||||||
|
<li style="margin:0.38rem 0;"><code>lot_hist</code> readonly ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Do weighing</code> crée ou met à jour un état ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">lot virtuel sans saisie directe <code>lot_qt</code> / <code>lot_unit</code> ;
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">contrôles SQL rejoués sur jeux de données incohérents.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Lots Management
|
# Lots Management
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,15 +15,21 @@ commercial, le sens achat/vente et l'avancement logistique.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Filtres: `Matching status`, `Side`, `Shipping status`, `Dimension`,
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
`Strategy`.
|
<li style="margin:0.38rem 0;">Filtres: <code>Matching status</code>, <code>Side</code>, <code>Shipping status</code>, <code>Dimension</code>, <code>Strategy</code>.
|
||||||
- Dates `As of` / `To`: `purchase.purchase_date` et `sale.sale_date`.
|
</li>
|
||||||
- `Unshipped`: aucun `shipment_in`.
|
<li style="margin:0.38rem 0;">Dates <code>As of</code> / <code>To</code>: <code>purchase.purchase_date</code> et <code>sale.sale_date</code>.
|
||||||
- `Scheduled`: shipment `draft`.
|
</li>
|
||||||
- `Shipped`: shipment `started`.
|
<li style="margin:0.38rem 0;"><code>Unshipped</code>: aucun <code>shipment_in</code>.
|
||||||
- `Received`: shipment `received` ou `done`.
|
</li>
|
||||||
- `Shipment Type = Dropship` si `from_location.type = supplier` et
|
<li style="margin:0.38rem 0;"><code>Scheduled</code>: shipment <code>draft</code>.
|
||||||
`to_location.type = customer`, sinon `Inbound`.
|
</li>
|
||||||
- `Mark as finished` masque seulement les reliquats ouverts / virtuels, pas
|
<li style="margin:0.38rem 0;"><code>Shipped</code>: shipment <code>started</code>.
|
||||||
les lots physiques.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Received</code>: shipment <code>received</code> ou <code>done</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Shipment Type = Dropship</code> si <code>from_location.type = supplier</code> et <code>to_location.type = customer</code>, sinon <code>Inbound</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>Mark as finished</code> masque seulement les reliquats ouverts / virtuels, pas les lots physiques.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Matching achat / vente
|
# Matching achat / vente
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -14,14 +16,16 @@ lot source.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- La quantite du wizard doit correspondre a la somme des quantites ouvertes
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
selectionnees.
|
<li style="margin:0.38rem 0;">La quantite du wizard doit correspondre a la somme des quantites ouvertes selectionnees.
|
||||||
- Creer une ligne par `lot.qt` source.
|
</li>
|
||||||
- Conserver `created_by_code = True` pour eviter les creations automatiques
|
<li style="margin:0.38rem 0;">Creer une ligne par <code>lot.qt</code> source.
|
||||||
parasites lors des validations.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Conserver <code>created_by_code = True</code> pour eviter les creations automatiques parasites lors des validations.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Notes de migration
|
## Notes de migration
|
||||||
|
|
||||||
Les regles sur `Apply matching` presentes dans les notes de session du
|
Les regles sur `Apply matching` presentes dans les notes de session du
|
||||||
`2026-05-09` doivent encore etre promues ici.
|
`2026-05-09` doivent encore etre promues ici.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Paiements et banques
|
# Paiements et banques
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,9 +15,13 @@ bancaire utilise par la compagnie courante pour encaisser ou payer.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Contrats: `sale.sale`, `purchase.purchase`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `bank_account`: compte de la party du contrat.
|
<li style="margin:0.38rem 0;">Contrats: <code>sale.sale</code>, <code>purchase.purchase</code>.
|
||||||
- `our_bank_account`: compte de la compagnie courante, selectionnable parmi
|
</li>
|
||||||
les comptes disponibles.
|
<li style="margin:0.38rem 0;"><code>bank_account</code>: compte de la party du contrat.
|
||||||
- La devise du contrat est prioritaire pour proposer un compte par defaut.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>our_bank_account</code>: compte de la compagnie courante, selectionnable parmi les comptes disponibles.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">La devise du contrat est prioritaire pour proposer un compte par defaut.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Pricing, basis, premium
|
# Pricing, basis, premium
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,9 +15,14 @@ la ligne soit en prix fixe ou en basis.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- `unit_price` reste le prix de base hors premium.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Montant economique: `unit_price + premium converti si necessaire`.
|
<li style="margin:0.38rem 0;"><code>unit_price</code> reste le prix de base hors premium.
|
||||||
- En basis, le premium s'applique aussi aux blocs valorises.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Montant economique: <code>unit_price + premium converti si necessaire</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">En basis, le premium s'applique aussi aux blocs valorises.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-PRI-002 - Linked currency
|
## BR-PT-PRI-002 - Linked currency
|
||||||
|
|
||||||
@@ -28,11 +35,14 @@ dans ce meme repere puis converti pour les calculs internes.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Champs obligatoires si active: `linked_price`, `linked_currency`,
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
`linked_unit`.
|
<li style="margin:0.38rem 0;">Champs obligatoires si active: <code>linked_price</code>, <code>linked_currency</code>, <code>linked_unit</code>.
|
||||||
- En `basis + linked currency`, `linked_price` represente le basis brut hors
|
</li>
|
||||||
premium.
|
<li style="margin:0.38rem 0;">En <code>basis + linked currency</code>, <code>linked_price</code> represente le basis brut hors premium.
|
||||||
- `amount` ajoute le premium converti.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>amount</code> ajoute le premium converti.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-PRI-003 - Pricing manuel
|
## BR-PT-PRI-003 - Pricing manuel
|
||||||
|
|
||||||
@@ -45,9 +55,13 @@ le prix de marche. Les cumuls et prix moyens sont calcules automatiquement.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Champs saisis: `quantity`, `settl_price`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Champs derives: `fixed_qt`, `fixed_qt_price`, `unfixed_qt`,
|
<li style="margin:0.38rem 0;">Champs saisis: <code>quantity</code>, <code>settl_price</code>.
|
||||||
`unfixed_qt_price`, `eod_price`, `last`.
|
</li>
|
||||||
- Groupe metier: `line + component` ou `sale_line + component`.
|
<li style="margin:0.38rem 0;">Champs derives: <code>fixed_qt</code>, <code>fixed_qt_price</code>, <code>unfixed_qt</code>, <code>unfixed_qt_price</code>, <code>eod_price</code>, <code>last</code>.
|
||||||
- Le composant choisi doit appartenir a la ligne courante.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Groupe metier: <code>line + component</code> ou <code>sale_line + component</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Le composant choisi doit appartenir a la ligne courante.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Reports et templates
|
# Reports et templates
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
|
|
||||||
Voir aussi:
|
Voir aussi:
|
||||||
|
|
||||||
- `../template-rules.md`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `../template-properties.md`
|
<li style="margin:0.38rem 0;"><code>../template-rules.md</code>
|
||||||
- `../../../../notes/template_business_rules.md`
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>../template-properties.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>../../../../notes/template_business_rules.md</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-RPT-001 - Templates trade via proprietes Python
|
## BR-PT-RPT-001 - Templates trade via proprietes Python
|
||||||
|
|
||||||
@@ -19,21 +26,30 @@ d'expressions fragiles dans le fichier bureautique.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Preferer des proprietes Python simples, souvent prefixees `report_*`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Dans les placeholders XML, utiliser `"` et `'` plutot que des
|
<li style="margin:0.38rem 0;">Preferer des proprietes Python simples, souvent prefixees <code>report_*</code>.
|
||||||
antislashs.
|
</li>
|
||||||
- Pour les factures liees a vente/achat/shipment, privilegier le lot physique
|
<li style="margin:0.38rem 0;">Dans les placeholders XML, utiliser <code>&quot;</code> et <code>&apos;</code> plutot que des antislashs.
|
||||||
comme pont.
|
</li>
|
||||||
- Verifier le cache `invoice_report_cache` avant de conclure qu'une action
|
<li style="margin:0.38rem 0;">Pour les factures liees a vente/achat/shipment, privilegier le lot physique comme pont.
|
||||||
report pointe vers le mauvais `.fodt`.
|
</li>
|
||||||
- Pour les templates shipment, preferer `records[0]...` ou des proprietes sur
|
<li style="margin:0.38rem 0;">Verifier le cache <code>invoice_report_cache</code> avant de conclure qu'une action report pointe vers le mauvais <code>.fodt</code>.
|
||||||
`stock.shipment.in` plutot qu'une variable locale supposee.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Pour les templates shipment, preferer <code>records[0]...</code> ou des proprietes sur <code>stock.shipment.in</code> plutot qu'une variable locale supposee.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Decisions deja documentees a migrer ensuite
|
## Decisions deja documentees a migrer ensuite
|
||||||
|
|
||||||
- `insurance.fodt`: compagnie courante, amount insured a 110%, surveyor.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `packing_list.fodt`: date du jour, unites depuis `purchase.line`.
|
<li style="margin:0.38rem 0;"><code>insurance.fodt</code>: compagnie courante, amount insured a 110%, surveyor.
|
||||||
- `bill.fodt`: maturity date reelle et montant en lettres depuis le total.
|
</li>
|
||||||
- `invoice_ict.fodt` / `invoice_ict_final.fodt`: poids, shipments et lots.
|
<li style="margin:0.38rem 0;"><code>packing_list.fodt</code>: date du jour, unites depuis <code>purchase.line</code>.
|
||||||
- `sale_ict.fodt`: priorite lots et unite reelle.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>bill.fodt</code>: maturity date reelle et montant en lettres depuis le total.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>invoice_ict.fodt</code> / <code>invoice_ict_final.fodt</code>: poids, shipments et lots.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>sale_ict.fodt</code>: priorite lots et unite reelle.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Risque, credit, forex
|
# Risque, credit, forex
|
||||||
|
|
||||||
Statut: `placeholder`
|
Statut: `placeholder`
|
||||||
@@ -9,7 +11,11 @@ Aucune regle canonique `purchase_trade` n'a ete promue ici dans cette premiere
|
|||||||
passe. Les notes comptables et forex existantes doivent etre relues avant toute
|
passe. Les notes comptables et forex existantes doivent etre relues avant toute
|
||||||
migration:
|
migration:
|
||||||
|
|
||||||
- `notes/accounting/README.md`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `notes/accounting/business_rules.md`
|
<li style="margin:0.38rem 0;"><code>notes/accounting/README.md</code>
|
||||||
- `notes/accounting/reporting.md`
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>notes/accounting/business_rules.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>notes/accounting/reporting.md</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Journal de migration et sessions
|
# Journal de migration et sessions
|
||||||
|
|
||||||
Statut: `non canonique`
|
Statut: `non canonique`
|
||||||
@@ -7,25 +9,28 @@ canonique seulement quand elle est reprise dans une page thematique.
|
|||||||
|
|
||||||
## Sources historiques
|
## Sources historiques
|
||||||
|
|
||||||
- `modules/purchase_trade/docs/business-rules.md`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `modules/purchase_trade/docs/business-rules-architecture-proposal.md`
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/business-rules.md</code>
|
||||||
- `notes/business_rules.md`
|
</li>
|
||||||
- `notes/template_business_rules.md`
|
<li style="margin:0.38rem 0;"><code>modules/purchase_trade/docs/business-rules-architecture-proposal.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>notes/business_rules.md</code>
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>notes/template_business_rules.md</code>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## Notes deja partiellement promues
|
## Notes deja partiellement promues
|
||||||
|
|
||||||
- Session `2026-04-30`: PnL fees ouverts et `% rate`, promue dans
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
[fees.md](fees.md) et [valuation-pnl-mtm.md](valuation-pnl-mtm.md).
|
<li style="margin:0.38rem 0;">Session <code>2026-04-30</code>: PnL fees ouverts et <code>% rate</code>, promue dans <a href="fees.md">fees.md</a> et <a href="valuation-pnl-mtm.md">valuation-pnl-mtm.md</a>.
|
||||||
- Session `2026-05-01`: solde ouvert apres lots physiques et lots effectifs
|
</li>
|
||||||
des fees, promue dans [lots-and-quantities.md](lots-and-quantities.md) et
|
<li style="margin:0.38rem 0;">Session <code>2026-05-01</code>: solde ouvert apres lots physiques et lots effectifs des fees, promue dans <a href="lots-and-quantities.md">lots-and-quantities.md</a> et <a href="fees.md">fees.md</a>.
|
||||||
[fees.md](fees.md).
|
</li>
|
||||||
- Session `2026-05-06`: Remove physical lot, promue dans
|
<li style="margin:0.38rem 0;">Session <code>2026-05-06</code>: Remove physical lot, promue dans <a href="lots-and-quantities.md">lots-and-quantities.md</a>.
|
||||||
[lots-and-quantities.md](lots-and-quantities.md).
|
</li>
|
||||||
- Session `2026-05-09`: Lots Management, promue partiellement dans
|
<li style="margin:0.38rem 0;">Session <code>2026-05-09</code>: Lots Management, promue partiellement dans <a href="lots-management.md">lots-management.md</a>.
|
||||||
[lots-management.md](lots-management.md).
|
</li>
|
||||||
- Session `2026-05-13`: cadrage `quantity_theorical` / `quantity`, amount de
|
<li style="margin:0.38rem 0;">Session <code>2026-05-13</code>: cadrage <code>quantity_theorical</code> / <code>quantity</code>, amount de ligne, Weight basis, invariants de quantite, checks Python bloquants et diagnostic SQL. Promue dans <a href="lots-and-quantities.md">lots-and-quantities.md</a>, <a href="lots-and-quantities.en.md">lots-and-quantities.en.md</a>, <a href="invariants.md">invariants.md</a> et <a href="sql/README.md">sql/README.md</a>.
|
||||||
ligne, Weight basis, invariants de quantite, checks Python bloquants et
|
</li>
|
||||||
diagnostic SQL. Promue dans
|
</ul>
|
||||||
[lots-and-quantities.md](lots-and-quantities.md),
|
|
||||||
[lots-and-quantities.en.md](lots-and-quantities.en.md),
|
|
||||||
[invariants.md](invariants.md) et [sql/README.md](sql/README.md).
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Shipments et execution
|
# Shipments et execution
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,10 +15,16 @@ retard par rapport a son objectif.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Configuration: onglet `Execution` de `party.party`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- La zone du shipment vient de `shipment.to_location.country`.
|
<li style="margin:0.38rem 0;">Configuration: onglet <code>Execution</code> de <code>party.party</code>.
|
||||||
- Une region parente couvre ses sous-regions.
|
</li>
|
||||||
- `% achieved` compte seulement les shipments deja affectes a un controller.
|
<li style="margin:0.38rem 0;">La zone du shipment vient de <code>shipment.to_location.country</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Une region parente couvre ses sous-regions.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>% achieved</code> compte seulement les shipments deja affectes a un controller.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-SHP-002 - Couts SLA controller par pays et/ou lieu
|
## BR-PT-SHP-002 - Couts SLA controller par pays et/ou lieu
|
||||||
|
|
||||||
@@ -29,8 +37,12 @@ lieu. Le couple est le cas le plus specifique.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Matching: `country + location`, puis `location`, puis `country`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Le pays vient de `shipment.to_location.country`.
|
<li style="margin:0.38rem 0;">Matching: <code>country + location</code>, puis <code>location</code>, puis <code>country</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Le pays vient de <code>shipment.to_location.country</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-SHP-003 - Weight reports distants par lot
|
## BR-PT-SHP-003 - Weight reports distants par lot
|
||||||
|
|
||||||
@@ -43,7 +55,11 @@ sur le shipment.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Exporter seulement les lots physiques des `incoming_moves`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Exiger au minimum `controller` et `returned_id` sur le shipment.
|
<li style="margin:0.38rem 0;">Exporter seulement les lots physiques des <code>incoming_moves</code>.
|
||||||
- Conserver les cles distantes et la date d'envoi sur le `weight.report`.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Exiger au minimum <code>controller</code> et <code>returned_id</code> sur le shipment.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Conserver les cles distantes et la date d'envoi sur le <code>weight.report</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# SQL diagnostics for purchase_trade business rules
|
# SQL diagnostics for purchase_trade business rules
|
||||||
|
|
||||||
These scripts are read-only diagnostics for a PostgreSQL test database.
|
These scripts are read-only diagnostics for a PostgreSQL test database.
|
||||||
@@ -23,24 +25,34 @@ reported as anomalous.
|
|||||||
|
|
||||||
Run it on a restored test database:
|
Run it on a restored test database:
|
||||||
|
|
||||||
```sql
|
<pre style="background:#263238; color:#eef7ff; padding:1rem; border-radius:0.35rem; overflow:auto;"><code>\i modules/purchase_trade/docs/business/sql/quantity_consistency_checks.sql</code></pre>
|
||||||
\i modules/purchase_trade/docs/business/sql/quantity_consistency_checks.sql
|
|
||||||
```
|
|
||||||
|
|
||||||
The script returns rows only when it finds a potential issue.
|
The script returns rows only when it finds a potential issue.
|
||||||
|
|
||||||
Main columns:
|
Main columns:
|
||||||
|
|
||||||
- `check_name`: invariant or diagnostic that failed.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- `contract_model`: `purchase.purchase` or `sale.sale`.
|
<li style="margin:0.38rem 0;"><code>check_name</code>: invariant or diagnostic that failed.
|
||||||
- `contract_id`: database id of the contract.
|
</li>
|
||||||
- `contract_number`: purchase or sale contract number.
|
<li style="margin:0.38rem 0;"><code>contract_model</code>: <code>purchase.purchase</code> or <code>sale.sale</code>.
|
||||||
- `line_id`: `purchase.line` or `sale.line` id depending on the check.
|
</li>
|
||||||
- `virtual_lot_id`: virtual lot involved in the inconsistency.
|
<li style="margin:0.38rem 0;"><code>contract_id</code>: database id of the contract.
|
||||||
- `observed_value`: value found in the database.
|
</li>
|
||||||
- `expected_value`: value required by the business rule.
|
<li style="margin:0.38rem 0;"><code>contract_number</code>: purchase or sale contract number.
|
||||||
- `diff`: observed minus expected.
|
</li>
|
||||||
- `detail`: human-readable explanation.
|
<li style="margin:0.38rem 0;"><code>line_id</code>: <code>purchase.line</code> or <code>sale.line</code> id depending on the check.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>virtual_lot_id</code>: virtual lot involved in the inconsistency.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>observed_value</code>: value found in the database.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>expected_value</code>: value required by the business rule.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>diff</code>: observed minus expected.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;"><code>detail</code>: human-readable explanation.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
Cross-category UoM rows are reported as manual-review diagnostics because the
|
Cross-category UoM rows are reported as manual-review diagnostics because the
|
||||||
Python code may pass explicit conversion factors that cannot be inferred safely
|
Python code may pass explicit conversion factors that cannot be inferred safely
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated from docs_source/business by docs/tools/render_business_docs.py. -->
|
||||||
|
|
||||||
# Valuation, PnL, MTM
|
# Valuation, PnL, MTM
|
||||||
|
|
||||||
Statut: `migration partielle`
|
Statut: `migration partielle`
|
||||||
@@ -13,12 +15,14 @@ n'est pas encore matchee a un achat.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- Une `sale.line` non matchee doit generer au minimum `sale priced`, `sale fee`
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
et `derivative` si applicable.
|
<li style="margin:0.38rem 0;">Une <code>sale.line</code> non matchee doit generer au minimum <code>sale priced</code>, <code>sale fee</code> et <code>derivative</code> si applicable.
|
||||||
- Une sale basis sans detail de prix doit quand meme produire une ligne a zero
|
</li>
|
||||||
ou au prix economique fallback selon la regle applicable.
|
<li style="margin:0.38rem 0;">Une sale basis sans detail de prix doit quand meme produire une ligne a zero ou au prix economique fallback selon la regle applicable.
|
||||||
- Ne pas attacher arbitrairement une sale unique si plusieurs sales sont
|
</li>
|
||||||
matchees au meme ouvert.
|
<li style="margin:0.38rem 0;">Ne pas attacher arbitrairement une sale unique si plusieurs sales sont matchees au meme ouvert.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-VAL-002 - References de valuation
|
## BR-PT-VAL-002 - References de valuation
|
||||||
|
|
||||||
@@ -31,9 +35,12 @@ vente, ouverte ou physique.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- References autorisees: `Purchase/Open`, `Purchase/Physic`, `Sale/Open`,
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
`Sale/Physic`.
|
<li style="margin:0.38rem 0;">References autorisees: <code>Purchase/Open</code>, <code>Purchase/Physic</code>, <code>Sale/Open</code>, <code>Sale/Physic</code>.
|
||||||
- Un lot virtuel ne doit pas sortir avec une reference physique.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Un lot virtuel ne doit pas sortir avec une reference physique.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
## BR-PT-VAL-003 - MTM hors fees
|
## BR-PT-VAL-003 - MTM hors fees
|
||||||
|
|
||||||
@@ -45,7 +52,11 @@ Le mark-to-market s'applique aux prix et aux derives, pas aux frais.
|
|||||||
|
|
||||||
### Notes developpeur
|
### Notes developpeur
|
||||||
|
|
||||||
- MTM autorise pour `pur. priced`, `sale priced`, `derivative`.
|
<ul style="margin:0.65rem 0 1rem 1.1rem; padding-left:1rem; list-style-type:disc;">
|
||||||
- Fees hors MTM: `pur. fee`, `sale fee`, `shipment fee`, `line fee`.
|
<li style="margin:0.38rem 0;">MTM autorise pour <code>pur. priced</code>, <code>sale priced</code>, <code>derivative</code>.
|
||||||
- Pour les fees: `mtm_price`, `mtm`, `strategy` doivent rester vides.
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Fees hors MTM: <code>pur. fee</code>, <code>sale fee</code>, <code>shipment fee</code>, <code>line fee</code>.
|
||||||
|
</li>
|
||||||
|
<li style="margin:0.38rem 0;">Pour les fees: <code>mtm_price</code>, <code>mtm</code>, <code>strategy</code> doivent rester vides.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|||||||
@@ -10,18 +10,13 @@ from __future__ import annotations
|
|||||||
import argparse
|
import argparse
|
||||||
import html
|
import html
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
BUSINESS = ROOT / "business"
|
BUSINESS = ROOT / "business"
|
||||||
SOURCE = ROOT.parent / "docs_source" / "business"
|
SOURCE = ROOT.parent / "docs_source" / "business"
|
||||||
TARGETS = (
|
|
||||||
"lots-and-quantities.md",
|
|
||||||
"lots-and-quantities.en.md",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
MATERIAL_ICON = re.compile(r":material-[a-z0-9-]+:\s*")
|
MATERIAL_ICON = re.compile(r":material-[a-z0-9-]+:\s*")
|
||||||
|
|
||||||
|
|
||||||
@@ -190,6 +185,56 @@ def render_callout(lines: list[str]) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_bullet_line(line: str) -> bool:
|
||||||
|
return bool(re.match(r"^\s*-\s+", line))
|
||||||
|
|
||||||
|
|
||||||
|
def bullet_level(line: str) -> int:
|
||||||
|
return len(re.match(r"^\s*", line).group(0)) // 2
|
||||||
|
|
||||||
|
|
||||||
|
def render_list(lines: list[str]) -> str:
|
||||||
|
root: list[dict[str, object]] = []
|
||||||
|
stack: list[tuple[int, list[dict[str, object]]]] = [(-1, root)]
|
||||||
|
last_item: dict[str, object] | None = None
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if is_bullet_line(line):
|
||||||
|
level = bullet_level(line)
|
||||||
|
content = re.sub(r"^\s*-\s+", "", line).strip()
|
||||||
|
while stack[-1][0] >= level:
|
||||||
|
stack.pop()
|
||||||
|
item: dict[str, object] = {
|
||||||
|
"content": content,
|
||||||
|
"children": [],
|
||||||
|
}
|
||||||
|
stack[-1][1].append(item)
|
||||||
|
stack.append((level, item["children"]))
|
||||||
|
last_item = item
|
||||||
|
elif line.strip() and last_item is not None:
|
||||||
|
last_item["content"] = str(last_item["content"]) + " " + line.strip()
|
||||||
|
|
||||||
|
def render_items(items: list[dict[str, object]], level: int = 0) -> str:
|
||||||
|
margin = "1.1rem" if level == 0 else "1.35rem"
|
||||||
|
bullet = "disc" if level == 0 else "circle"
|
||||||
|
parts = [
|
||||||
|
f'<ul style="margin:0.65rem 0 1rem {margin}; padding-left:1rem; list-style-type:{bullet};">'
|
||||||
|
]
|
||||||
|
for item in items:
|
||||||
|
children = item["children"]
|
||||||
|
parts.append(
|
||||||
|
'<li style="margin:0.38rem 0;">'
|
||||||
|
f"{render_inline(str(item['content']))}"
|
||||||
|
)
|
||||||
|
if children:
|
||||||
|
parts.append(render_items(children, level + 1))
|
||||||
|
parts.append("</li>")
|
||||||
|
parts.append("</ul>")
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
return render_items(root)
|
||||||
|
|
||||||
|
|
||||||
def render_source(text: str) -> str:
|
def render_source(text: str) -> str:
|
||||||
lines = text.splitlines()
|
lines = text.splitlines()
|
||||||
out = [
|
out = [
|
||||||
@@ -244,20 +289,47 @@ def render_source(text: str) -> str:
|
|||||||
out.extend(table)
|
out.extend(table)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if is_bullet_line(line):
|
||||||
|
list_lines = []
|
||||||
|
while i < len(lines) and (
|
||||||
|
is_bullet_line(lines[i])
|
||||||
|
or (
|
||||||
|
lines[i].startswith(" ")
|
||||||
|
and lines[i].strip()
|
||||||
|
and not lines[i].lstrip().startswith("|")
|
||||||
|
)
|
||||||
|
):
|
||||||
|
list_lines.append(lines[i])
|
||||||
|
i += 1
|
||||||
|
out.append(render_list(list_lines))
|
||||||
|
continue
|
||||||
|
|
||||||
out.append(line)
|
out.append(line)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
return "\n".join(out).strip() + "\n"
|
return "\n".join(out).strip() + "\n"
|
||||||
|
|
||||||
|
|
||||||
def render_all(normalize: bool = False) -> None:
|
def source_files() -> list[Path]:
|
||||||
|
return sorted(path for path in SOURCE.rglob("*.md") if path.is_file())
|
||||||
|
|
||||||
|
|
||||||
|
def render_all(normalize: bool = False, check: bool = False) -> bool:
|
||||||
SOURCE.mkdir(parents=True, exist_ok=True)
|
SOURCE.mkdir(parents=True, exist_ok=True)
|
||||||
for name in TARGETS:
|
ok = True
|
||||||
source = SOURCE / name
|
for source in source_files():
|
||||||
target = BUSINESS / name
|
target = BUSINESS / source.relative_to(SOURCE)
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
if normalize:
|
if normalize:
|
||||||
source.write_text(normalize_source(source.read_text(encoding="utf-8")), encoding="utf-8")
|
source.write_text(normalize_source(source.read_text(encoding="utf-8")), encoding="utf-8")
|
||||||
target.write_text(render_source(source.read_text(encoding="utf-8")), encoding="utf-8")
|
rendered = render_source(source.read_text(encoding="utf-8"))
|
||||||
|
if check:
|
||||||
|
if not target.exists() or target.read_text(encoding="utf-8") != rendered:
|
||||||
|
print(f"Outdated generated doc: {target.relative_to(ROOT.parent)}")
|
||||||
|
ok = False
|
||||||
|
else:
|
||||||
|
target.write_text(rendered, encoding="utf-8")
|
||||||
|
return ok
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@@ -267,8 +339,16 @@ def main() -> None:
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="Clean existing source files from wiki-only syntax before rendering.",
|
help="Clean existing source files from wiki-only syntax before rendering.",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--check",
|
||||||
|
action="store_true",
|
||||||
|
help="Fail if generated wiki files are not up to date.",
|
||||||
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
render_all(normalize=args.normalize_source)
|
if args.normalize_source and args.check:
|
||||||
|
parser.error("--normalize-source cannot be used with --check")
|
||||||
|
if not render_all(normalize=args.normalize_source, check=args.check):
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
48
modules/purchase_trade/docs_source/business/INDEX.md
Normal file
48
modules/purchase_trade/docs_source/business/INDEX.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Index thematique des regles business
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## Comment chercher une regle
|
||||||
|
|
||||||
|
- Contrats, dates, lieux, banques: [contracts.md](contracts.md)
|
||||||
|
- Lots virtuels, lots physiques, `lot.qt`, weighing: [FR](lots-and-quantities.md) / [EN](lots-and-quantities.en.md)
|
||||||
|
- Matching, Create Contracts, back-to-back: [matching.md](matching.md)
|
||||||
|
- Shipments, controllers, SLA, weight reports: [shipments-execution.md](shipments-execution.md)
|
||||||
|
- Pricing manuel, basis, premium, linked currency: [pricing.md](pricing.md)
|
||||||
|
- Fees, freight, lots effectifs, `% rate`: [fees.md](fees.md)
|
||||||
|
- Valuation, PnL, MTM, derivatives: [valuation-pnl-mtm.md](valuation-pnl-mtm.md)
|
||||||
|
- Factures provisoires/finales, padding: [invoicing.md](invoicing.md)
|
||||||
|
- Impacts `account.move`, validate/post: [accounting-bridge.md](accounting-bridge.md)
|
||||||
|
- Comptes bancaires, payment terms, payment orders: [payments-banking.md](payments-banking.md)
|
||||||
|
- Relatorio, `.fodt`, proprietes `report_*`: [reports-templates.md](reports-templates.md)
|
||||||
|
- Risque, credit, forex: [risk-credit-forex.md](risk-credit-forex.md)
|
||||||
|
- Rapport Lots Management: [lots-management.md](lots-management.md)
|
||||||
|
- Diagnostics SQL des invariants: [sql/README.md](sql/README.md)
|
||||||
|
|
||||||
|
## Regles migrees dans cette premiere passe
|
||||||
|
|
||||||
|
- `BR-PT-CON-001`: texte par defaut de pricing rule.
|
||||||
|
- `BR-PT-CON-002`: delivery period coherent.
|
||||||
|
- `BR-PT-CON-003`: lieux stock propages dans Create Contracts.
|
||||||
|
- `BR-PT-LOT-001`: cycle de vie des lots et des quantites.
|
||||||
|
- `BR-PT-LOT-002`: quantity contractuelle, execute physique et ligne finie.
|
||||||
|
- `BR-PT-LOT-003`: garde-fous Python et diagnostics SQL des invariants de
|
||||||
|
quantite.
|
||||||
|
- `BR-PT-MAT-001`: Create Contracts multi-lots.
|
||||||
|
- `BR-PT-SHP-001`: affectation controller.
|
||||||
|
- `BR-PT-SHP-002`: couts SLA controller.
|
||||||
|
- `BR-PT-SHP-003`: weight reports distants.
|
||||||
|
- `BR-PT-PRI-001`: premium dans priced et basis.
|
||||||
|
- `BR-PT-PRI-002`: linked currency.
|
||||||
|
- `BR-PT-PRI-003`: pricing manuel.
|
||||||
|
- `BR-PT-FEE-001`: maritime freight depuis fee shipment.
|
||||||
|
- `BR-PT-FEE-002`: lots effectifs des fees.
|
||||||
|
- `BR-PT-FEE-003`: `% rate` via delta de financement.
|
||||||
|
- `BR-PT-VAL-001`: valuation achat/vente et sale-first.
|
||||||
|
- `BR-PT-VAL-002`: references de valuation.
|
||||||
|
- `BR-PT-VAL-003`: MTM hors fees.
|
||||||
|
- `BR-PT-INV-001`: padding facture provisoire vente.
|
||||||
|
- `BR-PT-ACC-001`: Validate facture client attribue le numero.
|
||||||
|
- `BR-PT-PAY-001`: comptes bancaires tiers vs compagnie.
|
||||||
|
- `BR-PT-RPT-001`: templates trade via proprietes Python.
|
||||||
|
- `BR-PT-LOTMGT-001`: filtres Lots Management.
|
||||||
117
modules/purchase_trade/docs_source/business/README.md
Normal file
117
modules/purchase_trade/docs_source/business/README.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Guide de lecture des règles business
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
Dernière mise à jour: `2026-05-13`
|
||||||
|
|
||||||
|
Ce dossier devient la source de lecture thématique publiée dans le wiki pour les
|
||||||
|
règles business du module `purchase_trade`.
|
||||||
|
|
||||||
|
Toutes les pages business publiées dans `modules/purchase_trade/docs/business/`
|
||||||
|
sont générées depuis une source de vérité plus sobre, rangée hors du dossier
|
||||||
|
wiki dans `modules/purchase_trade/docs_source/business/`.
|
||||||
|
|
||||||
|
Les pages publiées portent un commentaire `Generated from ...` en tête de
|
||||||
|
fichier et ne doivent pas être modifiées directement. Aucun contenu business ne
|
||||||
|
doit être ajouté ou modifié sans passer par cette source puis par le script de
|
||||||
|
génération.
|
||||||
|
|
||||||
|
Chaque page doit rester lisible par deux publics:
|
||||||
|
|
||||||
|
- les consultants, qui ont besoin d'une règle fonctionnelle stable sans détail
|
||||||
|
de code inutile;
|
||||||
|
- les développeurs, qui ont besoin des champs, modèles, fichiers et tests
|
||||||
|
concernés pour appliquer la règle sans l'interpréter.
|
||||||
|
|
||||||
|
## Convention de langues
|
||||||
|
|
||||||
|
Chaque page thématique durable doit exister en deux versions maintenues
|
||||||
|
ensemble:
|
||||||
|
|
||||||
|
- une page française, rédigée en français correct avec accents, typographie et
|
||||||
|
formulations naturelles pour le wiki consultant;
|
||||||
|
- une page anglaise miroir, portant le même contenu fonctionnel et technique.
|
||||||
|
|
||||||
|
Convention de nommage:
|
||||||
|
|
||||||
|
- page française principale: `theme.md`;
|
||||||
|
- page anglaise miroir: `theme.en.md`.
|
||||||
|
|
||||||
|
Toute modification d'une règle business, d'un statut, d'un champ technique ou
|
||||||
|
d'un point de vigilance doit être reportée dans les deux pages au même moment.
|
||||||
|
Les deux pages doivent indiquer leur page miroir en en-tête.
|
||||||
|
|
||||||
|
## Convention source / wiki
|
||||||
|
|
||||||
|
Pour toute page business:
|
||||||
|
|
||||||
|
- éditer la source de vérité dans `modules/purchase_trade/docs_source/business/`;
|
||||||
|
- régénérer la version wiki avec:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python modules/purchase_trade/docs/tools/render_business_docs.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Le rendu wiki privilégie du HTML simple et portable plutôt que des extensions
|
||||||
|
MkDocs optionnelles. Cela évite d'exposer dans le wiki des marqueurs non rendus
|
||||||
|
comme `!!!` ou `:material-...:`.
|
||||||
|
|
||||||
|
Les fichiers générés dans `modules/purchase_trade/docs/business/` sont des
|
||||||
|
artefacts de publication: ils peuvent être relus, mais toute correction doit
|
||||||
|
être reportée dans `docs_source/business/` avant régénération.
|
||||||
|
|
||||||
|
Avant de livrer une modification documentaire, vérifier que les pages publiées
|
||||||
|
sont à jour avec:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python modules/purchase_trade/docs/tools/render_business_docs.py --check
|
||||||
|
```
|
||||||
|
|
||||||
|
## Convention de rédaction
|
||||||
|
|
||||||
|
Pour chaque règle durable, utiliser autant que possible ce format:
|
||||||
|
|
||||||
|
```md
|
||||||
|
### BR-PT-THEME-001 - Titre court
|
||||||
|
|
||||||
|
Statut: active
|
||||||
|
Source: business-rules.md / note de session / décision projet
|
||||||
|
|
||||||
|
#### Règle consultant
|
||||||
|
|
||||||
|
Texte fonctionnel, sans nom de champ si ce n'est pas nécessaire.
|
||||||
|
|
||||||
|
#### Notes développeur
|
||||||
|
|
||||||
|
- Modèles/champs:
|
||||||
|
- Fichiers:
|
||||||
|
- Tests:
|
||||||
|
- Points de vigilance:
|
||||||
|
```
|
||||||
|
|
||||||
|
## Convention de validation
|
||||||
|
|
||||||
|
Quand une règle business devient structurante pour l'intégrité des données, elle
|
||||||
|
doit être accompagnée autant que possible de deux garde-fous:
|
||||||
|
|
||||||
|
- un check applicatif bloquant dans le code Python, appelé à la fin des flux qui
|
||||||
|
modifient les données concernées;
|
||||||
|
- un diagnostic SQL en lecture seule pour auditer les bases existantes ou les
|
||||||
|
bases de test.
|
||||||
|
|
||||||
|
Les diagnostics SQL du module sont rangés dans `business/sql/`. Ils ne
|
||||||
|
remplacent pas les règles applicatives: ils servent à retrouver et qualifier les
|
||||||
|
écarts déjà présents dans une base.
|
||||||
|
|
||||||
|
## Sources pendant la migration
|
||||||
|
|
||||||
|
Les anciennes pages ne sont pas supprimées à cette étape. Elles restent des
|
||||||
|
sources de vérification jusqu'à ce que chaque décision soit promue dans une
|
||||||
|
page thématique:
|
||||||
|
|
||||||
|
- `modules/purchase_trade/docs/business-rules.md`
|
||||||
|
- `modules/purchase_trade/docs/fees.md`
|
||||||
|
- `modules/purchase_trade/docs/padding-invoice-accounting.md`
|
||||||
|
- `modules/purchase_trade/docs/template-rules.md`
|
||||||
|
- `modules/purchase_trade/docs/template-properties.md`
|
||||||
|
- `notes/business_rules.md`
|
||||||
|
- `notes/template_business_rules.md`
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Pont comptable
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-ACC-001 - Validate facture client attribue aussi le numero
|
||||||
|
|
||||||
|
Source: `BR-PT-017`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Une facture client doit recevoir son mouvement comptable et son numero des la
|
||||||
|
validation, comme une facture fournisseur.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Cible: `account.invoice` avec `type = out`.
|
||||||
|
- Workflow `Validate`: creer `account.move` et attribuer `number`.
|
||||||
|
- Workflow `Post`: ne doit pas reintroduire une session fraiche specifique au
|
||||||
|
flux client.
|
||||||
|
|
||||||
|
## Notes de migration
|
||||||
|
|
||||||
|
Les notes comptables detaillees restent dans `notes/accounting/` tant qu'elles
|
||||||
|
n'ont pas ete promues ici.
|
||||||
|
|
||||||
50
modules/purchase_trade/docs_source/business/contracts.md
Normal file
50
modules/purchase_trade/docs_source/business/contracts.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Contrats achat / vente
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-CON-001 - Texte par defaut de pricing rule
|
||||||
|
|
||||||
|
Source: `BR-PT-013`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le texte de regle de pricing recurrent doit etre configure une seule fois et
|
||||||
|
repris automatiquement sur les nouvelles lignes achat et vente.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Configuration: `purchase_trade.configuration.pricing_rule`.
|
||||||
|
- Cibles: `purchase.line.pricing_rule`, `sale.line.pricing_rule`.
|
||||||
|
- Les lignes existantes ne sont pas modifiees retroactivement.
|
||||||
|
|
||||||
|
## BR-PT-CON-002 - Delivery period coherent
|
||||||
|
|
||||||
|
Source: `BR-PT-014` historique, doublon de numerotation a corriger
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Une periode de livraison ne peut pas commencer apres sa date de fin. Une seule
|
||||||
|
borne renseignee reste acceptee.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Champs: `purchase.line.from_del`, `purchase.line.to_del`,
|
||||||
|
`sale.line.from_del`, `sale.line.to_del`.
|
||||||
|
- Validation attendue: bloquer si `from_del > to_del`.
|
||||||
|
|
||||||
|
## BR-PT-CON-003 - Propagation des lieux stock dans Create Contracts
|
||||||
|
|
||||||
|
Source: `BR-PT-024`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Quand un contrat miroir est cree depuis une quantite ouverte, les lieux
|
||||||
|
logistiques doivent etre proposes selon le flux source pour eviter la ressaisie.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Champs: `from_location`, `to_location`.
|
||||||
|
- Flux fournisseur vers client: recopier le couple source.
|
||||||
|
- Achat vers stock puis vente: `sale.from_location = purchase.to_location`.
|
||||||
|
- Vente depuis stock puis achat: `purchase.to_location = sale.from_location`.
|
||||||
|
|
||||||
55
modules/purchase_trade/docs_source/business/fees.md
Normal file
55
modules/purchase_trade/docs_source/business/fees.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Fees
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
Voir aussi la page technique historique: `../fees.md`.
|
||||||
|
|
||||||
|
## BR-PT-FEE-001 - Freight value depuis fee shipment
|
||||||
|
|
||||||
|
Source: `BR-PT-003`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
La valeur de fret affichee sur les documents facture vient du fee maritime du
|
||||||
|
shipment, pas d'un champ direct de la facture.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Retrouver le lot physique depuis la facture.
|
||||||
|
- Retrouver son `shipment_in`.
|
||||||
|
- Chercher le `fee.fee` avec `product.name = 'Maritime freight'`.
|
||||||
|
- Utiliser `fee.get_amount()`.
|
||||||
|
|
||||||
|
## BR-PT-FEE-002 - Les fees lies aux lots privilegient les physiques
|
||||||
|
|
||||||
|
Source: `BR-PT-021`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Un fee suit le lot virtuel tant qu'aucun lot physique n'est lie. Des qu'un lot
|
||||||
|
physique est lie, les lots physiques deviennent la base de calcul du fee.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Ne pas supprimer le lien virtuel: il reste le fallback.
|
||||||
|
- Quantite `ppack`: somme de `lot.lot_qt` des physiques.
|
||||||
|
- Modes quantitatifs: quantites courantes converties des physiques.
|
||||||
|
- La meme selection s'applique au PnL fee.
|
||||||
|
- Points de synchronisation: creation fee, lien `fee.lots`, changement de
|
||||||
|
`quantity_theorical`, weighing, suppression de physique.
|
||||||
|
|
||||||
|
## BR-PT-FEE-003 - Fees `% rate` via delta de financement
|
||||||
|
|
||||||
|
Source: `BR-PT-016` historique et notes `2026-04-30`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Les frais financiers en pourcentage se calculent avec le delta de financement
|
||||||
|
de la ligne d'estimation `BL date`, pas avec la date du jour.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Formule: `amount = unit_price * quantity * (price / 100) * fin_int_delta / 360`.
|
||||||
|
- Source du delta: ligne `Estimated date` avec `trigger = bldate`.
|
||||||
|
- Si aucune ligne `bldate` n'existe, ne pas calculer de montant `% rate`.
|
||||||
|
|
||||||
22
modules/purchase_trade/docs_source/business/glossary.md
Normal file
22
modules/purchase_trade/docs_source/business/glossary.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Glossaire purchase_trade
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
- `Purchase Line`: ligne d'achat.
|
||||||
|
- `Sale Line`: ligne de vente.
|
||||||
|
- `quantity_theorical`: quantite contractuelle theorique d'une ligne.
|
||||||
|
- `Virtual Lot`: lot de type `virtual`, representant un reliquat ouvert.
|
||||||
|
- `Physical Lot`: lot de type `physic`, representant une quantite executee.
|
||||||
|
- `lot.qt`: ligne de quantite ouverte, matchee ou rattachee a un shipment.
|
||||||
|
- `lot.qt ouvert`: `lot.qt` libre, sans lot oppose et sans shipment.
|
||||||
|
- `Shipment In`: shipment entrant utilise aussi pour les flux dropship dans ce module.
|
||||||
|
- `Dropship`: flux fournisseur vers client, sans passage par stock interne.
|
||||||
|
- `Inbound`: flux entrant classique qui ne correspond pas au dropship.
|
||||||
|
- `Basis`: mode de prix construit a partir d'un prix de marche et d'un premium.
|
||||||
|
- `Premium`: prime ou discount commercial ajoute au prix economique.
|
||||||
|
- `Linked currency`: saisie d'un prix dans une devise/unite liee, par exemple `USC/LB`.
|
||||||
|
- `Valuation`: lignes de PnL generees pour prix, fees, derivatives et MTM.
|
||||||
|
- `MTM`: mark-to-market applique aux lignes valorisables au marche.
|
||||||
|
- `Fee`: frais commercial ou logistique rattache a une ligne, un lot ou un shipment.
|
||||||
|
- `Report property`: propriete Python exposee pour simplifier un template Relatorio.
|
||||||
|
|
||||||
75
modules/purchase_trade/docs_source/business/invariants.md
Normal file
75
modules/purchase_trade/docs_source/business/invariants.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# Invariants structurants
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
Ces invariants doivent etre relus avant de modifier des flux `purchase_trade`
|
||||||
|
touchant lots, quantites, fees, PnL, factures ou templates.
|
||||||
|
|
||||||
|
## INV-PT-001 - Le lot physique est le pont metier stable
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Quand une information doit relier achat, vente, shipment et facture, le chemin
|
||||||
|
fonctionnel de reference passe par le lot physique. Il porte le lien entre les
|
||||||
|
contrats et l'execution logistique.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Source historique: `BR-PT-002`.
|
||||||
|
- Voir aussi: [lots-and-quantities.md](lots-and-quantities.md),
|
||||||
|
[matching.md](matching.md), [reports-templates.md](reports-templates.md).
|
||||||
|
- Champs frequents: `lot.line`, `lot.sale_line`, `lot_shipment_in`,
|
||||||
|
`lot_shipment_internal`, `lot_shipment_out`.
|
||||||
|
|
||||||
|
## INV-PT-002 - Le reliquat ouvert ne doit pas doubler les lots physiques
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Une quantite deja executee physiquement ne doit pas rester disponible comme
|
||||||
|
quantite ouverte. Le reliquat ouvert represente seulement ce qui reste a
|
||||||
|
executer.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Source historique: `BR-PT-020`.
|
||||||
|
- Le calcul doit tenir compte de la quantite contractuelle, des lots physiques
|
||||||
|
existants et des `lot.qt` deja matches ou shippes.
|
||||||
|
- Regle de conservation:
|
||||||
|
`sum(lots physiques) + lot virtuel = quantity_theorical`.
|
||||||
|
- Regle du forecast ouvert:
|
||||||
|
`sum(lot.qt non zero) = max(lot virtuel, 0)`.
|
||||||
|
- Les lignes `lot.qt` a zero sont ignorees par les checks: elles peuvent servir
|
||||||
|
de memoire d'une prevision consommee.
|
||||||
|
- Le check applicatif est centralise dans
|
||||||
|
`lot.lot.assert_lines_quantity_consistency()`.
|
||||||
|
- Le diagnostic SQL correspondant est
|
||||||
|
[sql/quantity_consistency_checks.sql](sql/quantity_consistency_checks.sql).
|
||||||
|
|
||||||
|
## INV-PT-003 - Les fees utilisent leurs lots effectifs
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Un fee ouvert suit le lot virtuel tant qu'il n'y a pas de lot physique. Des
|
||||||
|
qu'un ou plusieurs lots physiques sont lies au fee, ils deviennent la base
|
||||||
|
effective de calcul.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Source historique: `BR-PT-021`.
|
||||||
|
- Ne pas supprimer le lien virtuel: il reste le fallback si les physiques sont
|
||||||
|
retires.
|
||||||
|
- Voir [fees.md](fees.md).
|
||||||
|
|
||||||
|
## INV-PT-004 - Les templates doivent rester simples
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Les documents doivent afficher des informations metier stables, meme si le
|
||||||
|
chemin technique pour les retrouver est complexe.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Preferer des proprietes Python `report_*` aux expressions Genshi complexes.
|
||||||
|
- Ne pas supposer qu'une variable locale comme `shipment` existe partout dans
|
||||||
|
un `.fodt`.
|
||||||
|
- Voir [reports-templates.md](reports-templates.md).
|
||||||
24
modules/purchase_trade/docs_source/business/invoicing.md
Normal file
24
modules/purchase_trade/docs_source/business/invoicing.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Facturation trade
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-INV-001 - Padding facture provisoire vente
|
||||||
|
|
||||||
|
Source: `BR-PT-019` et `../padding-invoice-accounting.md`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le padding d'une facture provisoire vente augmente la quantite facturee pour
|
||||||
|
constituer une provision, sans modifier la quantite physique du lot.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Le padding global du wizard `lot.invoice` est reparti entre les lots
|
||||||
|
selectionnes.
|
||||||
|
- La ligne facture expose `Inc. padding`.
|
||||||
|
- Le lot conserve sa part dans `sale_invoice_padding`.
|
||||||
|
- La facture finale retire le padding de la quantite provisoire avant de
|
||||||
|
calculer le delta.
|
||||||
|
- Les ecritures d'extourne doivent relire la provisoire depuis
|
||||||
|
`lot.sale_invoice_line_prov`.
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Lots Management
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-LOTMGT-001 - Separations matching, side et shipping status
|
||||||
|
|
||||||
|
Source: `BR-PT-023` et notes `2026-05-09`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le rapport Lots Management doit permettre de lire separement le matching
|
||||||
|
commercial, le sens achat/vente et l'avancement logistique.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Filtres: `Matching status`, `Side`, `Shipping status`, `Dimension`,
|
||||||
|
`Strategy`.
|
||||||
|
- Dates `As of` / `To`: `purchase.purchase_date` et `sale.sale_date`.
|
||||||
|
- `Unshipped`: aucun `shipment_in`.
|
||||||
|
- `Scheduled`: shipment `draft`.
|
||||||
|
- `Shipped`: shipment `started`.
|
||||||
|
- `Received`: shipment `received` ou `done`.
|
||||||
|
- `Shipment Type = Dropship` si `from_location.type = supplier` et
|
||||||
|
`to_location.type = customer`, sinon `Inbound`.
|
||||||
|
- `Mark as finished` masque seulement les reliquats ouverts / virtuels, pas
|
||||||
|
les lots physiques.
|
||||||
|
|
||||||
27
modules/purchase_trade/docs_source/business/matching.md
Normal file
27
modules/purchase_trade/docs_source/business/matching.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Matching achat / vente
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-MAT-001 - Create Contracts multi-lots conserve le matching source
|
||||||
|
|
||||||
|
Source: `BR-PT-012` et doublon historique `BR-PT-013`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le wizard `Create contracts` peut creer un seul contrat miroir depuis plusieurs
|
||||||
|
quantites ouvertes selectionnees. Chaque ligne creee doit rester reliee a son
|
||||||
|
lot source.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- La quantite du wizard doit correspondre a la somme des quantites ouvertes
|
||||||
|
selectionnees.
|
||||||
|
- Creer une ligne par `lot.qt` source.
|
||||||
|
- Conserver `created_by_code = True` pour eviter les creations automatiques
|
||||||
|
parasites lors des validations.
|
||||||
|
|
||||||
|
## Notes de migration
|
||||||
|
|
||||||
|
Les regles sur `Apply matching` presentes dans les notes de session du
|
||||||
|
`2026-05-09` doivent encore etre promues ici.
|
||||||
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Paiements et banques
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-PAY-001 - Distinguer banque tiers et banque compagnie
|
||||||
|
|
||||||
|
Source: `BR-PT-018`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Un contrat distingue le compte bancaire du client ou fournisseur du compte
|
||||||
|
bancaire utilise par la compagnie courante pour encaisser ou payer.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Contrats: `sale.sale`, `purchase.purchase`.
|
||||||
|
- `bank_account`: compte de la party du contrat.
|
||||||
|
- `our_bank_account`: compte de la compagnie courante, selectionnable parmi
|
||||||
|
les comptes disponibles.
|
||||||
|
- La devise du contrat est prioritaire pour proposer un compte par defaut.
|
||||||
|
|
||||||
53
modules/purchase_trade/docs_source/business/pricing.md
Normal file
53
modules/purchase_trade/docs_source/business/pricing.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# Pricing, basis, premium
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-PRI-001 - Le premium fait partie du prix economique
|
||||||
|
|
||||||
|
Source: `BR-PT-008`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le premium ou discount saisi sur une ligne fait partie du prix economique, que
|
||||||
|
la ligne soit en prix fixe ou en basis.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- `unit_price` reste le prix de base hors premium.
|
||||||
|
- Montant economique: `unit_price + premium converti si necessaire`.
|
||||||
|
- En basis, le premium s'applique aussi aux blocs valorises.
|
||||||
|
|
||||||
|
## BR-PT-PRI-002 - Linked currency
|
||||||
|
|
||||||
|
Source: `BR-PT-009` et `BR-PT-010`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Quand le prix est saisi dans une devise ou unite liee, le premium est exprime
|
||||||
|
dans ce meme repere puis converti pour les calculs internes.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Champs obligatoires si active: `linked_price`, `linked_currency`,
|
||||||
|
`linked_unit`.
|
||||||
|
- En `basis + linked currency`, `linked_price` represente le basis brut hors
|
||||||
|
premium.
|
||||||
|
- `amount` ajoute le premium converti.
|
||||||
|
|
||||||
|
## BR-PT-PRI-003 - Pricing manuel
|
||||||
|
|
||||||
|
Source: `BR-PT-016` et doublon historique `BR-PT-015`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
En pricing manuel, l'utilisateur saisit uniquement la quantite fixee du jour et
|
||||||
|
le prix de marche. Les cumuls et prix moyens sont calcules automatiquement.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Champs saisis: `quantity`, `settl_price`.
|
||||||
|
- Champs derives: `fixed_qt`, `fixed_qt_price`, `unfixed_qt`,
|
||||||
|
`unfixed_qt_price`, `eod_price`, `last`.
|
||||||
|
- Groupe metier: `line + component` ou `sale_line + component`.
|
||||||
|
- Le composant choisi doit appartenir a la ligne courante.
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Reports et templates
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
Voir aussi:
|
||||||
|
|
||||||
|
- `../template-rules.md`
|
||||||
|
- `../template-properties.md`
|
||||||
|
- `../../../../notes/template_business_rules.md`
|
||||||
|
|
||||||
|
## BR-PT-RPT-001 - Templates trade via proprietes Python
|
||||||
|
|
||||||
|
Source: `template-rules.md`, `template-properties.md`, notes AGENTS
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Un document trade doit afficher des informations metier fiables, sans dependre
|
||||||
|
d'expressions fragiles dans le fichier bureautique.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Preferer des proprietes Python simples, souvent prefixees `report_*`.
|
||||||
|
- Dans les placeholders XML, utiliser `"` et `'` plutot que des
|
||||||
|
antislashs.
|
||||||
|
- Pour les factures liees a vente/achat/shipment, privilegier le lot physique
|
||||||
|
comme pont.
|
||||||
|
- Verifier le cache `invoice_report_cache` avant de conclure qu'une action
|
||||||
|
report pointe vers le mauvais `.fodt`.
|
||||||
|
- Pour les templates shipment, preferer `records[0]...` ou des proprietes sur
|
||||||
|
`stock.shipment.in` plutot qu'une variable locale supposee.
|
||||||
|
|
||||||
|
## Decisions deja documentees a migrer ensuite
|
||||||
|
|
||||||
|
- `insurance.fodt`: compagnie courante, amount insured a 110%, surveyor.
|
||||||
|
- `packing_list.fodt`: date du jour, unites depuis `purchase.line`.
|
||||||
|
- `bill.fodt`: maturity date reelle et montant en lettres depuis le total.
|
||||||
|
- `invoice_ict.fodt` / `invoice_ict_final.fodt`: poids, shipments et lots.
|
||||||
|
- `sale_ict.fodt`: priorite lots et unite reelle.
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Risque, credit, forex
|
||||||
|
|
||||||
|
Statut: `placeholder`
|
||||||
|
|
||||||
|
Cette page est reservee aux regles business sur le risque, le credit et les
|
||||||
|
ecarts de change.
|
||||||
|
|
||||||
|
Aucune regle canonique `purchase_trade` n'a ete promue ici dans cette premiere
|
||||||
|
passe. Les notes comptables et forex existantes doivent etre relues avant toute
|
||||||
|
migration:
|
||||||
|
|
||||||
|
- `notes/accounting/README.md`
|
||||||
|
- `notes/accounting/business_rules.md`
|
||||||
|
- `notes/accounting/reporting.md`
|
||||||
|
|
||||||
31
modules/purchase_trade/docs_source/business/sessions.md
Normal file
31
modules/purchase_trade/docs_source/business/sessions.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Journal de migration et sessions
|
||||||
|
|
||||||
|
Statut: `non canonique`
|
||||||
|
|
||||||
|
Cette page sert de routeur vers les notes historiques. Une note devient
|
||||||
|
canonique seulement quand elle est reprise dans une page thematique.
|
||||||
|
|
||||||
|
## Sources historiques
|
||||||
|
|
||||||
|
- `modules/purchase_trade/docs/business-rules.md`
|
||||||
|
- `modules/purchase_trade/docs/business-rules-architecture-proposal.md`
|
||||||
|
- `notes/business_rules.md`
|
||||||
|
- `notes/template_business_rules.md`
|
||||||
|
|
||||||
|
## Notes deja partiellement promues
|
||||||
|
|
||||||
|
- Session `2026-04-30`: PnL fees ouverts et `% rate`, promue dans
|
||||||
|
[fees.md](fees.md) et [valuation-pnl-mtm.md](valuation-pnl-mtm.md).
|
||||||
|
- Session `2026-05-01`: solde ouvert apres lots physiques et lots effectifs
|
||||||
|
des fees, promue dans [lots-and-quantities.md](lots-and-quantities.md) et
|
||||||
|
[fees.md](fees.md).
|
||||||
|
- Session `2026-05-06`: Remove physical lot, promue dans
|
||||||
|
[lots-and-quantities.md](lots-and-quantities.md).
|
||||||
|
- Session `2026-05-09`: Lots Management, promue partiellement dans
|
||||||
|
[lots-management.md](lots-management.md).
|
||||||
|
- Session `2026-05-13`: cadrage `quantity_theorical` / `quantity`, amount de
|
||||||
|
ligne, Weight basis, invariants de quantite, checks Python bloquants et
|
||||||
|
diagnostic SQL. Promue dans
|
||||||
|
[lots-and-quantities.md](lots-and-quantities.md),
|
||||||
|
[lots-and-quantities.en.md](lots-and-quantities.en.md),
|
||||||
|
[invariants.md](invariants.md) et [sql/README.md](sql/README.md).
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Shipments et execution
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-SHP-001 - Affectation controller par ecart a l'objectif
|
||||||
|
|
||||||
|
Source: `BR-PT-014`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le controller propose automatiquement est celui dont la zone a le plus grand
|
||||||
|
retard par rapport a son objectif.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Configuration: onglet `Execution` de `party.party`.
|
||||||
|
- La zone du shipment vient de `shipment.to_location.country`.
|
||||||
|
- Une region parente couvre ses sous-regions.
|
||||||
|
- `% achieved` compte seulement les shipments deja affectes a un controller.
|
||||||
|
|
||||||
|
## BR-PT-SHP-002 - Couts SLA controller par pays et/ou lieu
|
||||||
|
|
||||||
|
Source: `BR-PT-014-bis`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Un cout controller peut etre defini pour un pays, un lieu, ou le couple pays +
|
||||||
|
lieu. Le couple est le cas le plus specifique.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Matching: `country + location`, puis `location`, puis `country`.
|
||||||
|
- Le pays vient de `shipment.to_location.country`.
|
||||||
|
|
||||||
|
## BR-PT-SHP-003 - Weight reports distants par lot
|
||||||
|
|
||||||
|
Source: `BR-PT-015`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
L'export distant par lot part du weight report global choisi par l'utilisateur
|
||||||
|
sur le shipment.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Exporter seulement les lots physiques des `incoming_moves`.
|
||||||
|
- Exiger au minimum `controller` et `returned_id` sur le shipment.
|
||||||
|
- Conserver les cles distantes et la date d'envoi sur le `weight.report`.
|
||||||
|
|
||||||
47
modules/purchase_trade/docs_source/business/sql/README.md
Normal file
47
modules/purchase_trade/docs_source/business/sql/README.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# SQL diagnostics for purchase_trade business rules
|
||||||
|
|
||||||
|
These scripts are read-only diagnostics for a PostgreSQL test database.
|
||||||
|
|
||||||
|
They exist to support the same business rules enforced by Python guards. The
|
||||||
|
expected workflow is:
|
||||||
|
|
||||||
|
1. write the consultant/developer rule in the thematic documentation;
|
||||||
|
2. enforce the invariant in the application code when feasible;
|
||||||
|
3. provide a read-only SQL diagnostic to audit existing data.
|
||||||
|
|
||||||
|
## quantity_consistency_checks.sql
|
||||||
|
|
||||||
|
Checks the two core lot quantity invariants documented in
|
||||||
|
`lots-and-quantities.md` and `lots-and-quantities.en.md`.
|
||||||
|
|
||||||
|
Zero `lot_qt` rows are ignored completely. They are treated as legitimate
|
||||||
|
memory of an open quantity consumed by a physical lot. This is required because
|
||||||
|
`lot_qt` represents usable open forecast and stops at zero, while the virtual
|
||||||
|
lot may become negative to compensate the difference between theoretical and
|
||||||
|
executed quantity. A non-zero `lot_qt` row without both `lot_p` and `lot_s` is
|
||||||
|
reported as anomalous.
|
||||||
|
|
||||||
|
Run it on a restored test database:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
\i modules/purchase_trade/docs/business/sql/quantity_consistency_checks.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
The script returns rows only when it finds a potential issue.
|
||||||
|
|
||||||
|
Main columns:
|
||||||
|
|
||||||
|
- `check_name`: invariant or diagnostic that failed.
|
||||||
|
- `contract_model`: `purchase.purchase` or `sale.sale`.
|
||||||
|
- `contract_id`: database id of the contract.
|
||||||
|
- `contract_number`: purchase or sale contract number.
|
||||||
|
- `line_id`: `purchase.line` or `sale.line` id depending on the check.
|
||||||
|
- `virtual_lot_id`: virtual lot involved in the inconsistency.
|
||||||
|
- `observed_value`: value found in the database.
|
||||||
|
- `expected_value`: value required by the business rule.
|
||||||
|
- `diff`: observed minus expected.
|
||||||
|
- `detail`: human-readable explanation.
|
||||||
|
|
||||||
|
Cross-category UoM rows are reported as manual-review diagnostics because the
|
||||||
|
Python code may pass explicit conversion factors that cannot be inferred safely
|
||||||
|
from SQL alone.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Valuation, PnL, MTM
|
||||||
|
|
||||||
|
Statut: `migration partielle`
|
||||||
|
|
||||||
|
## BR-PT-VAL-001 - La valuation couvre achat, vente et sale-first
|
||||||
|
|
||||||
|
Source: `BR-PT-004`, `BR-PT-006`, `BR-PT-011`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le PnL doit exister pour les achats et pour les ventes, meme quand une vente
|
||||||
|
n'est pas encore matchee a un achat.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- Une `sale.line` non matchee doit generer au minimum `sale priced`, `sale fee`
|
||||||
|
et `derivative` si applicable.
|
||||||
|
- Une sale basis sans detail de prix doit quand meme produire une ligne a zero
|
||||||
|
ou au prix economique fallback selon la regle applicable.
|
||||||
|
- Ne pas attacher arbitrairement une sale unique si plusieurs sales sont
|
||||||
|
matchees au meme ouvert.
|
||||||
|
|
||||||
|
## BR-PT-VAL-002 - References de valuation
|
||||||
|
|
||||||
|
Source: `BR-PT-005`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
La reference de PnL doit decrire la nature de la ligne valorisee: achat ou
|
||||||
|
vente, ouverte ou physique.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- References autorisees: `Purchase/Open`, `Purchase/Physic`, `Sale/Open`,
|
||||||
|
`Sale/Physic`.
|
||||||
|
- Un lot virtuel ne doit pas sortir avec une reference physique.
|
||||||
|
|
||||||
|
## BR-PT-VAL-003 - MTM hors fees
|
||||||
|
|
||||||
|
Source: `BR-PT-007`
|
||||||
|
|
||||||
|
### Regle consultant
|
||||||
|
|
||||||
|
Le mark-to-market s'applique aux prix et aux derives, pas aux frais.
|
||||||
|
|
||||||
|
### Notes developpeur
|
||||||
|
|
||||||
|
- MTM autorise pour `pur. priced`, `sale priced`, `derivative`.
|
||||||
|
- Fees hors MTM: `pur. fee`, `sale fee`, `shipment fee`, `line fee`.
|
||||||
|
- Pour les fees: `mtm_price`, `mtm`, `strategy` doivent rester vides.
|
||||||
|
|
||||||
Reference in New Issue
Block a user