Update patch of product csot reaclculation

This commit is contained in:
Bernat Brunet 2020-06-17 18:11:57 +02:00
parent e45f3f27d4
commit 1402a589e0
1 changed files with 185 additions and 13 deletions

View File

@ -1,5 +1,52 @@
diff --git a/configuration.py b/configuration.py
new file mode 100644
index 0000000..e4e44fc
--- /dev/null
+++ b/trytond/trytond/modules/product_cost_fifo/configuration.py
@@ -0,0 +1,23 @@
+# 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.pool import PoolMeta
+
+__all__ = ['Configuration']
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'stock.configuration'
+
+ exclude_locations = fields.Many2Many('stock.locations', None, None,
+ 'Exclude Locations')
+
+ @classmethod
+ def __register__(cls, module_name):
+ table = cls.__table_handler__(module_name)
+
+ # Migration from 5.2: rename reference into valued_sale_line
+ if (table.column_exist('valued_sale_line')):
+ table.column_rename('valued_sale_line', 'valued_origin')
+
+ super(Configuration, cls).__register__(module_name)
diff --git a/configuration.xml b/configuration.xml
new file mode 100644
index 0000000..d1a8c9a
--- /dev/null
+++ b/trytond/trytond/modules/product_cost_fifo/configuration.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<tryton>
+ <data>
+ <record model="ir.ui.view" id="stock_configuration_view_form">
+ <field name="model">stock.configuration</field>
+ <field name="inherit" ref="stock.stock_configuration_view_form"/>
+ <field name="name">configuration_form</field>
+ </record>
+ </data>
+</tryton>
diff --git a/move.py b/move.py
index c7c41ca..266df58 100644
index 91a7b07..a7393dd 100644
--- a/trytond/trytond/modules/product_cost_fifo/move.py
+++ b/trytond/trytond/modules/product_cost_fifo/move.py
@@ -81,13 +81,15 @@ class Move(metaclass=PoolMeta):
@ -13,7 +60,7 @@ index c7c41ca..266df58 100644
- self.company.currency, round=False)
- move_unit_price = Uom.compute_price(move.uom, move_unit_price,
- move.product.default_uom)
+ if move.unit_price is not None:
+ if move.from_location.type in {'supplier', 'production'}:
+ with Transaction().set_context(date=move.effective_date):
+ move_unit_price = Currency.compute(
+ move.currency, move.unit_price,
@ -23,10 +70,10 @@ index c7c41ca..266df58 100644
+ else:
+ move_unit_price = move.cost_price or 0
cost_price += move_unit_price * Decimal(str(move_qty))
move_qty = Uom.compute_qty(self.product.default_uom, move_qty,
diff --git a/product.py b/product.py
index 9eaceac..cc6e982 100644
index 9eaceac..2ad49a2 100644
--- a/trytond/trytond/modules/product_cost_fifo/product.py
+++ b/trytond/trytond/modules/product_cost_fifo/product.py
@@ -31,7 +31,7 @@ class Product(metaclass=PoolMeta):
@ -38,21 +85,47 @@ index 9eaceac..cc6e982 100644
('to_location.type', '=', 'storage'),
]
if not date:
@@ -135,11 +135,10 @@ class Product(metaclass=PoolMeta):
@@ -95,7 +95,10 @@ class Product(metaclass=PoolMeta):
Move = pool.get('stock.move')
Currency = pool.get('currency.currency')
Uom = pool.get('product.uom')
+ Config = pool.get('stock.configuration')
+
digits = self.__class__.cost_price.digits
+ config = Config(1)
domain = [
('product', '=', self.id),
@@ -111,6 +114,14 @@ class Product(metaclass=PoolMeta):
],
],
]
+
+ if config.exclude_values:
+ locations_ids = [l.id for l in config.exclude_locations]
+ domain.extend([
+ ('to_location.id', 'not in', location_ids),
+ ('from_location.id', 'not in', location_ids),
+ ])
+
if start:
domain.append(('effective_date', '>=', start))
moves = Move.search(
@@ -135,11 +146,10 @@ class Product(metaclass=PoolMeta):
quantity = Decimal(str(quantity))
def in_move(move):
- return (move.from_location.type in ['supplier', 'production']
- or move.to_location.type == 'supplier')
+ return move.to_location.type == 'storage'
def out_move(move):
- return not in_move(move)
+ return move.from_location.type == 'storage'
def compute_fifo_cost_price(quantity, date):
fifo_moves = self.get_fifo_move(
@@ -150,12 +149,15 @@ class Product(metaclass=PoolMeta):
@@ -150,12 +160,15 @@ class Product(metaclass=PoolMeta):
consumed_qty = 0
for move, move_qty in fifo_moves:
consumed_qty += move_qty
@ -62,7 +135,7 @@ index 9eaceac..cc6e982 100644
- move.company.currency, round=False)
- unit_price = Uom.compute_price(
- move.uom, unit_price, move.product.default_uom)
+ if move.unit_price is not None:
+ if move.from_location.type in {'supplier', 'production'}:
+ with Transaction().set_context(date=move.effective_date):
+ unit_price = Currency.compute(
+ move.currency, move.unit_price,
@ -74,7 +147,17 @@ index 9eaceac..cc6e982 100644
cost_price += unit_price * Decimal(str(move_qty))
if consumed_qty:
return (cost_price / Decimal(str(consumed_qty))).quantize(
@@ -202,12 +204,15 @@ class Product(metaclass=PoolMeta):
@@ -163,7 +176,8 @@ class Product(metaclass=PoolMeta):
current_moves = []
current_out_qty = 0
- current_cost_price = cost_price
+ current_cost_price = cost_price.quantize(
+ Decimal(str(10.0 ** -digits[1])))
for move in moves:
if (current_moves
and current_moves[-1].effective_date
@@ -202,12 +216,15 @@ class Product(metaclass=PoolMeta):
if move.from_location.type == 'storage':
qty *= -1
if in_move(move):
@ -84,7 +167,7 @@ index 9eaceac..cc6e982 100644
- move.company.currency, round=False)
- unit_price = Uom.compute_price(
- move.uom, unit_price, self.default_uom)
+ if move.unit_price is not None:
+ if move.from_location.type in {'supplier', 'production'}:
+ with Transaction().set_context(date=move.effective_date):
+ unit_price = Currency.compute(
+ move.currency, move.unit_price,
@ -96,7 +179,7 @@ index 9eaceac..cc6e982 100644
if quantity + qty > 0 and quantity >= 0:
cost_price = (
(cost_price * quantity) + (unit_price * qty)
@@ -216,7 +221,7 @@ class Product(metaclass=PoolMeta):
@@ -216,7 +233,7 @@ class Product(metaclass=PoolMeta):
cost_price = unit_price
current_cost_price = cost_price.quantize(
Decimal(str(10.0 ** -digits[1])))
@ -104,3 +187,92 @@ index 9eaceac..cc6e982 100644
+ elif out_move(move):
current_out_qty += -qty
quantity += qty
diff --git a/tests/scenario_product_cost_fifo_recompute_cost_price.rst b/tests/scenario_product_cost_fifo_recompute_cost_price.rst
index f8b952f..d4f906d 100644
--- a/trytond/trytond/modules/product_cost_fifo/tests/scenario_product_cost_fifo_recompute_cost_price.rst
+++ b/trytond/trytond/modules/product_cost_fifo/tests/scenario_product_cost_fifo_recompute_cost_price.rst
@@ -45,6 +45,7 @@ Get stock locations::
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
+ >>> lost_found, = Location.find([('name', '=', "Lost and Found")])
Create some moves::
@@ -58,6 +59,12 @@ Create some moves::
... effective_date=today - dt.timedelta(days=2)).click('do')
>>> StockMove(
... product=product,
+ ... quantity=1,
+ ... from_location=lost_found,
+ ... to_location=storage_loc,
+ ... effective_date=today - dt.timedelta(days=1)).click('do')
+ >>> StockMove(
+ ... product=product,
... quantity=2,
... from_location=supplier_loc,
... to_location=storage_loc,
@@ -67,8 +74,7 @@ Create some moves::
... product=product,
... quantity=2,
... from_location=storage_loc,
- ... to_location=customer_loc,
- ... unit_price=Decimal('300'),
+ ... to_location=lost_found,
... effective_date=today - dt.timedelta(days=1)).click('do')
>>> StockMove(
... product=product,
@@ -94,11 +100,11 @@ Create some moves::
>>> [m.cost_price for m in StockMove.find([])]
- [Decimal('100.0000'), Decimal('110.0000'), Decimal('105.0000'), Decimal('110.0000'), Decimal('113.3333'), Decimal('100.0000')]
+ [Decimal('100.0000'), Decimal('116.6666'), Decimal('106.6666'), Decimal('110.0000'), Decimal('113.3333'), Decimal('113.3333'), Decimal('100.0000')]
>>> product.reload()
>>> product.cost_price
- Decimal('100.0000')
+ Decimal('99.9998')
Recompute cost price::
@@ -106,11 +112,11 @@ Recompute cost price::
>>> recompute.execute('recompute')
>>> [m.cost_price for m in StockMove.find([])]
- [Decimal('106.6667'), Decimal('106.6667'), Decimal('105.0000'), Decimal('110.0000'), Decimal('113.3333'), Decimal('100.0000')]
+ [Decimal('111.1111'), Decimal('111.1111'), Decimal('106.6666'), Decimal('110.0000'), Decimal('113.3333'), Decimal('113.3333'), Decimal('100.0000')]
>>> product.reload()
>>> product.cost_price
- Decimal('99.9999')
+ Decimal('100.0000')
Recompute cost price from a date::
@@ -119,8 +125,8 @@ Recompute cost price from a date::
>>> recompute.execute('recompute')
>>> [m.cost_price for m in StockMove.find([])]
- [Decimal('106.6667'), Decimal('106.6667'), Decimal('105.0000'), Decimal('110.0000'), Decimal('113.3333'), Decimal('100.0000')]
+ [Decimal('111.1111'), Decimal('111.1111'), Decimal('106.6666'), Decimal('110.0000'), Decimal('113.3333'), Decimal('113.3333'), Decimal('100.0000')]
>>> product.reload()
>>> product.cost_price
- Decimal('99.9999')
+ Decimal('100.0000')
diff --git a/view/configuration_form.xml b/view/configuration_form.xml
new file mode 100644
index 0000000..46c5ac5
--- /dev/null
+++ b/trytond/trytond/modules/product_cost_fifo/view/configuration_form.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!-- The COPYRIGHT file at the top level of this repository contains the full
+ copyright notices and license terms. -->
+<data>
+ <xpath expr="/form/" position="inside">
+ <field name="exclude_locations" colspan="4"/>
+ </xpath>
+</data>