Files
tradon/modules/carrier_carriage/stock.py
2026-03-14 09:42:12 +00:00

258 lines
8.2 KiB
Python

# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.i18n import gettext
from trytond.model import (
ModelSQL, ModelView, Workflow, fields, sequence_ordered)
from trytond.model.exceptions import AccessError
from trytond.modules.stock_shipment_cost import ShipmentCostMixin
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
try:
from trytond.modules.sale_shipment_cost import ShipmentCostSaleMixin
except ImportError:
ShipmentCostSaleMixin = object
class Carriage(sequence_ordered(), ShipmentCostMixin, ModelSQL, ModelView):
__name__ = 'stock.shipment.carriage'
_states = {
'readonly': Eval('shipment_cost_readonly', True),
}
shipment = fields.Reference(
"Shipment", selection='get_shipments', required=True, states=_states)
type = fields.Selection([
('before', "Before"),
('after', "After"),
], "Type", sort=False, required=True, states=_states)
from_ = fields.Many2One('party.address', "From", states=_states)
to = fields.Many2One('party.address', "To", states=_states)
company = fields.Function(
fields.Many2One('company.company', "Company"),
'on_change_with_company')
del _states
@classmethod
def __setup__(cls):
super().__setup__()
cls.carrier.required = True
@classmethod
def __register__(cls, module):
table_h = cls.__table_handler__(module)
# Migration from 7.2: use suffix sale
table_h.column_rename('cost_method', 'cost_sale_method')
table_h.column_rename('cost_invoice_line', 'cost_sale_invoice_line')
super().__register__(module)
@classmethod
def get_shipments(cls):
pool = Pool()
IrModel = pool.get('ir.model')
get_name = IrModel.get_name
models = cls._get_shipments()
return [(m, get_name(m)) for m in models]
@classmethod
def _get_shipments(cls):
return [
'stock.shipment.out',
'stock.shipment.out.return',
]
@fields.depends('shipment')
def on_change_with_shipment_cost_readonly(self, name=None):
pool = Pool()
ShipmentOut = pool.get('stock.shipment.out')
ShipmentOutReturn = pool.get('stock.shipment.out.return')
if isinstance(self.shipment, (ShipmentOut, ShipmentOutReturn)):
return self.shipment.state in {'done', 'cancelled'}
@fields.depends('shipment')
def on_change_with_company(self, name=None):
return self.shipment.company if self.shipment else None
def get_rec_name(self, name):
return f'{self.carrier.rec_name} @ {self.shipment.rec_name}'
@classmethod
def check_modification(cls, mode, carriages, values=None, external=False):
super().check_modification(
mode, carriages, values=values, external=external)
if mode == 'delete':
for carriage in carriages:
if carriage.shipment_cost_readonly:
raise AccessError(gettext(
'carrier_carriages.msg_shipment_carriage_delete',
carriage=carriage.rec_name))
class _ShipmentMixin:
__slots__ = ()
_states = {
'readonly': Eval('shipment_cost_readonly', True),
}
carriages = fields.One2Many(
'stock.shipment.carriage', 'shipment', "Carriages", readonly=True)
before_carriages = fields.One2Many(
'stock.shipment.carriage', 'shipment', "Before Carriages",
filter=[
('type', '=', 'before'),
],
states=_states,
help="Carriages before the main carrier.")
after_carriages = fields.One2Many(
'stock.shipment.carriage', 'shipment', "After Carriages",
filter=[
('type', '=', 'after'),
],
states=_states,
help="Carriages after the main carrier.")
del _states
def _get_shipment_cost(self):
cost = super()._get_shipment_cost()
for carriage in self.carriages:
carriage_cost = carriage._get_shipment_cost()
if carriage_cost:
cost += carriage_cost
return cost
@classmethod
def on_delete(cls, shipments):
pool = Pool()
Carriage = pool.get('stock.shipment.carriage')
callback = super().on_delete(shipments)
carriages = sum((s.carriages for s in shipments), ())
if carriages:
callback.append(lambda: Carriage.delete(carriages))
return callback
@classmethod
def copy(cls, shipments, default=None):
if default is None:
default = {}
else:
default = default.copy()
default.setdefault('before_carriages')
default.setdefault('after_carriages')
return super().copy(shipments, default=default)
class ShipmentCostSale(metaclass=PoolMeta):
__name__ = 'stock.shipment.cost_sale'
@classmethod
def __setup__(cls):
super().__setup__()
cls.shipment.selection.append(('stock.shipment.carriage', "Carriage"))
class Carriage_Sale(ShipmentCostSaleMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.carriage'
@fields.depends('shipment')
def on_change_with_shipment_cost_sale_readonly(self, name=None):
pool = Pool()
ShipmentOut = pool.get('stock.shipment.out')
if isinstance(self.shipment, ShipmentOut):
return self.shipment.shipment_cost_readonly
@property
def _shipment_cost_currency_date(self):
return self.shipment.effective_date
def get_cost_sale_invoice_line(self, invoice, origin=None):
invoice_line = super().get_cost_sale_invoice_line(
invoice, origin=origin)
if invoice_line:
invoice_line.cost_sale_shipment_carriages = [self]
return invoice_line
@classmethod
def from_sale(cls, carriage):
return cls(
sequence=carriage.sequence,
type=carriage.type,
carrier=carriage.carrier,
cost_sale_method=carriage.cost_method,
from_=carriage.from_,
to=carriage.to,
)
class _ShipmentOutMixin(_ShipmentMixin):
@classmethod
@ModelView.button
@Workflow.transition('done')
def do(cls, shipments):
pool = Pool()
Carriage = pool.get('stock.shipment.carriage')
has_cost_sale = hasattr(Carriage, 'cost_sale')
carriages = []
for shipment in shipments:
for carriage in shipment.carriages:
carriage.cost = carriage.cost_used
carriage.cost_currency = carriage.cost_currency_used
if has_cost_sale:
carriage.cost_sale = carriage.cost_sale_used
carriage.cost_sale_currency = (
carriage.cost_sale_currency_used)
carriages.append(carriage)
Carriage.save(carriages)
super().do(shipments)
class ShipmentOut(_ShipmentOutMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.out'
class ShipmentOutReturn(_ShipmentOutMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.out.return'
class Carriage_Purchase(metaclass=PoolMeta):
__name__ = 'stock.shipment.carriage'
@classmethod
def _get_shipments(cls):
return super()._get_shipments() + ['stock.shipment.in']
@fields.depends('shipment')
def on_change_with_shipment_cost_readonly(self, name=None):
pool = Pool()
ShipmentIn = pool.get('stock.shipment.in')
readonly = super().on_change_with_shipment_cost_readonly(name=name)
if isinstance(self.shipment, ShipmentIn):
readonly = self.shipment.state != 'draft'
return readonly
class ShipmentIn(_ShipmentMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.in'
@classmethod
@ModelView.button
@Workflow.transition('received')
def receive(cls, shipments):
pool = Pool()
Carriage = pool.get('stock.shipment.carriage')
carriages = []
for shipment in shipments:
for carriage in shipment.carriages:
carriage.cost = carriage.cost_used
carriage.cost_currency = carriage.cost_currency_used
Carriage.save(carriages)
super().receive(shipments)