Create contract detail

This commit is contained in:
2026-05-20 08:45:27 +02:00
parent 133ca49eda
commit c3d768d5a8
4 changed files with 55 additions and 16 deletions

View File

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

View File

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

View File

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

View File

@@ -6,8 +6,6 @@
<!-- <field name="unit"/> -->
<field name="quantity"/>
<field name="qt_unit"/>
<field name="tol_min"/>
<field name="tol_max"/>
<field name="price_type"/>
<field name="from_location"/>
<field name="to_location"/>
@@ -15,8 +13,6 @@
<field name="incoterm"/>
<field name="crop"/>
<field name="del_period"/>
<field name="from_del"/>
<field name="to_del"/>
<field name="category" tree_invisible="1"/>
<field name="company_visible" tree_invisible="1"/>
</tree>