odoo-addon-shopfloor 16.0.1.0.0.25__py3-none-any.whl → 16.0.2.1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/shopfloor/README.rst +1 -1
- odoo/addons/shopfloor/__manifest__.py +1 -1
- odoo/addons/shopfloor/actions/data.py +69 -34
- odoo/addons/shopfloor/actions/data_detail.py +20 -0
- odoo/addons/shopfloor/actions/message.py +94 -2
- odoo/addons/shopfloor/actions/move_line_search.py +2 -2
- odoo/addons/shopfloor/actions/packaging.py +10 -0
- odoo/addons/shopfloor/actions/schema.py +11 -0
- odoo/addons/shopfloor/actions/schema_detail.py +14 -8
- odoo/addons/shopfloor/actions/search.py +9 -6
- odoo/addons/shopfloor/components/scan_handler_product.py +2 -0
- odoo/addons/shopfloor/data/shopfloor_scenario_data.xml +4 -2
- odoo/addons/shopfloor/docs/checkout_diag_seq.plantuml +19 -5
- odoo/addons/shopfloor/docs/checkout_diag_seq.png +0 -0
- odoo/addons/shopfloor/docs/single_pack_transfer_diag_seq.plantuml +4 -4
- odoo/addons/shopfloor/docs/single_pack_transfer_diag_seq.png +0 -0
- odoo/addons/shopfloor/i18n/ca.po +373 -143
- odoo/addons/shopfloor/i18n/de.po +357 -145
- odoo/addons/shopfloor/i18n/es_AR.po +489 -174
- odoo/addons/shopfloor/i18n/it.po +642 -252
- odoo/addons/shopfloor/i18n/pt_BR.po +357 -145
- odoo/addons/shopfloor/i18n/shopfloor.pot +133 -8
- odoo/addons/shopfloor/migrations/16.0.2.0.0/post-migration.py +43 -0
- odoo/addons/shopfloor/models/shopfloor_menu.py +29 -5
- odoo/addons/shopfloor/models/stock_move_line.py +3 -0
- odoo/addons/shopfloor/models/stock_picking.py +11 -0
- odoo/addons/shopfloor/services/checkout.py +216 -61
- odoo/addons/shopfloor/services/cluster_picking.py +33 -18
- odoo/addons/shopfloor/services/delivery.py +25 -7
- odoo/addons/shopfloor/services/location_content_transfer.py +42 -28
- odoo/addons/shopfloor/services/single_pack_transfer.py +36 -13
- odoo/addons/shopfloor/services/zone_picking.py +187 -67
- odoo/addons/shopfloor/static/description/index.html +1 -1
- odoo/addons/shopfloor/tests/__init__.py +2 -0
- odoo/addons/shopfloor/tests/common.py +3 -1
- odoo/addons/shopfloor/tests/test_actions_data.py +46 -7
- odoo/addons/shopfloor/tests/test_actions_data_base.py +15 -0
- odoo/addons/shopfloor/tests/test_actions_data_detail.py +30 -8
- odoo/addons/shopfloor/tests/test_actions_packaging.py +43 -0
- odoo/addons/shopfloor/tests/test_checkout_base.py +15 -5
- odoo/addons/shopfloor/tests/test_checkout_done.py +40 -5
- odoo/addons/shopfloor/tests/test_checkout_list_delivery_packaging.py +1 -0
- odoo/addons/shopfloor/tests/test_checkout_list_package.py +3 -1
- odoo/addons/shopfloor/tests/test_checkout_scan.py +19 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_dest_location.py +99 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_line.py +3 -2
- odoo/addons/shopfloor/tests/test_checkout_scan_line_no_prefill_qty.py +48 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action.py +26 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action_no_prefill_qty.py +16 -0
- odoo/addons/shopfloor/tests/test_checkout_select_package_base.py +4 -1
- odoo/addons/shopfloor/tests/test_checkout_summary.py +1 -1
- odoo/addons/shopfloor/tests/test_cluster_picking_unload.py +37 -8
- odoo/addons/shopfloor/tests/test_delivery_list_stock_picking.py +5 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_base.py +4 -4
- odoo/addons/shopfloor/tests/test_location_content_transfer_set_destination_all.py +24 -2
- odoo/addons/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py +6 -4
- odoo/addons/shopfloor/tests/test_location_content_transfer_single.py +45 -0
- odoo/addons/shopfloor/tests/test_scan_anything.py +7 -0
- odoo/addons/shopfloor/tests/test_single_pack_transfer.py +59 -8
- odoo/addons/shopfloor/tests/test_zone_picking_base.py +36 -10
- odoo/addons/shopfloor/tests/test_zone_picking_change_pack_lot.py +2 -0
- odoo/addons/shopfloor/tests/test_zone_picking_complete_mix_pack_flux.py +59 -0
- odoo/addons/shopfloor/tests/test_zone_picking_select_line.py +33 -2
- odoo/addons/shopfloor/tests/test_zone_picking_select_line_first_scan_location.py +8 -3
- odoo/addons/shopfloor/tests/test_zone_picking_select_line_no_prefill_qty.py +19 -2
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination.py +88 -19
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_package_not_allowed.py +94 -0
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_pick_pack.py +1 -5
- odoo/addons/shopfloor/tests/test_zone_picking_start.py +4 -4
- odoo/addons/shopfloor/tests/test_zone_picking_unload_all.py +1 -1
- odoo/addons/shopfloor/tests/test_zone_picking_unload_set_destination.py +4 -4
- odoo/addons/shopfloor/views/shopfloor_menu.xml +30 -0
- {odoo_addon_shopfloor-16.0.1.0.0.25.dist-info → odoo_addon_shopfloor-16.0.2.1.0.1.dist-info}/METADATA +2 -2
- {odoo_addon_shopfloor-16.0.1.0.0.25.dist-info → odoo_addon_shopfloor-16.0.2.1.0.1.dist-info}/RECORD +76 -71
- {odoo_addon_shopfloor-16.0.1.0.0.25.dist-info → odoo_addon_shopfloor-16.0.2.1.0.1.dist-info}/WHEEL +0 -0
- {odoo_addon_shopfloor-16.0.1.0.0.25.dist-info → odoo_addon_shopfloor-16.0.2.1.0.1.dist-info}/top_level.txt +0 -0
@@ -53,8 +53,8 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
53
53
|
"name": location.name,
|
54
54
|
"barcode": location.name,
|
55
55
|
"operation_progress": {
|
56
|
-
"done":
|
57
|
-
"to_do":
|
56
|
+
"done": 0.0,
|
57
|
+
"to_do": 228.0,
|
58
58
|
},
|
59
59
|
}
|
60
60
|
self.assertDictEqual(data, expected)
|
@@ -86,13 +86,35 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
86
86
|
expected = {
|
87
87
|
"id": package.id,
|
88
88
|
"name": package.name,
|
89
|
-
"move_line_count": 1,
|
90
89
|
"packaging": self._expected_packaging(package.product_packaging_id),
|
91
90
|
"storage_type": self._expected_storage_type(package.package_type_id),
|
91
|
+
"total_quantity": 10.0,
|
92
92
|
"weight": 20.0,
|
93
93
|
}
|
94
94
|
self.assertDictEqual(data, expected)
|
95
95
|
|
96
|
+
def test_data_package_with_move_line_count(self):
|
97
|
+
package = self.move_a.move_line_ids.package_id
|
98
|
+
package.product_packaging_id = self.packaging.id
|
99
|
+
package.package_type_id = self.storage_type_pallet
|
100
|
+
data = self.data.package(
|
101
|
+
package,
|
102
|
+
picking=self.picking,
|
103
|
+
with_packaging=True,
|
104
|
+
with_package_move_line_count=True,
|
105
|
+
)
|
106
|
+
self.assert_schema(self.schema.package(with_packaging=True), data)
|
107
|
+
expected = {
|
108
|
+
"id": package.id,
|
109
|
+
"name": package.name,
|
110
|
+
"move_line_count": 2,
|
111
|
+
"packaging": self._expected_packaging(package.product_packaging_id),
|
112
|
+
"storage_type": self._expected_storage_type(package.package_type_id),
|
113
|
+
"weight": 20.0,
|
114
|
+
"total_quantity": sum(package.quant_ids.mapped("quantity")),
|
115
|
+
}
|
116
|
+
self.assertDictEqual(data, expected)
|
117
|
+
|
96
118
|
def test_data_package_level(self):
|
97
119
|
package_level = self.picking.package_level_ids[0]
|
98
120
|
data = self.data.package_level(package_level)
|
@@ -132,6 +154,7 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
132
154
|
"partner": {"id": self.customer.id, "name": self.customer.name},
|
133
155
|
"carrier": {"id": carrier.id, "name": carrier.name},
|
134
156
|
"ship_carrier": None,
|
157
|
+
"priority": "0",
|
135
158
|
}
|
136
159
|
self.assertEqual(data.pop("scheduled_date").split("T")[0], "2020-08-03")
|
137
160
|
self.assertDictEqual(data, expected)
|
@@ -156,6 +179,7 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
156
179
|
"carrier": {"id": carrier.id, "name": carrier.name},
|
157
180
|
"ship_carrier": None,
|
158
181
|
"progress": 0.0,
|
182
|
+
"priority": "0",
|
159
183
|
}
|
160
184
|
self.assertEqual(data.pop("scheduled_date").split("T")[0], "2020-08-03")
|
161
185
|
self.assertDictEqual(data, expected)
|
@@ -203,16 +227,18 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
203
227
|
"package_src": {
|
204
228
|
"id": move_line.package_id.id,
|
205
229
|
"name": move_line.package_id.name,
|
206
|
-
"move_line_count": 0,
|
207
230
|
"weight": 20.0,
|
208
231
|
"storage_type": None,
|
232
|
+
"total_quantity": sum(
|
233
|
+
move_line.package_id.quant_ids.mapped("quantity")
|
234
|
+
),
|
209
235
|
},
|
210
236
|
"package_dest": {
|
211
237
|
"id": result_package.id,
|
212
238
|
"name": result_package.name,
|
213
|
-
"move_line_count": 1,
|
214
239
|
"weight": 6.0,
|
215
240
|
"storage_type": None,
|
241
|
+
"total_quantity": sum(result_package.quant_ids.mapped("quantity")),
|
216
242
|
},
|
217
243
|
"location_src": self._expected_location(move_line.location_id),
|
218
244
|
"location_dest": self._expected_location(move_line.location_dest_id),
|
@@ -220,6 +246,10 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
220
246
|
"progress": 30.0,
|
221
247
|
}
|
222
248
|
self.assertDictEqual(data, expected)
|
249
|
+
data = self.data.move_line(move_line, with_package_move_line_count=True)
|
250
|
+
expected["package_src"]["move_line_count"] = 1
|
251
|
+
expected["package_dest"]["move_line_count"] = 1
|
252
|
+
self.assertDictEqual(data, expected)
|
223
253
|
|
224
254
|
def test_data_move_line_lot(self):
|
225
255
|
move_line = self.move_b.move_line_ids
|
@@ -264,16 +294,20 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
264
294
|
"package_src": {
|
265
295
|
"id": move_line.package_id.id,
|
266
296
|
"name": move_line.package_id.name,
|
267
|
-
"move_line_count": 1,
|
268
297
|
"weight": 30,
|
269
298
|
"storage_type": None,
|
299
|
+
"total_quantity": sum(
|
300
|
+
move_line.package_id.quant_ids.mapped("quantity")
|
301
|
+
),
|
270
302
|
},
|
271
303
|
"package_dest": {
|
272
304
|
"id": move_line.result_package_id.id,
|
273
305
|
"name": move_line.result_package_id.name,
|
274
|
-
"move_line_count": 1,
|
275
306
|
"weight": 0,
|
276
307
|
"storage_type": None,
|
308
|
+
"total_quantity": sum(
|
309
|
+
move_line.result_package_id.quant_ids.mapped("quantity")
|
310
|
+
),
|
277
311
|
},
|
278
312
|
"location_src": self._expected_location(move_line.location_id),
|
279
313
|
"location_dest": self._expected_location(move_line.location_dest_id),
|
@@ -281,6 +315,11 @@ class ActionsDataCase(ActionsDataCaseBase):
|
|
281
315
|
"progress": 0.0,
|
282
316
|
}
|
283
317
|
self.assertDictEqual(data, expected)
|
318
|
+
data = self.data.move_line(move_line, with_package_move_line_count=True)
|
319
|
+
self.assert_schema(self.schema.move_line(), data)
|
320
|
+
expected["package_src"]["move_line_count"] = 2
|
321
|
+
expected["package_dest"]["move_line_count"] = 2
|
322
|
+
self.assertDictEqual(data, expected)
|
284
323
|
|
285
324
|
def test_data_move_line_raw(self):
|
286
325
|
move_line = self.move_d.move_line_ids
|
@@ -176,6 +176,7 @@ class ActionsDataCaseBase(CommonCase, ActionsDataTestMixin):
|
|
176
176
|
"name": record.name,
|
177
177
|
"weight": record.pack_weight or record.estimated_pack_weight_kg,
|
178
178
|
"storage_type": None,
|
179
|
+
"total_quantity": sum(record.quant_ids.mapped("quantity")),
|
179
180
|
}
|
180
181
|
data.update(kw)
|
181
182
|
return data
|
@@ -242,3 +243,17 @@ class ActionsDataDetailCaseBase(ActionsDataCaseBase):
|
|
242
243
|
}
|
243
244
|
)
|
244
245
|
return dict(**self._expected_product(record), **detail)
|
246
|
+
|
247
|
+
def _expected_packaging_detail(self, record, **kw):
|
248
|
+
return dict(
|
249
|
+
**self._expected_packaging(record),
|
250
|
+
**{
|
251
|
+
"length": record.packaging_length,
|
252
|
+
"width": record.width,
|
253
|
+
"height": record.height,
|
254
|
+
"max_weight": record.package_type_id.max_weight,
|
255
|
+
"length_uom": record.length_uom_name,
|
256
|
+
"weight_uom": record.weight_uom_name,
|
257
|
+
"barcode": record.barcode,
|
258
|
+
}
|
259
|
+
)
|
@@ -33,9 +33,10 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
33
33
|
)
|
34
34
|
|
35
35
|
def test_data_packaging(self):
|
36
|
-
|
37
|
-
self.
|
38
|
-
self.
|
36
|
+
self.packaging.barcode = "barcode"
|
37
|
+
data = self.data_detail.packaging_detail(self.packaging)
|
38
|
+
self.assert_schema(self.schema_detail.packaging_detail(), data)
|
39
|
+
self.assertDictEqual(data, self._expected_packaging_detail(self.packaging))
|
39
40
|
|
40
41
|
def test_data_lot(self):
|
41
42
|
lot = self.env["stock.lot"].create(
|
@@ -81,7 +82,6 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
81
82
|
"name": package.location_id.display_name,
|
82
83
|
},
|
83
84
|
"name": package.name,
|
84
|
-
"move_line_count": 1,
|
85
85
|
"packaging": self.data_detail.packaging(package.product_packaging_id),
|
86
86
|
"weight": 20.0,
|
87
87
|
"pickings": self.data_detail.pickings(pickings),
|
@@ -90,8 +90,14 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
90
90
|
"id": self.storage_type_pallet.id,
|
91
91
|
"name": self.storage_type_pallet.name,
|
92
92
|
},
|
93
|
+
"total_quantity": sum(package.quant_ids.mapped("quantity")),
|
93
94
|
}
|
94
95
|
self.assertDictEqual(data, expected)
|
96
|
+
data = self.data_detail.package_detail(
|
97
|
+
package, picking=self.picking, with_package_move_line_count=True
|
98
|
+
)
|
99
|
+
expected.update({"move_line_count": 2})
|
100
|
+
self.assertDictEqual(data, expected)
|
95
101
|
|
96
102
|
def test_data_picking(self):
|
97
103
|
picking = self.picking
|
@@ -186,16 +192,20 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
186
192
|
"package_src": {
|
187
193
|
"id": move_line.package_id.id,
|
188
194
|
"name": move_line.package_id.name,
|
189
|
-
"move_line_count": 0,
|
190
195
|
"weight": 20.0,
|
191
196
|
"storage_type": None,
|
197
|
+
"total_quantity": sum(
|
198
|
+
move_line.package_id.quant_ids.mapped("quantity")
|
199
|
+
),
|
192
200
|
},
|
193
201
|
"package_dest": {
|
194
202
|
"id": result_package.id,
|
195
203
|
"name": result_package.name,
|
196
|
-
"move_line_count": 1,
|
197
204
|
"weight": 6.0,
|
198
205
|
"storage_type": None,
|
206
|
+
"total_quantity": sum(
|
207
|
+
move_line.result_package_id.quant_ids.mapped("quantity")
|
208
|
+
),
|
199
209
|
},
|
200
210
|
"location_src": self._expected_location(move_line.location_id),
|
201
211
|
"location_dest": self._expected_location(move_line.location_dest_id),
|
@@ -203,6 +213,10 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
203
213
|
"progress": 30.0,
|
204
214
|
}
|
205
215
|
self.assertDictEqual(data, expected)
|
216
|
+
data = self.data_detail.move_line(move_line, with_package_move_line_count=True)
|
217
|
+
expected["package_src"]["move_line_count"] = 1
|
218
|
+
expected["package_dest"]["move_line_count"] = 1
|
219
|
+
self.assertDictEqual(data, expected)
|
206
220
|
|
207
221
|
def test_data_move_line_lot(self):
|
208
222
|
move_line = self.move_b.move_line_ids
|
@@ -248,16 +262,20 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
248
262
|
"package_src": {
|
249
263
|
"id": move_line.package_id.id,
|
250
264
|
"name": move_line.package_id.name,
|
251
|
-
"move_line_count": 1,
|
252
265
|
"weight": 30.0,
|
253
266
|
"storage_type": None,
|
267
|
+
"total_quantity": sum(
|
268
|
+
move_line.package_id.quant_ids.mapped("quantity")
|
269
|
+
),
|
254
270
|
},
|
255
271
|
"package_dest": {
|
256
272
|
"id": move_line.result_package_id.id,
|
257
273
|
"name": move_line.result_package_id.name,
|
258
|
-
"move_line_count": 1,
|
259
274
|
"weight": 0.0,
|
260
275
|
"storage_type": None,
|
276
|
+
"total_quantity": sum(
|
277
|
+
move_line.result_package_id.quant_ids.mapped("quantity")
|
278
|
+
),
|
261
279
|
},
|
262
280
|
"location_src": self._expected_location(move_line.location_id),
|
263
281
|
"location_dest": self._expected_location(move_line.location_dest_id),
|
@@ -265,6 +283,10 @@ class TestActionsDataDetailCase(ActionsDataDetailCaseBase):
|
|
265
283
|
"progress": 0.0,
|
266
284
|
}
|
267
285
|
self.assertDictEqual(data, expected)
|
286
|
+
data = self.data_detail.move_line(move_line, with_package_move_line_count=True)
|
287
|
+
expected["package_src"]["move_line_count"] = 2
|
288
|
+
expected["package_dest"]["move_line_count"] = 2
|
289
|
+
self.assertDictEqual(data, expected)
|
268
290
|
|
269
291
|
def test_data_move_line_raw(self):
|
270
292
|
move_line = self.move_d.move_line_ids
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright 2023 Camptocamp SA (http://www.camptocamp.com)
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
|
4
|
+
# pylint: disable=missing-return
|
5
|
+
|
6
|
+
|
7
|
+
from .common import CommonCase
|
8
|
+
|
9
|
+
|
10
|
+
class TestActionsPackaging(CommonCase):
|
11
|
+
"""Tests covering methods to work on product packaging."""
|
12
|
+
|
13
|
+
@classmethod
|
14
|
+
def setUpClass(cls):
|
15
|
+
super().setUpClass()
|
16
|
+
with cls.work_on_actions(cls) as work:
|
17
|
+
cls.packaging = work.component(usage="packaging")
|
18
|
+
cls.picking = cls._create_picking(
|
19
|
+
lines=[(cls.product_a, 10), (cls.product_b, 10)], confirm=True
|
20
|
+
)
|
21
|
+
cls.move0 = cls.picking.move_ids[0]
|
22
|
+
cls.move1 = cls.picking.move_ids[1]
|
23
|
+
cls._fill_stock_for_moves(
|
24
|
+
cls.picking.move_ids, in_package=True, same_package=True
|
25
|
+
)
|
26
|
+
cls.picking.action_assign()
|
27
|
+
cls.package1 = cls.move0.move_line_ids.package_id
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def setUpClassVars(cls):
|
31
|
+
super().setUpClassVars()
|
32
|
+
cls.wh = cls.env.ref("stock.warehouse0")
|
33
|
+
cls.picking_type = cls.wh.out_type_id
|
34
|
+
|
35
|
+
def test_package_is_complete_mix_pack(self):
|
36
|
+
self.assertTrue(self.packaging.is_complete_mix_pack(self.package1))
|
37
|
+
|
38
|
+
def test_package_partially_reserved(self):
|
39
|
+
# Package has 2 products from pick 1 reserved
|
40
|
+
pick2 = self._create_picking(lines=[(self.product_c, 10)], confirm=True)
|
41
|
+
# But adding 1 more product from pick 2 that is not yet reserved
|
42
|
+
self._fill_stock_for_moves(pick2.move_ids, in_package=self.package1)
|
43
|
+
self.assertFalse(self.packaging.is_complete_mix_pack(self.package1))
|
@@ -35,8 +35,15 @@ class CheckoutCommonCase(CommonCase):
|
|
35
35
|
"checkout", menu=self.menu, profile=self.profile
|
36
36
|
)
|
37
37
|
|
38
|
-
def _stock_picking_data(
|
39
|
-
|
38
|
+
def _stock_picking_data(
|
39
|
+
self, picking, done=False, with_lines=True, with_location=False, **kw
|
40
|
+
):
|
41
|
+
return self.service._data_for_stock_picking(
|
42
|
+
picking, done, with_lines, with_location, **kw
|
43
|
+
)
|
44
|
+
|
45
|
+
def _stock_locations_data(self, locations, **kw):
|
46
|
+
return self.service._data_for_locations(locations, **kw)
|
40
47
|
|
41
48
|
# we test the methods that structure data in test_actions_data.py
|
42
49
|
def _picking_summary_data(self, picking):
|
@@ -45,8 +52,10 @@ class CheckoutCommonCase(CommonCase):
|
|
45
52
|
def _move_line_data(self, move_line):
|
46
53
|
return self.data.move_line(move_line)
|
47
54
|
|
48
|
-
def _package_data(self, package, picking):
|
49
|
-
return self.data.package(
|
55
|
+
def _package_data(self, package, picking, **kwargs):
|
56
|
+
return self.data.package(
|
57
|
+
package, picking=picking, with_packaging=True, **kwargs
|
58
|
+
)
|
50
59
|
|
51
60
|
def _packaging_data(self, packaging):
|
52
61
|
return self.data.delivery_packaging(packaging)
|
@@ -56,7 +65,7 @@ class CheckoutCommonCase(CommonCase):
|
|
56
65
|
"picking": self._stock_picking_data(picking),
|
57
66
|
"group_lines_by_location": True,
|
58
67
|
"show_oneline_package_content": False,
|
59
|
-
"need_confirm_pack_all":
|
68
|
+
"need_confirm_pack_all": "",
|
60
69
|
}
|
61
70
|
data.update(kw)
|
62
71
|
return data
|
@@ -72,6 +81,7 @@ class CheckoutCommonCase(CommonCase):
|
|
72
81
|
"picking": self._picking_summary_data(picking),
|
73
82
|
"packing_info": "",
|
74
83
|
"no_package_enabled": True,
|
84
|
+
"package_allowed": True,
|
75
85
|
},
|
76
86
|
message={
|
77
87
|
"message_type": "warning",
|
@@ -22,6 +22,7 @@ class CheckoutDoneCase(CheckoutCommonCase):
|
|
22
22
|
"message_type": "success",
|
23
23
|
"body": "Transfer {} done".format(picking.name),
|
24
24
|
},
|
25
|
+
data={"restrict_scan_first": False},
|
25
26
|
)
|
26
27
|
|
27
28
|
|
@@ -39,6 +40,13 @@ class CheckoutDonePartialCase(CheckoutCommonCase):
|
|
39
40
|
cls.line1.write({"qty_done": 10, "shopfloor_checkout_done": True})
|
40
41
|
cls.line2.write({"qty_done": 2, "shopfloor_checkout_done": True})
|
41
42
|
|
43
|
+
cls.dest_location = picking.location_dest_id
|
44
|
+
cls.child_location = (
|
45
|
+
cls.env["stock.location"]
|
46
|
+
.sudo()
|
47
|
+
.create({"name": "Child Location", "location_id": cls.dest_location.id})
|
48
|
+
)
|
49
|
+
|
42
50
|
def test_done_partial(self):
|
43
51
|
# line is done
|
44
52
|
response = self.service.dispatch("done", params={"picking_id": self.picking.id})
|
@@ -57,17 +65,43 @@ class CheckoutDonePartialCase(CheckoutCommonCase):
|
|
57
65
|
response = self.service.dispatch(
|
58
66
|
"done", params={"picking_id": self.picking.id, "confirmation": True}
|
59
67
|
)
|
60
|
-
|
61
|
-
# been extracted in a separate transfer. An usual backorder has been
|
62
|
-
# created for the unprocessed qty.
|
68
|
+
|
63
69
|
self.assertRecordValues(self.picking, [{"state": "done"}])
|
64
|
-
self.assertTrue(self.picking.backorder_ids)
|
65
|
-
self.assertEqual(self.picking.backorder_ids.move_line_ids.reserved_uom_qty, 8)
|
66
70
|
|
67
71
|
self.assert_response(
|
68
72
|
response,
|
69
73
|
next_state="select_document",
|
70
74
|
message=self.service.msg_store.transfer_done_success(self.picking),
|
75
|
+
data={"restrict_scan_first": False},
|
76
|
+
)
|
77
|
+
|
78
|
+
def test_done_ask_destination_location(self):
|
79
|
+
"""Check asking for destination location for view type location."""
|
80
|
+
view_location = (
|
81
|
+
self.env["stock.location"]
|
82
|
+
.sudo()
|
83
|
+
.create(
|
84
|
+
{
|
85
|
+
"name": "Test Location Usage View",
|
86
|
+
"location_id": self.picking.move_ids.location_dest_id.id,
|
87
|
+
"usage": "view",
|
88
|
+
}
|
89
|
+
)
|
90
|
+
)
|
91
|
+
self.picking.move_ids.location_dest_id = view_location
|
92
|
+
response = self.service.dispatch(
|
93
|
+
"done", params={"picking_id": self.picking.id, "confirmation": True}
|
94
|
+
)
|
95
|
+
|
96
|
+
self.assertRecordValues(self.picking, [{"state": "assigned"}])
|
97
|
+
self.assert_response(
|
98
|
+
response,
|
99
|
+
next_state="select_child_location",
|
100
|
+
data={
|
101
|
+
"picking": self._stock_picking_data(
|
102
|
+
self.picking, done=True, with_lines=False, with_location=True
|
103
|
+
),
|
104
|
+
},
|
71
105
|
)
|
72
106
|
|
73
107
|
|
@@ -130,4 +164,5 @@ class CheckoutDoneRawUnpackedCase(CheckoutCommonCase):
|
|
130
164
|
response,
|
131
165
|
next_state="select_document",
|
132
166
|
message=self.service.msg_store.transfer_done_success(picking_done),
|
167
|
+
data={"restrict_scan_first": False},
|
133
168
|
)
|
@@ -126,6 +126,7 @@ class CheckoutListDeliveryPackagingCase(CheckoutCommonCase, CheckoutSelectPackag
|
|
126
126
|
"no_package_enabled": not self.service.options.get(
|
127
127
|
"checkout__disable_no_package"
|
128
128
|
),
|
129
|
+
"package_allowed": True,
|
129
130
|
},
|
130
131
|
message=self.service.msg_store.no_delivery_packaging_available(),
|
131
132
|
)
|
@@ -28,7 +28,9 @@ class SelectDestPackageMixin:
|
|
28
28
|
"picking": picking_data,
|
29
29
|
"packages": [
|
30
30
|
self._package_data(
|
31
|
-
package.with_context(picking_id=picking.id),
|
31
|
+
package.with_context(picking_id=picking.id),
|
32
|
+
picking,
|
33
|
+
with_package_move_line_count=True,
|
32
34
|
)
|
33
35
|
for package in packages
|
34
36
|
],
|
@@ -31,6 +31,20 @@ class CheckoutScanCase(CheckoutCommonCase):
|
|
31
31
|
in_package=False,
|
32
32
|
)
|
33
33
|
|
34
|
+
def test_scan_document_with_option_product_not_ok(self):
|
35
|
+
self.menu.sudo().scan_location_or_pack_first = True
|
36
|
+
picking = self._create_picking()
|
37
|
+
self._fill_stock_for_moves(picking.move_ids)
|
38
|
+
picking.action_assign()
|
39
|
+
barcode = picking.move_line_ids.product_id[0].barcode
|
40
|
+
response = self.service.dispatch("scan_document", params={"barcode": barcode})
|
41
|
+
self.assert_response(
|
42
|
+
response,
|
43
|
+
next_state="select_document",
|
44
|
+
message={"message_type": "error", "body": "Barcode not found"},
|
45
|
+
data={"restrict_scan_first": True},
|
46
|
+
)
|
47
|
+
|
34
48
|
def test_scan_document_packaging_ok(self):
|
35
49
|
self._test_scan_ok(
|
36
50
|
lambda picking: picking.move_line_ids.product_id[0].packaging_ids.barcode,
|
@@ -43,6 +57,7 @@ class CheckoutScanCase(CheckoutCommonCase):
|
|
43
57
|
response,
|
44
58
|
next_state="select_document",
|
45
59
|
message={"message_type": "error", "body": "Barcode not found"},
|
60
|
+
data={"restrict_scan_first": False},
|
46
61
|
)
|
47
62
|
|
48
63
|
def _test_scan_document_error_not_available(self, barcode_func):
|
@@ -65,6 +80,7 @@ class CheckoutScanCase(CheckoutCommonCase):
|
|
65
80
|
"message_type": "error",
|
66
81
|
"body": "Transfer {} is not available.".format(picking.name),
|
67
82
|
},
|
83
|
+
data={"restrict_scan_first": False},
|
68
84
|
)
|
69
85
|
|
70
86
|
def test_scan_document_error_not_available_picking(self):
|
@@ -92,6 +108,7 @@ class CheckoutScanCase(CheckoutCommonCase):
|
|
92
108
|
response,
|
93
109
|
next_state="select_document",
|
94
110
|
message={"message_type": "error", "body": "Location not allowed here."},
|
111
|
+
data={"restrict_scan_first": False},
|
95
112
|
)
|
96
113
|
|
97
114
|
def _test_scan_document_error_different_picking_type(self, barcode_func):
|
@@ -107,6 +124,7 @@ class CheckoutScanCase(CheckoutCommonCase):
|
|
107
124
|
"message_type": "error",
|
108
125
|
"body": "You cannot move this using this menu.",
|
109
126
|
},
|
127
|
+
data={"restrict_scan_first": False},
|
110
128
|
)
|
111
129
|
|
112
130
|
def test_scan_document_error_different_picking_type_picking(self):
|
@@ -139,6 +157,7 @@ class CheckoutScanCase(CheckoutCommonCase):
|
|
139
157
|
"body": "Several transfers found, please scan a package"
|
140
158
|
" or select a transfer manually.",
|
141
159
|
},
|
160
|
+
data={"restrict_scan_first": False},
|
142
161
|
)
|
143
162
|
|
144
163
|
def test_scan_document_recover(self):
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright 2023 Camptocamp SA (http://www.camptocamp.com)
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
|
4
|
+
# pylint: disable=missing-return
|
5
|
+
|
6
|
+
from .test_checkout_base import CheckoutCommonCase
|
7
|
+
|
8
|
+
|
9
|
+
class CheckoutSelectChildLocationCase(CheckoutCommonCase):
|
10
|
+
@classmethod
|
11
|
+
def setUpClassBaseData(cls):
|
12
|
+
super().setUpClassBaseData()
|
13
|
+
cls.picking = picking = cls._create_picking(
|
14
|
+
lines=[(cls.product_a, 10), (cls.product_b, 10)]
|
15
|
+
)
|
16
|
+
cls._fill_stock_for_moves(picking.move_ids)
|
17
|
+
picking.action_assign()
|
18
|
+
cls.line1 = picking.move_line_ids[0]
|
19
|
+
cls.line2 = picking.move_line_ids[1]
|
20
|
+
cls.line1.write({"qty_done": 10, "shopfloor_checkout_done": True})
|
21
|
+
cls.line2.write({"qty_done": 2, "shopfloor_checkout_done": True})
|
22
|
+
|
23
|
+
cls.dest_location = picking.location_dest_id
|
24
|
+
cls.child_location = (
|
25
|
+
cls.env["stock.location"]
|
26
|
+
.sudo()
|
27
|
+
.create({"name": "Child Location", "location_id": cls.dest_location.id})
|
28
|
+
)
|
29
|
+
cls.child_location_view = (
|
30
|
+
cls.env["stock.location"]
|
31
|
+
.sudo()
|
32
|
+
.create(
|
33
|
+
{
|
34
|
+
"name": "Child Location View",
|
35
|
+
"location_id": cls.dest_location.id,
|
36
|
+
"usage": "view",
|
37
|
+
}
|
38
|
+
)
|
39
|
+
)
|
40
|
+
|
41
|
+
def test_scan_dest_location_ok(self):
|
42
|
+
response = self.service.dispatch(
|
43
|
+
"scan_dest_location",
|
44
|
+
params={
|
45
|
+
"picking_id": self.picking.id,
|
46
|
+
"barcode": self.child_location.name,
|
47
|
+
},
|
48
|
+
)
|
49
|
+
|
50
|
+
self.assertRecordValues(self.picking, [{"state": "done"}])
|
51
|
+
self.assertTrue(self.picking.backorder_ids)
|
52
|
+
self.assertEqual(self.picking.backorder_ids.move_line_ids.reserved_uom_qty, 8)
|
53
|
+
|
54
|
+
self.assert_response(
|
55
|
+
response,
|
56
|
+
next_state="select_document",
|
57
|
+
data={"restrict_scan_first": False},
|
58
|
+
message=self.service.msg_store.transfer_done_success(self.picking),
|
59
|
+
)
|
60
|
+
|
61
|
+
def test_scan_dest_location_not_found(self):
|
62
|
+
response = self.service.dispatch(
|
63
|
+
"scan_dest_location",
|
64
|
+
params={
|
65
|
+
"picking_id": self.picking.id,
|
66
|
+
"barcode": "not-a-location",
|
67
|
+
},
|
68
|
+
)
|
69
|
+
|
70
|
+
self.assert_response(
|
71
|
+
response,
|
72
|
+
next_state="select_child_location",
|
73
|
+
data={
|
74
|
+
"picking": self._stock_picking_data(
|
75
|
+
self.picking, done=True, with_lines=False, with_location=True
|
76
|
+
),
|
77
|
+
},
|
78
|
+
message=self.service.msg_store.location_not_found(),
|
79
|
+
)
|
80
|
+
|
81
|
+
def test_scan_dest_location_not_allowed(self):
|
82
|
+
response = self.service.dispatch(
|
83
|
+
"scan_dest_location",
|
84
|
+
params={
|
85
|
+
"picking_id": self.picking.id,
|
86
|
+
"barcode": self.child_location_view.name,
|
87
|
+
},
|
88
|
+
)
|
89
|
+
|
90
|
+
self.assert_response(
|
91
|
+
response,
|
92
|
+
next_state="select_child_location",
|
93
|
+
data={
|
94
|
+
"picking": self._stock_picking_data(
|
95
|
+
self.picking, done=True, with_lines=False, with_location=True
|
96
|
+
),
|
97
|
+
},
|
98
|
+
message=self.service.msg_store.dest_location_not_allowed(),
|
99
|
+
)
|
@@ -119,7 +119,8 @@ class CheckoutScanLineCase(CheckoutScanLineCaseBase):
|
|
119
119
|
picking.action_assign()
|
120
120
|
first_line = picking.move_line_ids[0]
|
121
121
|
lot = first_line.lot_id
|
122
|
-
|
122
|
+
related_lines = picking.move_line_ids - first_line
|
123
|
+
self._test_scan_line_ok(lot.name, first_line, related_lines)
|
123
124
|
|
124
125
|
def test_scan_line_product_in_one_package_all_package_lines_ok(self):
|
125
126
|
picking = self._create_picking(
|
@@ -365,7 +366,7 @@ class CheckoutScanLineCase(CheckoutScanLineCaseBase):
|
|
365
366
|
params={
|
366
367
|
"picking_id": picking.id,
|
367
368
|
"barcode": self.delivery_packaging.barcode,
|
368
|
-
"confirm_pack_all":
|
369
|
+
"confirm_pack_all": self.delivery_packaging.barcode,
|
369
370
|
},
|
370
371
|
)
|
371
372
|
# move to summary as all lines are done
|