odoo-addon-shopfloor 16.0.2.7.0.1__py3-none-any.whl → 16.0.2.8.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/change_package_lot.py +3 -1
- odoo/addons/shopfloor/actions/data.py +2 -1
- odoo/addons/shopfloor/actions/data_detail.py +2 -2
- odoo/addons/shopfloor/actions/location_content_transfer_sorter.py +0 -1
- odoo/addons/shopfloor/actions/message.py +12 -6
- odoo/addons/shopfloor/actions/move_line_search.py +3 -1
- odoo/addons/shopfloor/actions/savepoint.py +1 -1
- odoo/addons/shopfloor/actions/schema.py +0 -1
- odoo/addons/shopfloor/actions/search.py +2 -2
- odoo/addons/shopfloor/actions/stock.py +1 -1
- odoo/addons/shopfloor/demo/shopfloor_app_demo.xml +7 -7
- odoo/addons/shopfloor/i18n/it.po +8 -6
- odoo/addons/shopfloor/i18n/shopfloor.pot +8 -8
- odoo/addons/shopfloor/migrations/16.0.2.0.0/post-migration.py +1 -3
- odoo/addons/shopfloor/models/shopfloor_menu.py +5 -3
- odoo/addons/shopfloor/models/stock_picking.py +2 -1
- odoo/addons/shopfloor/services/checkout.py +16 -16
- odoo/addons/shopfloor/services/cluster_picking.py +10 -10
- odoo/addons/shopfloor/services/delivery.py +3 -3
- odoo/addons/shopfloor/services/service.py +0 -1
- odoo/addons/shopfloor/services/single_pack_transfer.py +0 -1
- odoo/addons/shopfloor/services/zone_picking.py +16 -13
- odoo/addons/shopfloor/static/description/index.html +1 -1
- odoo/addons/shopfloor/tests/common.py +0 -1
- odoo/addons/shopfloor/tests/models.py +1 -0
- odoo/addons/shopfloor/tests/test_actions_change_package_lot.py +6 -10
- odoo/addons/shopfloor/tests/test_actions_data_base.py +4 -4
- odoo/addons/shopfloor/tests/test_checkout_auto_post.py +7 -6
- odoo/addons/shopfloor/tests/test_checkout_base.py +1 -6
- odoo/addons/shopfloor/tests/test_checkout_change_packaging.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_done.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_list_delivery_packaging.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_scan.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_scan_line.py +4 -4
- odoo/addons/shopfloor/tests/test_checkout_scan_line_no_prefill_qty.py +3 -3
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action.py +10 -10
- odoo/addons/shopfloor/tests/test_cluster_picking_is_zero.py +2 -10
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_destination.py +6 -14
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_line_location_or_pack_first.py +1 -2
- odoo/addons/shopfloor/tests/test_cluster_picking_stock_issue.py +3 -3
- odoo/addons/shopfloor/tests/test_cluster_picking_unload.py +3 -3
- odoo/addons/shopfloor/tests/test_delivery_scan_deliver.py +1 -1
- odoo/addons/shopfloor/tests/test_location_content_transfer_get_work.py +5 -2
- odoo/addons/shopfloor/tests/test_location_content_transfer_mix.py +12 -11
- odoo/addons/shopfloor/tests/test_menu_contrains.py +0 -1
- odoo/addons/shopfloor/tests/test_single_pack_transfer.py +9 -9
- odoo/addons/shopfloor/tests/test_stock_split.py +1 -1
- odoo/addons/shopfloor/tests/test_zone_picking_base.py +11 -10
- odoo/addons/shopfloor/tests/test_zone_picking_complete_mix_pack_flux.py +2 -2
- odoo/addons/shopfloor/tests/test_zone_picking_require_destination_package.py +1 -1
- odoo/addons/shopfloor/tests/test_zone_picking_select_line.py +15 -15
- odoo/addons/shopfloor/tests/test_zone_picking_select_line_no_prefill_qty.py +2 -2
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination.py +9 -9
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_no_prefill_qty.py +1 -1
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_package_not_allowed.py +2 -2
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_pick_pack.py +2 -2
- odoo/addons/shopfloor/tests/test_zone_picking_unload_all.py +3 -1
- odoo/addons/shopfloor/tests/test_zone_picking_unload_set_destination.py +2 -2
- odoo/addons/shopfloor/views/shopfloor_menu.xml +96 -89
- {odoo_addon_shopfloor-16.0.2.7.0.1.dist-info → odoo_addon_shopfloor-16.0.2.8.0.dist-info}/METADATA +2 -2
- {odoo_addon_shopfloor-16.0.2.7.0.1.dist-info → odoo_addon_shopfloor-16.0.2.8.0.dist-info}/RECORD +65 -65
- {odoo_addon_shopfloor-16.0.2.7.0.1.dist-info → odoo_addon_shopfloor-16.0.2.8.0.dist-info}/WHEEL +0 -0
- {odoo_addon_shopfloor-16.0.2.7.0.1.dist-info → odoo_addon_shopfloor-16.0.2.8.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:8f4a1f9cca9cb3a4830c65a6a9d8a65ec3334a34722525fe5da87e77b0e90de2
|
11
11
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
12
12
|
|
13
13
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
@@ -171,5 +171,7 @@ class ChangePackageLot(Component):
|
|
171
171
|
restricts the reservation based on the previous move(s).
|
172
172
|
"""
|
173
173
|
return move_lines.filtered(
|
174
|
-
lambda
|
174
|
+
lambda x, lot=lot: (
|
175
|
+
x.product_id == lot.product_id and not x.move_id.move_orig_ids
|
176
|
+
)
|
175
177
|
)
|
@@ -351,7 +351,8 @@ class DataAction(Component):
|
|
351
351
|
|
352
352
|
def _get_operation_progress(self, domain):
|
353
353
|
lines = self.env["stock.move.line"].search(domain)
|
354
|
-
# operations_to_do = number of total operations
|
354
|
+
# operations_to_do = number of total operations
|
355
|
+
# that are pending for this location.
|
355
356
|
# operations_done = number of operations already done.
|
356
357
|
operations_to_do = 0
|
357
358
|
operations_done = 0
|
@@ -212,7 +212,7 @@ class DataDetailAction(Component):
|
|
212
212
|
def _product_image_url(self, record, field_name):
|
213
213
|
if not record[field_name]:
|
214
214
|
return None
|
215
|
-
return "/web/image/product.product/{}/{}"
|
215
|
+
return f"/web/image/product.product/{record.id}/{field_name}"
|
216
216
|
|
217
217
|
@property
|
218
218
|
def _product_supplierinfo_parser(self):
|
@@ -228,7 +228,7 @@ class DataDetailAction(Component):
|
|
228
228
|
return self._jsonify(
|
229
229
|
record.with_context(packaging=record.id),
|
230
230
|
self._packaging_detail_parser,
|
231
|
-
**kw
|
231
|
+
**kw,
|
232
232
|
)
|
233
233
|
|
234
234
|
@property
|
@@ -123,7 +123,8 @@ class MessageAction(Component):
|
|
123
123
|
return {
|
124
124
|
"message_type": "warning",
|
125
125
|
"body": _(
|
126
|
-
"Package %(package_name)s
|
126
|
+
"Package %(package_name)s "
|
127
|
+
"is not available in transfer %(picking_name)s.",
|
127
128
|
package_name=package.name,
|
128
129
|
picking_name=picking.name,
|
129
130
|
),
|
@@ -314,7 +315,8 @@ class MessageAction(Component):
|
|
314
315
|
return {
|
315
316
|
"message_type": "warning",
|
316
317
|
"body": _(
|
317
|
-
"Several moves found on different locations,
|
318
|
+
"Several moves found on different locations, "
|
319
|
+
"please scan first the location."
|
318
320
|
),
|
319
321
|
}
|
320
322
|
|
@@ -435,7 +437,8 @@ class MessageAction(Component):
|
|
435
437
|
"message_type": "warning",
|
436
438
|
"body": _(
|
437
439
|
_(
|
438
|
-
"This source document is part of multiple transfers,
|
440
|
+
"This source document is part of multiple transfers, "
|
441
|
+
"please scan a package."
|
439
442
|
)
|
440
443
|
),
|
441
444
|
}
|
@@ -511,8 +514,10 @@ class MessageAction(Component):
|
|
511
514
|
return {
|
512
515
|
"message_type": "warning",
|
513
516
|
"body": _(
|
514
|
-
"
|
515
|
-
|
517
|
+
"%(message_code)s not found in the current transfer "
|
518
|
+
"or already in a package.",
|
519
|
+
message_code=message_code,
|
520
|
+
),
|
516
521
|
}
|
517
522
|
|
518
523
|
def packaging_not_found_in_picking(self):
|
@@ -757,7 +762,8 @@ class MessageAction(Component):
|
|
757
762
|
return {
|
758
763
|
"message_type": "warning",
|
759
764
|
"body": _(
|
760
|
-
"Please note that the scanned quantity
|
765
|
+
"Please note that the scanned quantity "
|
766
|
+
"is higher than the maximum allowed."
|
761
767
|
),
|
762
768
|
}
|
763
769
|
|
@@ -53,7 +53,9 @@ class MoveLineSearch(Component):
|
|
53
53
|
"key": None,
|
54
54
|
"get_sort_key_priority": self._sort_key_move_lines_priority,
|
55
55
|
"get_sort_key_location": self._sort_key_move_lines_location,
|
56
|
-
"get_sort_key_assigned_to_current_user":
|
56
|
+
"get_sort_key_assigned_to_current_user": (
|
57
|
+
self._sort_key_assigned_to_current_user
|
58
|
+
),
|
57
59
|
}
|
58
60
|
|
59
61
|
def _search_move_lines_domain(
|
@@ -8,7 +8,6 @@ from odoo.addons.component.core import Component
|
|
8
8
|
|
9
9
|
|
10
10
|
class SearchResult:
|
11
|
-
|
12
11
|
__slots__ = ("record", "type", "code")
|
13
12
|
|
14
13
|
def __init__(self, **kw) -> None:
|
@@ -31,7 +30,8 @@ class SearchResult:
|
|
31
30
|
|
32
31
|
@property
|
33
32
|
def records(self):
|
34
|
-
|
33
|
+
# In some cases we expect more than one records
|
34
|
+
# (eg: location limit > 1) or lots
|
35
35
|
return self.record if len(self.record) > 1 else None
|
36
36
|
|
37
37
|
|
@@ -150,7 +150,7 @@ class StockAction(Component):
|
|
150
150
|
pickings = move_lines.picking_id
|
151
151
|
for picking in pickings:
|
152
152
|
lines_still_assigned = picking.move_line_ids.filtered(
|
153
|
-
lambda
|
153
|
+
lambda x: x.shopfloor_user_id
|
154
154
|
)
|
155
155
|
if lines_still_assigned:
|
156
156
|
# Because there is other lines in the picking still assigned
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<odoo noupdate="1">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
<record id="app_demo" model="shopfloor.app">
|
3
|
+
<field name="name">Shopfloor WMS (demo)</field>
|
4
|
+
<field name="short_name">WMS (demo)</field>
|
5
|
+
<field name="tech_name">wms_demo</field>
|
6
|
+
<field name="category">wms</field>
|
7
|
+
<field
|
8
8
|
name="profile_ids"
|
9
9
|
eval="[(4, ref('shopfloor.profile_demo_1')), (4, ref('shopfloor.profile_demo_2'))]"
|
10
10
|
/>
|
11
|
-
|
11
|
+
</record>
|
12
12
|
</odoo>
|
odoo/addons/shopfloor/i18n/it.po
CHANGED
@@ -6,7 +6,7 @@ msgid ""
|
|
6
6
|
msgstr ""
|
7
7
|
"Project-Id-Version: Odoo Server 14.0\n"
|
8
8
|
"Report-Msgid-Bugs-To: \n"
|
9
|
-
"PO-Revision-Date: 2025-
|
9
|
+
"PO-Revision-Date: 2025-05-03 14:48+0000\n"
|
10
10
|
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
|
11
11
|
"Language-Team: none\n"
|
12
12
|
"Language: it\n"
|
@@ -14,7 +14,7 @@ msgstr ""
|
|
14
14
|
"Content-Type: text/plain; charset=UTF-8\n"
|
15
15
|
"Content-Transfer-Encoding: \n"
|
16
16
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
17
|
-
"X-Generator: Weblate 5.
|
17
|
+
"X-Generator: Weblate 5.10.4\n"
|
18
18
|
|
19
19
|
#. module: shopfloor
|
20
20
|
#: model:ir.model.fields,help:shopfloor.field_shopfloor_menu__pick_pack_same_time
|
@@ -934,14 +934,14 @@ msgstr "Nessuna quantità elaborata, impossibile completare il trasferimento."
|
|
934
934
|
#: code:addons/shopfloor/actions/message.py:0
|
935
935
|
#, python-format
|
936
936
|
msgid "No transfer found for %(model_name)s %(record_name)s"
|
937
|
-
msgstr ""
|
937
|
+
msgstr "Nessun trasferimento trovato per %(model_name)s %(record_name)s"
|
938
938
|
|
939
939
|
#. module: shopfloor
|
940
940
|
#. odoo-python
|
941
941
|
#: code:addons/shopfloor/actions/message.py:0
|
942
942
|
#, python-format
|
943
943
|
msgid "No transfer found for barcode %s"
|
944
|
-
msgstr ""
|
944
|
+
msgstr "Nessun trasferimento trovato per il codice a barre %s"
|
945
945
|
|
946
946
|
#. module: shopfloor
|
947
947
|
#. odoo-python
|
@@ -1334,7 +1334,7 @@ msgstr ""
|
|
1334
1334
|
#: code:addons/shopfloor/actions/message.py:0
|
1335
1335
|
#, python-format
|
1336
1336
|
msgid "Product %s is not in the current transfer."
|
1337
|
-
msgstr ""
|
1337
|
+
msgstr "Il prodotto %s non è nel trasferimento attuale."
|
1338
1338
|
|
1339
1339
|
#. module: shopfloor
|
1340
1340
|
#: model:ir.model,name:shopfloor.model_stock_move_line
|
@@ -1415,7 +1415,7 @@ msgstr "Riga movimento prenotata"
|
|
1415
1415
|
#: code:addons/shopfloor/actions/message.py:0
|
1416
1416
|
#, python-format
|
1417
1417
|
msgid "Reserved for %(picking_type)s %(picking_name)s"
|
1418
|
-
msgstr ""
|
1418
|
+
msgstr "Prenotato per %(picking_type)s %(picking_name)s"
|
1419
1419
|
|
1420
1420
|
#. module: shopfloor
|
1421
1421
|
#. odoo-python
|
@@ -2060,6 +2060,8 @@ msgstr "Trasferimento"
|
|
2060
2060
|
msgid ""
|
2061
2061
|
"Transfer has been canceled. This cannot be processed using this scenario"
|
2062
2062
|
msgstr ""
|
2063
|
+
"Il trasferimento è stato annullato. Non può essere elaborato usando questo "
|
2064
|
+
"scenario"
|
2063
2065
|
|
2064
2066
|
#. module: shopfloor
|
2065
2067
|
#. odoo-python
|
@@ -85,6 +85,14 @@ msgid ""
|
|
85
85
|
"Incompatible with: \"Pick and pack at the same time\"\n"
|
86
86
|
msgstr ""
|
87
87
|
|
88
|
+
#. module: shopfloor
|
89
|
+
#. odoo-python
|
90
|
+
#: code:addons/shopfloor/actions/message.py:0
|
91
|
+
#, python-format
|
92
|
+
msgid ""
|
93
|
+
"%(message_code)s not found in the current transfer or already in a package."
|
94
|
+
msgstr ""
|
95
|
+
|
88
96
|
#. module: shopfloor
|
89
97
|
#. odoo-python
|
90
98
|
#: code:addons/shopfloor/actions/message.py:0
|
@@ -2168,14 +2176,6 @@ msgstr ""
|
|
2168
2176
|
msgid "Zone Picking"
|
2169
2177
|
msgstr ""
|
2170
2178
|
|
2171
|
-
#. module: shopfloor
|
2172
|
-
#. odoo-python
|
2173
|
-
#: code:addons/shopfloor/actions/message.py:0
|
2174
|
-
#, python-format
|
2175
|
-
msgid ""
|
2176
|
-
"{message_code} not found in the current transfer or already in a package."
|
2177
|
-
msgstr ""
|
2178
|
-
|
2179
2179
|
#. module: shopfloor
|
2180
2180
|
#. odoo-python
|
2181
2181
|
#: code:addons/shopfloor/actions/message.py:0
|
@@ -37,7 +37,5 @@ def _enable_option_in_menus(menus):
|
|
37
37
|
for menu in menus:
|
38
38
|
menu.allow_alternative_destination_package = True
|
39
39
|
_logger.info(
|
40
|
-
"Option allow_alternative_destination_package enabled for menu {}"
|
41
|
-
menu.name
|
42
|
-
)
|
40
|
+
f"Option allow_alternative_destination_package enabled for menu {menu.name}"
|
43
41
|
)
|
@@ -253,7 +253,8 @@ class ShopfloorMenu(models.Model):
|
|
253
253
|
string="Destination package required",
|
254
254
|
default=True,
|
255
255
|
help="If set, the user will have to scan only the source location "
|
256
|
-
"and the destination location to process a line.
|
256
|
+
"and the destination location to process a line. "
|
257
|
+
"The unload step will be skipped.",
|
257
258
|
)
|
258
259
|
|
259
260
|
require_destination_package_is_possible = fields.Boolean(
|
@@ -548,7 +549,8 @@ class ShopfloorMenu(models.Model):
|
|
548
549
|
):
|
549
550
|
raise exceptions.ValidationError(
|
550
551
|
_(
|
551
|
-
"Custom sort key code is required
|
552
|
+
"Custom sort key code is required "
|
553
|
+
"when 'Custom code' is selected."
|
552
554
|
)
|
553
555
|
)
|
554
556
|
if (
|
@@ -557,7 +559,7 @@ class ShopfloorMenu(models.Model):
|
|
557
559
|
):
|
558
560
|
raise exceptions.ValidationError(
|
559
561
|
_(
|
560
|
-
"Custom sort key code is only allowed when 'Custom code' is selected."
|
562
|
+
"Custom sort key code is only allowed when 'Custom code' is selected." # noqa
|
561
563
|
)
|
562
564
|
)
|
563
565
|
code = (
|
@@ -20,7 +20,8 @@ class StockPicking(models.Model):
|
|
20
20
|
)
|
21
21
|
bulk_line_count = fields.Integer(
|
22
22
|
compute="_compute_picking_info",
|
23
|
-
help="Technical field.
|
23
|
+
help="Technical field. "
|
24
|
+
"Indicates number of move lines without package included.",
|
24
25
|
)
|
25
26
|
|
26
27
|
@api.depends(
|
@@ -366,7 +366,7 @@ class Checkout(Component):
|
|
366
366
|
return picking.move_line_ids.filtered(self._filter_lines_unpacked)
|
367
367
|
|
368
368
|
def _lines_prepare(self, picking, selected_lines):
|
369
|
-
"""Hook to manipulate lines' ordering or anything else
|
369
|
+
"""Hook to manipulate lines' ordering or anything else."""
|
370
370
|
return selected_lines
|
371
371
|
|
372
372
|
def _domain_for_list_stock_picking(self):
|
@@ -439,7 +439,7 @@ class Checkout(Component):
|
|
439
439
|
return lines
|
440
440
|
|
441
441
|
def _deselect_lines(self, lines):
|
442
|
-
lines.filtered(lambda
|
442
|
+
lines.filtered(lambda x: not x.shopfloor_checkout_done).write(
|
443
443
|
{"qty_done": 0, "shopfloor_user_id": False}
|
444
444
|
)
|
445
445
|
|
@@ -517,7 +517,7 @@ class Checkout(Component):
|
|
517
517
|
self, picking, selection_lines, package, prefill_qty=0, **kw
|
518
518
|
):
|
519
519
|
lines = selection_lines.filtered(
|
520
|
-
lambda
|
520
|
+
lambda x: x.package_id == package and not x.shopfloor_checkout_done
|
521
521
|
)
|
522
522
|
if not lines:
|
523
523
|
# No line for scanned package in selected picking
|
@@ -542,7 +542,7 @@ class Checkout(Component):
|
|
542
542
|
picking, message=self.msg_store.scan_lot_on_product_tracked_by_lot()
|
543
543
|
)
|
544
544
|
|
545
|
-
lines = selection_lines.filtered(lambda
|
545
|
+
lines = selection_lines.filtered(lambda x: x.product_id == product)
|
546
546
|
if not lines:
|
547
547
|
return_picking = self._get_pickings_for_product(product, limit=1)
|
548
548
|
if return_picking:
|
@@ -580,7 +580,7 @@ class Checkout(Component):
|
|
580
580
|
# not in a package. But only the quantity on first selected lines
|
581
581
|
# are updated.
|
582
582
|
related_lines = selection_lines.filtered(
|
583
|
-
lambda
|
583
|
+
lambda x: not x.package_id and x.product_id != product
|
584
584
|
)
|
585
585
|
|
586
586
|
lines = self._select_lines(
|
@@ -630,7 +630,7 @@ class Checkout(Component):
|
|
630
630
|
# Change lot confirmed
|
631
631
|
line = fields.first(
|
632
632
|
selection_lines.filtered(
|
633
|
-
lambda
|
633
|
+
lambda x: x.product_id == lot.product_id and x.lot_id != lot
|
634
634
|
)
|
635
635
|
)
|
636
636
|
if not line:
|
@@ -689,7 +689,7 @@ class Checkout(Component):
|
|
689
689
|
|
690
690
|
def _picking_lines_by_lot(self, picking, selection_lines, lot):
|
691
691
|
"""Control filtering of selected lines by given lot."""
|
692
|
-
return selection_lines.filtered(lambda
|
692
|
+
return selection_lines.filtered(lambda x: x.lot_id == lot)
|
693
693
|
|
694
694
|
def _change_lot_response_handler_ok(self, move_line, message=None):
|
695
695
|
return message
|
@@ -698,7 +698,7 @@ class Checkout(Component):
|
|
698
698
|
return message
|
699
699
|
|
700
700
|
def _select_lines_from_serial(self, picking, selection_lines, lot, **kw):
|
701
|
-
# Search for serial number is
|
701
|
+
# Search for serial number is the same as searching for lot (as of v14)
|
702
702
|
return self._select_lines_from_lot(picking, selection_lines, lot, **kw)
|
703
703
|
|
704
704
|
# Handling of the destination package scanned
|
@@ -775,7 +775,7 @@ class Checkout(Component):
|
|
775
775
|
)
|
776
776
|
|
777
777
|
related_lines = selection_lines.filtered(
|
778
|
-
lambda
|
778
|
+
lambda x: not x.package_id and x.product_id != move_line.product_id
|
779
779
|
)
|
780
780
|
lines = self._select_lines(move_line, related_lines=related_lines)
|
781
781
|
return self._response_for_select_package(picking, lines)
|
@@ -884,7 +884,7 @@ class Checkout(Component):
|
|
884
884
|
as selected
|
885
885
|
"""
|
886
886
|
return self._change_line_qty(
|
887
|
-
picking_id, selected_line_ids, [move_line_id], lambda
|
887
|
+
picking_id, selected_line_ids, [move_line_id], lambda x: x.reserved_uom_qty
|
888
888
|
)
|
889
889
|
|
890
890
|
def set_custom_qty(self, picking_id, selected_line_ids, move_line_id, qty_done):
|
@@ -917,7 +917,7 @@ class Checkout(Component):
|
|
917
917
|
picking.id,
|
918
918
|
selected_lines.ids,
|
919
919
|
switch_lines.ids,
|
920
|
-
lambda
|
920
|
+
lambda x: x.reserved_uom_qty,
|
921
921
|
)
|
922
922
|
|
923
923
|
def _increment_custom_qty(
|
@@ -1117,7 +1117,7 @@ class Checkout(Component):
|
|
1117
1117
|
selected_lines,
|
1118
1118
|
message=self.msg_store.scan_lot_on_product_tracked_by_lot(),
|
1119
1119
|
)
|
1120
|
-
product_lines = selected_lines.filtered(lambda
|
1120
|
+
product_lines = selected_lines.filtered(lambda x: x.product_id == product)
|
1121
1121
|
if self.work.menu.no_prefill_qty:
|
1122
1122
|
quantity_increment = packaging.qty if packaging else 1
|
1123
1123
|
return self._increment_custom_qty(
|
@@ -1136,7 +1136,7 @@ class Checkout(Component):
|
|
1136
1136
|
)
|
1137
1137
|
|
1138
1138
|
def _scan_package_action_from_lot(self, picking, selected_lines, lot, **kw):
|
1139
|
-
lot_lines = selected_lines.filtered(lambda
|
1139
|
+
lot_lines = selected_lines.filtered(lambda x: x.lot_id == lot)
|
1140
1140
|
if self.work.menu.no_prefill_qty:
|
1141
1141
|
return self._increment_custom_qty(
|
1142
1142
|
picking, selected_lines, self._find_line_to_increment(lot_lines), 1
|
@@ -1144,7 +1144,7 @@ class Checkout(Component):
|
|
1144
1144
|
return self._switch_line_qty_done(picking, selected_lines, lot_lines)
|
1145
1145
|
|
1146
1146
|
def _scan_package_action_from_serial(self, picking, selection_lines, lot, **kw):
|
1147
|
-
# Search
|
1147
|
+
# Search serial number is actually the same as searching for lot (as of v14...)
|
1148
1148
|
return self._scan_package_action_from_lot(picking, selection_lines, lot, **kw)
|
1149
1149
|
|
1150
1150
|
def _scan_package_action_from_package(self, picking, selected_lines, package, **kw):
|
@@ -1482,8 +1482,8 @@ class Checkout(Component):
|
|
1482
1482
|
|
1483
1483
|
if package:
|
1484
1484
|
move_lines = picking.move_line_ids.filtered(
|
1485
|
-
lambda
|
1486
|
-
and
|
1485
|
+
lambda x: self._filter_lines_checkout_done(x)
|
1486
|
+
and x.result_package_id == package
|
1487
1487
|
)
|
1488
1488
|
for move_line in move_lines:
|
1489
1489
|
move_line.write(
|
@@ -364,13 +364,13 @@ class ClusterPicking(Component):
|
|
364
364
|
def _lines_to_pick(self, picking_batch):
|
365
365
|
return self._lines_for_picking_batch(
|
366
366
|
picking_batch,
|
367
|
-
filter_func=lambda
|
368
|
-
|
367
|
+
filter_func=lambda x: (
|
368
|
+
x.state in ("assigned", "partially_available")
|
369
369
|
# On 'StockPicking.action_assign()', result_package_id is set to
|
370
370
|
# the same package as 'package_id'. Here, we need to exclude lines
|
371
371
|
# that were already put into a bin, i.e. the destination package
|
372
372
|
# is different.
|
373
|
-
and (not
|
373
|
+
and (not x.result_package_id or x.result_package_id == x.package_id)
|
374
374
|
),
|
375
375
|
)
|
376
376
|
|
@@ -378,11 +378,11 @@ class ClusterPicking(Component):
|
|
378
378
|
"""Get the last line picked and put in a pack for this picking"""
|
379
379
|
return fields.first(
|
380
380
|
picking.move_line_ids.filtered(
|
381
|
-
lambda
|
382
|
-
and
|
381
|
+
lambda x: x.qty_done > 0
|
382
|
+
and x.result_package_id
|
383
383
|
# if we are moving the entire package, we shouldn't
|
384
384
|
# add stuff inside it, it's not a new package
|
385
|
-
and
|
385
|
+
and x.package_id != x.result_package_id
|
386
386
|
).sorted(key="write_date", reverse=True)
|
387
387
|
)
|
388
388
|
|
@@ -582,7 +582,7 @@ class ClusterPicking(Component):
|
|
582
582
|
def _scan_line_by_packaging(self, picking, move_line, packaging, sublocation):
|
583
583
|
"""Packaging scanned, check if we can work with it.
|
584
584
|
|
585
|
-
If the packaging
|
585
|
+
If the packaging product is part of several packages in the same location,
|
586
586
|
we can't be sure it's the correct one, in such case, ask to scan a package
|
587
587
|
"""
|
588
588
|
response = self._check_first_scan_location_or_pack_first(move_line, sublocation)
|
@@ -595,7 +595,7 @@ class ClusterPicking(Component):
|
|
595
595
|
move_line, message=self.msg_store.scan_lot_on_product_tracked_by_lot()
|
596
596
|
)
|
597
597
|
other_product_lines = picking.move_line_ids.filtered(
|
598
|
-
lambda
|
598
|
+
lambda x: x.product_id == product and x.location_id == move_line.location_id
|
599
599
|
)
|
600
600
|
packages = other_product_lines.mapped("package_id")
|
601
601
|
# Do not use mapped here: we want to see if we have more than one package,
|
@@ -1149,7 +1149,7 @@ class ClusterPicking(Component):
|
|
1149
1149
|
lines.write({"shopfloor_unloaded": True, "location_dest_id": location.id})
|
1150
1150
|
lines.package_level_id.location_dest_id = location
|
1151
1151
|
for picking in lines.batch_id.picking_ids:
|
1152
|
-
picking_lines = lines.filtered(lambda
|
1152
|
+
picking_lines = lines.filtered(lambda x, p=picking: x.picking_id == p)
|
1153
1153
|
self._unload_set_picking_to_done(picking, picking_lines)
|
1154
1154
|
|
1155
1155
|
def _unload_set_picking_to_done(self, picking, picking_lines):
|
@@ -1274,7 +1274,7 @@ class ClusterPicking(Component):
|
|
1274
1274
|
|
1275
1275
|
# we work only on the lines of the scanned package
|
1276
1276
|
lines = self._lines_to_unload(batch).filtered(
|
1277
|
-
lambda
|
1277
|
+
lambda x: x.result_package_id == package
|
1278
1278
|
)
|
1279
1279
|
if not lines:
|
1280
1280
|
return self._unload_end(batch)
|
@@ -233,7 +233,7 @@ class Delivery(Component):
|
|
233
233
|
|
234
234
|
def _deliver_package(self, picking, package, location):
|
235
235
|
lines = package.move_line_ids.filtered(
|
236
|
-
lambda
|
236
|
+
lambda x: x.state in ("assigned", "partially_available")
|
237
237
|
)
|
238
238
|
if not lines:
|
239
239
|
return self._response_for_deliver(
|
@@ -372,7 +372,7 @@ class Delivery(Component):
|
|
372
372
|
if message:
|
373
373
|
return self._response_for_deliver(location=location, message=message)
|
374
374
|
lines = lines.filtered(
|
375
|
-
lambda
|
375
|
+
lambda x: x.move_id.picking_type_id in self.picking_types
|
376
376
|
)
|
377
377
|
# State of the picking might change while we reach this point: check again!
|
378
378
|
message = self._check_picking_status(lines.mapped("picking_id"))
|
@@ -421,7 +421,7 @@ class Delivery(Component):
|
|
421
421
|
)
|
422
422
|
# We focus only on lines on which we can increase the 'qty_done'
|
423
423
|
lines = lines.filtered(
|
424
|
-
lambda
|
424
|
+
lambda x: (x.qty_done + product_qty) <= x.reserved_uom_qty
|
425
425
|
)
|
426
426
|
# Filter lines to keep only ones from one delivery operation
|
427
427
|
# (we do not want to process lines of another delivery operation)
|
@@ -126,7 +126,6 @@ class SinglePackTransfer(Component):
|
|
126
126
|
message=self.msg_store.package_already_picked_by(package, picking)
|
127
127
|
)
|
128
128
|
elif other_move_lines and self.work.menu.allow_unreserve_other_moves:
|
129
|
-
|
130
129
|
unreserved_moves = other_move_lines.move_id
|
131
130
|
other_package_levels = other_move_lines.package_level_id
|
132
131
|
other_package_levels.explode_package()
|
@@ -238,9 +238,11 @@ class ZonePicking(Component):
|
|
238
238
|
data = self._data_for_move_line(move_line)
|
239
239
|
data["move_line"].update(kw)
|
240
240
|
data["confirmation_required"] = confirmation_required
|
241
|
-
|
242
|
-
|
243
|
-
|
241
|
+
# fmt: off
|
242
|
+
data["allow_alternative_destination_package"] = (
|
243
|
+
self.work.menu.allow_alternative_destination_package
|
244
|
+
)
|
245
|
+
# fmt: on
|
244
246
|
data["handle_complete_mix_pack"] = self._handle_complete_mix_pack(
|
245
247
|
move_line.package_id
|
246
248
|
)
|
@@ -368,13 +370,15 @@ class ZonePicking(Component):
|
|
368
370
|
data_move_line["handle_complete_mix_pack"] = handle_complete_mix_pack
|
369
371
|
# `location_will_be_empty` flag states if, by processing this move line
|
370
372
|
# and picking the product, the location will be emptied.
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
373
|
+
# fmt: off
|
374
|
+
data_move_line["location_will_be_empty"] = (
|
375
|
+
move_line.location_id.planned_qty_in_location_is_empty(
|
376
|
+
move_line.package_id.move_line_ids
|
377
|
+
if handle_complete_mix_pack
|
378
|
+
else move_line
|
379
|
+
)
|
377
380
|
)
|
381
|
+
# fmt: on
|
378
382
|
return data
|
379
383
|
|
380
384
|
def _data_for_location(self, location, zone_location=None, picking_type=None):
|
@@ -1140,8 +1144,8 @@ class ZonePicking(Component):
|
|
1140
1144
|
When the barcode is the product (or its packaging) or the lot on the line:
|
1141
1145
|
* The done quantity is incremented by one or the packaging quantity.
|
1142
1146
|
|
1143
|
-
The `handle_complete_mix_pack` option, when it is set to true
|
1144
|
-
lines contained in the package of the move line
|
1147
|
+
The `handle_complete_mix_pack` option, when it is set to true,
|
1148
|
+
will move all lines contained in the package of the move line given.
|
1145
1149
|
|
1146
1150
|
Transitions:
|
1147
1151
|
* select_line: destination has been set, showing the next lines to pick
|
@@ -1214,7 +1218,6 @@ class ZonePicking(Component):
|
|
1214
1218
|
# When the barcode is a package
|
1215
1219
|
package = search.package_from_scan(barcode)
|
1216
1220
|
if package:
|
1217
|
-
|
1218
1221
|
if not moving_full_quantity and move_line.package_id == package:
|
1219
1222
|
# Check we're not using the source package as transfer package.
|
1220
1223
|
message = self.msg_store.dest_package_not_valid(package)
|
@@ -1230,7 +1233,7 @@ class ZonePicking(Component):
|
|
1230
1233
|
and move_line.result_package_id
|
1231
1234
|
and move_line.result_package_id != package
|
1232
1235
|
):
|
1233
|
-
# Check whether the user can move a whole package to a different
|
1236
|
+
# Check whether the user can move a whole package to a different one.
|
1234
1237
|
message = self.msg_store.package_transfer_not_allowed_scan_location()
|
1235
1238
|
return self._response_for_set_line_destination(
|
1236
1239
|
move_line, message=message, qty_done=quantity
|