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,723 @@
|
|
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 odoo import fields
|
4
|
+
|
5
|
+
from .test_zone_picking_base import ZonePickingCommonCase
|
6
|
+
|
7
|
+
|
8
|
+
# pylint: disable=missing-return
|
9
|
+
class ZonePickingSelectLineCase(ZonePickingCommonCase):
|
10
|
+
"""Tests for endpoint used from select_line
|
11
|
+
|
12
|
+
* /list_move_lines (to change order)
|
13
|
+
* /scan_source
|
14
|
+
* /prepare_unload
|
15
|
+
|
16
|
+
"""
|
17
|
+
|
18
|
+
def setUp(self):
|
19
|
+
super().setUp()
|
20
|
+
self.service.work.current_picking_type = self.picking1.picking_type_id
|
21
|
+
|
22
|
+
def test_list_move_lines_order(self):
|
23
|
+
self.zone_sublocation2.name = "AAA " + self.zone_sublocation2.name
|
24
|
+
|
25
|
+
# Test by location
|
26
|
+
today = fields.Datetime.today()
|
27
|
+
future = fields.Datetime.add(
|
28
|
+
fields.Datetime.end_of(fields.Datetime.today(), "day"), days=2
|
29
|
+
)
|
30
|
+
# change date to lines in the same location
|
31
|
+
move1 = self.picking2.move_ids[0]
|
32
|
+
move1.write({"date": today})
|
33
|
+
move1_line = move1.move_line_ids[0]
|
34
|
+
move2 = self.picking2.move_ids[1]
|
35
|
+
move2.write({"date": future})
|
36
|
+
move2_line = move2.move_line_ids[0]
|
37
|
+
|
38
|
+
self.service.work.current_lines_order = "location"
|
39
|
+
move_lines = self.service._find_location_move_lines()
|
40
|
+
order_mapping = {line: i for i, line in enumerate(move_lines)}
|
41
|
+
self.assertTrue(order_mapping[move1_line] < order_mapping[move2_line])
|
42
|
+
|
43
|
+
# swap dates
|
44
|
+
move2.write({"date": today})
|
45
|
+
move1.write({"date": future})
|
46
|
+
move_lines = self.service._find_location_move_lines()
|
47
|
+
order_mapping = {line: i for i, line in enumerate(move_lines)}
|
48
|
+
self.assertTrue(order_mapping[move1_line] > order_mapping[move2_line])
|
49
|
+
|
50
|
+
# Test by priority
|
51
|
+
self.picking2.write({"priority": "0"})
|
52
|
+
(self.pickings - self.picking2).write({"priority": "1"})
|
53
|
+
|
54
|
+
self.service.work.current_lines_order = "priority"
|
55
|
+
move_lines = self.service._find_location_move_lines()
|
56
|
+
order_mapping = {line: i for i, line in enumerate(move_lines)}
|
57
|
+
# picking2 lines stay at the end as they are low priority
|
58
|
+
self.assertTrue(move1_line in move_lines[-2:])
|
59
|
+
self.assertTrue(move2_line in move_lines[-2:])
|
60
|
+
# but move1_line comes after the other
|
61
|
+
self.assertTrue(order_mapping[move1_line] > order_mapping[move2_line])
|
62
|
+
|
63
|
+
# swap dates again
|
64
|
+
move2.write({"date": future})
|
65
|
+
move1.write({"date": today})
|
66
|
+
# and increase priority
|
67
|
+
self.picking2.write({"priority": "1"})
|
68
|
+
(self.pickings - self.picking2).write({"priority": "0"})
|
69
|
+
move_lines = self.service._find_location_move_lines()
|
70
|
+
order_mapping = {line: i for i, line in enumerate(move_lines)}
|
71
|
+
self.assertEqual(order_mapping[move1_line], 0)
|
72
|
+
self.assertEqual(order_mapping[move2_line], 1)
|
73
|
+
|
74
|
+
def test_list_move_lines_order_by_location(self):
|
75
|
+
self.service.work.current_lines_order = "location"
|
76
|
+
response = self.service.dispatch("list_move_lines", params={})
|
77
|
+
move_lines = self.service._find_location_move_lines()
|
78
|
+
res = [
|
79
|
+
x["location_src"]["name"]
|
80
|
+
for x in response["data"]["select_line"]["move_lines"]
|
81
|
+
]
|
82
|
+
self.assertEqual(res, [x.location_id.name for x in move_lines])
|
83
|
+
self.maxDiff = None
|
84
|
+
self.assert_response_select_line(
|
85
|
+
response,
|
86
|
+
self.zone_location,
|
87
|
+
self.picking1.picking_type_id,
|
88
|
+
move_lines,
|
89
|
+
)
|
90
|
+
|
91
|
+
def test_list_move_lines_order_by_priority(self):
|
92
|
+
response = self.service.dispatch("list_move_lines", params={})
|
93
|
+
move_lines = self.service._find_location_move_lines()
|
94
|
+
self.assert_response_select_line(
|
95
|
+
response,
|
96
|
+
self.zone_location,
|
97
|
+
self.picking_type,
|
98
|
+
move_lines,
|
99
|
+
)
|
100
|
+
|
101
|
+
def test_scan_source_barcode_location_not_allowed(self):
|
102
|
+
"""Scan source: scanned location not allowed."""
|
103
|
+
response = self.service.dispatch(
|
104
|
+
"scan_source",
|
105
|
+
params={"barcode": self.customer_location.barcode},
|
106
|
+
)
|
107
|
+
move_lines = self.service._find_location_move_lines()
|
108
|
+
self.assert_response_select_line(
|
109
|
+
response,
|
110
|
+
self.zone_location,
|
111
|
+
self.picking_type,
|
112
|
+
move_lines,
|
113
|
+
message=self.service.msg_store.location_not_allowed(),
|
114
|
+
)
|
115
|
+
|
116
|
+
def test_scan_source_barcode_location_one_move_line(self):
|
117
|
+
"""Scan source: scanned location 'Zone sub-location 1' contains only
|
118
|
+
one move line, next step 'set_line_destination' expected.
|
119
|
+
"""
|
120
|
+
response = self.service.dispatch(
|
121
|
+
"scan_source",
|
122
|
+
params={"barcode": self.zone_sublocation1.barcode},
|
123
|
+
)
|
124
|
+
move_line = self.picking1.move_line_ids
|
125
|
+
self.assert_response_set_line_destination(
|
126
|
+
response,
|
127
|
+
zone_location=self.zone_location,
|
128
|
+
picking_type=self.picking_type,
|
129
|
+
move_line=move_line,
|
130
|
+
qty_done=10.0,
|
131
|
+
)
|
132
|
+
|
133
|
+
def test_scan_source_barcode_location_two_move_lines_same_product(self):
|
134
|
+
"""Scan source: scanned location 'Zone sub-location 1' contains two lines.
|
135
|
+
|
136
|
+
Lines have the same product/package/lot,
|
137
|
+
they get processed one after the other,
|
138
|
+
next step 'set_line_destination' expected.
|
139
|
+
"""
|
140
|
+
package = self.picking1.move_line_ids.mapped("package_id")[0]
|
141
|
+
new_picking = self._create_picking(lines=[(self.product_a, 20)])
|
142
|
+
self._fill_stock_for_moves(
|
143
|
+
new_picking.move_ids, in_package=package, location=self.zone_sublocation1
|
144
|
+
)
|
145
|
+
new_picking.action_assign()
|
146
|
+
response = self.service.dispatch(
|
147
|
+
"scan_source",
|
148
|
+
params={"barcode": self.zone_sublocation1.barcode},
|
149
|
+
)
|
150
|
+
move_line = self.picking1.move_line_ids
|
151
|
+
self.assert_response_set_line_destination(
|
152
|
+
response,
|
153
|
+
zone_location=self.zone_location,
|
154
|
+
picking_type=self.picking_type,
|
155
|
+
move_line=move_line,
|
156
|
+
qty_done=10.0,
|
157
|
+
)
|
158
|
+
# first line done
|
159
|
+
move_line.qty_done = move_line.reserved_uom_qty
|
160
|
+
# get the next one
|
161
|
+
response = self.service.dispatch(
|
162
|
+
"scan_source",
|
163
|
+
params={"barcode": self.zone_sublocation1.barcode},
|
164
|
+
)
|
165
|
+
move_line = new_picking.move_line_ids
|
166
|
+
self.assert_response_set_line_destination(
|
167
|
+
response,
|
168
|
+
zone_location=self.zone_location,
|
169
|
+
picking_type=self.picking_type,
|
170
|
+
move_line=move_line,
|
171
|
+
qty_done=10.0,
|
172
|
+
)
|
173
|
+
|
174
|
+
def test_scan_source_barcode_location_several_move_lines(self):
|
175
|
+
"""Scan source: scanned location 'Zone sub-location 2' contains two
|
176
|
+
move lines, next step 'select_line' expected with the list of these
|
177
|
+
move lines.
|
178
|
+
"""
|
179
|
+
response = self.service.dispatch(
|
180
|
+
"scan_source",
|
181
|
+
params={"barcode": self.zone_sublocation2.barcode},
|
182
|
+
)
|
183
|
+
move_lines = self.pickings.move_line_ids.filtered(
|
184
|
+
lambda l: l.location_id == self.zone_sublocation2
|
185
|
+
).sorted(
|
186
|
+
self.service.search_move_line._sort_key_move_lines(self.service.lines_order)
|
187
|
+
)
|
188
|
+
self.assert_response_select_line(
|
189
|
+
response,
|
190
|
+
zone_location=self.zone_location,
|
191
|
+
picking_type=self.picking_type,
|
192
|
+
move_lines=move_lines,
|
193
|
+
message=self.service.msg_store.several_products_in_location(
|
194
|
+
self.zone_sublocation2
|
195
|
+
),
|
196
|
+
sublocation=self.zone_sublocation2,
|
197
|
+
location_first=False,
|
198
|
+
)
|
199
|
+
|
200
|
+
def test_scan_source_barcode_package(self):
|
201
|
+
"""Scan source: scanned package has one related move line,
|
202
|
+
next step 'set_line_destination' expected on it.
|
203
|
+
"""
|
204
|
+
package = self.picking1.package_level_ids[0].package_id
|
205
|
+
response = self.service.dispatch(
|
206
|
+
"scan_source",
|
207
|
+
params={"barcode": package.name},
|
208
|
+
)
|
209
|
+
move_lines = self.service._find_location_move_lines(
|
210
|
+
package=package,
|
211
|
+
)
|
212
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
213
|
+
move_line = move_lines[0]
|
214
|
+
self.assert_response_set_line_destination(
|
215
|
+
response,
|
216
|
+
zone_location=self.zone_location,
|
217
|
+
picking_type=self.picking_type,
|
218
|
+
move_line=move_line,
|
219
|
+
qty_done=10.0,
|
220
|
+
)
|
221
|
+
|
222
|
+
def test_scan_source_barcode_package_not_found(self):
|
223
|
+
"""Scan source: scanned package has no related move line,
|
224
|
+
next step 'select_line' expected.
|
225
|
+
"""
|
226
|
+
self.free_package.location_id = self.zone_location
|
227
|
+
pack_code = self.free_package.name
|
228
|
+
response = self.service.dispatch(
|
229
|
+
"scan_source",
|
230
|
+
params={"barcode": pack_code},
|
231
|
+
)
|
232
|
+
move_lines = self.service._find_location_move_lines()
|
233
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
234
|
+
self.assert_response_select_line(
|
235
|
+
response,
|
236
|
+
zone_location=self.zone_location,
|
237
|
+
picking_type=self.picking_type,
|
238
|
+
move_lines=move_lines,
|
239
|
+
message=self.service.msg_store.package_has_no_product_to_take(pack_code),
|
240
|
+
)
|
241
|
+
|
242
|
+
def test_scan_source_barcode_package_not_exist(self):
|
243
|
+
"""Scan source: scanned package that does not exist in the system
|
244
|
+
next step 'select_line' expected.
|
245
|
+
"""
|
246
|
+
response = self.service.dispatch(
|
247
|
+
"scan_source",
|
248
|
+
params={"barcode": "P-Unknown"},
|
249
|
+
)
|
250
|
+
move_lines = self.service._find_location_move_lines()
|
251
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
252
|
+
self.assert_response_select_line(
|
253
|
+
response,
|
254
|
+
zone_location=self.zone_location,
|
255
|
+
picking_type=self.picking_type,
|
256
|
+
move_lines=move_lines,
|
257
|
+
message=self.service.msg_store.barcode_not_found(),
|
258
|
+
)
|
259
|
+
|
260
|
+
def test_scan_source_package_many_products(self):
|
261
|
+
"""Scan source: scanned package that several product, aborting
|
262
|
+
next step 'select_line expected.
|
263
|
+
"""
|
264
|
+
pack = self.picking1.package_level_ids[0].package_id
|
265
|
+
self._update_qty_in_location(pack.location_id, self.product_b, 2, pack)
|
266
|
+
response = self.service.dispatch(
|
267
|
+
"scan_source",
|
268
|
+
params={"barcode": pack.name},
|
269
|
+
)
|
270
|
+
move_lines = self.service._find_location_move_lines(
|
271
|
+
locations=self.zone_sublocation1
|
272
|
+
)
|
273
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
274
|
+
self.assert_response_select_line(
|
275
|
+
response,
|
276
|
+
zone_location=self.zone_location,
|
277
|
+
picking_type=self.picking_type,
|
278
|
+
move_lines=move_lines,
|
279
|
+
package=pack,
|
280
|
+
message=self.service.msg_store.several_products_in_package(pack),
|
281
|
+
location_first=False,
|
282
|
+
)
|
283
|
+
|
284
|
+
def test_scan_source_barcode_package_can_replace_in_line(self):
|
285
|
+
"""Scan source: scanned package has no related line but can replace
|
286
|
+
next step 'select_line' expected with confirmation required set.
|
287
|
+
Scan source: 2nd time the package replace package line with new package
|
288
|
+
next step 'set_line_destination'.
|
289
|
+
"""
|
290
|
+
# Add the same product same package in the same location to use as replacement
|
291
|
+
picking1b = self._create_picking(lines=[(self.product_a, 10)])
|
292
|
+
self._fill_stock_for_moves(
|
293
|
+
picking1b.move_ids, in_package=True, location=self.zone_sublocation1
|
294
|
+
)
|
295
|
+
picking1b.action_assign()
|
296
|
+
package1b = picking1b.package_level_ids[0].package_id
|
297
|
+
picking1b.action_cancel()
|
298
|
+
package1 = self.picking1.package_level_ids[0].package_id
|
299
|
+
# 1st scan
|
300
|
+
response = self.service.dispatch(
|
301
|
+
"scan_source",
|
302
|
+
params={"barcode": package1b.name},
|
303
|
+
)
|
304
|
+
move_lines = self.service._find_location_move_lines(
|
305
|
+
package=package1,
|
306
|
+
)
|
307
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
308
|
+
self.assert_response_select_line(
|
309
|
+
response,
|
310
|
+
zone_location=self.zone_location,
|
311
|
+
picking_type=self.picking_type,
|
312
|
+
move_lines=move_lines,
|
313
|
+
message=self.service.msg_store.package_different_change(),
|
314
|
+
confirmation_required=True,
|
315
|
+
)
|
316
|
+
self.assertEqual(self.picking1.package_level_ids[0].package_id, package1)
|
317
|
+
# 2nd scan
|
318
|
+
response = self.service.dispatch(
|
319
|
+
"scan_source",
|
320
|
+
params={"barcode": package1b.name, "confirmation": True},
|
321
|
+
)
|
322
|
+
self.assert_response_set_line_destination(
|
323
|
+
response,
|
324
|
+
zone_location=self.zone_location,
|
325
|
+
picking_type=self.picking_type,
|
326
|
+
move_line=move_lines[0],
|
327
|
+
message=self.service.msg_store.package_replaced_by_package(
|
328
|
+
package1, package1b
|
329
|
+
),
|
330
|
+
)
|
331
|
+
# Check the package has been changed on the move line
|
332
|
+
self.assertEqual(self.picking1.package_level_ids[0].package_id, package1b)
|
333
|
+
|
334
|
+
def test_scan_source_barcode_product(self):
|
335
|
+
"""Scan source: scanned product has one related move line,
|
336
|
+
next step 'set_line_destination' expected on it.
|
337
|
+
"""
|
338
|
+
response = self.service.dispatch(
|
339
|
+
"scan_source",
|
340
|
+
params={"barcode": self.product_a.barcode},
|
341
|
+
)
|
342
|
+
move_line = self.service._find_location_move_lines(
|
343
|
+
product=self.product_a,
|
344
|
+
)
|
345
|
+
self.assert_response_set_line_destination(
|
346
|
+
response,
|
347
|
+
zone_location=self.zone_location,
|
348
|
+
picking_type=self.picking_type,
|
349
|
+
move_line=move_line,
|
350
|
+
qty_done=10.0,
|
351
|
+
)
|
352
|
+
|
353
|
+
def test_scan_source_barcode_product_not_found(self):
|
354
|
+
"""Scan source: scanned product has no related move line,
|
355
|
+
next step 'select_line' expected.
|
356
|
+
"""
|
357
|
+
response = self.service.dispatch(
|
358
|
+
"scan_source",
|
359
|
+
params={"barcode": self.free_product.barcode},
|
360
|
+
)
|
361
|
+
move_lines = self.service._find_location_move_lines()
|
362
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
363
|
+
self.assert_response_select_line(
|
364
|
+
response,
|
365
|
+
zone_location=self.zone_location,
|
366
|
+
picking_type=self.picking_type,
|
367
|
+
move_lines=move_lines,
|
368
|
+
message=self.service.msg_store.product_not_found_in_pickings(),
|
369
|
+
)
|
370
|
+
|
371
|
+
def test_scan_source_barcode_product_multiple_moves_different_location(self):
|
372
|
+
"""Scan source: scanned product has move lines in multiple sub location.
|
373
|
+
|
374
|
+
next step : 'select_line' expected.
|
375
|
+
|
376
|
+
Then scan a location and a specific line is selected.
|
377
|
+
|
378
|
+
next step : 'set_line_destination'
|
379
|
+
"""
|
380
|
+
# Using picking4 which has a product in two sublocation
|
381
|
+
response = self.service.dispatch(
|
382
|
+
"scan_source",
|
383
|
+
params={"barcode": self.product_e.barcode},
|
384
|
+
)
|
385
|
+
move_lines = self.service._find_location_move_lines(product=self.product_e)
|
386
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
387
|
+
self.assert_response_select_line(
|
388
|
+
response,
|
389
|
+
zone_location=self.zone_location,
|
390
|
+
picking_type=self.picking_type,
|
391
|
+
move_lines=move_lines,
|
392
|
+
product=self.product_e,
|
393
|
+
message=self.service.msg_store.several_move_in_different_location(),
|
394
|
+
)
|
395
|
+
response = self.service.dispatch(
|
396
|
+
"scan_source",
|
397
|
+
params={
|
398
|
+
"barcode": self.zone_sublocation3.barcode,
|
399
|
+
"product_id": self.product_e.id,
|
400
|
+
},
|
401
|
+
)
|
402
|
+
self.assertEqual(response["next_state"], "set_line_destination")
|
403
|
+
move_line = self.service._find_location_move_lines(
|
404
|
+
product=self.product_e, locations=self.zone_sublocation3
|
405
|
+
)
|
406
|
+
self.assert_response_set_line_destination(
|
407
|
+
response,
|
408
|
+
zone_location=self.zone_location,
|
409
|
+
picking_type=self.picking_type,
|
410
|
+
move_line=move_line,
|
411
|
+
qty_done=6.0,
|
412
|
+
)
|
413
|
+
|
414
|
+
def test_scan_source_barcode_location_multiple_moves_different_product(self):
|
415
|
+
"""Scan source: scanned location has move lines with multiple product.
|
416
|
+
|
417
|
+
next step : 'select_line' expected.
|
418
|
+
|
419
|
+
Then scan a product and a specific line is selected.
|
420
|
+
|
421
|
+
next step : 'set_line_destination'
|
422
|
+
"""
|
423
|
+
# Using picking4 which has a product in two sublocation
|
424
|
+
response = self.service.dispatch(
|
425
|
+
"scan_source",
|
426
|
+
params={"barcode": self.zone_sublocation3.barcode},
|
427
|
+
)
|
428
|
+
move_lines = self.service._find_location_move_lines(
|
429
|
+
locations=self.zone_sublocation3
|
430
|
+
)
|
431
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
432
|
+
self.assert_response_select_line(
|
433
|
+
response,
|
434
|
+
zone_location=self.zone_location,
|
435
|
+
picking_type=self.picking_type,
|
436
|
+
move_lines=move_lines,
|
437
|
+
sublocation=self.zone_sublocation3,
|
438
|
+
message=self.service.msg_store.several_products_in_location(
|
439
|
+
self.zone_sublocation3
|
440
|
+
),
|
441
|
+
location_first=False,
|
442
|
+
)
|
443
|
+
response = self.service.dispatch(
|
444
|
+
"scan_source",
|
445
|
+
params={
|
446
|
+
"barcode": self.product_e.barcode,
|
447
|
+
"sublocation_id": self.zone_sublocation3.id,
|
448
|
+
},
|
449
|
+
)
|
450
|
+
self.assertEqual(response["next_state"], "set_line_destination")
|
451
|
+
move_line = self.service._find_location_move_lines(
|
452
|
+
product=self.product_e, locations=self.zone_sublocation3
|
453
|
+
)
|
454
|
+
self.assert_response_set_line_destination(
|
455
|
+
response,
|
456
|
+
zone_location=self.zone_location,
|
457
|
+
picking_type=self.picking_type,
|
458
|
+
move_line=move_line,
|
459
|
+
qty_done=6.0,
|
460
|
+
)
|
461
|
+
|
462
|
+
def test_scan_source_barcode_product_with_multiple_lot(self):
|
463
|
+
"""Scan source: scanned product is found with mulitple lot number.
|
464
|
+
|
465
|
+
next step : 'select_line' expected.
|
466
|
+
"""
|
467
|
+
# Product C has already one lot from test_zone_picking_base.py
|
468
|
+
# So lets add one more lot for that product in same location.
|
469
|
+
pick = self._create_picking(lines=[(self.product_c, 10)])
|
470
|
+
self._fill_stock_for_moves(
|
471
|
+
pick.move_ids, in_lot=True, location=self.zone_sublocation2
|
472
|
+
)
|
473
|
+
pick.action_assign()
|
474
|
+
response = self.service.dispatch(
|
475
|
+
"scan_source",
|
476
|
+
params={"barcode": self.product_c.barcode},
|
477
|
+
)
|
478
|
+
move_lines = self.service._find_location_move_lines(product=self.product_c)
|
479
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
480
|
+
self.assert_response_select_line(
|
481
|
+
response,
|
482
|
+
zone_location=self.zone_location,
|
483
|
+
picking_type=self.picking_type,
|
484
|
+
move_lines=move_lines,
|
485
|
+
product=self.product_c,
|
486
|
+
message=self.service.msg_store.several_move_with_different_lot(),
|
487
|
+
)
|
488
|
+
|
489
|
+
def test_scan_source_barcode_lot(self):
|
490
|
+
"""Scan source: scanned lot has one related move line,
|
491
|
+
next step 'set_line_destination' expected on it.
|
492
|
+
"""
|
493
|
+
# Product C has already one lot from test_zone_picking_base.py
|
494
|
+
# So lets add one more lot for that product in a different location.
|
495
|
+
pick = self._create_picking(lines=[(self.product_c, 10)])
|
496
|
+
self._fill_stock_for_moves(
|
497
|
+
pick.move_ids, in_lot=True, location=self.zone_sublocation1
|
498
|
+
)
|
499
|
+
pick.action_assign()
|
500
|
+
lot = self.picking2.move_line_ids.lot_id[0]
|
501
|
+
response = self.service.dispatch(
|
502
|
+
"scan_source",
|
503
|
+
params={"barcode": lot.name},
|
504
|
+
)
|
505
|
+
move_lines = self.service._find_location_move_lines(lot=lot)
|
506
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
507
|
+
move_line = move_lines[0]
|
508
|
+
self.assert_response_set_line_destination(
|
509
|
+
response,
|
510
|
+
zone_location=self.zone_location,
|
511
|
+
picking_type=self.picking_type,
|
512
|
+
move_line=move_line,
|
513
|
+
qty_done=10.0,
|
514
|
+
)
|
515
|
+
|
516
|
+
def test_scan_source_barcode_lot_in_multiple_location(self):
|
517
|
+
"""Scan source: scanned lot is in multiple location
|
518
|
+
next step 'select_line' expected on it.
|
519
|
+
"""
|
520
|
+
# Picking 2 has already some lot from test_zone_picking_base.py
|
521
|
+
# So lets add in the same lot the same product in another location.
|
522
|
+
lot = self.picking2.move_line_ids.lot_id[0]
|
523
|
+
picking = self._create_picking(lines=[(lot.product_id, 2)])
|
524
|
+
self._fill_stock_for_moves(
|
525
|
+
picking.move_ids, in_lot=lot, location=self.zone_sublocation3
|
526
|
+
)
|
527
|
+
picking.action_assign()
|
528
|
+
response = self.service.dispatch(
|
529
|
+
"scan_source",
|
530
|
+
params={"barcode": lot.name},
|
531
|
+
)
|
532
|
+
# FIX ME: need to filter lines only on lot scanned !!
|
533
|
+
move_lines = self.service._find_location_move_lines()
|
534
|
+
# move_lines = self.service._find_location_move_lines(lot=lot)
|
535
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
536
|
+
self.assert_response_select_line(
|
537
|
+
response,
|
538
|
+
zone_location=self.zone_location,
|
539
|
+
picking_type=self.picking_type,
|
540
|
+
move_lines=move_lines,
|
541
|
+
message=self.service.msg_store.several_move_in_different_location(),
|
542
|
+
)
|
543
|
+
|
544
|
+
def test_scan_source_barcode_lot_not_found(self):
|
545
|
+
"""Scan source: scanned lot has no related move line,
|
546
|
+
next step 'select_line' expected.
|
547
|
+
"""
|
548
|
+
response = self.service.dispatch(
|
549
|
+
"scan_source",
|
550
|
+
params={"barcode": self.free_lot.name},
|
551
|
+
)
|
552
|
+
move_lines = self.service._find_location_move_lines()
|
553
|
+
move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
|
554
|
+
self.assert_response_select_line(
|
555
|
+
response,
|
556
|
+
zone_location=self.zone_location,
|
557
|
+
picking_type=self.picking_type,
|
558
|
+
move_lines=move_lines,
|
559
|
+
message=self.service.msg_store.lot_not_found_in_pickings(),
|
560
|
+
)
|
561
|
+
|
562
|
+
def test_scan_source_barcode_not_found(self):
|
563
|
+
response = self.service.dispatch(
|
564
|
+
"scan_source",
|
565
|
+
params={
|
566
|
+
"zone_location_id": self.zone_location.id,
|
567
|
+
"picking_type_id": self.picking_type.id,
|
568
|
+
"barcode": "UNKNOWN",
|
569
|
+
},
|
570
|
+
)
|
571
|
+
move_lines = self.service._find_location_move_lines()
|
572
|
+
self.assert_response_select_line(
|
573
|
+
response,
|
574
|
+
zone_location=self.zone_location,
|
575
|
+
picking_type=self.picking_type,
|
576
|
+
move_lines=move_lines,
|
577
|
+
message=self.service.msg_store.barcode_not_found(),
|
578
|
+
)
|
579
|
+
|
580
|
+
def test_scan_source_multi_users(self):
|
581
|
+
"""First user scans the source location 'Zone sub-location 1' containing
|
582
|
+
only one move line, then processes the next step 'set_line_destination'.
|
583
|
+
|
584
|
+
The second user scans the same source location, and should not find any line.
|
585
|
+
"""
|
586
|
+
# The first user starts to process the only line available
|
587
|
+
# - scan source
|
588
|
+
response = self.service.scan_source(
|
589
|
+
self.zone_sublocation1.barcode,
|
590
|
+
)
|
591
|
+
move_line = self.picking1.move_line_ids
|
592
|
+
self.assertEqual(response["next_state"], "set_line_destination")
|
593
|
+
# - set destination
|
594
|
+
self.service.set_destination(
|
595
|
+
move_line.id,
|
596
|
+
self.free_package.name,
|
597
|
+
move_line.reserved_uom_qty,
|
598
|
+
)
|
599
|
+
self.assertEqual(move_line.shopfloor_user_id, self.env.user)
|
600
|
+
# The second user scans the same source location
|
601
|
+
env = self.env(user=self.stock_user2)
|
602
|
+
with self.work_on_services(
|
603
|
+
env=env,
|
604
|
+
menu=self.menu,
|
605
|
+
profile=self.profile,
|
606
|
+
current_zone_location=self.zone_location,
|
607
|
+
current_picking_type=self.picking_type,
|
608
|
+
) as work:
|
609
|
+
service = work.component(usage="zone_picking")
|
610
|
+
response = service.scan_source(
|
611
|
+
self.zone_sublocation1.barcode,
|
612
|
+
)
|
613
|
+
self.assertEqual(response["next_state"], "select_line")
|
614
|
+
self.assertEqual(
|
615
|
+
response["message"],
|
616
|
+
self.service.msg_store.wrong_record(self.zone_sublocation1),
|
617
|
+
)
|
618
|
+
|
619
|
+
def test_prepare_unload_buffer_empty(self):
|
620
|
+
# unload goods
|
621
|
+
response = self.service.dispatch(
|
622
|
+
"prepare_unload",
|
623
|
+
params={},
|
624
|
+
)
|
625
|
+
# check response
|
626
|
+
move_lines = self.service._find_location_move_lines()
|
627
|
+
self.assert_response_select_line(
|
628
|
+
response,
|
629
|
+
self.zone_location,
|
630
|
+
self.picking_type,
|
631
|
+
move_lines,
|
632
|
+
)
|
633
|
+
|
634
|
+
def test_prepare_unload_buffer_one_line(self):
|
635
|
+
# scan a destination package to get something in the buffer
|
636
|
+
move_line = self.picking1.move_line_ids
|
637
|
+
response = self.service.dispatch(
|
638
|
+
"set_destination",
|
639
|
+
params={
|
640
|
+
"move_line_id": move_line.id,
|
641
|
+
"barcode": self.free_package.name,
|
642
|
+
"quantity": move_line.reserved_uom_qty,
|
643
|
+
},
|
644
|
+
)
|
645
|
+
# unload goods
|
646
|
+
response = self.service.dispatch(
|
647
|
+
"prepare_unload",
|
648
|
+
params={},
|
649
|
+
)
|
650
|
+
# check response
|
651
|
+
self.assert_response_unload_set_destination(
|
652
|
+
response,
|
653
|
+
self.zone_location,
|
654
|
+
self.picking_type,
|
655
|
+
move_line,
|
656
|
+
)
|
657
|
+
|
658
|
+
def test_prepare_unload_buffer_multi_line_same_destination(self):
|
659
|
+
# scan a destination package for some move lines
|
660
|
+
# to get several lines in the buffer (which have the same destination)
|
661
|
+
self.another_package = self.env["stock.quant.package"].create(
|
662
|
+
{"name": "ANOTHER_PACKAGE"}
|
663
|
+
)
|
664
|
+
move_lines = self.picking5.move_line_ids
|
665
|
+
self.assertEqual(move_lines.location_dest_id, self.packing_location)
|
666
|
+
for move_line, package_dest in zip(
|
667
|
+
move_lines, self.free_package | self.another_package
|
668
|
+
):
|
669
|
+
self.service.dispatch(
|
670
|
+
"set_destination",
|
671
|
+
params={
|
672
|
+
"move_line_id": move_line.id,
|
673
|
+
"barcode": package_dest.name,
|
674
|
+
"quantity": move_line.reserved_uom_qty,
|
675
|
+
},
|
676
|
+
)
|
677
|
+
# unload goods
|
678
|
+
response = self.service.dispatch(
|
679
|
+
"prepare_unload",
|
680
|
+
params={},
|
681
|
+
)
|
682
|
+
# check response
|
683
|
+
self.assert_response_unload_all(
|
684
|
+
response,
|
685
|
+
self.zone_location,
|
686
|
+
self.picking_type,
|
687
|
+
move_lines,
|
688
|
+
)
|
689
|
+
|
690
|
+
def test_list_move_lines_empty_location(self):
|
691
|
+
response = self.service.dispatch(
|
692
|
+
"list_move_lines",
|
693
|
+
params={"order": "location"},
|
694
|
+
)
|
695
|
+
# TODO: order by location?
|
696
|
+
move_lines = self.service._find_location_move_lines()
|
697
|
+
self.assert_response_select_line(
|
698
|
+
response,
|
699
|
+
self.zone_location,
|
700
|
+
self.picking_type,
|
701
|
+
move_lines,
|
702
|
+
)
|
703
|
+
data_move_lines = response["data"]["select_line"]["move_lines"]
|
704
|
+
# Check that the move line in "Zone sub-location 1" is about to empty
|
705
|
+
# its location if we process it
|
706
|
+
data_move_line = [
|
707
|
+
m
|
708
|
+
for m in data_move_lines
|
709
|
+
if m["location_src"]["barcode"] == "ZONE_SUBLOCATION_1"
|
710
|
+
][0]
|
711
|
+
self.assertTrue(data_move_line["location_will_be_empty"])
|
712
|
+
# Same check with the internal method
|
713
|
+
move_line = self.env["stock.move.line"].browse(data_move_line["id"])
|
714
|
+
location_src = move_line.location_id
|
715
|
+
move_line_will_empty_location = location_src.planned_qty_in_location_is_empty(
|
716
|
+
move_lines=move_line
|
717
|
+
)
|
718
|
+
self.assertTrue(move_line_will_empty_location)
|
719
|
+
# But if we check the location without giving the move line as parameter,
|
720
|
+
# knowing that this move line hasn't its 'qty_done' field filled,
|
721
|
+
# the location won't be considered empty with such pending move line
|
722
|
+
move_line_will_empty_location = location_src.planned_qty_in_location_is_empty()
|
723
|
+
self.assertFalse(move_line_will_empty_location)
|