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,643 @@
|
|
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 ZonePickingSetLineDestinationCase(ZonePickingCommonCase):
|
9
|
+
"""Tests for endpoint used from set_line_destination
|
10
|
+
|
11
|
+
* /set_destination
|
12
|
+
|
13
|
+
"""
|
14
|
+
|
15
|
+
def setUp(self):
|
16
|
+
super().setUp()
|
17
|
+
self.service.work.current_picking_type = self.picking1.picking_type_id
|
18
|
+
|
19
|
+
def test_set_destination_wrong_parameters(self):
|
20
|
+
move_line = self.picking1.move_line_ids[0]
|
21
|
+
response = self.service.dispatch(
|
22
|
+
"set_destination",
|
23
|
+
params={
|
24
|
+
"move_line_id": 1234567890,
|
25
|
+
"barcode": self.packing_location.barcode,
|
26
|
+
"quantity": move_line.reserved_uom_qty,
|
27
|
+
"confirmation": False,
|
28
|
+
},
|
29
|
+
)
|
30
|
+
self.assert_response_start(
|
31
|
+
response,
|
32
|
+
message=self.service.msg_store.record_not_found(),
|
33
|
+
)
|
34
|
+
|
35
|
+
def test_set_destination_location_confirm(self):
|
36
|
+
"""Scanned barcode is the destination location but needs confirmation
|
37
|
+
as it is outside the current move line destination but is still
|
38
|
+
allowed by the picking type's default destination.
|
39
|
+
"""
|
40
|
+
zone_location = self.zone_location
|
41
|
+
picking_type = self.picking1.picking_type_id
|
42
|
+
move_line = self.picking1.move_line_ids
|
43
|
+
move_line.location_dest_id = self.shelf1
|
44
|
+
quantity_done = move_line.reserved_uom_qty
|
45
|
+
response = self.service.dispatch(
|
46
|
+
"set_destination",
|
47
|
+
params={
|
48
|
+
"move_line_id": move_line.id,
|
49
|
+
"barcode": self.packing_location.barcode,
|
50
|
+
"quantity": quantity_done,
|
51
|
+
"confirmation": False,
|
52
|
+
},
|
53
|
+
)
|
54
|
+
# Check response
|
55
|
+
self.assert_response_set_line_destination(
|
56
|
+
response,
|
57
|
+
zone_location,
|
58
|
+
picking_type,
|
59
|
+
move_line,
|
60
|
+
message=self.service.msg_store.confirm_location_changed(
|
61
|
+
move_line.location_dest_id, self.packing_location
|
62
|
+
),
|
63
|
+
confirmation_required=True,
|
64
|
+
qty_done=quantity_done,
|
65
|
+
)
|
66
|
+
# Confirm the destination with a wrong destination (should not happen)
|
67
|
+
response = self.service.dispatch(
|
68
|
+
"set_destination",
|
69
|
+
params={
|
70
|
+
"move_line_id": move_line.id,
|
71
|
+
"barcode": self.customer_location.barcode,
|
72
|
+
"quantity": move_line.reserved_uom_qty,
|
73
|
+
"confirmation": True,
|
74
|
+
},
|
75
|
+
)
|
76
|
+
# Check response
|
77
|
+
self.assert_response_set_line_destination(
|
78
|
+
response,
|
79
|
+
zone_location,
|
80
|
+
picking_type,
|
81
|
+
move_line,
|
82
|
+
message=self.service.msg_store.dest_location_not_allowed(),
|
83
|
+
qty_done=quantity_done,
|
84
|
+
)
|
85
|
+
# Confirm the destination with the right destination this time
|
86
|
+
response = self.service.dispatch(
|
87
|
+
"set_destination",
|
88
|
+
params={
|
89
|
+
"move_line_id": move_line.id,
|
90
|
+
"barcode": self.packing_location.barcode,
|
91
|
+
"quantity": move_line.reserved_uom_qty,
|
92
|
+
"confirmation": True,
|
93
|
+
},
|
94
|
+
)
|
95
|
+
# Check response
|
96
|
+
move_lines = self.service._find_location_move_lines()
|
97
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
98
|
+
self.assert_response_select_line(
|
99
|
+
response,
|
100
|
+
zone_location,
|
101
|
+
picking_type,
|
102
|
+
move_lines,
|
103
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
104
|
+
)
|
105
|
+
|
106
|
+
def test_set_destination_location_move_invalid_location(self):
|
107
|
+
# Confirm the destination with a wrong destination, outside of picking
|
108
|
+
# and move's move line (should not happen)
|
109
|
+
zone_location = self.zone_location
|
110
|
+
picking_type = self.picking1.picking_type_id
|
111
|
+
move_line = self.picking1.move_line_ids
|
112
|
+
move_line.move_id.location_dest_id = self.packing_sublocation_a
|
113
|
+
move_line.picking_id.location_dest_id = self.packing_sublocation_a
|
114
|
+
quantity_done = move_line.reserved_uom_qty
|
115
|
+
response = self.service.dispatch(
|
116
|
+
"set_destination",
|
117
|
+
params={
|
118
|
+
"move_line_id": move_line.id,
|
119
|
+
"barcode": self.packing_sublocation_b.barcode,
|
120
|
+
"quantity": quantity_done,
|
121
|
+
"confirmation": True,
|
122
|
+
},
|
123
|
+
)
|
124
|
+
# Check response
|
125
|
+
self.assert_response_set_line_destination(
|
126
|
+
response,
|
127
|
+
zone_location,
|
128
|
+
picking_type,
|
129
|
+
move_line,
|
130
|
+
message=self.service.msg_store.dest_location_not_allowed(),
|
131
|
+
qty_done=quantity_done,
|
132
|
+
)
|
133
|
+
|
134
|
+
def test_set_destination_location_no_other_move_line_full_qty(self):
|
135
|
+
"""Scanned barcode is the destination location.
|
136
|
+
|
137
|
+
The move line is the only one in the move, and we move the whole qty.
|
138
|
+
|
139
|
+
Initial data:
|
140
|
+
|
141
|
+
move qty 10 (assigned):
|
142
|
+
-> move_line qty 10 from location X
|
143
|
+
|
144
|
+
Then the operator move the 10 qty, we get:
|
145
|
+
|
146
|
+
move qty 10 (done):
|
147
|
+
-> move_line qty 10 from location X
|
148
|
+
"""
|
149
|
+
zone_location = self.zone_location
|
150
|
+
picking_type = self.picking1.picking_type_id
|
151
|
+
moves_before = self.picking1.move_ids
|
152
|
+
self.assertEqual(len(moves_before), 1)
|
153
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
154
|
+
move_line = moves_before.move_line_ids
|
155
|
+
response = self.service.dispatch(
|
156
|
+
"set_destination",
|
157
|
+
params={
|
158
|
+
"move_line_id": move_line.id,
|
159
|
+
"barcode": self.packing_location.barcode,
|
160
|
+
"quantity": move_line.reserved_uom_qty,
|
161
|
+
"confirmation": False,
|
162
|
+
},
|
163
|
+
)
|
164
|
+
self.assertEqual(move_line.state, "done")
|
165
|
+
# Check picking data
|
166
|
+
moves_after = self.picking1.move_ids
|
167
|
+
self.assertEqual(moves_before, moves_after)
|
168
|
+
self.assertEqual(move_line.qty_done, 10)
|
169
|
+
# Check response
|
170
|
+
move_lines = self.service._find_location_move_lines()
|
171
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
172
|
+
self.assert_response_select_line(
|
173
|
+
response,
|
174
|
+
zone_location,
|
175
|
+
picking_type,
|
176
|
+
move_lines,
|
177
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
178
|
+
)
|
179
|
+
|
180
|
+
def test_set_destination_location_no_other_move_line_partial_qty(self):
|
181
|
+
"""Scanned barcode is the destination location.
|
182
|
+
|
183
|
+
The move line is the only one in the move, and we move some of the qty.
|
184
|
+
|
185
|
+
Initial data:
|
186
|
+
|
187
|
+
move qty 10 (assigned):
|
188
|
+
-> move_line qty 10 from location X
|
189
|
+
|
190
|
+
Then the operator move 6 qty on 10, we get:
|
191
|
+
|
192
|
+
an error because we can move only full qty by location
|
193
|
+
and only a package barcode is allowed on scan.
|
194
|
+
"""
|
195
|
+
zone_location = self.zone_location
|
196
|
+
picking_type = self.picking3.picking_type_id
|
197
|
+
barcode = self.packing_location.barcode
|
198
|
+
moves_before = self.picking3.move_ids
|
199
|
+
self.assertEqual(len(moves_before), 1)
|
200
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
201
|
+
move_line = moves_before.move_line_ids
|
202
|
+
# we need a destination package if we want to scan a destination location
|
203
|
+
move_line.result_package_id = self.free_package
|
204
|
+
response = self.service.dispatch(
|
205
|
+
"set_destination",
|
206
|
+
params={
|
207
|
+
"move_line_id": move_line.id,
|
208
|
+
"barcode": barcode,
|
209
|
+
"quantity": 6,
|
210
|
+
"confirmation": False,
|
211
|
+
},
|
212
|
+
)
|
213
|
+
self.assert_response_set_line_destination(
|
214
|
+
response,
|
215
|
+
zone_location,
|
216
|
+
picking_type,
|
217
|
+
move_line,
|
218
|
+
qty_done=6,
|
219
|
+
message=self.service.msg_store.package_not_found_for_barcode(barcode),
|
220
|
+
)
|
221
|
+
|
222
|
+
def test_set_destination_location_several_move_line_full_qty(self):
|
223
|
+
"""Scanned barcode is the destination location.
|
224
|
+
|
225
|
+
The move line has siblings in the move, and we move the whole qty:
|
226
|
+
the processed move line will then get its own move (split from original one)
|
227
|
+
|
228
|
+
Initial data:
|
229
|
+
|
230
|
+
move qty 10 (assigned):
|
231
|
+
-> move_line qty 6 from location X
|
232
|
+
-> move_line qty 4 from location Y
|
233
|
+
|
234
|
+
Then the operator move 6 qty (from the first move line), we get:
|
235
|
+
|
236
|
+
move qty 6 (done):
|
237
|
+
-> move_line qty 4 from location X
|
238
|
+
move qty 4 (assigned):
|
239
|
+
-> move_line qty 4 from location Y (untouched)
|
240
|
+
"""
|
241
|
+
zone_location = self.zone_location
|
242
|
+
picking_type = self.picking4.picking_type_id
|
243
|
+
moves_before = self.picking4.move_ids
|
244
|
+
self.assertEqual(len(moves_before), 1)
|
245
|
+
self.assertEqual(len(moves_before.move_line_ids), 2)
|
246
|
+
move_line = moves_before.move_line_ids[0]
|
247
|
+
# we need a destination package if we want to scan a destination location
|
248
|
+
move_line.result_package_id = self.free_package
|
249
|
+
other_move_line = moves_before.move_line_ids[1]
|
250
|
+
response = self.service.dispatch(
|
251
|
+
"set_destination",
|
252
|
+
params={
|
253
|
+
"move_line_id": move_line.id,
|
254
|
+
"barcode": self.packing_location.barcode,
|
255
|
+
"quantity": move_line.reserved_uom_qty, # 6 qty
|
256
|
+
"confirmation": False,
|
257
|
+
},
|
258
|
+
)
|
259
|
+
self.assertEqual(move_line.state, "done")
|
260
|
+
# Check picking data (move has been split in two, 6 done and 4 remaining)
|
261
|
+
|
262
|
+
done_picking = self.picking4.backorder_ids
|
263
|
+
self.assertEqual(done_picking.state, "done")
|
264
|
+
self.assertEqual(self.picking4.state, "assigned")
|
265
|
+
move_after = self.picking4.move_ids
|
266
|
+
self.assertEqual(len(move_after), 1)
|
267
|
+
self.assertEqual(move_line.move_id.product_uom_qty, 6)
|
268
|
+
self.assertEqual(move_line.move_id.state, "done")
|
269
|
+
self.assertEqual(move_line.move_id.move_line_ids.reserved_uom_qty, 0)
|
270
|
+
self.assertEqual(move_after.product_uom_qty, 4)
|
271
|
+
self.assertEqual(move_after.state, "assigned")
|
272
|
+
self.assertEqual(move_after.move_line_ids.reserved_uom_qty, 4)
|
273
|
+
self.assertEqual(move_line.qty_done, 6)
|
274
|
+
self.assertNotEqual(move_line.move_id, other_move_line.move_id)
|
275
|
+
# Check response
|
276
|
+
move_lines = self.service._find_location_move_lines()
|
277
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
278
|
+
self.assert_response_select_line(
|
279
|
+
response,
|
280
|
+
zone_location,
|
281
|
+
picking_type,
|
282
|
+
move_lines,
|
283
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
284
|
+
)
|
285
|
+
|
286
|
+
def test_set_destination_location_several_move_line_partial_qty(self):
|
287
|
+
"""Scanned barcode is the destination location.
|
288
|
+
|
289
|
+
The move line has siblings in the move, and we move some of the qty:
|
290
|
+
the processed move line will then get its own move (split from original one)
|
291
|
+
|
292
|
+
Initial data:
|
293
|
+
|
294
|
+
move qty 10 (assigned):
|
295
|
+
-> move_line qty 6 from location X
|
296
|
+
-> move_line qty 4 from location Y
|
297
|
+
|
298
|
+
Then the operator move 4 qty on 6 (from the first move line), we get:
|
299
|
+
|
300
|
+
an error because we can move only full qty by location
|
301
|
+
and only a package barcode is allowed on scan.
|
302
|
+
"""
|
303
|
+
zone_location = self.zone_location
|
304
|
+
picking_type = self.picking4.picking_type_id
|
305
|
+
barcode = self.packing_location.barcode
|
306
|
+
moves_before = self.picking4.move_ids
|
307
|
+
self.assertEqual(len(moves_before), 1) # 10 qty
|
308
|
+
self.assertEqual(len(moves_before.move_line_ids), 2) # 6+4 qty
|
309
|
+
move_line = moves_before.move_line_ids[0]
|
310
|
+
# we need a destination package if we want to scan a destination location
|
311
|
+
move_line.result_package_id = self.free_package
|
312
|
+
response = self.service.dispatch(
|
313
|
+
"set_destination",
|
314
|
+
params={
|
315
|
+
"move_line_id": move_line.id,
|
316
|
+
"barcode": barcode,
|
317
|
+
"quantity": 4, # 4/6 qty
|
318
|
+
"confirmation": False,
|
319
|
+
},
|
320
|
+
)
|
321
|
+
self.assert_response_set_line_destination(
|
322
|
+
response,
|
323
|
+
zone_location,
|
324
|
+
picking_type,
|
325
|
+
move_line,
|
326
|
+
qty_done=4,
|
327
|
+
message=self.service.msg_store.package_not_found_for_barcode(barcode),
|
328
|
+
)
|
329
|
+
|
330
|
+
def test_set_destination_location_zero_check(self):
|
331
|
+
"""Scanned barcode is the destination location.
|
332
|
+
|
333
|
+
The move line is the only one in the source location, as such the
|
334
|
+
'zero_check' step is triggered.
|
335
|
+
"""
|
336
|
+
zone_location = self.zone_location
|
337
|
+
picking_type = self.picking1.picking_type_id
|
338
|
+
picking_type.sudo().shopfloor_zero_check = True
|
339
|
+
self.assertEqual(len(self.picking1.move_line_ids), 1)
|
340
|
+
move_line = self.picking1.move_line_ids
|
341
|
+
location_is_empty = move_line.location_id.planned_qty_in_location_is_empty
|
342
|
+
self.assertFalse(location_is_empty())
|
343
|
+
response = self.service.dispatch(
|
344
|
+
"set_destination",
|
345
|
+
params={
|
346
|
+
"move_line_id": move_line.id,
|
347
|
+
"barcode": self.packing_location.barcode,
|
348
|
+
"quantity": move_line.reserved_uom_qty,
|
349
|
+
"confirmation": False,
|
350
|
+
},
|
351
|
+
)
|
352
|
+
self.assertTrue(location_is_empty())
|
353
|
+
# Check response
|
354
|
+
self.assert_response_zero_check(
|
355
|
+
response, zone_location, picking_type, move_line
|
356
|
+
)
|
357
|
+
|
358
|
+
def test_set_destination_package_full_qty(self):
|
359
|
+
"""Scanned barcode is the destination package.
|
360
|
+
|
361
|
+
Initial data:
|
362
|
+
|
363
|
+
move qty 10 (assigned):
|
364
|
+
-> move_line qty 10 from location X
|
365
|
+
|
366
|
+
Then the operator move the 10 qty, we get:
|
367
|
+
|
368
|
+
move qty 10 (done):
|
369
|
+
-> move_line qty 10 from location X with the scanned package
|
370
|
+
"""
|
371
|
+
zone_location = self.zone_location
|
372
|
+
picking_type = self.picking1.picking_type_id
|
373
|
+
moves_before = self.picking1.move_ids
|
374
|
+
self.assertEqual(len(moves_before), 1)
|
375
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
376
|
+
move_line = moves_before.move_line_ids
|
377
|
+
response = self.service.dispatch(
|
378
|
+
"set_destination",
|
379
|
+
params={
|
380
|
+
"move_line_id": move_line.id,
|
381
|
+
"barcode": self.free_package.name,
|
382
|
+
"quantity": move_line.reserved_uom_qty,
|
383
|
+
"confirmation": False,
|
384
|
+
},
|
385
|
+
)
|
386
|
+
# Check picking data
|
387
|
+
moves_after = self.picking1.move_ids
|
388
|
+
self.assertEqual(moves_before, moves_after)
|
389
|
+
self.assertRecordValues(
|
390
|
+
move_line,
|
391
|
+
[
|
392
|
+
{
|
393
|
+
"result_package_id": self.free_package.id,
|
394
|
+
"reserved_uom_qty": 10,
|
395
|
+
"qty_done": 10,
|
396
|
+
"shopfloor_user_id": self.env.user.id,
|
397
|
+
},
|
398
|
+
],
|
399
|
+
)
|
400
|
+
# Check response
|
401
|
+
move_lines = self.service._find_location_move_lines()
|
402
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
403
|
+
self.assert_response_select_line(
|
404
|
+
response,
|
405
|
+
zone_location,
|
406
|
+
picking_type,
|
407
|
+
move_lines,
|
408
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
409
|
+
)
|
410
|
+
|
411
|
+
def test_set_destination_package_partial_qty(self):
|
412
|
+
"""Scanned barcode is the destination package.
|
413
|
+
|
414
|
+
Initial data:
|
415
|
+
|
416
|
+
move qty 10 (assigned):
|
417
|
+
-> move_line qty 10 from location X
|
418
|
+
|
419
|
+
Then the operator move the 6 on 10 qty, we get:
|
420
|
+
|
421
|
+
move qty 6 (assigned):
|
422
|
+
-> move_line qty 6 from location X with the scanned package (buffer)
|
423
|
+
-> move_line qty 4 from location X (remaining)
|
424
|
+
"""
|
425
|
+
zone_location = self.zone_location
|
426
|
+
picking_type = self.picking1.picking_type_id
|
427
|
+
moves_before = self.picking1.move_ids
|
428
|
+
self.assertEqual(len(moves_before), 1)
|
429
|
+
self.assertEqual(len(moves_before.move_line_ids), 1)
|
430
|
+
move_line = moves_before.move_line_ids
|
431
|
+
response = self.service.dispatch(
|
432
|
+
"set_destination",
|
433
|
+
params={
|
434
|
+
"move_line_id": move_line.id,
|
435
|
+
"barcode": self.free_package.name,
|
436
|
+
"quantity": 6,
|
437
|
+
"confirmation": False,
|
438
|
+
},
|
439
|
+
)
|
440
|
+
# Check picking data
|
441
|
+
moves_after = self.picking1.move_ids
|
442
|
+
new_move_line = self.picking1.move_line_ids.filtered(
|
443
|
+
lambda line: line != move_line
|
444
|
+
)
|
445
|
+
self.assertTrue(move_line != new_move_line)
|
446
|
+
self.assertEqual(moves_before, moves_after)
|
447
|
+
self.assertRecordValues(
|
448
|
+
move_line,
|
449
|
+
[
|
450
|
+
{
|
451
|
+
"result_package_id": self.free_package.id,
|
452
|
+
"reserved_uom_qty": 6,
|
453
|
+
"qty_done": 6,
|
454
|
+
"shopfloor_user_id": self.env.user.id,
|
455
|
+
},
|
456
|
+
],
|
457
|
+
)
|
458
|
+
self.assertRecordValues(
|
459
|
+
new_move_line,
|
460
|
+
[
|
461
|
+
{
|
462
|
+
"result_package_id": new_move_line.package_id.id, # Unchanged
|
463
|
+
"reserved_uom_qty": 4,
|
464
|
+
"qty_done": 0,
|
465
|
+
"shopfloor_user_id": False,
|
466
|
+
},
|
467
|
+
],
|
468
|
+
)
|
469
|
+
# Check response
|
470
|
+
move_lines = self.service._find_location_move_lines()
|
471
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
472
|
+
self.assert_response_select_line(
|
473
|
+
response,
|
474
|
+
zone_location,
|
475
|
+
picking_type,
|
476
|
+
move_lines,
|
477
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
478
|
+
)
|
479
|
+
|
480
|
+
def test_set_destination_package_zero_check(self):
|
481
|
+
"""Scanned barcode is the destination package.
|
482
|
+
|
483
|
+
The move line is the only one in the source location, as such the
|
484
|
+
'zero_check' step is triggered.
|
485
|
+
"""
|
486
|
+
zone_location = self.zone_location
|
487
|
+
picking_type = self.picking1.picking_type_id
|
488
|
+
picking_type.sudo().shopfloor_zero_check = True
|
489
|
+
self.assertEqual(len(self.picking1.move_line_ids), 1)
|
490
|
+
move_line = self.picking1.move_line_ids
|
491
|
+
location_is_empty = move_line.location_id.planned_qty_in_location_is_empty
|
492
|
+
self.assertFalse(location_is_empty())
|
493
|
+
response = self.service.dispatch(
|
494
|
+
"set_destination",
|
495
|
+
params={
|
496
|
+
"move_line_id": move_line.id,
|
497
|
+
"barcode": self.free_package.name,
|
498
|
+
"quantity": move_line.reserved_uom_qty,
|
499
|
+
"confirmation": False,
|
500
|
+
},
|
501
|
+
)
|
502
|
+
self.assertTrue(location_is_empty())
|
503
|
+
# Check response
|
504
|
+
self.assert_response_zero_check(
|
505
|
+
response,
|
506
|
+
zone_location,
|
507
|
+
picking_type,
|
508
|
+
move_line,
|
509
|
+
)
|
510
|
+
|
511
|
+
def test_set_same_destination_package_multiple_moves(self):
|
512
|
+
"""Scanned barcode is the destination package."""
|
513
|
+
zone_location = self.zone_location
|
514
|
+
picking_type = self.picking1.picking_type_id
|
515
|
+
# picking_type.sudo().shopfloor_zero_check = True
|
516
|
+
self.assertEqual(len(self.picking1.move_line_ids), 1)
|
517
|
+
move_line = self.picking1.move_line_ids
|
518
|
+
location_is_empty = move_line.location_id.planned_qty_in_location_is_empty
|
519
|
+
self.assertFalse(location_is_empty())
|
520
|
+
response = self.service.dispatch(
|
521
|
+
"set_destination",
|
522
|
+
params={
|
523
|
+
"move_line_id": move_line.id,
|
524
|
+
"barcode": self.free_package.name,
|
525
|
+
"quantity": move_line.reserved_uom_qty,
|
526
|
+
"confirmation": False,
|
527
|
+
},
|
528
|
+
)
|
529
|
+
self.assertTrue(location_is_empty())
|
530
|
+
# Check response
|
531
|
+
move_lines = self.service._find_location_move_lines()
|
532
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
533
|
+
self.assert_response_select_line(
|
534
|
+
response,
|
535
|
+
zone_location,
|
536
|
+
picking_type,
|
537
|
+
move_lines,
|
538
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
539
|
+
)
|
540
|
+
# Now, try to add more goods in the same package
|
541
|
+
move_line = self.picking3.move_line_ids
|
542
|
+
response = self.service.dispatch(
|
543
|
+
"set_destination",
|
544
|
+
params={
|
545
|
+
"move_line_id": move_line.id,
|
546
|
+
"barcode": self.free_package.name,
|
547
|
+
"quantity": move_line.reserved_uom_qty,
|
548
|
+
"confirmation": False,
|
549
|
+
},
|
550
|
+
)
|
551
|
+
self.assertEqual(
|
552
|
+
response["message"],
|
553
|
+
{
|
554
|
+
"body": "Package FREE_PACKAGE is already used.",
|
555
|
+
"message_type": "warning",
|
556
|
+
},
|
557
|
+
)
|
558
|
+
# Now enable `multiple_move_single_pack` and try again
|
559
|
+
self.menu.sudo().write(
|
560
|
+
{
|
561
|
+
"multiple_move_single_pack": True,
|
562
|
+
"unload_package_at_destination": True,
|
563
|
+
}
|
564
|
+
)
|
565
|
+
response = self.service.dispatch(
|
566
|
+
"set_destination",
|
567
|
+
params={
|
568
|
+
"move_line_id": move_line.id,
|
569
|
+
"barcode": self.free_package.name,
|
570
|
+
"quantity": move_line.reserved_uom_qty,
|
571
|
+
"confirmation": False,
|
572
|
+
},
|
573
|
+
)
|
574
|
+
# We now have no error in the response
|
575
|
+
move_lines = self.service._find_location_move_lines()
|
576
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
577
|
+
self.assert_response_select_line(
|
578
|
+
response,
|
579
|
+
zone_location,
|
580
|
+
picking_type,
|
581
|
+
move_lines,
|
582
|
+
message=self.service.msg_store.confirm_pack_moved(),
|
583
|
+
)
|
584
|
+
|
585
|
+
def test_set_destination_location_zero_quantity(self):
|
586
|
+
"""Scanned barcode is the destination location.
|
587
|
+
|
588
|
+
Quantity to move is zero -> error raised, user can try again.
|
589
|
+
|
590
|
+
"""
|
591
|
+
zone_location = self.zone_location
|
592
|
+
picking_type = self.picking1.picking_type_id
|
593
|
+
move_line = self.picking1.move_ids.move_line_ids
|
594
|
+
response = self.service.dispatch(
|
595
|
+
"set_destination",
|
596
|
+
params={
|
597
|
+
"move_line_id": move_line.id,
|
598
|
+
"barcode": self.packing_location.barcode,
|
599
|
+
"quantity": 0,
|
600
|
+
},
|
601
|
+
)
|
602
|
+
# Check response
|
603
|
+
self.assert_response_set_line_destination(
|
604
|
+
response,
|
605
|
+
zone_location,
|
606
|
+
picking_type,
|
607
|
+
move_line,
|
608
|
+
message=self.service.msg_store.picking_zero_quantity(),
|
609
|
+
qty_done=move_line.reserved_uom_qty,
|
610
|
+
)
|
611
|
+
|
612
|
+
def test_set_destination_error_concurent_work(self):
|
613
|
+
"""Scanned barcode is the destination package.
|
614
|
+
|
615
|
+
Move line is already being worked on by someone else
|
616
|
+
"""
|
617
|
+
zone_location = self.zone_location
|
618
|
+
picking_type = self.picking1.picking_type_id
|
619
|
+
picking_type.sudo().shopfloor_zero_check = True
|
620
|
+
self.assertEqual(len(self.picking1.move_line_ids), 1)
|
621
|
+
move_line = self.picking1.move_line_ids
|
622
|
+
move_line.picking_id.user_id = self.shopfloor_manager
|
623
|
+
response = self.service.dispatch(
|
624
|
+
"set_destination",
|
625
|
+
params={
|
626
|
+
"move_line_id": move_line.id,
|
627
|
+
"barcode": self.free_package.name,
|
628
|
+
"quantity": move_line.reserved_uom_qty,
|
629
|
+
"confirmation": False,
|
630
|
+
},
|
631
|
+
)
|
632
|
+
# Check response
|
633
|
+
self.assert_response_set_line_destination(
|
634
|
+
response,
|
635
|
+
zone_location,
|
636
|
+
picking_type,
|
637
|
+
move_line,
|
638
|
+
message={
|
639
|
+
"message_type": "error",
|
640
|
+
"body": "Someone is already working on these transfers",
|
641
|
+
},
|
642
|
+
qty_done=move_line.reserved_uom_qty,
|
643
|
+
)
|