02.04.26
This commit is contained in:
@@ -79,15 +79,27 @@ de negoce physique:
|
|||||||
- `mtm_price` doit afficher le prix brut de valorisation (sans ratio), alors
|
- `mtm_price` doit afficher le prix brut de valorisation (sans ratio), alors
|
||||||
que `mtm` reste le montant calcule selon la logique de strategie
|
que `mtm` reste le montant calcule selon la logique de strategie
|
||||||
- En pricing:
|
- En pricing:
|
||||||
- le `premium` doit impacter le prix total et donc le `amount`, aussi bien
|
- le `unit_price` doit rester un prix de base, hors `premium`
|
||||||
en `priced` qu'en `basis`
|
- le `premium` doit impacter le prix total economique et donc le `amount`,
|
||||||
|
aussi bien en `priced` qu'en `basis`
|
||||||
- si `linked currency` est active, le `premium` est saisi dans la devise /
|
- si `linked currency` est active, le `premium` est saisi dans la devise /
|
||||||
unite liee (ex: `USC/LB`) puis converti vers le `unit_price` de la ligne
|
unite liee (ex: `USC/LB`) puis converti vers le repere de la ligne pour le
|
||||||
|
calcul du `amount`
|
||||||
- en `basis + linked currency`, le `linked_price` doit representer le prix
|
- en `basis + linked currency`, le `linked_price` doit representer le prix
|
||||||
basis brut (hors premium) dans la devise liee; le `unit_price` final
|
basis brut (hors premium) dans la devise liee; le `unit_price` reste ce
|
||||||
ajoute ensuite le premium converti
|
prix brut converti, et le `premium` converti est ajoute seulement dans
|
||||||
|
l'`amount`
|
||||||
|
- si `linked currency` est cochee, `linked_price`, `linked_currency` et
|
||||||
|
`linked_unit` sont 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
|
- en valuation `basis`, le premium s'applique a chaque composant, pas
|
||||||
uniquement a une ligne de resume
|
uniquement a une ligne de resume
|
||||||
|
- pour une ligne `basis` sans `price_summary`, la valuation fallback doit
|
||||||
|
utiliser `unit_price + premium` (et pas `unit_price` seul)
|
||||||
|
- a la validation d'une `sale.line`, si un lot virtuel est cree et qu'aucun
|
||||||
|
matching purchase n'existe, il faut lancer `generate_from_sale_line()` pour
|
||||||
|
alimenter le PnL sale-first
|
||||||
|
|
||||||
## 5) Conventions de modification
|
## 5) Conventions de modification
|
||||||
|
|
||||||
|
|||||||
@@ -199,12 +199,12 @@ Owner technique: `a completer`
|
|||||||
- Le `premium` d'une `purchase.line` ou `sale.line` doit impacter le prix
|
- Le `premium` d'une `purchase.line` ou `sale.line` doit impacter le prix
|
||||||
total quelle que soit la `price_type`.
|
total quelle que soit la `price_type`.
|
||||||
- Cette regle vaut pour:
|
- Cette regle vaut pour:
|
||||||
- le `unit_price`
|
|
||||||
- les calculs de `amount`
|
- les calculs de `amount`
|
||||||
- la valuation / PnL
|
- la valuation / PnL
|
||||||
- Resultat attendu:
|
- Resultat attendu:
|
||||||
- en `priced`, le prix total = prix de base + premium
|
- le `unit_price` reste le prix de base, hors premium
|
||||||
- en `basis`, le premium s'ajoute aussi au prix total
|
- 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
|
- en valuation `basis`, le premium s'applique a chaque composant valorise
|
||||||
(ex: meme premium repete sur chaque bloc ICE)
|
(ex: meme premium repete sur chaque bloc ICE)
|
||||||
- Exemple metier:
|
- Exemple metier:
|
||||||
@@ -221,13 +221,14 @@ Owner technique: `a completer`
|
|||||||
- Description:
|
- Description:
|
||||||
- Quand `enable_linked_currency` est coche, le `premium` est saisi dans la
|
- Quand `enable_linked_currency` est coche, le `premium` est saisi dans la
|
||||||
devise / unite liee, pas dans la devise / unite native de la ligne.
|
devise / unite liee, pas dans la devise / unite native de la ligne.
|
||||||
- Le systeme doit convertir ce premium vers le `unit_price` de la ligne pour
|
- Le systeme doit convertir ce premium vers le repere de la ligne pour les
|
||||||
les calculs internes.
|
calculs internes de montant et de valuation.
|
||||||
- Resultat attendu:
|
- Resultat attendu:
|
||||||
- `premium` est interprete dans le repere `linked_currency` / `linked_unit`
|
- `premium` est interprete dans le repere `linked_currency` / `linked_unit`
|
||||||
- le `unit_price` converti integre ce premium
|
- le `unit_price` ne doit pas absorber ce premium
|
||||||
- les `amount` et valuations bases sur `unit_price` reflectent donc ce
|
- les `amount` et valuations doivent refleter ce premium converti
|
||||||
premium converti
|
- si `linked currency` est cochee, `linked_price`, `linked_currency` et
|
||||||
|
`linked_unit` sont obligatoires
|
||||||
- Priorite:
|
- Priorite:
|
||||||
- `structurante`
|
- `structurante`
|
||||||
|
|
||||||
@@ -238,12 +239,47 @@ Owner technique: `a completer`
|
|||||||
- Quand une ligne est en `basis` et `linked currency`, le bloc
|
- Quand une ligne est en `basis` et `linked currency`, le bloc
|
||||||
`linked_price` doit etre recalcule automatiquement.
|
`linked_price` doit etre recalcule automatiquement.
|
||||||
- Ce `linked_price` doit representer le prix basis brut, hors premium.
|
- Ce `linked_price` doit representer le prix basis brut, hors premium.
|
||||||
- Le `unit_price` final de la ligne est ensuite obtenu en ajoutant le premium
|
- Le `unit_price` de la ligne doit rester ce prix brut converti.
|
||||||
converti.
|
- Le premium converti n'est ajoute qu'au niveau du `amount`.
|
||||||
- Resultat attendu:
|
- Resultat attendu:
|
||||||
- modification du basis -> mise a jour automatique du `linked_price`
|
- modification du basis -> mise a jour automatique du `linked_price`
|
||||||
- `linked_price` = base market / basis
|
- `linked_price` = base market / basis
|
||||||
- `unit_price` = `linked_price` converti + premium converti
|
- `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.
|
||||||
|
- 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-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:
|
- Priorite:
|
||||||
- `importante`
|
- `importante`
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ Source code: `modules/purchase_trade/invoice.py`
|
|||||||
Source code: `modules/purchase_trade/sale.py`
|
Source code: `modules/purchase_trade/sale.py`
|
||||||
|
|
||||||
- `report_terms`
|
- `report_terms`
|
||||||
|
- `report_crop_name`
|
||||||
- `report_gross`
|
- `report_gross`
|
||||||
- `report_net`
|
- `report_net`
|
||||||
- `report_qt`
|
- `report_qt`
|
||||||
|
|||||||
@@ -352,19 +352,25 @@ class Sale(metaclass=PoolMeta):
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def report_nb_bale(self):
|
def report_nb_bale(self):
|
||||||
text_bale = 'NB BALES: '
|
text_bale = 'NB BALES: '
|
||||||
nb_bale = 0
|
nb_bale = 0
|
||||||
if self.lines:
|
if self.lines:
|
||||||
for line in self.lines:
|
for line in self.lines:
|
||||||
if line.lots:
|
if line.lots:
|
||||||
nb_bale += sum([l.lot_qt for l in line.lots if l.lot_type == 'physic'])
|
nb_bale += sum([l.lot_qt for l in line.lots if l.lot_type == 'physic'])
|
||||||
return text_bale + str(int(nb_bale))
|
return text_bale + str(int(nb_bale))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def report_deal(self):
|
def report_crop_name(self):
|
||||||
if self.lines and self.lines[0].lots and len(self.lines[0].lots)>1:
|
if self.crop:
|
||||||
return self.lines[0].lots[1].line.purchase.number + ' ' + self.number
|
return self.crop.name or ''
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@property
|
||||||
|
def report_deal(self):
|
||||||
|
if self.lines and self.lines[0].lots and len(self.lines[0].lots)>1:
|
||||||
|
return self.lines[0].lots[1].line.purchase.number + ' ' + self.number
|
||||||
else:
|
else:
|
||||||
''
|
''
|
||||||
|
|
||||||
|
|||||||
@@ -142,5 +142,17 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
|||||||
{'type': 'derivative', 'amount': Decimal('30')},
|
{'type': 'derivative', 'amount': Decimal('30')},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_sale_report_crop_name_handles_missing_crop(self):
|
||||||
|
'sale report crop name returns an empty string when crop is missing'
|
||||||
|
Sale = Pool().get('sale.sale')
|
||||||
|
|
||||||
|
sale = Sale()
|
||||||
|
sale.crop = None
|
||||||
|
self.assertEqual(sale.report_crop_name, '')
|
||||||
|
|
||||||
|
sale.crop = Mock(name='crop')
|
||||||
|
sale.crop.name = 'Main Crop'
|
||||||
|
self.assertEqual(sale.report_crop_name, 'Main Crop')
|
||||||
|
|
||||||
|
|
||||||
del ModuleTestCase
|
del ModuleTestCase
|
||||||
|
|||||||
@@ -4069,7 +4069,7 @@
|
|||||||
<text:s />
|
<text:s />
|
||||||
<text:span text:style-name="T21">CROP </text:span>
|
<text:span text:style-name="T21">CROP </text:span>
|
||||||
<text:span text:style-name="T21">
|
<text:span text:style-name="T21">
|
||||||
<text:placeholder text:placeholder-type="text"><sale.crop.name></text:placeholder>
|
<text:placeholder text:placeholder-type="text"><sale.report_crop_name></text:placeholder>
|
||||||
</text:span>
|
</text:span>
|
||||||
</text:p>
|
</text:p>
|
||||||
</table:table-cell>
|
</table:table-cell>
|
||||||
|
|||||||
Reference in New Issue
Block a user