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,557 @@
|
|
1
|
+
# Copyright 2020 Camptocamp SA (http://www.camptocamp.com)
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
|
4
|
+
from .test_delivery_base import DeliveryCommonCase
|
5
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
|
8
|
+
|
9
|
+
class DeliveryScanDeliverCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /scan_deliver"""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def setUpClassBaseData(cls):
|
14
|
+
super().setUpClassBaseData()
|
15
|
+
cls.product_e.tracking = "lot"
|
16
|
+
cls.picking = picking = cls._create_picking(
|
17
|
+
lines=[
|
18
|
+
# we'll put A and B in a single package
|
19
|
+
(cls.product_a, 10),
|
20
|
+
(cls.product_b, 10),
|
21
|
+
# C alone in a package
|
22
|
+
(cls.product_c, 10),
|
23
|
+
# D as raw product
|
24
|
+
(cls.product_d, 10),
|
25
|
+
# E as raw product with a lot
|
26
|
+
(cls.product_e, 10),
|
27
|
+
# F in two different packages
|
28
|
+
(cls.product_f, 10),
|
29
|
+
# G in a package with quantity of one.
|
30
|
+
(cls.product_g, 10),
|
31
|
+
]
|
32
|
+
)
|
33
|
+
cls.pack1_moves = picking.move_ids[:2]
|
34
|
+
cls.pack2_move = picking.move_ids[2]
|
35
|
+
cls.pack3_move = picking.move_ids[5]
|
36
|
+
cls.pack4_move = picking.move_ids[6]
|
37
|
+
cls.raw_move = picking.move_ids[3]
|
38
|
+
cls.raw_lot_move = picking.move_ids[4]
|
39
|
+
cls._fill_stock_for_moves(cls.pack1_moves, in_package=True)
|
40
|
+
cls._fill_stock_for_moves(cls.pack2_move, in_package=True)
|
41
|
+
cls._fill_stock_for_moves(cls.pack4_move, in_package=True)
|
42
|
+
cls._fill_stock_for_moves(cls.raw_move)
|
43
|
+
cls._fill_stock_for_moves(cls.raw_lot_move, in_lot=True)
|
44
|
+
# Set a lot for A for the mixed package (A + B)
|
45
|
+
cls.product_a_lot = cls.env["stock.lot"].create(
|
46
|
+
{"product_id": cls.product_a.id, "company_id": cls.env.company.id}
|
47
|
+
)
|
48
|
+
cls.product_a_quant = cls.env["stock.quant"].search(
|
49
|
+
[("product_id", "=", cls.product_a.id)]
|
50
|
+
)
|
51
|
+
cls.product_a_quant.sudo().lot_id = cls.product_a_lot
|
52
|
+
# Fill stock for F moves (two packages)
|
53
|
+
for __ in range(2):
|
54
|
+
product_f_pkg = cls.env["stock.quant.package"].create({})
|
55
|
+
cls._update_qty_in_location(
|
56
|
+
cls.pack3_move.location_id,
|
57
|
+
cls.pack3_move.product_id,
|
58
|
+
5,
|
59
|
+
package=product_f_pkg,
|
60
|
+
)
|
61
|
+
picking.action_assign()
|
62
|
+
# Add a packaging on the raw product
|
63
|
+
cls.packaging = (
|
64
|
+
cls.env["product.packaging"]
|
65
|
+
.sudo()
|
66
|
+
.create(
|
67
|
+
{
|
68
|
+
"name": "TEST PACKAGING",
|
69
|
+
"product_id": cls.raw_move.product_id.id,
|
70
|
+
"qty": 10,
|
71
|
+
"product_uom_id": cls.raw_move.product_id.uom_id.id,
|
72
|
+
"barcode": "TEST_PACKAGING",
|
73
|
+
}
|
74
|
+
)
|
75
|
+
)
|
76
|
+
# Some records not related at all to the processed picking
|
77
|
+
cls.free_package = cls.env["stock.quant.package"].create(
|
78
|
+
{"name": "FREE_PACKAGE"}
|
79
|
+
)
|
80
|
+
cls.free_lot = cls.env["stock.lot"].create(
|
81
|
+
{
|
82
|
+
"name": "FREE_LOT",
|
83
|
+
"product_id": cls.product_a.id,
|
84
|
+
"company_id": cls.env.company.id,
|
85
|
+
}
|
86
|
+
)
|
87
|
+
cls.free_product = (
|
88
|
+
cls.env["product.product"]
|
89
|
+
.sudo()
|
90
|
+
.create({"name": "FREE_PRODUCT", "barcode": "FREE_PRODUCT"})
|
91
|
+
)
|
92
|
+
|
93
|
+
def test_scan_deliver_scan_picking_ok(self):
|
94
|
+
response = self.service.dispatch(
|
95
|
+
"scan_deliver",
|
96
|
+
params={
|
97
|
+
"barcode": self.picking.name,
|
98
|
+
"picking_id": None,
|
99
|
+
"location_id": None,
|
100
|
+
},
|
101
|
+
)
|
102
|
+
self.assert_response_deliver(response, picking=self.picking)
|
103
|
+
|
104
|
+
def test_scan_deliver_error_barcode_not_found(self):
|
105
|
+
response = self.service.dispatch(
|
106
|
+
"scan_deliver", params={"barcode": "NO VALID BARCODE", "picking_id": None}
|
107
|
+
)
|
108
|
+
self.assert_response_deliver(
|
109
|
+
response,
|
110
|
+
message=self.service.msg_store.barcode_not_found(),
|
111
|
+
)
|
112
|
+
|
113
|
+
def test_scan_deliver_error_barcode_not_found_keep_picking(self):
|
114
|
+
response = self.service.dispatch(
|
115
|
+
"scan_deliver",
|
116
|
+
params={"barcode": "NO VALID BARCODE", "picking_id": self.picking.id},
|
117
|
+
)
|
118
|
+
self.assert_response_deliver(
|
119
|
+
response,
|
120
|
+
# if the client was working on a picking (it sends picking_id, then
|
121
|
+
# send refreshed data)
|
122
|
+
picking=self.picking,
|
123
|
+
message=self.service.msg_store.barcode_not_found(),
|
124
|
+
)
|
125
|
+
|
126
|
+
def _test_scan_set_done_ok(self, move_lines, barcode, qties=None):
|
127
|
+
response = self.service.dispatch("scan_deliver", params={"barcode": barcode})
|
128
|
+
self.assert_qty_done(move_lines, qties)
|
129
|
+
picking = move_lines.move_id.picking_id
|
130
|
+
if picking.state == "done":
|
131
|
+
self.assert_response_deliver(
|
132
|
+
response, message=self.msg_store.transfer_complete(picking)
|
133
|
+
)
|
134
|
+
else:
|
135
|
+
self.assert_response_deliver(response, picking=picking)
|
136
|
+
|
137
|
+
def test_scan_deliver_scan_package(self):
|
138
|
+
move_lines = self.pack1_moves.mapped("move_line_ids")
|
139
|
+
package = move_lines.mapped("package_id")
|
140
|
+
self.assertEqual(self.picking.state, "assigned")
|
141
|
+
self._test_scan_set_done_ok(move_lines, package.name)
|
142
|
+
self.assertEqual(self.picking.state, "assigned")
|
143
|
+
|
144
|
+
def test_scan_deliver_scan_package_with_prepackaged_product(self):
|
145
|
+
"""Check scanning a package process it entirely.
|
146
|
+
|
147
|
+
"Process as pre-packaged product" option is enabled to create a backorder.
|
148
|
+
"""
|
149
|
+
self.menu.sudo().allow_prepackaged_product = True
|
150
|
+
move_lines = self.pack1_moves.mapped("move_line_ids")
|
151
|
+
package = move_lines.mapped("package_id")
|
152
|
+
self.assertEqual(self.picking.state, "assigned")
|
153
|
+
response = self.service.dispatch(
|
154
|
+
"scan_deliver", params={"barcode": package.name}
|
155
|
+
)
|
156
|
+
self.assert_response_deliver(
|
157
|
+
response, message=self.service.msg_store.transfer_complete(self.picking)
|
158
|
+
)
|
159
|
+
for line in move_lines:
|
160
|
+
self.assertEqual(line.move_id.product_uom_qty, line.move_id.quantity_done)
|
161
|
+
self.assertEqual(line.move_id.state, "done")
|
162
|
+
self.assertEqual(self.picking.state, "done")
|
163
|
+
self.assertTrue(self.picking.backorder_ids)
|
164
|
+
|
165
|
+
def test_scan_deliver_scan_package_no_move_lines(self):
|
166
|
+
response = self.service.dispatch(
|
167
|
+
"scan_deliver",
|
168
|
+
params={"barcode": self.free_package.name, "picking_id": self.picking.id},
|
169
|
+
)
|
170
|
+
self.assert_response_deliver(
|
171
|
+
response,
|
172
|
+
picking=self.picking,
|
173
|
+
message=self.service.msg_store.cannot_move_something_in_picking_type(),
|
174
|
+
)
|
175
|
+
|
176
|
+
def test_scan_deliver_scan_product_not_in_package(self):
|
177
|
+
"""Check scanning product increment quantity done by one."""
|
178
|
+
for qty_done in range(1, 3):
|
179
|
+
response = self.service.dispatch(
|
180
|
+
"scan_deliver",
|
181
|
+
params={
|
182
|
+
"barcode": self.product_d.barcode,
|
183
|
+
"picking_id": self.picking.id,
|
184
|
+
},
|
185
|
+
)
|
186
|
+
self.assertEqual(self.raw_move.move_line_ids.qty_done, qty_done)
|
187
|
+
|
188
|
+
self.assert_response_deliver(
|
189
|
+
response,
|
190
|
+
picking=self.picking,
|
191
|
+
)
|
192
|
+
|
193
|
+
def test_scan_deliver_scan_product_in_package_multiple(self):
|
194
|
+
"""Check product scanned alone in a package but quantity more than one."""
|
195
|
+
response = self.service.dispatch(
|
196
|
+
"scan_deliver",
|
197
|
+
params={"barcode": self.product_c.barcode, "picking_id": self.picking.id},
|
198
|
+
)
|
199
|
+
self.assert_response_deliver(
|
200
|
+
response,
|
201
|
+
picking=self.picking,
|
202
|
+
message=self.service.msg_store.product_not_unitary_in_package_scan_package(),
|
203
|
+
)
|
204
|
+
|
205
|
+
def test_scan_deliver_scan_product_in_multiple_packages(self):
|
206
|
+
response = self.service.dispatch(
|
207
|
+
"scan_deliver",
|
208
|
+
params={"barcode": self.product_f.barcode, "picking_id": self.picking.id},
|
209
|
+
)
|
210
|
+
self.assert_response_deliver(
|
211
|
+
response,
|
212
|
+
picking=self.picking,
|
213
|
+
message=self.service.msg_store.product_multiple_packages_scan_package(),
|
214
|
+
)
|
215
|
+
|
216
|
+
def test_scan_deliver_scan_product_in_mixed_package(self):
|
217
|
+
response = self.service.dispatch(
|
218
|
+
"scan_deliver",
|
219
|
+
params={"barcode": self.product_a.barcode, "picking_id": self.picking.id},
|
220
|
+
)
|
221
|
+
self.assert_response_deliver(
|
222
|
+
response,
|
223
|
+
picking=self.picking,
|
224
|
+
message=self.service.msg_store.product_mixed_package_scan_package(),
|
225
|
+
)
|
226
|
+
|
227
|
+
def test_scan_deliver_scan_product_tracked_by_lot(self):
|
228
|
+
response = self.service.dispatch(
|
229
|
+
"scan_deliver",
|
230
|
+
params={"barcode": self.product_e.barcode, "picking_id": self.picking.id},
|
231
|
+
)
|
232
|
+
self.assert_response_deliver(
|
233
|
+
response,
|
234
|
+
picking=self.picking,
|
235
|
+
message=self.service.msg_store.scan_lot_on_product_tracked_by_lot(),
|
236
|
+
)
|
237
|
+
|
238
|
+
def test_scan_deliver_scan_raw_product_ok(self):
|
239
|
+
self._test_scan_set_done_ok(
|
240
|
+
self.raw_move.mapped("move_line_ids"),
|
241
|
+
self.product_d.barcode,
|
242
|
+
[1], # When scanning a product we want to process only 1 qty
|
243
|
+
)
|
244
|
+
|
245
|
+
def test_scan_deliver_scan_raw_product_in_multiple_pickings(self):
|
246
|
+
# Scan a raw product (not related to a package or lot) which is present
|
247
|
+
# in multiple delivery operations (so two different moves).
|
248
|
+
# We should be able to process these two moves one after the other.
|
249
|
+
self.picking.do_unreserve()
|
250
|
+
self.raw_move.product_uom_qty = 1
|
251
|
+
self.picking.action_assign()
|
252
|
+
picking2 = self._create_picking(
|
253
|
+
lines=[
|
254
|
+
# D as raw product
|
255
|
+
(self.product_d, 1),
|
256
|
+
]
|
257
|
+
)
|
258
|
+
raw_move2 = picking2.move_ids
|
259
|
+
self._fill_stock_for_moves(raw_move2)
|
260
|
+
picking2.action_assign()
|
261
|
+
# Scan the first move
|
262
|
+
self._test_scan_set_done_ok(
|
263
|
+
self.raw_move.mapped("move_line_ids"), self.product_d.barcode
|
264
|
+
)
|
265
|
+
# Scan the second move
|
266
|
+
# NOTE: we do not use '_test_scan_set_done_ok' here as we expect
|
267
|
+
# the delivery to be complete (we process its only move line).
|
268
|
+
response = self.service.dispatch(
|
269
|
+
"scan_deliver", params={"barcode": self.product_d.barcode}
|
270
|
+
)
|
271
|
+
self.assert_response_deliver(
|
272
|
+
response, message=self.service.msg_store.transfer_complete(self.picking)
|
273
|
+
)
|
274
|
+
self.assertEqual(raw_move2.quantity_done, 1)
|
275
|
+
self.assertEqual(raw_move2.state, "done")
|
276
|
+
|
277
|
+
def test_scan_deliver_scan_product_not_found(self):
|
278
|
+
response = self.service.dispatch(
|
279
|
+
"scan_deliver", params={"barcode": self.free_product.barcode}
|
280
|
+
)
|
281
|
+
self.assert_response_deliver(
|
282
|
+
response,
|
283
|
+
message=self.service.msg_store.product_not_found_in_pickings(),
|
284
|
+
)
|
285
|
+
|
286
|
+
def test_scan_deliver_scan_lot(self):
|
287
|
+
"""Check scanning a lot process only one piece/unit of this lot."""
|
288
|
+
line = self.raw_lot_move.move_line_ids
|
289
|
+
lot = line.lot_id
|
290
|
+
response = self.service.dispatch("scan_deliver", params={"barcode": lot.name})
|
291
|
+
self.assert_response_deliver(
|
292
|
+
response,
|
293
|
+
picking=self.picking,
|
294
|
+
)
|
295
|
+
self.assertEqual(line.qty_done, 1)
|
296
|
+
self.assertEqual(line.state, "assigned")
|
297
|
+
for _ in range(int(line.reserved_uom_qty) - 1):
|
298
|
+
self.service.dispatch(
|
299
|
+
"scan_deliver",
|
300
|
+
params={
|
301
|
+
"barcode": lot.name,
|
302
|
+
"picking_id": self.picking.id,
|
303
|
+
},
|
304
|
+
)
|
305
|
+
self.assertEqual(line.qty_done, self.raw_lot_move.product_uom_qty)
|
306
|
+
|
307
|
+
def test_scan_deliver_scan_lot_with_prepackaged_product(self):
|
308
|
+
"""Check scanning a lot process only one piece/unit of this lot.
|
309
|
+
|
310
|
+
"Process as pre-packaged product" option is enabled to create a backorder.
|
311
|
+
"""
|
312
|
+
self.menu.sudo().allow_prepackaged_product = True
|
313
|
+
line = self.raw_lot_move.move_line_ids
|
314
|
+
lot = line.lot_id
|
315
|
+
response = self.service.dispatch("scan_deliver", params={"barcode": lot.name})
|
316
|
+
self.assert_response_deliver(
|
317
|
+
response, message=self.service.msg_store.transfer_complete(self.picking)
|
318
|
+
)
|
319
|
+
self.assertEqual(line.qty_done, 1)
|
320
|
+
self.assertEqual(line.move_id.state, "done")
|
321
|
+
self.assertEqual(self.picking.state, "done")
|
322
|
+
self.assertTrue(self.picking.backorder_ids)
|
323
|
+
|
324
|
+
def test_scan_deliver_scan_lot_not_found(self):
|
325
|
+
response = self.service.dispatch("scan_deliver", params={"barcode": "FREE_LOT"})
|
326
|
+
self.assert_response_deliver(
|
327
|
+
response,
|
328
|
+
message=self.service.msg_store.lot_not_found_in_pickings(),
|
329
|
+
)
|
330
|
+
|
331
|
+
def test_scan_deliver_scan_lot_in_mixed_package(self):
|
332
|
+
response = self.service.dispatch(
|
333
|
+
"scan_deliver", params={"barcode": self.product_a_lot.name}
|
334
|
+
)
|
335
|
+
self.assert_response_deliver(
|
336
|
+
response,
|
337
|
+
picking=self.picking,
|
338
|
+
message=self.service.msg_store.lot_mixed_package_scan_package(),
|
339
|
+
)
|
340
|
+
|
341
|
+
def test_scan_deliver_scan_product_packaging(self):
|
342
|
+
"""Check scanning a product packaging use the packaging quantity.
|
343
|
+
|
344
|
+
Quantity on the line is the packaging quantity
|
345
|
+
"""
|
346
|
+
# Scan a product packaging having the same qty than the qty to ship.
|
347
|
+
# We have 10 qties to ship and we scan a product packaging of 10 qties.
|
348
|
+
line = self.raw_move.mapped("move_line_ids")
|
349
|
+
response = self.service.dispatch(
|
350
|
+
"scan_deliver", params={"barcode": self.packaging.barcode}
|
351
|
+
)
|
352
|
+
self.assert_response_deliver(response, picking=self.picking)
|
353
|
+
self.assertEqual(line.qty_done, self.packaging.qty)
|
354
|
+
|
355
|
+
def test_scan_deliver_scan_product_packaging_with_prepackaged_product(self):
|
356
|
+
"""Check scanning a product packaging use the packaging quantity.
|
357
|
+
|
358
|
+
Quantity on the line is the packaging quantity
|
359
|
+
|
360
|
+
"Process as pre-packaged product" option is enabled to create a backorder.
|
361
|
+
"""
|
362
|
+
# Scan a product packaging having the same qty than the qty to ship.
|
363
|
+
# We have 10 qties to ship and we scan a product packaging of 10 qties.
|
364
|
+
self.menu.sudo().allow_prepackaged_product = True
|
365
|
+
line = self.raw_move.mapped("move_line_ids")
|
366
|
+
response = self.service.dispatch(
|
367
|
+
"scan_deliver", params={"barcode": self.packaging.barcode}
|
368
|
+
)
|
369
|
+
self.assert_response_deliver(
|
370
|
+
response, message=self.service.msg_store.transfer_complete(self.picking)
|
371
|
+
)
|
372
|
+
self.assertEqual(line.qty_done, self.packaging.qty)
|
373
|
+
|
374
|
+
def test_scan_deliver_scan_product_packaging_partial_qty(self):
|
375
|
+
# Scan a product packaging with a smaller qty than the move line
|
376
|
+
# We have 10 qties to ship but we scan a product packaging of 5 qties.
|
377
|
+
# -> Processed 5 over 10 qties
|
378
|
+
# Then we scan a second time the product packaging all qties will be processed
|
379
|
+
# -> Processed 10/10
|
380
|
+
self.packaging.qty = 5
|
381
|
+
line = self.raw_move.mapped("move_line_ids")
|
382
|
+
self.assertEqual(line.move_id.product_qty, 10)
|
383
|
+
response = self.service.dispatch(
|
384
|
+
"scan_deliver", params={"barcode": self.packaging.barcode}
|
385
|
+
)
|
386
|
+
self.assert_response_deliver(response, picking=self.picking)
|
387
|
+
self.assertEqual(line.qty_done, self.packaging.qty)
|
388
|
+
self.assertTrue(line.move_id.product_qty > self.packaging.qty)
|
389
|
+
# Process the remaining qties, still by scanning the packaging
|
390
|
+
response = self.service.dispatch(
|
391
|
+
"scan_deliver", params={"barcode": self.packaging.barcode}
|
392
|
+
)
|
393
|
+
self.assert_response_deliver(response, picking=self.picking)
|
394
|
+
self.assertEqual(line.move_id.product_qty, line.move_id.quantity_done)
|
395
|
+
self.assertEqual(line.move_id.state, "assigned")
|
396
|
+
|
397
|
+
def test_scan_deliver_scan_product_packaging_partial_qty_with_prepackaged_product(
|
398
|
+
self,
|
399
|
+
):
|
400
|
+
# Scan a product packaging with a smaller qty than the move line
|
401
|
+
# while the "Process pre-packaged product" option is enabled.
|
402
|
+
# We have 10 qties to ship but we scan a product packaging of 5 qties.
|
403
|
+
# -> Ship 5 (creating a backorder for the 5 remaining)
|
404
|
+
# Then we scan a second time the product packaging to process the backorder
|
405
|
+
# -> Ship 5 (again)
|
406
|
+
self.menu.sudo().allow_prepackaged_product = True
|
407
|
+
self.packaging.qty = 5
|
408
|
+
line = self.raw_move.mapped("move_line_ids")
|
409
|
+
self.assertEqual(line.move_id.product_qty, 10)
|
410
|
+
response = self.service.dispatch(
|
411
|
+
"scan_deliver", params={"barcode": self.packaging.barcode}
|
412
|
+
)
|
413
|
+
self.assert_response_deliver(
|
414
|
+
response,
|
415
|
+
message=self.service.msg_store.transfer_complete(self.picking),
|
416
|
+
)
|
417
|
+
self.assertEqual(line.qty_done, self.packaging.qty)
|
418
|
+
self.assertEqual(line.move_id.product_qty, self.packaging.qty)
|
419
|
+
self.assertEqual(line.move_id.state, "done")
|
420
|
+
self.assertTrue(self.picking.backorder_ids)
|
421
|
+
# Process the backorder
|
422
|
+
backorder = self.picking.backorder_ids
|
423
|
+
backorder_raw_move = backorder.move_ids.filtered_domain(
|
424
|
+
[("product_id", "=", self.product_d.id)]
|
425
|
+
)
|
426
|
+
backorder_line = backorder_raw_move.move_line_ids
|
427
|
+
response = self.service.dispatch(
|
428
|
+
"scan_deliver", params={"barcode": self.packaging.barcode}
|
429
|
+
)
|
430
|
+
self.assert_response_deliver(
|
431
|
+
response, message=self.service.msg_store.transfer_complete(backorder)
|
432
|
+
)
|
433
|
+
self.assertEqual(backorder_line.move_id.product_qty, self.packaging.qty)
|
434
|
+
self.assertEqual(backorder_line.move_id.state, "done")
|
435
|
+
|
436
|
+
def test_scan_deliver_scan_product_alone_in_package_qty_one(self):
|
437
|
+
"""Check scanning a product alone in a package with a quantity of one."""
|
438
|
+
self.picking.action_cancel()
|
439
|
+
pick = self._create_picking(
|
440
|
+
lines=[
|
441
|
+
(self.product_c, 1),
|
442
|
+
]
|
443
|
+
)
|
444
|
+
pack_move = pick.move_ids[:1]
|
445
|
+
self._fill_stock_for_moves(pack_move, in_package=True)
|
446
|
+
pick.action_assign()
|
447
|
+
move_lines = pick.move_ids.mapped("move_line_ids")
|
448
|
+
self._test_scan_set_done_ok(move_lines, self.product_c.barcode, [1])
|
449
|
+
|
450
|
+
def test_scan_deliver_picking_done(self):
|
451
|
+
# Set qty done for all lines (packages/raw product/lot...), picking is
|
452
|
+
# automatically set to done when the last line is completed
|
453
|
+
package1 = self.pack1_moves.mapped("move_line_ids").mapped("package_id")
|
454
|
+
package2 = self.pack2_move.mapped("move_line_ids").mapped("package_id")
|
455
|
+
package4 = self.pack4_move.mapped("move_line_ids").mapped("package_id")
|
456
|
+
self.service.dispatch(
|
457
|
+
"set_qty_done_pack",
|
458
|
+
params={"package_id": package1.id, "picking_id": self.picking.id},
|
459
|
+
)
|
460
|
+
self.assertEqual(self.picking.state, "assigned")
|
461
|
+
self.service.dispatch(
|
462
|
+
"set_qty_done_pack",
|
463
|
+
params={"package_id": package2.id, "picking_id": self.picking.id},
|
464
|
+
)
|
465
|
+
self.assertEqual(self.picking.state, "assigned")
|
466
|
+
|
467
|
+
self.service.dispatch(
|
468
|
+
"set_qty_done_pack",
|
469
|
+
params={"package_id": package4.id, "picking_id": self.picking.id},
|
470
|
+
)
|
471
|
+
self.assertEqual(self.picking.state, "assigned")
|
472
|
+
|
473
|
+
# When a product is scanned, we process only one unit of it
|
474
|
+
for _ in range(int(self.raw_move.product_uom_qty)):
|
475
|
+
self.service.dispatch(
|
476
|
+
"scan_deliver",
|
477
|
+
params={
|
478
|
+
"barcode": self.raw_move.product_id.barcode,
|
479
|
+
"picking_id": self.picking.id,
|
480
|
+
},
|
481
|
+
)
|
482
|
+
self.assertEqual(self.picking.state, "assigned")
|
483
|
+
|
484
|
+
# When a lot is scanned, we process only one unit of it
|
485
|
+
lot = self.raw_lot_move.move_line_ids.lot_id
|
486
|
+
for _ in range(int(self.raw_lot_move.product_uom_qty)):
|
487
|
+
response = self.service.dispatch(
|
488
|
+
"scan_deliver",
|
489
|
+
params={"barcode": lot.name, "picking_id": self.picking.id},
|
490
|
+
)
|
491
|
+
self.assertEqual(self.picking.state, "assigned")
|
492
|
+
packages_f = self.pack3_move.move_line_ids.mapped("package_id")
|
493
|
+
# While all lines are not processed, response still returns the picking
|
494
|
+
self.assert_response_deliver(
|
495
|
+
response,
|
496
|
+
picking=self.picking,
|
497
|
+
)
|
498
|
+
response = None
|
499
|
+
# Once all lines are processed, the last response has no picking returned
|
500
|
+
for package in packages_f:
|
501
|
+
response = self.service.dispatch(
|
502
|
+
"set_qty_done_pack",
|
503
|
+
params={"package_id": package.id, "picking_id": self.picking.id},
|
504
|
+
)
|
505
|
+
self.assertEqual(self.picking.state, "done")
|
506
|
+
self.assert_response_deliver(
|
507
|
+
response,
|
508
|
+
message=self.service.msg_store.transfer_complete(self.picking),
|
509
|
+
)
|
510
|
+
|
511
|
+
|
512
|
+
class DeliveryScanDeliverSpecialCase(DeliveryCommonCase):
|
513
|
+
"""Special cases with different setup for /scan_deliver"""
|
514
|
+
|
515
|
+
def test_scan_deliver_error_picking_wrong_type(self):
|
516
|
+
picking = self._create_picking(
|
517
|
+
picking_type=self.wh.out_type_id, lines=[(self.product_a, 10)]
|
518
|
+
)
|
519
|
+
self._fill_stock_for_moves(picking.move_ids, in_package=True)
|
520
|
+
picking.action_assign()
|
521
|
+
response = self.service.dispatch(
|
522
|
+
"scan_deliver", params={"barcode": picking.name}
|
523
|
+
)
|
524
|
+
self.assert_response_deliver(
|
525
|
+
response,
|
526
|
+
message={
|
527
|
+
"message_type": "error",
|
528
|
+
"body": "You cannot move this using this menu.",
|
529
|
+
},
|
530
|
+
)
|
531
|
+
|
532
|
+
def test_scan_deliver_error_picking_unavailable(self):
|
533
|
+
picking = self._create_picking(lines=[(self.product_a, 10)])
|
534
|
+
response = self.service.dispatch(
|
535
|
+
"scan_deliver", params={"barcode": picking.name}
|
536
|
+
)
|
537
|
+
self.assert_response_deliver(
|
538
|
+
response,
|
539
|
+
message={
|
540
|
+
"message_type": "error",
|
541
|
+
"body": "Transfer {} is not available.".format(picking.name),
|
542
|
+
},
|
543
|
+
)
|
544
|
+
|
545
|
+
def test_scan_deliver_error_picking_already_done(self):
|
546
|
+
picking = self._create_picking(lines=[(self.product_a, 10)])
|
547
|
+
self._fill_stock_for_moves(picking.move_ids, in_package=True)
|
548
|
+
picking.action_assign()
|
549
|
+
picking.move_line_ids.qty_done = picking.move_line_ids.reserved_uom_qty
|
550
|
+
picking._action_done()
|
551
|
+
response = self.service.dispatch(
|
552
|
+
"scan_deliver", params={"barcode": picking.name}
|
553
|
+
)
|
554
|
+
self.assert_response_deliver(
|
555
|
+
response,
|
556
|
+
message={"message_type": "info", "body": "Operation already processed."},
|
557
|
+
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Copyright 2020 Camptocamp SA
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
3
|
+
|
4
|
+
from .test_delivery_base import DeliveryCommonCase
|
5
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
|
8
|
+
|
9
|
+
class DeliverySelectCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /select"""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def setUpClassBaseData(cls):
|
14
|
+
super().setUpClassBaseData()
|
15
|
+
cls.picking1 = cls._create_picking(
|
16
|
+
lines=[(cls.product_a, 10), (cls.product_b, 10)]
|
17
|
+
)
|
18
|
+
cls.picking2 = cls._create_picking(
|
19
|
+
lines=[(cls.product_a, 10), (cls.product_b, 10)]
|
20
|
+
)
|
21
|
+
cls._fill_stock_for_moves(cls.picking1.move_ids)
|
22
|
+
cls._fill_stock_for_moves(cls.picking2.move_ids)
|
23
|
+
cls.pickings = cls.picking1 | cls.picking2
|
24
|
+
cls.pickings.action_assign()
|
25
|
+
|
26
|
+
def test_select_ok(self):
|
27
|
+
response = self.service.dispatch(
|
28
|
+
"select", params={"picking_id": self.picking1.id}
|
29
|
+
)
|
30
|
+
self.assert_response_deliver(response, picking=self.picking1)
|
31
|
+
|
32
|
+
def test_select_not_found(self):
|
33
|
+
response = self.service.dispatch("select", params={"picking_id": -1})
|
34
|
+
self.assert_response_manual_selection(
|
35
|
+
response,
|
36
|
+
pickings=self.pickings,
|
37
|
+
message=self.service.msg_store.stock_picking_not_found(),
|
38
|
+
)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Copyright 2020 Camptocamp SA
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
3
|
+
|
4
|
+
from .test_delivery_base import DeliveryCommonCase
|
5
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
|
8
|
+
|
9
|
+
class DeliverySetQtyDoneLineCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /set_qty_done_line"""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def setUpClassBaseData(cls):
|
14
|
+
super().setUpClassBaseData()
|
15
|
+
cls.picking = picking = cls._create_picking(
|
16
|
+
lines=[
|
17
|
+
# put A in a package
|
18
|
+
(cls.product_a, 10),
|
19
|
+
# B as raw product
|
20
|
+
(cls.product_b, 10),
|
21
|
+
]
|
22
|
+
)
|
23
|
+
cls.pack1_move = picking.move_ids[0]
|
24
|
+
cls.raw_move = picking.move_ids[1]
|
25
|
+
cls._fill_stock_for_moves(cls.pack1_move, in_package=True)
|
26
|
+
cls._fill_stock_for_moves(cls.raw_move)
|
27
|
+
picking.action_assign()
|
28
|
+
|
29
|
+
def _test_set_qty_done_line_ok(self, move_line):
|
30
|
+
response = self.service.dispatch(
|
31
|
+
"set_qty_done_line",
|
32
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
33
|
+
)
|
34
|
+
self.assert_qty_done(move_line)
|
35
|
+
self.assert_response_deliver(response, picking=self.picking)
|
36
|
+
|
37
|
+
def test_set_qty_done_line_picking_not_found(self):
|
38
|
+
move_line = self.pack1_move.mapped("move_line_ids")
|
39
|
+
response = self.service.dispatch(
|
40
|
+
"set_qty_done_line", params={"move_line_id": move_line.id, "picking_id": -1}
|
41
|
+
)
|
42
|
+
self.assert_response_deliver(
|
43
|
+
response, message=self.service.msg_store.stock_picking_not_found()
|
44
|
+
)
|
45
|
+
|
46
|
+
def test_set_qty_done_line_picking_canceled(self):
|
47
|
+
move_line = self.pack1_move.mapped("move_line_ids")
|
48
|
+
self.picking.action_cancel()
|
49
|
+
response = self.service.dispatch(
|
50
|
+
"set_qty_done_line",
|
51
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
52
|
+
)
|
53
|
+
self.assert_response_deliver(
|
54
|
+
response,
|
55
|
+
message=self.service.msg_store.stock_picking_not_available(self.picking),
|
56
|
+
)
|
57
|
+
|
58
|
+
def test_set_qty_done_line_line_not_found(self):
|
59
|
+
response = self.service.dispatch(
|
60
|
+
"set_qty_done_line",
|
61
|
+
params={"move_line_id": -1, "picking_id": self.picking.id},
|
62
|
+
)
|
63
|
+
self.assert_response_deliver(
|
64
|
+
response,
|
65
|
+
picking=self.picking,
|
66
|
+
message=self.service.msg_store.record_not_found(),
|
67
|
+
)
|
68
|
+
|
69
|
+
def test_set_qty_done_line_ok(self):
|
70
|
+
move_line = self.raw_move.mapped("move_line_ids")
|
71
|
+
self._test_set_qty_done_line_ok(move_line)
|
72
|
+
# picking is still assigned as only one move line have been processed
|
73
|
+
self.assertEqual(self.picking.state, "assigned")
|
74
|
+
|
75
|
+
def test_set_qty_done_line_picking_done(self):
|
76
|
+
# process the first move line with a package
|
77
|
+
move_line = self.pack1_move.mapped("move_line_ids")
|
78
|
+
package = move_line.mapped("package_id")
|
79
|
+
self.service.dispatch(
|
80
|
+
"set_qty_done_pack",
|
81
|
+
params={"package_id": package.id, "picking_id": self.picking.id},
|
82
|
+
)
|
83
|
+
self.assertEqual(self.picking.state, "assigned")
|
84
|
+
# process the remaining move line
|
85
|
+
move_line = self.raw_move.mapped("move_line_ids")
|
86
|
+
self.service.dispatch(
|
87
|
+
"set_qty_done_line",
|
88
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
89
|
+
)
|
90
|
+
# picking is done once all its moves have been processed
|
91
|
+
self.assertEqual(self.picking.state, "done")
|