diff --git a/issue239_630.diff b/issue239_630.diff new file mode 100644 index 0000000..5413783 --- /dev/null +++ b/issue239_630.diff @@ -0,0 +1,33 @@ +Index: location.py +=================================================================== + +--- ./modules/stock/location.py ++++ ./modules/stock/location.py +@@ -160,6 +160,11 @@ + return [(cls._rec_name,) + tuple(clause[1:])] + + @classmethod ++ def _quantity_grouping_and_key(cls): ++ product_id = Transaction().context['product'] ++ return ('product', ), (product_id,) ++ ++ @classmethod + def get_quantity(cls, locations, name): + pool = Pool() + Product = pool.get('product.product') +@@ -189,11 +194,12 @@ + + location_ids = [l.id for l in locations] + product_id = Transaction().context['product'] ++ grouping, key = cls._quantity_grouping_and_key() + with Transaction().set_context(context): + pbl = Product.products_by_location(location_ids=location_ids, +- product_ids=[product_id], with_childs=True) ++ product_ids=[product_id], with_childs=True, grouping=grouping) + +- return dict((loc, pbl.get((loc, product_id), 0)) ++ return dict((loc, pbl.get((loc,) + key, 0)) + for loc in location_ids) + + @classmethod + diff --git a/issue240_631.diff b/issue240_631.diff new file mode 100644 index 0000000..afc20ec --- /dev/null +++ b/issue240_631.diff @@ -0,0 +1,169 @@ +Index: __init__.py +=================================================================== + +--- ./modules/stock_lot/__init__.py ++++ ./modules/stock_lot/__init__.py +@@ -21,4 +21,9 @@ + Template, + Product, + TemplateLotType, ++ Location, ++ LotByLocationStart, + module='stock_lot', type_='model') ++ Pool.register( ++ LotByLocation, ++ module='stock_lot', type_='wizard') + +Index: stock.py +=================================================================== + +--- ./modules/stock_lot/stock.py ++++ ./modules/stock_lot/stock.py +@@ -1,17 +1,20 @@ + #This file is part of Tryton. The COPYRIGHT file at the top level of + #this repository contains the full copyright notices and license terms. ++import datetime + from collections import defaultdict + + from trytond.model import ModelView, ModelSQL, Workflow, fields +-from trytond.pyson import Eval ++from trytond.pyson import PYSONEncoder, Eval + from trytond.pool import Pool, PoolMeta + from trytond.transaction import Transaction ++from trytond.wizard import Wizard, StateView, StateAction, Button + from trytond.modules.stock import StockMixin + + __all__ = ['Lot', 'LotType', 'Move', 'ShipmentIn', 'ShipmentOut', + 'ShipmentOutReturn', + 'Period', 'PeriodCacheLot', +- 'Inventory', 'InventoryLine'] ++ 'Inventory', 'InventoryLine', ++ 'Location', 'LotByLocation', 'LotByLocationStart'] + __metaclass__ = PoolMeta + + +@@ -294,3 +297,73 @@ + if move: + move.lot = self.lot + return move ++ ++ ++class Location: ++ __name__ = 'stock.location' ++ ++ @classmethod ++ def _quantity_grouping_and_key(cls): ++ if Transaction().context.get('lot'): ++ lot_id = Transaction().context['lot'] ++ product_id = Transaction().context['product'] ++ return ('product', 'lot'), (product_id, lot_id) ++ return super(Location, cls)._quantity_grouping_and_key() ++ ++ ++class LotByLocationStart(ModelView): ++ 'Lot by Location' ++ __name__ = 'stock.lot.by_location.start' ++ forecast_date = fields.Date( ++ 'At Date', help=('Allow to compute expected ' ++ 'stock quantities for this date.\n' ++ '* An empty value is an infinite date in the future.\n' ++ '* A date in the past will provide historical values.')) ++ ++ @staticmethod ++ def default_forecast_date(): ++ Date = Pool().get('ir.date') ++ return Date.today() ++ ++ ++class LotByLocation(Wizard): ++ 'Lot by Location' ++ __name__ = 'stock.lot.by_location' ++ start = StateView('stock.lot.by_location.start', ++ 'stock_lot.lot_by_location_start_view_form', [ ++ Button('Cancel', 'end', 'tryton-cancel'), ++ Button('Open', 'open', 'tryton-ok', default=True), ++ ]) ++ open = StateAction('stock.act_location_quantity_tree') ++ ++ def do_open(self, action): ++ pool = Pool() ++ Lot = pool.get('stock.lot') ++ Lang = pool.get('ir.lang') ++ ++ context = {} ++ lot_id = Transaction().context['active_id'] ++ context['lot'] = lot_id ++ ++ lot = Lot(lot_id) ++ context['product'] = lot.product.id ++ ++ if self.start.forecast_date: ++ context['stock_date_end'] = self.start.forecast_date ++ else: ++ context['stock_date_end'] = datetime.date.max ++ action['pyson_context'] = PYSONEncoder().encode(context) ++ ++ for code in [Transaction().language, 'en_US']: ++ langs = Lang.search([ ++ ('code', '=', code), ++ ]) ++ if langs: ++ break ++ lang, = langs ++ date = Lang.strftime(context['stock_date_end'], ++ lang.code, lang.date) ++ ++ action['name'] += ' - %s (%s) @ %s' % (lot.rec_name, ++ lot.product.default_uom.rec_name, date) ++ return action, {} + +Index: stock.xml +=================================================================== + +--- ./modules/stock_lot/stock.xml ++++ ./modules/stock_lot/stock.xml +@@ -48,6 +48,28 @@ + + + ++ ++ Lot by Locations ++ stock.lot.by_location ++ stock.lot ++ ++ ++ form_relate ++ stock.lot,-1 ++ ++ ++ ++ ++ ++ ++ ++ ++ stock.lot.by_location.start ++ form ++ lot_by_location_start_form ++ ++ + + supplier + Supplier + +Index: view/lot_by_location_start_form.xml +=================================================================== +new file mode 100644 + +--- /dev/null ++++ ./modules/stock_lot/view/lot_by_location_start_form.xml +@@ -0,0 +1,7 @@ ++ ++ ++
++