padding acc

This commit is contained in:
2026-04-26 14:35:07 +02:00
parent 9544418897
commit fbfa73110f
11 changed files with 590 additions and 14 deletions

View File

@@ -1,8 +1,8 @@
# Business Rules - Purchase Trade
Statut: `draft`
Version: `v0.6`
Derniere mise a jour: `2026-04-23`
Version: `v0.7`
Derniere mise a jour: `2026-04-26`
Owner metier: `a completer`
Owner technique: `a completer`
@@ -426,11 +426,16 @@ Owner technique: `a completer`
- deux lots factures ensemble avec un padding global de `1000` recoivent
chacun `500` de padding
- la ligne facture affiche la quantite augmentee
- la ligne facture expose `Included padding`
- la ligne facture expose `Inc. padding`
- le lot conserve sa part de padding dans `sale_invoice_padding`
- Hors scope:
- les ecritures comptables specifiques au padding seront traitees dans un
second temps
- Validation comptable:
- au `Validate`, le move principal de facture inclut deja le padding car il
est integre a `account.invoice.line.quantity`
- la provisoire doit utiliser le couple de comptes configure
`Default Sale Padding` / `Default Accrual Padding`
- la finale doit passer l'ecriture inverse pour exactement le montant padding
comptabilise lors de la provisoire
- voir `modules/purchase_trade/docs/padding-invoice-accounting.md`
- Priorite:
- `importante`

View File

@@ -0,0 +1,294 @@
# Padding facture provisoire vente - notes comptables
Statut: `draft`
Derniere mise a jour: `2026-04-26`
Scope: `lot.invoice` -> `account.invoice` -> validation comptable.
## 1) Objectif metier
Le padding sert a augmenter temporairement la quantite facturee sur une facture
provisoire cote vente, afin de constituer une provision avant la facture finale.
Exemple:
- 2 lots factures ensemble
- padding global saisi dans le wizard: `1000`
- repartition actuelle: `500` par lot
- chaque ligne facture affiche:
- `quantity = quantite reelle du lot + padding du lot`
- `Inc. padding = padding du lot`
Le padding ne modifie pas la quantite physique du lot. Il doit rester visible et
traçable comme ecart entre la facture provisoire et le lot.
## 2) Donnees creees ou utilisees
### `lot.lot`
- Champ: `sale_invoice_padding`
- Role: memoire de la part de padding appliquee au lot pour la facture
provisoire vente.
- UI: readonly sur le lot.
### `account.invoice.line`
- Champ fonctionnel: `included_padding`
- Label UI: `Inc. padding`
- Role: affichage de `line.lot.sale_invoice_padding` sur la ligne facture.
- La valeur n'est pas stockee sur la ligne; elle lit le padding du lot.
### Wizard `lot.invoice`
- Champ: `sale_padding` (`Global padding`)
- Visible seulement pour:
- `type = sale`
- `action = prov`
- Repartition actuelle:
- padding global / nombre de lots selectionnes
## 3) Flux de creation de facture avec padding
1. L'utilisateur ouvre le wizard `lot.invoice` depuis les lots physiques.
2. Le wizard prepare deux listes:
- `lot_p` pour achat
- `lot_s` pour vente
3. En mode vente provisoire, l'utilisateur saisit `Global padding`.
4. Au clic `Invoice`, le wizard:
- calcule la part de padding par lot
- ecrit cette part dans `lot.sale_invoice_padding`
- appelle `sale.sale._process_invoice(..., action='prov')`
5. `sale.line.get_invoice_line(lots, action)` cree une ligne facture par lot
physique.
6. Pour chaque ligne positive `out` / `Pro forma`, le module ajoute le padding
du lot a `invoice_line.quantity`.
7. L'amount de la ligne augmente naturellement via:
- `quantity * unit_price`
## 4) Ce qui se passe actuellement lors de `Validate` d'une facture
Bouton UI: `Validate` sur `account.invoice`.
Code principal:
- `modules/account_invoice/invoice.py`
- `Invoice.validate_invoice`
- `Invoice.get_move`
- `InvoiceLine.get_move_lines`
- `Invoice.do_lot_invoicing`
- `Invoice.cleanMoves`
### Etapes de `validate_invoice`
1. Verifie les taxes avec `_check_taxes`.
2. Attribue le numero via `set_number`.
3. Stocke les caches de montants via `_store_cache`.
4. Pour chaque facture:
- appelle `invoice.get_move()`
- affecte le move a `invoice.move` s'il est nouveau
- appelle `invoice.do_lot_invoicing()`
5. Sauvegarde les moves crees.
6. Nettoie certaines lignes de move via `cleanMoves`.
7. Sauvegarde les factures.
Note importante deja actee dans le projet:
- `Validate` cree deja le `account.move` et attribue le `number` aussi pour les
factures client (`type = out`).
- `Post` ne doit plus etre le premier moment ou ces donnees apparaissent cote
client.
### `get_move()`
`get_move()` construit le move comptable principal de la facture:
- appelle `update_taxes(exception=True)`
- parcourt `invoice.lines`
- pour chaque ligne, appelle `line.get_move_lines()`
- ajoute les lignes de taxes via `tax.get_move_lines()`
- ajoute la ligne tiers / receivable-payable via `_get_move_line`
- ajoute eventuellement une ligne de change via `_get_exchange_move_line`
- cree un `account.move` avec:
- `journal = invoice.journal`
- `period` trouve depuis la date comptable
- `origin = invoice`
- `lines = move_lines`
### `account.invoice.line.get_move_lines()`
Pour une ligne facture `type = line`:
- cree une ligne `account.move.line`
- rattache `line.lot = self.invoice.lines[0].lot`
- attention: comportement existant, pas forcement la ligne courante
- convertit le montant si devise differente
- pour une facture client (`type = out`):
- montant positif => credit du compte de revenu de la ligne
- montant negatif => debit
- met `line.account = self.account`
- met `line.origin = self`
- calcule les lignes de taxe
Pour le padding actuel, comme il augmente `invoice_line.quantity`, il est deja
inclus dans le montant de revenu du move principal.
### `do_lot_invoicing()`
`do_lot_invoicing()` traite des ajustements lies aux lots:
- groupe les lignes facture par `i.lot`
- calcule:
- `var_price`
- `var_qt`
- retrouve le mouvement stock:
- fournisseur pour `type = in`
- client pour `type = out`
- declenche des actions stock / shipment si necessaire
- calcule le COG du lot
- prepare des lignes d'ajustement via `_get_move_lines`
- actuellement, le move d'ajustement n'est cree/poste que si:
- `adjust_move_lines` existe
- `self.type == 'in'`
Consequence importante pour le padding:
- les ajustements de quantite/prix existants sont principalement effectifs cote
achat (`type = in`)
- une facture client provisoire avec padding augmente deja le move principal de
vente, mais ne genere pas encore d'ecritures specifiques padding separees
### `_get_move_lines(gl, amount, drop, IsUsd=False, stock_move=None)`
Helper existant pour creer des paires de lignes de move liees au stock/COG:
- rattache `lot`, `fee`, `origin`
- gere la conversion devise / second currency
- choisit les comptes stock / stock out / stock in / COG selon le signe, fee et
contexte
- peut creer une variante `drop`
Ce helper est un candidat possible pour reutilisation partielle, mais il est
aujourd'hui pense pour des ajustements stock/COG, pas pour isoler un padding de
facture provisoire vente.
## 5) Question comptable a trancher pour le padding
Le besoin restant est: au `Validate` d'une facture provisoire vente avec padding,
generer des ecritures propres a ce padding.
Points a definir avant implementation:
- Le move padding doit-il etre:
- integre dans le move principal de facture ?
- cree comme `additional_move` ?
- cree comme move separe avec `origin = invoice` ?
- Quels comptes utiliser ?
- compte de revenu temporaire / provision ?
- compte de contrepartie padding ?
- compte lie au produit ?
- compte de configuration dedie ?
- Faut-il neutraliser une partie du revenu principal deja augmente par la
quantity, ou seulement ajouter une ecriture analytique/stock parallele ?
- Le padding doit-il impacter:
- revenu client ?
- stock out ?
- COG ?
- PnL / valuation ?
- Que doit faire la facture finale ?
- reprendre le padding provisoire ?
- le contrepasser ?
- ne rien faire si la finale facture la vraie quantite ?
- Le montant padding a utiliser est:
- `lot.sale_invoice_padding * invoice_line.unit_price`
- dans la devise de facture
- a convertir si devise societe differente selon la logique standard
## 5.1) Decision comptable cible
Comptes de configuration ajoutes sur `account.configuration`:
- `default_sale_padding_account`
- label UI: `Default Sale Padding`
- compte attendu metier: `80021`
- nature: revenu
- `default_accrual_padding_account`
- label UI: `Default Accrual Padding`
- compte attendu metier: `42021`
- nature: bilan / accrual
Facture provisoire vente:
- condition:
- `invoice.type = out`
- `invoice.reference = Provisional`
- `invoice_line.description = Pro forma`
- `invoice_line.lot.sale_invoice_padding > 0`
- montant:
- `padding_amount = lot.sale_invoice_padding * invoice_line.unit_price`
- le prix est celui de la facture provisoire, pas un prix recalcule plus tard
- ecriture attendue:
- couple `80021 / 42021`
- rattachement au lot obligatoire sur les lignes si possible
Facture finale vente:
- condition:
- lot deja facture en provisoire avec padding
- la finale doit inverser le padding deja provisionne
- montant:
- exactement le montant comptabilise lors de la provisoire
- ne pas recalculer avec le prix de la finale
- ecriture attendue:
- couple inverse `42021 / 80021`
Decision technique retenue:
- ne pas ajouter de nouveau champ montant pour l'instant
- utiliser le lien deja ecrit sur le lot:
- `lot.sale_invoice_line_prov`
- au moment de la finale, retrouver la ligne provisoire via ce champ
- calculer le montant a extourner avec:
- `lot.sale_invoice_padding * lot.sale_invoice_line_prov.unit_price`
- utiliser la devise, le taux et la date de la facture provisoire pour obtenir
le meme montant societe que l'ecriture initiale
- garder le rattachement comptable par `account.move.line.lot`
Raison:
- evite les ecarts si le prix final change
- reutilise le lien direct deja maintenu entre le lot et la ligne provisoire
- rend la reprise finale audit-friendly
- garde le pivot comptable lot coherent
## 6) Invariants a preserver
- Le padding ne change pas la quantite physique du lot.
- Le padding est uniquement pour facture provisoire vente:
- `invoice.type = out`
- `invoice.reference = Provisional`
- lignes `description = Pro forma`
- L'utilisateur doit voir clairement l'ecart:
- `Quantity`
- `Inc. padding`
- Le lien principal reste:
- `account.invoice.line.lot`
- `lot.sale_invoice_padding`
- Les futures ecritures doivent etre rattachees au lot autant que possible pour
rester visibles dans le pivot comptable du lot.
## 7) Tests a prevoir pour la suite
- Validation d'une facture provisoire vente avec padding:
- move principal existe
- montant facture inclut le padding
- ecritures specifiques padding creees selon la regle retenue
- lignes rattachees au bon lot
- Facture provisoire vente sans padding:
- aucun move padding specifique
- Facture finale vente:
- aucun nouveau padding applique automatiquement
- comportement de reprise/contrepassation selon decision metier
- Facture achat:
- aucun impact padding vente
- Multi-lots:
- padding reparti correctement
- ecritures detaillees par lot si la regle comptable l'exige