Create contract detail
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user