changeset 36999d34ea12 in modules/production:default
details:
https://hg.tryton.org/modules/production?cmd=changeset;node=36999d34ea12
description:
Keep cost of unused input products
We set the average cost price of the input products as the unit price
of the
output of the same product. This way the cost price computation for this
product does not change.
issue9637
review316051002
diffstat:
CHANGELOG | 1 +
production.py | 38 ++++++++++++++++++++++++++++++---
tests/scenario_production_set_cost.rst | 25 +++++++++++++--------
3 files changed, 50 insertions(+), 14 deletions(-)
diffs (140 lines):
diff -r 5fa6035477e6 -r 36999d34ea12 CHANGELOG
--- a/CHANGELOG Fri Oct 09 19:09:05 2020 +0200
+++ b/CHANGELOG Sun Oct 11 16:12:36 2020 +0200
@@ -1,3 +1,4 @@
+* Keep cost of unused input products
* Use the shipment assign wizard for production
* Rename production state from cancel to cancelled
diff -r 5fa6035477e6 -r 36999d34ea12 production.py
--- a/production.py Fri Oct 09 19:09:05 2020 +0200
+++ b/production.py Sun Oct 11 16:12:36 2020 +0200
@@ -1,5 +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 collections import defaultdict
from decimal import Decimal
from itertools import chain
@@ -529,8 +530,37 @@
for production in productions:
sum_ = Decimal(0)
prices = {}
+ cost = production.cost
+
+ input_quantities = defaultdict(Decimal)
+ input_costs = defaultdict(Decimal)
+ for input_ in production.inputs:
+ if input_.cost_price is not None:
+ cost_price = input_.cost_price
+ else:
+ cost_price = input_.product.cost_price
+ input_quantities[input_.product] += (
+ Decimal(str(input_.internal_quantity)))
+ input_costs[input_.product] += (
+ Decimal(str(input_.internal_quantity)) * cost_price)
+ outputs = []
for output in production.outputs:
product = output.product
+ if input_quantities.get(output.product):
+ cost_price = (
+ input_costs[product] / input_quantities[product])
+ unit_price = round_price(Uom.compute_price(
+ product.default_uom, cost_price, output.uom))
+ if output.unit_price != unit_price:
+ output.unit_price = unit_price
+ moves.append(output)
+ cost -= min(
+ unit_price * Decimal(str(output.quantity)), cost)
+ else:
+ outputs.append(output)
+
+ for output in outputs:
+ product = output.product
with Transaction().set_context(production._list_price_context):
list_price = product.list_price_used
product_price = (Decimal(str(output.quantity))
@@ -541,7 +571,7 @@
if not sum_ and production.product:
prices.clear()
- for output in production.outputs:
+ for output in outputs:
if output.product == production.product:
quantity = Uom.compute_qty(
output.uom, output.quantity,
@@ -550,13 +580,13 @@
prices[output] = quantity
sum_ += quantity
- for output in production.outputs:
+ for output in outputs:
if sum_:
ratio = prices.get(output, 0) / sum_
else:
- ratio = Decimal(1) / len(production.outputs)
+ ratio = Decimal(1) / len(outputs)
quantity = Decimal(str(output.quantity))
- unit_price = round_price(production.cost * ratio / quantity)
+ unit_price = round_price(cost * ratio / quantity)
if output.unit_price != unit_price:
output.unit_price = unit_price
moves.append(output)
diff -r 5fa6035477e6 -r 36999d34ea12 tests/scenario_production_set_cost.rst
--- a/tests/scenario_production_set_cost.rst Fri Oct 09 19:09:05 2020 +0200
+++ b/tests/scenario_production_set_cost.rst Sun Oct 11 16:12:36 2020 +0200
@@ -51,13 +51,13 @@
>>> bom = BOM(name='product')
>>> input = bom.inputs.new()
>>> input.product = component
- >>> input.quantity = 2
+ >>> input.quantity = 3
>>> output = bom.outputs.new()
>>> output.product = product
>>> output.quantity = 1
>>> bom.save()
-Make a production::
+Make a production with 2 unused component::
>>> Production = Model.get('production')
>>> production = Production()
@@ -67,15 +67,20 @@
>>> production.click('wait')
>>> production.click('assign_force')
>>> production.click('run')
+ >>> output = production.outputs.new()
+ >>> output.product = component
+ >>> output.quantity = 2
+ >>> output.unit_price = Decimal(0)
+ >>> output.from_location = production.location
+ >>> output.to_location = production.warehouse.storage_location
>>> production.click('done')
Check output price::
>>> production.cost
- Decimal('20.0000')
- >>> output, = production.outputs
- >>> output.unit_price
- Decimal('10.0000')
+ Decimal('30.0000')
+ >>> sorted([o.unit_price for o in production.outputs])
+ [Decimal('5.0000'), Decimal('10.0000')]
Change cost of input::
@@ -97,9 +102,9 @@
>>> cron_set_cost.companies.append(Company(company.id))
>>> cron_set_cost.click('run_once')
- >>> output.reload()
- >>> output.unit_price
- Decimal('12.0000')
- >>> input.reload()
+ >>> production.reload()
+ >>> sorted([o.unit_price for o in production.outputs])
+ [Decimal('6.0000'), Decimal('12.0000')]
+ >>> input, = production.inputs
>>> bool(input.production_cost_price_updated)
False