Update the issue9724 patch, for the fifo product calculation. Remove the extra config field add on last commit and use the default warehouse configuration field. Control the return products taken the cost price from the last move with the correct cost price

This commit is contained in:
Bernat Brunet 2020-06-23 18:32:51 +02:00
parent 3252894928
commit b1d60b3582
1 changed files with 132 additions and 144 deletions

View File

@ -10,7 +10,6 @@ index 06b209f..48f9eb6 100644
-from .move import *
+from . import product
+from . import move
+from . import configuration
def register():
@ -21,131 +20,152 @@ index 06b209f..48f9eb6 100644
+ product.Template,
+ product.Product,
+ move.Move,
+ configuration.Configuration,
+ configuration.ConfigurationExcludeLocations,
module='product_cost_fifo', type_='model')
new file mode 100644
index 0000000..9d761ed
--- /dev/null
+++ b/trytond/trytond/modules/product_cost_fifo/configuration.py
@@ -0,0 +1,56 @@
+# 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 import backend
+from trytond.model import fields, ModelSQL
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval
+from trytond.tools.multivalue import migrate_property
+from trytond.modules.company.model import CompanyValueMixin
diff --git a/move.py b/move.py
index 1d4bd63..b169ac9 100644
--- a/trytond/trytond/modules/product_cost_fifo/move.py
+++ b/trytond/trytond/modules/product_cost_fifo/move.py
@@ -60,6 +60,23 @@ class Move(metaclass=PoolMeta):
column, operator, value, expression)
return expression
+ def _compute_product_cost_price(self, direction):
+ pool = Pool()
+ Location = pool.get('stock.location')
+ Config = pool.get('stock.configuration')
+
+__all__ = ['Configuration', 'ConfigurationExcludeLocations']
+ configuration = Config(1)
+ location_ids = []
+
+ if configuration.warehouse:
+ locations = Location.search([
+ ('parent', 'child_of', [configuration.warehouse]),
+ ])
+ location_ids = list(set(x.id for x in locations))
+ with Transaction().set_context(locations=location_ids):
+ self = self.__class__(self.id)
+ return super()._compute_product_cost_price(direction)
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'stock.configuration'
def _update_fifo_out_product_cost_price(self):
'''
Update the product cost price of the given product on the move. Update
@@ -121,6 +138,19 @@ class Move(metaclass=PoolMeta):
cost_price = average_cost_price
return cost_price, average_cost_price
+ def _get_last_cost_price(self):
+ pool = Pool()
+ Move = pool.get('stock.move')
+
+ exclude_location = fields.MultiValue(fields.Many2One(
+ 'stock.location', "Exclude Location",
+ domain=[
+ ('type', '=', 'warehouse'),
+ ]))
+ move = None
+ domain = self.product._domain_fifo_moves()
+ moves = Move.search(domain, limit=1,
+ order=[('effective_date', 'DESC'), ('id', 'DESC')])
+ if moves:
+ move = moves[0]
+
+ @classmethod
+ def multivalue_model(cls, field):
+ if field == 'exclude_location':
+ return Pool().get('stock.configuration.exclude_location')
+ return super().multivalue_model(field)
+ return move.cost_price if move else 0
+
+
+class ConfigurationExcludeLocations(ModelSQL, CompanyValueMixin):
+ "Configuration Exlcude Location"
+ __name__ = 'stock.configuration.exclude_location'
+
+ exclude_location = fields.Many2One(
+ 'stock.location', "Exclude Location",
+ domain=[
+ ('type', '=', 'warehouse'),
+ ])
+
+ @classmethod
+ def __register__(cls, module_name):
+ TableHandler = backend.get('TableHandler')
+ exist = TableHandler.table_exist(cls._table)
+
+ super().__register__(module_name)
+
+ if not exist:
+ cls._migrate_property([], [], [])
+
+ @classmethod
+ def _migrate_property(cls, field_names, value_names, fields):
+ field_names.extend('exclude_location')
+ value_names.extend('exclude_location')
+ fields.append('company')
+ migrate_property(
+ 'stock.configuration', field_names, cls, value_names,
+ fields=fields)
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>
def _do(self):
cost_price = super(Move, self)._do()
if (self.from_location.type in ('supplier', 'production')
@@ -138,6 +168,10 @@ class Move(metaclass=PoolMeta):
self._update_fifo_out_product_cost_price())
if self.cost_price is None:
self.cost_price = fifo_cost_price
+ elif (self.from_location.type == 'customer'
+ and self.to_location.type == 'storage'
+ and self.product.cost_price_method == 'fifo'):
+ cost_price = self._get_last_cost_price()
return cost_price
@classmethod
diff --git a/product.py b/product.py
index 9eaceac..8b5aa0a 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):
@@ -24,20 +24,51 @@ class Template(metaclass=PoolMeta):
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
- def _get_available_fifo_moves(self, date=None, offset=0, limit=None):
+ def _domain_fifo_moves(self):
pool = Pool()
- Move = pool.get('stock.move')
+ Location = pool.get('stock.location')
+ Config = pool.get('stock.configuration')
+
+ configuration = Config(1)
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:
@@ -95,7 +95,11 @@ class Product(metaclass=PoolMeta):
Move = pool.get('stock.move')
Currency = pool.get('currency.currency')
Uom = pool.get('product.uom')
+ Location = pool.get('stock.location')
+ Config = pool.get('stock.configuration')
+
digits = self.__class__.cost_price.digits
+ config = Config(1)
domain = [
('product', '=', self.id),
@@ -111,6 +115,17 @@ class Product(metaclass=PoolMeta):
],
],
- ('to_location.type', '=', 'storage'),
+ ['OR',
+ [
+ ('to_location.type', '=', 'storage'),
+ ('from_location.type', '!=', 'storage'),
+ ],
+ [
+ ('from_location.type', '=', 'storage'),
+ ('to_location.type', '!=', 'storage'),
+ ],
+ ],
]
+
+ if config.exclude_location:
+ if configuration.warehouse:
+ storage_locations = Location.search(['type', '=', 'storage'])
+ locations = Location.search([
+ ('parent', 'child_of', [config.exclude_location]),
+ ('parent', 'child_of', [configuration.warehouse]),
+ ])
+ location_ids = list(set(x.id for x in locations))
+ location_ids = list(set(x.id for x in storage_locations) -
+ set(x.id for x in locations))
+ domain.extend([
+ ('to_location.id', 'not in', location_ids),
+ ('from_location.id', 'not in', location_ids),
+ ])
+ return domain
+
+ def _get_available_fifo_moves(self, date=None, offset=0, limit=None):
+ pool = Pool()
+ Move = pool.get('stock.move')
+
+ domain = self._domain_fifo_moves()
if not date:
domain.append(('fifo_quantity_available', '>', 0))
else:
domain.append(('effective_date', '<=', date))
+
return Move.search(
domain,
offset=offset, limit=limit,
@@ -95,22 +126,9 @@ class Product(metaclass=PoolMeta):
Move = pool.get('stock.move')
Currency = pool.get('currency.currency')
Uom = pool.get('product.uom')
- digits = self.__class__.cost_price.digits
- domain = [
- ('product', '=', self.id),
- self._domain_moves_cost(),
- ['OR',
- [
- ('to_location.type', '=', 'storage'),
- ('from_location.type', '!=', 'storage'),
- ],
- [
- ('from_location.type', '=', 'storage'),
- ('to_location.type', '!=', 'storage'),
- ],
- ],
- ]
+ digits = self.__class__.cost_price.digits
+ domain = self._domain_fifo_moves()
if start:
domain.append(('effective_date', '>=', start))
moves = Move.search(
@@ -135,11 +150,10 @@ class Product(metaclass=PoolMeta):
@@ -135,11 +153,10 @@ class Product(metaclass=PoolMeta):
quantity = Decimal(str(quantity))
def in_move(move):
@ -159,7 +179,7 @@ index 9eaceac..8b5aa0a 100644
def compute_fifo_cost_price(quantity, date):
fifo_moves = self.get_fifo_move(
@@ -150,12 +164,15 @@ class Product(metaclass=PoolMeta):
@@ -150,12 +167,15 @@ class Product(metaclass=PoolMeta):
consumed_qty = 0
for move, move_qty in fifo_moves:
consumed_qty += move_qty
@ -181,7 +201,7 @@ index 9eaceac..8b5aa0a 100644
cost_price += unit_price * Decimal(str(move_qty))
if consumed_qty:
return (cost_price / Decimal(str(consumed_qty))).quantize(
@@ -163,7 +180,8 @@ class Product(metaclass=PoolMeta):
@@ -163,7 +183,8 @@ class Product(metaclass=PoolMeta):
current_moves = []
current_out_qty = 0
@ -191,7 +211,16 @@ index 9eaceac..8b5aa0a 100644
for move in moves:
if (current_moves
and current_moves[-1].effective_date
@@ -202,12 +220,15 @@ class Product(metaclass=PoolMeta):
@@ -189,7 +210,7 @@ class Product(metaclass=PoolMeta):
quantity + current_out_qty))
- (fifo_cost_price * current_out_qty))
/ quantity)
- else:
+ elif move.from_location.type != 'customer':
cost_price = Decimal(0)
current_cost_price = cost_price.quantize(
Decimal(str(10.0 ** -digits[1])))
@@ -202,12 +223,15 @@ class Product(metaclass=PoolMeta):
if move.from_location.type == 'storage':
qty *= -1
if in_move(move):
@ -213,7 +242,7 @@ index 9eaceac..8b5aa0a 100644
if quantity + qty > 0 and quantity >= 0:
cost_price = (
(cost_price * quantity) + (unit_price * qty)
@@ -216,7 +237,7 @@ class Product(metaclass=PoolMeta):
@@ -216,7 +240,7 @@ class Product(metaclass=PoolMeta):
cost_price = unit_price
current_cost_price = cost_price.quantize(
Decimal(str(10.0 ** -digits[1])))
@ -296,44 +325,3 @@ index f8b952f..d4f906d 100644
>>> product.cost_price
- Decimal('99.9999')
+ Decimal('100.0000')
diff --git a/tryton.cfg b/tryton.cfg
index dbe44d2..529bcc8 100644
--- a/trytond/trytond/modules/product_cost_fifo/tryton.cfg
+++ b/trytond/trytond/modules/product_cost_fifo/tryton.cfg
@@ -6,3 +6,4 @@ depends:
stock
xml:
message.xml
+ configuration.xml
new file mode 100644
index 0000000..b6a45ed
--- /dev/null
+++ b/trytond/trytond/modules/product_cost_fifo/view/configuration_form.xml
@@ -0,0 +1,9 @@
+<?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/field[@name='shipment_internal_transit']" position="after">
+ <label name="exclude_location"/>
+ <field name="exclude_location"/>
+ </xpath>
+</data>
diff --git a/production.py b/production.py
index 867f0ea..3cd2295 100644
--- a/trytond/trytond/modules/production/production.py
+++ b/trytond/trytond/modules/production/production.py
@@ -514,8 +514,11 @@ class Production(Workflow, ModelSQL, ModelView):
else:
ratio = Decimal(1) / len(production.outputs)
quantity = Decimal(str(output.quantity))
- unit_price = (
- production.cost * ratio / quantity).quantize(digits)
+ if quantity:
+ unit_price = (
+ production.cost * ratio / quantity).quantize(digits)
+ else:
+ unit_price = Decimal(0)
if output.unit_price != unit_price:
output.unit_price = unit_price
moves.append(output)