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,121 @@
|
|
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
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
class ZonePickingStockIssueCase(ZonePickingCommonCase):
|
8
|
+
"""Tests for endpoint used from stock_issue
|
9
|
+
|
10
|
+
* /stock_issue
|
11
|
+
|
12
|
+
"""
|
13
|
+
|
14
|
+
def setUp(self):
|
15
|
+
super().setUp()
|
16
|
+
self.service.work.current_picking_type = self.picking1.picking_type_id
|
17
|
+
|
18
|
+
def test_stock_issue_wrong_parameters(self):
|
19
|
+
response = self.service.dispatch(
|
20
|
+
"stock_issue",
|
21
|
+
params={"move_line_id": 1234567890},
|
22
|
+
)
|
23
|
+
self.assert_response_start(
|
24
|
+
response,
|
25
|
+
message=self.service.msg_store.record_not_found(),
|
26
|
+
)
|
27
|
+
|
28
|
+
def test_stock_issue_no_more_reservation(self):
|
29
|
+
zone_location = self.zone_location
|
30
|
+
picking_type = self.picking1.picking_type_id
|
31
|
+
move_line = self.picking1.move_line_ids[0]
|
32
|
+
move = move_line.move_id
|
33
|
+
response = self.service.dispatch(
|
34
|
+
"stock_issue",
|
35
|
+
params={"move_line_id": move_line.id},
|
36
|
+
)
|
37
|
+
self.assertFalse(move_line.exists())
|
38
|
+
self.assertFalse(move.move_line_ids)
|
39
|
+
move_lines = self.service._find_location_move_lines()
|
40
|
+
self.assert_response_select_line(
|
41
|
+
response,
|
42
|
+
zone_location,
|
43
|
+
picking_type,
|
44
|
+
move_lines,
|
45
|
+
)
|
46
|
+
|
47
|
+
def test_stock_issue1(self):
|
48
|
+
"""Once the stock issue is done, the move can't be reserved anymore."""
|
49
|
+
zone_location = self.zone_location
|
50
|
+
picking_type = self.picking1.picking_type_id
|
51
|
+
move_line = self.picking1.move_line_ids[0]
|
52
|
+
move = move_line.move_id
|
53
|
+
response = self.service.dispatch(
|
54
|
+
"stock_issue",
|
55
|
+
params={"move_line_id": move_line.id},
|
56
|
+
)
|
57
|
+
self.assertFalse(move_line.exists())
|
58
|
+
self.assertFalse(move.move_line_ids)
|
59
|
+
move_lines = self.service._find_location_move_lines()
|
60
|
+
self.assert_response_select_line(
|
61
|
+
response,
|
62
|
+
zone_location,
|
63
|
+
picking_type,
|
64
|
+
move_lines,
|
65
|
+
)
|
66
|
+
|
67
|
+
def test_stock_issue2(self):
|
68
|
+
"""Once the stock issue is done, the move has been reserved again."""
|
69
|
+
zone_location = self.zone_location
|
70
|
+
picking_type = self.picking1.picking_type_id
|
71
|
+
move_line = self.picking1.move_line_ids[0]
|
72
|
+
location = move_line.location_id
|
73
|
+
move = move_line.move_id
|
74
|
+
quants_before = self.env["stock.quant"].search(
|
75
|
+
[("location_id", "=", location.id), ("product_id", "=", move.product_id.id)]
|
76
|
+
)
|
77
|
+
# Increase the quantity in the current location
|
78
|
+
self._update_qty_in_location(location, move.product_id, 100)
|
79
|
+
response = self.service.dispatch(
|
80
|
+
"stock_issue",
|
81
|
+
params={"move_line_id": move_line.id},
|
82
|
+
)
|
83
|
+
self.assertFalse(move_line.exists())
|
84
|
+
self.assertTrue(move.move_line_ids)
|
85
|
+
self.assertEqual(move.move_line_ids.location_id, location)
|
86
|
+
self.assert_response_set_line_destination(
|
87
|
+
response,
|
88
|
+
zone_location,
|
89
|
+
picking_type,
|
90
|
+
move.move_line_ids,
|
91
|
+
)
|
92
|
+
# Check the inventory
|
93
|
+
quants_after = self.env["stock.quant"].search(
|
94
|
+
[("location_id", "=", location.id), ("product_id", "=", move.product_id.id)]
|
95
|
+
)
|
96
|
+
inventory_quant = quants_after - quants_before
|
97
|
+
self.assertTrue(inventory_quant)
|
98
|
+
|
99
|
+
def test_stock_issue3(self):
|
100
|
+
"""Once the stock issue is done, the move has been reserved again
|
101
|
+
but from another location.
|
102
|
+
"""
|
103
|
+
zone_location = self.zone_location
|
104
|
+
picking_type = self.picking1.picking_type_id
|
105
|
+
move_line = self.picking1.move_line_ids[0]
|
106
|
+
move = move_line.move_id
|
107
|
+
# Put some quantity in another location to get a new reservations from there
|
108
|
+
self._update_qty_in_location(self.zone_sublocation2, move.product_id, 10)
|
109
|
+
response = self.service.dispatch(
|
110
|
+
"stock_issue",
|
111
|
+
params={"move_line_id": move_line.id},
|
112
|
+
)
|
113
|
+
self.assertFalse(move_line.exists())
|
114
|
+
self.assertTrue(move.move_line_ids)
|
115
|
+
self.assertEqual(move.move_line_ids.location_id, self.zone_sublocation2)
|
116
|
+
self.assert_response_set_line_destination(
|
117
|
+
response,
|
118
|
+
zone_location,
|
119
|
+
picking_type,
|
120
|
+
move.move_line_ids,
|
121
|
+
)
|
@@ -0,0 +1,353 @@
|
|
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
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
class ZonePickingUnloadAllCase(ZonePickingCommonCase):
|
8
|
+
"""Tests for endpoint used from unload_all
|
9
|
+
|
10
|
+
* /set_destination_all
|
11
|
+
* /unload_split
|
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_all_different_destination(self):
|
20
|
+
zone_location = self.zone_location
|
21
|
+
picking_type = self.picking1.picking_type_id
|
22
|
+
move_line1 = self.picking5.move_line_ids[0]
|
23
|
+
move_line2 = self.picking5.move_line_ids[1]
|
24
|
+
another_package = self.env["stock.quant.package"].create(
|
25
|
+
{"name": "ANOTHER_PACKAGE"}
|
26
|
+
)
|
27
|
+
# change the destination location of one move line
|
28
|
+
move_line2.location_dest_id = self.zone_sublocation3
|
29
|
+
# set the destination package on lines
|
30
|
+
self.service._set_destination_package(
|
31
|
+
move_line1,
|
32
|
+
move_line1.reserved_uom_qty,
|
33
|
+
self.free_package,
|
34
|
+
)
|
35
|
+
self.service._set_destination_package(
|
36
|
+
move_line2,
|
37
|
+
move_line2.reserved_uom_qty,
|
38
|
+
another_package,
|
39
|
+
)
|
40
|
+
# set destination location for all lines in the buffer
|
41
|
+
response = self.service.dispatch(
|
42
|
+
"set_destination_all",
|
43
|
+
params={"barcode": self.packing_location.barcode},
|
44
|
+
)
|
45
|
+
# check response
|
46
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
47
|
+
self.assert_response_unload_all(
|
48
|
+
response,
|
49
|
+
zone_location,
|
50
|
+
picking_type,
|
51
|
+
buffer_lines,
|
52
|
+
message=self.service.msg_store.lines_different_dest_location(),
|
53
|
+
)
|
54
|
+
|
55
|
+
def test_set_destination_all_confirm_destination(self):
|
56
|
+
zone_location = self.zone_location
|
57
|
+
picking_type = self.picking1.picking_type_id
|
58
|
+
move_line1 = self.picking5.move_line_ids[0]
|
59
|
+
move_line2 = self.picking5.move_line_ids[1]
|
60
|
+
another_package = self.env["stock.quant.package"].create(
|
61
|
+
{"name": "ANOTHER_PACKAGE"}
|
62
|
+
)
|
63
|
+
packing_sublocation1 = (
|
64
|
+
self.env["stock.location"]
|
65
|
+
.sudo()
|
66
|
+
.create(
|
67
|
+
{
|
68
|
+
"name": "Packing sublocation-1",
|
69
|
+
"location_id": self.packing_location.id,
|
70
|
+
"barcode": "PACKING_SUBLOCATION_1",
|
71
|
+
}
|
72
|
+
)
|
73
|
+
)
|
74
|
+
packing_sublocation2 = (
|
75
|
+
self.env["stock.location"]
|
76
|
+
.sudo()
|
77
|
+
.create(
|
78
|
+
{
|
79
|
+
"name": "Packing sublocation-2",
|
80
|
+
"location_id": self.packing_location.id,
|
81
|
+
"barcode": "PACKING_SUBLOCATION_2",
|
82
|
+
}
|
83
|
+
)
|
84
|
+
)
|
85
|
+
# set the destination package on lines
|
86
|
+
self.service._set_destination_package(
|
87
|
+
move_line1,
|
88
|
+
move_line1.reserved_uom_qty,
|
89
|
+
self.free_package,
|
90
|
+
)
|
91
|
+
self.service._set_destination_package(
|
92
|
+
move_line2,
|
93
|
+
move_line2.reserved_uom_qty,
|
94
|
+
another_package,
|
95
|
+
)
|
96
|
+
# set an allowed destination location (inside the picking type default
|
97
|
+
# destination location) for all lines in the buffer with a non-expected
|
98
|
+
# one, meaning a destination which is not a child of the current buffer
|
99
|
+
# lines destination
|
100
|
+
(move_line1 | move_line2).location_dest_id = packing_sublocation1
|
101
|
+
response = self.service.dispatch(
|
102
|
+
"set_destination_all",
|
103
|
+
params={"barcode": packing_sublocation2.barcode},
|
104
|
+
)
|
105
|
+
# check response: this destination needs the user confirmation
|
106
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
107
|
+
self.assert_response_unload_all(
|
108
|
+
response,
|
109
|
+
zone_location,
|
110
|
+
picking_type,
|
111
|
+
buffer_lines,
|
112
|
+
message=self.service.msg_store.confirm_location_changed(
|
113
|
+
packing_sublocation1,
|
114
|
+
packing_sublocation2,
|
115
|
+
),
|
116
|
+
confirmation_required=True,
|
117
|
+
)
|
118
|
+
# set an allowed destination location (inside the picking type default
|
119
|
+
# destination location) for all lines in the buffer with an expected one
|
120
|
+
# meaning a destination which is a child of the current buffer lines
|
121
|
+
# destination
|
122
|
+
response = self.service.dispatch(
|
123
|
+
"set_destination_all",
|
124
|
+
params={"barcode": packing_sublocation1.barcode},
|
125
|
+
)
|
126
|
+
# check response: OK
|
127
|
+
move_lines = self.service._find_location_move_lines()
|
128
|
+
self.assert_response_select_line(
|
129
|
+
response,
|
130
|
+
zone_location,
|
131
|
+
picking_type,
|
132
|
+
move_lines,
|
133
|
+
message=self.service.msg_store.buffer_complete(),
|
134
|
+
)
|
135
|
+
|
136
|
+
def test_set_destination_all_ok(self):
|
137
|
+
zone_location = self.zone_location
|
138
|
+
picking_type = self.picking1.picking_type_id
|
139
|
+
move_line1 = self.picking5.move_line_ids[0]
|
140
|
+
move_line2 = self.picking5.move_line_ids[1]
|
141
|
+
another_package = self.env["stock.quant.package"].create(
|
142
|
+
{"name": "ANOTHER_PACKAGE"}
|
143
|
+
)
|
144
|
+
# set the destination package on lines
|
145
|
+
self.service._set_destination_package(
|
146
|
+
move_line1,
|
147
|
+
move_line1.reserved_uom_qty,
|
148
|
+
self.free_package,
|
149
|
+
)
|
150
|
+
self.service._set_destination_package(
|
151
|
+
move_line2,
|
152
|
+
move_line2.reserved_uom_qty,
|
153
|
+
another_package,
|
154
|
+
)
|
155
|
+
# set destination location for all lines in the buffer
|
156
|
+
response = self.service.dispatch(
|
157
|
+
"set_destination_all",
|
158
|
+
params={"barcode": self.packing_location.barcode},
|
159
|
+
)
|
160
|
+
# check data
|
161
|
+
self.assertEqual(self.picking5.state, "done")
|
162
|
+
# buffer should be empty
|
163
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
164
|
+
self.assertFalse(buffer_lines)
|
165
|
+
# check response
|
166
|
+
move_lines = self.service._find_location_move_lines()
|
167
|
+
self.assert_response_select_line(
|
168
|
+
response,
|
169
|
+
zone_location,
|
170
|
+
picking_type,
|
171
|
+
move_lines,
|
172
|
+
message=self.service.msg_store.buffer_complete(),
|
173
|
+
)
|
174
|
+
|
175
|
+
def test_set_destination_all_partial_qty_done_ok(self):
|
176
|
+
zone_location = self.zone_location
|
177
|
+
picking_type = self.picking6.picking_type_id
|
178
|
+
move_g = self.picking6.move_ids.filtered(
|
179
|
+
lambda m: m.product_id == self.product_g
|
180
|
+
)
|
181
|
+
move_h = self.picking6.move_ids.filtered(
|
182
|
+
lambda m: m.product_id == self.product_h
|
183
|
+
)
|
184
|
+
self.assertEqual(move_g.state, "assigned")
|
185
|
+
self.assertEqual(move_h.state, "partially_available")
|
186
|
+
move_line_g = move_g.move_line_ids
|
187
|
+
move_line_h = move_h.move_line_ids
|
188
|
+
another_package = self.env["stock.quant.package"].create(
|
189
|
+
{"name": "ANOTHER_PACKAGE"}
|
190
|
+
)
|
191
|
+
# set the destination package on lines
|
192
|
+
self.service._set_destination_package(
|
193
|
+
move_line_g,
|
194
|
+
move_line_g.reserved_uom_qty,
|
195
|
+
self.free_package,
|
196
|
+
)
|
197
|
+
self.service._set_destination_package(
|
198
|
+
move_line_h,
|
199
|
+
move_line_h.reserved_uom_qty,
|
200
|
+
another_package, # partial qty
|
201
|
+
)
|
202
|
+
# set destination location for all lines in the buffer
|
203
|
+
response = self.service.dispatch(
|
204
|
+
"set_destination_all",
|
205
|
+
params={"barcode": self.packing_location.barcode},
|
206
|
+
)
|
207
|
+
# check data
|
208
|
+
# picking validated
|
209
|
+
self.assertEqual(move_line_g.state, "done")
|
210
|
+
self.assertEqual(move_line_g.picking_id.state, "done")
|
211
|
+
self.assertEqual(move_line_g.qty_done, 6)
|
212
|
+
self.assertEqual(move_line_h.state, "done")
|
213
|
+
self.assertEqual(move_line_h.picking_id.state, "done")
|
214
|
+
self.assertEqual(move_line_h.qty_done, 3)
|
215
|
+
# current picking (backorder)
|
216
|
+
backorder = (move_line_g | move_line_h).picking_id.backorder_id
|
217
|
+
self.assertEqual(backorder, self.picking6)
|
218
|
+
self.assertEqual(backorder.state, "confirmed")
|
219
|
+
self.assertEqual(backorder.move_ids.product_id, self.product_h)
|
220
|
+
self.assertEqual(backorder.move_ids.product_uom_qty, 3)
|
221
|
+
self.assertFalse(backorder.move_line_ids)
|
222
|
+
# buffer should be empty
|
223
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
224
|
+
self.assertFalse(buffer_lines)
|
225
|
+
# check response
|
226
|
+
move_lines = self.service._find_location_move_lines()
|
227
|
+
self.assert_response_select_line(
|
228
|
+
response,
|
229
|
+
zone_location,
|
230
|
+
picking_type,
|
231
|
+
move_lines,
|
232
|
+
message=self.service.msg_store.buffer_complete(),
|
233
|
+
)
|
234
|
+
|
235
|
+
def test_set_destination_all_location_not_allowed(self):
|
236
|
+
zone_location = self.zone_location
|
237
|
+
picking_type = self.picking1.picking_type_id
|
238
|
+
move_line = self.picking1.move_line_ids
|
239
|
+
# set the destination package on lines
|
240
|
+
self.service._set_destination_package(
|
241
|
+
move_line,
|
242
|
+
move_line.reserved_uom_qty,
|
243
|
+
self.free_package,
|
244
|
+
)
|
245
|
+
response = self.service.dispatch(
|
246
|
+
"set_destination_all",
|
247
|
+
params={"barcode": self.customer_location.barcode},
|
248
|
+
)
|
249
|
+
# check response
|
250
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
251
|
+
self.assert_response_unload_all(
|
252
|
+
response,
|
253
|
+
zone_location,
|
254
|
+
picking_type,
|
255
|
+
buffer_lines,
|
256
|
+
message=self.service.msg_store.location_not_allowed(),
|
257
|
+
)
|
258
|
+
|
259
|
+
def test_set_destination_all_location_not_found(self):
|
260
|
+
zone_location = self.zone_location
|
261
|
+
picking_type = self.picking1.picking_type_id
|
262
|
+
move_line = self.picking1.move_line_ids
|
263
|
+
# set the destination package on lines
|
264
|
+
self.service._set_destination_package(
|
265
|
+
move_line,
|
266
|
+
move_line.reserved_uom_qty,
|
267
|
+
self.free_package,
|
268
|
+
)
|
269
|
+
response = self.service.dispatch(
|
270
|
+
"set_destination_all",
|
271
|
+
params={"barcode": "UNKNOWN"},
|
272
|
+
)
|
273
|
+
# check response
|
274
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
275
|
+
self.assert_response_unload_all(
|
276
|
+
response,
|
277
|
+
zone_location,
|
278
|
+
picking_type,
|
279
|
+
buffer_lines,
|
280
|
+
message=self.service.msg_store.no_location_found(),
|
281
|
+
)
|
282
|
+
|
283
|
+
def test_unload_split_buffer_empty(self):
|
284
|
+
zone_location = self.zone_location
|
285
|
+
picking_type = self.picking1.picking_type_id
|
286
|
+
response = self.service.dispatch(
|
287
|
+
"unload_split",
|
288
|
+
params={},
|
289
|
+
)
|
290
|
+
# check response
|
291
|
+
move_lines = self.service._find_location_move_lines()
|
292
|
+
self.assert_response_select_line(
|
293
|
+
response,
|
294
|
+
zone_location,
|
295
|
+
picking_type,
|
296
|
+
move_lines,
|
297
|
+
message=self.service.msg_store.buffer_complete(),
|
298
|
+
)
|
299
|
+
|
300
|
+
def test_unload_split_buffer_one_line(self):
|
301
|
+
zone_location = self.zone_location
|
302
|
+
picking_type = self.picking1.picking_type_id
|
303
|
+
move_line = self.picking1.move_line_ids
|
304
|
+
# put one line in the buffer
|
305
|
+
self.service._set_destination_package(
|
306
|
+
move_line,
|
307
|
+
move_line.reserved_uom_qty,
|
308
|
+
self.free_package,
|
309
|
+
)
|
310
|
+
response = self.service.dispatch(
|
311
|
+
"unload_split",
|
312
|
+
params={},
|
313
|
+
)
|
314
|
+
# check response
|
315
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
316
|
+
self.assert_response_unload_set_destination(
|
317
|
+
response,
|
318
|
+
zone_location,
|
319
|
+
picking_type,
|
320
|
+
buffer_lines,
|
321
|
+
)
|
322
|
+
|
323
|
+
def test_unload_split_buffer_multi_lines(self):
|
324
|
+
zone_location = self.zone_location
|
325
|
+
picking_type = self.picking5.picking_type_id
|
326
|
+
move_line = self.picking5.move_line_ids
|
327
|
+
# put several lines in the buffer
|
328
|
+
self.another_package = self.env["stock.quant.package"].create(
|
329
|
+
{"name": "ANOTHER_PACKAGE"}
|
330
|
+
)
|
331
|
+
for move_line, package_dest in zip(
|
332
|
+
self.picking5.move_line_ids, self.free_package | self.another_package
|
333
|
+
):
|
334
|
+
self.service._set_destination_package(
|
335
|
+
move_line,
|
336
|
+
move_line.reserved_uom_qty,
|
337
|
+
package_dest,
|
338
|
+
)
|
339
|
+
response = self.service.dispatch(
|
340
|
+
"unload_split",
|
341
|
+
params={},
|
342
|
+
)
|
343
|
+
# check response
|
344
|
+
buffer_lines = self.service._find_buffer_move_lines()
|
345
|
+
completion_info = self.service._actions_for("completion.info")
|
346
|
+
completion_info_popup = completion_info.popup(buffer_lines)
|
347
|
+
self.assert_response_unload_single(
|
348
|
+
response,
|
349
|
+
zone_location,
|
350
|
+
picking_type,
|
351
|
+
buffer_lines[0],
|
352
|
+
popup=completion_info_popup,
|
353
|
+
)
|
@@ -0,0 +1,113 @@
|
|
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
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
class ZonePickingUnloadBufferLinesCase(ZonePickingCommonCase):
|
8
|
+
"""Tests buffer lines to unload are retrieved properly.
|
9
|
+
|
10
|
+
Buffer lines are the lines processed during zone picking work.
|
11
|
+
At the end of her/his work, the user can unload all processed lines
|
12
|
+
in one or more destination.
|
13
|
+
|
14
|
+
Here we make sure all the lines are processable.
|
15
|
+
"""
|
16
|
+
|
17
|
+
def setUp(self):
|
18
|
+
super().setUp()
|
19
|
+
self.service.work.current_picking_type = self.picking1.picking_type_id
|
20
|
+
|
21
|
+
def test_find_buffer_lines1(self):
|
22
|
+
move_lines = (
|
23
|
+
self.picking1.move_line_ids
|
24
|
+
| self.picking2.move_line_ids
|
25
|
+
| self.picking3.move_line_ids
|
26
|
+
| self.picking4.move_line_ids
|
27
|
+
)
|
28
|
+
zones = move_lines.mapped("location_id")
|
29
|
+
# we work on lines coming from 4 different locations
|
30
|
+
self.assertEqual(len(zones), 4)
|
31
|
+
# Process them all (simulate)
|
32
|
+
for i, line in enumerate(move_lines):
|
33
|
+
dest_package = self.env["stock.quant.package"].create(
|
34
|
+
{"name": f"TEST PKG {i}"}
|
35
|
+
)
|
36
|
+
self.service._set_destination_package(
|
37
|
+
line,
|
38
|
+
line.reserved_uom_qty,
|
39
|
+
dest_package,
|
40
|
+
)
|
41
|
+
|
42
|
+
# We can unload all the lines no matter which zone we are before unload
|
43
|
+
for zone in zones:
|
44
|
+
self.service.work.current_zone_location = zone
|
45
|
+
self.assertEqual(self.service._find_buffer_move_lines(), move_lines)
|
46
|
+
|
47
|
+
def test_find_buffer_lines2(self):
|
48
|
+
# Skip lines from picking1
|
49
|
+
move_lines = (
|
50
|
+
self.picking2.move_line_ids
|
51
|
+
| self.picking3.move_line_ids
|
52
|
+
| self.picking4.move_line_ids
|
53
|
+
)
|
54
|
+
zones = move_lines.mapped("location_id")
|
55
|
+
# we work on lines coming from 3 different locations
|
56
|
+
self.assertEqual(len(zones), 3)
|
57
|
+
# Process them all (simulate)
|
58
|
+
for i, line in enumerate(move_lines):
|
59
|
+
dest_package = self.env["stock.quant.package"].create(
|
60
|
+
{"name": f"TEST PKG {i}"}
|
61
|
+
)
|
62
|
+
self.service._set_destination_package(
|
63
|
+
line,
|
64
|
+
line.reserved_uom_qty,
|
65
|
+
dest_package,
|
66
|
+
)
|
67
|
+
|
68
|
+
# We can unload all the lines no matter which zone we are before unload
|
69
|
+
for zone in zones:
|
70
|
+
self.service.work.current_zone_location = zone
|
71
|
+
self.assertEqual(self.service._find_buffer_move_lines(), move_lines)
|
72
|
+
self.assertNotIn(
|
73
|
+
self.picking1.move_line_ids, self.service._find_buffer_move_lines()
|
74
|
+
)
|
75
|
+
|
76
|
+
def test_find_buffer_lines3(self):
|
77
|
+
move_lines = (
|
78
|
+
self.picking2.move_line_ids
|
79
|
+
| self.picking3.move_line_ids
|
80
|
+
| self.picking4.move_line_ids
|
81
|
+
)
|
82
|
+
zones = move_lines.mapped("location_id")
|
83
|
+
# we work on lines coming from 4 different locations
|
84
|
+
self.assertEqual(len(zones), 3)
|
85
|
+
# Process them all (simulate)
|
86
|
+
for i, line in enumerate(move_lines):
|
87
|
+
dest_package = self.env["stock.quant.package"].create(
|
88
|
+
{"name": f"TEST PKG {i}"}
|
89
|
+
)
|
90
|
+
self.service._set_destination_package(
|
91
|
+
line,
|
92
|
+
line.reserved_uom_qty,
|
93
|
+
dest_package,
|
94
|
+
)
|
95
|
+
# Simulate line from picking1 processed by another user
|
96
|
+
for i, line in enumerate(self.picking1.move_line_ids):
|
97
|
+
dest_package = self.env["stock.quant.package"].create(
|
98
|
+
{"name": f"TEST PKG 1 {i}"}
|
99
|
+
)
|
100
|
+
self.service._actions_for("stock").mark_move_line_as_picked(
|
101
|
+
line,
|
102
|
+
line.reserved_uom_qty,
|
103
|
+
dest_package,
|
104
|
+
user=self.env.ref("base.user_admin"),
|
105
|
+
)
|
106
|
+
|
107
|
+
# We can unload all the lines no matter which zone we are before unload
|
108
|
+
for zone in zones:
|
109
|
+
self.service.work.current_zone_location = zone
|
110
|
+
self.assertEqual(self.service._find_buffer_move_lines(), move_lines)
|
111
|
+
self.assertNotIn(
|
112
|
+
self.picking1.move_line_ids, self.service._find_buffer_move_lines()
|
113
|
+
)
|