diff --git a/modules/purchase_trade/fee.py b/modules/purchase_trade/fee.py
index c2a7502..f0ea47f 100755
--- a/modules/purchase_trade/fee.py
+++ b/modules/purchase_trade/fee.py
@@ -8,7 +8,7 @@ from trytond.tools import is_full_text, lstrip_wildcard
from trytond.transaction import Transaction, inactive_records
from decimal import getcontext, Decimal, ROUND_UP, ROUND_HALF_UP
from sql.aggregate import Count, Max, Min, Sum, Avg, BoolOr
-from sql.conditionals import Case
+from sql.conditionals import Case, Coalesce
from sql import Column, Literal, Null
from sql.functions import CurrentTimestamp, DateTrunc
from trytond.wizard import Button, StateTransition, StateView, Wizard
@@ -1515,10 +1515,10 @@ class FeeLots(ModelSQL,ModelView):
class FeeReport(
ModelSQL, ModelView):
- "Fee Report"
- __name__ = 'fee.report'
- r_purchase_line = fields.Many2One('purchase.line', "Purchase line")
- r_sale_line = fields.Many2One('sale.line', "Sale line")
+ "Fee Report"
+ __name__ = 'fee.report'
+ r_purchase_line = fields.Many2One('purchase.line', "Purchase line")
+ r_sale_line = fields.Many2One('sale.line', "Sale line")
r_shipment_in = fields.Many2One('stock.shipment.in', "Shipment in")
r_shipment_out = fields.Many2One('stock.shipment.out', "Shipment out")
r_shipment_internal = fields.Many2One('stock.shipment.internal', "Shipment internal")
@@ -1540,9 +1540,10 @@ class FeeReport(
('pcost', '% cost price'),
], 'Mode', required=True)
- r_fee_quantity = fields.Function(fields.Numeric("Qt",digits=(1,4)),'get_quantity')
- r_fee_unit = fields.Function(fields.Many2One('product.uom',"Unit"),'get_unit')
- r_purchase = fields.Many2One('purchase.purchase',"Purchase", ondelete='CASCADE')
+ r_fee_quantity = fields.Function(fields.Numeric("Qt",digits=(1,4)),'get_quantity')
+ r_fee_unit = fields.Function(fields.Many2One('product.uom',"Unit"),'get_unit')
+ r_purchase = fields.Many2One('purchase.purchase',"Purchase", ondelete='CASCADE')
+ r_sale = fields.Many2One('sale.sale',"Sale", ondelete='CASCADE')
r_fee_amount = fields.Function(fields.Numeric("Amount", digits=(1,4)),'get_amount')
r_inv = fields.Function(fields.Many2One('account.invoice',"Invoice"),'get_invoice')
r_dn_cn = fields.Function(fields.Many2One('account.invoice',"DN/CN"),
@@ -1617,16 +1618,26 @@ class FeeReport(
@classmethod
def table_query(cls):
- FeeReport = Pool().get('fee.fee')
- fr = FeeReport.__table__()
- Purchase = Pool().get('purchase.purchase')
- pu = Purchase.__table__()
- PurchaseLine = Pool().get('purchase.line')
- pl = PurchaseLine.__table__()
- Sale = Pool().get('sale.sale')
- sa = Sale.__table__()
- SaleLine = Pool().get('sale.line')
- sl = SaleLine.__table__()
+ FeeReport = Pool().get('fee.fee')
+ fr = FeeReport.__table__()
+ FeeLots = Pool().get('fee.lots')
+ fl = FeeLots.__table__()
+ PurchaseLine = Pool().get('purchase.line')
+ pl = PurchaseLine.__table__()
+ SaleLine = Pool().get('sale.line')
+ sl = SaleLine.__table__()
+
+ fee_lot_lines = (
+ fl
+ .join(pl, 'LEFT', condition=fl.line == pl.id)
+ .join(sl, 'LEFT', condition=fl.sale_line == sl.id)
+ .select(
+ fl.fee.as_('fee'),
+ Min(fl.line).as_('purchase_line'),
+ Min(pl.purchase).as_('purchase'),
+ Min(fl.sale_line).as_('sale_line'),
+ Min(sl.sale).as_('sale'),
+ group_by=[fl.fee]))
context = Transaction().context
party = context.get('party')
@@ -1644,10 +1655,13 @@ class FeeReport(
wh &= (fr.fee_counterparty == party)
if fee_type:
wh &= (fr.fee_type == fee_type)
- if purchase:
- wh &= (pu.id == purchase)
- if sale:
- wh &= (sa.id == sale)
+ purchase_expr = Coalesce(fee_lot_lines.purchase, fr.purchase)
+ purchase_line_expr = Coalesce(fee_lot_lines.purchase_line, fr.line)
+ sale_expr = fee_lot_lines.sale
+ if purchase:
+ wh &= (purchase_expr == purchase)
+ if sale:
+ wh &= (sale_expr == sale)
if shipment_in:
wh &= (fr.shipment_in == shipment_in)
if invoice_status == 'not_invoiced':
@@ -1656,30 +1670,33 @@ class FeeReport(
wh &= ((fr.state == 'invoiced') & (fr.dn_cn == Null))
elif invoice_status == 'invoiced_with_dn_cn':
wh &= ((fr.state == 'invoiced') & (fr.dn_cn != Null))
- # if shipment_out:
- # wh &= (fr.shipment_out == shipment_out)
-
- query = fr.join(pl,'LEFT',condition=fr.line == pl.id).join(pu,'LEFT', condition=pl.purchase == pu.id).select(
- Literal(0).as_('create_uid'),
- CurrentTimestamp().as_('create_date'),
- Literal(None).as_('write_uid'),
- Literal(None).as_('write_date'),
- fr.id.as_('id'),
- fr.line.as_('r_purchase_line'),
- Literal(None).as_('r_sale_line'),
- fr.shipment_in.as_('r_shipment_in'),
- Literal(None).as_('r_shipment_out'),
- fr.shipment_internal.as_('r_shipment_internal'),
- fr.product.as_('r_fee_type'),
- fr.supplier.as_('r_fee_counterparty'),
+ # if shipment_out:
+ # wh &= (fr.shipment_out == shipment_out)
+
+ query = fr.join(
+ fee_lot_lines, 'LEFT', condition=fr.id == fee_lot_lines.fee
+ ).select(
+ Literal(0).as_('create_uid'),
+ CurrentTimestamp().as_('create_date'),
+ Literal(None).as_('write_uid'),
+ Literal(None).as_('write_date'),
+ fr.id.as_('id'),
+ purchase_line_expr.as_('r_purchase_line'),
+ fee_lot_lines.sale_line.as_('r_sale_line'),
+ fr.shipment_in.as_('r_shipment_in'),
+ Literal(None).as_('r_shipment_out'),
+ fr.shipment_internal.as_('r_shipment_internal'),
+ fr.product.as_('r_fee_type'),
+ fr.supplier.as_('r_fee_counterparty'),
fr.type.as_('r_type'),
- fr.p_r.as_('r_fee_paystatus'),
- fr.mode.as_('r_mode'),
- fr.state.as_('r_state'),
- fr.purchase.as_('r_purchase'),
- #fr.amount.as_('r_fee_amount'),
- fr.price.as_('r_fee_price'),
- fr.currency.as_('r_fee_currency'),
+ fr.p_r.as_('r_fee_paystatus'),
+ fr.mode.as_('r_mode'),
+ fr.state.as_('r_state'),
+ purchase_expr.as_('r_purchase'),
+ sale_expr.as_('r_sale'),
+ #fr.amount.as_('r_fee_amount'),
+ fr.price.as_('r_fee_price'),
+ fr.currency.as_('r_fee_currency'),
#fr.fee_lots.as_('r_fee_lots'),
#fr.lots.as_('r_lots'),
where=wh)
diff --git a/modules/purchase_trade/fee.xml b/modules/purchase_trade/fee.xml
index d95a602..55dfeb8 100755
--- a/modules/purchase_trade/fee.xml
+++ b/modules/purchase_trade/fee.xml
@@ -159,5 +159,9 @@ this repository contains the full copyright notices and license terms. -->
action="act_fee_report_form"
sequence="10"
id="menu_fee_report_form"/>
+
diff --git a/modules/purchase_trade/pricing.py b/modules/purchase_trade/pricing.py
index ff1ebf6..545b4ba 100755
--- a/modules/purchase_trade/pricing.py
+++ b/modules/purchase_trade/pricing.py
@@ -612,24 +612,24 @@ class MtmStrategy(ModelSQL, ModelView):
if comp.price_source_type == 'curve' and comp.price_index:
value = Decimal(
- comp.price_index.get_price(
- dt,
- line.unit,
- self.currency,
- last=scenario.use_last_price
- )
- )
+ comp.price_index.get_price(
+ dt,
+ line.unit,
+ self.currency,
+ relative_last=scenario.use_last_price
+ )
+ )
elif comp.price_source_type == 'matrix' and comp.price_matrix:
value = self._get_matrix_price(comp, line, dt)
elif comp.price_source_type == 'fixed':
- value = Decimal(comp.get_price(
- dt,
- line.unit,
- self.currency,
- last=scenario.use_last_price
- ))
+ value = Decimal(comp.get_price(
+ dt,
+ line.unit,
+ self.currency,
+ relative_last=scenario.use_last_price
+ ))
if comp.ratio:
value *= Decimal(comp.ratio) / Decimal(100)
diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py
index 2b7a281..d105461 100644
--- a/modules/purchase_trade/tests/test_module.py
+++ b/modules/purchase_trade/tests/test_module.py
@@ -709,6 +709,11 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(
strategy.get_mtm(line, Decimal('10')),
Decimal('250.00'))
+ strategy.components[0].price_index.get_price.assert_called_once_with(
+ '2026-03-29',
+ line.unit,
+ strategy.currency,
+ relative_last=True)
@with_transaction()
def test_get_mtm_uses_fixed_pricing_component(self):
@@ -1205,6 +1210,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
def test_get_strategy_mtm_price_applies_component_ratio(self):
'strategy mtm price applies component ratios'
+ price_index = Mock(get_price=Mock(return_value=Decimal('100')))
strategy = Mock(
scenario=Mock(
valuation_date='2026-03-29',
@@ -1214,7 +1220,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
)
strategy.components = [Mock(
price_source_type='curve',
- price_index=Mock(get_price=Mock(return_value=Decimal('100'))),
+ price_index=price_index,
price_matrix=None,
ratio=Decimal('25'),
)]
@@ -1223,6 +1229,11 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(
valuation_module.Valuation._get_strategy_mtm_price(strategy, line),
Decimal('25.0000'))
+ price_index.get_price.assert_called_once_with(
+ '2026-03-29',
+ line.unit,
+ strategy.currency,
+ relative_last=True)
def test_get_strategy_mtm_price_keeps_signed_component_spread(self):
'strategy mtm price keeps signed spread between different components'
diff --git a/modules/purchase_trade/valuation.py b/modules/purchase_trade/valuation.py
index 5b68559..db43d13 100644
--- a/modules/purchase_trade/valuation.py
+++ b/modules/purchase_trade/valuation.py
@@ -522,7 +522,7 @@ class ValuationBase(ModelSQL):
scenario.valuation_date,
line.unit,
strategy.currency,
- last=scenario.use_last_price
+ relative_last=scenario.use_last_price
))
elif comp.price_source_type == 'matrix' and comp.price_matrix:
value = Decimal(strategy._get_matrix_price(
@@ -533,7 +533,7 @@ class ValuationBase(ModelSQL):
scenario.valuation_date,
line.unit,
strategy.currency,
- last=scenario.use_last_price
+ relative_last=scenario.use_last_price
))
if comp.ratio:
@@ -583,7 +583,7 @@ class ValuationBase(ModelSQL):
scenario.valuation_date,
line.unit,
strategy.currency,
- last=scenario.use_last_price))
+ relative_last=scenario.use_last_price))
previous = cls._previous_curve_price(
component.price_index,
scenario.valuation_date,
diff --git a/modules/purchase_trade/view/fee_report_list.xml b/modules/purchase_trade/view/fee_report_list.xml
index 39a813d..b0e35dc 100755
--- a/modules/purchase_trade/view/fee_report_list.xml
+++ b/modules/purchase_trade/view/fee_report_list.xml
@@ -1,6 +1,8 @@
-
+
+
+