Set sale shipment cost on sale only at quotation

For performance reason, it is better to compute the shipment cost only at
quotation instead of when lines are changed.

issue4531
review5991002
This commit is contained in:
Cédric Krier
2015-02-27 11:57:58 +01:00
parent c1004f5c97
commit b9eff72791
4 changed files with 52 additions and 63 deletions
+1
View File
@@ -1,3 +1,4 @@
* Set sale shipment cost on sale only at quotation
* Allow to change the carrier until the shipment is done
Version 3.4.0 - 2014-10-20
+2 -1
View File
@@ -11,7 +11,8 @@ Two new fields are added to *Sale* and *Sale Configuration*:
- *On Order*: The cost will be computed once for the sale.
- *On Shipment*: The cost will be compted for each shipments.
Once a carrier is selected a new line is appended with the shipment cost.
At the quotation if a carrier is selected a new line is appended with the
shipment cost but the added line can be modified when going back to draft.
Three new fields are added to *Customer Shipment*:
+44 -57
View File
@@ -1,6 +1,6 @@
# 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.model import fields
from trytond.model import ModelView, Workflow, fields
from trytond.transaction import Transaction
from trytond.pyson import Eval, Bool
from trytond.pool import Pool, PoolMeta
@@ -54,90 +54,77 @@ class Sale:
config = Config(1)
return config.sale_shipment_cost_method
@classmethod
@ModelView.button
@Workflow.transition('quotation')
def quote(cls, sales):
super(Sale, cls).quote(sales)
for sale in sales:
sale.set_shipment_cost()
cls.save(sales)
def _get_carrier_context(self):
return {}
@fields.depends(methods=['lines'])
def on_change_carrier(self):
self.on_change_lines()
@fields.depends('carrier', 'party', 'currency', 'sale_date',
'shipment_cost_method', 'lines')
def on_change_lines(self):
def set_shipment_cost(self):
pool = Pool()
Product = pool.get('product.product')
Currency = pool.get('currency.currency')
SaleLine = pool.get('sale.line')
Date = pool.get('ir.date')
today = Date.today()
Currency = pool.get('currency.currency')
cost, currency_id = 0, None
if self.carrier:
with Transaction().set_context(self._get_carrier_context()):
cost, currency_id = self.carrier.get_sale_price()
party = None
party_context = {}
if self.party:
if self.party.lang:
party_context['language'] = self.party.lang.code
cost_line = None
products = [line.product for line in self.lines or []
if getattr(line, 'product', None)]
stockable = any(product.type in ('goods', 'assets')
for product in products)
if cost and currency_id and stockable:
today = Date.today()
date = self.sale_date or today
with Transaction().set_context(date=date):
cost = Currency.compute(Currency(currency_id), cost,
self.currency)
product = self.carrier.carrier_product
with Transaction().set_context(party_context):
description = Product(product.id).rec_name
taxes = []
cost_line = SaleLine(
**SaleLine.default_get(SaleLine._fields.keys()))
cost_line.type = 'line'
cost_line.product = product
cost_line.description = description
cost_line.quantity = 1 # XXX
cost_line.unit = product.sale_uom
cost_line.unit_price = cost
cost_line.shipment_cost = cost
cost_line.amount = cost
cost_line.taxes = taxes
cost_line.sequence = 9999 # XXX
pattern = cost_line._get_tax_rule_pattern()
for tax in product.customer_taxes_used:
if party and party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(tax, pattern)
if tax_ids:
taxes.extend(tax_ids)
continue
taxes.append(tax.id)
if party and party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(None, pattern)
if tax_ids:
taxes.extend(tax_ids)
cost_line = self.get_shipment_cost_line(cost)
lines = list(self.lines or [])
for line in self.lines:
if getattr(line, 'shipment_cost', None):
if line.shipment_cost != cost:
lines.remove(line)
if cost_line:
cost_line.description = getattr(
line, 'description', '')
else:
cost_line = None
break
if line.type != 'line' or not line.shipment_cost:
continue
if cost_line and line.shipment_cost == cost:
cost_line = None
else:
lines.remove(line)
if cost_line:
lines.append(cost_line)
self.lines = lines
super(Sale, self).on_change_lines()
def get_shipment_cost_line(self, cost):
pool = Pool()
SaleLine = pool.get('sale.line')
product = self.carrier.carrier_product
sequence = None
if self.lines:
last_line = self.lines[-1]
if last_line.sequence is not None:
sequence = last_line.sequence + 1
cost_line = SaleLine(
sale=self,
sequence=sequence,
type='line',
product=product,
quantity=1, # XXX
unit=product.sale_uom,
shipment_cost=cost,
)
cost_line.on_change_product()
cost_line.unit_price = cost_line.amount = cost
return cost_line
def create_shipment(self, shipment_type):
Shipment = Pool().get('stock.shipment.out')
+5 -5
View File
@@ -129,14 +129,14 @@ Sale products with cost on shipment::
>>> sale_line = sale.lines.new()
>>> sale_line.product = product
>>> sale_line.quantity = 5.0
>>> sale.click('quote')
>>> cost_line = sale.lines[-1]
>>> cost_line.product == carrier_product
True
>>> cost_line.quantity
1
1.0
>>> cost_line.amount
Decimal('3.00')
>>> sale.click('quote')
>>> sale.click('confirm')
>>> sale.click('process')
>>> sale.state
@@ -190,14 +190,14 @@ Sale products with cost on order::
>>> sale_line = sale.lines.new()
>>> sale_line.product = product
>>> sale_line.quantity = 3.0
>>> sale.click('quote')
>>> cost_line = sale.lines[-1]
>>> cost_line.product == carrier_product
True
>>> cost_line.quantity == 1
True
>>> cost_line.quantity
1.0
>>> cost_line.amount
Decimal('3.00')
>>> sale.click('quote')
>>> sale.click('confirm')
>>> sale.click('process')
>>> sale.state