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 @@
-
-