trytond-carrier_load/sale.py

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_'