220 lines
6.8 KiB
Python
220 lines
6.8 KiB
Python
# The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from decimal import Decimal
|
|
from trytond.model import fields
|
|
from trytond.pool import PoolMeta, Pool
|
|
from trytond.pyson import Eval
|
|
from trytond.transaction import Transaction
|
|
from trytond.exceptions import UserError
|
|
from trytond.i18n import gettext
|
|
from trytond.wizard import Wizard, StateTransition, StateReport
|
|
|
|
|
|
class Sale(metaclass=PoolMeta):
|
|
__name__ = 'sale.sale'
|
|
|
|
loads = fields.One2Many('carrier.load.order', 'sale', 'Load orders')
|
|
|
|
@classmethod
|
|
def _get_origin(cls):
|
|
res = super(Sale, cls)._get_origin()
|
|
res.append('carrier.load.order')
|
|
return res
|
|
|
|
@classmethod
|
|
def delete(cls, records):
|
|
for record in records:
|
|
if record.loads and not record.origin:
|
|
raise UserError(gettext(
|
|
'carrier_load.msg_sale_sale_has_load',
|
|
sale=record.rec_name))
|
|
super(Sale, cls).delete(records)
|
|
|
|
@classmethod
|
|
def copy(cls, records, default=None):
|
|
if default is None:
|
|
default = {}
|
|
else:
|
|
default = default.copy()
|
|
default.setdefault('origin', None)
|
|
default.setdefault('loads', None)
|
|
return super().copy(records, default=default)
|
|
|
|
@classmethod
|
|
def get_carrier_states_methods(cls):
|
|
"""
|
|
Returns a list(tuple) of the states ordered by execution.
|
|
does not include cancelled, draft, do status
|
|
format tuple: ('state', 'method')
|
|
"""
|
|
return [
|
|
('quotation', 'quote'),
|
|
('confirmed', 'confirm'),
|
|
('processing', 'process'),
|
|
]
|
|
|
|
|
|
class SaleCreditLimit(metaclass=PoolMeta):
|
|
__name__ = 'sale.sale'
|
|
|
|
@classmethod
|
|
def proceed(cls, sales):
|
|
for sale in sales:
|
|
if sale.state == 'confirmed' and \
|
|
sale.shipment_method == 'manual' and \
|
|
sale.loads:
|
|
sale.party.check_credit_limit(sale.untaxed_amount,
|
|
origin=str(sale))
|
|
return super(Sale, cls).proceed(sales)
|
|
|
|
|
|
class CostMixin(object):
|
|
__slots__ = ()
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(CostMixin, cls).__setup__()
|
|
|
|
def get_context_formula(self, cost):
|
|
res = super(CostMixin, self).get_context_formula(cost)
|
|
res['names'].update({'carrier_amount': Decimal(
|
|
cost.document_carrier_amount if cost and
|
|
cost.document_carrier_amount else 0)
|
|
})
|
|
return res
|
|
|
|
|
|
class CostType(CostMixin, metaclass=PoolMeta):
|
|
__name__ = 'sale.cost.type'
|
|
|
|
|
|
class CostTemplate(CostMixin, metaclass=PoolMeta):
|
|
__name__ = 'sale.cost.template'
|
|
|
|
|
|
class CostSale(CostMixin, metaclass=PoolMeta):
|
|
__name__ = 'sale.cost'
|
|
|
|
document_carrier_amount = fields.Function(
|
|
fields.Numeric('Sale carrier amount',
|
|
digits=(16, Eval('currency_digits', 2))),
|
|
'get_document_carrier_amount')
|
|
|
|
def _compute_document_values(self):
|
|
super(CostSale, self)._compute_document_values()
|
|
self.document_carrier_amount = self.get_document_carrier_amount()
|
|
|
|
def get_document_carrier_amount(self, name=None):
|
|
pool = Pool()
|
|
LoadOrder = pool.get('carrier.load.order')
|
|
|
|
if not self.document:
|
|
return 0
|
|
orders = LoadOrder.search([('sale', '=', self.document)])
|
|
if not orders:
|
|
return 0
|
|
amount = sum(order.carrier_amount for order in orders)
|
|
if self.currency and orders[0].load.currency != self.currency:
|
|
with Transaction().set_context(date=self.document.sale_date):
|
|
amount = self.currency.compute(
|
|
orders[0].load.currency, amount, self.currency)
|
|
return amount
|
|
|
|
def _must_update_carrier_amount(self):
|
|
return self.type_.apply_method == 'none'
|
|
|
|
|
|
class CostSale2(metaclass=PoolMeta):
|
|
__name__ = 'sale.cost'
|
|
|
|
@fields.depends('formula', 'document', 'invoice_party', 'apply_method')
|
|
def _load_invoice_party(self):
|
|
if (self.formula and 'carrier_amount' in self.formula and
|
|
self.document and self.document.loads and
|
|
self.apply_method == 'invoice_in' and
|
|
not self.invoice_party and
|
|
self.document.loads[0].load.carrier):
|
|
self.invoice_party = self.document.loads[0].load.carrier.party
|
|
|
|
@fields.depends(methods=['_load_invoice_party'])
|
|
def on_change_template(self):
|
|
super().on_change_template()
|
|
self._load_invoice_party()
|
|
|
|
@fields.depends(methods=['_load_invoice_party'])
|
|
def on_change_type_(self):
|
|
super().on_change_type_()
|
|
self._load_invoice_party()
|
|
|
|
|
|
class CostSaleLine(metaclass=PoolMeta):
|
|
__name__ = 'sale.cost.line'
|
|
|
|
document_carrier_amount = fields.Function(
|
|
fields.Numeric('Sale carrier amount',
|
|
digits=(16, Eval('currency_digits', 2))),
|
|
'get_document_carrier_amount')
|
|
|
|
def get_document_carrier_amount(self, name=None):
|
|
if self.cost and self.cost.document_carrier_amount:
|
|
if self.cost.document_quantity:
|
|
return (self.currency.round(self.document_quantity /
|
|
self.cost.document_quantity
|
|
) * self.cost.document_carrier_amount)
|
|
return 0
|
|
|
|
|
|
class SaleReport(metaclass=PoolMeta):
|
|
__name__ = 'sale.sale'
|
|
|
|
@classmethod
|
|
def execute(cls, ids, data):
|
|
with Transaction().set_context(_check_access=False):
|
|
# allow to print without sale group
|
|
return super().execute(ids, data)
|
|
|
|
|
|
class PrintCarrierNote(Wizard):
|
|
"""Print Sale Carrier note"""
|
|
__name__ = 'sale.print_carrier_note'
|
|
|
|
start = StateTransition()
|
|
print_ = StateTransition()
|
|
print_cmr = StateReport('carrier.load.order.cmr')
|
|
print_road_note = StateReport('carrier.load.order.road_note')
|
|
|
|
def transition_start(self):
|
|
Order = Pool().get('carrier.load.order')
|
|
|
|
self.to_print = {}
|
|
for sale in self.records:
|
|
if sale.origin and isinstance(sale.origin, Order):
|
|
self.to_print.setdefault(
|
|
Order.get_carrier_report(order=sale.origin),
|
|
[]).append(sale.origin.id)
|
|
return 'print_'
|
|
|
|
def transition_print_(self):
|
|
if self.to_print.get('cmr', []):
|
|
return 'print_cmr'
|
|
elif self.to_print.get('road_note', []):
|
|
return 'print_road_note'
|
|
else:
|
|
return 'end'
|
|
|
|
def do_print_cmr(self, action):
|
|
ids = self.to_print.pop('cmr')
|
|
data = {'ids': ids}
|
|
return action, data
|
|
|
|
def transition_print_cmr(self):
|
|
return 'print_'
|
|
|
|
def do_print_road_note(self, action):
|
|
ids = self.to_print.pop('road_note')
|
|
data = {'ids': ids}
|
|
return action, data
|
|
|
|
def transition_print_road_note(self):
|
|
return 'print_'
|