Bug accrual fee + invoice sale side
This commit is contained in:
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user