194 lines
6.2 KiB
Markdown
194 lines
6.2 KiB
Markdown
# Fees
|
|
|
|
Langue : `fr`
|
|
Page miroir : [fees.en.md](fees.en.md)
|
|
Statut : `migration partielle`
|
|
|
|
Voir aussi la page technique historique : `../fees.md`.
|
|
|
|
> **Résumé opérationnel**
|
|
> Un fee porte un montant, mais sa quantité doit rester alignée avec les lots
|
|
> qui le composent. Le mode `Per packing` est la seule exception : il suit une
|
|
> quantité de colisage, pas le poids du lot.
|
|
|
|
| Repère | Sujet | Règle courte |
|
|
| --- | --- | --- |
|
|
| Quantité | `fee.quantity` | Somme des lots liés dans `fee.lots`. |
|
|
| État | `fee.qt_state` vide | Utilise le `weight basis` du contrat. |
|
|
| État | `fee.qt_state` renseigné | Utilise cet état, plafonné au `weight basis`. |
|
|
| Fallback | état absent sur le lot | Prend l'état antérieur le plus proche par `sequence`. |
|
|
| Net / brut | `fee.weight_type` | `net` lit `quantity`, `brut` lit `gross_quantity`. |
|
|
| Packing | `ppack` | Quantité de packing, décorrélée du poids. |
|
|
| Contrôle | Python + SQL | Check applicatif et diagnostic SQL. |
|
|
|
|
## Règles consultant
|
|
|
|
### BR-PT-FEE-001 - Freight value depuis fee shipment
|
|
|
|
Source : `BR-PT-003`
|
|
|
|
#### Règle consultant
|
|
|
|
La valeur de fret affichée sur les documents facture vient du fee maritime du
|
|
shipment, pas d'un champ direct de la facture.
|
|
|
|
#### Notes développeur
|
|
|
|
- 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 - Lots effectifs des fees
|
|
|
|
Source : `BR-PT-021`
|
|
|
|
#### Règle consultant
|
|
|
|
Un fee suit le lot virtuel tant qu'aucun lot physique n'est lié. Dès qu'un lot
|
|
physique est lié, les lots physiques deviennent la base de calcul du fee.
|
|
|
|
#### Notes développeur
|
|
|
|
- Ne pas supprimer le lien virtuel : il reste le fallback.
|
|
- Les lots effectifs sont :
|
|
- les physiques si au moins un physique est lié ;
|
|
- sinon les virtuels.
|
|
- La même sélection s'applique au PnL fee.
|
|
- Points de synchronisation :
|
|
- création fee ;
|
|
- lien `fee.lots` ;
|
|
- changement de `quantity_theorical` ;
|
|
- weighing ;
|
|
- suppression de physique.
|
|
|
|
### BR-PT-FEE-003 - Quantité du fee
|
|
|
|
#### Règle consultant
|
|
|
|
La quantité d'un fee suit la vie de la quantité des lots qui lui sont liés. Elle
|
|
doit représenter la somme des quantités de ces lots dans l'état contractuel
|
|
autorisé.
|
|
|
|
#### Règle courte
|
|
|
|
```text
|
|
fee.quantity = somme(quantité applicable des lots effectifs fee.lots)
|
|
```
|
|
|
|
#### Sélection de l'état de quantité
|
|
|
|
| Cas | État cible |
|
|
| --- | --- |
|
|
| `fee.qt_state` vide | `weight basis` du contrat porteur du fee |
|
|
| `fee.qt_state` renseigné | `fee.qt_state`, sauf s'il est postérieur au `weight basis` |
|
|
| `fee.qt_state` postérieur au `weight basis` | `weight basis` |
|
|
| état cible absent du lot | état antérieur le plus proche par `lot.qt.type.sequence` |
|
|
| aucun état cible disponible | poids courant du lot, seulement si aucun `weight basis` ne s'applique |
|
|
|
|
#### Source du `weight basis`
|
|
|
|
| Fee | `weight basis` |
|
|
| --- | --- |
|
|
| Fee achat | `fee.line.purchase.wb.qt_type` |
|
|
| Fee vente | `fee.sale_line.sale.wb.qt_type` |
|
|
| Fee shipment | weight basis achat du lot si présent |
|
|
| Fee shipment sans achat | weight basis vente du lot si présent |
|
|
|
|
#### Net / brut
|
|
|
|
- Si `fee.weight_type = net` :
|
|
- lire `lot.qt.hist.quantity`.
|
|
- Si `fee.weight_type = brut` :
|
|
- lire `lot.qt.hist.gross_quantity`.
|
|
|
|
#### Per packing
|
|
|
|
- `mode = ppack` est exclu de la règle poids.
|
|
- `fee.quantity` représente une quantité de packing.
|
|
- Cette quantité peut être décorrélée du poids net ou brut.
|
|
|
|
#### Lump sum
|
|
|
|
- `mode = lumpsum` suit aussi la règle de quantité.
|
|
- Le montant reste forfaitaire.
|
|
- La quantité permet de calculer un prix par tonne plus précis.
|
|
|
|
### BR-PT-FEE-004 - Fees `% rate` via delta de financement
|
|
|
|
Source : `BR-PT-016` historique et notes `2026-04-30`
|
|
|
|
#### Règle 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 développeur
|
|
|
|
- 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`.
|
|
|
|
## Section développeur
|
|
|
|
### Champs clés
|
|
|
|
- Fee : `fee.fee`
|
|
- Lots du fee : `fee.lots`
|
|
- Quantité du fee : `fee.fee.quantity`
|
|
- Mode : `fee.fee.mode`
|
|
- État de quantité optionnel : `fee.fee.qt_state`
|
|
- Net / brut : `fee.fee.weight_type`
|
|
- État de quantité lot : `lot.qt.hist.quantity_type`
|
|
- Quantité nette : `lot.qt.hist.quantity`
|
|
- Quantité brute : `lot.qt.hist.gross_quantity`
|
|
- Ordre des états : `lot.qt.type.sequence`
|
|
- Weight basis achat / vente : `purchase.weight.basis.qt_type`
|
|
|
|
### Fonctions de calcul
|
|
|
|
- `Fee._get_effective_fee_lots()` :
|
|
- sélectionne physiques puis virtuels.
|
|
- `Fee._target_qt_type_for_lot()` :
|
|
- choisit `fee.qt_state` ou le `weight basis` ;
|
|
- plafonne l'état au `weight basis`.
|
|
- `Fee._select_lot_qt_type()` :
|
|
- prend l'état exact s'il existe ;
|
|
- sinon prend l'état antérieur le plus proche par `sequence`.
|
|
- `Fee._get_lot_fee_quantity()` :
|
|
- lit net ou brut selon `weight_type`.
|
|
- `Fee.sync_quantity_from_lots()` :
|
|
- resynchronise `fee.quantity`.
|
|
|
|
### Garde-fous Python
|
|
|
|
- Check central :
|
|
- `fee.fee.assert_quantity_consistency()`
|
|
- `fee.fee.assert_quantities_consistency()`
|
|
- Points de déclenchement :
|
|
- création de fee ;
|
|
- modification de fee ;
|
|
- création / modification / suppression de `fee.lots` ;
|
|
- weighing via resynchronisation des fees liés.
|
|
- Exception :
|
|
- `mode = ppack` n'est pas contrôlé comme un poids.
|
|
|
|
### Gap connu
|
|
|
|
- Split / merge de lots :
|
|
- le flux peut cloner ou créer des lots physiques ;
|
|
- le recâblage de `fee.lots` vers les nouveaux lots n'est pas encore garanti ;
|
|
- les fees concernés doivent donc être contrôlés par le diagnostic SQL après
|
|
utilisation de ce flux.
|
|
|
|
### Diagnostic SQL
|
|
|
|
- Script :
|
|
- [sql/fee_quantity_consistency_checks.sql](sql/fee_quantity_consistency_checks.sql)
|
|
- Usage :
|
|
- audit des bases de test ;
|
|
- audit des données historiques ;
|
|
- qualification avant correction.
|
|
- Le script remonte les fees non `ppack` dont `fee.quantity` ne correspond pas
|
|
à la somme des lots effectifs selon l'état de quantité applicable.
|