Delivery period changed into Shipment period

This commit is contained in:
2026-06-13 11:04:13 +02:00
parent 77b1ab333b
commit ec90d19cc7
10 changed files with 288 additions and 51 deletions

View File

@@ -0,0 +1,50 @@
from trytond.pool import Pool
from trytond.transaction import Transaction
ITSA_COMPANY_NAME = 'ITSA'
def record_id(record):
return getattr(record, 'id', record)
def is_itsa_company(company=None):
if company is None:
company_id = Transaction().context.get('company')
if not company_id:
return False
Company = Pool().get('company.company')
company = Company(company_id)
party = getattr(company, 'party', None)
return bool(party and party.name == ITSA_COMPANY_NAME)
def _search_first(model_name, domains):
Model = Pool().get(model_name)
for domain in domains:
try:
records = Model.search(domain, limit=1)
except Exception:
continue
if records:
return records[0]
def default_itsa_currency():
currency = _search_first('currency.currency', [
[('code', '=', 'USD')],
[('name', '=', 'USD')],
[('symbol', '=', 'USD')],
])
return record_id(currency) if currency else None
def default_itsa_unit():
unit = _search_first('product.uom', [
[('symbol', '=', 'Mt')],
[('name', '=', 'Mt')],
[('symbol', '=', 'MT')],
[('name', '=', 'MT')],
])
return record_id(unit) if unit else None

View File

@@ -1186,7 +1186,7 @@ class CTRMContractPerformanceContext(ModelView):
], "Side") ], "Side")
product = fields.Many2One('product.product', "Product") product = fields.Many2One('product.product', "Product")
counterparty = fields.Many2One('party.party', "Counterparty") counterparty = fields.Many2One('party.party', "Counterparty")
delivery_period = fields.Many2One('product.month', "Delivery Period") delivery_period = fields.Many2One('product.month', "Shipment Period")
status = fields.Selection([ status = fields.Selection([
(None, ''), (None, ''),
('under', 'Under delivery'), ('under', 'Under delivery'),
@@ -1210,7 +1210,7 @@ class CTRMContractPerformance(ModelSQL, ModelView):
sale_line = fields.Many2One('sale.line', "Sale Line") sale_line = fields.Many2One('sale.line', "Sale Line")
counterparty = fields.Many2One('party.party', "Counterparty") counterparty = fields.Many2One('party.party', "Counterparty")
product = fields.Many2One('product.product', "Product") product = fields.Many2One('product.product', "Product")
delivery_period = fields.Many2One('product.month', "Delivery Period") delivery_period = fields.Many2One('product.month', "Shipment Period")
from_date = fields.Date("From") from_date = fields.Date("From")
to_date = fields.Date("To") to_date = fields.Date("To")
contract_quantity = fields.Numeric("Contract Quantity", digits=(16, 5)) contract_quantity = fields.Numeric("Contract Quantity", digits=(16, 5))
@@ -1453,7 +1453,7 @@ class CTRMScheduling(ModelSQL, ModelView):
warehouse = fields.Many2One('stock.location', "Warehouse") warehouse = fields.Many2One('stock.location', "Warehouse")
from_location = fields.Many2One('stock.location', "From") from_location = fields.Many2One('stock.location', "From")
to_location = fields.Many2One('stock.location', "To") to_location = fields.Many2One('stock.location', "To")
delivery_period = fields.Many2One('product.month', "Delivery Period") delivery_period = fields.Many2One('product.month', "Shipment Period")
contract_from = fields.Date("Contract From") contract_from = fields.Date("Contract From")
contract_to = fields.Date("Contract To") contract_to = fields.Date("Contract To")
scheduled_date = fields.Date("Scheduled Date") scheduled_date = fields.Date("Scheduled Date")

View File

@@ -19,6 +19,8 @@ import logging
from collections import defaultdict from collections import defaultdict
from trytond.exceptions import UserWarning, UserError from trytond.exceptions import UserWarning, UserError
from trytond.modules.account.exceptions import PeriodNotFoundError from trytond.modules.account.exceptions import PeriodNotFoundError
from trytond.modules.purchase_trade.company_defaults import (
default_itsa_currency, default_itsa_unit, is_itsa_company)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -106,6 +108,20 @@ class Fee(ModelSQL,ModelView):
Date = Pool().get('ir.date') Date = Pool().get('ir.date')
return Date.today() return Date.today()
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
@classmethod
def default_unit(cls):
if is_itsa_company():
unit = default_itsa_unit()
if unit:
return unit
@classmethod @classmethod
def default_generated_by_rule(cls): def default_generated_by_rule(cls):
return False return False
@@ -1056,6 +1072,20 @@ class FeeRule(ModelSQL, ModelView):
def default_weight_type(cls): def default_weight_type(cls):
return 'brut' return 'brut'
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
@classmethod
def default_unit(cls):
if is_itsa_company():
unit = default_itsa_unit()
if unit:
return unit
@staticmethod @staticmethod
def _same_record(left, right): def _same_record(left, right):
return bool( return bool(

View File

@@ -22,6 +22,8 @@ import json
import logging import logging
from trytond.exceptions import UserWarning, UserError from trytond.exceptions import UserWarning, UserError
from trytond.modules.purchase_trade.service import ContractFactory from trytond.modules.purchase_trade.service import ContractFactory
from trytond.modules.purchase_trade.company_defaults import (
default_itsa_unit, is_itsa_company)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -290,6 +292,22 @@ class Lot(metaclass=PoolMeta):
or self.planned_to_date or self.planned_to_date
or self.planned_note) or self.planned_note)
@classmethod
def default_lot_unit(cls):
if is_itsa_company():
return default_itsa_unit()
default = getattr(super(), 'default_lot_unit', None)
if default:
return default()
@classmethod
def default_lot_unit_line(cls):
if is_itsa_company():
return default_itsa_unit()
default = getattr(super(), 'default_lot_unit_line', None)
if default:
return default()
def get_pivot(self,name=None): def get_pivot(self,name=None):
AccountMoveLine = Pool().get('account.move.line') AccountMoveLine = Pool().get('account.move.line')
Account = Pool().get('account.account') Account = Pool().get('account.account')
@@ -2708,9 +2726,9 @@ class LotReport(
r_lot_price = fields.Function(fields.Numeric("Price", digits='r_lot_unit_line'),'get_lot_price') r_lot_price = fields.Function(fields.Numeric("Price", digits='r_lot_unit_line'),'get_lot_price')
r_lot_price_sale = fields.Function(fields.Numeric("Price", digits='r_lot_unit_line'),'get_lot_sale_price') r_lot_price_sale = fields.Function(fields.Numeric("Price", digits='r_lot_unit_line'),'get_lot_sale_price')
r_del_period = fields.Many2One( r_del_period = fields.Many2One(
'product.month', "Purchase Delivery Period") 'product.month', "Purchase Shipment Period")
r_sale_del_period = fields.Many2One( r_sale_del_period = fields.Many2One(
'product.month', "Sale Delivery Period") 'product.month', "Sale Shipment Period")
r_sale_line = fields.Many2One('sale.line',"S. line") r_sale_line = fields.Many2One('sale.line',"S. line")
r_sale = fields.Many2One('sale.sale',"Sale") r_sale = fields.Many2One('sale.sale',"Sale")
r_tot = fields.Numeric("Qt tot", digits='r_lot_unit_line') r_tot = fields.Numeric("Qt tot", digits='r_lot_unit_line')
@@ -4164,6 +4182,16 @@ class LotAddLine(ModelView):
lot_premium = fields.Numeric("Premium") lot_premium = fields.Numeric("Premium")
lot_chunk_key = fields.Integer("Chunk key") lot_chunk_key = fields.Integer("Chunk key")
@classmethod
def default_lot_unit(cls):
if is_itsa_company():
return default_itsa_unit()
@classmethod
def default_lot_unit_line(cls):
if is_itsa_company():
return default_itsa_unit()
# @fields.depends('lot_qt') # @fields.depends('lot_qt')
# def on_change_with_lot_quantity(self): # def on_change_with_lot_quantity(self):
# if not self.lot_quantity: # if not self.lot_quantity:
@@ -5049,7 +5077,7 @@ class ContractDetail(ModelView):
crop = fields.Many2One( crop = fields.Many2One(
'purchase.crop', "Crop", 'purchase.crop', "Crop",
states={'invisible': Eval('company_visible')}) states={'invisible': Eval('company_visible')})
del_period = fields.Many2One('product.month',"Delivery Period") del_period = fields.Many2One('product.month',"Shipment Period")
from_del = fields.Date("From") from_del = fields.Date("From")
to_del = fields.Date("To") to_del = fields.Date("To")
price = fields.Numeric("Price", required=True,digits=(1,4),states={'invisible': Eval('price_type') != 'priced'}) price = fields.Numeric("Price", required=True,digits=(1,4),states={'invisible': Eval('price_type') != 'priced'})

View File

@@ -24,6 +24,8 @@ import zipfile
from io import BytesIO from io import BytesIO
from xml.etree import ElementTree from xml.etree import ElementTree
from trytond.modules.purchase_trade.purchase import (TRIGGERS) from trytond.modules.purchase_trade.purchase import (TRIGGERS)
from trytond.modules.purchase_trade.company_defaults import (
default_itsa_currency, default_itsa_unit, is_itsa_company)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -590,6 +592,13 @@ class MtmStrategy(ModelSQL, ModelView):
def default_active(cls): def default_active(cls):
return True return True
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
def get_mtm(self,line,qty): def get_mtm(self,line,qty):
pool = Pool() pool = Pool()
Currency = pool.get('currency.currency') Currency = pool.get('currency.currency')
@@ -713,6 +722,13 @@ class Mtm(ModelSQL, ModelView):
def on_change_with_currency(self): def on_change_with_currency(self):
return self.get_cur() return self.get_cur()
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
class PriceMatrix(ModelSQL, ModelView): class PriceMatrix(ModelSQL, ModelView):
"Price Matrix" "Price Matrix"
__name__ = 'price.matrix' __name__ = 'price.matrix'
@@ -741,6 +757,20 @@ class PriceMatrix(ModelSQL, ModelView):
'price.matrix.line', 'matrix', "Lines" 'price.matrix.line', 'matrix', "Lines"
) )
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
@classmethod
def default_unit(cls):
if is_itsa_company():
unit = default_itsa_unit()
if unit:
return unit
class PriceMatrixLine(ModelSQL, ModelView): class PriceMatrixLine(ModelSQL, ModelView):
"Price Matrix Line" "Price Matrix Line"
__name__ = 'price.matrix.line' __name__ = 'price.matrix.line'
@@ -859,6 +889,13 @@ class Component(ModelSQL, ModelView):
if self.price_source_type == 'fixed': if self.price_source_type == 'fixed':
return self.fixed_currency return self.fixed_currency
@classmethod
def default_fixed_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
@classmethod @classmethod
def set_cur(cls, components, name, value): def set_cur(cls, components, name, value):
cls.write(components, {'fixed_currency': value}) cls.write(components, {'fixed_currency': value})

View File

@@ -25,6 +25,8 @@ import jwt
from collections import defaultdict from collections import defaultdict
from trytond.exceptions import UserWarning, UserError from trytond.exceptions import UserWarning, UserError
from trytond.modules.purchase_trade.numbers_to_words import quantity_to_words, amount_to_currency_words, format_date_en from trytond.modules.purchase_trade.numbers_to_words import quantity_to_words, amount_to_currency_words, format_date_en
from trytond.modules.purchase_trade.company_defaults import (
default_itsa_currency, default_itsa_unit, is_itsa_company, record_id)
import requests import requests
import io import io
@@ -323,7 +325,7 @@ class Purchase(metaclass=PoolMeta):
('efp', 'EFP'), ('efp', 'EFP'),
], "Price Type"), 'get_first_line_price_type') ], "Price Type"), 'get_first_line_price_type')
first_line_del_period = fields.Function( first_line_del_period = fields.Function(
fields.Many2One('product.month', "Delivery Period"), fields.Many2One('product.month', "Shipment Period"),
'get_first_line_del_period') 'get_first_line_del_period')
first_line_from_del = fields.Function( first_line_from_del = fields.Function(
fields.Date("Delivery From"), 'get_first_line_from_del') fields.Date("Delivery From"), 'get_first_line_from_del')
@@ -434,9 +436,29 @@ class Purchase(metaclass=PoolMeta):
@fields.depends('company', 'currency', 'our_bank_account', @fields.depends('company', 'currency', 'our_bank_account',
'_parent_company.party') '_parent_company.party')
def on_change_company(self): def on_change_company(self):
previous_currency = self.currency
super().on_change_company() super().on_change_company()
if (is_itsa_company(self.company)
and (not previous_currency
or record_id(self.currency)
== record_id(getattr(self.company, 'currency', None))
or record_id(previous_currency)
== record_id(getattr(self.company, 'currency', None)))):
currency = default_itsa_currency()
if currency:
self.currency = currency
self.our_bank_account = self._get_default_our_bank_account() self.our_bank_account = self._get_default_our_bank_account()
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
default = getattr(super(), 'default_currency', None)
if default:
return default()
@classmethod @classmethod
def default_wb(cls): def default_wb(cls):
WB = Pool().get('purchase.weight.basis') WB = Pool().get('purchase.weight.basis')
@@ -1831,7 +1853,7 @@ class Line(metaclass=PoolMeta):
to_del = values.get('to_del', getattr(line, 'to_del', None)) to_del = values.get('to_del', getattr(line, 'to_del', None))
if from_del and to_del and from_del > to_del: if from_del and to_del and from_del > to_del:
raise UserError( raise UserError(
"Delivery period From date must be before To date.") "Shipment period From date must be before To date.")
@classmethod @classmethod
def create(cls, vlist): def create(cls, vlist):
@@ -1852,7 +1874,7 @@ class Line(metaclass=PoolMeta):
def _check_delivery_period(self): def _check_delivery_period(self):
if self._has_invalid_delivery_period(self): if self._has_invalid_delivery_period(self):
raise UserError( raise UserError(
"Delivery period From date must be before To date.") "Shipment period From date must be before To date.")
@fields.depends('from_del', 'to_del') @fields.depends('from_del', 'to_del')
def on_change_from_del(self): def on_change_from_del(self):
@@ -1873,7 +1895,7 @@ class Line(metaclass=PoolMeta):
states={ states={
'invisible': Eval('price_type') != 'basis', 'invisible': Eval('price_type') != 'basis',
}),'get_progress') }),'get_progress')
del_period = fields.Many2One('product.month',"Delivery Period") del_period = fields.Many2One('product.month',"Shipment Period")
from_del = fields.Date("From") from_del = fields.Date("From")
to_del = fields.Date("To") to_del = fields.Date("To")
period_at = fields.Selection([ period_at = fields.Selection([
@@ -1948,6 +1970,30 @@ class Line(metaclass=PoolMeta):
fee_ = fields.Many2One('fee.fee',"Fee") fee_ = fields.Many2One('fee.fee',"Fee")
pricing_rule = fields.Text("Pricing description") pricing_rule = fields.Text("Pricing description")
@classmethod
def default_unit(cls):
if is_itsa_company():
unit = default_itsa_unit()
if unit:
return unit
default = getattr(super(), 'default_unit', None)
if default:
return default()
@fields.depends('product', 'unit', 'purchase',
'_parent_purchase.company', '_parent_purchase.company.party')
def on_change_product(self):
previous_unit = self.unit
parent_on_change = getattr(super(), 'on_change_product', None)
if parent_on_change:
parent_on_change()
if (self.purchase and is_itsa_company(self.purchase.company)
and (not previous_unit
or record_id(previous_unit) == default_itsa_unit())):
unit = default_itsa_unit()
if unit:
self.unit = unit
attributes = fields.Dict( attributes = fields.Dict(
'product.attribute', 'Attributes', 'product.attribute', 'Attributes',
domain=[ domain=[
@@ -2580,7 +2626,7 @@ class Line(metaclass=PoolMeta):
for line in lines: for line in lines:
if cls._has_invalid_delivery_period(line): if cls._has_invalid_delivery_period(line):
raise UserError( raise UserError(
"Delivery period From date must be before To date.") "Shipment period From date must be before To date.")
if line.price_components: if line.price_components:
for pc in line.price_components: for pc in line.price_components:
if pc.triggers: if pc.triggers:

View File

@@ -18,6 +18,8 @@ import json
from collections import defaultdict from collections import defaultdict
from trytond.exceptions import UserWarning, UserError from trytond.exceptions import UserWarning, UserError
from trytond.modules.purchase_trade.numbers_to_words import quantity_to_words, amount_to_currency_words, format_date_en from trytond.modules.purchase_trade.numbers_to_words import quantity_to_words, amount_to_currency_words, format_date_en
from trytond.modules.purchase_trade.company_defaults import (
default_itsa_currency, default_itsa_unit, is_itsa_company, record_id)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -378,9 +380,29 @@ class Sale(metaclass=PoolMeta):
@fields.depends('company', 'currency', 'our_bank_account', @fields.depends('company', 'currency', 'our_bank_account',
'_parent_company.party') '_parent_company.party')
def on_change_company(self): def on_change_company(self):
previous_currency = self.currency
super().on_change_company() super().on_change_company()
if (is_itsa_company(self.company)
and (not previous_currency
or record_id(self.currency)
== record_id(getattr(self.company, 'currency', None))
or record_id(previous_currency)
== record_id(getattr(self.company, 'currency', None)))):
currency = default_itsa_currency()
if currency:
self.currency = currency
self.our_bank_account = self._get_default_our_bank_account() self.our_bank_account = self._get_default_our_bank_account()
@classmethod
def default_currency(cls):
if is_itsa_company():
currency = default_itsa_currency()
if currency:
return currency
default = getattr(super(), 'default_currency', None)
if default:
return default()
@classmethod @classmethod
def default_wb(cls): def default_wb(cls):
WB = Pool().get('purchase.weight.basis') WB = Pool().get('purchase.weight.basis')
@@ -1564,6 +1586,30 @@ class SaleLine(metaclass=PoolMeta):
super().__setup__() super().__setup__()
cls.quantity.readonly = True cls.quantity.readonly = True
@classmethod
def default_unit(cls):
if is_itsa_company():
unit = default_itsa_unit()
if unit:
return unit
default = getattr(super(), 'default_unit', None)
if default:
return default()
@fields.depends('product', 'unit', 'sale',
'_parent_sale.company', '_parent_sale.company.party')
def on_change_product(self):
previous_unit = self.unit
parent_on_change = getattr(super(), 'on_change_product', None)
if parent_on_change:
parent_on_change()
if (self.sale and is_itsa_company(self.sale.company)
and (not previous_unit
or record_id(previous_unit) == default_itsa_unit())):
unit = default_itsa_unit()
if unit:
self.unit = unit
@staticmethod @staticmethod
def _is_empty_quantity(quantity): def _is_empty_quantity(quantity):
if quantity in (None, ''): if quantity in (None, ''):
@@ -1692,7 +1738,7 @@ class SaleLine(metaclass=PoolMeta):
to_del = values.get('to_del', getattr(line, 'to_del', None)) to_del = values.get('to_del', getattr(line, 'to_del', None))
if from_del and to_del and from_del > to_del: if from_del and to_del and from_del > to_del:
raise UserError( raise UserError(
"Delivery period From date must be before To date.") "Shipment period From date must be before To date.")
@classmethod @classmethod
def create(cls, vlist): def create(cls, vlist):
@@ -1713,7 +1759,7 @@ class SaleLine(metaclass=PoolMeta):
def _check_delivery_period(self): def _check_delivery_period(self):
if self._has_invalid_delivery_period(self): if self._has_invalid_delivery_period(self):
raise UserError( raise UserError(
"Delivery period From date must be before To date.") "Shipment period From date must be before To date.")
@fields.depends('from_del', 'to_del') @fields.depends('from_del', 'to_del')
def on_change_from_del(self): def on_change_from_del(self):
@@ -1723,7 +1769,7 @@ class SaleLine(metaclass=PoolMeta):
def on_change_to_del(self): def on_change_to_del(self):
self._check_delivery_period() self._check_delivery_period()
del_period = fields.Many2One('product.month',"Delivery Period") del_period = fields.Many2One('product.month',"Shipment Period")
lots = fields.One2Many('lot.lot','sale_line',"Lots",readonly=True) lots = fields.One2Many('lot.lot','sale_line',"Lots",readonly=True)
fees = fields.One2Many('fee.fee', 'sale_line', 'Fees') fees = fields.One2Many('fee.fee', 'sale_line', 'Fees')
quantity_theorical = fields.Numeric("Th. quantity", digits='unit', readonly=False) quantity_theorical = fields.Numeric("Th. quantity", digits='unit', readonly=False)
@@ -2580,7 +2626,7 @@ class SaleLine(metaclass=PoolMeta):
for line in salelines: for line in salelines:
if cls._has_invalid_delivery_period(line): if cls._has_invalid_delivery_period(line):
raise UserError( raise UserError(
"Delivery period From date must be before To date.") "Shipment period From date must be before To date.")
if line.price_components: if line.price_components:
for pc in line.price_components: for pc in line.price_components:
if pc.triggers: if pc.triggers:

View File

@@ -722,7 +722,7 @@ class ShipmentIn(metaclass=PoolMeta):
fields.One2Many('charter.condition', '', "Customer Conditions"), fields.One2Many('charter.condition', '', "Customer Conditions"),
'get_sale_charter_conditions') 'get_sale_charter_conditions')
sof = fields.One2Many('sof.statement', 'shipment',"Demurrage calculations") sof = fields.One2Many('sof.statement', 'shipment',"Demurrage calculations")
del_from = fields.Date("Delivery period from") del_from = fields.Date("Shipment period from")
del_to = fields.Date("to") del_to = fields.Date("to")
estimated_date = fields.One2Many('pricing.estimated','shipment_in',"Estimated date") estimated_date = fields.One2Many('pricing.estimated','shipment_in',"Estimated date")
carrier_ = fields.Many2One('party.party',"Carrier") carrier_ = fields.Many2One('party.party',"Carrier")

View File

@@ -1,8 +1,8 @@
<tree> <tree>
<field name="r_lot_type" widget="badge" badge_colors="virtual:#2563eb,physic:#8b5cf6" width="80"/> <field name="r_lot_type" widget="badge" badge_colors="virtual:#2563eb,physic:#8b5cf6" width="80"/>
<field name="r_lot_p" width="60"/> <field name="r_lot_p" width="60"/>
<field name="r_del_period" width="110"/> <field name="r_del_period" string="Purchase Sh. period" width="110"/>
<field name="r_sale_del_period" width="110"/> <field name="r_sale_del_period" string="Sale Sh. period" width="110"/>
<field name="r_supplier" width="90"/> <field name="r_supplier" width="90"/>
<field name="r_purchase" width="120"/> <field name="r_purchase" width="120"/>
<field name="r_lot_pur_inv" width="120"/> <field name="r_lot_pur_inv" width="120"/>

View File

@@ -13,7 +13,7 @@ this repository contains the full copyright notices and license terms. -->
badge_colors="priced:#16a34a,basis:#2563eb,efp:#8b5cf6,cash:#f59e0b" badge_colors="priced:#16a34a,basis:#2563eb,efp:#8b5cf6,cash:#f59e0b"
optional="0" optional="0"
width="100"/> width="100"/>
<field name="first_line_del_period" string="Delivery Period" optional="0"/> <field name="first_line_del_period" string="Shipment Period" optional="0"/>
<field name="first_line_from_del" string="Delivery From" optional="1"/> <field name="first_line_from_del" string="Delivery From" optional="1"/>
<field name="first_line_to_del" string="Delivery To" optional="1"/> <field name="first_line_to_del" string="Delivery To" optional="1"/>
</xpath> </xpath>