This commit is contained in:
2026-06-12 20:34:47 +02:00
parent 7107625664
commit 1a5e2e4033
6 changed files with 205 additions and 118 deletions

View File

@@ -440,6 +440,60 @@ class PurchaseTradeTestCase(ModuleTestCase):
with self.assertRaises(UserError):
wizard.transition_shipping()
def test_lot_shipping_physical_without_move_creates_shipment_move(self):
'linking a physical lot to shipment creates the missing stock move'
wizard = lot_module.LotShipping()
shipment = Mock(id=40)
wizard.ship = Mock(
shipment='in',
shipment_in=shipment,
shipment_out=None,
shipment_internal=None,
create_new_shipment=False,
quantity=None,
)
record = Mock(
id=2014,
r_lot_type='physic',
)
wizard.records = [record]
move = Mock()
move.get_linked_transit_move.return_value = None
lot = Mock(
id=2014,
move=None,
line=Mock(),
sale_line=None,
)
lot.get_current_quantity_converted.return_value = Decimal('22')
lot.getVlot_p.return_value = Mock()
lot.getVlot_s.return_value = None
lot.create_shipment_move.return_value = move
Lot = Mock()
Lot.return_value = lot
Lot.skip_quantity_consistency.return_value.__enter__ = Mock()
Lot.skip_quantity_consistency.return_value.__exit__ = Mock()
LotQt = Mock()
Move = Mock()
pool = Mock()
pool.get.side_effect = [Lot, LotQt, Move]
with patch('trytond.modules.purchase_trade.lot.Pool',
return_value=pool):
state = wizard.transition_shipping()
self.assertEqual(state, 'end')
self.assertEqual(lot.lot_shipment_in, shipment)
lot.create_shipment_move.assert_called_once_with(
'stock.shipment.in,40')
self.assertEqual(move.shipment, 'stock.shipment.in,40')
Move.save.assert_called_once_with([move])
lot.updateVirtualPart.assert_called_once_with(
Decimal('-22'), 'stock.shipment.in,40', None)
Lot.save.assert_called()
Lot.assert_lines_quantity_consistency.assert_called_once_with([
lot.line])
def test_lot_shipping_scheduled_lotqt_keeps_planned_locations(self):
'scheduled lot.qt keeps the planned from and to locations'
wizard = lot_module.LotShipping()
@@ -556,8 +610,8 @@ class PurchaseTradeTestCase(ModuleTestCase):
Decimal('-349167.53'))
@with_transaction()
def test_strategy_mtm_lines_split_by_curve_with_previous_price(self):
'strategy MTM creates one valuation line per curve with previous price'
def test_strategy_mtm_lines_are_separate_from_realized_price(self):
'strategy MTM creates separate curve lines and preserves realized line'
Valuation = Pool().get('valuation.valuation')
valuation_date = datetime.date(2026, 6, 5)
previous_date = datetime.date(2026, 6, 4)
@@ -583,6 +637,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
price_index=curve_b,
ratio=Decimal('40')),
])
line.mtm = [strategy]
values = {
'type': 'pur. priced',
'price': Decimal('10'),
@@ -596,22 +651,28 @@ class PurchaseTradeTestCase(ModuleTestCase):
with patch('trytond.modules.purchase_trade.valuation.Pool') as PoolMock:
PoolMock.return_value.get.return_value = price_value
Valuation._append_strategy_mtm_lines(
target, values, strategy, line)
Valuation._append_pnl_values(target, values, line)
self.assertEqual(len(target), 2)
self.assertEqual(target[0]['mtm_curve'], curve_a.id)
self.assertEqual(target[0]['amount'], Decimal('-60.00'))
self.assertEqual(target[0]['mtm_price'], Decimal('60.0000'))
self.assertEqual(target[0]['mtm_price_prev'], Decimal('54.0000'))
self.assertEqual(target[0]['amount_prev'], Decimal('-540.00'))
self.assertEqual(target[0]['mtm'], Decimal('-600.00'))
self.assertEqual(target[1]['mtm_curve'], curve_b.id)
self.assertEqual(target[1]['amount'], Decimal('-40.00'))
self.assertEqual(target[1]['mtm_price'], Decimal('20.0000'))
self.assertEqual(target[1]['mtm_price_prev'], Decimal('18.0000'))
self.assertEqual(target[1]['amount_prev'], Decimal('-180.00'))
self.assertEqual(target[1]['mtm'], Decimal('-200.00'))
self.assertEqual(len(target), 3)
self.assertEqual(target[0], values)
self.assertEqual(target[1]['type'], 'mtm')
self.assertEqual(target[1]['mtm_curve'], curve_a.id)
self.assertEqual(target[1]['price'], None)
self.assertEqual(target[1]['amount'], Decimal('0'))
self.assertEqual(target[1]['quantity'], Decimal('10'))
self.assertEqual(target[1]['mtm_price'], Decimal('100.0000'))
self.assertEqual(target[1]['mtm_price_prev'], Decimal('90.0000'))
self.assertEqual(target[1]['amount_prev'], Decimal('-540.00'))
self.assertEqual(target[1]['mtm'], Decimal('-600.00'))
self.assertEqual(target[2]['type'], 'mtm')
self.assertEqual(target[2]['mtm_curve'], curve_b.id)
self.assertEqual(target[2]['price'], None)
self.assertEqual(target[2]['amount'], Decimal('0'))
self.assertEqual(target[2]['quantity'], Decimal('10'))
self.assertEqual(target[2]['mtm_price'], Decimal('50.0000'))
self.assertEqual(target[2]['mtm_price_prev'], Decimal('45.0000'))
self.assertEqual(target[2]['amount_prev'], Decimal('-180.00'))
self.assertEqual(target[2]['mtm'], Decimal('-200.00'))
def test_purchase_pnl_uses_partial_lotqt_match_quantity(self):
'open matched purchase and sale pnl use the matched lot.qt quantity'
@@ -1095,6 +1156,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
Valuation._get_generate_types('derivatives'),
{'derivative'})
self.assertIn('pur. priced', Valuation._get_generate_types('goods'))
self.assertIn('mtm', Valuation._get_generate_types('goods'))
def test_filter_values_by_types_keeps_matching_entries_only(self):
'type filtering keeps only the requested valuation entries'