diff --git a/stock_receipt_lot_info/__manifest__.py b/stock_receipt_lot_info/__manifest__.py index 015c4ea751c..bbf6bf38e8d 100644 --- a/stock_receipt_lot_info/__manifest__.py +++ b/stock_receipt_lot_info/__manifest__.py @@ -6,7 +6,7 @@ "summary": "Be able to introduce more info on lot/serial " "number while processing a receipt.", "author": "ForgeFlow, Odoo Community Association (OCA)", - "version": "15.0.1.0.0", + "version": "16.0.1.0.0", "category": "Warehouse Management", "website": "https://github.com/OCA/stock-logistics-workflow", "license": "LGPL-3", diff --git a/stock_receipt_lot_info/migrations/15.0.1.0.0/pre-migration.py b/stock_receipt_lot_info/migrations/15.0.1.0.0/pre-migration.py deleted file mode 100644 index ed76bfd8eed..00000000000 --- a/stock_receipt_lot_info/migrations/15.0.1.0.0/pre-migration.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2022 ForgeFlow, S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). - -from openupgradelib import openupgrade # pylint: disable=W7936 - -_field_renames = [ - ("stock.move.line", "stock_move_line", "lot_life_date", "lot_expiration_date"), -] - - -@openupgrade.migrate() -def migrate(env, version): - cr = env.cr - for field in _field_renames: - if openupgrade.table_exists(cr, field[1]) and openupgrade.column_exists( - cr, field[1], field[2] - ): - openupgrade.rename_fields(env, [field]) diff --git a/stock_receipt_lot_info/model/stock_move_line.py b/stock_receipt_lot_info/model/stock_move_line.py index 29c7abc089b..dbf76a4a38d 100644 --- a/stock_receipt_lot_info/model/stock_move_line.py +++ b/stock_receipt_lot_info/model/stock_move_line.py @@ -1,4 +1,4 @@ -# Copyright 2021 ForgeFlow, S.L. +# Copyright 2022 ForgeFlow, S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). from odoo import fields, models @@ -12,8 +12,8 @@ class StockMoveLine(models.Model): lot_removal_date = fields.Datetime(string="Lot/Serial Removal Date") lot_alert_date = fields.Datetime(string="Lot/Serial Alert Date") - def _prepare_new_lot_vals(self): - vals = super()._prepare_new_lot_vals() + def _get_value_production_lot(self): + vals = super()._get_value_production_lot() creation_lot_fields = [ "expiration_date", "use_date", diff --git a/stock_receipt_lot_info/readme/CONTRIBUTORS.rst b/stock_receipt_lot_info/readme/CONTRIBUTORS.rst index 6987e7abeb3..5b512cd3e61 100644 --- a/stock_receipt_lot_info/readme/CONTRIBUTORS.rst +++ b/stock_receipt_lot_info/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * Forgeflow (https://www.forgeflow.com) * Lois Rilo + * Marc Belmonte diff --git a/stock_receipt_lot_info/tests/__init__.py b/stock_receipt_lot_info/tests/__init__.py index 82d5e07f437..f00ae1e4dfa 100644 --- a/stock_receipt_lot_info/tests/__init__.py +++ b/stock_receipt_lot_info/tests/__init__.py @@ -1,3 +1 @@ -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from . import test_stock_picking_show_return +from . import test_receipt_lot_info diff --git a/stock_receipt_lot_info/tests/test_receipt_lot_info.py b/stock_receipt_lot_info/tests/test_receipt_lot_info.py new file mode 100644 index 00000000000..fd2777b10ad --- /dev/null +++ b/stock_receipt_lot_info/tests/test_receipt_lot_info.py @@ -0,0 +1,117 @@ +# Copyright 2022 ForgeFlow, S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import timedelta + +from odoo.fields import Datetime +from odoo.tests.common import TransactionCase + + +class ReceiptLotInfo(TransactionCase): + @classmethod + def setUpClass(cls): + super(ReceiptLotInfo, cls).setUpClass() + group_stock_multi_locations = cls.env.ref("stock.group_stock_multi_locations") + cls.env.user.write({"groups_id": [(4, group_stock_multi_locations.id, 0)]}) + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.customer_location = cls.env.ref("stock.stock_location_customers") + cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") + cls.uom_unit = cls.env.ref("uom.product_uom_unit") + cls.uom_dozen = cls.env.ref("uom.product_uom_dozen") + cls.product = cls.env["product.product"].create( + { + "name": "Product A", + "type": "product", + "categ_id": cls.env.ref("product.product_category_all").id, + } + ) + cls.product_serial = cls.env["product.product"].create( + { + "name": "Product B", + "type": "product", + "tracking": "serial", + "categ_id": cls.env.ref("product.product_category_all").id, + } + ) + cls.product_lot = cls.env["product.product"].create( + { + "name": "Product C", + "type": "product", + "tracking": "lot", + "categ_id": cls.env.ref("product.product_category_all").id, + } + ) + + def test_in_1(self): + """This tests adds info about dates in move lines and check if + its set correctly. + """ + + picking = self.env["stock.picking"].create( + { + "location_id": self.supplier_location.id, + "location_dest_id": self.stock_location.id, + "picking_type_id": self.env.ref("stock.picking_type_in").id, + } + ) + move1 = self.env["stock.move"].create( + { + "name": "test_lot_info_1", + "location_id": self.supplier_location.id, + "location_dest_id": self.stock_location.id, + "product_id": self.product_lot.id, + "product_uom": self.uom_unit.id, + "product_uom_qty": 1.0, + "picking_id": picking.id, + "picking_type_id": self.env.ref("stock.picking_type_in").id, + } + ) + move1._action_confirm() + move1._action_assign() + self.assertEqual(move1.state, "assigned") + + # create an untracked quant + self.env["stock.quant"]._update_available_quantity( + self.product_lot, self.stock_location, 1.0 + ) + # lot1 = self.env["stock.lot"].create( + # { + # "name": "lot1", + # "product_id": self.product_lot.id, + # "company_id": self.env.company.id, + # } + # ) + + # create a new move line with a lot not assigned to any quant + self.env["stock.move.line"].create( + { + "move_id": move1.id, + "product_id": move1.product_id.id, + "qty_done": 1, + "product_uom_id": move1.product_uom.id, + "location_id": move1.location_id.id, + "location_dest_id": move1.location_dest_id.id, + # "lot_id": lot1.id, + "lot_name": "LOT001", + "lot_expiration_date": Datetime.now() + timedelta(days=15), + "lot_use_date": Datetime.now() + timedelta(days=5), + "lot_removal_date": Datetime.now() + timedelta(days=20), + "lot_alert_date": Datetime.now() + timedelta(days=10), + } + ) + + move_line = move1.move_line_ids + # move_line.lot_id = lot1 + # validating the move line should move the lot, not create a negative quant in stock + move1._action_done() + + self.assertEqual( + move_line[1].lot_expiration_date, Datetime.now() + timedelta(days=15) + ) + self.assertEqual(move_line[1].lot_use_date, Datetime.now() + timedelta(days=5)) + self.assertEqual( + move_line[1].lot_removal_date, Datetime.now() + timedelta(days=20) + ) + self.assertEqual( + move_line[1].lot_alert_date, Datetime.now() + timedelta(days=10) + ) diff --git a/stock_receipt_lot_info/tests/test_stock_picking_show_return.py b/stock_receipt_lot_info/tests/test_stock_picking_show_return.py deleted file mode 100644 index c1626692a46..00000000000 --- a/stock_receipt_lot_info/tests/test_stock_picking_show_return.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2014-2017 Pedro M. Baeza -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo.tests.common import Form, TransactionCase, tagged - - -@tagged("post_install", "-at_install") -class TestStockPickingShowReturn(TransactionCase): - def setUp(self): - super(TestStockPickingShowReturn, self).setUp() - self.product = self.env["product.product"].create({"name": "Test product"}) - picking_type = self.env.ref("stock.picking_type_internal") - self.picking = self.env["stock.picking"].create( - { - "picking_type_id": picking_type.id, - "location_id": picking_type.default_location_src_id.id, - "location_dest_id": picking_type.default_location_dest_id.id, - "move_lines": [ - ( - 0, - 0, - { - "name": self.product.name, - "location_id": picking_type.default_location_src_id.id, - "location_dest_id": picking_type.default_location_dest_id.id, - "product_id": self.product.id, - "product_uom": self.product.uom_id.id, - "product_uom_qty": 1, - }, - ) - ], - } - ) - - def get_return_picking_wizard(self, picking): - stock_return_picking_form = Form( - self.env["stock.return.picking"].with_context( - active_ids=picking.ids, - active_id=picking.ids[0], - active_model="stock.picking", - ) - ) - return stock_return_picking_form.save() - - def test_returned_ids_field(self): - self.picking.action_assign() - self.picking.move_line_ids.qty_done = 1 - self.picking._action_done() - wizard = self.get_return_picking_wizard(self.picking) - wizard.create_returns() - self.picking._compute_returned_ids() - self.assertTrue(self.picking.returned_ids) - - def test_source_picking_id_field(self): - self.picking.action_assign() - self.picking.move_line_ids.qty_done = 1 - self.picking._action_done() - wizard = self.get_return_picking_wizard(self.picking) - wizard.create_returns() - self.picking._compute_returned_ids() - picking_returned = self.picking.returned_ids[0] - # Get first picking returned to check if origin is self.picking - picking_origin = picking_returned.source_picking_id - self.assertEqual(picking_origin, self.picking) - # Open origin returned picking form view - action = picking_returned.action_show_source_picking() - self.assertEqual(action["res_id"], self.picking.id)