Bug accrual fee + invoice sale side

This commit is contained in:
2026-05-11 20:19:44 +02:00
parent 4ae64269f4
commit 09c78395f1
3 changed files with 200 additions and 17 deletions

View File

@@ -0,0 +1,163 @@
# Proposition d'architecture des regles business CTRM
Statut: `proposal`
Date: `2026-05-11`
Scope: documentation metier `purchase_trade` / CTRM
## Objectif
Cette note garde la proposition de structure documentaire pour les regles
business trading. L'objectif est de pouvoir s'appuyer sur une source de verite
exhaustive sans charger trop de contexte quand une demande concerne seulement
un theme precis.
## Etat des lieux
- `modules/AGENTS.md` porte les regles courtes communes aux modules.
- `modules/purchase_trade/AGENTS.md` porte les invariants critiques du module
trading et les fichiers pivots.
- `modules/purchase_trade/docs/business-rules.md` est la base metier la plus
riche, mais elle melange regles canoniques, notes de session et quelques
doublons de numerotation.
- `notes/business_rules.md` sert de journal transverse de sessions.
- `notes/accounting/` documente plutot le standard comptable Tryton, les gaps
de reporting et les extensions comptables `purchase_trade`.
- Les fichiers specialises comme `fees.md`,
`padding-invoice-accounting.md`, `template-rules.md` et
`template-properties.md` sont de bons exemples de documentation ciblee.
## Principe recommande
Garder `purchase_trade` comme source de verite canonique pour le metier CTRM,
mais decouper les regles par theme.
`AGENTS.md` doit rester court et servir de routeur:
- charger seulement les invariants toujours utiles;
- indiquer quel fichier thematique lire selon la demande;
- eviter d'embarquer toute la documentation business a chaque intervention.
Les notes de session doivent rester historiques. Une decision devient
canonique seulement quand elle est promue dans un fichier thematique.
## Structure cible proposee
```text
modules/purchase_trade/docs/business/
README.md
INDEX.md
glossary.md
invariants.md
sessions.md
contracts.md
lots-and-quantities.md
matching.md
shipments-execution.md
pricing.md
fees.md
valuation-pnl-mtm.md
invoicing.md
accounting-bridge.md
payments-banking.md
reports-templates.md
risk-credit-forex.md
lots-management.md
```
## Role des fichiers
- `README.md`: explique la convention documentaire et le statut des fichiers.
- `INDEX.md`: routeur par theme, avec les fichiers a lire selon le sujet.
- `glossary.md`: vocabulaire stable du CTRM Tradon.
- `invariants.md`: principes structurants toujours vrais.
- `sessions.md`: journal historique non canonique.
- fichiers thematiques: source canonique exhaustive pour chaque domaine.
## Grands themes metier
- `contracts.md`: achats, ventes, lignes, dates, lieux, banques,
counterparties, quantite contractuelle, statut finished.
- `lots-and-quantities.md`: lots virtuels/physiques, `lot.qt`, historique,
weighing, split/merge, suppression de lot physique, solde ouvert.
- `matching.md`: matching purchase/sale, open matching via `lot.qt`, wizard
`Create contracts`, back-to-back, multi-lots.
- `shipments-execution.md`: shipments, dropship/inbound, controller, SLA,
locations, surveyor, weight reports, BL.
- `pricing.md`: `priced`, `basis`, components, manual pricing, summary,
linked currency, premium, settlement price.
- `fees.md`: fees ligne/shipment, lots effectifs, `% rate`, `ppack`,
maritime freight, insurance, declencheurs PnL.
- `valuation-pnl-mtm.md`: valuation achat/vente, sale-first, references,
MTM strategies, derivatives, exclusions fees.
- `invoicing.md`: provisional/final, facture achat/vente, padding, quantites
facturees, liens lot/facture, templates invoice.
- `accounting-bridge.md`: effets sur `account_invoice`, `account.move`,
taxes, devises, additional moves, validate/post.
- `payments-banking.md`: payment terms, echeances, comptes bancaires
party/company, payment order.
- `reports-templates.md`: Relatorio, proprietes `report_*`, documents trade,
regles XML, cache report.
- `risk-credit-forex.md`: credit risk, forex, FX revaluation, exposition.
- `lots-management.md`: rapports operationnels, filtres matching/side/shipping,
dimension, strategy.
## Format conseille pour une regle
```md
### BR-PT-VAL-007 - Le MTM ne s'applique pas aux fees
Theme: valuation-pnl-mtm
Status: active
Scope: purchase_trade
Code: valuation.py, fee.py
Depends on: BR-PT-FEE-002
Summary: Les lignes de fee ne portent jamais mtm, mtm_price ou strategy.
Rule:
- MTM autorise seulement pour `pur. priced`, `sale priced`, `derivative`.
- Fees: `pur. fee`, `sale fee`, `shipment fee`, `line fee` restent hors MTM.
Tests:
- valuation fee sans mtm
- valuation priced avec mtm
```
Les identifiants devraient encoder le theme (`LOT`, `MAT`, `PRI`, `FEE`,
`VAL`, `INV`, `ACC`, etc.) plutot qu'une numerotation globale unique. Cela
evite les collisions quand les regles sont ajoutees au fil des sessions.
## Routeur de contexte a ajouter plus tard dans `AGENTS.md`
```md
Si la demande concerne:
- lots, quantites, matching: lire `docs/business/lots-and-quantities.md` et
`docs/business/matching.md`
- pricing, premium, basis: lire `docs/business/pricing.md`
- fees, freight, insurance: lire `docs/business/fees.md`
- valuation, PnL, MTM: lire `docs/business/valuation-pnl-mtm.md`
- facture, padding, payment order: lire `docs/business/invoicing.md` et
`docs/business/accounting-bridge.md`
- templates `.fodt`: lire `docs/business/reports-templates.md` et
`docs/template-rules.md`
```
## Migration proposee
1. Creer `docs/business/INDEX.md`, `invariants.md` et `glossary.md`.
2. Decouper `docs/business-rules.md` par theme, sans changer le fond.
3. Deplacer les notes de session dans `sessions.md`.
4. Promouvoir uniquement les decisions durables dans les fichiers thematiques.
5. Reduire `modules/purchase_trade/AGENTS.md` a un memo court + routeur.
6. Garder `notes/accounting/` comme documentation comptable Tryton et comme
vue specialisee des extensions comptables `purchase_trade`.
## Risque actuel a traiter lors de la migration
Le risque principal n'est pas le manque de regles, mais leur dilution entre
plusieurs fichiers. Certaines decisions existent a la fois dans `AGENTS.md`,
`notes/business_rules.md`, `business-rules.md`, `fees.md` et les notes
accounting. La migration devra designer une source canonique par theme et
laisser les autres fichiers jouer leur role d'index, de journal ou de vue
specialisee.

View File

@@ -569,10 +569,28 @@ class Fee(ModelSQL,ModelView):
# def validate(cls, fees):
# super(Fee, cls).validate(fees)
@classmethod
def create(cls, vlist):
vlist = [x.copy() for x in vlist]
fees = super(Fee, cls).create(vlist)
@classmethod
def _save_fee_accrual_or_warn(cls, account_move, fee, lot):
AccountMove = Pool().get('account.move')
if account_move:
AccountMove.save([account_move])
return
Warning = Pool().get('res.user.warning')
warning_name = Warning.format(
"Fee accrual not generated", [fee.product, lot])
if Warning.check(warning_name):
raise UserWarning(
warning_name,
"The fee can be saved, but the accrual entry could not be "
"generated because the stock accounting configuration or "
"accounting period is missing or incomplete. Do you want to "
"continue without creating the accrual entry?")
@classmethod
def create(cls, vlist):
vlist = [x.copy() for x in vlist]
fees = super(Fee, cls).create(vlist)
qt_sh = Decimal(0)
qt_line = Decimal(0)
unit = None
@@ -677,16 +695,16 @@ class Fee(ModelSQL,ModelView):
if move:
Warning = Pool().get('res.user.warning')
warning_name = Warning.format("Lot ever received", [])
if Warning.check(warning_name):
raise UserWarning(warning_name,
"By clicking yes, an accrual for this fee will be created")
AccountMove = Pool().get('account.move')
account_move = move._get_account_stock_move_fee(fee)
AccountMove.save([account_move])
else:
AccountMove = Pool().get('account.move')
if Warning.check(warning_name):
raise UserWarning(warning_name,
"By clicking yes, an accrual for this fee will be created")
account_move = move._get_account_stock_move_fee(fee)
cls._save_fee_accrual_or_warn(
account_move, fee, fl.lot)
else:
account_move = fee._get_account_move_fee(fl.lot)
AccountMove.save([account_move])
cls._save_fee_accrual_or_warn(
account_move, fee, fl.lot)
cls._regenerate_fee_pnl(fees=fees)
return fees

View File

@@ -3057,10 +3057,12 @@ class LotInvoice(Wizard):
# Warning = Pool().get('res.user.warning')
# warning_name = Warning.format("Lot not confirmed", [])
# if Warning.check(warning_name):
# raise QtWarning(warning_name,
# "Lot not confirmed, click yes to confirm and invoice")
# continue
if lot.invoice_line:
# raise QtWarning(warning_name,
# "Lot not confirmed, click yes to confirm and invoice")
# continue
if self.inv.type == 'purchase' and lot.invoice_line:
continue
if self.inv.type == 'sale' and lot.sale_invoice_line:
continue
lots.append(lot)