Shipment Pnl

This commit is contained in:
2026-06-10 11:37:33 +02:00
parent 96ad6dd1c6
commit 925fdfd32b
3 changed files with 261 additions and 112 deletions

View File

@@ -1235,6 +1235,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
'ir.date': Mock(today=Mock(return_value=datetime.date(2026, 4, 23))),
'currency.currency': Mock(),
'fee.lots': fee_lots,
'lot.qt': Mock(),
}[name]
values = Valuation.create_pnl_fee_from_line(line)
@@ -1625,7 +1626,12 @@ class PurchaseTradeTestCase(ModuleTestCase):
)
lot_qt_model = Mock()
lot_qt_model.search.return_value = [Mock(lot_s=sale_lot)]
lot_qt_model.search.return_value = [
Mock(
lot_s=sale_lot,
lot_quantity=Decimal('2'),
lot_unit=unit,
lot_shipment_in=None)]
with patch('trytond.modules.purchase_trade.valuation.Pool') as PoolMock:
PoolMock.return_value.get.side_effect = lambda name: {
@@ -1673,7 +1679,12 @@ class PurchaseTradeTestCase(ModuleTestCase):
unit=unit,
)
lot_qt_model = Mock()
lot_qt_model.search.return_value = [Mock(lot_s=sale_lot)]
lot_qt_model.search.return_value = [
Mock(
lot_s=sale_lot,
lot_quantity=Decimal('2'),
lot_unit=unit,
lot_shipment_in=None)]
fee_lots = Mock()
fee_lots.search.return_value = [Mock(fee=fee)]
@@ -1739,6 +1750,65 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(values[0]['type'], 'sale fee')
self.assertEqual(values[0]['lot'], sale_lot.id)
def test_sale_open_fee_pnl_splits_by_shipment_lotqt(self):
'sale open fee pnl is split between shipped and unshipped lot.qt'
Valuation = Pool().get('valuation.valuation')
currency = Mock(id=1)
unit = Mock(id=2)
shipment = Mock(id=70)
sale = Mock(id=3, currency=currency)
sale_line = Mock(id=4, sale=sale, unit=unit, finished=False)
sale_lot = Mock(id=5, sale_line=sale_line, lot_type='virtual')
sale_lot.get_current_quantity_converted.return_value = Decimal('220')
sale_line.lots = [sale_lot]
fee = Mock(
product=Mock(id=6, name='Broker commission'),
supplier=Mock(id=7),
type='budgeted',
p_r='pay',
mode='perqt',
price=Decimal('10'),
currency=currency,
shipment_in=None,
sale_line=sale_line,
unit=unit,
)
fee.is_effective_fee_lot.return_value = True
fee.get_price_per_qt.return_value = Decimal('10')
fee_lots = Mock()
fee_lots.search.return_value = [Mock(fee=fee)]
lot_qt_model = Mock()
lot_qt_model.search.return_value = [
Mock(
lot_s=sale_lot,
lot_quantity=Decimal('88'),
lot_unit=unit,
lot_shipment_in=shipment),
Mock(
lot_s=sale_lot,
lot_quantity=Decimal('132'),
lot_unit=unit,
lot_shipment_in=None),
]
with patch('trytond.modules.purchase_trade.valuation.Pool') as PoolMock:
PoolMock.return_value.get.side_effect = lambda name: {
'ir.date': Mock(today=Mock(return_value=datetime.date(2026, 5, 14))),
'currency.currency': Mock(),
'fee.lots': fee_lots,
'lot.qt': lot_qt_model,
}[name]
values = Valuation.create_pnl_fee_from_sale_line(sale_line)
self.assertEqual(len(values), 2)
self.assertEqual(values[0]['shipment_in'], shipment.id)
self.assertEqual(values[0]['quantity'], Decimal('88.00000'))
self.assertEqual(values[0]['amount'], Decimal('-880.00'))
self.assertIsNone(values[1]['shipment_in'])
self.assertEqual(values[1]['quantity'], Decimal('132.00000'))
self.assertEqual(values[1]['amount'], Decimal('-1320.00'))
def test_snapshot_identity_prefers_sale_line_over_purchase_line(self):
'valuation snapshot identity ignores purchase line when sale line exists'
Valuation = Pool().get('valuation.valuation')
@@ -1839,6 +1909,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
'ir.date': Mock(today=Mock(return_value=datetime.date(2026, 4, 29))),
'currency.currency': Mock(),
'fee.lots': fee_lots,
'lot.qt': Mock(),
}[name]
values = Valuation.create_pnl_fee_from_sale_line(sale_line)
@@ -3005,13 +3076,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(shipment.get_pnl_lines(None), [10, 11])
valuation_model.search.assert_called_once_with(
['OR',
[('shipment_in', '=', 99)],
[
('shipment_in', '=', None),
('lot', 'in', [1, 2, 3]),
],
],
[('shipment_in', '=', 99)],
order=[('date', 'DESC'), ('id', 'DESC')])
def test_sale_and_purchase_tolerance_option_defaults_to_empty(self):