From b5b2f1c36258f030dac08d79ecf49dbbf213fd6e Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Sun, 8 Feb 2026 21:25:22 +0100 Subject: [PATCH] 08.02.26 --- modules/purchase_trade/valuation.py | 140 +++++++++++++----- .../view/valuation_context_form.xml | 2 + .../view/valuation_tree_sequence3.xml | 3 +- .../view/valuation_tree_sequence4.xml | 3 +- 4 files changed, 109 insertions(+), 39 deletions(-) diff --git a/modules/purchase_trade/valuation.py b/modules/purchase_trade/valuation.py index 7cc4e64..9fa16ad 100644 --- a/modules/purchase_trade/valuation.py +++ b/modules/purchase_trade/valuation.py @@ -49,6 +49,7 @@ class ValuationBase(ModelSQL): unit = fields.Many2One('product.uom',"Unit") amount = fields.Numeric("Amount",digits=(16,2)) mtm = fields.Numeric("Mtm",digits=(16,2)) + strategy = fields.Many2One('mtm.strategy',"Strategy") lot = fields.Many2One('lot.lot',"Lot") base_amount = fields.Numeric("Base Amount",digits=(16,2)) rate = fields.Numeric("Rate", digits=(16,6)) @@ -109,14 +110,13 @@ class ValuationBase(ModelSQL): base_amount = Currency.compute(currency,amount, line.purchase.company.currency) rate = round(amount / base_amount,6) last_price = pc.get_last_price() - mtm = round(Decimal(last_price) * qty * Decimal(sign), 2) if last_price else Decimal(0) - + # mtm = round(Decimal(last_price) * qty * Decimal(sign), 2) if last_price else Decimal(0) values.update({ 'quantity': round(qty, 5), 'amount': amount, 'base_amount': base_amount, 'rate': rate, - 'mtm': round(amount - (mtm * pc.ratio / 100), 2), + 'mtm': None #round(amount - (mtm * pc.ratio / 100), 2), 'unit': sale_line.unit.id if sale_line else line.unit.id, 'currency': currency, }) @@ -177,12 +177,19 @@ class ValuationBase(ModelSQL): if line.price_type == 'basis': for pc in line.price_summary or []: values = cls._build_basis_pnl(line=line, lot=lot, sale_line=None, pc=pc, sign=-1) - if values: - price_lines.append(values) + if line.mtm: + for strat in line.mtm: + values['mtm'] = line.get_mtm(values['qty']) + values['strategy'] = strat.name + + if values: + price_lines.append(values) + else: + if values: + price_lines.append(values) elif line.price_type in ('priced', 'efp') and lot.lot_price: - price_lines.append( - cls._build_simple_pnl( + values = cls._build_simple_pnl( line=line, lot=lot, sale_line=None, @@ -191,7 +198,16 @@ class ValuationBase(ModelSQL): sign=-1, pnl_type=f'pur. {line.price_type}' ) - ) + if line.mtm: + for strat in line.mtm: + values['mtm'] = line.get_mtm(values['qty']) + values['strategy'] = strat.name + + if values: + price_lines.append(values) + else: + if values: + price_lines.append(values) sale_lots = [lot] if lot.sale_line else [ lqt.lot_s for lqt in LotQt.search([ @@ -209,12 +225,19 @@ class ValuationBase(ModelSQL): if sl_line.price_type == 'basis': for pc in sl_line.price_summary or []: values = cls._build_basis_pnl(line=line, lot=sl, sale_line=sl_line, pc=pc, sign=+1) - if values: - price_lines.append(values) + if sl_line.mtm: + for strat in line.mtm: + values['mtm'] = sl_line.get_mtm(values['qty']) + values['strategy'] = strat.name + + if values: + price_lines.append(values) + else: + if values: + price_lines.append(values) elif sl_line.price_type in ('priced', 'efp'): - price_lines.append( - cls._build_simple_pnl( + values = cls._build_simple_pnl( line=line, lot=sl, sale_line=sl_line, @@ -223,7 +246,16 @@ class ValuationBase(ModelSQL): sign=+1, pnl_type=f'sale {sl_line.price_type}' ) - ) + if sl_line.mtm: + for strat in sl_line.mtm: + values['mtm'] = sl_line.get_mtm(values['qty']) + values['strategy'] = strat.name + + if values: + price_lines.append(values) + else: + if values: + price_lines.append(values) return price_lines @@ -270,29 +302,56 @@ class ValuationBase(ModelSQL): if sf.currency != line.purchase.currency: with Transaction().set_context(date=Date.today()): price = Currency.compute(sf.currency, price, line.purchase.currency) - - fee_lines.append({ - 'lot': lot.id, - 'sale': lot.sale_line.sale.id if lot.sale_line else None, - 'purchase': line.purchase.id, - 'line': line.id, - 'type': ( - 'shipment fee' if sf.shipment_in - else 'sale fee' if sf.sale_line - else 'pur. fee' - ), - 'date': Date.today(), - 'price': price, - 'counterparty': sf.supplier.id, - 'reference': f"{sf.product.name}/{'Physic' if lot.lot_type == 'physic' else 'Open'}", - 'product': sf.product.id, - 'state': sf.type, - 'quantity': round(lot.get_current_quantity_converted(), 5), - 'amount': amount, - 'mtm': Decimal(0), - 'unit': sf.unit.id if sf.unit else line.unit.id, - 'currency': sf.currency.id, - }) + if line.mtm: + for strat in line.mtm: + qty = round(lot.get_current_quantity_converted(), 5) + fee_lines.append({ + 'lot': lot.id, + 'sale': lot.sale_line.sale.id if lot.sale_line else None, + 'purchase': line.purchase.id, + 'line': line.id, + 'type': ( + 'shipment fee' if sf.shipment_in + else 'sale fee' if sf.sale_line + else 'pur. fee' + ), + 'date': Date.today(), + 'price': price, + 'counterparty': sf.supplier.id, + 'reference': f"{sf.product.name}/{'Physic' if lot.lot_type == 'physic' else 'Open'}", + 'product': sf.product.id, + 'state': sf.type, + 'quantity': qty, + 'amount': amount, + 'mtm': strat.get_mtm(qty), + 'strategy': strat, + 'unit': sf.unit.id if sf.unit else line.unit.id, + 'currency': sf.currency.id, + }) + else: + fee_lines.append({ + 'lot': lot.id, + 'sale': lot.sale_line.sale.id if lot.sale_line else None, + 'purchase': line.purchase.id, + 'line': line.id, + 'type': ( + 'shipment fee' if sf.shipment_in + else 'sale fee' if sf.sale_line + else 'pur. fee' + ), + 'date': Date.today(), + 'price': price, + 'counterparty': sf.supplier.id, + 'reference': f"{sf.product.name}/{'Physic' if lot.lot_type == 'physic' else 'Open'}", + 'product': sf.product.id, + 'state': sf.type, + 'quantity': qty, + 'amount': amount, + 'mtm': Decimal(0), + 'strategy': None, + 'unit': sf.unit.id if sf.unit else line.unit.id, + 'currency': sf.currency.id, + }) return fee_lines @@ -427,6 +486,7 @@ class ValuationDyn(ModelSQL,ModelView): r_base_amount = fields.Numeric("Base Amount",digits='r_unit') r_rate = fields.Numeric("Rate",digits=(16,6)) r_mtm = fields.Numeric("Mtm",digits='r_unit') + r_strategy = fields.Many2One('mtm.strategy',"Strategy") r_lot = fields.Many2One('lot.lot',"Lot") @classmethod @@ -459,6 +519,7 @@ class ValuationDyn(ModelSQL,ModelView): Sum(val.base_amount).as_('r_base_amount'), Sum(val.rate).as_('r_rate'), Sum(val.mtm).as_('r_mtm'), + Max(val.strategy).as_('r_strategy'), Max(val.lot).as_('r_lot'), where=wh, group_by=[val.type,val.counterparty,val.state]) @@ -475,8 +536,11 @@ class ValuationReport(ValuationBase, ModelView): val = Valuation.__table__() context = Transaction().context valuation_date = context.get('valuation_date') + strategy = context.get('strategy') wh = (val.date == valuation_date) - + if strategy: + wh &= (val.strategy == strategy) + query = val.select( Literal(0).as_('create_uid'), CurrentTimestamp().as_('create_date'), @@ -501,6 +565,7 @@ class ValuationReport(ValuationBase, ModelView): val.base_amount.as_('base_amount'), val.rate.as_('rate'), val.mtm.as_('mtm'), + val.strategy.as_('strategy'), val.lot.as_('lot'), where=wh) @@ -522,6 +587,7 @@ class ValuationReportContext(ModelView): ('fixed', 'Fixed'), ('hedged', 'Hedged') ], 'State') + strategy = fields.Many2One('mtm.strategy') @classmethod def default_valuation_date(cls): diff --git a/modules/purchase_trade/view/valuation_context_form.xml b/modules/purchase_trade/view/valuation_context_form.xml index 8ec7022..c467180 100644 --- a/modules/purchase_trade/view/valuation_context_form.xml +++ b/modules/purchase_trade/view/valuation_context_form.xml @@ -13,4 +13,6 @@