first commit
This commit is contained in:
717
modules/account_stock_eu/stock.py
Normal file
717
modules/account_stock_eu/stock.py
Normal file
@@ -0,0 +1,717 @@
|
||||
# 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 decimal import Decimal
|
||||
|
||||
from sql import Null
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import Index, ModelView, Workflow, fields
|
||||
from trytond.modules.account.exceptions import FiscalYearNotFoundError
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Eval
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .exceptions import CounterPartyNotFound, CountryNotFound
|
||||
|
||||
|
||||
class Move(metaclass=PoolMeta):
|
||||
__name__ = 'stock.move'
|
||||
|
||||
_states = {
|
||||
'required': Eval('intrastat_type') & (Eval('state') == 'done'),
|
||||
'invisible': ~Eval('intrastat_type'),
|
||||
}
|
||||
_states_dispatch = {
|
||||
'required': (
|
||||
(Eval('intrastat_type') == 'dispatch')
|
||||
& (Eval('state') == 'done')),
|
||||
'invisible': Eval('intrastat_type') != 'dispatch',
|
||||
}
|
||||
|
||||
intrastat_type = fields.Selection([
|
||||
(None, ""),
|
||||
('arrival', "Arrival"),
|
||||
('dispatch', "Dispatch"),
|
||||
], "Intrastat Type", sort=False, readonly=True)
|
||||
intrastat_warehouse_country = fields.Many2One(
|
||||
'country.country', "Intrastat Warehouse Country",
|
||||
ondelete='RESTRICT', states=_states)
|
||||
intrastat_country = fields.Many2One(
|
||||
'country.country', "Intrastat Country",
|
||||
ondelete='RESTRICT', states=_states)
|
||||
intrastat_subdivision = fields.Many2One(
|
||||
'country.subdivision', "Intrastat Subdivision",
|
||||
ondelete='RESTRICT',
|
||||
domain=[
|
||||
('country', '=', Eval('intrastat_warehouse_country', -1)),
|
||||
('intrastat_code', '!=', None),
|
||||
],
|
||||
states=_states)
|
||||
intrastat_tariff_code = fields.Many2One(
|
||||
'customs.tariff.code', "Intrastat Tariff Code",
|
||||
ondelete='RESTRICT', states=_states)
|
||||
intrastat_value = fields.Numeric(
|
||||
"Intrastat Value", digits=(None, 2), readonly=True, states=_states)
|
||||
intrastat_transaction = fields.Many2One(
|
||||
'account.stock.eu.intrastat.transaction', "Intrastat Transaction",
|
||||
ondelete='RESTRICT', states=_states)
|
||||
intrastat_additional_unit = fields.Float(
|
||||
"Intrastat Additional Unit", digits=(None, 3),
|
||||
states={
|
||||
'required': (
|
||||
_states['required'] & Eval('intrastat_tariff_code_uom')),
|
||||
'invisible': _states['invisible'],
|
||||
})
|
||||
intrastat_country_of_origin = fields.Many2One(
|
||||
'country.country', "Intrastat Country of Origin",
|
||||
ondelete='RESTRICT', states=_states_dispatch)
|
||||
intrastat_vat = fields.Many2One(
|
||||
'party.identifier', "Intrastat VAT",
|
||||
ondelete='RESTRICT',
|
||||
domain=[
|
||||
('type', '=', 'eu_vat'),
|
||||
],
|
||||
states={
|
||||
'invisible': _states_dispatch['invisible'],
|
||||
})
|
||||
intrastat_declaration = fields.Many2One(
|
||||
'account.stock.eu.intrastat.declaration', "Intrastat Declaration",
|
||||
readonly=True, states=_states, ondelete='RESTRICT',
|
||||
domain=[
|
||||
('company', '=', Eval('company', -1)),
|
||||
('country', '=', Eval('intrastat_warehouse_country', -1)),
|
||||
])
|
||||
|
||||
intrastat_tariff_code_uom = fields.Function(
|
||||
fields.Many2One('product.uom', "Intrastat Tariff Code Unit"),
|
||||
'on_change_with_intrastat_tariff_code_uom')
|
||||
|
||||
del _states, _states_dispatch
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
intrastat_required = Eval('intrastat_type') & (Eval('state') == 'done')
|
||||
weight_required = cls.internal_weight.states.get('required')
|
||||
if weight_required:
|
||||
weight_required |= intrastat_required
|
||||
else:
|
||||
weight_required = intrastat_required
|
||||
cls.internal_weight.states['required'] = weight_required
|
||||
|
||||
t = cls.__table__()
|
||||
cls._sql_indexes.add(
|
||||
Index(
|
||||
t,
|
||||
(t.intrastat_declaration, Index.Range()),
|
||||
(t.company, Index.Range()),
|
||||
where=(t.intrastat_type != Null) & (t.state == 'done')))
|
||||
|
||||
@fields.depends(
|
||||
'effective_date', 'planned_date',
|
||||
'from_location', 'to_location',
|
||||
methods=['intrastat_from_country', 'intrastat_to_country'])
|
||||
def on_change_with_intrastat_type(self):
|
||||
from_country = self.intrastat_from_country
|
||||
to_country = self.intrastat_to_country
|
||||
if (from_country != to_country
|
||||
and from_country and from_country.in_intrastat(
|
||||
date=self.effective_date or self.planned_date)
|
||||
and to_country and to_country.in_intrastat(
|
||||
date=self.effective_date or self.planned_date)):
|
||||
if self.from_location.type == 'storage' and self.from_warehouse:
|
||||
return 'dispatch'
|
||||
elif self.to_location.type == 'storage' and self.to_warehouse:
|
||||
return 'arrival'
|
||||
|
||||
@fields.depends('intrastat_tariff_code')
|
||||
def on_change_with_intrastat_tariff_code_uom(self, name=None):
|
||||
if self.intrastat_tariff_code:
|
||||
return self.intrastat_tariff_code.intrastat_uom
|
||||
|
||||
@property
|
||||
@fields.depends(
|
||||
'from_location', 'to_location', 'shipment',
|
||||
methods=['intrastat_to_country'])
|
||||
def intrastat_from_country(self):
|
||||
if self.from_location:
|
||||
if self.from_warehouse and self.from_warehouse.address:
|
||||
return self.from_warehouse.address.country
|
||||
elif (self.from_location.type in {'supplier', 'customer'}
|
||||
and hasattr(self.shipment, 'intrastat_from_country')):
|
||||
return self.shipment.intrastat_from_country
|
||||
elif self.from_location.type == 'lost_found':
|
||||
if (self.to_location
|
||||
and self.to_location.type != 'lost_found'):
|
||||
return self.intrastat_to_country
|
||||
|
||||
@property
|
||||
@fields.depends(
|
||||
'to_location', 'from_location', 'shipment',
|
||||
methods=['intrastat_from_country'])
|
||||
def intrastat_to_country(self):
|
||||
if self.to_location:
|
||||
if self.to_warehouse and self.to_warehouse.address:
|
||||
return self.to_warehouse.address.country
|
||||
elif (self.to_location.type in {'supplier', 'customer'}
|
||||
and hasattr(self.shipment, 'intrastat_to_country')):
|
||||
return self.shipment.intrastat_to_country
|
||||
elif self.to_location.type == 'lost_found':
|
||||
if (self.from_location
|
||||
and self.from_location.type != 'lost_found'):
|
||||
return self.intrastat_from_country
|
||||
|
||||
@classmethod
|
||||
def _reopen_intrastat(cls, moves):
|
||||
pool = Pool()
|
||||
IntrastatDeclaration = pool.get(
|
||||
'account.stock.eu.intrastat.declaration')
|
||||
declarations = {
|
||||
m.intrastat_declaration for m in moves
|
||||
if m.intrastat_declaration}
|
||||
if declarations:
|
||||
IntrastatDeclaration.open(
|
||||
IntrastatDeclaration.browse(declarations))
|
||||
|
||||
@classmethod
|
||||
def view_attributes(cls):
|
||||
return super().view_attributes() + [
|
||||
('//page[@id="intrastat"]', 'states', {
|
||||
'invisible': ~Eval('intrastat_type'),
|
||||
}),
|
||||
]
|
||||
|
||||
def compute_fields(self, field_names=None):
|
||||
cls = self.__class__
|
||||
values = super().compute_fields(field_names=field_names)
|
||||
if (self.state not in {'done', 'cancelled'}
|
||||
and (field_names is None
|
||||
or (cls.intrastat_type.on_change_with & field_names))):
|
||||
intrastat_type = self.on_change_with_intrastat_type()
|
||||
if getattr(self, 'intrastat_type', None) != intrastat_type:
|
||||
values['intrastat_type'] = intrastat_type
|
||||
if (field_names is None
|
||||
or (cls.intrastat_value.on_change_with & field_names)):
|
||||
intrastat_value = self.on_change_with_intrastat_value()
|
||||
if getattr(self, 'intrastat_value', None) != intrastat_value:
|
||||
values['intrastat_value'] = intrastat_value
|
||||
return values
|
||||
|
||||
@classmethod
|
||||
def on_write(cls, moves, values):
|
||||
callback = super().on_write(moves, values)
|
||||
callback.append(lambda: cls._reopen_intrastat(moves))
|
||||
if any(f.startswith('intrastat_') for f in values):
|
||||
cls._reopen_intrastat(moves)
|
||||
return callback
|
||||
|
||||
@classmethod
|
||||
def copy(cls, moves, default=None):
|
||||
default = default.copy() if default else {}
|
||||
default.setdefault('intrastat_type')
|
||||
default.setdefault('intrastat_warehouse_country')
|
||||
default.setdefault('intrastat_country')
|
||||
default.setdefault('intrastat_subdivision')
|
||||
default.setdefault('intrastat_tariff_code')
|
||||
default.setdefault('intrastat_value')
|
||||
default.setdefault('intrastat_transaction')
|
||||
default.setdefault('intrastat_additional_unit')
|
||||
default.setdefault('intrastat_country_of_origin')
|
||||
default.setdefault('intrastat_vat')
|
||||
default.setdefault('intrastat_declaration')
|
||||
return super().copy(moves, default=default)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('cancelled')
|
||||
def cancel(cls, moves):
|
||||
pool = Pool()
|
||||
IntrastatDeclaration = pool.get(
|
||||
'account.stock.eu.intrastat.declaration')
|
||||
super().cancel(moves)
|
||||
declarations = {
|
||||
m.intrastat_declaration for m in moves if m.intrastat_declaration}
|
||||
if declarations:
|
||||
IntrastatDeclaration.open(
|
||||
IntrastatDeclaration.browse(declarations))
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('done')
|
||||
def do(cls, moves):
|
||||
pool = Pool()
|
||||
Warning = pool.get('res.user.warning')
|
||||
unknown_country = []
|
||||
for move in moves:
|
||||
move._set_intrastat()
|
||||
if (move.intrastat_type
|
||||
and (not move.intrastat_from_country
|
||||
or not move.intrastat_to_country)):
|
||||
unknown_country.append(move)
|
||||
if unknown_country:
|
||||
warning_name = Warning.format(
|
||||
'intrastat_country', unknown_country)
|
||||
if Warning.check(warning_name):
|
||||
names = ', '.join(m.rec_name for m in unknown_country[:5])
|
||||
if len(unknown_country) > 5:
|
||||
names + '...'
|
||||
raise CountryNotFound(warning_name,
|
||||
gettext('account_stock_eu.msg_move_country_not_found',
|
||||
moves=names))
|
||||
cls.save(moves)
|
||||
super().do(moves)
|
||||
|
||||
def _set_intrastat(self):
|
||||
pool = Pool()
|
||||
IntrastatTransaction = pool.get(
|
||||
'account.stock.eu.intrastat.transaction')
|
||||
IntrastatDeclaration = pool.get(
|
||||
'account.stock.eu.intrastat.declaration')
|
||||
Warning = pool.get('res.user.warning')
|
||||
if not self.intrastat_type:
|
||||
return
|
||||
self.set_effective_date()
|
||||
self.intrastat_value = self.on_change_with_intrastat_value()
|
||||
if self.intrastat_type == 'arrival':
|
||||
if not self.intrastat_warehouse_country:
|
||||
self.intrastat_warehouse_country = self.intrastat_to_country
|
||||
if not self.intrastat_country:
|
||||
self.intrastat_country = self.intrastat_from_country
|
||||
if not self.intrastat_subdivision:
|
||||
if (self.to_warehouse
|
||||
and self.to_warehouse.address
|
||||
and self.to_warehouse.address.subdivision):
|
||||
subdivision = self.to_warehouse.address.subdivision
|
||||
self.intrastat_subdivision = subdivision.get_intrastat()
|
||||
if self.intrastat_country_of_origin:
|
||||
self.intrastat_country_of_origin = None
|
||||
if self.intrastat_vat:
|
||||
self.intrastat_vat = None
|
||||
elif self.intrastat_type == 'dispatch':
|
||||
if not self.intrastat_warehouse_country:
|
||||
self.intrastat_warehouse_country = self.intrastat_from_country
|
||||
if not self.intrastat_country:
|
||||
self.intrastat_country = self.intrastat_to_country
|
||||
if not self.intrastat_subdivision:
|
||||
if (self.from_warehouse
|
||||
and self.from_warehouse.address
|
||||
and self.from_warehouse.address.subdivision):
|
||||
subdivision = self.from_warehouse.address.subdivision
|
||||
self.intrastat_subdivision = subdivision.get_intrastat()
|
||||
if not self.intrastat_country_of_origin:
|
||||
self.intrastat_country_of_origin = (
|
||||
self.product.country_of_origin)
|
||||
if not self.intrastat_vat:
|
||||
counterparty = self._intrastat_counterparty()
|
||||
if not counterparty:
|
||||
warning_name = Warning.format(
|
||||
'intrastat_counterparty', [self])
|
||||
if Warning.check(warning_name):
|
||||
raise CounterPartyNotFound(warning_name,
|
||||
gettext('account_stock_eu'
|
||||
'.msg_move_counterparty_not_found',
|
||||
move=self.rec_name))
|
||||
else:
|
||||
fallback = None
|
||||
for identifier in counterparty.identifiers:
|
||||
if identifier.type == 'eu_vat':
|
||||
if not fallback:
|
||||
fallback = identifier
|
||||
if (self.intrastat_country
|
||||
and identifier.code.startswith(
|
||||
self.intrastat_country.code)):
|
||||
break
|
||||
else:
|
||||
identifier = fallback
|
||||
self.intrastat_vat = identifier
|
||||
if self.intrastat_warehouse_country:
|
||||
self.intrastat_declaration = IntrastatDeclaration.get(
|
||||
self.company,
|
||||
self.intrastat_warehouse_country,
|
||||
self.effective_date or self.planned_date)
|
||||
if not self.intrastat_tariff_code:
|
||||
self.intrastat_tariff_code = self.product.get_tariff_code(
|
||||
self._intrastat_tariff_code_pattern())
|
||||
if not self.intrastat_transaction:
|
||||
self.intrastat_transaction = IntrastatTransaction.get(
|
||||
self._intrastat_transaction_code())
|
||||
if (not self.intrastat_additional_unit
|
||||
and self.intrastat_tariff_code
|
||||
and self.intrastat_tariff_code.intrastat_uom):
|
||||
quantity = self._intrastat_quantity(
|
||||
self.intrastat_tariff_code.intrastat_uom)
|
||||
if quantity is not None:
|
||||
ndigits = self.__class__.intrastat_additional_unit.digits[1]
|
||||
self.intrastat_additional_unit = round(quantity, ndigits)
|
||||
|
||||
def _intrastat_tariff_code_pattern(self):
|
||||
return {
|
||||
'date': self.effective_date,
|
||||
'country': (
|
||||
self.intrastat_country.id if self.intrastat_country else None),
|
||||
}
|
||||
|
||||
def _intrastat_transaction_code(self):
|
||||
pool = Pool()
|
||||
ShipmentIn = pool.get('stock.shipment.in')
|
||||
ShipmentInReturn = pool.get('stock.shipment.in.return')
|
||||
ShipmentOut = pool.get('stock.shipment.out')
|
||||
ShipmentOutReturn = pool.get('stock.shipment.out.return')
|
||||
ShipmentInternal = pool.get('stock.shipment.internal')
|
||||
|
||||
if isinstance(self.shipment, ShipmentInternal):
|
||||
return '31'
|
||||
|
||||
try:
|
||||
SaleLine = pool.get('sale.line')
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if isinstance(self.origin, SaleLine):
|
||||
sale = self.origin.sale
|
||||
party = sale.invoice_party or sale.party
|
||||
if self.quantity >= 0:
|
||||
if party.tax_identifier:
|
||||
return '11'
|
||||
else:
|
||||
return '12'
|
||||
else:
|
||||
return '21'
|
||||
try:
|
||||
PurchaseLine = pool.get('purchase.line')
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if isinstance(self.origin, PurchaseLine):
|
||||
purchase = self.origin.purchase
|
||||
party = purchase.invoice_party or purchase.party
|
||||
if self.quantity >= 0:
|
||||
if party.tax_identifier:
|
||||
return '11'
|
||||
else:
|
||||
return '12'
|
||||
else:
|
||||
return '21'
|
||||
|
||||
if isinstance(self.shipment, ShipmentIn):
|
||||
if self.shipment.supplier.tax_identifier:
|
||||
return '11'
|
||||
else:
|
||||
return '12'
|
||||
elif isinstance(self.shipment, ShipmentInReturn):
|
||||
return '21'
|
||||
elif isinstance(self.shipment, ShipmentOut):
|
||||
if self.shipment.customer.tax_identifier:
|
||||
return '11'
|
||||
else:
|
||||
return '12'
|
||||
elif isinstance(self.shipment, ShipmentOutReturn):
|
||||
return '21'
|
||||
|
||||
@fields.depends(
|
||||
'state', 'unit_price', 'currency', 'quantity', 'effective_date',
|
||||
'planned_date', 'company')
|
||||
def on_change_with_intrastat_value(self):
|
||||
pool = Pool()
|
||||
Currency = pool.get('currency.currency')
|
||||
if self.state == 'done' and self.unit_price is not None:
|
||||
ndigits = self.__class__.intrastat_value.digits[1]
|
||||
with Transaction().set_context(
|
||||
date=self.effective_date or self.planned_date):
|
||||
return round(Currency.compute(
|
||||
self.currency,
|
||||
self.unit_price * Decimal(str(self.quantity)),
|
||||
self.company.intrastat_currency or self.currency,
|
||||
round=False), ndigits)
|
||||
|
||||
def _intrastat_quantity(self, unit):
|
||||
pool = Pool()
|
||||
UoM = pool.get('product.uom')
|
||||
if self.unit.category == unit.category:
|
||||
return UoM.compute_qty(self.unit, self.quantity, unit, round=False)
|
||||
elif (getattr(self, 'secondary_unit', None)
|
||||
and self.secondary_unit.category == unit.category):
|
||||
return UoM.compute_qty(
|
||||
self.secondary_unit, self.secondary_quantity, unit,
|
||||
round=False)
|
||||
if (self.product.volume
|
||||
and self.product.volume_uom.category == unit.category):
|
||||
return UoM.compute_qty(
|
||||
self.product.volume_uom,
|
||||
self.internal_quantity * self.product.volume,
|
||||
unit, round=False)
|
||||
|
||||
def _intrastat_counterparty(self):
|
||||
pool = Pool()
|
||||
ShipmentIn = pool.get('stock.shipment.in')
|
||||
ShipmentInReturn = pool.get('stock.shipment.in.return')
|
||||
ShipmentOut = pool.get('stock.shipment.out')
|
||||
ShipmentOutReturn = pool.get('stock.shipment.out.return')
|
||||
ShipmentInternal = pool.get('stock.shipment.internal')
|
||||
|
||||
if isinstance(self.shipment, ShipmentInternal):
|
||||
return self.company.party
|
||||
|
||||
try:
|
||||
SaleLine = pool.get('sale.line')
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if isinstance(self.origin, SaleLine):
|
||||
sale = self.origin.sale
|
||||
return sale.invoice_party or sale.party
|
||||
|
||||
try:
|
||||
PurchaseLine = pool.get('purchase.line')
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if isinstance(self.origin, PurchaseLine):
|
||||
purchase = self.origin.purchase
|
||||
return purchase.invoice_party or purchase.party
|
||||
|
||||
if isinstance(self.shipment, (ShipmentIn, ShipmentInReturn)):
|
||||
return self.shipment.supplier
|
||||
elif isinstance(self.shipment, (ShipmentOut, ShipmentOutReturn)):
|
||||
return self.shipment.customer
|
||||
|
||||
|
||||
class Move_Production(metaclass=PoolMeta):
|
||||
__name__ = 'stock.move'
|
||||
|
||||
@property
|
||||
@fields.depends('from_location', 'production')
|
||||
def intrastat_from_country(self):
|
||||
country = super().intrastat_from_country
|
||||
if self.from_location:
|
||||
if (self.from_location.type == 'production'
|
||||
and self.production
|
||||
and getattr(self.production, 'warehouse', None)
|
||||
and self.production.warehouse.address):
|
||||
country = self.production.warehouse.address.country
|
||||
return country
|
||||
|
||||
@property
|
||||
@fields.depends('to_location', 'production')
|
||||
def intrastat_to_country(self):
|
||||
country = super().intrastat_to_country
|
||||
if self.to_location:
|
||||
if (self.to_location.type == 'production'
|
||||
and self.production
|
||||
and getattr(self.production, 'warehouse', None)
|
||||
and self.production.warehouse.address):
|
||||
country = self.production.warehouse.address.country
|
||||
return country
|
||||
|
||||
|
||||
class Move_Incoterm(metaclass=PoolMeta):
|
||||
__name__ = 'stock.move'
|
||||
|
||||
_states = {
|
||||
'required': (
|
||||
Eval('intrastat_type') & Eval('intrastat_extended')
|
||||
& (Eval('state') == 'done')),
|
||||
'invisible': ~Eval('intrastat_type') | ~Eval('intrastat_extended'),
|
||||
}
|
||||
|
||||
intrastat_transport = fields.Many2One(
|
||||
'account.stock.eu.intrastat.transport', "Intrastat Transport",
|
||||
ondelete='RESTRICT', states=_states)
|
||||
intrastat_incoterm = fields.Many2One(
|
||||
'incoterm.incoterm', "Intrastat Incoterm",
|
||||
ondelete='RESTRICT', states=_states)
|
||||
|
||||
intrastat_extended = fields.Function(
|
||||
fields.Boolean("Intrastat Extended"),
|
||||
'on_change_with_intrastat_extended')
|
||||
|
||||
del _states
|
||||
|
||||
@fields.depends('company', 'effective_date', 'planned_date')
|
||||
def on_change_with_intrastat_extended(self, name=None):
|
||||
pool = Pool()
|
||||
FiscalYear = pool.get('account.fiscalyear')
|
||||
if self.company:
|
||||
try:
|
||||
fiscalyear = FiscalYear.find(
|
||||
self.company.id,
|
||||
date=self.effective_date or self.planned_date)
|
||||
except FiscalYearNotFoundError:
|
||||
pass
|
||||
else:
|
||||
return fiscalyear.intrastat_extended
|
||||
|
||||
def _set_intrastat(self):
|
||||
from trytond.modules.incoterm.common import IncotermMixin
|
||||
super()._set_intrastat()
|
||||
|
||||
if not self.intrastat_transport:
|
||||
carrier = self._intrastat_carrier()
|
||||
if carrier:
|
||||
self.intrastat_transport = carrier.intrastat_transport
|
||||
|
||||
if not self.intrastat_incoterm:
|
||||
if isinstance(self.shipment, IncotermMixin):
|
||||
self.intrastat_incoterm = self.shipment.incoterm
|
||||
elif isinstance(self.origin, IncotermMixin):
|
||||
self.intrastat_incoterm = self.origin.incoterm
|
||||
|
||||
def _intrastat_carrier(self):
|
||||
if (hasattr(self.shipment, 'carrier')
|
||||
and not getattr(self.shipment, 'carriages', None)):
|
||||
return self.shipment.carrier
|
||||
|
||||
@classmethod
|
||||
def copy(cls, moves, default=None):
|
||||
default = default.copy() if default else {}
|
||||
default.setdefault('intrastat_transport')
|
||||
default.setdefault('intrastat_incoterm')
|
||||
return super().copy(moves, default=default)
|
||||
|
||||
|
||||
class Move_Consignment(metaclass=PoolMeta):
|
||||
__name__ = 'stock.move'
|
||||
|
||||
def _intrastat_transaction_code(self):
|
||||
code = super()._intrastat_transaction_code()
|
||||
if self.is_supplier_consignment or self.is_customer_consignment:
|
||||
code = '32'
|
||||
return code
|
||||
|
||||
|
||||
class ShipmentMixin:
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def intrastat_from_country(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def intrastat_to_country(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class ShipmentIn(ShipmentMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.in'
|
||||
|
||||
intrastat_from_country = fields.Many2One(
|
||||
'country.country', "From Country")
|
||||
intrastat_to_country = fields.Function(
|
||||
fields.Many2One('country.country', "To Country"),
|
||||
'on_change_with_intrastat_to_country')
|
||||
|
||||
@fields.depends('supplier')
|
||||
def on_change_supplier(self):
|
||||
try:
|
||||
super().on_change_supplier()
|
||||
except AttributeError:
|
||||
pass
|
||||
if self.supplier:
|
||||
address = self.supplier.address_get(type='delivery')
|
||||
if address:
|
||||
self.intrastat_from_country = address.country
|
||||
|
||||
@fields.depends('warehouse')
|
||||
def on_change_with_intrastat_to_country(self, name=None):
|
||||
if self.warehouse and self.warehouse.address:
|
||||
return self.warehouse.address.country
|
||||
|
||||
|
||||
class ShipmentInReturn(ShipmentMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.in.return'
|
||||
|
||||
intrastat_from_country = fields.Function(
|
||||
fields.Many2One('country.country', "From Country"),
|
||||
'on_change_with_intrastat_from_country')
|
||||
intrastat_to_country = fields.Function(
|
||||
fields.Many2One('country.country', "To Country"),
|
||||
'on_change_with_intrastat_to_country')
|
||||
|
||||
@fields.depends('warehouse')
|
||||
def on_change_with_intrastat_from_country(self, name=None):
|
||||
if self.warehouse and self.warehouse.address:
|
||||
return self.warehouse.address.country
|
||||
|
||||
@fields.depends('delivery_address')
|
||||
def on_change_with_intrastat_to_country(self, name=None):
|
||||
if self.delivery_address:
|
||||
return self.delivery_address.country
|
||||
|
||||
|
||||
class ShipmentOut(ShipmentMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.out'
|
||||
|
||||
intrastat_from_country = fields.Function(
|
||||
fields.Many2One('country.country', "From Country"),
|
||||
'on_change_with_intrastat_from_country')
|
||||
intrastat_to_country = fields.Function(
|
||||
fields.Many2One('country.country', "To Country"),
|
||||
'on_change_with_intrastat_to_country')
|
||||
|
||||
@fields.depends('warehouse')
|
||||
def on_change_with_intrastat_from_country(self, name=None):
|
||||
if self.warehouse and self.warehouse.address:
|
||||
return self.warehouse.address.country
|
||||
|
||||
@fields.depends('delivery_address')
|
||||
def on_change_with_intrastat_to_country(self, name=None):
|
||||
if self.delivery_address:
|
||||
return self.delivery_address.country
|
||||
|
||||
|
||||
class ShipmentOutReturn(ShipmentMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.out.return'
|
||||
|
||||
intrastat_from_country = fields.Many2One('country.country', "From Country")
|
||||
intrastat_to_country = fields.Function(
|
||||
fields.Many2One('country.country', "To Country"),
|
||||
'on_change_with_intrastat_to_country')
|
||||
|
||||
@fields.depends('customer')
|
||||
def on_change_customer(self):
|
||||
try:
|
||||
super().on_change_customer()
|
||||
except AttributeError:
|
||||
pass
|
||||
if self.customer:
|
||||
address = self.customer.address_get(type='delivery')
|
||||
if address:
|
||||
self.intrastat_from_country = address.country
|
||||
|
||||
@fields.depends('warehouse')
|
||||
def on_change_with_intrastat_to_country(self, name=None):
|
||||
if self.warehouse and self.warehouse.address:
|
||||
return self.warehouse.address.country
|
||||
|
||||
|
||||
class ShipmentInternal(ShipmentMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.internal'
|
||||
|
||||
intrastat_from_country = fields.Function(
|
||||
fields.Many2One('country.country', "From Country"),
|
||||
'on_change_with_intrastat_from_country')
|
||||
intrastat_to_country = fields.Function(
|
||||
fields.Many2One('country.country', "To Country"),
|
||||
'on_change_with_intrastat_to_country')
|
||||
|
||||
@fields.depends('from_location')
|
||||
def on_change_with_intrastat_from_country(self, name=None):
|
||||
if (self.from_location
|
||||
and self.from_location.warehouse
|
||||
and self.from_location.warehouse.address):
|
||||
return self.from_location.warehouse.address.country
|
||||
|
||||
@fields.depends('to_location')
|
||||
def on_change_with_intrastat_to_country(self, name=None):
|
||||
if (self.to_location
|
||||
and self.to_location.warehouse
|
||||
and self.to_location.warehouse.address):
|
||||
return self.to_location.warehouse.address.country
|
||||
|
||||
|
||||
class ShipmentDrop(ShipmentMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.drop'
|
||||
|
||||
intrastat_from_country = None
|
||||
intrastat_to_country = None
|
||||
Reference in New Issue
Block a user