odoo-addon-shopfloor 16.0.1.0.0.24__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 +160 -0
- odoo/addons/shopfloor/__init__.py +4 -0
- odoo/addons/shopfloor/__manifest__.py +65 -0
- odoo/addons/shopfloor/actions/__init__.py +15 -0
- odoo/addons/shopfloor/actions/change_package_lot.py +164 -0
- odoo/addons/shopfloor/actions/completion_info.py +42 -0
- odoo/addons/shopfloor/actions/data.py +329 -0
- odoo/addons/shopfloor/actions/data_detail.py +154 -0
- odoo/addons/shopfloor/actions/inventory.py +150 -0
- odoo/addons/shopfloor/actions/location_content_transfer_sorter.py +89 -0
- odoo/addons/shopfloor/actions/message.py +846 -0
- odoo/addons/shopfloor/actions/move_line_search.py +119 -0
- odoo/addons/shopfloor/actions/packaging.py +59 -0
- odoo/addons/shopfloor/actions/savepoint.py +44 -0
- odoo/addons/shopfloor/actions/schema.py +182 -0
- odoo/addons/shopfloor/actions/schema_detail.py +98 -0
- odoo/addons/shopfloor/actions/search.py +187 -0
- odoo/addons/shopfloor/actions/stock.py +239 -0
- odoo/addons/shopfloor/actions/stock_unreserve.py +66 -0
- odoo/addons/shopfloor/components/__init__.py +5 -0
- odoo/addons/shopfloor/components/scan_handler_location.py +26 -0
- odoo/addons/shopfloor/components/scan_handler_lot.py +26 -0
- odoo/addons/shopfloor/components/scan_handler_package.py +26 -0
- odoo/addons/shopfloor/components/scan_handler_product.py +26 -0
- odoo/addons/shopfloor/components/scan_handler_transfer.py +26 -0
- odoo/addons/shopfloor/data/shopfloor_scenario_data.xml +73 -0
- odoo/addons/shopfloor/demo/shopfloor_app_demo.xml +12 -0
- odoo/addons/shopfloor/demo/shopfloor_menu_demo.xml +64 -0
- odoo/addons/shopfloor/demo/shopfloor_profile_demo.xml +8 -0
- odoo/addons/shopfloor/demo/stock_picking_type_demo.xml +93 -0
- odoo/addons/shopfloor/docs/checkout_diag_seq.plantuml +61 -0
- odoo/addons/shopfloor/docs/checkout_diag_seq.png +0 -0
- odoo/addons/shopfloor/docs/cluster_picking_diag_seq.plantuml +112 -0
- odoo/addons/shopfloor/docs/cluster_picking_diag_seq.png +0 -0
- odoo/addons/shopfloor/docs/delivery_diag_seq.plantuml +56 -0
- odoo/addons/shopfloor/docs/delivery_diag_seq.png +0 -0
- odoo/addons/shopfloor/docs/location_content_transfer_diag_seq.plantuml +66 -0
- odoo/addons/shopfloor/docs/location_content_transfer_diag_seq.png +0 -0
- odoo/addons/shopfloor/docs/oca_logo.png +0 -0
- odoo/addons/shopfloor/docs/single_pack_transfer_diag_seq.plantuml +36 -0
- odoo/addons/shopfloor/docs/single_pack_transfer_diag_seq.png +0 -0
- odoo/addons/shopfloor/docs/zone_picking_diag_seq.plantuml +85 -0
- odoo/addons/shopfloor/docs/zone_picking_diag_seq.png +0 -0
- odoo/addons/shopfloor/exceptions.py +6 -0
- odoo/addons/shopfloor/i18n/ca.po +1802 -0
- odoo/addons/shopfloor/i18n/de.po +1791 -0
- odoo/addons/shopfloor/i18n/es_AR.po +2147 -0
- odoo/addons/shopfloor/i18n/pt_BR.po +1791 -0
- odoo/addons/shopfloor/i18n/shopfloor.pot +1877 -0
- odoo/addons/shopfloor/models/__init__.py +12 -0
- odoo/addons/shopfloor/models/priority_postpone_mixin.py +41 -0
- odoo/addons/shopfloor/models/shopfloor_app.py +9 -0
- odoo/addons/shopfloor/models/shopfloor_menu.py +436 -0
- odoo/addons/shopfloor/models/stock_location.py +76 -0
- odoo/addons/shopfloor/models/stock_move.py +119 -0
- odoo/addons/shopfloor/models/stock_move_line.py +307 -0
- odoo/addons/shopfloor/models/stock_package_level.py +50 -0
- odoo/addons/shopfloor/models/stock_picking.py +118 -0
- odoo/addons/shopfloor/models/stock_picking_batch.py +41 -0
- odoo/addons/shopfloor/models/stock_picking_type.py +26 -0
- odoo/addons/shopfloor/models/stock_quant.py +31 -0
- odoo/addons/shopfloor/models/stock_quant_package.py +101 -0
- odoo/addons/shopfloor/readme/CONTRIBUTORS.rst +18 -0
- odoo/addons/shopfloor/readme/CREDITS.rst +5 -0
- odoo/addons/shopfloor/readme/DESCRIPTION.rst +17 -0
- odoo/addons/shopfloor/readme/HISTORY.rst +4 -0
- odoo/addons/shopfloor/readme/ROADMAP.rst +4 -0
- odoo/addons/shopfloor/readme/USAGE.rst +6 -0
- odoo/addons/shopfloor/security/groups.xml +17 -0
- odoo/addons/shopfloor/services/__init__.py +16 -0
- odoo/addons/shopfloor/services/checkout.py +1763 -0
- odoo/addons/shopfloor/services/cluster_picking.py +1628 -0
- odoo/addons/shopfloor/services/delivery.py +828 -0
- odoo/addons/shopfloor/services/forms/__init__.py +1 -0
- odoo/addons/shopfloor/services/forms/picking_form.py +78 -0
- odoo/addons/shopfloor/services/location_content_transfer.py +1194 -0
- odoo/addons/shopfloor/services/menu.py +60 -0
- odoo/addons/shopfloor/services/picking_batch.py +126 -0
- odoo/addons/shopfloor/services/service.py +101 -0
- odoo/addons/shopfloor/services/single_pack_transfer.py +366 -0
- odoo/addons/shopfloor/services/zone_picking.py +1938 -0
- odoo/addons/shopfloor/static/description/icon.png +0 -0
- odoo/addons/shopfloor/static/description/index.html +500 -0
- odoo/addons/shopfloor/tests/__init__.py +83 -0
- odoo/addons/shopfloor/tests/common.py +324 -0
- odoo/addons/shopfloor/tests/models.py +29 -0
- odoo/addons/shopfloor/tests/test_actions_change_package_lot.py +1175 -0
- odoo/addons/shopfloor/tests/test_actions_data.py +376 -0
- odoo/addons/shopfloor/tests/test_actions_data_base.py +244 -0
- odoo/addons/shopfloor/tests/test_actions_data_detail.py +322 -0
- odoo/addons/shopfloor/tests/test_actions_search.py +248 -0
- odoo/addons/shopfloor/tests/test_actions_stock.py +48 -0
- odoo/addons/shopfloor/tests/test_checkout_auto_post.py +67 -0
- odoo/addons/shopfloor/tests/test_checkout_base.py +81 -0
- odoo/addons/shopfloor/tests/test_checkout_cancel_line.py +154 -0
- odoo/addons/shopfloor/tests/test_checkout_change_packaging.py +184 -0
- odoo/addons/shopfloor/tests/test_checkout_done.py +133 -0
- odoo/addons/shopfloor/tests/test_checkout_list_delivery_packaging.py +131 -0
- odoo/addons/shopfloor/tests/test_checkout_list_package.py +327 -0
- odoo/addons/shopfloor/tests/test_checkout_new_package.py +88 -0
- odoo/addons/shopfloor/tests/test_checkout_no_package.py +95 -0
- odoo/addons/shopfloor/tests/test_checkout_scan.py +174 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_line.py +377 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_line_base.py +25 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_line_no_prefill_qty.py +91 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action.py +451 -0
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action_no_prefill_qty.py +107 -0
- odoo/addons/shopfloor/tests/test_checkout_select.py +74 -0
- odoo/addons/shopfloor/tests/test_checkout_select_line.py +130 -0
- odoo/addons/shopfloor/tests/test_checkout_select_package_base.py +64 -0
- odoo/addons/shopfloor/tests/test_checkout_set_qty.py +257 -0
- odoo/addons/shopfloor/tests/test_checkout_summary.py +69 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_base.py +83 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_batch.py +109 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_change_pack_lot.py +111 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_is_zero.py +98 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_destination.py +376 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_destination_no_prefill_qty.py +115 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_line.py +402 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_line_location_or_pack_first.py +114 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_scan_line_no_prefill_qty.py +70 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_select.py +387 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_skip.py +90 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_stock_issue.py +364 -0
- odoo/addons/shopfloor/tests/test_cluster_picking_unload.py +911 -0
- odoo/addons/shopfloor/tests/test_delivery_base.py +155 -0
- odoo/addons/shopfloor/tests/test_delivery_done.py +108 -0
- odoo/addons/shopfloor/tests/test_delivery_list_stock_picking.py +49 -0
- odoo/addons/shopfloor/tests/test_delivery_reset_qty_done_line.py +119 -0
- odoo/addons/shopfloor/tests/test_delivery_reset_qty_done_pack.py +107 -0
- odoo/addons/shopfloor/tests/test_delivery_scan_deliver.py +557 -0
- odoo/addons/shopfloor/tests/test_delivery_select.py +38 -0
- odoo/addons/shopfloor/tests/test_delivery_set_qty_done_line.py +91 -0
- odoo/addons/shopfloor/tests/test_delivery_set_qty_done_pack.py +135 -0
- odoo/addons/shopfloor/tests/test_delivery_sublocation.py +180 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_base.py +136 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_get_work.py +125 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_mix.py +509 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_putaway.py +143 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_scan_location.py +34 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_set_destination_all.py +343 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py +1074 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_single.py +748 -0
- odoo/addons/shopfloor/tests/test_location_content_transfer_start.py +359 -0
- odoo/addons/shopfloor/tests/test_menu_base.py +261 -0
- odoo/addons/shopfloor/tests/test_menu_counters.py +61 -0
- odoo/addons/shopfloor/tests/test_misc.py +25 -0
- odoo/addons/shopfloor/tests/test_move_action_assign.py +87 -0
- odoo/addons/shopfloor/tests/test_openapi.py +21 -0
- odoo/addons/shopfloor/tests/test_picking_form.py +62 -0
- odoo/addons/shopfloor/tests/test_scan_anything.py +49 -0
- odoo/addons/shopfloor/tests/test_single_pack_transfer.py +1121 -0
- odoo/addons/shopfloor/tests/test_single_pack_transfer_base.py +32 -0
- odoo/addons/shopfloor/tests/test_single_pack_transfer_putaway.py +104 -0
- odoo/addons/shopfloor/tests/test_stock_split.py +204 -0
- odoo/addons/shopfloor/tests/test_user.py +42 -0
- odoo/addons/shopfloor/tests/test_zone_picking_base.py +608 -0
- odoo/addons/shopfloor/tests/test_zone_picking_change_pack_lot.py +140 -0
- odoo/addons/shopfloor/tests/test_zone_picking_select_line.py +723 -0
- odoo/addons/shopfloor/tests/test_zone_picking_select_line_first_scan_location.py +207 -0
- odoo/addons/shopfloor/tests/test_zone_picking_select_line_first_scan_location.py.bak +202 -0
- odoo/addons/shopfloor/tests/test_zone_picking_select_line_no_prefill_qty.py +107 -0
- odoo/addons/shopfloor/tests/test_zone_picking_select_picking_type.py +26 -0
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination.py +643 -0
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_no_prefill_qty.py +146 -0
- odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_pick_pack.py +241 -0
- odoo/addons/shopfloor/tests/test_zone_picking_start.py +206 -0
- odoo/addons/shopfloor/tests/test_zone_picking_stock_issue.py +121 -0
- odoo/addons/shopfloor/tests/test_zone_picking_unload_all.py +353 -0
- odoo/addons/shopfloor/tests/test_zone_picking_unload_buffer_lines.py +113 -0
- odoo/addons/shopfloor/tests/test_zone_picking_unload_set_destination.py +374 -0
- odoo/addons/shopfloor/tests/test_zone_picking_unload_single.py +123 -0
- odoo/addons/shopfloor/tests/test_zone_picking_zero_check.py +43 -0
- odoo/addons/shopfloor/utils.py +13 -0
- odoo/addons/shopfloor/views/shopfloor_menu.xml +167 -0
- odoo/addons/shopfloor/views/stock_location.xml +20 -0
- odoo/addons/shopfloor/views/stock_move_line.xml +52 -0
- odoo/addons/shopfloor/views/stock_picking_type.xml +19 -0
- odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/METADATA +192 -0
- odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/RECORD +182 -0
- odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/WHEEL +5 -0
- odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/top_level.txt +1 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# Copyright 2022 Camptocamp SA (http://www.camptocamp.com)
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
from .test_zone_picking_base import ZonePickingCommonCase
|
4
|
+
|
5
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
class ZonePickingSetLineDestinationNoPrefillQtyCase(ZonePickingCommonCase):
|
8
|
+
"""Tests for endpoint used from set_line_destination
|
9
|
+
|
10
|
+
With the no prefill quantity option set
|
11
|
+
|
12
|
+
* /set_destination
|
13
|
+
"""
|
14
|
+
|
15
|
+
def setUp(self):
|
16
|
+
super().setUp()
|
17
|
+
self.service.work.current_picking_type = self.picking2.picking_type_id
|
18
|
+
self.menu.sudo().no_prefill_qty = True
|
19
|
+
|
20
|
+
def test_set_destination_increment_with_product(self):
|
21
|
+
"""Check increment quantity by scanning the product."""
|
22
|
+
picking_type = self.picking2.picking_type_id
|
23
|
+
move_line = self.picking2.move_line_ids[0]
|
24
|
+
# Scan twice the product in a row to increment the quantity
|
25
|
+
for qty_done in range(2):
|
26
|
+
response = self.service.dispatch(
|
27
|
+
"set_destination",
|
28
|
+
params={
|
29
|
+
"move_line_id": move_line.id,
|
30
|
+
"barcode": move_line.product_id.barcode,
|
31
|
+
"quantity": qty_done,
|
32
|
+
},
|
33
|
+
)
|
34
|
+
qty_done += 1
|
35
|
+
# Check response
|
36
|
+
self.assert_response_set_line_destination(
|
37
|
+
response,
|
38
|
+
self.zone_location,
|
39
|
+
picking_type,
|
40
|
+
move_line,
|
41
|
+
qty_done=qty_done,
|
42
|
+
)
|
43
|
+
|
44
|
+
def test_set_destination_increment_with_wrong_package(self):
|
45
|
+
"""Check scanning wrong package incremented quantity is not lost."""
|
46
|
+
wrong_package = self.picking1.move_line_ids.package_id
|
47
|
+
picking_type = self.picking2.picking_type_id
|
48
|
+
move_line = self.picking2.move_line_ids[0]
|
49
|
+
# Simulate the product has been scanned twice
|
50
|
+
qty_done = 2
|
51
|
+
response = self.service.dispatch(
|
52
|
+
"set_destination",
|
53
|
+
params={
|
54
|
+
"move_line_id": move_line.id,
|
55
|
+
"barcode": wrong_package.name,
|
56
|
+
"quantity": qty_done,
|
57
|
+
},
|
58
|
+
)
|
59
|
+
# Check response
|
60
|
+
self.assert_response_set_line_destination(
|
61
|
+
response,
|
62
|
+
self.zone_location,
|
63
|
+
picking_type,
|
64
|
+
move_line,
|
65
|
+
qty_done=qty_done,
|
66
|
+
message={
|
67
|
+
"body": "Package {} is not empty.".format(wrong_package.name),
|
68
|
+
"message_type": "warning",
|
69
|
+
},
|
70
|
+
)
|
71
|
+
|
72
|
+
def test_set_destination_increment_with_wrong_product(self):
|
73
|
+
"""Check increment quantity by scanning the wrong product."""
|
74
|
+
picking_type = self.picking2.picking_type_id
|
75
|
+
move_line = self.picking2.move_line_ids[0]
|
76
|
+
# Scan twice the product in a row to increment the quantity
|
77
|
+
qty_done = 2
|
78
|
+
response = self.service.dispatch(
|
79
|
+
"set_destination",
|
80
|
+
params={
|
81
|
+
"move_line_id": move_line.id,
|
82
|
+
"barcode": self.product_a.barcode,
|
83
|
+
"quantity": qty_done,
|
84
|
+
},
|
85
|
+
)
|
86
|
+
# Check response
|
87
|
+
self.assert_response_set_line_destination(
|
88
|
+
response,
|
89
|
+
self.zone_location,
|
90
|
+
picking_type,
|
91
|
+
move_line,
|
92
|
+
qty_done=qty_done,
|
93
|
+
message={"body": "The package A doesn't exist", "message_type": "error"},
|
94
|
+
)
|
95
|
+
|
96
|
+
def test_set_destination_increment_with_lot(self):
|
97
|
+
"""Check increment quantity by scanning the lot."""
|
98
|
+
picking_type = self.picking2.picking_type_id
|
99
|
+
move_line = self.picking2.move_line_ids.filtered("lot_id")[0]
|
100
|
+
# Scan twice the lot in a row to increment the quantity
|
101
|
+
for qty_done in range(2):
|
102
|
+
response = self.service.dispatch(
|
103
|
+
"set_destination",
|
104
|
+
params={
|
105
|
+
"move_line_id": move_line.id,
|
106
|
+
"barcode": move_line.lot_id.name,
|
107
|
+
"quantity": qty_done,
|
108
|
+
},
|
109
|
+
)
|
110
|
+
qty_done += 1
|
111
|
+
# Check response
|
112
|
+
self.assert_response_set_line_destination(
|
113
|
+
response,
|
114
|
+
self.zone_location,
|
115
|
+
picking_type,
|
116
|
+
move_line,
|
117
|
+
qty_done=qty_done,
|
118
|
+
)
|
119
|
+
|
120
|
+
def test_set_destination_location_zero_quantity(self):
|
121
|
+
"""Scanned barcode is the destination location.
|
122
|
+
|
123
|
+
Quantity to move is zero -> error raised, user can try again.
|
124
|
+
|
125
|
+
"""
|
126
|
+
zone_location = self.zone_location
|
127
|
+
picking_type = self.picking1.picking_type_id
|
128
|
+
move_line = self.picking1.move_ids.move_line_ids
|
129
|
+
response = self.service.dispatch(
|
130
|
+
"set_destination",
|
131
|
+
params={
|
132
|
+
"move_line_id": move_line.id,
|
133
|
+
"barcode": self.packing_location.barcode,
|
134
|
+
"quantity": 0,
|
135
|
+
},
|
136
|
+
)
|
137
|
+
# Check response
|
138
|
+
self.assert_response_set_line_destination(
|
139
|
+
response,
|
140
|
+
zone_location,
|
141
|
+
picking_type,
|
142
|
+
move_line,
|
143
|
+
message=self.service.msg_store.picking_zero_quantity(),
|
144
|
+
# And that the quantity done is zero
|
145
|
+
qty_done=0,
|
146
|
+
)
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# Copyright 2021 Camptocamp SA (http://www.camptocamp.com)
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
from odoo_test_helper import FakeModelLoader
|
4
|
+
|
5
|
+
from .test_zone_picking_base import ZonePickingCommonCase
|
6
|
+
|
7
|
+
|
8
|
+
# pylint: disable=missing-return
|
9
|
+
class ZonePickingSetLineDestinationPickPackCase(ZonePickingCommonCase):
|
10
|
+
"""Tests set_line_destination when `pick_pack_same_time` is one
|
11
|
+
|
12
|
+
* /set_destination
|
13
|
+
|
14
|
+
"""
|
15
|
+
|
16
|
+
@classmethod
|
17
|
+
def setUpClass(cls):
|
18
|
+
try:
|
19
|
+
super().setUpClass()
|
20
|
+
except BaseException:
|
21
|
+
# ensure that the registry is restored in case of error in setUpClass
|
22
|
+
# since tearDownClass is not called in this case and our _load_test_models
|
23
|
+
# loads fake models
|
24
|
+
if hasattr(cls, "loader"):
|
25
|
+
cls.loader.restore_registry()
|
26
|
+
raise
|
27
|
+
|
28
|
+
@classmethod
|
29
|
+
def _load_test_models(cls):
|
30
|
+
cls.loader = FakeModelLoader(cls.env, cls.__module__)
|
31
|
+
cls.loader.backup_registry()
|
32
|
+
from .models import DeliveryCarrierTest, StockPackageType
|
33
|
+
|
34
|
+
cls.loader.update_registry((DeliveryCarrierTest, StockPackageType))
|
35
|
+
|
36
|
+
@classmethod
|
37
|
+
def tearDownClass(cls):
|
38
|
+
cls.loader.restore_registry()
|
39
|
+
super().tearDownClass()
|
40
|
+
|
41
|
+
@classmethod
|
42
|
+
def setUpClassBaseData(cls, *args, **kwargs):
|
43
|
+
super().setUpClassBaseData(*args, **kwargs)
|
44
|
+
cls._load_test_models()
|
45
|
+
cls.carrier = cls.env["delivery.carrier"].search([], limit=1)
|
46
|
+
delivery_packaging_type = (
|
47
|
+
cls.env["stock.package.type"]
|
48
|
+
.sudo()
|
49
|
+
.create({"name": "TEST DEFAULT", "package_carrier_type": "test"})
|
50
|
+
)
|
51
|
+
cls.carrier.sudo().write(
|
52
|
+
{
|
53
|
+
"delivery_type": "test",
|
54
|
+
"integration_level": "rate", # avoid sending emails
|
55
|
+
"test_default_packaging_id": delivery_packaging_type.id,
|
56
|
+
}
|
57
|
+
)
|
58
|
+
|
59
|
+
def setUp(self):
|
60
|
+
super().setUp()
|
61
|
+
self.service.work.current_picking_type = self.picking1.picking_type_id
|
62
|
+
self.menu.sudo().pick_pack_same_time = True
|
63
|
+
|
64
|
+
def test_set_destination_location_no_carrier(self):
|
65
|
+
"""Scan location but carrier not set on picking"""
|
66
|
+
zone_location = self.zone_location
|
67
|
+
picking_type = self.picking1.picking_type_id
|
68
|
+
move_line = self.picking1.move_line_ids
|
69
|
+
move_line.location_dest_id = self.shelf1
|
70
|
+
quantity_done = move_line.reserved_uom_qty
|
71
|
+
previous_qty_done = move_line.qty_done
|
72
|
+
# Confirm the destination with the right destination
|
73
|
+
response = self.service.dispatch(
|
74
|
+
"set_destination",
|
75
|
+
params={
|
76
|
+
"move_line_id": move_line.id,
|
77
|
+
"barcode": self.packing_location.barcode,
|
78
|
+
"quantity": quantity_done,
|
79
|
+
"confirmation": True,
|
80
|
+
},
|
81
|
+
)
|
82
|
+
self.assertEqual(move_line.qty_done, previous_qty_done)
|
83
|
+
self.assert_response_set_line_destination(
|
84
|
+
response,
|
85
|
+
zone_location,
|
86
|
+
picking_type,
|
87
|
+
move_line,
|
88
|
+
message=self.service.msg_store.picking_without_carrier_cannot_pack(
|
89
|
+
move_line.picking_id
|
90
|
+
),
|
91
|
+
qty_done=quantity_done,
|
92
|
+
)
|
93
|
+
|
94
|
+
def test_set_destination_location_ok_carrier(self):
|
95
|
+
"""When carried is set goods are packed into new delivery package."""
|
96
|
+
existing_packages = self.env["stock.quant.package"].search([])
|
97
|
+
zone_location = self.zone_location
|
98
|
+
picking_type = self.picking1.picking_type_id
|
99
|
+
move_line = self.picking1.move_line_ids
|
100
|
+
move_line.location_dest_id = self.shelf1
|
101
|
+
move_line.picking_id.carrier_id = self.carrier
|
102
|
+
response = self.service.dispatch(
|
103
|
+
"set_destination",
|
104
|
+
params={
|
105
|
+
"move_line_id": move_line.id,
|
106
|
+
"barcode": self.packing_location.barcode,
|
107
|
+
"quantity": move_line.reserved_uom_qty,
|
108
|
+
"confirmation": True,
|
109
|
+
},
|
110
|
+
)
|
111
|
+
# Check response
|
112
|
+
move_lines = self.service._find_location_move_lines()
|
113
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
114
|
+
delivery_pkg = move_line.result_package_id
|
115
|
+
self.assertNotIn(delivery_pkg, existing_packages)
|
116
|
+
self.assertEqual(
|
117
|
+
delivery_pkg.package_type_id, self.carrier.test_default_packaging_id
|
118
|
+
)
|
119
|
+
message = self.msg_store.confirm_pack_moved()
|
120
|
+
message["body"] += "\n" + self.msg_store.goods_packed_in(delivery_pkg)["body"]
|
121
|
+
self.assert_response_select_line(
|
122
|
+
response,
|
123
|
+
zone_location,
|
124
|
+
picking_type,
|
125
|
+
move_lines,
|
126
|
+
message=message,
|
127
|
+
)
|
128
|
+
|
129
|
+
def test_set_destination_package_full_qty_no_carrier(self):
|
130
|
+
"""Scan destination package, no carrier on picking."""
|
131
|
+
zone_location = self.zone_location
|
132
|
+
picking_type = self.picking1.picking_type_id
|
133
|
+
moves_before = self.picking1.move_ids
|
134
|
+
self.assertEqual(len(moves_before), 1)
|
135
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
136
|
+
move_line = moves_before.move_line_ids
|
137
|
+
quantity_done = move_line.reserved_uom_qty
|
138
|
+
response = self.service.dispatch(
|
139
|
+
"set_destination",
|
140
|
+
params={
|
141
|
+
"move_line_id": move_line.id,
|
142
|
+
"barcode": self.free_package.name,
|
143
|
+
"quantity": quantity_done,
|
144
|
+
"confirmation": True,
|
145
|
+
},
|
146
|
+
)
|
147
|
+
self.assert_response_set_line_destination(
|
148
|
+
response,
|
149
|
+
zone_location,
|
150
|
+
picking_type,
|
151
|
+
move_line,
|
152
|
+
message=self.service.msg_store.picking_without_carrier_cannot_pack(
|
153
|
+
move_line.picking_id
|
154
|
+
),
|
155
|
+
qty_done=quantity_done,
|
156
|
+
)
|
157
|
+
|
158
|
+
def test_set_destination_package_full_qty_ok_carrier_bad_package(self):
|
159
|
+
"""Scan destination package, carrier on picking, package invalid."""
|
160
|
+
zone_location = self.zone_location
|
161
|
+
picking_type = self.picking1.picking_type_id
|
162
|
+
moves_before = self.picking1.move_ids
|
163
|
+
self.assertEqual(len(moves_before), 1)
|
164
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
165
|
+
move_line = moves_before.move_line_ids
|
166
|
+
move_line.picking_id.carrier_id = self.carrier
|
167
|
+
quantity_done = move_line.reserved_uom_qty
|
168
|
+
response = self.service.dispatch(
|
169
|
+
"set_destination",
|
170
|
+
params={
|
171
|
+
"move_line_id": move_line.id,
|
172
|
+
"barcode": self.free_package.name,
|
173
|
+
"quantity": quantity_done,
|
174
|
+
"confirmation": False,
|
175
|
+
},
|
176
|
+
)
|
177
|
+
self.assert_response_set_line_destination(
|
178
|
+
response,
|
179
|
+
zone_location,
|
180
|
+
picking_type,
|
181
|
+
move_line,
|
182
|
+
message=self.service.msg_store.packaging_invalid_for_carrier(
|
183
|
+
self.free_package.product_packaging_id, self.carrier
|
184
|
+
),
|
185
|
+
qty_done=quantity_done,
|
186
|
+
)
|
187
|
+
|
188
|
+
def test_set_destination_package_full_qty_ok_carrier_ok_package(self):
|
189
|
+
"""Scan destination package, carrier on picking, package valid."""
|
190
|
+
zone_location = self.zone_location
|
191
|
+
picking_type = self.picking1.picking_type_id
|
192
|
+
moves_before = self.picking1.move_ids
|
193
|
+
self.assertEqual(len(moves_before), 1)
|
194
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
195
|
+
move_line = moves_before.move_line_ids
|
196
|
+
move_line.picking_id.carrier_id = self.carrier
|
197
|
+
packaging = (
|
198
|
+
self.env["product.packaging"]
|
199
|
+
.sudo()
|
200
|
+
.create(
|
201
|
+
{
|
202
|
+
"name": "TEST DEFAULT",
|
203
|
+
"package_type_id": self.carrier.test_default_packaging_id.id,
|
204
|
+
}
|
205
|
+
)
|
206
|
+
)
|
207
|
+
|
208
|
+
self.free_package.product_packaging_id = packaging
|
209
|
+
response = self.service.dispatch(
|
210
|
+
"set_destination",
|
211
|
+
params={
|
212
|
+
"move_line_id": move_line.id,
|
213
|
+
"barcode": self.free_package.name,
|
214
|
+
"quantity": move_line.reserved_uom_qty,
|
215
|
+
"confirmation": True,
|
216
|
+
},
|
217
|
+
)
|
218
|
+
# Check picking data
|
219
|
+
moves_after = self.picking1.move_ids
|
220
|
+
self.assertEqual(moves_before, moves_after)
|
221
|
+
self.assertRecordValues(
|
222
|
+
move_line,
|
223
|
+
[
|
224
|
+
{
|
225
|
+
"result_package_id": self.free_package.id,
|
226
|
+
"reserved_uom_qty": 10,
|
227
|
+
"qty_done": 10,
|
228
|
+
"shopfloor_user_id": self.env.user.id,
|
229
|
+
},
|
230
|
+
],
|
231
|
+
)
|
232
|
+
# Check response
|
233
|
+
move_lines = self.service._find_location_move_lines()
|
234
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
235
|
+
self.assert_response_select_line(
|
236
|
+
response,
|
237
|
+
zone_location,
|
238
|
+
picking_type,
|
239
|
+
move_lines,
|
240
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
241
|
+
)
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# Copyright 2020 Camptocamp SA (http://www.camptocamp.com)
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
from .test_zone_picking_base import ZonePickingCommonCase
|
4
|
+
|
5
|
+
# pylint: disable=missing-return
|
6
|
+
|
7
|
+
|
8
|
+
class ZonePickingStartCase(ZonePickingCommonCase):
|
9
|
+
"""Tests for endpoint used from start
|
10
|
+
|
11
|
+
* /scan_location
|
12
|
+
|
13
|
+
"""
|
14
|
+
|
15
|
+
@classmethod
|
16
|
+
def setUpClassBaseData(cls, *args, **kwargs):
|
17
|
+
super().setUpClassBaseData(*args, **kwargs)
|
18
|
+
# create a picking w/ a different picking type
|
19
|
+
# which should be excluded from picking types list
|
20
|
+
bad_picking_type = cls.picking_type.sudo().copy(
|
21
|
+
{
|
22
|
+
"name": "Bad type",
|
23
|
+
"sequence_code": "WH/BAD",
|
24
|
+
"default_location_src_id": cls.zone_location.id,
|
25
|
+
"shopfloor_menu_ids": False,
|
26
|
+
}
|
27
|
+
)
|
28
|
+
cls.extra_picking = extra_picking = cls._create_picking(
|
29
|
+
lines=[(cls.product_b, 10)],
|
30
|
+
picking_type=bad_picking_type,
|
31
|
+
)
|
32
|
+
cls._fill_stock_for_moves(
|
33
|
+
extra_picking.move_ids, in_package=True, location=cls.zone_sublocation1
|
34
|
+
)
|
35
|
+
cls._update_qty_in_location(cls.zone_sublocation1, cls.product_b, 10)
|
36
|
+
extra_picking.action_assign()
|
37
|
+
|
38
|
+
def test_data_for_zone(self):
|
39
|
+
op_type_data = self.data.picking_type(self.menu.picking_type_ids[0])
|
40
|
+
zones_data = self.service._response_for_start()["data"]["start"]["zones"]
|
41
|
+
expected_sub1 = dict(
|
42
|
+
self.data.location(self.zone_sublocation1),
|
43
|
+
lines_count=1,
|
44
|
+
picking_count=1,
|
45
|
+
priority_lines_count=0,
|
46
|
+
priority_picking_count=0,
|
47
|
+
operation_types=[
|
48
|
+
dict(
|
49
|
+
op_type_data,
|
50
|
+
lines_count=1,
|
51
|
+
picking_count=1,
|
52
|
+
priority_lines_count=0,
|
53
|
+
priority_picking_count=0,
|
54
|
+
)
|
55
|
+
],
|
56
|
+
)
|
57
|
+
expected_sub2 = dict(
|
58
|
+
self.data.location(self.zone_sublocation2),
|
59
|
+
lines_count=2,
|
60
|
+
picking_count=2,
|
61
|
+
priority_lines_count=0,
|
62
|
+
priority_picking_count=0,
|
63
|
+
operation_types=[
|
64
|
+
dict(
|
65
|
+
op_type_data,
|
66
|
+
lines_count=2,
|
67
|
+
picking_count=2,
|
68
|
+
priority_lines_count=0,
|
69
|
+
priority_picking_count=0,
|
70
|
+
)
|
71
|
+
],
|
72
|
+
)
|
73
|
+
expected_sub3 = dict(
|
74
|
+
self.data.location(self.zone_sublocation3),
|
75
|
+
lines_count=2,
|
76
|
+
picking_count=2,
|
77
|
+
priority_lines_count=0,
|
78
|
+
priority_picking_count=0,
|
79
|
+
operation_types=[
|
80
|
+
dict(
|
81
|
+
op_type_data,
|
82
|
+
lines_count=2,
|
83
|
+
picking_count=2,
|
84
|
+
priority_lines_count=0,
|
85
|
+
priority_picking_count=0,
|
86
|
+
)
|
87
|
+
],
|
88
|
+
)
|
89
|
+
expected_sub4 = dict(
|
90
|
+
self.data.location(self.zone_sublocation4),
|
91
|
+
lines_count=3,
|
92
|
+
picking_count=3,
|
93
|
+
priority_lines_count=0,
|
94
|
+
priority_picking_count=0,
|
95
|
+
operation_types=[
|
96
|
+
dict(
|
97
|
+
op_type_data,
|
98
|
+
lines_count=3,
|
99
|
+
picking_count=3,
|
100
|
+
priority_lines_count=0,
|
101
|
+
priority_picking_count=0,
|
102
|
+
)
|
103
|
+
],
|
104
|
+
)
|
105
|
+
expected_sub5 = dict(
|
106
|
+
self.data.location(self.zone_sublocation5),
|
107
|
+
lines_count=2,
|
108
|
+
picking_count=1,
|
109
|
+
priority_lines_count=0,
|
110
|
+
priority_picking_count=0,
|
111
|
+
operation_types=[
|
112
|
+
dict(
|
113
|
+
op_type_data,
|
114
|
+
lines_count=2,
|
115
|
+
picking_count=1,
|
116
|
+
priority_lines_count=0,
|
117
|
+
priority_picking_count=0,
|
118
|
+
)
|
119
|
+
],
|
120
|
+
)
|
121
|
+
self.assertEqual(
|
122
|
+
zones_data,
|
123
|
+
[expected_sub1, expected_sub2, expected_sub3, expected_sub4, expected_sub5],
|
124
|
+
)
|
125
|
+
|
126
|
+
def test_select_zone(self):
|
127
|
+
"""Scanned location invalid, no location found."""
|
128
|
+
response = self.service.dispatch("select_zone")
|
129
|
+
self.assert_response_start(response)
|
130
|
+
|
131
|
+
def test_select_zone_with_loaded_buffer(self):
|
132
|
+
"""Check loaded buffer info in select zone answer."""
|
133
|
+
zone_location = self.zone_location
|
134
|
+
picking_type = self.picking1.picking_type_id
|
135
|
+
move_line = self.picking5.move_line_ids[1]
|
136
|
+
# change the destination location on the move line
|
137
|
+
move_line.location_dest_id = self.zone_sublocation3
|
138
|
+
# and set the destination package
|
139
|
+
self.service._set_destination_package(
|
140
|
+
move_line,
|
141
|
+
move_line.reserved_uom_qty,
|
142
|
+
self.free_package,
|
143
|
+
)
|
144
|
+
response = self.service.dispatch("select_zone")
|
145
|
+
data = {
|
146
|
+
"zones": self.service._data_for_select_zone(zone_location.child_ids),
|
147
|
+
"buffer": {
|
148
|
+
"zone_location": self.service.data.location(zone_location),
|
149
|
+
"picking_type": self.service.data.picking_type(picking_type),
|
150
|
+
},
|
151
|
+
}
|
152
|
+
self.assert_response(
|
153
|
+
response,
|
154
|
+
next_state="start",
|
155
|
+
data=data,
|
156
|
+
)
|
157
|
+
|
158
|
+
def test_scan_location_wrong_barcode(self):
|
159
|
+
"""Scanned location invalid, no location found."""
|
160
|
+
response = self.service.dispatch(
|
161
|
+
"scan_location",
|
162
|
+
params={"barcode": "UNKNOWN LOCATION"},
|
163
|
+
)
|
164
|
+
self.assert_response_start(
|
165
|
+
response,
|
166
|
+
message=self.service.msg_store.no_location_found(),
|
167
|
+
)
|
168
|
+
|
169
|
+
def test_scan_location_not_allowed(self):
|
170
|
+
"""Scanned location not allowed because it's not a child of picking
|
171
|
+
types' source location.
|
172
|
+
"""
|
173
|
+
response = self.service.dispatch(
|
174
|
+
"scan_location",
|
175
|
+
params={"barcode": self.customer_location.barcode},
|
176
|
+
)
|
177
|
+
self.assert_response_start(
|
178
|
+
response,
|
179
|
+
message=self.service.msg_store.location_not_allowed(),
|
180
|
+
)
|
181
|
+
|
182
|
+
def test_scan_location_no_move_lines(self):
|
183
|
+
"""Scanned location valid, but no move lines found in it."""
|
184
|
+
sub1_lines = self.service._find_location_move_lines(self.zone_sublocation1)
|
185
|
+
# no more lines available
|
186
|
+
sub1_lines.picking_id.action_cancel()
|
187
|
+
response = self.service.dispatch(
|
188
|
+
"scan_location",
|
189
|
+
params={"barcode": self.zone_sublocation1.barcode},
|
190
|
+
)
|
191
|
+
self.assert_response_start(
|
192
|
+
response,
|
193
|
+
message=self.service.msg_store.no_lines_to_process(),
|
194
|
+
)
|
195
|
+
|
196
|
+
def test_scan_location_ok(self):
|
197
|
+
"""Scanned location valid, list of picking types of related move lines."""
|
198
|
+
response = self.service.dispatch(
|
199
|
+
"scan_location",
|
200
|
+
params={"barcode": self.zone_location.barcode},
|
201
|
+
)
|
202
|
+
self.assert_response_select_picking_type(
|
203
|
+
response,
|
204
|
+
zone_location=self.zone_location,
|
205
|
+
picking_types=self.picking_type,
|
206
|
+
)
|