Duplicate custom

This commit is contained in:
2026-06-18 12:59:16 +02:00
parent f8d53a27fa
commit 903b42f730
3 changed files with 288 additions and 1 deletions

View File

@@ -6203,6 +6203,108 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(virtual_parts, [
(43, Decimal('50.00000'), None, 43, 'only sale')])
def test_custom_duplicate_defaults_mirror_from_matched_sale(self):
'custom duplicate can default mirror party from the matched sale'
purchase_party = SimpleNamespace(id=1)
sale_party = SimpleNamespace(id=2)
purchase_lot = SimpleNamespace(id=10)
sale = SimpleNamespace(party=sale_party)
sale_line = SimpleNamespace(id=20, sale=sale)
lot_qt = SimpleNamespace(lot_s=SimpleNamespace(sale_line=sale_line))
class FakeLotQt:
@classmethod
def search(cls, domain):
return [lot_qt]
pool = Mock()
pool.get.side_effect = lambda name: {'lot.qt': FakeLotQt}[name]
line = SimpleNamespace(
__name__='purchase.line',
id=11,
type='line',
product=Mock(),
lots=[purchase_lot],
unit=SimpleNamespace(id=3),
quantity=Decimal('100'),
quantity_theorical=Decimal('100'),
unit_price=Decimal('25'),
price_type='priced',
)
record = SimpleNamespace(
__name__='purchase.purchase',
id=12,
lines=[line],
party=purchase_party,
currency=SimpleNamespace(id=4),
payment_term=SimpleNamespace(id=5),
incoterm=SimpleNamespace(id=6),
)
wizard = duplicate_module.TradeCustomDuplicate()
wizard.records = [record]
with patch.object(duplicate_module, 'Pool', return_value=pool):
values = wizard.default_start(None)
self.assertEqual(values['mirror_mode'], 'duplicate_pair')
self.assertEqual(values['mirror_party'], sale_party.id)
def test_custom_duplicate_match_pair_lots_links_new_quantities(self):
'custom duplicate matches the new purchase and sale lot.qt rows'
saved = []
deleted = []
checked_lines = []
purchase_lqt = SimpleNamespace(
lot_s=None,
lot_quantity=Decimal('0'),
)
sale_lqt = SimpleNamespace(
lot_p=None,
lot_quantity=Decimal('100'),
)
class FakeLotQt:
@classmethod
def search(cls, domain):
if ('lot_p', '=', 101) in domain:
return [purchase_lqt]
if ('lot_s', '=', 202) in domain:
return [sale_lqt]
return []
@classmethod
def save(cls, records):
saved.extend(records)
@classmethod
def delete(cls, records):
deleted.extend(records)
class FakeLot:
@classmethod
def assert_lines_quantity_consistency(cls, lines):
checked_lines.extend(lines)
pool = Mock()
pool.get.side_effect = lambda name: {
'lot.qt': FakeLotQt,
'lot.lot': FakeLot,
}[name]
purchase_line = SimpleNamespace(__name__='purchase.line')
sale_line = SimpleNamespace(__name__='sale.line')
with patch.object(duplicate_module, 'Pool', return_value=pool):
duplicate_module.TradeCustomDuplicate._match_duplicate_pair_lots(
purchase_line, SimpleNamespace(id=101),
sale_line, SimpleNamespace(id=202),
Decimal('100'))
self.assertEqual(purchase_lqt.lot_s, 202)
self.assertEqual(purchase_lqt.lot_quantity, Decimal('100.00000'))
self.assertEqual(saved, [purchase_lqt])
self.assertEqual(deleted, [sale_lqt])
self.assertEqual(checked_lines, [purchase_line, sale_line])
def test_lot_matching_rejects_purchase_quantity_above_available(self):
'apply matching cannot consume more than available purchase quantity'
class LotQtMock: