diff --git a/CHANGELOG b/CHANGELOG index 68bcda4904..dbaaa4cefa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Add products_by_locations Model + Version 5.8.0 - 2020-11-02 * Bug fixes (see mercurial logs for details) * Remove support for Python 3.5 diff --git a/__init__.py b/__init__.py index a0e3032df2..d9f97d0bd0 100644 --- a/__init__.py +++ b/__init__.py @@ -25,6 +25,7 @@ def register(): location.Party, location.PartyLocation, location.ProductsByLocationsContext, + location.ProductsByLocations, location.LocationLeadTime, move.Move, shipment.ShipmentIn, diff --git a/location.py b/location.py index 88187f4110..d2fab328e5 100644 --- a/location.py +++ b/location.py @@ -4,10 +4,12 @@ import datetime import operator from decimal import Decimal +from sql import Column + from trytond.i18n import gettext from trytond.model import ( - ModelView, ModelSQL, MatchMixin, ValueMixin, DeactivableMixin, fields, - sequence_ordered, tree) + Model, ModelView, ModelSQL, MatchMixin, ValueMixin, DeactivableMixin, + fields, sequence_ordered, tree) from trytond import backend from trytond.cache import Cache from trytond.pyson import Eval, If @@ -710,6 +712,65 @@ class ProductsByLocationsContext(ModelView): return self.forecast_date +class ProductsByLocations(DeactivableMixin, ModelSQL, ModelView): + "Products by Locations" + __name__ = 'stock.products_by_locations' + + product = fields.Many2One('product.product', "Product") + quantity = fields.Function( + fields.Float( + "Quantity", digits=(16, Eval('default_uom_digits', 2)), + depends=['default_uom_digits']), + 'get_product', searcher='search_product') + forecast_quantity = fields.Function( + fields.Float( + "Forecast Quantity", digits=(16, Eval('default_uom_digits', 2)), + depends=['default_uom_digits']), + 'get_product', searcher='search_product') + default_uom = fields.Function( + fields.Many2One('product.uom', "Default UOM"), + 'get_product', searcher='search_product') + default_uom_digits = fields.Function( + fields.Integer("Default UOM Digits"), 'get_product') + cost_value = fields.Function( + fields.Numeric("Cost Value"), 'get_product') + consumable = fields.Function( + fields.Boolean("Consumable"), 'get_product', + searcher='search_product') + + @classmethod + def __setup__(cls): + super().__setup__() + cls._order.insert(0, ('product', 'ASC')) + + @classmethod + def table_query(cls): + pool = Pool() + Product = pool.get('product.product') + product = Product.__table__() + columns = [] + for fname, field in cls._fields.items(): + if not hasattr(field, 'set'): + if (isinstance(field, fields.Many2One) + and field.get_target() == Product): + column = Column(product, 'id') + else: + column = Column(product, fname) + columns.append(column.as_(fname)) + return product.select(*columns) + + def get_product(self, name): + value = getattr(self.product, name) + if isinstance(value, Model): + value = value.id + return value + + @classmethod + def search_product(cls, name, clause): + nested = clause[0].lstrip(name) + return [('product.' + name + nested,) + tuple(clause[1:])] + + class LocationLeadTime(sequence_ordered(), ModelSQL, ModelView, MatchMixin): 'Location Lead Time' __name__ = 'stock.location.lead_time' diff --git a/location.xml b/location.xml index e60ad7c2f9..870fd5c6b6 100644 --- a/location.xml +++ b/location.xml @@ -67,11 +67,16 @@ this repository contains the full copyright notices and license terms. --> products_by_locations_context_form - - Products - product.product - + + stock.products_by_locations + tree + products_by_locations_list + + + + Products by Locations + stock.products_by_locations + @@ -80,27 +85,20 @@ this repository contains the full copyright notices and license terms. --> pyson="1"/> stock.products_by_locations.context - + - - + + - - - - - - + tree_open stock.location,-1 - + - + form_relate stock.location,-1 - + diff --git a/product.py b/product.py index 9e6dc1a692..9fd2649abb 100644 --- a/product.py +++ b/product.py @@ -23,7 +23,7 @@ from trytond.transaction import Transaction from trytond.pool import Pool, PoolMeta from trytond.tools import grouped_slice -from trytond.modules.product import round_price +from trytond.modules.product import round_price, price_digits from .exceptions import ProductCostPriceError from .move import StockMixin @@ -111,14 +111,19 @@ class Template(metaclass=PoolMeta): class Product(StockMixin, object, metaclass=PoolMeta): __name__ = "product.product" - quantity = fields.Function(fields.Float('Quantity', - help="The amount of stock in the location."), + quantity = fields.Function(fields.Float( + "Quantity", digits=(16, Eval('default_uom_digits', 2)), + depends=['default_uom_digits'], + help="The amount of stock in the location."), 'get_quantity', searcher='search_quantity') - forecast_quantity = fields.Function(fields.Float('Forecast Quantity', - help="The amount of stock expected to be in the location."), + forecast_quantity = fields.Function(fields.Float( + "Forecast Quantity", digits=(16, Eval('default_uom_digits', 2)), + depends=['default_uom_digits'], + help="The amount of stock expected to be in the location."), 'get_quantity', searcher='search_quantity') - cost_value = fields.Function(fields.Numeric('Cost Value', - help="The value of the stock in the location."), + cost_value = fields.Function(fields.Numeric( + "Cost Value", digits=price_digits, + help="The value of the stock in the location."), 'get_cost_value') @classmethod @@ -149,7 +154,7 @@ class Product(StockMixin, object, metaclass=PoolMeta): for product in cls.browse(products): # The product may not have a cost price if product.cost_price is not None: - cost_values[product.id] = ( + cost_values[product.id] = round_price( Decimal(str(product.quantity)) * product.cost_price) return cost_values diff --git a/product.xml b/product.xml index d30847d100..1394414dac 100644 --- a/product.xml +++ b/product.xml @@ -3,13 +3,6 @@ this repository contains the full copyright notices and license terms. --> - - product.product - tree - - product_tree_qty - - Recompute Cost Price product.recompute_cost_price diff --git a/view/product_tree_qty.xml b/view/products_by_locations_list.xml similarity index 65% rename from view/product_tree_qty.xml rename to view/products_by_locations_list.xml index 9028e02868..0c937b675a 100644 --- a/view/product_tree_qty.xml +++ b/view/products_by_locations_list.xml @@ -2,11 +2,9 @@ - - - - - + + +