12 KiB
12 KiB
AGENTS.md - Module purchase_trade
Ce guide complete le AGENTS.md racine.
Pour ce module, les regles locales ci-dessous priment.
1) Perimetre metier
Le module purchase_trade etend les flux achat/vente Tryton avec une logique
de negoce physique:
- contrats d'achat (
purchase.purchase,purchase.line) - contrats de vente (
sale.sale,sale.line) - lots physiques et virtuels
- matching achat/vente
- shipments et execution logistique
- frais (
fee.fee) - templates de documents metier et facture
2) Fichiers pivots
- Contrats achat:
modules/purchase_trade/purchase.py
- Contrats vente:
modules/purchase_trade/sale.py
- Lots / matching / invoicing:
modules/purchase_trade/lot.py
- Shipments / lien facture-lot:
modules/purchase_trade/stock.py
- Fees:
modules/purchase_trade/fee.py
- Bridge facture / templates:
modules/purchase_trade/invoice.py
- Vues:
modules/purchase_trade/view/*.xml
- Actions module:
modules/purchase_trade/*.xml
- Manifest:
modules/purchase_trade/tryton.cfg
3) Documentation locale a lire en priorite
- Regles metier:
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:
modules/purchase_trade/docs/template-rules.md
- Catalogue des proprietes templates:
modules/purchase_trade/docs/template-properties.md
- Padding facture provisoire vente / validation comptable:
modules/purchase_trade/docs/padding-invoice-accounting.md
4) Invariants metier a preserver
- Un lot
virtualest la reference d'ouverture de quantite pour unepurchase.line. - Une
sale.linedoit aussi avoir au minimum un lotvirtual; une valuation cote sale ne doit donc pas disparaitre juste parce que le lot estopen. - Le lot physique est le pont principal entre:
purchase.linesale.line- shipment
- facture
- Pour remonter d'une facture vers shipment / BL / controller / fret:
- privilegier le lot physique
- ne pas multiplier des chemins d'acces concurrents
- Pour les champs de colis (
NB BALES) dans les templates facture:- la source de verite est
line.lot.lot_qt - sur une facture, sommer les
lot_qtdes lignes de facture - tenir compte du signe de la ligne de facture pour les notes finales
- ne pas proratiser depuis le poids (
net/gross)
- la source de verite est
- Le
FREIGHT VALUEd'un template facture vient dufee.feedu shipment dont le produit estMaritime freight. - Pour
stock/insurance.fodt, leAmount insureddoit venir en priorite de110%du total desincoming_moves(fallback feeInsurancesi aucun montant incoming calculable). - Pour le surveyor du certificat d'assurance shipment, la priorite est:
shipment.surveyor->shipment.controller-> fournisseur du feeInsurance. - Pour
payment_order.fodt, utiliser des proprietesinvoice.report_payment_order_*plutot que des tokens legacy<...>. - Ajouter un champ de template dans
Document Templatesne rend pas le report visible dans la fiche: il faut aussi l'actionir.action.report+ir.action.keyword(form_print) coteaccount.invoice. - Le wizard
Create contractsen modematchedpeut maintenant partir de plusieurslot.qt, mais doit conserver un matching par lot source et laissercreated_by_code = Truesur les lignes creees pour ne pas declencher les creations automatiques de lots dans les validations. - En valuation / PnL:
- la valeur stockee dans
typeest la cle technique (pur. priced,sale priced,pur. fee, etc.), pas le label affiche dans l'UI - les references doivent rester coherentes avec le type de lot:
Purchase/Open,Purchase/Physic,Sale/Open,Sale/Physic - pour une sale matchee, les lignes de valuation purchase generees sur un lot
physique doivent aussi renseigner
saleetsale_lineafin de remonter dans l'onglet PnL de la sale - une sale non matchee doit etre valorisable "sale-first" et alimenter
valuation.valuation/valuation.valuation.line - si une
sale.linebasisn'a niprice_summarynilot_price_sale, creer quand meme une lignesale pricedavecprice = 0etamount = 0plutot que de ne rien generer - le MTM ne doit etre renseigne que pour
pur. priced,sale pricedetderivative; jamais pour les fees mtm_pricedoit afficher le prix brut de valorisation (sans ratio), alors quemtmreste le montant calcule selon la logique de strategie
- la valeur stockee dans
- En pricing:
- le
unit_pricedoit rester un prix de base, horspremium - le
premiumdoit impacter le prix total economique et donc leamount, aussi bien enpricedqu'enbasis - dans
pricing.pricingen saisie manuelle, l'utilisateur renseigne seulementquantityetsettl_price fixed_qt,fixed_qt_price,unfixed_qt,unfixed_qt_priceeteod_pricesont des valeurs derivees et ne doivent pas etre saisies a la main- en manuel,
fixed_qt= cumul desquantitydu groupe trie parpricing_date - en manuel,
fixed_qt_price= moyenne ponderee cumulee dessettl_price - en manuel,
unfixed_qt_price=settl_pricede la ligne - pour les documents commerciaux / facture, une ligne
basisaffiche lepremiumcomme prix visible, pas le prix economique total - si
linked currencyest active, lepremiumest saisi dans la devise / unite liee (ex:USC/LB) puis converti vers le repere de la ligne pour le calcul duamount - en
basis + linked currency, lelinked_pricedoit representer le prix basis brut (hors premium) dans la devise liee; leunit_pricereste ce prix brut converti, et lepremiumconverti est ajoute seulement dans l'amount - si
linked currencyest cochee,linked_price,linked_currencyetlinked_unitsont requis - dans les forms, presenter le bloc prix dans l'ordre:
price_type-> linked fields ->premium->unit_price->amount - en valuation
basis, le premium s'applique a chaque composant, pas uniquement a une ligne de resume - pour une ligne
basissansprice_summary, la valuation fallback doit utiliserunit_price + premium(et pasunit_priceseul) - a la validation d'une
sale.line, si un lot virtuel est cree et qu'aucun matching purchase n'existe, il faut lancergenerate_from_sale_line()pour alimenter le PnL sale-first
- le
- En padding de facture provisoire vente:
- le padding est saisi globalement dans
lot.invoice - il est uniquement applique aux factures provisoires cote vente
- il est reparti par lot et stocke dans
lot.sale_invoice_padding - la ligne facture affiche
Inc. paddingdepuis le lot - le padding augmente
account.invoice.line.quantity, donc le move principal de facture inclut deja le montant padding - les comptes de padding viennent de
account.configuration:Default Sale PaddingetDefault Accrual Padding - la section
Paddingdoit rester avant la sectionInvoicedansFinancial / Configuration - la provisoire cree un
additional_movedebitDefault Sale Padding/ creditDefault Accrual Padding - la finale cree l'inverse en reprenant le montant depuis
lot.sale_invoice_line_prov, donc avec le prix, la devise, la date et le taux de la provisoire - le wizard final doit calculer son delta depuis la quantite provisoire hors
padding:
sale_invoice_line_prov.quantity - sale_invoice_padding
- le padding est saisi globalement dans
- En modification de quantite contractuelle:
quantity_theoricalest la source contractuelle;quantitypeut refleter l'execute physique.- le
lot.qtlibre doit etre resynchronise sur le solde ouvert reel:quantity_theorical - lots physiques - lot.qt deja matches/shippes. - ne jamais ajuster le
lot.qtlibre uniquement par delta si des lots physiques existent deja. - les fees suivent les lots effectifs: physiques s'il en existe dans
fee.lots, sinon virtuel. - conserver le lien
fee.lotsvers le virtuel comme fallback; ne pas le supprimer lors de la creation d'un physique. - le PnL fee applique la meme regle: full open tant qu'il n'y a que le virtuel, puis uniquement les physiques.
- detail durable:
modules/purchase_trade/docs/business-rules.mdBR-PT-020 / BR-PT-021.
- En execution controller / SLA:
- les objectifs de repartition controller utilisent
party.execution.area(country.region). - les couts SLA utilisent
party.execution.placeet peuvent matcher parcountry, parlocation, ou par couplecountry + location. - la creation du fee controller depuis shipment part de
shipment.to_location; le pays de matching estshipment.to_location.country. - priorite cout SLA: couple pays+location, puis location seule, puis pays seul.
- les objectifs de repartition controller utilisent
5) Conventions de modification
Documentation business
- Ne pas modifier directement une page generee sous
modules/purchase_trade/docs/business/si elle contient le commentaireGenerated 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.
- Modifier la logique metier dans le fichier pivot le plus proche.
- Si un template
.fodtdevient complexe, deplacer la logique dans une propriete Pythonreport_*. - Pour une facture trade, preferer enrichir
modules/purchase_trade/invoice.pyplutot que surcharger lourdement le.fodt. - Si une regle metier durable change, mettre a jour
docs/business-rules.md. - Si une convention de template change, mettre a jour
docs/template-rules.md. - Pour les vues XML Tryton de ce module, utiliser
editable="1"sur les<tree>editables; ne pas utilisereditable="bottom". - Ne pas ajouter
keyword_open/open_keywordsur les vues<tree>: ces attributs ne sont pas supportes par Tryton. - Si une regle de texte par defaut durable est demandee sur achat/vente,
preferer un singleton de configuration expose dans un menu fonctionnel
existant plutot qu'un menu technique
purchase_trade.
6) Pieges connus
- Plusieurs actions de report
account.invoicepeuvent sembler rendre le meme document a cause du cacheinvoice_report_cache. - Les reports alternatifs (
Final Invoice,Prepayment, etc.) ne doivent pas reutiliser le cache du report standard sans verification. - Pour les donnees achat/vente partagees, ne pas supposer qu'une facture de
vente doit lire directement sur la
sale.line: souvent, la verite metier passe par le lot physique et/ou laaccount.invoice.line. - Les templates
invoice_ict*peuvent partager les memes proprietes Python; si une regle doit valoir pour provisional et final, la mettre dansmodules/purchase_trade/invoice.pyplutot que dupliquer dans les.fodt. - Dans les ecrans PnL, le label
Sale pricecorrespond au type stockesale priced; idem pourPur. price/pur. priced. - Une ligne
basissans resume de pricing peut sinon disparaitre de la valuation si aucun fallback explicite a0n'est prevu. - Le calcul du prix peut diverger entre
unit_price,linked_price,lot_priceet valuation si le premium n'est pas traite explicitement dans chaque maillon. - Sur
account.invoice, le workflowValidatedoit maintenant aligner fournisseur et client pour:- creation du
account.move - attribution du
number Postne doit pas reintroduire une difference de session/fresh login cote client
- creation du
- Pour le padding provisoire vente, ne pas changer la quantite physique du lot:
l'ecart doit rester porte par
lot.sale_invoice_paddinget visible sur la facture viaInc. padding.
7) Definition of done (module purchase_trade)
- Le flux achat/vente/lot cible reste coherent.
- Les impacts templates/facture ont ete verifies conceptuellement.
- Les docs locales ont ete mises a jour si une nouvelle regle durable a emerge.
- Le patch reste minimal et local au domaine demande.