From 5db3170b5306c4a26c62e6674f42ce229a0654bd Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Sat, 27 Jun 2015 20:42:48 +0200 Subject: [PATCH 01/24] [IMP] stock_inventory_preparation_filter: Preparation for OCA --- stock_inventory_preparation_filter/README.rst | 59 +++++++ .../__init__.py | 19 +++ .../__openerp__.py | 41 +++++ stock_inventory_preparation_filter/i18n/es.po | 113 ++++++++++++++ stock_inventory_preparation_filter/i18n/fr.po | 112 +++++++++++++ .../stock_inventory_preparation_filters.pot | 113 ++++++++++++++ .../models/__init__.py | 19 +++ .../models/stock_inventory.py | 133 ++++++++++++++++ .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../tests/__init__.py | 17 ++ ...test_stock_inventory_preparation_filter.py | 147 ++++++++++++++++++ .../views/stock_inventory_view.xml | 45 ++++++ 13 files changed, 821 insertions(+) create mode 100644 stock_inventory_preparation_filter/README.rst create mode 100644 stock_inventory_preparation_filter/__init__.py create mode 100644 stock_inventory_preparation_filter/__openerp__.py create mode 100644 stock_inventory_preparation_filter/i18n/es.po create mode 100644 stock_inventory_preparation_filter/i18n/fr.po create mode 100644 stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot create mode 100644 stock_inventory_preparation_filter/models/__init__.py create mode 100644 stock_inventory_preparation_filter/models/stock_inventory.py create mode 100644 stock_inventory_preparation_filter/security/ir.model.access.csv create mode 100644 stock_inventory_preparation_filter/static/description/icon.png create mode 100644 stock_inventory_preparation_filter/tests/__init__.py create mode 100644 stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py create mode 100644 stock_inventory_preparation_filter/views/stock_inventory_view.xml diff --git a/stock_inventory_preparation_filter/README.rst b/stock_inventory_preparation_filter/README.rst new file mode 100644 index 000000000..7f69a754c --- /dev/null +++ b/stock_inventory_preparation_filter/README.rst @@ -0,0 +1,59 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================================== +More preparation filters for inventories +======================================== + +Includes more options for making an inventory out of: + +* Multiple products. +* Products of a category. +* Multiple lots + +It also allows to make an inventory based on scanned products, adding a line +with product code and quantity. + +Usage +===== + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/153/8.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed `feedback +`_. + +Credits +======= + +Contributors +------------ + +* Oihane Crucelaegui +* Pedro M. Baeza + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/stock_inventory_preparation_filter/__init__.py b/stock_inventory_preparation_filter/__init__.py new file mode 100644 index 000000000..7fc7c09f9 --- /dev/null +++ b/stock_inventory_preparation_filter/__init__.py @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from . import models diff --git a/stock_inventory_preparation_filter/__openerp__.py b/stock_inventory_preparation_filter/__openerp__.py new file mode 100644 index 000000000..3970d655f --- /dev/null +++ b/stock_inventory_preparation_filter/__openerp__.py @@ -0,0 +1,41 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +{ + "name": "Extended Inventory Preparation Filters", + "version": "8.0.1.0.0", + "depends": [ + "stock", + ], + "author": "OdooMRP team," + "AvanzOSC," + "Serv. Tecnol. Avanzados - Pedro M. Baeza," + "Odoo Community Association (OCA)", + "contributors": [ + "Oihane Crucelaegui ", + "Pedro M. Baeza ", + ], + "category": "Inventory, Logistic, Storage", + "website": "http://www.odoomrp.com", + "summary": "More filters for inventory adjustments", + "data": [ + "views/stock_inventory_view.xml", + "security/ir.model.access.csv", + ], + "installable": True, +} diff --git a/stock_inventory_preparation_filter/i18n/es.po b/stock_inventory_preparation_filter/i18n/es.po new file mode 100644 index 000000000..baa74a0f9 --- /dev/null +++ b/stock_inventory_preparation_filter/i18n/es.po @@ -0,0 +1,113 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_inventory_preparation_filters +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0rc1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-30 08:59+0000\n" +"PO-Revision-Date: 2014-07-30 11:01+0100\n" +"Last-Translator: Oihane \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" + +#. module: stock_inventory_preparation_filters +#: view:stock.inventory:0 +#: field:stock.inventory,empty_line_ids:0 +msgid "Capture Lines" +msgstr "Líneas capturadas" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,categ_ids:0 +msgid "Categories" +msgstr "Categorias" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,create_uid:0 +msgid "Created by" +msgstr "Creado por" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,create_date:0 +msgid "Created on" +msgstr "Creado el" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:66 +#, python-format +msgid "Empty list" +msgstr "Lista vacía" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,id:0 +msgid "ID" +msgstr "ID" + +#. module: stock_inventory_preparation_filters +#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory +#: field:stock.inventory.line.empty,inventory_id:0 +msgid "Inventory" +msgstr "Inventario" + +#. module: stock_inventory_preparation_filters +#: view:stock.inventory:0 +msgid "Inventory Details" +msgstr "Detalles del inventario" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,write_uid:0 +msgid "Last Updated by" +msgstr "Actualizado por" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,write_date:0 +msgid "Last Updated on" +msgstr "Actualizado el" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,lot_ids:0 +msgid "Lots" +msgstr "Lotes" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,product_code:0 +msgid "Product Code" +msgstr "Codigo de producto" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,product_ids:0 +msgid "Products" +msgstr "Productos" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,product_qty:0 +msgid "Quantity" +msgstr "Cantidad" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:61 +#, python-format +msgid "Selected Categories" +msgstr "Categorias seleccionadas" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:65 +#, python-format +msgid "Selected Lots" +msgstr "Lotes seleccionados" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:62 +#, python-format +msgid "Selected Products" +msgstr "Productos seleccionados" + +#. module: stock_inventory_preparation_filters +#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory_line_empty +msgid "stock.inventory.line.empty" +msgstr "stock.inventory.line.empty" + diff --git a/stock_inventory_preparation_filter/i18n/fr.po b/stock_inventory_preparation_filter/i18n/fr.po new file mode 100644 index 000000000..84c7e2eca --- /dev/null +++ b/stock_inventory_preparation_filter/i18n/fr.po @@ -0,0 +1,112 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_inventory_preparation_filters +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0rc1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-30 08:59+0000\n" +"PO-Revision-Date: 2015-06-27 11:09+0100\n" +"Last-Translator: Antoine Morit \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 1.5.4\n" + +#. module: stock_inventory_preparation_filters +#: view:stock.inventory:0 field:stock.inventory,empty_line_ids:0 +msgid "Capture Lines" +msgstr "Lignes extraites" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,categ_ids:0 +msgid "Categories" +msgstr "Catégories" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,create_uid:0 +msgid "Created by" +msgstr "Créé par" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,create_date:0 +msgid "Created on" +msgstr "Créé le" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:66 +#, python-format +msgid "Empty list" +msgstr "Liste vide" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,id:0 +msgid "ID" +msgstr "ID" + +#. module: stock_inventory_preparation_filters +#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory +#: field:stock.inventory.line.empty,inventory_id:0 +msgid "Inventory" +msgstr "Inventaire" + +#. module: stock_inventory_preparation_filters +#: view:stock.inventory:0 +msgid "Inventory Details" +msgstr "Détails de l'inventaire" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,write_uid:0 +msgid "Last Updated by" +msgstr "Dernière màj par" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,write_date:0 +msgid "Last Updated on" +msgstr "Dernière màj le" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,lot_ids:0 +msgid "Lots" +msgstr "Lots" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,product_code:0 +msgid "Product Code" +msgstr "Code produit" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,product_ids:0 +msgid "Products" +msgstr "Produits" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,product_qty:0 +msgid "Quantity" +msgstr "Quantité" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:61 +#, python-format +msgid "Selected Categories" +msgstr "Catégories sélectionnées" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:65 +#, python-format +msgid "Selected Lots" +msgstr "Lots sélectionnés" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:62 +#, python-format +msgid "Selected Products" +msgstr "Produits sélectionnés" + +#. module: stock_inventory_preparation_filters +#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory_line_empty +msgid "stock.inventory.line.empty" +msgstr "stock.inventory.line.empty" diff --git a/stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot b/stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot new file mode 100644 index 000000000..4a7f7738d --- /dev/null +++ b/stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot @@ -0,0 +1,113 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_inventory_preparation_filters +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0rc1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-30 08:58+0000\n" +"PO-Revision-Date: 2014-07-30 08:58+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_inventory_preparation_filters +#: view:stock.inventory:0 +#: field:stock.inventory,empty_line_ids:0 +msgid "Capture Lines" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,categ_ids:0 +msgid "Categories" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,create_date:0 +msgid "Created on" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:66 +#, python-format +msgid "Empty list" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,id:0 +msgid "ID" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory +#: field:stock.inventory.line.empty,inventory_id:0 +msgid "Inventory" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: view:stock.inventory:0 +msgid "Inventory Details" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,lot_ids:0 +msgid "Lots" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,product_code:0 +msgid "Product Code" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory,product_ids:0 +msgid "Products" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: field:stock.inventory.line.empty,product_qty:0 +msgid "Quantity" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:61 +#, python-format +msgid "Selected Categories" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:65 +#, python-format +msgid "Selected Lots" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:62 +#, python-format +msgid "Selected Products" +msgstr "" + +#. module: stock_inventory_preparation_filters +#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory_line_empty +msgid "stock.inventory.line.empty" +msgstr "" + diff --git a/stock_inventory_preparation_filter/models/__init__.py b/stock_inventory_preparation_filter/models/__init__.py new file mode 100644 index 000000000..6149c9932 --- /dev/null +++ b/stock_inventory_preparation_filter/models/__init__.py @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from . import stock_inventory diff --git a/stock_inventory_preparation_filter/models/stock_inventory.py b/stock_inventory_preparation_filter/models/stock_inventory.py new file mode 100644 index 000000000..00e0d147b --- /dev/null +++ b/stock_inventory_preparation_filter/models/stock_inventory.py @@ -0,0 +1,133 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +############################################################################## + +from openerp import models, fields, api, _ + + +class StockInventoryEmptyLines(models.Model): + _name = 'stock.inventory.line.empty' + + product_code = fields.Char( + string='Product Code', size=64, required=True) + product_qty = fields.Float( + string='Quantity', required=True, default=1.0) + inventory_id = fields.Many2one( + comodel_name='stock.inventory', string='Inventory', + required=True, ondelete="cascade") + + +class StockInventoryFake(object): + def __init__(self, inventory, product=None, lot=None): + self.id = inventory.id + self.location_id = inventory.location_id + self.product_id = product + self.lot_id = lot + self.partner_id = inventory.partner_id + self.package_id = inventory.package_id + + +class StockInventory(models.Model): + _inherit = 'stock.inventory' + + @api.model + def _get_available_filters(self): + """This function will return the list of filters allowed according to + the options checked in 'Settings/Warehouse'. + + :return: list of tuple + """ + res_filters = super(StockInventory, self)._get_available_filters() + res_filters.append(('categories', _('Selected Categories'))) + res_filters.append(('products', _('Selected Products'))) + for res_filter in res_filters: + if res_filter[0] == 'lot': + res_filters.append(('lots', _('Selected Lots'))) + res_filters.append(('empty', _('Empty list'))) + return res_filters + + filter = fields.Selection( + selection=_get_available_filters, string='Selection Filter', + required=True) + categ_ids = fields.Many2many( + comodel_name='product.category', relation='rel_inventories_categories', + column1='inventory_id', column2='category_id', string='Categories') + product_ids = fields.Many2many( + comodel_name='product.product', relation='rel_inventories_products', + column1='inventory_id', column2='product_id', string='Products') + lot_ids = fields.Many2many( + comodel_name='stock.production.lot', relation='rel_inventories_lots', + column1='inventory_id', column2='lot_id', string='Lots') + empty_line_ids = fields.One2many( + comodel_name='stock.inventory.line.empty', inverse_name='inventory_id', + string='Capture Lines') + + @api.model + def _get_inventory_lines(self, inventory): + vals = [] + product_tmpl_obj = self.env['product.template'] + product_obj = self.env['product.product'] + if inventory.filter in ('categories', 'products'): + products = product_obj + if inventory.filter == 'categories': + product_tmpls = product_tmpl_obj.search( + [('categ_id', 'in', inventory.categ_ids.ids)]) + products = product_obj.search( + [('product_tmpl_id', 'in', product_tmpls.ids)]) + elif inventory.filter == 'products': + products = inventory.product_ids + for product in products: + fake_inventory = StockInventoryFake(inventory, product=product) + vals += super(StockInventory, self)._get_inventory_lines( + fake_inventory) + elif inventory.filter == 'lots': + for lot in inventory.lot_ids: + fake_inventory = StockInventoryFake(inventory, lot=lot) + vals += super(StockInventory, self)._get_inventory_lines( + fake_inventory) + elif inventory.filter == 'empty': + tmp_lines = {} + empty_line_obj = self.env['stock.inventory.line.empty'] + for line in inventory.empty_line_ids: + if line.product_code in tmp_lines: + tmp_lines[line.product_code] += line.product_qty + else: + tmp_lines[line.product_code] = line.product_qty + inventory.empty_line_ids.unlink() + for product_code in tmp_lines.keys(): + products = product_obj.search( + [('default_code', '=', product_code)]) + if products: + product = products[0] + fake_inventory = StockInventoryFake( + inventory, product=product) + values = super(StockInventory, self)._get_inventory_lines( + fake_inventory) + if values: + values[0]['product_qty'] = tmp_lines[product_code] + else: + empty_line_obj.create( + { + 'product_code': product_code, + 'product_qty': tmp_lines[product_code], + 'inventory_id': inventory.id, + }) + vals += values + else: + vals = super(StockInventory, self)._get_inventory_lines( + inventory) + return vals diff --git a/stock_inventory_preparation_filter/security/ir.model.access.csv b/stock_inventory_preparation_filter/security/ir.model.access.csv new file mode 100644 index 000000000..723cb2057 --- /dev/null +++ b/stock_inventory_preparation_filter/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_stock_inventory_line_empty_user,access_stock_inventory_line_empty_user,model_stock_inventory_line_empty,stock.group_stock_user,1,0,0,0 +access_stock_inventory_line_empty_manager,access_stock_inventory_line_empty_manager,model_stock_inventory_line_empty,stock.group_stock_manager,1,1,1,1 diff --git a/stock_inventory_preparation_filter/static/description/icon.png b/stock_inventory_preparation_filter/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/stock_inventory_preparation_filter/tests/__init__.py b/stock_inventory_preparation_filter/tests/__init__.py new file mode 100644 index 000000000..79299bb59 --- /dev/null +++ b/stock_inventory_preparation_filter/tests/__init__.py @@ -0,0 +1,17 @@ +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +from . import test_stock_inventory_preparation_filter diff --git a/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py b/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py new file mode 100644 index 000000000..5ef493c3f --- /dev/null +++ b/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py @@ -0,0 +1,147 @@ +############################################################################## +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +import openerp.tests.common as common + + +class TestStockInventoryPreparationFilterCategories(common.TransactionCase): + + def setUp(self): + super(TestStockInventoryPreparationFilterCategories, self).setUp() + self.inventory_model = self.env['stock.inventory'] + # Create a category + self.category = self.env['product.category'].create( + { + 'name': 'Category for inventory', + 'type': 'normal', + }) + # Create some products in the category + self.product1 = self.env['product.product'].create( + { + 'name': 'Product for inventory 1', + 'type': 'product', + 'categ_id': self.category.id, + 'default_code': 'PROD1', + } + ) + self.product2 = self.env['product.product'].create( + { + 'name': 'Product for inventory 2', + 'type': 'product', + 'categ_id': self.category.id, + 'default_code': 'PROD2', + } + ) + # And have some stock in a location + self.location = self.env['stock.location'].create( + { + 'name': 'Inventory tests', + 'usage': 'internal', + } + ) + inventory = self.inventory_model.create( + { + 'name': 'Product1 inventory', + 'filter': 'product', + 'line_ids': [ + (0, 0, { + 'product_id': self.product1.id, + 'product_uom_id': self.env.ref( + "product.product_uom_unit").id, + 'product_qty': 2.0, + 'location_id': self.location.id, + }), + (0, 0, { + 'product_id': self.product2.id, + 'product_uom_id': self.env.ref( + "product.product_uom_unit").id, + 'product_qty': 4.0, + 'location_id': self.location.id, + }), + ], + }) + inventory.action_done() + + def test_inventory_category_filter(self): + inventory = self.inventory_model.create( + { + 'name': 'Category inventory', + 'filter': 'categories', + 'location_id': self.location.id, + 'categ_ids': [(6, 0, [self.category.id])], + } + ) + inventory.prepare_inventory() + self.assertEqual(len(inventory.line_ids), 2) + line1 = inventory.line_ids[0] + self.assertEqual(line1.product_id, self.product1) + self.assertEqual(line1.theoretical_qty, 2.0) + self.assertEqual(line1.location_id, self.location) + line2 = inventory.line_ids[1] + self.assertEqual(line2.product_id, self.product2) + self.assertEqual(line2.theoretical_qty, 4.0) + self.assertEqual(line2.location_id, self.location) + + def test_inventory_products_filter(self): + inventory = self.inventory_model.create( + { + 'name': 'Products inventory', + 'filter': 'products', + 'location_id': self.location.id, + 'product_ids': [(6, 0, [self.product1.id, self.product2.id])], + } + ) + inventory.prepare_inventory() + self.assertEqual(len(inventory.line_ids), 2) + line1 = inventory.line_ids[0] + self.assertEqual(line1.product_id, self.product1) + self.assertEqual(line1.theoretical_qty, 2.0) + self.assertEqual(line1.location_id, self.location) + line2 = inventory.line_ids[1] + self.assertEqual(line2.product_id, self.product2) + self.assertEqual(line2.theoretical_qty, 4.0) + self.assertEqual(line2.location_id, self.location) + + def test_inventory_empty_filter(self): + inventory = self.inventory_model.create( + { + 'name': 'Products inventory', + 'filter': 'empty', + 'location_id': self.location.id, + 'empty_line_ids': [ + (0, 0, { + 'product_code': 'PROD1', + 'product_qty': 3.0, + }), + (0, 0, { + 'product_code': 'PROD2', + 'product_qty': 7.0, + }), + ], + } + ) + inventory.prepare_inventory() + self.assertEqual(len(inventory.line_ids), 2) + line1 = inventory.line_ids[0] + self.assertEqual(line1.product_id, self.product1) + self.assertEqual(line1.theoretical_qty, 2.0) + self.assertEqual(line1.product_qty, 3.0) + self.assertEqual(line1.location_id, self.location) + line2 = inventory.line_ids[1] + self.assertEqual(line2.product_id, self.product2) + self.assertEqual(line2.theoretical_qty, 4.0) + self.assertEqual(line2.product_qty, 7.0) + self.assertEqual(line2.location_id, self.location) diff --git a/stock_inventory_preparation_filter/views/stock_inventory_view.xml b/stock_inventory_preparation_filter/views/stock_inventory_view.xml new file mode 100644 index 000000000..cb9109413 --- /dev/null +++ b/stock_inventory_preparation_filter/views/stock_inventory_view.xml @@ -0,0 +1,45 @@ + + + + + stock.inventory.form + stock.inventory + + + + + + + + {'invisible':[('state','=','draft')]} + + + + + + + + + + + + + + + + + + + + + + + + From ac4c7f8cf2cc8f8c2526c746cf538deaa50eaeb2 Mon Sep 17 00:00:00 2001 From: Jos De Graeve Date: Wed, 11 May 2016 16:55:00 +0200 Subject: [PATCH 02/24] FIX stock_inventory_preparation_filter search EAN13 for scanned products When using the feature 'allows to make an inventory based on scanned products', users might expect they can use the EAN13 barcode for scanning their products. --- .../models/stock_inventory.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stock_inventory_preparation_filter/models/stock_inventory.py b/stock_inventory_preparation_filter/models/stock_inventory.py index 00e0d147b..8fa5669fd 100644 --- a/stock_inventory_preparation_filter/models/stock_inventory.py +++ b/stock_inventory_preparation_filter/models/stock_inventory.py @@ -109,8 +109,10 @@ class StockInventory(models.Model): tmp_lines[line.product_code] = line.product_qty inventory.empty_line_ids.unlink() for product_code in tmp_lines.keys(): - products = product_obj.search( - [('default_code', '=', product_code)]) + products = product_obj.search([ + '|', ('default_code', '=', product_code), + ('ean13', '=', product_code), + ]) if products: product = products[0] fake_inventory = StockInventoryFake( From 4842244df89d1e94fc5b88ac0655bd4719f90806 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 4 Jan 2018 20:18:07 +0100 Subject: [PATCH 03/24] [MIG] stock_inventory_preparation_filter: Migration to 10.0 --- stock_inventory_preparation_filter/README.rst | 11 +- .../__init__.py | 16 -- .../__manifest__.py | 25 ++ .../__openerp__.py | 41 ---- .../stock_inventory_preparation_filters.pot | 113 --------- .../models/__init__.py | 18 +- .../models/stock_inventory.py | 154 ++++++------- .../tests/__init__.py | 18 +- ...test_stock_inventory_preparation_filter.py | 214 +++++++++++------- .../views/stock_inventory_view.xml | 11 +- 10 files changed, 231 insertions(+), 390 deletions(-) create mode 100644 stock_inventory_preparation_filter/__manifest__.py delete mode 100644 stock_inventory_preparation_filter/__openerp__.py delete mode 100644 stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot diff --git a/stock_inventory_preparation_filter/README.rst b/stock_inventory_preparation_filter/README.rst index 7f69a754c..bae4ea0c8 100644 --- a/stock_inventory_preparation_filter/README.rst +++ b/stock_inventory_preparation_filter/README.rst @@ -20,7 +20,7 @@ Usage .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/153/8.0 + :target: https://runbot.odoo-community.org/runbot/153/10.0 Bug Tracker =========== @@ -28,11 +28,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, -help us smashing it by providing a detailed and welcomed `feedback -`_. +help us smash it by providing detailed and welcomed feedback. Credits ======= @@ -41,7 +37,8 @@ Contributors ------------ * Oihane Crucelaegui -* Pedro M. Baeza +* Pedro M. Baeza +* David Vidal Maintainer ---------- diff --git a/stock_inventory_preparation_filter/__init__.py b/stock_inventory_preparation_filter/__init__.py index 7fc7c09f9..21ff7c22f 100644 --- a/stock_inventory_preparation_filter/__init__.py +++ b/stock_inventory_preparation_filter/__init__.py @@ -1,19 +1,3 @@ # -*- encoding: utf-8 -*- -############################################################################## -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## from . import models diff --git a/stock_inventory_preparation_filter/__manifest__.py b/stock_inventory_preparation_filter/__manifest__.py new file mode 100644 index 000000000..56366872b --- /dev/null +++ b/stock_inventory_preparation_filter/__manifest__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 AvanzOSC - Oihane Crucelaegi +# Copyright 2015 Tecnativa - Pedro M. Baeza +# Copyright 2017 Tecnativa - David Vidal +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Extended Inventory Preparation Filters", + "version": "10.0.1.0.0", + "depends": [ + "stock", + ], + "author": "AvanzOSC," + "Tecnativa," + "Odoo Community Association (OCA)", + "category": "Inventory, Logistic, Storage", + "website": "http://github.com/OCA/stock-logistics-workflow", + "summary": "More filters for inventory adjustments", + "data": [ + "views/stock_inventory_view.xml", + "security/ir.model.access.csv", + ], + 'installable': True, + "license": 'AGPL-3', +} diff --git a/stock_inventory_preparation_filter/__openerp__.py b/stock_inventory_preparation_filter/__openerp__.py deleted file mode 100644 index 3970d655f..000000000 --- a/stock_inventory_preparation_filter/__openerp__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## - -{ - "name": "Extended Inventory Preparation Filters", - "version": "8.0.1.0.0", - "depends": [ - "stock", - ], - "author": "OdooMRP team," - "AvanzOSC," - "Serv. Tecnol. Avanzados - Pedro M. Baeza," - "Odoo Community Association (OCA)", - "contributors": [ - "Oihane Crucelaegui ", - "Pedro M. Baeza ", - ], - "category": "Inventory, Logistic, Storage", - "website": "http://www.odoomrp.com", - "summary": "More filters for inventory adjustments", - "data": [ - "views/stock_inventory_view.xml", - "security/ir.model.access.csv", - ], - "installable": True, -} diff --git a/stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot b/stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot deleted file mode 100644 index 4a7f7738d..000000000 --- a/stock_inventory_preparation_filter/i18n/stock_inventory_preparation_filters.pot +++ /dev/null @@ -1,113 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * stock_inventory_preparation_filters -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0rc1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-30 08:58+0000\n" -"PO-Revision-Date: 2014-07-30 08:58+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: stock_inventory_preparation_filters -#: view:stock.inventory:0 -#: field:stock.inventory,empty_line_ids:0 -msgid "Capture Lines" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory,categ_ids:0 -msgid "Categories" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,create_uid:0 -msgid "Created by" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,create_date:0 -msgid "Created on" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:66 -#, python-format -msgid "Empty list" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,id:0 -msgid "ID" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory -#: field:stock.inventory.line.empty,inventory_id:0 -msgid "Inventory" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: view:stock.inventory:0 -msgid "Inventory Details" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,write_uid:0 -msgid "Last Updated by" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,write_date:0 -msgid "Last Updated on" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory,lot_ids:0 -msgid "Lots" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,product_code:0 -msgid "Product Code" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory,product_ids:0 -msgid "Products" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: field:stock.inventory.line.empty,product_qty:0 -msgid "Quantity" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:61 -#, python-format -msgid "Selected Categories" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:65 -#, python-format -msgid "Selected Lots" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: code:addons/stock_inventory_preparation_filters/models/stock_inventory.py:62 -#, python-format -msgid "Selected Products" -msgstr "" - -#. module: stock_inventory_preparation_filters -#: model:ir.model,name:stock_inventory_preparation_filters.model_stock_inventory_line_empty -msgid "stock.inventory.line.empty" -msgstr "" - diff --git a/stock_inventory_preparation_filter/models/__init__.py b/stock_inventory_preparation_filter/models/__init__.py index 6149c9932..9525632ba 100644 --- a/stock_inventory_preparation_filter/models/__init__.py +++ b/stock_inventory_preparation_filter/models/__init__.py @@ -1,19 +1,3 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- from . import stock_inventory diff --git a/stock_inventory_preparation_filter/models/stock_inventory.py b/stock_inventory_preparation_filter/models/stock_inventory.py index 8fa5669fd..9bfe2dfff 100644 --- a/stock_inventory_preparation_filter/models/stock_inventory.py +++ b/stock_inventory_preparation_filter/models/stock_inventory.py @@ -1,68 +1,51 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see http://www.gnu.org/licenses/. -# -############################################################################## +# -*- coding: utf-8 -*- +# Copyright 2015 AvanzOSC - Oihane Crucelaegi +# Copyright 2015 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields, api, _ +from odoo import _, api, fields, models class StockInventoryEmptyLines(models.Model): _name = 'stock.inventory.line.empty' product_code = fields.Char( - string='Product Code', size=64, required=True) + string='Product Code', + required=True, + ) product_qty = fields.Float( - string='Quantity', required=True, default=1.0) + string='Quantity', + required=True, + default=1.0, + ) inventory_id = fields.Many2one( - comodel_name='stock.inventory', string='Inventory', - required=True, ondelete="cascade") - - -class StockInventoryFake(object): - def __init__(self, inventory, product=None, lot=None): - self.id = inventory.id - self.location_id = inventory.location_id - self.product_id = product - self.lot_id = lot - self.partner_id = inventory.partner_id - self.package_id = inventory.package_id + comodel_name='stock.inventory', + string='Inventory', + required=True, + ondelete="cascade", + ) class StockInventory(models.Model): _inherit = 'stock.inventory' @api.model - def _get_available_filters(self): + def _selection_filter(self): """This function will return the list of filters allowed according to the options checked in 'Settings/Warehouse'. :return: list of tuple """ - res_filters = super(StockInventory, self)._get_available_filters() + res_filters = super(StockInventory, self)._selection_filter() res_filters.append(('categories', _('Selected Categories'))) res_filters.append(('products', _('Selected Products'))) for res_filter in res_filters: if res_filter[0] == 'lot': res_filters.append(('lots', _('Selected Lots'))) + break res_filters.append(('empty', _('Empty list'))) return res_filters - filter = fields.Selection( - selection=_get_available_filters, string='Selection Filter', - required=True) categ_ids = fields.Many2many( comodel_name='product.category', relation='rel_inventories_categories', column1='inventory_id', column2='category_id', string='Categories') @@ -77,59 +60,56 @@ class StockInventory(models.Model): string='Capture Lines') @api.model - def _get_inventory_lines(self, inventory): + def _get_inventory_lines_values(self): + self.ensure_one() vals = [] - product_tmpl_obj = self.env['product.template'] product_obj = self.env['product.product'] - if inventory.filter in ('categories', 'products'): - products = product_obj - if inventory.filter == 'categories': - product_tmpls = product_tmpl_obj.search( - [('categ_id', 'in', inventory.categ_ids.ids)]) - products = product_obj.search( - [('product_tmpl_id', 'in', product_tmpls.ids)]) - elif inventory.filter == 'products': - products = inventory.product_ids - for product in products: - fake_inventory = StockInventoryFake(inventory, product=product) - vals += super(StockInventory, self)._get_inventory_lines( - fake_inventory) - elif inventory.filter == 'lots': - for lot in inventory.lot_ids: - fake_inventory = StockInventoryFake(inventory, lot=lot) - vals += super(StockInventory, self)._get_inventory_lines( - fake_inventory) - elif inventory.filter == 'empty': - tmp_lines = {} - empty_line_obj = self.env['stock.inventory.line.empty'] - for line in inventory.empty_line_ids: - if line.product_code in tmp_lines: - tmp_lines[line.product_code] += line.product_qty - else: - tmp_lines[line.product_code] = line.product_qty - inventory.empty_line_ids.unlink() - for product_code in tmp_lines.keys(): + inventory = self.new(self._convert_to_write(self._cache)) + if self.filter in ('categories', 'products'): + if self.filter == 'categories': products = product_obj.search([ - '|', ('default_code', '=', product_code), - ('ean13', '=', product_code), + ('product_tmpl_id.categ_id', 'in', self.categ_ids.ids) ]) - if products: - product = products[0] - fake_inventory = StockInventoryFake( - inventory, product=product) - values = super(StockInventory, self)._get_inventory_lines( - fake_inventory) - if values: - values[0]['product_qty'] = tmp_lines[product_code] - else: - empty_line_obj.create( - { - 'product_code': product_code, - 'product_qty': tmp_lines[product_code], - 'inventory_id': inventory.id, - }) - vals += values + else: # filter = 'products' + products = self.product_ids + inventory.filter = 'product' + for product in products: + inventory.product_id = product + vals += super(StockInventory, + inventory)._get_inventory_lines_values() + elif self.filter == 'lots': + inventory.filter = 'lot' + for lot in self.lot_ids: + inventory.lot_id = lot + vals += super(StockInventory, + inventory)._get_inventory_lines_values() + elif self.filter == 'empty': + tmp_lines = {} + for line in self.empty_line_ids: + tmp_lines.setdefault(line.product_code, 0) + tmp_lines[line.product_code] += line.product_qty + self.empty_line_ids.unlink() + inventory.filter = 'product' + for product_code in tmp_lines.keys(): + product = product_obj.search([ + '|', + ('default_code', '=', product_code), + ('barcode', '=', product_code), + ], limit=1) + if not product: + continue + inventory.product_id = product + values = super(StockInventory, + inventory)._get_inventory_lines_values() + if values: + values[0]['product_qty'] = tmp_lines[product_code] + else: + vals += [{ + 'product_id': product.id, + 'product_qty': tmp_lines[product_code], + 'location_id': self.location_id.id, + }] + vals += values else: - vals = super(StockInventory, self)._get_inventory_lines( - inventory) + vals = super(StockInventory, self)._get_inventory_lines_values() return vals diff --git a/stock_inventory_preparation_filter/tests/__init__.py b/stock_inventory_preparation_filter/tests/__init__.py index 79299bb59..9c3a513b0 100644 --- a/stock_inventory_preparation_filter/tests/__init__.py +++ b/stock_inventory_preparation_filter/tests/__init__.py @@ -1,17 +1,3 @@ -############################################################################## -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# -*- encoding: utf-8 -*- + from . import test_stock_inventory_preparation_filter diff --git a/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py b/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py index 5ef493c3f..3c1e483a2 100644 --- a/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py +++ b/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py @@ -1,89 +1,101 @@ -############################################################################## -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -import openerp.tests.common as common +# -*- coding: utf-8 -*- +# Copyright 2015 AvanzOSC - Oihane Crucelaegi +# Copyright 2015 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import common +@common.at_install(False) +@common.post_install(True) class TestStockInventoryPreparationFilterCategories(common.TransactionCase): def setUp(self): super(TestStockInventoryPreparationFilterCategories, self).setUp() self.inventory_model = self.env['stock.inventory'] - # Create a category - self.category = self.env['product.category'].create( - { - 'name': 'Category for inventory', - 'type': 'normal', - }) + # Create some categories + self.category = self.env['product.category'].create({ + 'name': 'Category for inventory', + 'type': 'normal', + }) + self.category2 = self.env['product.category'].create({ + 'name': 'Category for inventory 2', + 'type': 'normal', + }) # Create some products in the category - self.product1 = self.env['product.product'].create( - { - 'name': 'Product for inventory 1', - 'type': 'product', - 'categ_id': self.category.id, - 'default_code': 'PROD1', - } - ) - self.product2 = self.env['product.product'].create( - { - 'name': 'Product for inventory 2', - 'type': 'product', - 'categ_id': self.category.id, - 'default_code': 'PROD2', - } - ) + self.product1 = self.env['product.product'].create({ + 'name': 'Product for inventory 1', + 'type': 'product', + 'categ_id': self.category.id, + 'default_code': 'PROD1-TEST', + }) + self.product2 = self.env['product.product'].create({ + 'name': 'Product for inventory 2', + 'type': 'product', + 'categ_id': self.category.id, + 'default_code': 'PROD2-TEST', + }) + self.product3 = self.env['product.product'].create({ + 'name': 'Product for inventory 3', + 'type': 'product', + 'categ_id': self.category.id, + 'default_code': 'PROD3-TEST', + }) + self.product_lot = self.env['product.product'].create({ + 'name': 'Product for inventory with lots', + 'type': 'product', + 'categ_id': self.category2.id, + }) + self.lot = self.env['stock.production.lot'].create({ + 'name': 'Lot test', + 'product_id': self.product_lot.id, + }) + # Add user to lot tracking group + self.env.user.groups_id = [ + (4, self.env.ref('stock.group_production_lot').id), + ] # And have some stock in a location - self.location = self.env['stock.location'].create( - { - 'name': 'Inventory tests', - 'usage': 'internal', - } - ) - inventory = self.inventory_model.create( - { - 'name': 'Product1 inventory', - 'filter': 'product', - 'line_ids': [ - (0, 0, { - 'product_id': self.product1.id, - 'product_uom_id': self.env.ref( - "product.product_uom_unit").id, - 'product_qty': 2.0, - 'location_id': self.location.id, - }), - (0, 0, { - 'product_id': self.product2.id, - 'product_uom_id': self.env.ref( - "product.product_uom_unit").id, - 'product_qty': 4.0, - 'location_id': self.location.id, - }), - ], - }) + self.location = self.env['stock.location'].create({ + 'name': 'Inventory tests', + 'usage': 'internal', + }) + inventory = self.inventory_model.create({ + 'name': 'Product1 inventory', + 'filter': 'product', + 'line_ids': [ + (0, 0, { + 'product_id': self.product1.id, + 'product_uom_id': self.env.ref( + "product.product_uom_unit").id, + 'product_qty': 2.0, + 'location_id': self.location.id, + }), + (0, 0, { + 'product_id': self.product2.id, + 'product_uom_id': self.env.ref( + "product.product_uom_unit").id, + 'product_qty': 4.0, + 'location_id': self.location.id, + }), + (0, 0, { + 'product_id': self.product_lot.id, + 'product_uom_id': self.env.ref( + "product.product_uom_unit").id, + 'product_qty': 6.0, + 'location_id': self.location.id, + 'prod_lot_id': self.lot.id, + }), + ], + }) inventory.action_done() def test_inventory_category_filter(self): - inventory = self.inventory_model.create( - { - 'name': 'Category inventory', - 'filter': 'categories', - 'location_id': self.location.id, - 'categ_ids': [(6, 0, [self.category.id])], - } - ) + inventory = self.inventory_model.create({ + 'name': 'Category inventory', + 'filter': 'categories', + 'location_id': self.location.id, + 'categ_ids': [(6, 0, [self.category.id])], + }) inventory.prepare_inventory() self.assertEqual(len(inventory.line_ids), 2) line1 = inventory.line_ids[0] @@ -115,26 +127,49 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase): self.assertEqual(line2.theoretical_qty, 4.0) self.assertEqual(line2.location_id, self.location) - def test_inventory_empty_filter(self): + def test_inventory_lots_filter(self): inventory = self.inventory_model.create( { 'name': 'Products inventory', - 'filter': 'empty', + 'filter': 'lots', 'location_id': self.location.id, - 'empty_line_ids': [ - (0, 0, { - 'product_code': 'PROD1', - 'product_qty': 3.0, - }), - (0, 0, { - 'product_code': 'PROD2', - 'product_qty': 7.0, - }), - ], + 'lot_ids': [(6, 0, [self.lot.id, ])], } ) inventory.prepare_inventory() - self.assertEqual(len(inventory.line_ids), 2) + self.assertEqual(len(inventory.line_ids), 1) + line1 = inventory.line_ids[0] + self.assertEqual(line1.product_id, self.product_lot) + self.assertEqual(line1.prod_lot_id, self.lot) + self.assertEqual(line1.theoretical_qty, 6.0) + self.assertEqual(line1.location_id, self.location) + + def test_inventory_empty_filter(self): + inventory = self.inventory_model.create({ + 'name': 'Products inventory', + 'filter': 'empty', + 'location_id': self.location.id, + 'empty_line_ids': [ + (0, 0, { + 'product_code': 'PROD1-TEST', + 'product_qty': 3.0, + }), + (0, 0, { + 'product_code': 'PROD2-TEST', + 'product_qty': 7.0, + }), + (0, 0, { + 'product_code': 'PROD3-TEST', + 'product_qty': 5.0, + }), + (0, 0, { + 'product_code': 'UNEXISTING-CODE', + 'product_qty': 0.0, + }), + ], + }) + inventory.prepare_inventory() + self.assertEqual(len(inventory.line_ids), 3) line1 = inventory.line_ids[0] self.assertEqual(line1.product_id, self.product1) self.assertEqual(line1.theoretical_qty, 2.0) @@ -145,3 +180,8 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase): self.assertEqual(line2.theoretical_qty, 4.0) self.assertEqual(line2.product_qty, 7.0) self.assertEqual(line2.location_id, self.location) + line3 = inventory.line_ids[2] + self.assertEqual(line3.product_id, self.product3) + self.assertEqual(line3.theoretical_qty, 0.0) + self.assertEqual(line3.product_qty, 5.0) + self.assertEqual(line3.location_id, self.location) diff --git a/stock_inventory_preparation_filter/views/stock_inventory_view.xml b/stock_inventory_preparation_filter/views/stock_inventory_view.xml index cb9109413..a00af66fc 100644 --- a/stock_inventory_preparation_filter/views/stock_inventory_view.xml +++ b/stock_inventory_preparation_filter/views/stock_inventory_view.xml @@ -1,6 +1,6 @@ - - + + stock.inventory.form stock.inventory @@ -10,9 +10,9 @@ - + {'invisible':[('state','=','draft')]} - + - - + From 19d2da0a64e9ad31f328b829e71ca52e4962ca2e Mon Sep 17 00:00:00 2001 From: xavierjimenez Date: Thu, 28 Jun 2018 09:10:09 +0200 Subject: [PATCH 04/24] [MIG][11.0] stock_inventory_preparation_filter --- stock_inventory_preparation_filter/README.rst | 77 +++- .../__init__.py | 1 - .../__manifest__.py | 5 +- .../models/__init__.py | 1 - .../models/stock_inventory.py | 9 +- .../readme/CONTRIBUTORS.rst | 7 + .../readme/DESCRIPTION.rst | 8 + .../static/description/index.html | 433 ++++++++++++++++++ .../tests/__init__.py | 1 - ...test_stock_inventory_preparation_filter.py | 26 +- .../views/stock_inventory_view.xml | 29 +- 11 files changed, 535 insertions(+), 62 deletions(-) create mode 100644 stock_inventory_preparation_filter/readme/CONTRIBUTORS.rst create mode 100644 stock_inventory_preparation_filter/readme/DESCRIPTION.rst create mode 100644 stock_inventory_preparation_filter/static/description/index.html diff --git a/stock_inventory_preparation_filter/README.rst b/stock_inventory_preparation_filter/README.rst index bae4ea0c8..b1751fbeb 100644 --- a/stock_inventory_preparation_filter/README.rst +++ b/stock_inventory_preparation_filter/README.rst @@ -1,10 +1,29 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html - :alt: License: AGPL-3 +====================================== +Extended Inventory Preparation Filters +====================================== -======================================== -More preparation filters for inventories -======================================== +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_inventory_preparation_filter + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-11-0/stock-logistics-warehouse-11-0-stock_inventory_preparation_filter + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/153/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| Includes more options for making an inventory out of: @@ -15,42 +34,54 @@ Includes more options for making an inventory out of: It also allows to make an inventory based on scanned products, adding a line with product code and quantity. -Usage -===== +**Table of contents** -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/153/10.0 +.. contents:: + :local: Bug Tracker =========== -Bugs are tracked on `GitHub Issues -`_. In case of trouble, please -check there if your issue has already been reported. If you spotted it first, -help us smash it by providing detailed and welcomed feedback. +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. Credits ======= +Authors +~~~~~~~ + +* AvanzOSC +* Tecnativa + Contributors ------------- +~~~~~~~~~~~~ * Oihane Crucelaegui -* Pedro M. Baeza -* David Vidal +* `Tecnativa `__: -Maintainer ----------- + * Pedro M. Baeza + * David Vidal + +* Xavier Jimenez + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. .. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association :target: https://odoo-community.org -This module is maintained by the OCA. - OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit https://odoo-community.org. +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_inventory_preparation_filter/__init__.py b/stock_inventory_preparation_filter/__init__.py index 21ff7c22f..a9e337226 100644 --- a/stock_inventory_preparation_filter/__init__.py +++ b/stock_inventory_preparation_filter/__init__.py @@ -1,3 +1,2 @@ -# -*- encoding: utf-8 -*- from . import models diff --git a/stock_inventory_preparation_filter/__manifest__.py b/stock_inventory_preparation_filter/__manifest__.py index 56366872b..686e4adf8 100644 --- a/stock_inventory_preparation_filter/__manifest__.py +++ b/stock_inventory_preparation_filter/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2015 AvanzOSC - Oihane Crucelaegi # Copyright 2015 Tecnativa - Pedro M. Baeza # Copyright 2017 Tecnativa - David Vidal @@ -6,7 +5,7 @@ { "name": "Extended Inventory Preparation Filters", - "version": "10.0.1.0.0", + "version": "11.0.1.0.0", "depends": [ "stock", ], @@ -14,7 +13,7 @@ "Tecnativa," "Odoo Community Association (OCA)", "category": "Inventory, Logistic, Storage", - "website": "http://github.com/OCA/stock-logistics-workflow", + "website": "http://github.com/OCA/stock-logistics-warehouse", "summary": "More filters for inventory adjustments", "data": [ "views/stock_inventory_view.xml", diff --git a/stock_inventory_preparation_filter/models/__init__.py b/stock_inventory_preparation_filter/models/__init__.py index 9525632ba..5f81629c4 100644 --- a/stock_inventory_preparation_filter/models/__init__.py +++ b/stock_inventory_preparation_filter/models/__init__.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- from . import stock_inventory diff --git a/stock_inventory_preparation_filter/models/stock_inventory.py b/stock_inventory_preparation_filter/models/stock_inventory.py index 9bfe2dfff..3e2efbf85 100644 --- a/stock_inventory_preparation_filter/models/stock_inventory.py +++ b/stock_inventory_preparation_filter/models/stock_inventory.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- # Copyright 2015 AvanzOSC - Oihane Crucelaegi # Copyright 2015 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models +from odoo.addons import decimal_precision as dp class StockInventoryEmptyLines(models.Model): @@ -17,6 +17,7 @@ class StockInventoryEmptyLines(models.Model): string='Quantity', required=True, default=1.0, + digits=dp.get_precision('Product Unit of Measure'), ) inventory_id = fields.Many2one( comodel_name='stock.inventory', @@ -64,7 +65,7 @@ class StockInventory(models.Model): self.ensure_one() vals = [] product_obj = self.env['product.product'] - inventory = self.new(self._convert_to_write(self._cache)) + inventory = self.new(self._convert_to_write(self.read()[0])) if self.filter in ('categories', 'products'): if self.filter == 'categories': products = product_obj.search([ @@ -90,6 +91,8 @@ class StockInventory(models.Model): tmp_lines[line.product_code] += line.product_qty self.empty_line_ids.unlink() inventory.filter = 'product' + # HACK: Make sure location is preserved + inventory.location_id = self.location_id for product_code in tmp_lines.keys(): product = product_obj.search([ '|', @@ -111,5 +114,5 @@ class StockInventory(models.Model): }] vals += values else: - vals = super(StockInventory, self)._get_inventory_lines_values() + vals = super()._get_inventory_lines_values() return vals diff --git a/stock_inventory_preparation_filter/readme/CONTRIBUTORS.rst b/stock_inventory_preparation_filter/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..74d17e3f1 --- /dev/null +++ b/stock_inventory_preparation_filter/readme/CONTRIBUTORS.rst @@ -0,0 +1,7 @@ +* Oihane Crucelaegui +* `Tecnativa `__: + + * Pedro M. Baeza + * David Vidal + +* Xavier Jimenez diff --git a/stock_inventory_preparation_filter/readme/DESCRIPTION.rst b/stock_inventory_preparation_filter/readme/DESCRIPTION.rst new file mode 100644 index 000000000..7eb4d0bf4 --- /dev/null +++ b/stock_inventory_preparation_filter/readme/DESCRIPTION.rst @@ -0,0 +1,8 @@ +Includes more options for making an inventory out of: + +* Multiple products. +* Products of a category. +* Multiple lots + +It also allows to make an inventory based on scanned products, adding a line +with product code and quantity. diff --git a/stock_inventory_preparation_filter/static/description/index.html b/stock_inventory_preparation_filter/static/description/index.html new file mode 100644 index 000000000..4d4293fb3 --- /dev/null +++ b/stock_inventory_preparation_filter/static/description/index.html @@ -0,0 +1,433 @@ + + + + + + +Extended Inventory Preparation Filters + + + +
+

Extended Inventory Preparation Filters

+ + +

Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

+

Includes more options for making an inventory out of:

+
    +
  • Multiple products.
  • +
  • Products of a category.
  • +
  • Multiple lots
  • +
+

It also allows to make an inventory based on scanned products, adding a line +with product code and quantity.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • AvanzOSC
  • +
  • Tecnativa
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/stock-logistics-warehouse project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/stock_inventory_preparation_filter/tests/__init__.py b/stock_inventory_preparation_filter/tests/__init__.py index 9c3a513b0..76616c897 100644 --- a/stock_inventory_preparation_filter/tests/__init__.py +++ b/stock_inventory_preparation_filter/tests/__init__.py @@ -1,3 +1,2 @@ -# -*- encoding: utf-8 -*- from . import test_stock_inventory_preparation_filter diff --git a/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py b/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py index 3c1e483a2..be71c984a 100644 --- a/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py +++ b/stock_inventory_preparation_filter/tests/test_stock_inventory_preparation_filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2015 AvanzOSC - Oihane Crucelaegi # Copyright 2015 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -9,18 +8,15 @@ from odoo.tests import common @common.at_install(False) @common.post_install(True) class TestStockInventoryPreparationFilterCategories(common.TransactionCase): - def setUp(self): super(TestStockInventoryPreparationFilterCategories, self).setUp() self.inventory_model = self.env['stock.inventory'] # Create some categories self.category = self.env['product.category'].create({ 'name': 'Category for inventory', - 'type': 'normal', }) self.category2 = self.env['product.category'].create({ 'name': 'Category for inventory 2', - 'type': 'normal', }) # Create some products in the category self.product1 = self.env['product.product'].create({ @@ -96,7 +92,7 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase): 'location_id': self.location.id, 'categ_ids': [(6, 0, [self.category.id])], }) - inventory.prepare_inventory() + inventory.action_start() self.assertEqual(len(inventory.line_ids), 2) line1 = inventory.line_ids[0] self.assertEqual(line1.product_id, self.product1) @@ -108,15 +104,13 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase): self.assertEqual(line2.location_id, self.location) def test_inventory_products_filter(self): - inventory = self.inventory_model.create( - { - 'name': 'Products inventory', - 'filter': 'products', - 'location_id': self.location.id, - 'product_ids': [(6, 0, [self.product1.id, self.product2.id])], - } - ) - inventory.prepare_inventory() + inventory = self.inventory_model.create({ + 'name': 'Products inventory', + 'filter': 'products', + 'location_id': self.location.id, + 'product_ids': [(6, 0, [self.product1.id, self.product2.id])], + }) + inventory.action_start() self.assertEqual(len(inventory.line_ids), 2) line1 = inventory.line_ids[0] self.assertEqual(line1.product_id, self.product1) @@ -136,7 +130,7 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase): 'lot_ids': [(6, 0, [self.lot.id, ])], } ) - inventory.prepare_inventory() + inventory.action_start() self.assertEqual(len(inventory.line_ids), 1) line1 = inventory.line_ids[0] self.assertEqual(line1.product_id, self.product_lot) @@ -168,7 +162,7 @@ class TestStockInventoryPreparationFilterCategories(common.TransactionCase): }), ], }) - inventory.prepare_inventory() + inventory.action_start() self.assertEqual(len(inventory.line_ids), 3) line1 = inventory.line_ids[0] self.assertEqual(line1.product_id, self.product1) diff --git a/stock_inventory_preparation_filter/views/stock_inventory_view.xml b/stock_inventory_preparation_filter/views/stock_inventory_view.xml index a00af66fc..40468dc80 100644 --- a/stock_inventory_preparation_filter/views/stock_inventory_view.xml +++ b/stock_inventory_preparation_filter/views/stock_inventory_view.xml @@ -10,22 +10,23 @@ - + {'invisible':[('state','=','draft')]} - - - - - - - + + + + + + + + + From 6b9c7ba973bd812e859e4feb1ab7c3a4cf971843 Mon Sep 17 00:00:00 2001 From: xavierpiernas Date: Tue, 28 May 2019 09:43:00 +0200 Subject: [PATCH 05/24] [MIG] stock_inventory_preparation_filter: Migration to 12.0 --- stock_inventory_preparation_filter/README.rst | 10 +++++----- stock_inventory_preparation_filter/__manifest__.py | 2 +- .../models/stock_inventory.py | 1 + .../static/description/index.html | 8 ++++---- .../tests/test_stock_inventory_preparation_filter.py | 8 ++++---- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/stock_inventory_preparation_filter/README.rst b/stock_inventory_preparation_filter/README.rst index b1751fbeb..02d4c20cb 100644 --- a/stock_inventory_preparation_filter/README.rst +++ b/stock_inventory_preparation_filter/README.rst @@ -14,13 +14,13 @@ Extended Inventory Preparation Filters :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github - :target: https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_inventory_preparation_filter + :target: https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_inventory_preparation_filter :alt: OCA/stock-logistics-warehouse .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-11-0/stock-logistics-warehouse-11-0-stock_inventory_preparation_filter + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_inventory_preparation_filter :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/153/11.0 + :target: https://runbot.odoo-community.org/runbot/153/12.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -45,7 +45,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -82,6 +82,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_inventory_preparation_filter/__manifest__.py b/stock_inventory_preparation_filter/__manifest__.py index 686e4adf8..c5a0fc435 100644 --- a/stock_inventory_preparation_filter/__manifest__.py +++ b/stock_inventory_preparation_filter/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Extended Inventory Preparation Filters", - "version": "11.0.1.0.0", + "version": "12.0.1.0.0", "depends": [ "stock", ], diff --git a/stock_inventory_preparation_filter/models/stock_inventory.py b/stock_inventory_preparation_filter/models/stock_inventory.py index 3e2efbf85..cd736122c 100644 --- a/stock_inventory_preparation_filter/models/stock_inventory.py +++ b/stock_inventory_preparation_filter/models/stock_inventory.py @@ -8,6 +8,7 @@ from odoo.addons import decimal_precision as dp class StockInventoryEmptyLines(models.Model): _name = 'stock.inventory.line.empty' + _description = 'Inventory Line Empty' product_code = fields.Char( string='Product Code', diff --git a/stock_inventory_preparation_filter/static/description/index.html b/stock_inventory_preparation_filter/static/description/index.html index 4d4293fb3..82c5fb771 100644 --- a/stock_inventory_preparation_filter/static/description/index.html +++ b/stock_inventory_preparation_filter/static/description/index.html @@ -3,7 +3,7 @@ - + Extended Inventory Preparation Filters