CreateContract
This commit is contained in:
@@ -4386,17 +4386,31 @@ class ContractDetail(ModelView):
|
||||
return getattr(line.purchase.currency if lqt.lot_p else line.sale.currency, 'id', None)
|
||||
|
||||
@classmethod
|
||||
def default_unit(cls):
|
||||
lqt = cls._get_lqt_from_context()
|
||||
if not lqt:
|
||||
return
|
||||
line = lqt.lot_p.line if lqt.lot_p else lqt.lot_s.sale_line
|
||||
if getattr(line, 'enable_linked_currency', False):
|
||||
return line.linked_unit.id
|
||||
return getattr(line.unit, 'id', None)
|
||||
|
||||
@classmethod
|
||||
def default_tol_min(cls):
|
||||
def default_unit(cls):
|
||||
lqt = cls._get_lqt_from_context()
|
||||
if not lqt:
|
||||
return
|
||||
line = lqt.lot_p.line if lqt.lot_p else lqt.lot_s.sale_line
|
||||
if getattr(line, 'enable_linked_currency', False):
|
||||
return line.linked_unit.id
|
||||
return getattr(line.unit, 'id', None)
|
||||
|
||||
@classmethod
|
||||
def default_currency_unit(cls):
|
||||
lqt = cls._get_lqt_from_context()
|
||||
if not lqt:
|
||||
return
|
||||
line = lqt.lot_p.line if lqt.lot_p else lqt.lot_s.sale_line
|
||||
if getattr(line, 'enable_linked_currency', False):
|
||||
return "0_%s" % line.linked_unit.id
|
||||
contract = line.purchase if lqt.lot_p else line.sale
|
||||
currency = getattr(contract, 'currency', None)
|
||||
unit = getattr(line, 'unit', None)
|
||||
if currency and unit:
|
||||
return "%s_%s" % (currency.id, unit.id)
|
||||
|
||||
@classmethod
|
||||
def default_tol_min(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_min', None) if lqt else None
|
||||
|
||||
|
||||
@@ -46,16 +46,19 @@ class ContractFactory:
|
||||
contract = Purchase() if type_ == 'Purchase' else Sale()
|
||||
|
||||
# ---------- CONTRACT ----------
|
||||
parts = c.currency_unit.split("_")
|
||||
parts = cls._get_currency_unit_parts(c, base_contract)
|
||||
contract.currency = int(parts[0]) or 1
|
||||
contract.party = c.party
|
||||
contract.crop = cls._get_crop(c, base_contract)
|
||||
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.payment_term = cls._get_payment_term(
|
||||
c, base_contract, type_)
|
||||
contract.reference = c.reference
|
||||
contract.from_location = c.from_location
|
||||
contract.to_location = c.to_location
|
||||
from_location, to_location = cls._get_locations(
|
||||
c, base_contract, type_)
|
||||
contract.from_location = from_location
|
||||
contract.to_location = to_location
|
||||
context = Transaction().context
|
||||
contract.company = context.get('company') if context else None
|
||||
if type_ == 'Purchase':
|
||||
@@ -63,18 +66,18 @@ class ContractFactory:
|
||||
else:
|
||||
contract.sale_date = Date.today()
|
||||
|
||||
cls._apply_locations(contract, base_contract, type_)
|
||||
cls._apply_party_data(contract, c.party, type_)
|
||||
cls._apply_payment_term(contract, c.party, type_)
|
||||
cls._apply_party_data(contract, c.party, base_contract, type_)
|
||||
if type_ == 'Sale':
|
||||
contract.product_origin = getattr(base_contract, 'product_origin', None)
|
||||
|
||||
contract.incoterm = c.incoterm
|
||||
contract.incoterm = cls._get_contract_value(
|
||||
c, base_contract, 'incoterm')
|
||||
|
||||
if c.party.addresses:
|
||||
contract.invoice_address = c.party.addresses[0]
|
||||
addresses = getattr(c.party, 'addresses', None)
|
||||
if addresses:
|
||||
contract.invoice_address = addresses[0]
|
||||
if type_ == 'Sale':
|
||||
contract.shipment_address = c.party.addresses[0]
|
||||
contract.shipment_address = addresses[0]
|
||||
|
||||
contract.save()
|
||||
|
||||
@@ -147,19 +150,74 @@ class ContractFactory:
|
||||
return to_location, None
|
||||
return None, None
|
||||
|
||||
@staticmethod
|
||||
def _apply_party_data(contract, party, type_):
|
||||
if party.wb:
|
||||
contract.wb = party.wb
|
||||
if party.association:
|
||||
contract.association = party.association
|
||||
@classmethod
|
||||
def _get_locations(cls, contract_detail, base, type_):
|
||||
mirror_from, mirror_to = cls._get_mirror_locations(base, type_)
|
||||
return (
|
||||
getattr(contract_detail, 'from_location', None)
|
||||
or mirror_from
|
||||
or getattr(base, 'from_location', None),
|
||||
getattr(contract_detail, 'to_location', None)
|
||||
or mirror_to
|
||||
or getattr(base, 'to_location', None),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _apply_party_data(cls, contract, party, base, type_):
|
||||
Contract = Pool().get(
|
||||
'purchase.purchase' if type_ == 'Purchase' else 'sale.sale')
|
||||
contract.wb = cls._get_header_value(
|
||||
'wb', party, base, Contract.default_wb)
|
||||
contract.association = cls._get_header_value(
|
||||
'association', party, base, Contract.default_association)
|
||||
contract.certif = cls._get_header_value(
|
||||
'certif', party, base, Contract.default_certif)
|
||||
|
||||
@staticmethod
|
||||
def _apply_payment_term(contract, party, type_):
|
||||
if type_ == 'Purchase' and party.supplier_payment_term:
|
||||
contract.payment_term = party.supplier_payment_term
|
||||
elif type_ == 'Sale' and party.customer_payment_term:
|
||||
contract.payment_term = party.customer_payment_term
|
||||
def _get_header_value(field, party, base, default_getter=None):
|
||||
value = getattr(party, field, None)
|
||||
if value:
|
||||
return value
|
||||
value = getattr(base, field, None)
|
||||
if value:
|
||||
return value
|
||||
if default_getter:
|
||||
return default_getter()
|
||||
|
||||
@staticmethod
|
||||
def _get_payment_term(contract_detail, base, type_):
|
||||
value = getattr(contract_detail, 'payment_term', None)
|
||||
if value:
|
||||
return value
|
||||
party = getattr(contract_detail, 'party', None)
|
||||
field = (
|
||||
'supplier_payment_term'
|
||||
if type_ == 'Purchase' else 'customer_payment_term')
|
||||
value = getattr(party, field, None)
|
||||
if value:
|
||||
return value
|
||||
return getattr(base, 'payment_term', None)
|
||||
|
||||
@staticmethod
|
||||
def _get_contract_value(contract_detail, base, field):
|
||||
return (
|
||||
getattr(contract_detail, field, None)
|
||||
or getattr(base, field, None))
|
||||
|
||||
@staticmethod
|
||||
def _get_currency_unit_parts(contract_detail, base):
|
||||
value = getattr(contract_detail, 'currency_unit', None)
|
||||
if value:
|
||||
return value.split("_")
|
||||
currency = (
|
||||
getattr(contract_detail, 'currency', None)
|
||||
or getattr(base, 'currency', None))
|
||||
unit = getattr(contract_detail, 'unit', None)
|
||||
currency_id = getattr(currency, 'id', currency)
|
||||
unit_id = getattr(unit, 'id', unit)
|
||||
if currency_id and unit_id:
|
||||
return [str(currency_id), str(unit_id)]
|
||||
return ["1", str(unit_id or 1)]
|
||||
|
||||
@staticmethod
|
||||
def _apply_price(line, c, parts):
|
||||
|
||||
@@ -2786,6 +2786,65 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
ContractFactory._get_crop(contract_detail, base_contract),
|
||||
crop)
|
||||
|
||||
def test_contract_factory_locations_fallback_to_source_contract(self):
|
||||
'create contracts keeps required locations when wizard line is empty'
|
||||
source_from = Mock(type='supplier')
|
||||
source_to = Mock(type='storage')
|
||||
contract_detail = Mock(from_location=None, to_location=None)
|
||||
base_contract = Mock(
|
||||
from_location=source_from, to_location=source_to)
|
||||
|
||||
from_location, to_location = ContractFactory._get_locations(
|
||||
contract_detail, base_contract, 'Sale')
|
||||
|
||||
self.assertEqual(from_location, source_to)
|
||||
self.assertEqual(to_location, source_to)
|
||||
|
||||
def test_contract_factory_required_header_fields_fallback_to_defaults(self):
|
||||
'create contracts fills required header fields outside the normal form'
|
||||
contract = Mock()
|
||||
party = Mock(wb=None, association=None, certif=None)
|
||||
base_contract = Mock(wb=None, association=None, certif=None)
|
||||
Contract = Mock()
|
||||
Contract.default_wb.return_value = 1
|
||||
Contract.default_association.return_value = 2
|
||||
Contract.default_certif.return_value = 3
|
||||
|
||||
with patch('trytond.modules.purchase_trade.service.Pool') as PoolMock:
|
||||
PoolMock.return_value.get.return_value = Contract
|
||||
|
||||
ContractFactory._apply_party_data(
|
||||
contract, party, base_contract, 'Purchase')
|
||||
|
||||
self.assertEqual(contract.wb, 1)
|
||||
self.assertEqual(contract.association, 2)
|
||||
self.assertEqual(contract.certif, 3)
|
||||
|
||||
def test_contract_factory_incoterm_fallback_to_source_contract(self):
|
||||
'create contracts keeps required incoterm when wizard line is empty'
|
||||
incoterm = Mock()
|
||||
contract_detail = Mock(incoterm=None)
|
||||
base_contract = Mock(incoterm=incoterm)
|
||||
|
||||
self.assertEqual(
|
||||
ContractFactory._get_contract_value(
|
||||
contract_detail, base_contract, 'incoterm'),
|
||||
incoterm)
|
||||
|
||||
def test_contract_factory_currency_unit_fallback_to_hidden_defaults(self):
|
||||
'create contracts can price even when currency/unit selector is empty'
|
||||
contract_detail = Mock(
|
||||
currency_unit=None,
|
||||
currency=Mock(id=7),
|
||||
unit=Mock(id=9),
|
||||
)
|
||||
base_contract = Mock(currency=Mock(id=3))
|
||||
|
||||
self.assertEqual(
|
||||
ContractFactory._get_currency_unit_parts(
|
||||
contract_detail, base_contract),
|
||||
['7', '9'])
|
||||
|
||||
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')
|
||||
|
||||
Reference in New Issue
Block a user