mirror of
https://github.com/bringout/oca-warehouse.git
synced 2026-04-21 20:22:03 +02:00
539 lines
22 KiB
Python
539 lines
22 KiB
Python
# Copyright 2108-2019 Sergio Teruel <sergio.teruel@tecnativa.com>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
from odoo.exceptions import MissingError, UserError
|
|
from odoo.tests.common import tagged
|
|
|
|
from .common import TestCommonStockBarcodes
|
|
|
|
|
|
@tagged("post_install", "-at_install")
|
|
class TestStockBarcodesPicking(TestCommonStockBarcodes):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.ScanReadPicking = cls.env["wiz.stock.barcodes.read.picking"]
|
|
cls.stock_picking_model = cls.env.ref("stock.model_stock_picking")
|
|
|
|
# Model Data
|
|
cls.barcode_option_group_out = cls._create_barcode_option_group_outgoing()
|
|
cls.barcode_option_group_in = cls._create_barcode_option_group_incoming()
|
|
|
|
cls.barcode_option_group_out.barcode_guided_mode = False
|
|
cls.barcode_option_group_in.barcode_guided_mode = False
|
|
cls.partner_agrolite = cls.env.ref("base.res_partner_2")
|
|
cls.picking_type_in = cls.env.ref("stock.picking_type_in")
|
|
cls.picking_type_in.barcode_option_group_id = cls.barcode_option_group_in
|
|
cls.picking_type_out = cls.env.ref("stock.picking_type_out")
|
|
cls.picking_type_out.reservation_method = "manual"
|
|
cls.picking_type_out.barcode_option_group_id = cls.barcode_option_group_out
|
|
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
|
|
cls.customer_location = cls.env.ref("stock.stock_location_customers")
|
|
cls.stock_location = cls.env.ref("stock.stock_location_stock")
|
|
cls.categ_unit = cls.env.ref("uom.product_uom_categ_unit")
|
|
cls.categ_kgm = cls.env.ref("uom.product_uom_categ_kgm")
|
|
cls.picking_out_01 = (
|
|
cls.env["stock.picking"]
|
|
.with_context(planned_picking=True)
|
|
.create(
|
|
{
|
|
"location_id": cls.stock_location.id,
|
|
"location_dest_id": cls.customer_location.id,
|
|
"partner_id": cls.partner_agrolite.id,
|
|
"picking_type_id": cls.picking_type_out.id,
|
|
"move_ids": [
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"name": cls.product_tracking.name,
|
|
"product_id": cls.product_tracking.id,
|
|
"product_uom_qty": 3,
|
|
"product_uom": cls.product_tracking.uom_id.id,
|
|
"location_id": cls.stock_location.id,
|
|
"location_dest_id": cls.customer_location.id,
|
|
},
|
|
)
|
|
],
|
|
}
|
|
)
|
|
)
|
|
cls.picking_out_02 = cls.picking_out_01.copy()
|
|
cls.picking_in_01 = (
|
|
cls.env["stock.picking"]
|
|
.with_context(planned_picking=True)
|
|
.create(
|
|
{
|
|
"location_id": cls.supplier_location.id,
|
|
"location_dest_id": cls.stock_location.id,
|
|
"partner_id": cls.partner_agrolite.id,
|
|
"picking_type_id": cls.picking_type_in.id,
|
|
"move_ids": [
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"name": cls.product_wo_tracking.name,
|
|
"product_id": cls.product_wo_tracking.id,
|
|
"product_uom_qty": 3,
|
|
"product_uom": cls.product_wo_tracking.uom_id.id,
|
|
"location_id": cls.supplier_location.id,
|
|
"location_dest_id": cls.stock_location.id,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"name": cls.product_wo_tracking.name,
|
|
"product_id": cls.product_wo_tracking.id,
|
|
"product_uom_qty": 5,
|
|
"product_uom": cls.product_wo_tracking.uom_id.id,
|
|
"location_id": cls.supplier_location.id,
|
|
"location_dest_id": cls.stock_location.id,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"name": cls.product_tracking.name,
|
|
"product_id": cls.product_tracking.id,
|
|
"product_uom_qty": 3,
|
|
"product_uom": cls.product_tracking.uom_id.id,
|
|
"location_id": cls.supplier_location.id,
|
|
"location_dest_id": cls.stock_location.id,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"name": cls.product_tracking.name,
|
|
"product_id": cls.product_tracking.id,
|
|
"product_uom_qty": 5,
|
|
"product_uom": cls.product_tracking.uom_id.id,
|
|
"location_id": cls.supplier_location.id,
|
|
"location_dest_id": cls.stock_location.id,
|
|
},
|
|
),
|
|
],
|
|
}
|
|
)
|
|
)
|
|
cls.picking_in_01.action_confirm()
|
|
action = cls.picking_in_01.action_barcode_scan()
|
|
cls.wiz_scan_picking = cls.ScanReadPicking.browse(action["res_id"])
|
|
|
|
# Create a wizard for outgoing picking
|
|
cls.picking_out_01.action_confirm()
|
|
action = cls.picking_out_01.action_barcode_scan()
|
|
cls.wiz_scan_picking_out = cls.ScanReadPicking.browse(action["res_id"])
|
|
|
|
def test_wiz_picking_values(self):
|
|
self.assertEqual(
|
|
self.wiz_scan_picking.location_id, self.picking_in_01.location_id
|
|
)
|
|
self.assertEqual(self.wiz_scan_picking.res_model_id, self.stock_picking_model)
|
|
self.assertEqual(self.wiz_scan_picking.res_id, self.picking_in_01.id)
|
|
self.assertIn(
|
|
"Barcode reader - %s - " % (self.picking_in_01.name),
|
|
self.wiz_scan_picking.display_name,
|
|
)
|
|
|
|
def test_picking_wizard_scan_product(self):
|
|
# self.wiz_scan_picking.manual_entry = True
|
|
wiz_scan_picking = self.wiz_scan_picking.with_context(
|
|
force_create_move=True, no_increase_qty_done=True
|
|
)
|
|
self.action_barcode_scanned(wiz_scan_picking, "8480000723208")
|
|
sml = self.picking_in_01.move_line_ids.filtered(
|
|
lambda x: x.product_id == self.product_wo_tracking
|
|
)
|
|
self.assertEqual(sml.qty_done, 1.0)
|
|
# Scan product with tracking lot enable
|
|
self.action_barcode_scanned(wiz_scan_picking, "8433281006850")
|
|
sml = self.picking_in_01.move_line_ids.filtered(
|
|
lambda x: x.product_id == self.product_tracking
|
|
)
|
|
self.assertEqual(sml.qty_done, 0.0)
|
|
self.assertEqual(
|
|
self.wiz_scan_picking.message,
|
|
"8433281006850 (Scan Product, Packaging, Lot / Serial)",
|
|
)
|
|
# Scan a lot. Increment quantities if scan product or other lot from
|
|
# this product
|
|
self.action_barcode_scanned(wiz_scan_picking, "8411822222568")
|
|
sml = self.picking_in_01.move_line_ids.filtered(
|
|
lambda x: x.product_id == self.product_tracking and x.lot_id
|
|
)
|
|
self.assertEqual(sml.lot_id, self.lot_1)
|
|
self.assertEqual(sml.qty_done, 1.0)
|
|
self.action_barcode_scanned(wiz_scan_picking, "8433281006850")
|
|
stock_move = sml.move_id
|
|
self.assertEqual(sum(stock_move.move_line_ids.mapped("qty_done")), 1.0)
|
|
self.action_barcode_scanned(wiz_scan_picking, "8411822222568")
|
|
self.assertEqual(sum(stock_move.move_line_ids.mapped("qty_done")), 1.0)
|
|
self.assertEqual(
|
|
self.wiz_scan_picking.message,
|
|
"8411822222568 (Scan Product, Packaging, Lot / Serial)",
|
|
)
|
|
# Scan a package
|
|
self.action_barcode_scanned(wiz_scan_picking, "5420008510489")
|
|
# Package of 5 product units. Already three unit exists
|
|
self.assertEqual(sum(stock_move.move_line_ids.mapped("qty_done")), 5.0)
|
|
|
|
def test_picking_wizard_scan_product_manual_entry(self):
|
|
wiz_scan_picking = self.wiz_scan_picking.with_context(
|
|
force_create_move=True, no_increase_qty_done=True
|
|
)
|
|
wiz_scan_picking.manual_entry = True
|
|
self.action_barcode_scanned(wiz_scan_picking, "8480000723208")
|
|
sml = self.picking_in_01.move_line_ids.filtered(
|
|
lambda x: x.product_id == self.product_wo_tracking
|
|
)
|
|
self.assertEqual(wiz_scan_picking.product_qty, 0.0)
|
|
wiz_scan_picking.product_qty = 12.0
|
|
wiz_scan_picking.action_confirm()
|
|
self.assertEqual(sml.qty_done, 12.0)
|
|
|
|
def test_barcode_from_operation(self):
|
|
picking_out_3 = self.picking_out_01.copy()
|
|
self.picking_out_01.action_assign()
|
|
self.picking_out_02.action_assign()
|
|
self.picking_type_out.default_location_dest_id = self.customer_location
|
|
|
|
action = self.picking_type_out.action_barcode_scan()
|
|
self.wiz_scan_picking = self.ScanReadPicking.browse(action["res_id"])
|
|
self.wiz_scan_picking.manual_entry = True
|
|
self.wiz_scan_picking.product_id = self.product_tracking
|
|
self.wiz_scan_picking.lot_id = self.lot_1
|
|
self.wiz_scan_picking.product_qty = 2
|
|
|
|
self.wiz_scan_picking.with_context(
|
|
force_create_move=True, no_increase_qty_done=True
|
|
).action_confirm()
|
|
self.assertEqual(len(self.wiz_scan_picking.candidate_picking_ids[0:2]), 2)
|
|
# Lock first picking
|
|
candidate = self.wiz_scan_picking.candidate_picking_ids.filtered(
|
|
lambda c: c.picking_id == self.picking_out_01
|
|
)
|
|
candidate_wiz = candidate.with_context(
|
|
wiz_barcode_id=self.wiz_scan_picking.id, picking_id=self.picking_out_01.id
|
|
)
|
|
candidate_wiz.with_context(force_create_move=True).action_lock_picking()
|
|
self.assertEqual(self.picking_out_01.move_ids.quantity_done, 2)
|
|
self.wiz_scan_picking.product_qty = 2
|
|
self.wiz_scan_picking.with_context(
|
|
force_create_move=True, no_increase_qty_done=True
|
|
).action_confirm()
|
|
self.assertEqual(self.picking_out_01.move_ids.quantity_done, 2)
|
|
|
|
# Picking out 3 is in confirmed state, so until confirmed moves has
|
|
# not been activated candidate pickings is 2
|
|
picking_out_3.action_confirm()
|
|
candidate_wiz.action_unlock_picking()
|
|
self.wiz_scan_picking.product_qty = 2
|
|
self.wiz_scan_picking.with_context(
|
|
force_create_move=True, no_increase_qty_done=True
|
|
).action_confirm()
|
|
self.assertEqual(len(self.wiz_scan_picking.candidate_picking_ids[0:2]), 2)
|
|
candidate_wiz.action_unlock_picking()
|
|
self.wiz_scan_picking.product_qty = 2
|
|
self.wiz_scan_picking.option_group_id.confirmed_moves = True
|
|
self.wiz_scan_picking.with_context(
|
|
force_create_move=True, no_increase_qty_done=True
|
|
).action_confirm()
|
|
self.assertEqual(len(self.wiz_scan_picking.candidate_picking_ids[0:3]), 3)
|
|
|
|
def test_picking_wizard_scan_product_auto_lot(self):
|
|
# Prepare more data
|
|
lot_2 = self.StockProductionLot.create(
|
|
{
|
|
"name": "8411822222578",
|
|
"product_id": self.product_tracking.id,
|
|
"company_id": self.company.id,
|
|
}
|
|
)
|
|
lot_3 = self.StockProductionLot.create(
|
|
{
|
|
"name": "8411822222588",
|
|
"product_id": self.product_tracking.id,
|
|
"company_id": self.company.id,
|
|
}
|
|
)
|
|
quant_lot_2 = self.StockQuant.create(
|
|
{
|
|
"product_id": self.product_tracking.id,
|
|
"lot_id": lot_2.id,
|
|
"location_id": self.stock_location.id,
|
|
"quantity": 15.0,
|
|
}
|
|
)
|
|
quant_lot_3 = self.StockQuant.create(
|
|
{
|
|
"product_id": self.product_tracking.id,
|
|
"lot_id": lot_3.id,
|
|
"location_id": self.stock_location.id,
|
|
"quantity": 10.0,
|
|
}
|
|
)
|
|
self.quant_lot_1.in_date = "2021-01-01"
|
|
quant_lot_2.in_date = "2021-01-05"
|
|
quant_lot_3.in_date = "2021-01-06"
|
|
# Scan product with tracking lot enable
|
|
self.action_barcode_scanned(self.wiz_scan_picking, "8433281006850")
|
|
self.assertEqual(
|
|
self.wiz_scan_picking.message,
|
|
"8433281006850 (Scan Product, Packaging, Lot / Serial)",
|
|
)
|
|
|
|
self.wiz_scan_picking.auto_lot = True
|
|
# self.wiz_scan_picking.manual_entry = True
|
|
|
|
# Removal strategy FIFO
|
|
|
|
# No auto lot for incoming pickings
|
|
self.action_barcode_scanned(self.wiz_scan_picking, "8433281006850")
|
|
self.assertFalse(self.wiz_scan_picking.lot_id)
|
|
|
|
# Continue test with a outgoing wizard
|
|
self.wiz_scan_picking_out.option_group_id.auto_lot = True
|
|
self.wiz_scan_picking_out.auto_lot = True
|
|
self.action_barcode_scanned(self.wiz_scan_picking_out, "8433281006850")
|
|
self.assertEqual(self.wiz_scan_picking_out.lot_id, self.lot_1)
|
|
|
|
# Removal strategy LIFO
|
|
self.wiz_scan_picking_out.lot_id = False
|
|
self.product_tracking.categ_id.removal_strategy_id = self.env.ref(
|
|
"stock.removal_lifo"
|
|
)
|
|
self.wiz_scan_picking_out.action_clean_values()
|
|
self.action_barcode_scanned(self.wiz_scan_picking_out, "8433281006850")
|
|
self.assertEqual(self.wiz_scan_picking_out.lot_id, lot_3)
|
|
|
|
@classmethod
|
|
def _create_barcode_option_group_incoming(cls):
|
|
return cls.env["stock.barcodes.option.group"].create(
|
|
{
|
|
"name": "option group incoming for tests",
|
|
"option_ids": [
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 1,
|
|
"name": "Location",
|
|
"field_name": "location_id",
|
|
"filled_default": True,
|
|
"to_scan": False,
|
|
"required": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 2,
|
|
"name": "Product",
|
|
"field_name": "product_id",
|
|
"to_scan": True,
|
|
"required": True,
|
|
"clean_after_done": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 2,
|
|
"name": "Packaging",
|
|
"field_name": "packaging_id",
|
|
"to_scan": True,
|
|
"required": False,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 2,
|
|
"name": "Lot / Serial",
|
|
"field_name": "lot_id",
|
|
"to_scan": True,
|
|
"required": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 3,
|
|
"name": "Location Dest",
|
|
"field_name": "location_dest_id",
|
|
"filled_default": True,
|
|
"to_scan": False,
|
|
"required": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 4,
|
|
"name": "Quantity",
|
|
"field_name": "product_qty",
|
|
"required": True,
|
|
"clean_after_done": True,
|
|
},
|
|
),
|
|
],
|
|
}
|
|
)
|
|
|
|
@classmethod
|
|
def _create_barcode_option_group_outgoing(cls):
|
|
return cls.env["stock.barcodes.option.group"].create(
|
|
{
|
|
"name": "option group outgoing for tests",
|
|
"option_ids": [
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 1,
|
|
"name": "Location",
|
|
"field_name": "location_id",
|
|
"to_scan": True,
|
|
"required": True,
|
|
"filled_default": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 2,
|
|
"name": "Product",
|
|
"field_name": "product_id",
|
|
"to_scan": True,
|
|
"required": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 2,
|
|
"name": "Packaging",
|
|
"field_name": "packaging_id",
|
|
"to_scan": True,
|
|
"required": False,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 2,
|
|
"name": "Lot / Serial",
|
|
"field_name": "lot_id",
|
|
"to_scan": True,
|
|
"required": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 3,
|
|
"name": "Location Dest",
|
|
"field_name": "location_dest_id",
|
|
"filled_default": True,
|
|
"to_scan": False,
|
|
"required": True,
|
|
},
|
|
),
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"step": 4,
|
|
"name": "Quantity",
|
|
"field_name": "product_qty",
|
|
"required": True,
|
|
"clean_after_done": True,
|
|
},
|
|
),
|
|
],
|
|
}
|
|
)
|
|
|
|
def test_stock_picking_validate(self):
|
|
self.picking_in_01.state = False
|
|
with self.assertRaises(UserError):
|
|
self.picking_in_01.with_context(
|
|
stock_barcodes_validate_picking=True
|
|
).button_validate()
|
|
|
|
def test_barcode_read_picking(self):
|
|
self.picking_in_01.state = "done"
|
|
self.wiz_scan_picking._compute_enable_add_product()
|
|
self.assertFalse(self.wiz_scan_picking.enable_add_product)
|
|
|
|
self.wiz_scan_picking.show_detailed_operations = False
|
|
self.wiz_scan_picking.action_show_detailed_operations()
|
|
self.assertTrue(self.wiz_scan_picking.action_show_detailed_operations)
|
|
|
|
self.wiz_scan_picking.action_show_detailed_operations()
|
|
self.assertFalse(self.wiz_scan_picking.show_detailed_operations)
|
|
|
|
def test_barcode_read_inventory(self):
|
|
context = {
|
|
"params": {
|
|
"model": "wiz.stock.barcodes.read.inventory",
|
|
"id": self.quant_lot_1.id,
|
|
}
|
|
}
|
|
with self.assertRaises(MissingError):
|
|
self.quant_lot_1.with_context(
|
|
**context
|
|
).action_barcode_inventory_quant_unlink()
|
|
context = {
|
|
"params": {
|
|
"model": self.wiz_scan_read_inventory._name,
|
|
"id": self.wiz_scan_read_inventory.id,
|
|
}
|
|
}
|
|
self.quant_lot_1.with_context(**context).action_barcode_inventory_quant_unlink()
|
|
self.assertIsNone(
|
|
self.quant_lot_1.with_context(
|
|
**context
|
|
).action_barcode_inventory_quant_unlink()
|
|
)
|
|
self.assertIsNone(self.quant_lot_1.enable_current_operations())
|
|
self.assertIsNone(self.quant_lot_1.action_barcode_inventory_quant_edit())
|
|
with self.assertRaises(ValueError):
|
|
self.quant_lot_1.write({"inventory_quantity": "test"})
|
|
self.quant_lot_1.operation_quantities_rest()
|
|
self.quant_lot_1.operation_quantities()
|
|
self.assertEqual(
|
|
type(self.picking_in_01.picking_type_id.get_action_picking_tree_ready()),
|
|
dict,
|
|
)
|
|
self.assertEqual(
|
|
type(
|
|
self.picking_in_01.picking_type_id.with_context(
|
|
**{"operations_mode": True}
|
|
).get_action_picking_tree_ready()
|
|
),
|
|
dict,
|
|
)
|
|
self.assertIsNone(self.wiz_scan_candidate_picking._compute_picking_quantity())
|
|
self.assertIsNone(self.wiz_scan_candidate_picking._compute_is_pending())
|
|
self.assertEqual(
|
|
self.wiz_scan_candidate_picking._get_picking_to_validate()._name,
|
|
self.picking_in_01._name,
|
|
)
|
|
self.assertEqual(
|
|
type(self.wiz_scan_candidate_picking.action_validate_picking()), tuple
|
|
)
|