diff --git a/__init__.py b/__init__.py index ca706eb..a56c3ee 100644 --- a/__init__.py +++ b/__init__.py @@ -6,4 +6,9 @@ def register(): Pool.register( Lot, LotLocationQuantity, - module='stock_lot_location_quantity', type_='model') \ No newline at end of file + LotByLocationStart, + LotByLocationOpen, + module='stock_lot_location_quantity', type_='model'), + Pool.register( + LotByLocation, + module='stock_lot_location_quantity', type_='wizard') \ No newline at end of file diff --git a/locale/es_ES.po b/locale/es_ES.po new file mode 100644 index 0000000..8e4e320 --- /dev/null +++ b/locale/es_ES.po @@ -0,0 +1,97 @@ +# +msgid "" +msgstr "Content-Type: text/plain; charset=utf-8\n" + +msgctxt "field:stock.lot.location-quantity,id:" +msgid "ID" +msgstr "Identificador" + +msgctxt "field:stock.lot.location-quantity,location:" +msgid "Location" +msgstr "Ubicación" + +msgctxt "field:stock.lot.location-quantity,lot:" +msgid "Lot" +msgstr "Lote" + +msgctxt "field:stock.lot.location-quantity,product:" +msgid "Product" +msgstr "Producto" + +msgctxt "field:stock.lot.location-quantity,quantity:" +msgid "Quantity" +msgstr "Cantidad" + +msgctxt "field:stock.lot.location.open,forecast_date:" +msgid "At Date" +msgstr "A fecha" + +msgctxt "field:stock.lot.location.open,id:" +msgid "ID" +msgstr "Identificador" + +msgctxt "field:stock.lot.location.open,lot:" +msgid "Lot" +msgstr "Lote" + +msgctxt "field:stock.lot.location.open,product:" +msgid "Product" +msgstr "Producto" + +msgctxt "field:stock.lot.location.open,quantities:" +msgid "Stock" +msgstr "Detalle" + +msgctxt "field:stock.lot.location.start,forecast_date:" +msgid "At Date" +msgstr "A fecha" + +msgctxt "field:stock.lot.location.start,id:" +msgid "ID" +msgstr "Identificador" + +msgctxt "help:stock.lot.location.start,forecast_date:" +msgid "" +"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." +msgstr "" +"Permite calcular las cantidades previstas de stock para esta fecha.\n" +"* Un valor vacío es un fecha infinita en el futuro.\n" +"* Una fecha en el pasado proporcionará valores históricos." + +msgctxt "model:ir.action,name:wizard_stock_lot_location" +msgid "Quantity in locations" +msgstr "Cantidad en ubicaciones" + +msgctxt "model:stock.lot.location-quantity,name:" +msgid "Lot quantity by Location" +msgstr "Cantidad lote por ubicación" + +msgctxt "model:stock.lot.location.open,name:" +msgid "Lot By Location" +msgstr "Lote por ubicación" + +msgctxt "model:stock.lot.location.start,name:" +msgid "Lot By Location" +msgstr "Lote por ubicación" + +msgctxt "wizard_button:stock.lot.location,open,end:" +msgid "Close" +msgstr "Cerrar" + +msgctxt "wizard_button:stock.lot.location,start,end:" +msgid "Cancel" +msgstr "Cancelar" + +msgctxt "wizard_button:stock.lot.location,start,open:" +msgid "Get quantities" +msgstr "Cantidades" + +msgctxt "view:stock.lot.location.start:" +msgid "Lot Quantity in locations" +msgstr "Cantidad Lote en ubicaciones" + +msgctxt "view:stock.lot.location.open:" +msgid "Lot Quantity in locations" +msgstr "Cantidad Lote en ubicaciones" \ No newline at end of file diff --git a/stock.py b/stock.py index 89a8f01..81ee761 100644 --- a/stock.py +++ b/stock.py @@ -1,10 +1,14 @@ -#This file is part of Tryton. The COPYRIGHT file at the top level of -#this repository contains the full copyright notices and license terms. +# 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 trytond.model import fields, ModelView from trytond.pool import PoolMeta, Pool +from trytond.transaction import Transaction +from trytond.wizard import StateView, Button, Wizard -__all__ = ['Lot', 'LotLocationQuantity'] +__all__ = ['Lot', 'LotLocationQuantity', 'LotByLocationStart', + 'LotByLocationOpen', 'LotByLocation'] __metaclass__ = PoolMeta @@ -13,16 +17,22 @@ class Lot: __name__ = 'stock.lot' @classmethod - def lots_by_location(cls, location_ids, lot_ids=None, + def lots_by_location(cls, lot_ids, location_ids=None, with_childs=False, grouping=('product', 'lot',)): pool = Pool() Product = pool.get('product.product') Lot = pool.get('stock.lot') + Location = pool.get('stock.location') + if lot_ids: lots = Lot.search([('id', 'in', lot_ids)]) product_ids = [l.product.id for l in lots] else: product_ids = None + if not location_ids: + locations = Location.search([('type', 'in', ['storage', 'lost_found'])]) + location_ids = [l.id for l in locations] + pbl = Product.products_by_location(location_ids=location_ids, product_ids=product_ids, with_childs=with_childs, @@ -46,4 +56,81 @@ class LotLocationQuantity(ModelView): location = fields.Many2One('stock.location', 'Location', required=True, readonly=True) quantity = fields.Float('Quantity', readonly=True) - product = fields.Many2One('product.product', 'Product', readonly=True) \ No newline at end of file + product = fields.Many2One('product.product', 'Product', readonly=True) + + +class LotByLocationStart(ModelView): + """Lot By Location""" + __name__ = 'stock.lot.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 LotByLocationOpen(ModelView): + """Lot By Location""" + __name__ = 'stock.lot.location.open' + + forecast_date = fields.Date('At Date', readonly=True) + lot = fields.Many2One('stock.lot', 'Lot', readonly=True) + product = fields.Function(fields.Many2One('product.product', 'Product', readonly=True, + depends=['lot']), + 'on_change_lot') + quantities = fields.One2Many('stock.lot.location-quantity', None, 'Stock', + readonly=True) + + @fields.depends('lot') + def on_change_lot(self, name): + if self.lot: + return self.lot.product.id + + +class LotByLocation(Wizard): + """Lot By Location""" + __name__ = 'stock.lot.location' + start = StateView('stock.lot.location.start', + 'stock_lot_location_quantity.stock_lot_location_start_view_form', + [Button('Cancel', 'end', 'tryton-cancel'), + Button('Get quantities', 'open', 'tryton-ok', default=True), ]) + open = StateView('stock.lot.location.open', + 'stock_lot_location_quantity.stock_lot_location_open_view_form', + [Button('Close', 'end', 'tryton-ok', default=True)]) + + def default_open(self, fields): + pool = Pool() + Lot = pool.get('stock.lot') + + context = {} + lot_id = Transaction().context['active_id'] + lot = Lot(lot_id) + if self.start.forecast_date: + context['stock_date_end'] = self.start.forecast_date + else: + context['stock_date_end'] = datetime.date.max + + with Transaction().set_context(context): + pbl = Lot.lots_by_location(lot_ids=[lot_id], + with_childs=False) + + items = [] + result = {'forecast_date': self.start.forecast_date, + 'lot': lot_id, + 'product': lot.product.id, + 'quantities': items} + for key, quantity in pbl.iteritems(): + if quantity == 0: + continue + ps = {'location': key[0], + 'product': key[1], + 'lot': key[2], + 'quantity': quantity} + items.append(ps) + + return result \ No newline at end of file diff --git a/stock.xml b/stock.xml index 27a4708..ba3560a 100644 --- a/stock.xml +++ b/stock.xml @@ -22,5 +22,26 @@ tree stock_lot_location_quantity_list + + + stock.lot.location.start + form + stock_lot_location_start_form + + + stock.lot.location.open + form + stock_lot_location_open_form + + + Quantity in locations + stock.lot.location + stock.lot + + + form_relate + stock.lot,-1 + + \ No newline at end of file diff --git a/view/stock_lot_location_open_form.xml b/view/stock_lot_location_open_form.xml new file mode 100644 index 0000000..6198bcd --- /dev/null +++ b/view/stock_lot_location_open_form.xml @@ -0,0 +1,12 @@ + + +
+