odoo-addon-shopfloor 16.0.2.5.0.2__py3-none-any.whl → 16.0.2.7.0__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/message.py +50 -5
- odoo/addons/shopfloor/actions/stock_unreserve.py +11 -4
- odoo/addons/shopfloor/i18n/shopfloor.pot +35 -13
- odoo/addons/shopfloor/services/checkout.py +129 -105
- odoo/addons/shopfloor/services/cluster_picking.py +24 -8
- odoo/addons/shopfloor/services/delivery.py +89 -64
- odoo/addons/shopfloor/services/location_content_transfer.py +34 -18
- odoo/addons/shopfloor/services/service.py +52 -15
- odoo/addons/shopfloor/services/zone_picking.py +13 -9
- odoo/addons/shopfloor/static/description/index.html +1 -1
- odoo/addons/shopfloor/tests/test_checkout_scan.py +11 -3
- odoo/addons/shopfloor/tests/test_checkout_scan_line.py +35 -4
- odoo/addons/shopfloor/tests/test_checkout_select.py +3 -1
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_destination_no_prefill_qty.py +6 -4
- odoo/addons/shopfloor/tests/test_delivery_scan_deliver.py +143 -1
- odoo/addons/shopfloor/tests/test_delivery_set_qty_done_line.py +1 -1
- odoo/addons/shopfloor/tests/test_delivery_set_qty_done_pack.py +1 -1
- odoo/addons/shopfloor/tests/test_location_content_transfer_start.py +24 -1
- {odoo_addon_shopfloor-16.0.2.5.0.2.dist-info → odoo_addon_shopfloor-16.0.2.7.0.dist-info}/METADATA +2 -2
- {odoo_addon_shopfloor-16.0.2.5.0.2.dist-info → odoo_addon_shopfloor-16.0.2.7.0.dist-info}/RECORD +24 -24
- {odoo_addon_shopfloor-16.0.2.5.0.2.dist-info → odoo_addon_shopfloor-16.0.2.7.0.dist-info}/WHEEL +0 -0
- {odoo_addon_shopfloor-16.0.2.5.0.2.dist-info → odoo_addon_shopfloor-16.0.2.7.0.dist-info}/top_level.txt +0 -0
odoo/addons/shopfloor/README.rst
CHANGED
@@ -7,7 +7,7 @@ Shopfloor
|
|
7
7
|
!! This file is generated by oca-gen-addon-readme !!
|
8
8
|
!! changes will be overwritten. !!
|
9
9
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
10
|
-
!! source digest: sha256:
|
10
|
+
!! source digest: sha256:986a6c228f6ee438330907a4be64b74f7291bb1acfc6498a2617ed5e69777d9e
|
11
11
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
12
12
|
|
13
13
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
@@ -214,6 +214,15 @@ class MessageAction(Component):
|
|
214
214
|
def already_done(self):
|
215
215
|
return {"message_type": "info", "body": _("Operation already processed.")}
|
216
216
|
|
217
|
+
def transfer_canceled(self):
|
218
|
+
return {
|
219
|
+
"message_type": "info",
|
220
|
+
"body": _(
|
221
|
+
"Transfer has been canceled. "
|
222
|
+
"This cannot be processed using this scenario"
|
223
|
+
),
|
224
|
+
}
|
225
|
+
|
217
226
|
def move_already_done(self):
|
218
227
|
return {"message_type": "warning", "body": _("Move already processed.")}
|
219
228
|
|
@@ -458,6 +467,34 @@ class MessageAction(Component):
|
|
458
467
|
"body": _("No transfer found for this product."),
|
459
468
|
}
|
460
469
|
|
470
|
+
def transfer_not_found_for_barcode(self, barcode):
|
471
|
+
body = _("No transfer found for barcode %s", barcode)
|
472
|
+
return {
|
473
|
+
"message_type": "error",
|
474
|
+
"body": body,
|
475
|
+
}
|
476
|
+
|
477
|
+
def transfer_not_found_for_record(self, record):
|
478
|
+
model_mapping = {
|
479
|
+
"product.product": "product",
|
480
|
+
"stock.picking": "transfer",
|
481
|
+
"stock.quant.package": "package",
|
482
|
+
"product.packaging": "packaging",
|
483
|
+
"stock.location": "location",
|
484
|
+
"stock.lot": "lot",
|
485
|
+
"stock.move": "move",
|
486
|
+
}
|
487
|
+
model_name = model_mapping.get(record._name)
|
488
|
+
body = _(
|
489
|
+
"No transfer found for %(model_name)s %(record_name)s",
|
490
|
+
model_name=model_name,
|
491
|
+
record_name=record.name,
|
492
|
+
)
|
493
|
+
return {
|
494
|
+
"message_type": "error",
|
495
|
+
"body": body,
|
496
|
+
}
|
497
|
+
|
461
498
|
def product_not_found_in_location_or_transfer(self, product, location, picking):
|
462
499
|
return {
|
463
500
|
"message_type": "error",
|
@@ -526,11 +563,9 @@ class MessageAction(Component):
|
|
526
563
|
"body": _("Place it in {}?").format(location_name),
|
527
564
|
}
|
528
565
|
|
529
|
-
def product_not_found_in_current_picking(self):
|
530
|
-
|
531
|
-
|
532
|
-
"body": _("Product is not in the current transfer."),
|
533
|
-
}
|
566
|
+
def product_not_found_in_current_picking(self, product):
|
567
|
+
body = _("Product %s is not in the current transfer.", product.name)
|
568
|
+
return {"message_type": "error", "body": body}
|
534
569
|
|
535
570
|
def lot_mixed_package_scan_package(self):
|
536
571
|
return {
|
@@ -982,3 +1017,13 @@ class MessageAction(Component):
|
|
982
1017
|
"message_type": "error",
|
983
1018
|
"body": _("Unable to find a line with the same product but different lot."),
|
984
1019
|
}
|
1020
|
+
|
1021
|
+
def reserved_for_other_picking_type(self, picking):
|
1022
|
+
body = _("Reserved for %(picking_type)s %(picking_name)s") % {
|
1023
|
+
"picking_type": picking.picking_type_id.name,
|
1024
|
+
"picking_name": picking.name,
|
1025
|
+
}
|
1026
|
+
return {
|
1027
|
+
"message_type": "error",
|
1028
|
+
"body": body,
|
1029
|
+
}
|
@@ -10,7 +10,9 @@ class StockUnreserve(Component):
|
|
10
10
|
_inherit = "shopfloor.process.action"
|
11
11
|
_usage = "stock.unreserve"
|
12
12
|
|
13
|
-
def check_unreserve(
|
13
|
+
def check_unreserve(
|
14
|
+
self, location, move_lines, product=None, lot=None, allowed_types=None
|
15
|
+
):
|
14
16
|
"""Return a message if there is an ongoing operation in the location.
|
15
17
|
|
16
18
|
It could be a move line with some qty already processed or another
|
@@ -20,12 +22,17 @@ class StockUnreserve(Component):
|
|
20
22
|
:param move_lines: move lines to unreserve
|
21
23
|
:param product: optional product to limit the scope in the location
|
22
24
|
"""
|
25
|
+
if not allowed_types:
|
26
|
+
allowed_types = self.env["stock.picking.type"]
|
23
27
|
location_move_lines = self._find_location_all_move_lines(location, product, lot)
|
24
28
|
extra_move_lines = location_move_lines - move_lines
|
25
29
|
if extra_move_lines:
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
extra_pickings = extra_move_lines.picking_id
|
31
|
+
if allowed_types:
|
32
|
+
for picking in extra_pickings:
|
33
|
+
if picking.picking_type_id not in allowed_types:
|
34
|
+
return self.msg_store.reserved_for_other_picking_type(picking)
|
35
|
+
return self.msg_store.picking_already_started_in_location(extra_pickings)
|
29
36
|
|
30
37
|
def unreserve_moves(self, move_lines, picking_types):
|
31
38
|
"""Unreserve moves from `move_lines'.
|
@@ -839,6 +839,20 @@ msgstr ""
|
|
839
839
|
msgid "No quantity has been processed, unable to complete the transfer."
|
840
840
|
msgstr ""
|
841
841
|
|
842
|
+
#. module: shopfloor
|
843
|
+
#. odoo-python
|
844
|
+
#: code:addons/shopfloor/actions/message.py:0
|
845
|
+
#, python-format
|
846
|
+
msgid "No transfer found for %(model_name)s %(record_name)s"
|
847
|
+
msgstr ""
|
848
|
+
|
849
|
+
#. module: shopfloor
|
850
|
+
#. odoo-python
|
851
|
+
#: code:addons/shopfloor/actions/message.py:0
|
852
|
+
#, python-format
|
853
|
+
msgid "No transfer found for barcode %s"
|
854
|
+
msgstr ""
|
855
|
+
|
842
856
|
#. module: shopfloor
|
843
857
|
#. odoo-python
|
844
858
|
#: code:addons/shopfloor/actions/message.py:0
|
@@ -1047,13 +1061,6 @@ msgstr ""
|
|
1047
1061
|
msgid "Package {} is not empty."
|
1048
1062
|
msgstr ""
|
1049
1063
|
|
1050
|
-
#. module: shopfloor
|
1051
|
-
#. odoo-python
|
1052
|
-
#: code:addons/shopfloor/services/checkout.py:0
|
1053
|
-
#, python-format
|
1054
|
-
msgid "Package {} is not in the current transfer."
|
1055
|
-
msgstr ""
|
1056
|
-
|
1057
1064
|
#. module: shopfloor
|
1058
1065
|
#: model:ir.model,name:shopfloor.model_stock_quant_package
|
1059
1066
|
msgid "Packages"
|
@@ -1209,16 +1216,16 @@ msgid ""
|
|
1209
1216
|
" %(picking_name)s."
|
1210
1217
|
msgstr ""
|
1211
1218
|
|
1212
|
-
#. module: shopfloor
|
1213
|
-
#: model:ir.model,name:shopfloor.model_stock_move_line
|
1214
|
-
msgid "Product Moves (Stock Move Line)"
|
1215
|
-
msgstr ""
|
1216
|
-
|
1217
1219
|
#. module: shopfloor
|
1218
1220
|
#. odoo-python
|
1219
1221
|
#: code:addons/shopfloor/actions/message.py:0
|
1220
1222
|
#, python-format
|
1221
|
-
msgid "Product is not in the current transfer."
|
1223
|
+
msgid "Product %s is not in the current transfer."
|
1224
|
+
msgstr ""
|
1225
|
+
|
1226
|
+
#. module: shopfloor
|
1227
|
+
#: model:ir.model,name:shopfloor.model_stock_move_line
|
1228
|
+
msgid "Product Moves (Stock Move Line)"
|
1222
1229
|
msgstr ""
|
1223
1230
|
|
1224
1231
|
#. module: shopfloor
|
@@ -1289,6 +1296,13 @@ msgstr ""
|
|
1289
1296
|
msgid "Reserved Move Line"
|
1290
1297
|
msgstr ""
|
1291
1298
|
|
1299
|
+
#. module: shopfloor
|
1300
|
+
#. odoo-python
|
1301
|
+
#: code:addons/shopfloor/actions/message.py:0
|
1302
|
+
#, python-format
|
1303
|
+
msgid "Reserved for %(picking_type)s %(picking_name)s"
|
1304
|
+
msgstr ""
|
1305
|
+
|
1292
1306
|
#. module: shopfloor
|
1293
1307
|
#. odoo-python
|
1294
1308
|
#: code:addons/shopfloor/actions/message.py:0
|
@@ -1890,6 +1904,14 @@ msgstr ""
|
|
1890
1904
|
msgid "Transfer"
|
1891
1905
|
msgstr ""
|
1892
1906
|
|
1907
|
+
#. module: shopfloor
|
1908
|
+
#. odoo-python
|
1909
|
+
#: code:addons/shopfloor/actions/message.py:0
|
1910
|
+
#, python-format
|
1911
|
+
msgid ""
|
1912
|
+
"Transfer has been canceled. This cannot be processed using this scenario"
|
1913
|
+
msgstr ""
|
1914
|
+
|
1893
1915
|
#. module: shopfloor
|
1894
1916
|
#. odoo-python
|
1895
1917
|
#: code:addons/shopfloor/actions/message.py:0
|
@@ -214,25 +214,29 @@ class Checkout(Component):
|
|
214
214
|
* summary: stock.picking is selected and all its lines have a
|
215
215
|
destination pack set
|
216
216
|
"""
|
217
|
-
|
218
|
-
|
219
|
-
|
217
|
+
handlers = {
|
218
|
+
"picking": self._select_document_from_picking,
|
219
|
+
"location": self._select_document_from_location,
|
220
|
+
"package": self._select_document_from_package,
|
221
|
+
"packaging": self._select_document_from_packaging,
|
222
|
+
"product": self._select_document_from_product,
|
223
|
+
"none": self._select_document_from_none,
|
224
|
+
}
|
225
|
+
if self.work.menu.scan_location_or_pack_first:
|
226
|
+
handlers.pop("product")
|
227
|
+
search_result = self._scan_document_find(barcode, handlers.keys())
|
228
|
+
# Keep track of what has been initially scan, and forward it through kwargs
|
229
|
+
kwargs = {
|
230
|
+
"barcode": barcode,
|
231
|
+
"current_state": "select_document",
|
232
|
+
"scanned_record": search_result.record,
|
233
|
+
}
|
234
|
+
handler = handlers.get(search_result.type, self._select_document_from_none)
|
235
|
+
return handler(search_result.record, **kwargs)
|
220
236
|
|
221
|
-
def _scan_document_find(self, barcode, search_types
|
237
|
+
def _scan_document_find(self, barcode, search_types):
|
222
238
|
search = self._actions_for("search")
|
223
|
-
|
224
|
-
"picking",
|
225
|
-
"location",
|
226
|
-
"package",
|
227
|
-
"packaging",
|
228
|
-
) + (("product",) if not self.work.menu.scan_location_or_pack_first else ())
|
229
|
-
return search.find(
|
230
|
-
barcode,
|
231
|
-
types=search_types,
|
232
|
-
)
|
233
|
-
|
234
|
-
def _select_document_from_picking(self, picking, **kw):
|
235
|
-
return self._select_picking(picking, "select_document")
|
239
|
+
return search.find(barcode, types=search_types)
|
236
240
|
|
237
241
|
def _select_document_from_location(self, location, **kw):
|
238
242
|
if not self.is_src_location_valid(location):
|
@@ -251,7 +255,9 @@ class Checkout(Component):
|
|
251
255
|
),
|
252
256
|
}
|
253
257
|
)
|
254
|
-
|
258
|
+
# Keep track of what has been initially scan, and forward it through kwargs
|
259
|
+
kwargs = {**kw, "current_state": "select_document"}
|
260
|
+
return self._select_document_from_picking(pickings, **kwargs)
|
255
261
|
|
256
262
|
def _select_document_from_package(self, package, **kw):
|
257
263
|
pickings = package.move_line_ids.filtered(
|
@@ -260,14 +266,15 @@ class Checkout(Component):
|
|
260
266
|
if len(pickings) > 1:
|
261
267
|
# Filter only if we find several pickings to narrow the
|
262
268
|
# selection to one of the good type. If we have one picking
|
263
|
-
# of the wrong type, it will be caught in
|
269
|
+
# of the wrong type, it will be caught in _select_document_from_picking
|
264
270
|
# with the proper error message.
|
265
271
|
# Side note: rather unlikely to have several transfers ready
|
266
272
|
# and moving the same things
|
267
273
|
pickings = pickings.filtered(
|
268
274
|
lambda p: p.picking_type_id in self.picking_types
|
269
275
|
)
|
270
|
-
|
276
|
+
kwargs = {**kw, "current_state": "select_document"}
|
277
|
+
return self._select_document_from_picking(fields.first(pickings), **kwargs)
|
271
278
|
|
272
279
|
def _select_document_from_product(self, product, line_domain=None, **kw):
|
273
280
|
line_domain = line_domain or []
|
@@ -287,7 +294,8 @@ class Checkout(Component):
|
|
287
294
|
order="priority desc, scheduled_date asc, id desc",
|
288
295
|
limit=1,
|
289
296
|
)
|
290
|
-
|
297
|
+
kwargs = {**kw, "current_state": "select_document"}
|
298
|
+
return self._select_document_from_picking(picking, **kwargs)
|
291
299
|
|
292
300
|
def _select_document_from_packaging(self, packaging, **kw):
|
293
301
|
# And retrieve its product
|
@@ -298,35 +306,33 @@ class Checkout(Component):
|
|
298
306
|
line_domain = [("reserved_uom_qty", ">=", packaging.qty)]
|
299
307
|
return self._select_document_from_product(product, line_domain=line_domain)
|
300
308
|
|
301
|
-
def _select_document_from_none(self,
|
309
|
+
def _select_document_from_none(self, *args, barcode=None, **kwargs):
|
302
310
|
"""Handle result when no record is found."""
|
303
|
-
return self.
|
311
|
+
return self._response_for_select_document(
|
312
|
+
message=self.msg_store.transfer_not_found_for_barcode(barcode)
|
313
|
+
)
|
304
314
|
|
305
|
-
def
|
315
|
+
def _select_document_from_picking(
|
316
|
+
self, picking, current_state=None, barcode=None, **kwargs
|
317
|
+
):
|
318
|
+
# Get origin record to give more context to the user when raising an error
|
319
|
+
# as we got picking from product/package/packaging/...
|
320
|
+
scanned_record = kwargs.get("scanned_record")
|
306
321
|
if not picking:
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
return self._response_for_select_document(
|
312
|
-
message=self.msg_store.barcode_not_found()
|
313
|
-
)
|
322
|
+
message = self.msg_store.transfer_not_found_for_record(scanned_record)
|
323
|
+
if current_state == "manual_selection":
|
324
|
+
return self._response_for_manual_selection(message=message)
|
325
|
+
return self._response_for_select_document(message=message)
|
314
326
|
if picking.picking_type_id not in self.picking_types:
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
return self._response_for_select_document(
|
320
|
-
message=self.msg_store.cannot_move_something_in_picking_type()
|
321
|
-
)
|
327
|
+
message = self.msg_store.reserved_for_other_picking_type(picking)
|
328
|
+
if current_state == "manual_selection":
|
329
|
+
return self._response_for_manual_selection(message=message)
|
330
|
+
return self._response_for_select_document(message=message)
|
322
331
|
if picking.state != "assigned":
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
return self._response_for_select_document(
|
328
|
-
message=self.msg_store.stock_picking_not_available(picking)
|
329
|
-
)
|
332
|
+
message = self.msg_store.stock_picking_not_available(picking)
|
333
|
+
if current_state == "manual_selection":
|
334
|
+
return self._response_for_manual_selection(message=message)
|
335
|
+
return self._response_for_select_document(message=message)
|
330
336
|
return self._response_for_select_line(picking)
|
331
337
|
|
332
338
|
def _data_for_move_lines(self, lines, **kw):
|
@@ -402,10 +408,17 @@ class Checkout(Component):
|
|
402
408
|
lines
|
403
409
|
"""
|
404
410
|
picking = self.env["stock.picking"].browse(picking_id)
|
405
|
-
message = self.
|
411
|
+
message = self._check_picking_processible(picking)
|
406
412
|
if message:
|
407
413
|
return self._response_for_manual_selection(message=message)
|
408
|
-
|
414
|
+
# Because _select_document_from_picking expects some context
|
415
|
+
# to give meaningful infos to the user, add some here.
|
416
|
+
kwargs = {
|
417
|
+
"current_state": "manual_selection",
|
418
|
+
"barcode": picking.name,
|
419
|
+
"scanned_record": picking,
|
420
|
+
}
|
421
|
+
return self._select_document_from_picking(picking, **kwargs)
|
409
422
|
|
410
423
|
def _select_lines(self, lines, prefill_qty=0, related_lines=None):
|
411
424
|
for i, line in enumerate(lines):
|
@@ -451,7 +464,7 @@ class Checkout(Component):
|
|
451
464
|
screen to change the qty done and destination pack if needed
|
452
465
|
"""
|
453
466
|
picking = self.env["stock.picking"].browse(picking_id)
|
454
|
-
message = self.
|
467
|
+
message = self._check_picking_processible(picking)
|
455
468
|
if message:
|
456
469
|
return self._response_for_select_document(message=message)
|
457
470
|
|
@@ -460,21 +473,31 @@ class Checkout(Component):
|
|
460
473
|
return self._response_for_summary(picking)
|
461
474
|
|
462
475
|
# Search of the destination package
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
476
|
+
handlers = {
|
477
|
+
"package": self._select_lines_from_package,
|
478
|
+
"product": self._select_lines_from_product,
|
479
|
+
"packaging": self._select_lines_from_packaging,
|
480
|
+
"lot": self._select_lines_from_lot,
|
481
|
+
"serial": self._select_lines_from_serial,
|
482
|
+
"delivery_packaging": self._select_lines_from_delivery_packaging,
|
483
|
+
"none": self._select_lines_from_none,
|
484
|
+
}
|
485
|
+
search_result = self._scan_line_find(picking, barcode, handlers.keys())
|
486
|
+
# setting scanned record as kwarg in order to make better logs.
|
487
|
+
# The reason for this is that from a product we might select various records
|
488
|
+
# and lose track of what was initially scanned. This forces us to display
|
489
|
+
# standard messages that might have no meaning for the user.
|
490
|
+
kwargs = {
|
491
|
+
"confirm_pack_all": confirm_pack_all,
|
492
|
+
"confirm_lot": confirm_lot,
|
493
|
+
"scanned_record": search_result.record,
|
494
|
+
"barcode": barcode,
|
495
|
+
}
|
496
|
+
handler = handlers.get(search_result.type, self._select_lines_from_none)
|
497
|
+
return handler(picking, selection_lines, search_result.record, **kwargs)
|
467
498
|
|
468
|
-
def _scan_line_find(self, picking, barcode, search_types
|
499
|
+
def _scan_line_find(self, picking, barcode, search_types):
|
469
500
|
search = self._actions_for("search")
|
470
|
-
search_types = (
|
471
|
-
"package",
|
472
|
-
"product",
|
473
|
-
"packaging",
|
474
|
-
"lot",
|
475
|
-
"serial",
|
476
|
-
"delivery_packaging",
|
477
|
-
)
|
478
501
|
return search.find(
|
479
502
|
barcode,
|
480
503
|
types=search_types,
|
@@ -497,15 +520,14 @@ class Checkout(Component):
|
|
497
520
|
lambda l: l.package_id == package and not l.shopfloor_checkout_done
|
498
521
|
)
|
499
522
|
if not lines:
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
)
|
523
|
+
# No line for scanned package in selected picking
|
524
|
+
# Check if there's any picking reserving this product.
|
525
|
+
return_picking = self._get_pickings_for_package(package, limit=1)
|
526
|
+
if return_picking:
|
527
|
+
message = self.msg_store.reserved_for_other_picking_type(return_picking)
|
528
|
+
else:
|
529
|
+
message = self.msg_store.package_not_found_in_picking(package, picking)
|
530
|
+
return self._response_for_select_line(picking, message=message)
|
509
531
|
self._select_lines(lines, prefill_qty=prefill_qty)
|
510
532
|
if self.work.menu.no_prefill_qty:
|
511
533
|
lines = picking.move_line_ids
|
@@ -522,9 +544,12 @@ class Checkout(Component):
|
|
522
544
|
|
523
545
|
lines = selection_lines.filtered(lambda l: l.product_id == product)
|
524
546
|
if not lines:
|
525
|
-
|
526
|
-
|
527
|
-
|
547
|
+
return_picking = self._get_pickings_for_product(product, limit=1)
|
548
|
+
if return_picking:
|
549
|
+
message = self.msg_store.reserved_for_other_picking_type(return_picking)
|
550
|
+
else:
|
551
|
+
message = self.msg_store.product_not_found_in_current_picking(product)
|
552
|
+
return self._response_for_select_line(picking, message=message)
|
528
553
|
|
529
554
|
# When products are as units outside of packages, we can select them for
|
530
555
|
# packing, but if they are in a package, we want the user to scan the packages.
|
@@ -774,7 +799,7 @@ class Checkout(Component):
|
|
774
799
|
assert package_id or move_line_id
|
775
800
|
|
776
801
|
picking = self.env["stock.picking"].browse(picking_id)
|
777
|
-
message = self.
|
802
|
+
message = self._check_picking_processible(picking)
|
778
803
|
if message:
|
779
804
|
return self._response_for_select_document(message=message)
|
780
805
|
|
@@ -793,7 +818,7 @@ class Checkout(Component):
|
|
793
818
|
self, picking_id, selected_line_ids, move_line_ids, quantity_func
|
794
819
|
):
|
795
820
|
picking = self.env["stock.picking"].browse(picking_id)
|
796
|
-
message = self.
|
821
|
+
message = self._check_picking_processible(picking)
|
797
822
|
if message:
|
798
823
|
return self._response_for_select_document(message=message)
|
799
824
|
|
@@ -1031,25 +1056,28 @@ class Checkout(Component):
|
|
1031
1056
|
to close the stock picking
|
1032
1057
|
"""
|
1033
1058
|
picking = self.env["stock.picking"].browse(picking_id)
|
1034
|
-
message = self.
|
1059
|
+
message = self._check_picking_processible(picking)
|
1035
1060
|
if message:
|
1036
1061
|
return self._response_for_select_document(message=message)
|
1037
1062
|
|
1038
1063
|
selected_lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1064
|
+
handlers = {
|
1065
|
+
"package": self._scan_package_action_from_package,
|
1066
|
+
"product": self._scan_package_action_from_product,
|
1067
|
+
"packaging": self._scan_package_action_from_packaging,
|
1068
|
+
"lot": self._scan_package_action_from_lot,
|
1069
|
+
"serial": self._scan_package_action_from_serial,
|
1070
|
+
"delivery_packaging": self._scan_package_action_from_delivery_packaging,
|
1071
|
+
}
|
1072
|
+
search_result = self._scan_package_find(picking, barcode, handlers.keys())
|
1073
|
+
handler = handlers.get(search_result.type, self._scan_package_action_from_none)
|
1074
|
+
kwargs = {
|
1075
|
+
"barcode": barcode,
|
1076
|
+
"scanned_record": search_result.record,
|
1077
|
+
}
|
1078
|
+
return handler(picking, selected_lines, search_result.record, **kwargs)
|
1051
1079
|
|
1052
|
-
def _scan_package_find(self, picking, barcode, search_types
|
1080
|
+
def _scan_package_find(self, picking, barcode, search_types):
|
1053
1081
|
search = self._actions_for("search")
|
1054
1082
|
search_types = (
|
1055
1083
|
"package",
|
@@ -1068,10 +1096,6 @@ class Checkout(Component):
|
|
1068
1096
|
),
|
1069
1097
|
)
|
1070
1098
|
|
1071
|
-
def _check_scan_package_find(self, picking, search_result):
|
1072
|
-
# Used by inheriting modules
|
1073
|
-
return False
|
1074
|
-
|
1075
1099
|
def _find_line_to_increment(self, product_lines):
|
1076
1100
|
"""Find which line should have its qty incremented.
|
1077
1101
|
|
@@ -1186,7 +1210,7 @@ class Checkout(Component):
|
|
1186
1210
|
* select_package: when no delivery packaging is available
|
1187
1211
|
"""
|
1188
1212
|
picking = self.env["stock.picking"].browse(picking_id)
|
1189
|
-
message = self.
|
1213
|
+
message = self._check_picking_processible(picking)
|
1190
1214
|
if message:
|
1191
1215
|
return self._response_for_select_document(message=message)
|
1192
1216
|
selected_lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
@@ -1216,7 +1240,7 @@ class Checkout(Component):
|
|
1216
1240
|
* select_line: goes back to selection of lines to work on next lines
|
1217
1241
|
"""
|
1218
1242
|
picking = self.env["stock.picking"].browse(picking_id)
|
1219
|
-
message = self.
|
1243
|
+
message = self._check_picking_processible(picking)
|
1220
1244
|
if message:
|
1221
1245
|
return self._response_for_select_document(message=message)
|
1222
1246
|
packaging = None
|
@@ -1238,7 +1262,7 @@ class Checkout(Component):
|
|
1238
1262
|
if self.options.get("checkout__disable_no_package"):
|
1239
1263
|
raise BadRequest("`checkout.no_package` endpoint is not enabled")
|
1240
1264
|
picking = self.env["stock.picking"].browse(picking_id)
|
1241
|
-
message = self.
|
1265
|
+
message = self._check_picking_processible(picking)
|
1242
1266
|
if message:
|
1243
1267
|
return self._response_for_select_document(message=message)
|
1244
1268
|
selected_lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
@@ -1270,7 +1294,7 @@ class Checkout(Component):
|
|
1270
1294
|
* select_package: when no package is available
|
1271
1295
|
"""
|
1272
1296
|
picking = self.env["stock.picking"].browse(picking_id)
|
1273
|
-
message = self.
|
1297
|
+
message = self._check_picking_processible(picking)
|
1274
1298
|
if message:
|
1275
1299
|
return self._response_for_select_document(message=message)
|
1276
1300
|
lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
@@ -1320,7 +1344,7 @@ class Checkout(Component):
|
|
1320
1344
|
* summary: all lines are put in packages
|
1321
1345
|
"""
|
1322
1346
|
picking = self.env["stock.picking"].browse(picking_id)
|
1323
|
-
message = self.
|
1347
|
+
message = self._check_picking_processible(picking)
|
1324
1348
|
if message:
|
1325
1349
|
return self._response_for_select_document(message=message)
|
1326
1350
|
lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
@@ -1347,7 +1371,7 @@ class Checkout(Component):
|
|
1347
1371
|
* summary: all lines are put in packages
|
1348
1372
|
"""
|
1349
1373
|
picking = self.env["stock.picking"].browse(picking_id)
|
1350
|
-
message = self.
|
1374
|
+
message = self._check_picking_processible(picking)
|
1351
1375
|
if message:
|
1352
1376
|
return self._response_for_select_document(message=message)
|
1353
1377
|
lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
@@ -1374,7 +1398,7 @@ class Checkout(Component):
|
|
1374
1398
|
* summary
|
1375
1399
|
"""
|
1376
1400
|
picking = self.env["stock.picking"].browse(picking_id)
|
1377
|
-
message = self.
|
1401
|
+
message = self._check_picking_processible(picking)
|
1378
1402
|
if message:
|
1379
1403
|
return self._response_for_select_document(message=message)
|
1380
1404
|
return self._response_for_summary(picking)
|
@@ -1393,7 +1417,7 @@ class Checkout(Component):
|
|
1393
1417
|
* summary: if the package_id no longer exists
|
1394
1418
|
"""
|
1395
1419
|
picking = self.env["stock.picking"].browse(picking_id)
|
1396
|
-
message = self.
|
1420
|
+
message = self._check_picking_processible(picking)
|
1397
1421
|
if message:
|
1398
1422
|
return self._response_for_select_document(message=message)
|
1399
1423
|
package = self.env["stock.quant.package"].browse(package_id).exists()
|
@@ -1408,7 +1432,7 @@ class Checkout(Component):
|
|
1408
1432
|
* summary
|
1409
1433
|
"""
|
1410
1434
|
picking = self.env["stock.picking"].browse(picking_id)
|
1411
|
-
message = self.
|
1435
|
+
message = self._check_picking_processible(picking)
|
1412
1436
|
if message:
|
1413
1437
|
return self._response_for_select_document(message=message)
|
1414
1438
|
|
@@ -1445,7 +1469,7 @@ class Checkout(Component):
|
|
1445
1469
|
* select_line: when package or line has been canceled
|
1446
1470
|
"""
|
1447
1471
|
picking = self.env["stock.picking"].browse(picking_id)
|
1448
|
-
message = self.
|
1472
|
+
message = self._check_picking_processible(picking)
|
1449
1473
|
if message:
|
1450
1474
|
return self._response_for_select_document(message=message)
|
1451
1475
|
|
@@ -1490,7 +1514,7 @@ class Checkout(Component):
|
|
1490
1514
|
* select_child_location: there are child destination locations
|
1491
1515
|
"""
|
1492
1516
|
picking = self.env["stock.picking"].browse(picking_id)
|
1493
|
-
message = self.
|
1517
|
+
message = self._check_picking_processible(picking)
|
1494
1518
|
if message:
|
1495
1519
|
return self._response_for_select_document(message=message)
|
1496
1520
|
lines = picking.move_line_ids
|
@@ -1533,7 +1557,7 @@ class Checkout(Component):
|
|
1533
1557
|
* select_child_location: in case of error
|
1534
1558
|
"""
|
1535
1559
|
picking = self.env["stock.picking"].browse(picking_id)
|
1536
|
-
message = self.
|
1560
|
+
message = self._check_picking_processible(picking)
|
1537
1561
|
if message:
|
1538
1562
|
return self._response_for_select_document(message=message)
|
1539
1563
|
search = self._actions_for("search")
|