diff --git a/modules/purchase_trade/lot.py b/modules/purchase_trade/lot.py index 2fdd0a6..408ffb0 100755 --- a/modules/purchase_trade/lot.py +++ b/modules/purchase_trade/lot.py @@ -4284,8 +4284,8 @@ class ContractDetail(ModelView): quantity = fields.Numeric("Quantity",digits=(1,5), required=True) unit = fields.Many2One('product.uom',"Unit", required=True) qt_unit = fields.Many2One('product.uom',"Unit") - tol_min = fields.Numeric("Tol - in %", required=True) - tol_max = fields.Numeric("Tol + in %", required=True) + tol_min = fields.Numeric("Tol - in %") + tol_max = fields.Numeric("Tol + in %") crop = fields.Many2One( 'purchase.crop', "Crop", states={'invisible': Eval('company_visible')}) @@ -4400,12 +4400,18 @@ class ContractDetail(ModelView): lqt = cls._get_lqt_from_context() return getattr(lqt.lot_p.line.purchase if lqt.lot_p else lqt.lot_s.sale_line.sale, 'tol_min', None) if lqt else None - @classmethod - def default_tol_max(cls): - lqt = cls._get_lqt_from_context() - return getattr(lqt.lot_p.line.purchase if lqt.lot_p else lqt.lot_s.sale_line.sale, 'tol_max', None) if lqt else None - - @classmethod + @classmethod + def default_tol_max(cls): + lqt = cls._get_lqt_from_context() + return getattr(lqt.lot_p.line.purchase if lqt.lot_p else lqt.lot_s.sale_line.sale, 'tol_max', None) if lqt else None + + @fields.depends('party', '_parent_party.tol_min', '_parent_party.tol_max') + def on_change_party(self): + if self.party: + self.tol_min = self.party.tol_min + self.tol_max = self.party.tol_max + + @classmethod def default_del_period(cls): lqt = cls._get_lqt_from_context() if lqt and getattr(lqt.lot_p.line.purchase if lqt.lot_p else lqt.lot_s.sale_line.sale, 'del_period', None): diff --git a/modules/purchase_trade/service.py b/modules/purchase_trade/service.py index 236abb6..ef7cbdc 100644 --- a/modules/purchase_trade/service.py +++ b/modules/purchase_trade/service.py @@ -50,8 +50,8 @@ class ContractFactory: contract.currency = int(parts[0]) or 1 contract.party = c.party contract.crop = c.crop - contract.tol_min = c.tol_min - contract.tol_max = c.tol_max + contract.tol_min = cls._get_tolerance(c, 'tol_min') + contract.tol_max = cls._get_tolerance(c, 'tol_max') contract.payment_term = c.payment_term contract.reference = c.reference contract.from_location = c.from_location @@ -181,8 +181,21 @@ class ContractFactory: line.to_del = getattr(source_line, 'to_del', None) return line.del_period = c.del_period - line.from_del = c.from_del - line.to_del = c.to_del + line.from_del = ( + c.from_del + or getattr(getattr(c, 'del_period', None), 'beg_date', None)) + line.to_del = ( + c.to_del + or getattr(getattr(c, 'del_period', None), 'end_date', None)) + + @staticmethod + def _get_tolerance(contract_detail, field): + value = getattr(contract_detail, field, None) + if value is not None: + return value + party = getattr(contract_detail, 'party', None) + value = getattr(party, field, None) + return value if value is not None else Decimal(0) @staticmethod def _normalize_quantity(quantity): diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index 01c7aac..8737c1b 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -2707,6 +2707,30 @@ class PurchaseTradeTestCase(ModuleTestCase): with self.assertRaises(UserError): ContractFactory._validate_requested_quantity(contracts, sources, ct) + def test_contract_factory_uses_party_tolerance_when_line_is_empty(self): + 'create contracts falls back to counterparty tolerance' + party = Mock(tol_min=Decimal('2'), tol_max=Decimal('5')) + contract_detail = Mock(party=party, tol_min=None, tol_max=None) + + self.assertEqual( + ContractFactory._get_tolerance(contract_detail, 'tol_min'), + Decimal('2')) + self.assertEqual( + ContractFactory._get_tolerance(contract_detail, 'tol_max'), + Decimal('5')) + + def test_contract_factory_delivery_dates_fallback_to_period(self): + 'hidden delivery dates are still derived from delivery period' + period = Mock(beg_date='2026-05-01', end_date='2026-05-31') + contract_detail = Mock( + del_period=period, from_del=None, to_del=None) + line = Mock() + + ContractFactory._apply_delivery(line, contract_detail, {}) + + self.assertEqual(line.from_del, '2026-05-01') + self.assertEqual(line.to_del, '2026-05-31') + def test_lot_matching_rejects_purchase_quantity_above_available(self): 'apply matching cannot consume more than available purchase quantity' class LotQtMock: diff --git a/modules/purchase_trade/view/contract_detail_tree.xml b/modules/purchase_trade/view/contract_detail_tree.xml index 205f48d..67b318f 100755 --- a/modules/purchase_trade/view/contract_detail_tree.xml +++ b/modules/purchase_trade/view/contract_detail_tree.xml @@ -6,8 +6,6 @@ - - @@ -15,8 +13,6 @@ - -