# Business Rules - Purchase Trade

Statut: `draft`
Version: `v0.7`
Derniere mise a jour: `2026-04-26`
Owner metier: `a completer`
Owner technique: `a completer`

## 1) Scope

- Domaine: `purchase_trade`
- Hors scope:
- Modules impactes:
  - `purchase_trade`
  - `lot`

## 2) Glossaire

- `Purchase Line`: ligne d'achat.
- `quantity_theorical`: quantite theorique contractuelle de la ligne.
- `Virtual Lot`: lot unique de type `virtual` rattache a une `purchase.line`.
- `lot.qt`: table des quantites ouvertes, matchées ou shippées par lot.
- `lot.qt ouvert`: enregistrement `lot.qt` avec `lot_p = virtual lot`, `lot_s = None` et sans shipment.

## 3) Regles metier

### BR-PT-001 - Ajustement de la quantite theorique apres creation du contrat

- Intent: conserver la coherence entre la quantite theorique de la ligne d'achat, le lot virtuel associe et les quantites ouvertes stockees dans `lot.qt`.
- Description:
  - Quand `purchase.line.quantity_theorical` est modifiee apres creation du contrat, le systeme doit recalculer le delta entre l'ancienne et la nouvelle valeur.
  - La regle s'applique au lot unique de type `virtual` rattache a la `purchase.line`.
- Conditions d'entree:
  - Une `purchase.line` existe deja.
  - Son champ `quantity_theorical` est modifie via `write`.
  - Un lot `virtual` est rattache a la ligne.
- Resultat attendu:
  - Si `delta > 0`:
    - augmenter la quantite courante du lot `virtual` via `set_current_quantity` pour conserver l'historique `lot.qt.hist`
    - augmenter le `lot.qt` ouvert existant
    - si aucun `lot.qt` ouvert n'existe, en creer un nouveau avec le delta
  - Si `delta < 0`:
    - diminuer le `lot.qt` ouvert uniquement si la quantite ouverte disponible est suffisante
    - diminuer la quantite courante du lot `virtual` du meme delta
    - si aucun `lot.qt` ouvert n'existe ou si sa quantite est insuffisante, bloquer avec l'erreur `Please unlink or unmatch lot`
- Definition du `lot.qt` ouvert:
  - `lot_p = virtual lot`
  - `lot_s = None`
  - `lot_shipment_in = None`
  - `lot_shipment_internal = None`
  - `lot_shipment_out = None`
- Exceptions:
  - si aucun lot `virtual` n'est trouve sur la ligne, la regle ne fait rien
- Priorite:
  - `bloquante`
- Source:
  - `Decision metier documentee dans les commentaires de purchase_trade.purchase.Line.write`

### BR-PT-002 - Le lot physique est le pont metier entre purchase, sale et shipment

- Intent: disposer d'un chemin unique et stable pour retrouver les informations logistiques et de facturation reliees a un contrat d'achat ou de vente.
- Description:
  - Le lot physique (`lot_type = physic`) porte simultanement le lien vers:
    - la `purchase.line` via `lot.line`
    - la `sale.line` via `lot.sale_line`
    - le shipment via `lot.lot_shipment_in` / `lot.lot_shipment_internal` / `lot.lot_shipment_out`
  - Pour toute logique qui doit naviguer entre achat, vente, shipment et facture, il faut privilegier ce lot physique comme source de verite.
- Resultat attendu:
  - depuis une facture d'achat:
    - remonter a la `purchase.line`
    - puis au lot physique de la ligne
    - puis au shipment et aux donnees logistiques associees
  - depuis une facture de vente:
    - remonter a la `sale.line`
    - puis au lot physique matchant qui porte aussi la `purchase.line`
    - puis au shipment et aux donnees logistiques associees
- Cas d'usage typiques:
  - recuperer `bl_date`, `bl_number`, `controller`, `from_location`, `to_location`
  - retrouver une facture provisoire liee au lot
  - retrouver des fees rattaches au shipment
- Priorite:
  - `structurante`

### BR-PT-003 - Le freight amount des templates facture vient du fee de shipment

- Intent: afficher dans les documents facture la vraie valeur de fret maritime rattachee au shipment du lot physique.
- Description:
  - Le `FREIGHT VALUE` d'une facture ne doit pas etre pris sur la facture elle-meme.
  - Il doit etre calcule a partir du `fee.fee` rattache au shipment (`shipment_in`) du lot physique relie a la facture.
- Regle de navigation:
  - retrouver le lot physique pertinent depuis la facture
  - retrouver son shipment
  - chercher le `fee.fee` avec:
    - `shipment_in = shipment.id`
    - `product.name = 'Maritime freight'`
  - utiliser `fee.get_amount()` comme montant de fret
- Portee:
  - s'applique aussi bien aux factures d'achat qu'aux factures de vente
  - cote vente, la remontee doit passer par le lot physique qui fait le lien entre `purchase.line` et `sale.line`
- Priorite:
  - `importante`

### BR-PT-004 - La valuation doit couvrir les flux purchase et sale, y compris les sales non matchees

- Intent: obtenir un PnL coherent cote achat et cote vente, meme lorsqu'une
  sale n'est pas encore matchee a une purchase.
- Description:
  - Le flux historique de valuation part de `purchase.line` puis remonte vers
    les ventes via les lots/lots matchants.
  - Le systeme doit egalement savoir valoriser directement une `sale.line`
    non matchee ("sale-first").
  - Une sale non matchee doit creer des lignes dans
    `valuation.valuation` et `valuation.valuation.line` afin d'apparaitre dans
    l'onglet PnL de la sale.
- Resultat attendu:
  - pour une `sale.line` non matchee, generer au minimum les types:
    - `sale priced`
    - `sale fee`
    - `derivative` si la ligne porte des derives
  - si la sale est matchee via un lot physique, les lignes purchase portees par
    ce lot physique doivent aussi renseigner `sale` et `sale_line`
  - une sale matchee doit donc voir:
    - ses lignes `sale *`
    - les lignes purchase portees par le lot physique partage
- Priorite:
  - `structurante`

### BR-PT-005 - Les references de valuation doivent decrire la nature du lot de la ligne

- Intent: eviter les ambiguÃ¯tes dans les ecrans PnL entre lots `open` et lots
  `physic`.
- Description:
  - La reference affichee dans la valuation doit decrire la ligne elle-meme,
    pas son vis-a-vis.
  - Les references autorisees pour les lignes de prix sont:
    - `Purchase/Open`
    - `Purchase/Physic`
    - `Sale/Open`
    - `Sale/Physic`
- Resultat attendu:
  - un lot `virtual` cote purchase ne doit jamais sortir avec la reference
    `Purchase/Physic`
  - un lot `virtual` cote sale ne doit jamais sortir avec la reference
    `Sale/Physic`
  - un lot physique matche peut produire:
    - une ligne purchase en `Purchase/Physic`
    - une ligne sale en `Sale/Physic`
  - un open sale matche a un open purchase peut produire des quantites egales
    tout en gardant des references differentes (`Purchase/Open` vs `Sale/Open`)
- Priorite:
  - `importante`

### BR-PT-006 - Une sale basis sans prix detaille doit quand meme apparaitre en valuation

- Intent: ne pas perdre les lignes de PnL lorsque le detail de pricing n'est
  pas encore renseigne.
- Description:
  - Une `sale.line` de type `basis` peut exister avec un lot `virtual`, sans
    `price_summary` et sans `lot_price_sale`.
  - Dans ce cas, la valuation doit quand meme creer une ligne `sale priced`.
- Resultat attendu:
  - si `price_summary` est vide:
    - creer une ligne `sale priced`
    - avec `price = 0`
    - avec `amount = 0`
    - avec un `state` de type `unfixed`
  - si `lot_price_sale` est vide sur un lot sale, utiliser `sale_line.unit_price`
    comme fallback quand il existe
- Priorite:
  - `importante`

### BR-PT-007 - Le MTM de valuation ne s'applique pas aux fees

- Intent: distinguer les lignes de prix marquables au marche des lignes de
  frais qui ne doivent pas etre mark-to-market.
- Description:
  - Le systeme peut renseigner `mtm_price`, `mtm` et `strategy` uniquement pour:
    - `pur. priced`
    - `sale priced`
    - `derivative`
  - Les fees (`pur. fee`, `sale fee`, `shipment fee`, `line fee`) ne doivent
    jamais porter de valorisation MTM.
- Resultat attendu:
  - les lignes de fee doivent conserver:
    - `mtm_price = NULL`
    - `mtm = NULL`
    - `strategy = NULL`
  - `mtm_price` doit representer le prix brut de valorisation sans appliquer le
    ratio de composant
  - `mtm` reste le montant calcule selon la logique de strategie
- Priorite:
  - `structurante`

### BR-PT-008 - Le premium fait partie du prix contractuel en `priced` et en `basis`

- Intent: garantir que le montant total valorise et facture reflete toujours le
  premium/discount saisi sur la ligne.
- Description:
  - Le `premium` d'une `purchase.line` ou `sale.line` doit impacter le prix
    total quelle que soit la `price_type`.
  - Cette regle vaut pour:
    - les calculs de `amount`
    - la valuation / PnL
- Resultat attendu:
  - le `unit_price` reste le prix de base, hors premium
  - en `priced`, le montant economique = `unit_price + premium`
  - en `basis`, le premium s'ajoute aussi au prix total economique
  - en valuation `basis`, le premium s'applique a chaque composant valorise
    (ex: meme premium repete sur chaque bloc ICE)
- Exemple metier:
  - `8.30 USC/LB 500 TONS ON ICE MCH'26`
  - `8.30 USC/LB 500 TONS ON ICE MAY 26`
  - le premium `8.30 USC/LB` s'applique a chaque composant
- Priorite:
  - `structurante`

### BR-PT-009 - En linked currency, le premium est exprime dans la devise/unite liee

- Intent: respecter la facon dont les traders saisissent les prix sur certains
  produits (ex: coton en `USC/LB`).
- Description:
  - Quand `enable_linked_currency` est coche, le `premium` est saisi dans la
    devise / unite liee, pas dans la devise / unite native de la ligne.
  - Le systeme doit convertir ce premium vers le repere de la ligne pour les
    calculs internes de montant et de valuation.
- Resultat attendu:
  - `premium` est interprete dans le repere `linked_currency` / `linked_unit`
  - le `unit_price` ne doit pas absorber ce premium
  - les `amount` et valuations doivent refleter ce premium converti
  - si `linked currency` est cochee, `linked_price`, `linked_currency` et
    `linked_unit` sont obligatoires
- Priorite:
  - `structurante`

### BR-PT-010 - En `basis + linked currency`, le linked price suit le basis brut

- Intent: rendre lisible la decomposition entre prix basis de marche et premium.
- Description:
  - Quand une ligne est en `basis` et `linked currency`, le bloc
    `linked_price` doit etre recalcule automatiquement.
  - Ce `linked_price` doit representer le prix basis brut, hors premium.
  - Le `unit_price` de la ligne doit rester ce prix brut converti.
  - Le premium converti n'est ajoute qu'au niveau du `amount`.
- Resultat attendu:
  - modification du basis -> mise a jour automatique du `linked_price`
  - `linked_price` = base market / basis
  - `unit_price` = `linked_price` converti
  - `amount` = quantite * (`unit_price` + premium converti)
- Priorite:
  - `importante`

### BR-PT-011 - Une sale line non matchee avec lot virtuel doit generer une valuation sale-first des la validation

- Intent: ne pas attendre un matching purchase pour afficher le PnL d'une sale
  ouverte.
- Description:
  - Lors de la validation d'une `sale.line`, le systeme peut creer un lot
    `virtual`.
  - Si aucun `lot.qt` ne relie ce lot a une `purchase.line`, il faut tout de
    meme generer la valuation cote sale.

### BR-PT-012 - Le wizard Create contracts peut creer un seul achat matche a plusieurs open sales

- Intent: permettre la creation d'un contrat achat unique a partir de plusieurs
  `lot.qt` de vente selectionnes.
- Description:
  - En mode `matched`, le wizard `Create contracts` peut recevoir plusieurs
    `lot.qt` selectionnes.
  - Il doit creer un seul contrat, avec une ligne par lot source selectionne.
  - Chaque ligne doit conserver son lot d'origine pour le matching.
- Resultat attendu:
  - le wizard agrege les quantites de la selection
  - il refuse une quantite saisie differente du total selectionne
  - il conserve `created_by_code = True` sur les lignes creees pour ne pas
    declencher les creations automatiques parasites lors des validations
- Priorite:
  - `importante`

### BR-PT-013 - Le texte par defaut de pricing_rule est configure globalement

- Intent: centraliser un texte metier recurrent reutilise a la creation des
  lignes achat et vente.
- Description:
  - Le module expose un singleton `purchase_trade.configuration` avec un champ
    texte `pricing_rule`.
  - Toute nouvelle `purchase.line` et `sale.line` doit prendre ce texte comme
    valeur par defaut de `pricing_rule`.
- Resultat attendu:
  - la configuration est accessible depuis le menu `Prices`
  - la valeur sert de defaut a la creation des lignes
  - les lignes existantes ne sont pas modifiees retroactivement
- Priorite:
  - `importante`

### BR-PT-014 - L'affectation d'un controller doit suivre l'ecart a l'objectif regional

- Intent: repartir les controllers selon les cibles definies dans l'onglet
  `Execution` des `party.party`.
- Description:
  - chaque ligne `party.execution` fixe une cible `% targeted` pour un
    controller sur une `country.region`
  - le `% achieved` est calcule a partir des `stock.shipment.in` deja affectes
    a un controller dans cette zone
  - la zone d'un shipment est determinee par `shipment.to_location.country`
  - une region parente couvre aussi ses sous-regions
- Resultat attendu:
  - pour une ligne `party.execution`, `achieved_percent` =
    `shipments de la zone avec ce controller / shipments controles de la zone`
  - le denominateur ne compte que les `stock.shipment.in` qui ont deja un
    `controller`; les shipments encore non affectes ne biaisent donc pas la
    statistique affichee
  - lors d'un choix automatique de controller, la priorite va a la regle dont
    l'ecart `targeted - achieved` est le plus eleve
  - un controller a `80%` cible et `40%` reel doit donc passer avant un
    controller a `50%` cible et `45%` reel sur la meme zone
  - l'appartenance a la zone se lit depuis `shipment.to_location.country`, et
    une region parente couvre aussi ses sous-regions
- Priorite:
  - `importante`

### BR-PT-015 - Les weight reports distants par lot partent du weight report global attache au shipment

- Intent: separer la creation du `weight.report` global et l'export detaille
  par lot vers le systeme distant.
- Description:
  - l'automation cree le `weight.report` global et l'attache au
    `stock.shipment.in`
  - l'export FastAPI par lot ne part plus directement de l'automation
  - l'utilisateur ouvre le `weight.report` voulu depuis le shipment et lance
    l'action d'export depuis ce rapport
- Resultat attendu:
  - le rapport choisi sert de base unique pour calculer les payloads par lot
  - seuls les lots physiques des `incoming_moves` du shipment sont exportes
  - l'action exige au minimum un `controller` et un `returned_id` sur le
    shipment
- les cles renvoyees par le systeme distant et la date d'envoi sont
  conservees sur le `weight.report` local
- Priorite:
  - `importante`

### BR-PT-016 - En pricing manuel, seules la quantite fixee du jour et le prix de marche sont saisis

- Intent: simplifier la saisie utilisateur et garantir une coherence unique
  entre les colonnes de `pricing.pricing`.
- Description:
  - Pour une ligne de `pricing.pricing` en mode manuel, l'utilisateur ne doit
    saisir que:
    - `quantity`
    - `settl_price`
  - Les autres colonnes de suivi sont derivees automatiquement sur tout le
    groupe metier (`line + component` ou `sale_line + component`) trie par
    `pricing_date`.
- Resultat attendu:
  - `fixed_qt` = cumul des `quantity`
  - `fixed_qt_price` = moyenne ponderee cumulee des `settl_price`
  - `unfixed_qt` = quantite de base de la ligne - `fixed_qt`
  - `unfixed_qt_price` = `settl_price` de la ligne
  - `eod_price` = moyenne ponderee entre jambe fixee et non fixee
  - `last=True` reste unique par groupe et suit la plus grande `pricing_date`
- Hors scope:
  - la generation automatique des lignes quand `pricing.component.auto = True`
    ne doit pas changer de comportement
- Priorite:
  - `structurante`

### BR-PT-017 - Le workflow Validate des factures client doit aussi attribuer le numero

- Intent: aligner le comportement des factures client et fournisseur au moment
  de `Validate`.
- Description:
  - Lors du workflow `Validate` sur `account.invoice`, une facture client
    (`type = out`) doit maintenant:
    - creer son `account.move`
    - recevoir son `number`
  - La numerotation ne doit plus etre repoussee au `Post` cote client.
- Resultat attendu:
  - a l'issue de `Validate`, une facture fournisseur ou client possede deja:
    - son `account.move`
    - son `number`
  - `Post` conserve son role de posting comptable sans reintroduire de
    difference de session/fresh login cote client
- Priorite:
  - `importante`
- Resultat attendu:
  - apres creation du lot virtuel, si aucun matching purchase n'existe:
    - appeler `Valuation.generate_from_sale_line(line)`
    - creer au moins la ligne `sale priced` fallback si la ligne porte un prix
      economique via le premium
- Priorite:
  - `importante`

### BR-PT-018 - Les contrats distinguent le compte bancaire tiers du compte bancaire compagnie

- Intent: eviter de confondre le compte bancaire du client/fournisseur avec le
  compte bancaire de la compagnie courante utilise pour encaisser ou payer.
- Description:
  - Sur `sale.sale` et `purchase.purchase`, `bank_account` represente le compte
    bancaire propre a la `party` du contrat.
  - Sur `sale.sale` et `purchase.purchase`, `our_bank_account` represente le
    compte bancaire utilise par la compagnie courante pour encaisser ou payer.
  - `bank_account` est limite aux comptes bancaires de la party du contrat.
  - `our_bank_account` reste librement selectionnable parmi les comptes
    bancaires disponibles.
- Resultat attendu:
  - si plusieurs comptes existent, le compte dont la devise correspond a la
    devise du contrat est propose en priorite
  - si aucun compte ne matche la devise, le premier compte disponible est
    propose
  - le champ `Our Bank Account` est pre-rempli depuis les comptes de la
    compagnie quand possible, mais sa recherche n'est pas limitee a ces comptes
- Priorite:
  - `importante`

### BR-PT-019 - Le padding de facture provisoire vente augmente la quantite facturee sans modifier le lot physique

- Intent: permettre de constituer une provision sur une facture provisoire
  vente tout en gardant la trace de l'ecart avec la quantite reelle du lot.
- Description:
  - Le wizard `lot.invoice` expose un padding global uniquement pour les
    factures provisoires cote vente.
  - Ce padding global est reparti egalement entre les lots selectionnes.
  - La quantite de chaque ligne de facture provisoire vente est augmentee de la
    part de padding du lot.
  - Le padding ne modifie pas la quantite physique du lot.
- Resultat attendu:
  - 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 `Inc. padding`
  - le lot conserve sa part de padding dans `sale_invoice_padding`
- Validation comptable:
  - au `Validate`, le move principal de facture inclut deja le padding car il
    est integre a `account.invoice.line.quantity`
  - la provisoire cree un `additional_move` avec le couple de comptes configure
    `Default Sale Padding` / `Default Accrual Padding`
  - montant provisoire:
    `lot.sale_invoice_padding * account.invoice.line.unit_price`
  - la finale cree l'ecriture inverse pour exactement le montant padding
    comptabilise lors de la provisoire
  - le montant d'extourne finale doit etre relu depuis
    `lot.sale_invoice_line_prov`, afin de reprendre le prix, la devise, la date
    et le taux de la provisoire
  - le calcul de quantite finale doit retirer le padding de la quantite
    provisoire avant de calculer le delta
  - voir `modules/purchase_trade/docs/padding-invoice-accounting.md`
- Priorite:
  - `importante`

### BR-PT-012 - Fallback valuation basis sans summary: utiliser le prix economique de la ligne

- Intent: eviter qu'une valuation `basis` ouverte sorte a zero alors que la
  ligne a bien une valeur economique via le premium.
- Description:
  - Une ligne `basis` peut ne pas avoir encore de `price_summary`.
  - Dans ce cas, la valuation fallback ne doit pas prendre `unit_price` seul si
    celui-ci est brut et hors premium.
- Resultat attendu:
  - le fallback valuation `basis` doit utiliser:
    - `unit_price + premium converti`
  - cette regle vaut au minimum pour:
    - `sale.line` non matchee
    - `purchase.line` sans summary
- Priorite:
  - `importante`

### BR-PT-013 - Create Contracts multi-lots doit conserver un matching par lot source

- Intent: permettre la creation d'un seul contrat mirror a partir de plusieurs
  open quantities sans perdre le lien lot-a-lot.
- Description:
  - Le wizard `Create contracts` peut etre lance avec plusieurs `lot.qt`
    selectionnes.
  - En creation `matched`, le systeme doit creer un seul contrat avec une ligne
    par lot source selectionne, et chaque ligne doit etre matchee avec son lot
    d'origine.
- Resultat attendu:
  - la quantite totale du wizard = somme des open quantities selectionnees
  - le contrat cree porte plusieurs lignes si plusieurs lots source sont
    selectionnes
  - chaque ligne creee reutilise le `shipment_origin` et le lot source qui lui
    correspondent
  - `created_by_code` doit rester positionne sur les lignes creees par wizard
    pour eviter la recreation automatique de lots virtuels dans les `validate`
    de `purchase.line`, `sale.line` et `lot.lot`
- Priorite:
  - `importante`

### BR-PT-014 - Delivery period: From doit rester inferieur ou egal a To

- Intent: eviter les periodes de livraison incoherentes sur les lignes achat et
  vente.
- Description:
  - Les champs `from_del` et `to_del` sont presents sur `purchase.line` et
    `sale.line`.
  - Si les deux dates sont renseignees, `from_del` ne doit jamais etre
    posterieur a `to_del`.
- Resultat attendu:
  - la sauvegarde d'une `purchase.line` ou `sale.line` est bloquee si
    `from_del > to_del`
  - une date ouverte reste autorisee si seulement une des deux bornes est
    renseignee
- Priorite:
  - `importante`

### BR-PT-015 - Pricing manuel: composant limite a la ligne courante

- Intent: eviter qu'une ligne de pricing saisie manuellement utilise un
  composant rattache a une autre ligne de contrat.
- Description:
  - Dans l'onglet `Pricing dates` d'une `purchase.line`, le champ
    `pricing.pricing.price_component` doit proposer uniquement les composants
    dont `pricing.component.line` est la ligne achat courante.
  - Dans l'onglet `Pricing dates` d'une `sale.line`, il doit proposer
    uniquement les composants dont `pricing.component.sale_line` est la ligne
    vente courante.
  - Une ligne de pricing sans composant reste possible pour le mode manuel sans
    component.
- Resultat attendu:
  - le domaine UI filtre les composants sur la ligne courante
  - une validation serveur bloque aussi un composant appartenant a une autre
    ligne
- Priorite:
  - `importante`

## 4) Exemples concrets

### Exemple E1 - Augmentation simple

- Donnees:
  - `ancienne quantity_theorical = 100`
  - `nouvelle quantity_theorical = 120`
  - `lot.qt ouvert = 40`
- Attendu:
  - lot `virtual` augmente de `20`
  - `lot.qt ouvert` passe de `40` a `60`

### Exemple E2 - Augmentation sans lot.qt ouvert

- Donnees:
  - `ancienne quantity_theorical = 100`
  - `nouvelle quantity_theorical = 110`
  - aucun `lot.qt` ouvert
- Attendu:
  - lot `virtual` augmente de `10`
  - creation d'un `lot.qt` ouvert a `10`

### Exemple E3 - Diminution possible

- Donnees:
  - `ancienne quantity_theorical = 100`
  - `nouvelle quantity_theorical = 90`
  - `lot.qt ouvert = 25`
- Attendu:
  - lot `virtual` diminue de `10`
  - `lot.qt ouvert` passe de `25` a `15`

### Exemple E4 - Diminution impossible

- Donnees:
  - `ancienne quantity_theorical = 100`
  - `nouvelle quantity_theorical = 80`
  - `lot.qt ouvert = 5`
- Attendu:
  - blocage avec `Please unlink or unmatch lot`

## 5) Impact code attendu

- Fichiers Python concernes:
  - `modules/purchase_trade/purchase.py`
  - `modules/purchase_trade/lot.py`
  - `modules/purchase_trade/valuation.py`
  - `modules/purchase_trade/sale.py`

## 6) Strategie de tests

Pour cette regle, couvrir au minimum:

- augmentation avec `lot.qt` ouvert existant
- augmentation sans `lot.qt` ouvert
- diminution possible
- diminution impossible avec erreur
- valuation purchase/sale sur lot physique matche
- valuation sale-first sur sale non matchee avec lot virtual
- valuation sale `basis` sans `price_summary`
- absence de MTM sur les fees
- premium en `priced`
- premium en `basis`
- premium en `linked currency`
- synchro `basis` -> `linked_price` -> `unit_price`
