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,155 @@
|
|
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 .common import CommonCase
|
5
|
+
|
6
|
+
# pylint: disable=missing-return
|
7
|
+
|
8
|
+
|
9
|
+
class DeliveryCommonCase(CommonCase):
|
10
|
+
@classmethod
|
11
|
+
def setUpClassVars(cls, *args, **kwargs):
|
12
|
+
super().setUpClassVars(*args, **kwargs)
|
13
|
+
cls.menu = cls.env.ref("shopfloor.shopfloor_menu_demo_delivery")
|
14
|
+
cls.profile = cls.env.ref("shopfloor_base.profile_demo_1")
|
15
|
+
cls.picking_type = cls.menu.picking_type_ids
|
16
|
+
cls.wh = cls.picking_type.warehouse_id
|
17
|
+
|
18
|
+
@classmethod
|
19
|
+
def setUpClassBaseData(cls, *args, **kwargs):
|
20
|
+
super().setUpClassBaseData(*args, **kwargs)
|
21
|
+
cls.wh.sudo().delivery_steps = "pick_pack_ship"
|
22
|
+
cls.product_e = (
|
23
|
+
cls.env["product.product"]
|
24
|
+
.sudo()
|
25
|
+
.create(
|
26
|
+
{
|
27
|
+
"name": "Product E",
|
28
|
+
"type": "product",
|
29
|
+
"default_code": "E",
|
30
|
+
"barcode": "E",
|
31
|
+
"weight": 3,
|
32
|
+
}
|
33
|
+
)
|
34
|
+
)
|
35
|
+
cls.product_e_packaging = (
|
36
|
+
cls.env["product.packaging"]
|
37
|
+
.sudo()
|
38
|
+
.create(
|
39
|
+
{
|
40
|
+
"name": "Box",
|
41
|
+
"product_id": cls.product_e.id,
|
42
|
+
"barcode": "ProductEBox",
|
43
|
+
}
|
44
|
+
)
|
45
|
+
)
|
46
|
+
cls.product_f = (
|
47
|
+
cls.env["product.product"]
|
48
|
+
.sudo()
|
49
|
+
.create(
|
50
|
+
{
|
51
|
+
"name": "Product F",
|
52
|
+
"type": "product",
|
53
|
+
"default_code": "F",
|
54
|
+
"barcode": "F",
|
55
|
+
"weight": 3,
|
56
|
+
}
|
57
|
+
)
|
58
|
+
)
|
59
|
+
cls.product_f_packaging = (
|
60
|
+
cls.env["product.packaging"]
|
61
|
+
.sudo()
|
62
|
+
.create(
|
63
|
+
{
|
64
|
+
"name": "Box",
|
65
|
+
"product_id": cls.product_f.id,
|
66
|
+
"barcode": "ProductFBox",
|
67
|
+
}
|
68
|
+
)
|
69
|
+
)
|
70
|
+
cls.product_g = (
|
71
|
+
cls.env["product.product"]
|
72
|
+
.sudo()
|
73
|
+
.create(
|
74
|
+
{
|
75
|
+
"name": "Product G",
|
76
|
+
"type": "product",
|
77
|
+
"default_code": "G",
|
78
|
+
"barcode": "G",
|
79
|
+
"weight": 1,
|
80
|
+
}
|
81
|
+
)
|
82
|
+
)
|
83
|
+
cls.product_g_packaging = (
|
84
|
+
cls.env["product.packaging"]
|
85
|
+
.sudo()
|
86
|
+
.create(
|
87
|
+
{
|
88
|
+
"name": "Box",
|
89
|
+
"product_id": cls.product_g.id,
|
90
|
+
"barcode": "ProductGBox",
|
91
|
+
}
|
92
|
+
)
|
93
|
+
)
|
94
|
+
|
95
|
+
def setUp(self):
|
96
|
+
super().setUp()
|
97
|
+
self.service = self.get_service(
|
98
|
+
"delivery", menu=self.menu, profile=self.profile
|
99
|
+
)
|
100
|
+
|
101
|
+
def _stock_picking_data(self, picking):
|
102
|
+
return self.service.data_detail.picking_detail(picking)
|
103
|
+
|
104
|
+
def _stock_location_data(self, location):
|
105
|
+
return self.service.data.location(location, with_operation_progress=True)
|
106
|
+
|
107
|
+
def assert_response_deliver(
|
108
|
+
self, response, picking=None, message=None, location=None
|
109
|
+
):
|
110
|
+
self.assert_response(
|
111
|
+
response,
|
112
|
+
next_state="deliver",
|
113
|
+
data={
|
114
|
+
"picking": self._stock_picking_data(picking) if picking else None,
|
115
|
+
"sublocation": self._stock_location_data(location)
|
116
|
+
if location
|
117
|
+
else None,
|
118
|
+
},
|
119
|
+
message=message,
|
120
|
+
)
|
121
|
+
|
122
|
+
def assert_response_manual_selection(self, response, pickings=None, message=None):
|
123
|
+
self.assert_response(
|
124
|
+
response,
|
125
|
+
next_state="manual_selection",
|
126
|
+
data={
|
127
|
+
"pickings": [self._stock_picking_data(picking) for picking in pickings]
|
128
|
+
},
|
129
|
+
message=message,
|
130
|
+
)
|
131
|
+
|
132
|
+
def assert_qty_done(self, move_lines, qties=None):
|
133
|
+
"""Ensure that the quantities done are the expected ones.
|
134
|
+
|
135
|
+
If `qties` is not defined, the expected qties are `product_uom_qty`
|
136
|
+
of the move lines.
|
137
|
+
`qties` parameter is a list of move lines qty (same order).
|
138
|
+
"""
|
139
|
+
if qties:
|
140
|
+
assert len(move_lines) == len(qties), "'qties' doesn't match 'move_lines'"
|
141
|
+
expected_qties = []
|
142
|
+
for qty in qties:
|
143
|
+
expected_qties.append({"qty_done": qty})
|
144
|
+
else:
|
145
|
+
expected_qties = [
|
146
|
+
{"qty_done": line.reserved_uom_qty} for line in move_lines
|
147
|
+
]
|
148
|
+
self.assertRecordValues(move_lines, expected_qties)
|
149
|
+
package_level = move_lines.package_level_id
|
150
|
+
if package_level:
|
151
|
+
values = [{"is_done": True}]
|
152
|
+
if qties:
|
153
|
+
values = [{"is_done": bool(qty)} for qty in qties]
|
154
|
+
# we have a package level only when there is a package
|
155
|
+
self.assertRecordValues(package_level, values)
|
@@ -0,0 +1,108 @@
|
|
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 DeliveryDoneCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /done"""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def setUpClassBaseData(cls):
|
14
|
+
super().setUpClassBaseData()
|
15
|
+
cls.picking = picking = cls._create_picking(
|
16
|
+
lines=[
|
17
|
+
# we'll put A and B in a single package
|
18
|
+
(cls.product_a, 10),
|
19
|
+
(cls.product_b, 10),
|
20
|
+
# C as raw product
|
21
|
+
(cls.product_c, 10),
|
22
|
+
]
|
23
|
+
)
|
24
|
+
cls.pack1_moves = picking.move_ids[:2]
|
25
|
+
cls.raw_move = cls.picking.move_ids[2]
|
26
|
+
cls._fill_stock_for_moves(cls.pack1_moves, in_package=True)
|
27
|
+
cls._fill_stock_for_moves(cls.raw_move)
|
28
|
+
cls.picking.action_assign()
|
29
|
+
|
30
|
+
def assert_response_confirm_done(self, response, picking=None, message=None):
|
31
|
+
self.assert_response(
|
32
|
+
response,
|
33
|
+
next_state="confirm_done",
|
34
|
+
data={"picking": self._stock_picking_data(picking) if picking else None},
|
35
|
+
message=message,
|
36
|
+
)
|
37
|
+
|
38
|
+
def test_done_picking_not_found(self):
|
39
|
+
response = self.service.dispatch("done", params={"picking_id": -1})
|
40
|
+
self.assert_response_deliver(
|
41
|
+
response, message=self.service.msg_store.stock_picking_not_found()
|
42
|
+
)
|
43
|
+
|
44
|
+
def test_done_all_qty_done(self):
|
45
|
+
# Do not use the /set_qty_done_line endpoint to set done qties to not
|
46
|
+
# update the picking to 'done' state automatically
|
47
|
+
for move_line in self.picking.move_line_ids:
|
48
|
+
move_line.qty_done = move_line.reserved_uom_qty
|
49
|
+
response = self.service.dispatch("done", params={"picking_id": self.picking.id})
|
50
|
+
self.assert_response_deliver(
|
51
|
+
response,
|
52
|
+
message=self.service.msg_store.transfer_complete(self.picking),
|
53
|
+
)
|
54
|
+
self.assertEqual(self.picking.state, "done")
|
55
|
+
|
56
|
+
def test_done_no_qty_done(self):
|
57
|
+
response = self.service.dispatch("done", params={"picking_id": self.picking.id})
|
58
|
+
self.assert_response_confirm_done(
|
59
|
+
response,
|
60
|
+
picking=self.picking,
|
61
|
+
message=self.service.msg_store.transfer_confirm_done(),
|
62
|
+
)
|
63
|
+
self.assertEqual(self.picking.state, "assigned")
|
64
|
+
|
65
|
+
def test_done_some_qty_done(self):
|
66
|
+
move_line = self.raw_move.move_line_ids[0]
|
67
|
+
self.service.dispatch(
|
68
|
+
"set_qty_done_line",
|
69
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
70
|
+
)
|
71
|
+
response = self.service.dispatch("done", params={"picking_id": self.picking.id})
|
72
|
+
self.assert_response_confirm_done(
|
73
|
+
response,
|
74
|
+
picking=self.picking,
|
75
|
+
message=self.service.msg_store.transfer_confirm_done(),
|
76
|
+
)
|
77
|
+
self.assertEqual(self.picking.state, "assigned")
|
78
|
+
|
79
|
+
def test_done_no_qty_done_confirm(self):
|
80
|
+
self.assertEqual(self.picking.state, "assigned")
|
81
|
+
response = self.service.dispatch(
|
82
|
+
"done", params={"picking_id": self.picking.id, "confirm": True}
|
83
|
+
)
|
84
|
+
self.assert_response_deliver(
|
85
|
+
response,
|
86
|
+
message=self.service.msg_store.transfer_no_qty_done(),
|
87
|
+
)
|
88
|
+
self.assertEqual(self.picking.state, "assigned")
|
89
|
+
|
90
|
+
def test_done_some_qty_done_confirm(self):
|
91
|
+
move_line = self.raw_move.move_line_ids[0]
|
92
|
+
self.service.dispatch(
|
93
|
+
"set_qty_done_line",
|
94
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
95
|
+
)
|
96
|
+
self.assertEqual(self.picking.state, "assigned")
|
97
|
+
response = self.service.dispatch(
|
98
|
+
"done", params={"picking_id": self.picking.id, "confirm": True}
|
99
|
+
)
|
100
|
+
self.assert_response_deliver(
|
101
|
+
response,
|
102
|
+
message=self.service.msg_store.transfer_complete(self.picking),
|
103
|
+
)
|
104
|
+
self.assertEqual(self.picking.state, "done")
|
105
|
+
self.assertEqual(self.picking.move_ids, self.raw_move)
|
106
|
+
backorder = self.picking.backorder_ids
|
107
|
+
self.assertTrue(backorder)
|
108
|
+
self.assertEqual(self.pack1_moves.picking_id, backorder)
|
@@ -0,0 +1,49 @@
|
|
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 DeliveryListStockPickingCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /list_stock_picking"""
|
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
|
+
|
22
|
+
def test_list_stock_picking_ko(self):
|
23
|
+
"""No picking is ready, no picking to list."""
|
24
|
+
response = self.service.dispatch("list_stock_picking", params={})
|
25
|
+
self.assert_response_manual_selection(
|
26
|
+
response,
|
27
|
+
pickings=[],
|
28
|
+
)
|
29
|
+
|
30
|
+
def test_list_stock_picking_ok(self):
|
31
|
+
"""Picking ready to list."""
|
32
|
+
# prepare 1st picking
|
33
|
+
self._fill_stock_for_moves(self.picking1.move_ids)
|
34
|
+
self.picking1.action_assign()
|
35
|
+
response = self.service.dispatch("list_stock_picking", params={})
|
36
|
+
# picking1 only available
|
37
|
+
self.assert_response_manual_selection(
|
38
|
+
response,
|
39
|
+
pickings=self.picking1,
|
40
|
+
)
|
41
|
+
# prepare 2nd picking
|
42
|
+
self._fill_stock_for_moves(self.picking2.move_ids)
|
43
|
+
self.picking2.action_assign()
|
44
|
+
response = self.service.dispatch("list_stock_picking", params={})
|
45
|
+
# all pickings available
|
46
|
+
self.assert_response_manual_selection(
|
47
|
+
response,
|
48
|
+
pickings=self.picking1 + self.picking2,
|
49
|
+
)
|
@@ -0,0 +1,119 @@
|
|
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 DeliveryResetQtyDoneLineCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /reset_qty_done_line"""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def setUpClassBaseData(cls):
|
14
|
+
super().setUpClassBaseData()
|
15
|
+
cls.picking = picking = cls._create_picking(
|
16
|
+
lines=[
|
17
|
+
# we'll put A and B in a single package
|
18
|
+
(cls.product_a, 10),
|
19
|
+
(cls.product_b, 10),
|
20
|
+
# C as raw product
|
21
|
+
(cls.product_c, 10),
|
22
|
+
]
|
23
|
+
)
|
24
|
+
cls.pack1_moves = picking.move_ids[:2]
|
25
|
+
cls.raw_move = picking.move_ids[2]
|
26
|
+
cls._fill_stock_for_moves(cls.pack1_moves, in_package=True)
|
27
|
+
cls._fill_stock_for_moves(cls.raw_move)
|
28
|
+
picking.action_assign()
|
29
|
+
# Some records not related at all to the processed picking
|
30
|
+
cls.free_picking = cls._create_picking(lines=[(cls.product_d, 10)])
|
31
|
+
cls.free_raw_move = cls.free_picking.move_ids[0]
|
32
|
+
cls._fill_stock_for_moves(cls.free_raw_move)
|
33
|
+
cls.free_picking.action_assign()
|
34
|
+
|
35
|
+
def test_reset_qty_done_line_picking_not_found(self):
|
36
|
+
move_lines = self.pack1_moves.mapped("move_line_ids")
|
37
|
+
response = self.service.dispatch(
|
38
|
+
"reset_qty_done_line",
|
39
|
+
params={"move_line_id": move_lines[0].id, "picking_id": -1},
|
40
|
+
)
|
41
|
+
self.assert_response_deliver(
|
42
|
+
response, message=self.service.msg_store.stock_picking_not_found()
|
43
|
+
)
|
44
|
+
|
45
|
+
def test_reset_qty_done_line_line_not_found(self):
|
46
|
+
response = self.service.dispatch(
|
47
|
+
"reset_qty_done_line",
|
48
|
+
params={"move_line_id": -1, "picking_id": self.picking.id},
|
49
|
+
)
|
50
|
+
self.assert_response_deliver(
|
51
|
+
response,
|
52
|
+
picking=self.picking,
|
53
|
+
message=self.service.msg_store.record_not_found(),
|
54
|
+
)
|
55
|
+
|
56
|
+
def test_reset_qty_done_line_line_not_available_in_picking(self):
|
57
|
+
move_line = self.free_raw_move.mapped("move_line_ids")
|
58
|
+
response = self.service.dispatch(
|
59
|
+
"reset_qty_done_line",
|
60
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
61
|
+
)
|
62
|
+
self.assert_response_deliver(
|
63
|
+
response,
|
64
|
+
picking=self.picking,
|
65
|
+
message=self.service.msg_store.line_not_available_in_picking(self.picking),
|
66
|
+
)
|
67
|
+
|
68
|
+
def test_reset_qty_done_line_ok(self):
|
69
|
+
move_line = self.raw_move.mapped("move_line_ids")
|
70
|
+
# Set qty done on a line
|
71
|
+
self.service.dispatch(
|
72
|
+
"set_qty_done_line",
|
73
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
74
|
+
)
|
75
|
+
self.assertTrue(move_line.qty_done == move_line.reserved_uom_qty)
|
76
|
+
# Reset it, no related move lines are "done"
|
77
|
+
response = self.service.dispatch(
|
78
|
+
"reset_qty_done_line",
|
79
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
80
|
+
)
|
81
|
+
self.assert_response_deliver(response, picking=self.picking)
|
82
|
+
self.assertFalse(move_line.qty_done)
|
83
|
+
|
84
|
+
def test_reset_qty_done_line_with_package(self):
|
85
|
+
move_line = self.pack1_moves[0].mapped("move_line_ids")
|
86
|
+
response = self.service.dispatch(
|
87
|
+
"set_qty_done_line",
|
88
|
+
params={"move_line_id": move_line.id, "picking_id": self.picking.id},
|
89
|
+
)
|
90
|
+
self.assert_response_deliver(
|
91
|
+
response,
|
92
|
+
picking=self.picking,
|
93
|
+
message=self.service.msg_store.line_has_package_scan_package(),
|
94
|
+
)
|
95
|
+
|
96
|
+
def test_reset_qty_done_pack_picking_status(self):
|
97
|
+
move_lines = self.picking.move_line_ids
|
98
|
+
raw_move_line = self.raw_move.mapped("move_line_ids")
|
99
|
+
# Set qty done for all lines (some are linked to packages here),
|
100
|
+
# picking is automatically set to done
|
101
|
+
for package in move_lines.mapped("package_id"):
|
102
|
+
self.service.dispatch(
|
103
|
+
"set_qty_done_pack",
|
104
|
+
params={"package_id": package.id, "picking_id": self.picking.id},
|
105
|
+
)
|
106
|
+
self.service.dispatch(
|
107
|
+
"set_qty_done_line",
|
108
|
+
params={"move_line_id": raw_move_line.id, "picking_id": self.picking.id},
|
109
|
+
)
|
110
|
+
self.assertEqual(self.picking.state, "done")
|
111
|
+
# Try to reset one of them => picking already processed
|
112
|
+
response = self.service.dispatch(
|
113
|
+
"reset_qty_done_line",
|
114
|
+
params={"move_line_id": raw_move_line.id, "picking_id": self.picking.id},
|
115
|
+
)
|
116
|
+
self.assert_response_deliver(
|
117
|
+
response, message=self.service.msg_store.already_done()
|
118
|
+
)
|
119
|
+
self.assertEqual(self.picking.state, "done")
|
@@ -0,0 +1,107 @@
|
|
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 DeliveryResetQtyDonePackCase(DeliveryCommonCase):
|
10
|
+
"""Tests for /reset_qty_done_pack"""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def setUpClassBaseData(cls):
|
14
|
+
super().setUpClassBaseData()
|
15
|
+
cls.picking = picking = cls._create_picking(
|
16
|
+
lines=[
|
17
|
+
# we'll put A and B in a single package
|
18
|
+
(cls.product_a, 10),
|
19
|
+
(cls.product_b, 10),
|
20
|
+
# C alone in a package
|
21
|
+
(cls.product_c, 10),
|
22
|
+
]
|
23
|
+
)
|
24
|
+
cls.pack1_moves = picking.move_ids[:2]
|
25
|
+
cls.pack2_move = picking.move_ids[2]
|
26
|
+
cls._fill_stock_for_moves(cls.pack1_moves, in_package=True)
|
27
|
+
cls._fill_stock_for_moves(cls.pack2_move, in_package=True)
|
28
|
+
picking.action_assign()
|
29
|
+
# Some records not related at all to the processed picking
|
30
|
+
cls.free_package = cls.env["stock.quant.package"].create(
|
31
|
+
{"name": "FREE_PACKAGE"}
|
32
|
+
)
|
33
|
+
|
34
|
+
def test_reset_qty_done_pack_picking_not_found(self):
|
35
|
+
move_lines = self.pack1_moves.mapped("move_line_ids")
|
36
|
+
package = move_lines.mapped("package_id")
|
37
|
+
response = self.service.dispatch(
|
38
|
+
"reset_qty_done_pack", params={"package_id": package.id, "picking_id": -1}
|
39
|
+
)
|
40
|
+
self.assert_response_deliver(
|
41
|
+
response, message=self.service.msg_store.stock_picking_not_found()
|
42
|
+
)
|
43
|
+
|
44
|
+
def test_reset_qty_done_pack_package_not_found(self):
|
45
|
+
response = self.service.dispatch(
|
46
|
+
"reset_qty_done_pack",
|
47
|
+
params={"package_id": -1, "picking_id": self.picking.id},
|
48
|
+
)
|
49
|
+
self.assert_response_deliver(
|
50
|
+
response,
|
51
|
+
picking=self.picking,
|
52
|
+
message=self.service.msg_store.package_not_found(),
|
53
|
+
)
|
54
|
+
|
55
|
+
def test_reset_qty_done_pack_package_not_available_in_picking(self):
|
56
|
+
response = self.service.dispatch(
|
57
|
+
"reset_qty_done_pack",
|
58
|
+
params={"package_id": self.free_package.id, "picking_id": self.picking.id},
|
59
|
+
)
|
60
|
+
self.assert_response_deliver(
|
61
|
+
response,
|
62
|
+
picking=self.picking,
|
63
|
+
message=self.service.msg_store.package_not_available_in_picking(
|
64
|
+
self.free_package, self.picking
|
65
|
+
),
|
66
|
+
)
|
67
|
+
|
68
|
+
def test_reset_qty_done_pack_ok(self):
|
69
|
+
move_lines = self.pack1_moves.mapped("move_line_ids")
|
70
|
+
package = move_lines.mapped("package_id")
|
71
|
+
# Set qty done on a package, related move lines are "done"
|
72
|
+
self.service.dispatch(
|
73
|
+
"set_qty_done_pack",
|
74
|
+
params={"package_id": package.id, "picking_id": self.picking.id},
|
75
|
+
)
|
76
|
+
self.assertTrue(all(ml.qty_done == ml.reserved_uom_qty for ml in move_lines))
|
77
|
+
# Reset it, no related move lines are "done"
|
78
|
+
response = self.service.dispatch(
|
79
|
+
"reset_qty_done_pack",
|
80
|
+
params={"package_id": package.id, "picking_id": self.picking.id},
|
81
|
+
)
|
82
|
+
self.assert_response_deliver(response, picking=self.picking)
|
83
|
+
self.assertFalse(any(ml.qty_done > 0 for ml in move_lines))
|
84
|
+
|
85
|
+
def test_reset_qty_done_pack_picking_status(self):
|
86
|
+
package1 = self.pack1_moves.mapped("move_line_ids").mapped("package_id")
|
87
|
+
package2 = self.pack2_move.mapped("move_line_ids").mapped("package_id")
|
88
|
+
# Set qty done for all lines (all linked to packages here), picking is
|
89
|
+
# automatically set to done
|
90
|
+
self.service.dispatch(
|
91
|
+
"set_qty_done_pack",
|
92
|
+
params={"package_id": package1.id, "picking_id": self.picking.id},
|
93
|
+
)
|
94
|
+
self.service.dispatch(
|
95
|
+
"set_qty_done_pack",
|
96
|
+
params={"package_id": package2.id, "picking_id": self.picking.id},
|
97
|
+
)
|
98
|
+
self.assertEqual(self.picking.state, "done")
|
99
|
+
# Try to reset one of them => picking already processed
|
100
|
+
response = self.service.dispatch(
|
101
|
+
"reset_qty_done_pack",
|
102
|
+
params={"package_id": package1.id, "picking_id": self.picking.id},
|
103
|
+
)
|
104
|
+
self.assert_response_deliver(
|
105
|
+
response, message=self.service.msg_store.already_done()
|
106
|
+
)
|
107
|
+
self.assertEqual(self.picking.state, "done")
|