Skip to content

Commit 926ec11

Browse files
[MIG] stock_picking_import_serial_number: Migration to 18.0
1 parent cdee984 commit 926ec11

File tree

6 files changed

+60
-75
lines changed

6 files changed

+60
-75
lines changed

stock_picking_import_serial_number/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"name": "Stock Picking Import Serial Numbers",
66
"summary": "Import S/N from excel file for incoming pickings",
7-
"version": "16.0.1.0.1",
7+
"version": "18.0.1.0.0",
88
"development_status": "Production/Stable",
99
"category": "stock",
1010
"website": "https://github.com/OCA/stock-logistics-workflow",

stock_picking_import_serial_number/tests/common.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def assertUniqueIn(self, element_list):
1111
elements = []
1212
for element in element_list:
1313
if element in elements:
14-
raise Exception("Element %s is not unique in list" % element)
14+
raise Exception(f"Element {element} is not unique in list")
1515
elements.append(element)
1616

1717
@classmethod
@@ -21,7 +21,6 @@ def setUpClass(cls):
2121
cls.warehouse = cls.env.ref("stock.warehouse0")
2222
cls.picking_type_in = cls.env.ref("stock.picking_type_in")
2323
cls.picking_type_in.use_create_lots = True
24-
cls.picking_type_in.show_reserved = True
2524
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
2625
cls.supplier = cls.env["res.partner"].create({"name": "Supplier - test"})
2726

@@ -34,7 +33,8 @@ def _create_product(cls, tracking="lot", reference=None):
3433
name = f"{tracking}"
3534
vals = {
3635
"name": name,
37-
"type": "product",
36+
"type": "consu",
37+
"is_storable": True,
3838
"tracking": tracking,
3939
}
4040
if reference:

stock_picking_import_serial_number/tests/test_stock_picking_import_serial_number.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def _create_wizard(self, pickings=False, filename=False):
4747
default_filename=filename,
4848
)
4949
)
50-
wizard_form.data_file = self._data_file("data/%s" % filename)
50+
wizard_form.data_file = self._data_file(f"data/{filename}")
5151
return wizard_form.save()
5252

5353
@mute_logger("odoo.models.unlink")
@@ -69,7 +69,7 @@ def test_import_serial_number_01(self):
6969
wiz = self._create_wizard()
7070
wiz.action_import()
7171
smls = self.picking_in_01.move_line_ids.filtered("lot_name")
72-
self.assertEqual(len(smls), 3)
72+
self.assertEqual(len(smls), 6)
7373
lot_names = smls.mapped("lot_name")
7474
self.assertIn("LOT-1", lot_names)
7575
self.assertIn("LOT-2", lot_names)
@@ -79,7 +79,7 @@ def test_import_serial_number_01(self):
7979
self.assertIn("PACK-2", package_names)
8080
self.assertIn("PACK-3", package_names)
8181
smls = self.picking_in_02.move_line_ids.filtered("lot_name")
82-
self.assertEqual(len(smls), 3)
82+
self.assertEqual(len(smls), 6)
8383
lot_names = smls.mapped("lot_name")
8484
self.assertIn("LOT-1", lot_names)
8585
self.assertIn("LOT-2", lot_names)
@@ -95,24 +95,24 @@ def test_import_serial_number_02(self):
9595
wiz = self._create_wizard(filename="SNImport-2.xls")
9696
wiz.action_import()
9797
smls = self.picking_in_01.move_line_ids.filtered("lot_name")
98-
self.assertEqual(len(smls), 3)
98+
self.assertEqual(len(smls), 6)
9999
lot_names = smls.mapped("lot_name")
100100
self.assertIn("LOT-1", lot_names)
101101
self.assertIn("LOT-2", lot_names)
102102
self.assertIn("LOT-3", lot_names)
103103
package_names = smls.mapped("result_package_id.name")
104104
self.assertIn("PACK-1", package_names)
105-
self.assertNotIn("PACK-2", package_names)
105+
self.assertIn("PACK-2", package_names)
106106
self.assertNotIn("PACK-3", package_names)
107107
smls = self.picking_in_02.move_line_ids.filtered("lot_name")
108-
self.assertEqual(len(smls), 3)
108+
self.assertEqual(len(smls), 6)
109109
lot_names = smls.mapped("lot_name")
110110
self.assertIn("LOT-1", lot_names)
111111
self.assertIn("LOT-2", lot_names)
112112
self.assertIn("LOT-3", lot_names)
113113
package_names = smls.mapped("result_package_id.name")
114114
self.assertIn("PACK-1", package_names)
115-
self.assertNotIn("PACK-2", package_names)
115+
self.assertIn("PACK-2", package_names)
116116
self.assertNotIn("PACK-3", package_names)
117117

118118
@mute_logger("odoo.models.unlink")
@@ -122,14 +122,14 @@ def test_import_serial_number_03(self):
122122
wiz.sn_package_column_index = 10
123123
wiz.action_import()
124124
smls = self.picking_in_01.move_line_ids.filtered("lot_name")
125-
self.assertEqual(len(smls), 3)
125+
self.assertEqual(len(smls), 6)
126126
lot_names = smls.mapped("lot_name")
127127
self.assertIn("LOT-1", lot_names)
128128
self.assertIn("LOT-2", lot_names)
129129
self.assertIn("LOT-3", lot_names)
130130
self.assertFalse(smls[0].result_package_id)
131131
smls = self.picking_in_02.move_line_ids.filtered("lot_name")
132-
self.assertEqual(len(smls), 3)
132+
self.assertEqual(len(smls), 6)
133133
lot_names = smls.mapped("lot_name")
134134
self.assertIn("LOT-1", lot_names)
135135
self.assertIn("LOT-2", lot_names)
@@ -139,13 +139,12 @@ def test_import_serial_number_03(self):
139139
@mute_logger("odoo.models.unlink")
140140
def test_import_serial_number_no_show_reserved_01(self):
141141
# Full import: Lots + packages (SNImport-1.xls)
142-
self.picking_in_01.picking_type_id.show_reserved = False
143142
picking = self.picking_in_01.copy()
144143
picking.action_confirm()
145144
picking.action_assign()
146145
wiz = self._create_wizard(pickings=picking)
147146
wiz.action_import()
148-
smls = picking.move_line_nosuggest_ids.filtered("lot_name")
147+
smls = picking.move_line_ids.filtered("lot_name")
149148
self.assertEqual(len(smls), 6)
150149
lot_names = smls.mapped("lot_name")
151150
self.assertIn("LOT-1", lot_names)
@@ -165,13 +164,12 @@ def test_import_serial_number_no_show_reserved_01(self):
165164
@mute_logger("odoo.models.unlink")
166165
def test_import_serial_number_no_show_reserved_02(self):
167166
# Full import: Lots + packages (SNImport-2.xls)
168-
self.picking_in_01.picking_type_id.show_reserved = False
169167
picking = self.picking_in_01.copy()
170168
picking.action_confirm()
171169
picking.action_assign()
172170
wiz = self._create_wizard(pickings=picking, filename="SNImport-2.xls")
173171
wiz.action_import()
174-
smls = picking.move_line_nosuggest_ids.filtered("lot_name")
172+
smls = picking.move_line_ids.filtered("lot_name")
175173
self.assertEqual(len(smls), 6)
176174
lot_names = smls.mapped("lot_name")
177175
self.assertIn("LOT-1", lot_names)
@@ -191,14 +189,13 @@ def test_import_serial_number_no_show_reserved_02(self):
191189
@mute_logger("odoo.models.unlink")
192190
def test_import_serial_number_no_show_reserved_03(self):
193191
# Import only lots
194-
self.picking_in_01.picking_type_id.show_reserved = False
195192
picking = self.picking_in_01.copy()
196193
picking.action_confirm()
197194
picking.action_assign()
198195
wiz = self._create_wizard(pickings=picking)
199196
wiz.sn_package_column_index = 10
200197
wiz.action_import()
201-
smls = picking.move_line_nosuggest_ids.filtered("lot_name")
198+
smls = picking.move_line_ids.filtered("lot_name")
202199
self.assertEqual(len(smls), 6)
203200
lot_names = smls.mapped("lot_name")
204201
self.assertIn("LOT-1", lot_names)

stock_picking_import_serial_number/views/res_config_settings_views.xml

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,63 +4,48 @@
44
<field name="model">res.config.settings</field>
55
<field name="inherit_id" ref="stock.res_config_settings_view_form" />
66
<field name="arch" type="xml">
7-
<div id="production_lot_info" position="after">
8-
<h2>Import S/N</h2>
9-
<div class="row mt16 o_settings_container" id="serial_number_importer">
10-
<div class="col-12 col-lg-6 o_setting_box">
11-
<div class="o_setting_left_pane" />
12-
<div class="o_setting_right_pane">
13-
<span class="o_form_label">Field to search products</span>
14-
<div class="text-muted">
7+
<block id="production_lot_info" position="after">
8+
<block title="Import S/N">
9+
<setting>
10+
<span class="o_form_label">Field to search products</span>
11+
<div class="text-muted">
1512
Select the field to search products
1613
</div>
17-
<div class="text-muted">
18-
<field name="default_sn_search_product_by_field" />
19-
</div>
14+
<div class="text-muted">
15+
<field name="default_sn_search_product_by_field" />
2016
</div>
21-
</div>
22-
<div class="col-12 col-lg-6 o_setting_box">
23-
<div class="o_setting_left_pane" />
24-
<div class="o_setting_right_pane">
25-
<span
26-
class="o_form_label"
27-
>File column index for products</span>
28-
<div class="text-muted">
17+
</setting>
18+
<setting>
19+
<span class="o_form_label">File column index for products</span>
20+
<div class="text-muted">
2921
Select the index file column which contains the product info
3022
</div>
31-
<div class="text-muted">
32-
<field name="default_sn_product_column_index" />
33-
</div>
23+
<div class="text-muted">
24+
<field name="default_sn_product_column_index" />
3425
</div>
35-
</div>
36-
<div class="col-12 col-lg-6 o_setting_box">
37-
<div class="o_setting_right_pane">
38-
<span
39-
class="o_form_label"
40-
>File column index for serial number</span>
41-
<div class="text-muted">
26+
</setting>
27+
<setting>
28+
<span
29+
class="o_form_label"
30+
>File column index for serial number</span>
31+
<div class="text-muted">
4232
Select the index file column which contains the serial numbers info
4333
</div>
44-
<div class="text-muted">
34+
<div class="text-muted">s
4535
<field name="default_sn_serial_column_index" />
4636
</div>
47-
</div>
48-
</div>
49-
<div class="col-12 col-lg-6 o_setting_box">
50-
<div class="o_setting_right_pane">
51-
<span
52-
class="o_form_label"
53-
>File column index for package</span>
54-
<div class="text-muted">
37+
</setting>
38+
<setting>
39+
<span class="o_form_label">File column index for package</span>
40+
<div class="text-muted">
5541
Select the index file column which contains the package info
5642
</div>
57-
<div class="text-muted">
58-
<field name="default_sn_package_column_index" />
59-
</div>
43+
<div class="text-muted">
44+
<field name="default_sn_package_column_index" />
6045
</div>
61-
</div>
62-
</div>
63-
</div>
46+
</setting>
47+
</block>
48+
</block>
6449
</field>
6550
</record>
6651
</odoo>

stock_picking_import_serial_number/views/stock_picking.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<field name="model">stock.picking</field>
44
<field name="inherit_id" ref="stock.view_picking_form" />
55
<field name="arch" type="xml">
6-
<button name="action_toggle_is_locked" position="after">
6+
<button name="action_cancel" position="before">
77
<button
88
name="%(action_import_serial_number)d"
99
string="Import S/N"
10-
attrs="{'invisible': ['|', ('state', '!=', 'assigned'), ('picking_type_code', '!=', 'incoming')]}"
10+
invisible="state != 'assigned' or picking_type_code != 'incoming'"
1111
type="action"
1212
groups="base.group_user"
1313
/>

stock_picking_import_serial_number/wizard/import_serial_number_wizard.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import xlrd
88

9-
from odoo import _, api, fields, models
9+
from odoo import api, fields, models
1010
from odoo.exceptions import UserError
1111

1212

@@ -49,13 +49,13 @@ def default_get(self, fields):
4949
def action_import(self):
5050
if self.picking_ids.filtered(lambda p: not p.picking_type_id.use_create_lots):
5151
raise UserError(
52-
_(
52+
self.env._(
5353
"You only can import S/N for picking operations with"
5454
" creation lots checked"
5555
)
5656
)
5757
if not self.data_file:
58-
raise UserError(_("You must upload file to import records"))
58+
raise UserError(self.env._("You must upload file to import records"))
5959
xl_workbook = False
6060
xl_sheet = False
6161
if self.filename.split(".")[1] in ["xls", "xlsx"]:
@@ -91,8 +91,7 @@ def _prepare_stock_move_line_vals(self, picking, product):
9191
"location_dest_id": picking.location_dest_id.id,
9292
"product_id": product.id,
9393
"product_uom_id": product.uom_id.id,
94-
"reserved_uom_qty": 0.0,
95-
"qty_done": 1.0,
94+
"quantity": 1.0,
9695
}
9796

9897
def _import_serial_number(self, xl_sheet, stock_move_lines, picking):
@@ -115,26 +114,30 @@ def _import_serial_number(self, xl_sheet, stock_move_lines, picking):
115114
)
116115
for item in serial_list:
117116
product = products.filtered(
118-
lambda p: p[self.sn_search_product_by_field] == item[0]
117+
lambda p, item=item[0]: p[self.sn_search_product_by_field] == item
119118
)
120-
if picking.picking_type_id.show_reserved:
121-
smls = stock_move_lines.filtered(lambda ln: ln.product_id == product)
119+
if picking.picking_type_code != "incoming":
120+
smls = stock_move_lines.filtered(
121+
lambda ln, product=product: ln.product_id == product
122+
)
122123
for sml in smls:
123124
if not sml.lot_name or self.overwrite_serial:
124125
sml.lot_name = item[1]
125-
sml.qty_done = 1.0
126+
sml.quantity = 1.0
126127
if item[2]:
127128
sml.result_package_id = self._search_or_create_package(
128129
picking, item[2]
129130
)
130131
# Only assign one serial
131132
break
132133
# TODO: Check if product is present on initial demand??
133-
# elif product and picking.move_lines.filtered(lambda ln: ln.product_id == product)
134+
# elif product and picking.move_lines.filtered(
135+
# lambda ln: ln.product_id == product)
134136
elif product:
135137
vals = self._prepare_stock_move_line_vals(picking, product)
136138
vals.update(lot_name=item[1])
137139
if item[2]:
138140
package = self._search_or_create_package(picking, item[2])
139141
vals.update(result_package_id=package.id)
142+
140143
self.env["stock.move.line"].create(vals)

0 commit comments

Comments
 (0)