From 8764236bb9f2750ef5e8f1d24ad0f14a813e4ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 19 Jun 2020 00:24:56 +0200 Subject: [PATCH] Use all moves to compute FIFO We must consider any incoming moves (ex: inventory) for the computation of the FIFO otherwise the back computation to find first in moves does not pick enough moves. As not all incoming moves have a unit price, we use the current cost price as fallback. Also in re-computation, the in or out move test should only rely on the storage location usage in order to properly compute the average cost. issue9274 review321471002 --- move.py | 16 +++++++++------- product.py | 39 ++++++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/move.py b/move.py index a33fbd9cca..1235b326f7 100644 --- a/move.py +++ b/move.py @@ -81,13 +81,15 @@ class Move(metaclass=PoolMeta): to_save = [] for move, move_qty in fifo_moves: consumed_qty += move_qty - - with Transaction().set_context(date=move.effective_date): - move_unit_price = Currency.compute( - move.currency, move.unit_price, - self.company.currency, round=False) - move_unit_price = Uom.compute_price(move.uom, move_unit_price, - move.product.default_uom) + 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, + self.company.currency, round=False) + move_unit_price = Uom.compute_price( + move.uom, move_unit_price, move.product.default_uom) + 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 cb3dbf3f53..8afd781b2e 100644 --- a/product.py +++ b/product.py @@ -31,7 +31,7 @@ class Product(metaclass=PoolMeta): domain = [ ('product', '=', self.id), self._domain_moves_cost(), - ('from_location.type', 'in', ['supplier', 'production']), + ('from_location.type', '!=', 'storage'), ('to_location.type', '=', 'storage'), ] if not date: @@ -137,11 +137,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( @@ -152,12 +151,15 @@ class Product(metaclass=PoolMeta): consumed_qty = 0 for move, move_qty in fifo_moves: consumed_qty += move_qty - with Transaction().set_context(date=move.effective_date): - unit_price = Currency.compute( - move.currency, move.unit_price, - move.company.currency, round=False) - unit_price = Uom.compute_price( - move.uom, unit_price, move.product.default_uom) + 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, + move.company.currency, round=False) + unit_price = Uom.compute_price( + move.uom, unit_price, move.product.default_uom) + else: + unit_price = move.cost_price or 0 cost_price += unit_price * Decimal(str(move_qty)) if consumed_qty: return round_price(cost_price / Decimal(str(consumed_qty))) @@ -204,12 +206,15 @@ class Product(metaclass=PoolMeta): if move.from_location.type == 'storage': qty *= -1 if in_move(move): - with Transaction().set_context(date=move.effective_date): - unit_price = Currency.compute( - move.currency, move.unit_price, - move.company.currency, round=False) - unit_price = Uom.compute_price( - move.uom, unit_price, self.default_uom) + 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, + move.company.currency, round=False) + unit_price = Uom.compute_price( + move.uom, unit_price, self.default_uom) + else: + unit_price = cost_price if quantity + qty > 0 and quantity >= 0: cost_price = ( (cost_price * quantity) + (unit_price * qty) @@ -217,7 +222,7 @@ class Product(metaclass=PoolMeta): elif qty > 0: cost_price = unit_price current_cost_price = round_price(cost_price) - else: + elif out_move(move): current_out_qty += -qty quantity += qty