padding acc
This commit is contained in:
@@ -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`
|
||||
|
||||
|
||||
294
modules/purchase_trade/docs/padding-invoice-accounting.md
Normal file
294
modules/purchase_trade/docs/padding-invoice-accounting.md
Normal 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
|
||||
Reference in New Issue
Block a user