diff --git a/modules/purchase_trade/sale.py b/modules/purchase_trade/sale.py index 9ab4cd8..ae3e2b8 100755 --- a/modules/purchase_trade/sale.py +++ b/modules/purchase_trade/sale.py @@ -2813,6 +2813,9 @@ class SaleLine(metaclass=PoolMeta): if (not line.lots and line.product.type != 'service' and line.quantity_theorical and Decimal(str(line.quantity_theorical or 0)) != Decimal(0)): + FeeLots = Pool().get('fee.lots') + LotQtHist = Pool().get('lot.qt.hist') + LotQtType = Pool().get('lot.qt.type') Lot = Pool().get('lot.lot') lot = Lot() lot.sale_line = line.id diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index ddc04de..f3da85b 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -6403,6 +6403,74 @@ class PurchaseTradeTestCase(ModuleTestCase): self.assertIs(matched_line, sale_line_a) + def test_sale_line_validate_uses_pool_fee_lots_model(self): + 'sale line validation uses the real fee.lots model for new lot fees' + created_fee_lots = [] + saved_lots = [] + + class FakeFeeLots: + @classmethod + def search(cls, domain): + return [] + + @classmethod + def save(cls, records): + created_fee_lots.extend(records) + + class FakeLot: + def __init__(self): + self.id = 42 + + @classmethod + def save(cls, records): + saved_lots.extend(records) + + class FakeLotQtHist: + pass + + class FakeLotQtType: + @classmethod + def search(cls, domain): + return [] + + pool = Mock() + pool.get.side_effect = lambda name: { + 'fee.lots': FakeFeeLots, + 'lot.qt.hist': FakeLotQtHist, + 'lot.qt.type': FakeLotQtType, + 'lot.lot': FakeLot, + 'lot.qt': Mock(search=Mock(return_value=[])), + }[name] + line = Mock( + id=11, + product=Mock(type='goods'), + lots=[], + fees=[SimpleNamespace(id=7)], + unit=Mock(), + quantity_theorical=Decimal('25'), + created_by_code=False, + price_components=[], + fee_=None, + ) + line.check_pricing.return_value = None + line.check_targeted_qt_tolerance.return_value = None + + with patch.object(sale_module, 'Pool', return_value=pool), \ + patch.object( + sale_module.SaleLine, '_has_invalid_delivery_period', + return_value=False), \ + patch.object( + sale_module.SaleLine, + '_sync_initial_quantity_from_theorical', + return_value=False), \ + patch.object(sale_module.SaleLine, 'save'), \ + patch.object(sale_module.Pnl, 'generate_from_sale_line'): + sale_module.SaleLine.validate([line]) + + self.assertEqual(len(saved_lots), 1) + self.assertEqual(len(created_fee_lots), 1) + self.assertEqual(created_fee_lots[0].sale_line, line.id) + def test_custom_duplicate_match_pair_lots_links_new_quantities(self): 'custom duplicate matches the new purchase and sale lot.qt rows' saved = []