Simplify manual alteration of shipment cost

issue10142
review340111002
This commit is contained in:
Cédric Krier committed 2021-03-13 23:43:51 +01:00
1 parent b5461c07f7
commit c1c8b4a8d3
5 files changed
+144 -64

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Simplify manual alteration of shipment cost
* Use purchase carrier price as cost for shipment
* Allow shipment costs to not be sold
* Add carrier on shipment list view
-12
View File
@@ -268,23 +268,11 @@ class Sale(metaclass=PoolMeta):
def create_shipment(self, shipment_type):
pool = Pool()
Shipment = pool.get('stock.shipment.out')
Currency = pool.get('currency.currency')
shipments = super(Sale, self).create_shipment(shipment_type)
if shipment_type == 'out' and shipments and self.carrier:
for shipment in shipments:
shipment.carrier = self.carrier
with Transaction().set_context(
shipment.get_carrier_context()):
cost, currency_id = self.carrier.get_purchase_price()
shipment.cost = round_price(Currency.compute(
Currency(currency_id), cost, shipment.company.currency,
round=False))
with Transaction().set_context(
shipment.get_carrier_context()):
cost_sale, currency_id = self.carrier.get_sale_price()
shipment.cost_sale = round_price(cost_sale)
shipment.cost_sale_currency = currency_id
Shipment.save(shipments)
return shipments
+123 -38
View File
@@ -1,7 +1,7 @@
# 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 fields
from trytond.model import ModelView, Workflow, fields
from trytond.pyson import Eval, Bool
from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
@@ -17,27 +17,62 @@ class ShipmentOut(metaclass=PoolMeta):
'picked', 'packed']),
},
depends=['state'])
cost = fields.Numeric("Cost",
digits=price_digits, states={
'invisible': ~Eval('carrier'),
cost_used = fields.Function(fields.Numeric(
"Cost", digits=price_digits,
states={
'invisible': ~Eval('carrier') | Eval('cost_edit', False),
},
depends=['carrier', 'cost_edit']),
'on_change_with_cost_used')
cost = fields.Numeric(
"Cost", digits=price_digits,
states={
'invisible': ~Eval('carrier') | ~Eval('cost_edit', False),
'readonly': ~Eval('state').in_(
['draft', 'waiting', 'assigned', 'packed']),
}, depends=['carrier', 'state'])
['draft', 'waiting', 'assigned', 'picked', 'packed']),
},
depends=['carrier', 'state'])
cost_sale_currency_used = fields.Function(fields.Many2One(
'currency.currency', "Cost Sale Currency",
states={
'invisible': ~Eval('carrier') | Eval('cost_edit', False),
},
depends=['carrier', 'cost_edit']),
'on_change_with_cost_sale_currency_used')
cost_sale_currency = fields.Many2One(
'currency.currency', "Cost Sale Currency",
states={
'invisible': ~Eval('carrier'),
'required': Bool(Eval('carrier')),
'invisible': ~Eval('carrier') | ~Eval('cost_edit', False),
'required': Bool(Eval('cost_sale')),
'readonly': ~Eval('state').in_(
['draft', 'waiting', 'assigned', 'picked', 'packed']),
}, depends=['carrier', 'cost_sale', 'state'])
cost_sale_used = fields.Function(fields.Numeric(
"Cost Sale", digits=price_digits,
states={
'invisible': ~Eval('carrier') | Eval('cost_edit', False),
},
depends=['carrier', 'cost_edit']),
'on_change_with_cost_sale_used')
cost_sale = fields.Numeric(
"Cost Sale", digits=price_digits,
states={
'invisible': ~Eval('carrier') | ~Eval('cost_edit', False),
'readonly': ~Eval('state').in_(
['draft', 'waiting', 'assigned', 'picked', 'packed']),
}, depends=['carrier', 'state'])
cost_sale = fields.Numeric(
"Cost Sale", digits=price_digits,
cost_edit = fields.Boolean(
"Edit Cost",
states={
'invisible': ~Eval('carrier'),
'readonly': ~Eval('state').in_(
['draft', 'waiting', 'assigned', 'picked', 'packed']),
}, depends=['carrier', 'state'])
},
depends=['carrier', 'state'],
help="Check to edit the cost.")
cost_invoice_line = fields.Many2One('account.invoice.line',
'Cost Invoice Line', readonly=True)
@@ -59,31 +94,59 @@ class ShipmentOut(metaclass=PoolMeta):
def get_carrier_context(self):
return self._get_carrier_context()
@fields.depends(methods=['on_change_inventory_moves'])
def on_change_carrier(self):
self.on_change_inventory_moves()
@fields.depends('carrier', 'company', methods=['_get_carrier_context'])
def on_change_inventory_moves(self):
def _compute_costs(self):
pool = Pool()
Currency = pool.get('currency.currency')
try:
super(ShipmentOut, self).on_change_inventory_moves()
except AttributeError:
pass
if not self.carrier:
self.cost = None
self.cost_sale = None
self.cost_sale_currency = None
return
with Transaction().set_context(self._get_carrier_context()):
cost, currency_id = self.carrier.get_purchase_price()
cost_sale, sale_currency_id = self.carrier.get_sale_price()
self.cost = round_price(Currency.compute(
Currency(currency_id), cost, self.company.currency,
round=False))
self.cost_sale = round_price(cost_sale)
self.cost_sale_currency = sale_currency_id
costs = {
'cost': None,
'cost_sale': None,
'cost_sale_currency': None,
}
if self.carrier:
with Transaction().set_context(self._get_carrier_context()):
cost, currency_id = self.carrier.get_purchase_price()
cost_sale, sale_currency_id = self.carrier.get_sale_price()
if cost is not None:
cost = Currency.compute(
Currency(currency_id), cost, self.company.currency,
round=False)
costs['cost'] = round_price(cost)
if cost_sale is not None:
costs['cost_sale'] = round_price(cost_sale)
costs['cost_sale_currency'] = sale_currency_id
return costs
@fields.depends('state', 'cost', 'cost_edit', methods=['_compute_costs'])
def on_change_with_cost_used(self, name=None):
if not self.cost_edit and self.state not in {'cancelled', 'done'}:
return self._compute_costs()['cost']
else:
return self.cost
@fields.depends(
'state', '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'}:
return self._compute_costs()['cost_sale']
else:
return self.cost_sale
@fields.depends(
'state', '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'}:
return self._compute_costs()['cost_sale_currency']
elif self.cost_sale_currency:
return self.cost_sale_currency.id
@fields.depends(
'cost_edit', 'cost_used', 'cost_sale_used', 'cost_sale_currency_used')
def on_change_cost_edit(self):
if self.cost_edit:
self.cost = self.cost_used
self.cost_sale = self.cost_sale_used
self.cost_sale_currency = self.cost_sale_currency_used
def _get_cost_tax_rule_pattern(self):
'Get tax rule pattern for invoice line'
@@ -95,7 +158,7 @@ class ShipmentOut(metaclass=PoolMeta):
Currency = pool.get('currency.currency')
InvoiceLine = pool.get('account.invoice.line')
if not self.cost_sale:
if not self.cost_sale_used:
return
invoice_line = InvoiceLine()
product = self.carrier.carrier_product
@@ -111,11 +174,11 @@ class ShipmentOut(metaclass=PoolMeta):
invoice_line.quantity = 1 # XXX
invoice_line.unit = product.sale_uom.id
cost = self.cost_sale
if invoice.currency != self.cost_sale_currency:
cost = self.cost_sale_used
if invoice.currency != self.cost_sale_currency_used:
with Transaction().set_context(date=invoice.currency_date):
cost = Currency.compute(
self.cost_sale_currency, cost,
self.cost_sale_currency_used, cost,
invoice.currency, round=False)
invoice_line.unit_price = round_price(cost)
invoice_line.currency = invoice.currency
@@ -148,5 +211,27 @@ class ShipmentOut(metaclass=PoolMeta):
def _get_shipment_cost(self):
cost = super()._get_shipment_cost()
if all(not m.sale.shipment_cost_method for m in self.outgoing_moves):
cost += self.cost
cost += self.cost_used
return cost
@classmethod
@ModelView.button
@Workflow.transition('done')
def done(cls, shipments):
for shipment in shipments:
shipment.cost = shipment.cost_used
shipment.cost_sale = shipment.cost_sale_used
shipment.cost_sale_currency = shipment.cost_sale_currency_used
cls.save(shipments)
super().done(shipments)
@classmethod
@ModelView.button
@Workflow.transition('cancelled')
def cancel(cls, shipments):
for shipment in shipments:
shipment.cost = None
shipment.cost_sale = None
shipment.cost_sale_currency = None
cls.save(shipments)
super().cancel(shipments)
+7 -7
View File
@@ -141,17 +141,17 @@ Send products::
>>> shipment, = sale.shipments
>>> shipment.carrier == carrier
True
>>> shipment.cost
>>> shipment.cost_used
Decimal('2.0000')
>>> shipment.cost_sale
>>> shipment.cost_sale_used
Decimal('3.0000')
>>> shipment.cost_sale_currency == company.currency
>>> shipment.cost_sale_currency_used == company.currency
True
>>> move, = shipment.inventory_moves
>>> move.quantity = 4
>>> shipment.cost_sale
>>> shipment.cost_sale_used
Decimal('3.0000')
>>> shipment.cost_sale_currency == company.currency
>>> shipment.cost_sale_currency_used == company.currency
True
>>> shipment.state
'waiting'
@@ -299,9 +299,9 @@ Check no customer invoice::
Send products::
>>> shipment, = sale.shipments
>>> shipment.cost
>>> shipment.cost_used
Decimal('2.0000')
>>> shipment.cost_sale
>>> shipment.cost_sale_used
Decimal('3.0000')
>>> shipment.click('assign_force')
>>> shipment.click('pick')
+13 -7
View File
@@ -5,12 +5,18 @@ this repository contains the full copyright notices and license terms. -->
<xpath expr="/form/notebook" position="after">
<label name="carrier"/>
<field name="carrier"/>
<label name="cost"/>
<field name="cost"/>
<label name="cost_sale"/>
<field name="cost_sale"/>
<label name="cost_sale_currency"/>
<field name="cost_sale_currency"/>
<group id="costs" col="-1" colspan="2">
<label name="cost"/>
<label name="cost_used"/>
<field name="cost"/>
<field name="cost_used"/>
<label name="cost_sale"/>
<label name="cost_sale_used"/>
<field name="cost_sale"/>
<field name="cost_sale_used"/>
<field name="cost_sale_currency"/>
<field name="cost_sale_currency_used"/>
<field name="cost_edit"/>
</group>
</xpath>
</data>