Add carrier_carriage module
issue11623 review443451003
This commit is contained in:
1 parent
659d7ae8ef
commit
e9e547fdb8
5 files changed
+91
-58
No files matched your search
@@ -4,6 +4,9 @@
|
||||
from trytond.pool import Pool
|
||||
|
||||
from . import account, party, sale, stock
|
||||
from .stock import ShipmentCostSaleMixin
|
||||
|
||||
__all__ = ['register', 'ShipmentCostSaleMixin']
|
||||
|
||||
|
||||
def register():
|
||||
|
||||
@@ -6,9 +6,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<record model="ir.message" id="msg_sale_invalid_carrier">
|
||||
<field name="text">To confirm sale "%(sale)s" you must change the carrier "%(carrier)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_sale_shipment_cost_unique">
|
||||
<field name="text">A sale can have only one shipment cost line.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_cost_invoice_missing_account_revenue">
|
||||
<field name="text">To invoice shipment cost of "%(shipment)s", you must define an account revenue for product "%(product)s".</field>
|
||||
</record>
|
||||
|
||||
@@ -4,7 +4,7 @@ from decimal import Decimal
|
||||
|
||||
from trytond import backend
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import ModelView, Unique, Workflow, fields
|
||||
from trytond.model import ModelView, Workflow, fields
|
||||
from trytond.modules.product import price_digits, round_price
|
||||
from trytond.modules.sale.exceptions import SaleConfirmError
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
@@ -214,10 +214,10 @@ class Sale(metaclass=PoolMeta):
|
||||
with Transaction().set_context(_shipment_cost_invoiced=list()):
|
||||
super().process(sales)
|
||||
|
||||
def _get_carrier_context(self):
|
||||
def _get_carrier_context(self, carrier):
|
||||
return {}
|
||||
|
||||
def compute_shipment_cost(self):
|
||||
def compute_shipment_cost(self, carrier):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
Currency = pool.get('currency.currency')
|
||||
@@ -227,9 +227,9 @@ class Sale(metaclass=PoolMeta):
|
||||
if line.type == 'line'
|
||||
and line.product
|
||||
and line.product.type in Line.get_move_product_types())
|
||||
if self.carrier and stockable:
|
||||
with Transaction().set_context(self._get_carrier_context()):
|
||||
cost, currency_id = self.carrier.get_sale_price()
|
||||
if stockable:
|
||||
with Transaction().set_context(self._get_carrier_context(carrier)):
|
||||
cost, currency_id = carrier.get_sale_price()
|
||||
if cost is not None:
|
||||
with Transaction().set_context(company=self.company.id):
|
||||
today = Date.today()
|
||||
@@ -241,8 +241,8 @@ class Sale(metaclass=PoolMeta):
|
||||
|
||||
def set_shipment_cost(self):
|
||||
cost = None
|
||||
if self.shipment_cost_method:
|
||||
cost = self.compute_shipment_cost()
|
||||
if self.carrier and self.shipment_cost_method:
|
||||
cost = self.compute_shipment_cost(self.carrier)
|
||||
removed = []
|
||||
unit_price = None
|
||||
lines = list(self.lines or [])
|
||||
@@ -254,15 +254,15 @@ class Sale(metaclass=PoolMeta):
|
||||
removed.append(line)
|
||||
if cost is not None:
|
||||
lines.append(self.get_shipment_cost_line(
|
||||
cost, unit_price=unit_price))
|
||||
self.carrier, cost, unit_price=unit_price))
|
||||
self.lines = lines
|
||||
return removed
|
||||
|
||||
def get_shipment_cost_line(self, cost, unit_price=None):
|
||||
def get_shipment_cost_line(self, carrier, cost, unit_price=None):
|
||||
pool = Pool()
|
||||
SaleLine = pool.get('sale.line')
|
||||
|
||||
product = self.carrier.carrier_product
|
||||
product = carrier.carrier_product
|
||||
|
||||
sequence = None
|
||||
if self.lines:
|
||||
@@ -319,15 +319,18 @@ class Line(metaclass=PoolMeta):
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
t = cls.__table__()
|
||||
cls._sql_constraints += [
|
||||
('sale_shipment_cost_unique',
|
||||
Unique(t, t.sale, t.shipment_cost),
|
||||
'sale_shipment_cost.msg_sale_shipment_cost_unique'),
|
||||
]
|
||||
# shipment_cost is needed to compute the unit_price
|
||||
cls.unit_price.depends.add('shipment_cost')
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module):
|
||||
table_h = cls.__table_handler__(module)
|
||||
|
||||
super().__register__(module)
|
||||
|
||||
# Migration from 6.4: drop shipment cost unique
|
||||
table_h.drop_constraint('sale_shipment_cost_unique')
|
||||
|
||||
@fields.depends('shipment_cost', 'unit_price')
|
||||
def compute_unit_price(self):
|
||||
unit_price = super().compute_unit_price()
|
||||
|
||||
@@ -10,14 +10,15 @@ from trytond.transaction import Transaction
|
||||
from .exceptions import InvoiceShipmentCostError
|
||||
|
||||
|
||||
class ShipmentOut(metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.out'
|
||||
class ShipmentCostSaleMixin:
|
||||
__slots__ = ()
|
||||
|
||||
cost_sale_currency_used = fields.Function(fields.Many2One(
|
||||
'currency.currency', "Cost Sale Currency",
|
||||
states={
|
||||
'invisible': Eval('cost_method') != 'shipment',
|
||||
'readonly': (Eval('state').in_(['done', 'cancelled'])
|
||||
'readonly': (
|
||||
Eval('shipment_cost_sale_readonly', True)
|
||||
| ~Eval('cost_edit', False)),
|
||||
}),
|
||||
'on_change_with_cost_sale_currency_used', setter='set_cost')
|
||||
@@ -26,13 +27,14 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||
states={
|
||||
'invisible': Eval('cost_method') != 'shipment',
|
||||
'required': Bool(Eval('cost_sale')),
|
||||
'readonly': Eval('state').in_(['done', 'cancelled']),
|
||||
'readonly': Eval('shipment_cost_sale_readonly', True),
|
||||
})
|
||||
cost_sale_used = fields.Function(fields.Numeric(
|
||||
"Cost Sale", digits=price_digits,
|
||||
states={
|
||||
'invisible': Eval('cost_method') != 'shipment',
|
||||
'readonly': (Eval('state').in_(['done', 'cancelled'])
|
||||
'readonly': (
|
||||
Eval('shipment_cost_sale_readonly', True)
|
||||
| ~Eval('cost_edit', False)),
|
||||
}),
|
||||
'on_change_with_cost_sale_used', setter='set_cost')
|
||||
@@ -42,34 +44,17 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||
'invisible': Eval('cost_method') != 'shipment',
|
||||
})
|
||||
|
||||
cost_invoice_line = fields.Many2One('account.invoice.line',
|
||||
'Cost Invoice Line', readonly=True)
|
||||
cost_invoice_line = fields.Many2One(
|
||||
'account.invoice.line', "Cost Invoice Line", readonly=True)
|
||||
cost_method = fields.Selection(
|
||||
'get_cost_methods', 'Cost Method', readonly=True)
|
||||
'get_cost_methods', "Cost Method", readonly=True)
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module):
|
||||
table_h = cls.__table_handler__(module)
|
||||
cursor = Transaction().connection.cursor()
|
||||
table = cls.__table__()
|
||||
shipment_cost_sale_readonly = fields.Function(
|
||||
fields.Boolean("Shipment Cost Sale Read Only"),
|
||||
'on_change_with_shipment_cost_sale_readonly')
|
||||
|
||||
# Migration from 5.8: rename cost into cost_sale
|
||||
if (table_h.column_exist('cost')
|
||||
and not table_h.column_exist('cost_sale')):
|
||||
table_h.column_rename('cost', 'cost_sale')
|
||||
if (table_h.column_exist('cost_currency')
|
||||
and not table_h.column_exist('cost_sale_currency')):
|
||||
table_h.column_rename('cost_currency', 'cost_sale_currency')
|
||||
|
||||
cost_method_exists = table_h.column_exist('cost_method')
|
||||
|
||||
super().__register__(module)
|
||||
|
||||
# Migration from 6.0: fill new cost_method field
|
||||
if not cost_method_exists:
|
||||
cursor.execute(*table.update(
|
||||
columns=[table.cost_method],
|
||||
values=['shipment']))
|
||||
def on_change_with_shipment_cost_sale_readonly(self, name=None):
|
||||
raise NotImplementedError
|
||||
|
||||
@fields.depends('carrier', 'cost_method', methods=['_get_carrier_context'])
|
||||
def _compute_costs(self):
|
||||
@@ -87,17 +72,19 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||
return costs
|
||||
|
||||
@fields.depends(
|
||||
'state', 'cost_sale', 'cost_edit', methods=['_compute_costs'])
|
||||
'shipment_cost_sale_readonly', 'cost_sale', 'cost_edit',
|
||||
methods=['_compute_costs'])
|
||||
def on_change_with_cost_sale_used(self, name=None):
|
||||
if not self.cost_edit and self.state not in {'cancelled', 'done'}:
|
||||
if not self.cost_edit and not self.shipment_cost_sale_readonly:
|
||||
return self._compute_costs()['cost_sale']
|
||||
else:
|
||||
return self.cost_sale
|
||||
|
||||
@fields.depends(
|
||||
'state', 'cost_sale_currency', 'cost_edit', methods=['_compute_costs'])
|
||||
'shipment_cost_sale_readonly', 'cost_sale_currency', 'cost_edit',
|
||||
methods=['_compute_costs'])
|
||||
def on_change_with_cost_sale_currency_used(self, name=None):
|
||||
if not self.cost_edit and self.state not in {'cancelled', 'done'}:
|
||||
if not self.cost_edit and not self.shipment_cost_sale_readonly:
|
||||
return self._compute_costs()['cost_sale_currency']
|
||||
elif self.cost_sale_currency:
|
||||
return self.cost_sale_currency.id
|
||||
@@ -135,7 +122,6 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||
invoice_line.unit_price = round_price(cost)
|
||||
invoice_line.product = product
|
||||
invoice_line.on_change_product()
|
||||
invoice_line.cost_shipments = [self]
|
||||
|
||||
if not invoice_line.account:
|
||||
raise InvoiceShipmentCostError(
|
||||
@@ -155,8 +141,46 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||
self.cost_sale_currency, self.cost_sale,
|
||||
self.company.currency, round=False)
|
||||
cost -= cost_sale
|
||||
elif self.cost_method == 'order':
|
||||
sales = {m.sale for m in self.outgoing_moves if m.sale}
|
||||
return cost
|
||||
|
||||
|
||||
class ShipmentOut(ShipmentCostSaleMixin, metaclass=PoolMeta):
|
||||
__name__ = 'stock.shipment.out'
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module):
|
||||
table_h = cls.__table_handler__(module)
|
||||
cursor = Transaction().connection.cursor()
|
||||
table = cls.__table__()
|
||||
|
||||
# Migration from 5.8: rename cost into cost_sale
|
||||
if (table_h.column_exist('cost')
|
||||
and not table_h.column_exist('cost_sale')):
|
||||
table_h.column_rename('cost', 'cost_sale')
|
||||
if (table_h.column_exist('cost_currency')
|
||||
and not table_h.column_exist('cost_sale_currency')):
|
||||
table_h.column_rename('cost_currency', 'cost_sale_currency')
|
||||
|
||||
cost_method_exists = table_h.column_exist('cost_method')
|
||||
|
||||
super().__register__(module)
|
||||
|
||||
# Migration from 6.0: fill new cost_method field
|
||||
if not cost_method_exists:
|
||||
cursor.execute(*table.update(
|
||||
columns=[table.cost_method],
|
||||
values=['shipment']))
|
||||
|
||||
@fields.depends('state')
|
||||
def on_change_with_shipment_cost_sale_readonly(self, name=None):
|
||||
return self.state in {'done', 'cancelled'}
|
||||
|
||||
def _get_shipment_cost(self):
|
||||
cost = super()._get_shipment_cost()
|
||||
if self.cost_method == 'order':
|
||||
sales = {
|
||||
m.sale for m in self.outgoing_moves
|
||||
if m.sale and m.sale.shipment_cost_method == 'order'}
|
||||
for sale in sales:
|
||||
shipment_cost = sum(
|
||||
(s.cost_used or 0) for s in sale.shipments
|
||||
@@ -165,6 +189,12 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||
cost -= max(cost_sale - shipment_cost, 0)
|
||||
return cost
|
||||
|
||||
def get_cost_invoice_line(self, invoice):
|
||||
invoice_line = super().get_cost_invoice_line(invoice)
|
||||
if invoice_line:
|
||||
invoice_line.cost_shipments = [self]
|
||||
return invoice_line
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('done')
|
||||
|
||||
@@ -6,7 +6,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<label name="cost_sale_used"/>
|
||||
<group id="cost_sale_used" col="-1" colspan="3">
|
||||
<field name="cost_sale_used" xexpand="0"/>
|
||||
<field name="cost_sale_currency_used" xexpand="0" xalign="0"/>
|
||||
<field name="cost_sale_currency_used"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</data>
|
||||
Reference in new issue
Block a user