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.
Files changed (182) hide show
  1. odoo/addons/shopfloor/README.rst +160 -0
  2. odoo/addons/shopfloor/__init__.py +4 -0
  3. odoo/addons/shopfloor/__manifest__.py +65 -0
  4. odoo/addons/shopfloor/actions/__init__.py +15 -0
  5. odoo/addons/shopfloor/actions/change_package_lot.py +164 -0
  6. odoo/addons/shopfloor/actions/completion_info.py +42 -0
  7. odoo/addons/shopfloor/actions/data.py +329 -0
  8. odoo/addons/shopfloor/actions/data_detail.py +154 -0
  9. odoo/addons/shopfloor/actions/inventory.py +150 -0
  10. odoo/addons/shopfloor/actions/location_content_transfer_sorter.py +89 -0
  11. odoo/addons/shopfloor/actions/message.py +846 -0
  12. odoo/addons/shopfloor/actions/move_line_search.py +119 -0
  13. odoo/addons/shopfloor/actions/packaging.py +59 -0
  14. odoo/addons/shopfloor/actions/savepoint.py +44 -0
  15. odoo/addons/shopfloor/actions/schema.py +182 -0
  16. odoo/addons/shopfloor/actions/schema_detail.py +98 -0
  17. odoo/addons/shopfloor/actions/search.py +187 -0
  18. odoo/addons/shopfloor/actions/stock.py +239 -0
  19. odoo/addons/shopfloor/actions/stock_unreserve.py +66 -0
  20. odoo/addons/shopfloor/components/__init__.py +5 -0
  21. odoo/addons/shopfloor/components/scan_handler_location.py +26 -0
  22. odoo/addons/shopfloor/components/scan_handler_lot.py +26 -0
  23. odoo/addons/shopfloor/components/scan_handler_package.py +26 -0
  24. odoo/addons/shopfloor/components/scan_handler_product.py +26 -0
  25. odoo/addons/shopfloor/components/scan_handler_transfer.py +26 -0
  26. odoo/addons/shopfloor/data/shopfloor_scenario_data.xml +73 -0
  27. odoo/addons/shopfloor/demo/shopfloor_app_demo.xml +12 -0
  28. odoo/addons/shopfloor/demo/shopfloor_menu_demo.xml +64 -0
  29. odoo/addons/shopfloor/demo/shopfloor_profile_demo.xml +8 -0
  30. odoo/addons/shopfloor/demo/stock_picking_type_demo.xml +93 -0
  31. odoo/addons/shopfloor/docs/checkout_diag_seq.plantuml +61 -0
  32. odoo/addons/shopfloor/docs/checkout_diag_seq.png +0 -0
  33. odoo/addons/shopfloor/docs/cluster_picking_diag_seq.plantuml +112 -0
  34. odoo/addons/shopfloor/docs/cluster_picking_diag_seq.png +0 -0
  35. odoo/addons/shopfloor/docs/delivery_diag_seq.plantuml +56 -0
  36. odoo/addons/shopfloor/docs/delivery_diag_seq.png +0 -0
  37. odoo/addons/shopfloor/docs/location_content_transfer_diag_seq.plantuml +66 -0
  38. odoo/addons/shopfloor/docs/location_content_transfer_diag_seq.png +0 -0
  39. odoo/addons/shopfloor/docs/oca_logo.png +0 -0
  40. odoo/addons/shopfloor/docs/single_pack_transfer_diag_seq.plantuml +36 -0
  41. odoo/addons/shopfloor/docs/single_pack_transfer_diag_seq.png +0 -0
  42. odoo/addons/shopfloor/docs/zone_picking_diag_seq.plantuml +85 -0
  43. odoo/addons/shopfloor/docs/zone_picking_diag_seq.png +0 -0
  44. odoo/addons/shopfloor/exceptions.py +6 -0
  45. odoo/addons/shopfloor/i18n/ca.po +1802 -0
  46. odoo/addons/shopfloor/i18n/de.po +1791 -0
  47. odoo/addons/shopfloor/i18n/es_AR.po +2147 -0
  48. odoo/addons/shopfloor/i18n/pt_BR.po +1791 -0
  49. odoo/addons/shopfloor/i18n/shopfloor.pot +1877 -0
  50. odoo/addons/shopfloor/models/__init__.py +12 -0
  51. odoo/addons/shopfloor/models/priority_postpone_mixin.py +41 -0
  52. odoo/addons/shopfloor/models/shopfloor_app.py +9 -0
  53. odoo/addons/shopfloor/models/shopfloor_menu.py +436 -0
  54. odoo/addons/shopfloor/models/stock_location.py +76 -0
  55. odoo/addons/shopfloor/models/stock_move.py +119 -0
  56. odoo/addons/shopfloor/models/stock_move_line.py +307 -0
  57. odoo/addons/shopfloor/models/stock_package_level.py +50 -0
  58. odoo/addons/shopfloor/models/stock_picking.py +118 -0
  59. odoo/addons/shopfloor/models/stock_picking_batch.py +41 -0
  60. odoo/addons/shopfloor/models/stock_picking_type.py +26 -0
  61. odoo/addons/shopfloor/models/stock_quant.py +31 -0
  62. odoo/addons/shopfloor/models/stock_quant_package.py +101 -0
  63. odoo/addons/shopfloor/readme/CONTRIBUTORS.rst +18 -0
  64. odoo/addons/shopfloor/readme/CREDITS.rst +5 -0
  65. odoo/addons/shopfloor/readme/DESCRIPTION.rst +17 -0
  66. odoo/addons/shopfloor/readme/HISTORY.rst +4 -0
  67. odoo/addons/shopfloor/readme/ROADMAP.rst +4 -0
  68. odoo/addons/shopfloor/readme/USAGE.rst +6 -0
  69. odoo/addons/shopfloor/security/groups.xml +17 -0
  70. odoo/addons/shopfloor/services/__init__.py +16 -0
  71. odoo/addons/shopfloor/services/checkout.py +1763 -0
  72. odoo/addons/shopfloor/services/cluster_picking.py +1628 -0
  73. odoo/addons/shopfloor/services/delivery.py +828 -0
  74. odoo/addons/shopfloor/services/forms/__init__.py +1 -0
  75. odoo/addons/shopfloor/services/forms/picking_form.py +78 -0
  76. odoo/addons/shopfloor/services/location_content_transfer.py +1194 -0
  77. odoo/addons/shopfloor/services/menu.py +60 -0
  78. odoo/addons/shopfloor/services/picking_batch.py +126 -0
  79. odoo/addons/shopfloor/services/service.py +101 -0
  80. odoo/addons/shopfloor/services/single_pack_transfer.py +366 -0
  81. odoo/addons/shopfloor/services/zone_picking.py +1938 -0
  82. odoo/addons/shopfloor/static/description/icon.png +0 -0
  83. odoo/addons/shopfloor/static/description/index.html +500 -0
  84. odoo/addons/shopfloor/tests/__init__.py +83 -0
  85. odoo/addons/shopfloor/tests/common.py +324 -0
  86. odoo/addons/shopfloor/tests/models.py +29 -0
  87. odoo/addons/shopfloor/tests/test_actions_change_package_lot.py +1175 -0
  88. odoo/addons/shopfloor/tests/test_actions_data.py +376 -0
  89. odoo/addons/shopfloor/tests/test_actions_data_base.py +244 -0
  90. odoo/addons/shopfloor/tests/test_actions_data_detail.py +322 -0
  91. odoo/addons/shopfloor/tests/test_actions_search.py +248 -0
  92. odoo/addons/shopfloor/tests/test_actions_stock.py +48 -0
  93. odoo/addons/shopfloor/tests/test_checkout_auto_post.py +67 -0
  94. odoo/addons/shopfloor/tests/test_checkout_base.py +81 -0
  95. odoo/addons/shopfloor/tests/test_checkout_cancel_line.py +154 -0
  96. odoo/addons/shopfloor/tests/test_checkout_change_packaging.py +184 -0
  97. odoo/addons/shopfloor/tests/test_checkout_done.py +133 -0
  98. odoo/addons/shopfloor/tests/test_checkout_list_delivery_packaging.py +131 -0
  99. odoo/addons/shopfloor/tests/test_checkout_list_package.py +327 -0
  100. odoo/addons/shopfloor/tests/test_checkout_new_package.py +88 -0
  101. odoo/addons/shopfloor/tests/test_checkout_no_package.py +95 -0
  102. odoo/addons/shopfloor/tests/test_checkout_scan.py +174 -0
  103. odoo/addons/shopfloor/tests/test_checkout_scan_line.py +377 -0
  104. odoo/addons/shopfloor/tests/test_checkout_scan_line_base.py +25 -0
  105. odoo/addons/shopfloor/tests/test_checkout_scan_line_no_prefill_qty.py +91 -0
  106. odoo/addons/shopfloor/tests/test_checkout_scan_package_action.py +451 -0
  107. odoo/addons/shopfloor/tests/test_checkout_scan_package_action_no_prefill_qty.py +107 -0
  108. odoo/addons/shopfloor/tests/test_checkout_select.py +74 -0
  109. odoo/addons/shopfloor/tests/test_checkout_select_line.py +130 -0
  110. odoo/addons/shopfloor/tests/test_checkout_select_package_base.py +64 -0
  111. odoo/addons/shopfloor/tests/test_checkout_set_qty.py +257 -0
  112. odoo/addons/shopfloor/tests/test_checkout_summary.py +69 -0
  113. odoo/addons/shopfloor/tests/test_cluster_picking_base.py +83 -0
  114. odoo/addons/shopfloor/tests/test_cluster_picking_batch.py +109 -0
  115. odoo/addons/shopfloor/tests/test_cluster_picking_change_pack_lot.py +111 -0
  116. odoo/addons/shopfloor/tests/test_cluster_picking_is_zero.py +98 -0
  117. odoo/addons/shopfloor/tests/test_cluster_picking_scan_destination.py +376 -0
  118. odoo/addons/shopfloor/tests/test_cluster_picking_scan_destination_no_prefill_qty.py +115 -0
  119. odoo/addons/shopfloor/tests/test_cluster_picking_scan_line.py +402 -0
  120. odoo/addons/shopfloor/tests/test_cluster_picking_scan_line_location_or_pack_first.py +114 -0
  121. odoo/addons/shopfloor/tests/test_cluster_picking_scan_line_no_prefill_qty.py +70 -0
  122. odoo/addons/shopfloor/tests/test_cluster_picking_select.py +387 -0
  123. odoo/addons/shopfloor/tests/test_cluster_picking_skip.py +90 -0
  124. odoo/addons/shopfloor/tests/test_cluster_picking_stock_issue.py +364 -0
  125. odoo/addons/shopfloor/tests/test_cluster_picking_unload.py +911 -0
  126. odoo/addons/shopfloor/tests/test_delivery_base.py +155 -0
  127. odoo/addons/shopfloor/tests/test_delivery_done.py +108 -0
  128. odoo/addons/shopfloor/tests/test_delivery_list_stock_picking.py +49 -0
  129. odoo/addons/shopfloor/tests/test_delivery_reset_qty_done_line.py +119 -0
  130. odoo/addons/shopfloor/tests/test_delivery_reset_qty_done_pack.py +107 -0
  131. odoo/addons/shopfloor/tests/test_delivery_scan_deliver.py +557 -0
  132. odoo/addons/shopfloor/tests/test_delivery_select.py +38 -0
  133. odoo/addons/shopfloor/tests/test_delivery_set_qty_done_line.py +91 -0
  134. odoo/addons/shopfloor/tests/test_delivery_set_qty_done_pack.py +135 -0
  135. odoo/addons/shopfloor/tests/test_delivery_sublocation.py +180 -0
  136. odoo/addons/shopfloor/tests/test_location_content_transfer_base.py +136 -0
  137. odoo/addons/shopfloor/tests/test_location_content_transfer_get_work.py +125 -0
  138. odoo/addons/shopfloor/tests/test_location_content_transfer_mix.py +509 -0
  139. odoo/addons/shopfloor/tests/test_location_content_transfer_putaway.py +143 -0
  140. odoo/addons/shopfloor/tests/test_location_content_transfer_scan_location.py +34 -0
  141. odoo/addons/shopfloor/tests/test_location_content_transfer_set_destination_all.py +343 -0
  142. odoo/addons/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py +1074 -0
  143. odoo/addons/shopfloor/tests/test_location_content_transfer_single.py +748 -0
  144. odoo/addons/shopfloor/tests/test_location_content_transfer_start.py +359 -0
  145. odoo/addons/shopfloor/tests/test_menu_base.py +261 -0
  146. odoo/addons/shopfloor/tests/test_menu_counters.py +61 -0
  147. odoo/addons/shopfloor/tests/test_misc.py +25 -0
  148. odoo/addons/shopfloor/tests/test_move_action_assign.py +87 -0
  149. odoo/addons/shopfloor/tests/test_openapi.py +21 -0
  150. odoo/addons/shopfloor/tests/test_picking_form.py +62 -0
  151. odoo/addons/shopfloor/tests/test_scan_anything.py +49 -0
  152. odoo/addons/shopfloor/tests/test_single_pack_transfer.py +1121 -0
  153. odoo/addons/shopfloor/tests/test_single_pack_transfer_base.py +32 -0
  154. odoo/addons/shopfloor/tests/test_single_pack_transfer_putaway.py +104 -0
  155. odoo/addons/shopfloor/tests/test_stock_split.py +204 -0
  156. odoo/addons/shopfloor/tests/test_user.py +42 -0
  157. odoo/addons/shopfloor/tests/test_zone_picking_base.py +608 -0
  158. odoo/addons/shopfloor/tests/test_zone_picking_change_pack_lot.py +140 -0
  159. odoo/addons/shopfloor/tests/test_zone_picking_select_line.py +723 -0
  160. odoo/addons/shopfloor/tests/test_zone_picking_select_line_first_scan_location.py +207 -0
  161. odoo/addons/shopfloor/tests/test_zone_picking_select_line_first_scan_location.py.bak +202 -0
  162. odoo/addons/shopfloor/tests/test_zone_picking_select_line_no_prefill_qty.py +107 -0
  163. odoo/addons/shopfloor/tests/test_zone_picking_select_picking_type.py +26 -0
  164. odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination.py +643 -0
  165. odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_no_prefill_qty.py +146 -0
  166. odoo/addons/shopfloor/tests/test_zone_picking_set_line_destination_pick_pack.py +241 -0
  167. odoo/addons/shopfloor/tests/test_zone_picking_start.py +206 -0
  168. odoo/addons/shopfloor/tests/test_zone_picking_stock_issue.py +121 -0
  169. odoo/addons/shopfloor/tests/test_zone_picking_unload_all.py +353 -0
  170. odoo/addons/shopfloor/tests/test_zone_picking_unload_buffer_lines.py +113 -0
  171. odoo/addons/shopfloor/tests/test_zone_picking_unload_set_destination.py +374 -0
  172. odoo/addons/shopfloor/tests/test_zone_picking_unload_single.py +123 -0
  173. odoo/addons/shopfloor/tests/test_zone_picking_zero_check.py +43 -0
  174. odoo/addons/shopfloor/utils.py +13 -0
  175. odoo/addons/shopfloor/views/shopfloor_menu.xml +167 -0
  176. odoo/addons/shopfloor/views/stock_location.xml +20 -0
  177. odoo/addons/shopfloor/views/stock_move_line.xml +52 -0
  178. odoo/addons/shopfloor/views/stock_picking_type.xml +19 -0
  179. odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/METADATA +192 -0
  180. odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/RECORD +182 -0
  181. odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/WHEEL +5 -0
  182. odoo_addon_shopfloor-16.0.1.0.0.24.dist-info/top_level.txt +1 -0
@@ -0,0 +1,146 @@
1
+ # Copyright 2022 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 ZonePickingSetLineDestinationNoPrefillQtyCase(ZonePickingCommonCase):
8
+ """Tests for endpoint used from set_line_destination
9
+
10
+ With the no prefill quantity option set
11
+
12
+ * /set_destination
13
+ """
14
+
15
+ def setUp(self):
16
+ super().setUp()
17
+ self.service.work.current_picking_type = self.picking2.picking_type_id
18
+ self.menu.sudo().no_prefill_qty = True
19
+
20
+ def test_set_destination_increment_with_product(self):
21
+ """Check increment quantity by scanning the product."""
22
+ picking_type = self.picking2.picking_type_id
23
+ move_line = self.picking2.move_line_ids[0]
24
+ # Scan twice the product in a row to increment the quantity
25
+ for qty_done in range(2):
26
+ response = self.service.dispatch(
27
+ "set_destination",
28
+ params={
29
+ "move_line_id": move_line.id,
30
+ "barcode": move_line.product_id.barcode,
31
+ "quantity": qty_done,
32
+ },
33
+ )
34
+ qty_done += 1
35
+ # Check response
36
+ self.assert_response_set_line_destination(
37
+ response,
38
+ self.zone_location,
39
+ picking_type,
40
+ move_line,
41
+ qty_done=qty_done,
42
+ )
43
+
44
+ def test_set_destination_increment_with_wrong_package(self):
45
+ """Check scanning wrong package incremented quantity is not lost."""
46
+ wrong_package = self.picking1.move_line_ids.package_id
47
+ picking_type = self.picking2.picking_type_id
48
+ move_line = self.picking2.move_line_ids[0]
49
+ # Simulate the product has been scanned twice
50
+ qty_done = 2
51
+ response = self.service.dispatch(
52
+ "set_destination",
53
+ params={
54
+ "move_line_id": move_line.id,
55
+ "barcode": wrong_package.name,
56
+ "quantity": qty_done,
57
+ },
58
+ )
59
+ # Check response
60
+ self.assert_response_set_line_destination(
61
+ response,
62
+ self.zone_location,
63
+ picking_type,
64
+ move_line,
65
+ qty_done=qty_done,
66
+ message={
67
+ "body": "Package {} is not empty.".format(wrong_package.name),
68
+ "message_type": "warning",
69
+ },
70
+ )
71
+
72
+ def test_set_destination_increment_with_wrong_product(self):
73
+ """Check increment quantity by scanning the wrong product."""
74
+ picking_type = self.picking2.picking_type_id
75
+ move_line = self.picking2.move_line_ids[0]
76
+ # Scan twice the product in a row to increment the quantity
77
+ qty_done = 2
78
+ response = self.service.dispatch(
79
+ "set_destination",
80
+ params={
81
+ "move_line_id": move_line.id,
82
+ "barcode": self.product_a.barcode,
83
+ "quantity": qty_done,
84
+ },
85
+ )
86
+ # Check response
87
+ self.assert_response_set_line_destination(
88
+ response,
89
+ self.zone_location,
90
+ picking_type,
91
+ move_line,
92
+ qty_done=qty_done,
93
+ message={"body": "The package A doesn't exist", "message_type": "error"},
94
+ )
95
+
96
+ def test_set_destination_increment_with_lot(self):
97
+ """Check increment quantity by scanning the lot."""
98
+ picking_type = self.picking2.picking_type_id
99
+ move_line = self.picking2.move_line_ids.filtered("lot_id")[0]
100
+ # Scan twice the lot in a row to increment the quantity
101
+ for qty_done in range(2):
102
+ response = self.service.dispatch(
103
+ "set_destination",
104
+ params={
105
+ "move_line_id": move_line.id,
106
+ "barcode": move_line.lot_id.name,
107
+ "quantity": qty_done,
108
+ },
109
+ )
110
+ qty_done += 1
111
+ # Check response
112
+ self.assert_response_set_line_destination(
113
+ response,
114
+ self.zone_location,
115
+ picking_type,
116
+ move_line,
117
+ qty_done=qty_done,
118
+ )
119
+
120
+ def test_set_destination_location_zero_quantity(self):
121
+ """Scanned barcode is the destination location.
122
+
123
+ Quantity to move is zero -> error raised, user can try again.
124
+
125
+ """
126
+ zone_location = self.zone_location
127
+ picking_type = self.picking1.picking_type_id
128
+ move_line = self.picking1.move_ids.move_line_ids
129
+ response = self.service.dispatch(
130
+ "set_destination",
131
+ params={
132
+ "move_line_id": move_line.id,
133
+ "barcode": self.packing_location.barcode,
134
+ "quantity": 0,
135
+ },
136
+ )
137
+ # Check response
138
+ self.assert_response_set_line_destination(
139
+ response,
140
+ zone_location,
141
+ picking_type,
142
+ move_line,
143
+ message=self.service.msg_store.picking_zero_quantity(),
144
+ # And that the quantity done is zero
145
+ qty_done=0,
146
+ )
@@ -0,0 +1,241 @@
1
+ # Copyright 2021 Camptocamp SA (http://www.camptocamp.com)
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3
+ from odoo_test_helper import FakeModelLoader
4
+
5
+ from .test_zone_picking_base import ZonePickingCommonCase
6
+
7
+
8
+ # pylint: disable=missing-return
9
+ class ZonePickingSetLineDestinationPickPackCase(ZonePickingCommonCase):
10
+ """Tests set_line_destination when `pick_pack_same_time` is one
11
+
12
+ * /set_destination
13
+
14
+ """
15
+
16
+ @classmethod
17
+ def setUpClass(cls):
18
+ try:
19
+ super().setUpClass()
20
+ except BaseException:
21
+ # ensure that the registry is restored in case of error in setUpClass
22
+ # since tearDownClass is not called in this case and our _load_test_models
23
+ # loads fake models
24
+ if hasattr(cls, "loader"):
25
+ cls.loader.restore_registry()
26
+ raise
27
+
28
+ @classmethod
29
+ def _load_test_models(cls):
30
+ cls.loader = FakeModelLoader(cls.env, cls.__module__)
31
+ cls.loader.backup_registry()
32
+ from .models import DeliveryCarrierTest, StockPackageType
33
+
34
+ cls.loader.update_registry((DeliveryCarrierTest, StockPackageType))
35
+
36
+ @classmethod
37
+ def tearDownClass(cls):
38
+ cls.loader.restore_registry()
39
+ super().tearDownClass()
40
+
41
+ @classmethod
42
+ def setUpClassBaseData(cls, *args, **kwargs):
43
+ super().setUpClassBaseData(*args, **kwargs)
44
+ cls._load_test_models()
45
+ cls.carrier = cls.env["delivery.carrier"].search([], limit=1)
46
+ delivery_packaging_type = (
47
+ cls.env["stock.package.type"]
48
+ .sudo()
49
+ .create({"name": "TEST DEFAULT", "package_carrier_type": "test"})
50
+ )
51
+ cls.carrier.sudo().write(
52
+ {
53
+ "delivery_type": "test",
54
+ "integration_level": "rate", # avoid sending emails
55
+ "test_default_packaging_id": delivery_packaging_type.id,
56
+ }
57
+ )
58
+
59
+ def setUp(self):
60
+ super().setUp()
61
+ self.service.work.current_picking_type = self.picking1.picking_type_id
62
+ self.menu.sudo().pick_pack_same_time = True
63
+
64
+ def test_set_destination_location_no_carrier(self):
65
+ """Scan location but carrier not set on picking"""
66
+ zone_location = self.zone_location
67
+ picking_type = self.picking1.picking_type_id
68
+ move_line = self.picking1.move_line_ids
69
+ move_line.location_dest_id = self.shelf1
70
+ quantity_done = move_line.reserved_uom_qty
71
+ previous_qty_done = move_line.qty_done
72
+ # Confirm the destination with the right destination
73
+ response = self.service.dispatch(
74
+ "set_destination",
75
+ params={
76
+ "move_line_id": move_line.id,
77
+ "barcode": self.packing_location.barcode,
78
+ "quantity": quantity_done,
79
+ "confirmation": True,
80
+ },
81
+ )
82
+ self.assertEqual(move_line.qty_done, previous_qty_done)
83
+ self.assert_response_set_line_destination(
84
+ response,
85
+ zone_location,
86
+ picking_type,
87
+ move_line,
88
+ message=self.service.msg_store.picking_without_carrier_cannot_pack(
89
+ move_line.picking_id
90
+ ),
91
+ qty_done=quantity_done,
92
+ )
93
+
94
+ def test_set_destination_location_ok_carrier(self):
95
+ """When carried is set goods are packed into new delivery package."""
96
+ existing_packages = self.env["stock.quant.package"].search([])
97
+ zone_location = self.zone_location
98
+ picking_type = self.picking1.picking_type_id
99
+ move_line = self.picking1.move_line_ids
100
+ move_line.location_dest_id = self.shelf1
101
+ move_line.picking_id.carrier_id = self.carrier
102
+ response = self.service.dispatch(
103
+ "set_destination",
104
+ params={
105
+ "move_line_id": move_line.id,
106
+ "barcode": self.packing_location.barcode,
107
+ "quantity": move_line.reserved_uom_qty,
108
+ "confirmation": True,
109
+ },
110
+ )
111
+ # Check response
112
+ move_lines = self.service._find_location_move_lines()
113
+ move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
114
+ delivery_pkg = move_line.result_package_id
115
+ self.assertNotIn(delivery_pkg, existing_packages)
116
+ self.assertEqual(
117
+ delivery_pkg.package_type_id, self.carrier.test_default_packaging_id
118
+ )
119
+ message = self.msg_store.confirm_pack_moved()
120
+ message["body"] += "\n" + self.msg_store.goods_packed_in(delivery_pkg)["body"]
121
+ self.assert_response_select_line(
122
+ response,
123
+ zone_location,
124
+ picking_type,
125
+ move_lines,
126
+ message=message,
127
+ )
128
+
129
+ def test_set_destination_package_full_qty_no_carrier(self):
130
+ """Scan destination package, no carrier on picking."""
131
+ zone_location = self.zone_location
132
+ picking_type = self.picking1.picking_type_id
133
+ moves_before = self.picking1.move_ids
134
+ self.assertEqual(len(moves_before), 1)
135
+ self.assertEqual(len(moves_before.move_line_ids), 1)
136
+ move_line = moves_before.move_line_ids
137
+ quantity_done = move_line.reserved_uom_qty
138
+ response = self.service.dispatch(
139
+ "set_destination",
140
+ params={
141
+ "move_line_id": move_line.id,
142
+ "barcode": self.free_package.name,
143
+ "quantity": quantity_done,
144
+ "confirmation": True,
145
+ },
146
+ )
147
+ self.assert_response_set_line_destination(
148
+ response,
149
+ zone_location,
150
+ picking_type,
151
+ move_line,
152
+ message=self.service.msg_store.picking_without_carrier_cannot_pack(
153
+ move_line.picking_id
154
+ ),
155
+ qty_done=quantity_done,
156
+ )
157
+
158
+ def test_set_destination_package_full_qty_ok_carrier_bad_package(self):
159
+ """Scan destination package, carrier on picking, package invalid."""
160
+ zone_location = self.zone_location
161
+ picking_type = self.picking1.picking_type_id
162
+ moves_before = self.picking1.move_ids
163
+ self.assertEqual(len(moves_before), 1)
164
+ self.assertEqual(len(moves_before.move_line_ids), 1)
165
+ move_line = moves_before.move_line_ids
166
+ move_line.picking_id.carrier_id = self.carrier
167
+ quantity_done = move_line.reserved_uom_qty
168
+ response = self.service.dispatch(
169
+ "set_destination",
170
+ params={
171
+ "move_line_id": move_line.id,
172
+ "barcode": self.free_package.name,
173
+ "quantity": quantity_done,
174
+ "confirmation": False,
175
+ },
176
+ )
177
+ self.assert_response_set_line_destination(
178
+ response,
179
+ zone_location,
180
+ picking_type,
181
+ move_line,
182
+ message=self.service.msg_store.packaging_invalid_for_carrier(
183
+ self.free_package.product_packaging_id, self.carrier
184
+ ),
185
+ qty_done=quantity_done,
186
+ )
187
+
188
+ def test_set_destination_package_full_qty_ok_carrier_ok_package(self):
189
+ """Scan destination package, carrier on picking, package valid."""
190
+ zone_location = self.zone_location
191
+ picking_type = self.picking1.picking_type_id
192
+ moves_before = self.picking1.move_ids
193
+ self.assertEqual(len(moves_before), 1)
194
+ self.assertEqual(len(moves_before.move_line_ids), 1)
195
+ move_line = moves_before.move_line_ids
196
+ move_line.picking_id.carrier_id = self.carrier
197
+ packaging = (
198
+ self.env["product.packaging"]
199
+ .sudo()
200
+ .create(
201
+ {
202
+ "name": "TEST DEFAULT",
203
+ "package_type_id": self.carrier.test_default_packaging_id.id,
204
+ }
205
+ )
206
+ )
207
+
208
+ self.free_package.product_packaging_id = packaging
209
+ response = self.service.dispatch(
210
+ "set_destination",
211
+ params={
212
+ "move_line_id": move_line.id,
213
+ "barcode": self.free_package.name,
214
+ "quantity": move_line.reserved_uom_qty,
215
+ "confirmation": True,
216
+ },
217
+ )
218
+ # Check picking data
219
+ moves_after = self.picking1.move_ids
220
+ self.assertEqual(moves_before, moves_after)
221
+ self.assertRecordValues(
222
+ move_line,
223
+ [
224
+ {
225
+ "result_package_id": self.free_package.id,
226
+ "reserved_uom_qty": 10,
227
+ "qty_done": 10,
228
+ "shopfloor_user_id": self.env.user.id,
229
+ },
230
+ ],
231
+ )
232
+ # Check response
233
+ move_lines = self.service._find_location_move_lines()
234
+ move_lines = move_lines.sorted(lambda l: l.move_id.priority, reverse=True)
235
+ self.assert_response_select_line(
236
+ response,
237
+ zone_location,
238
+ picking_type,
239
+ move_lines,
240
+ message=self.service.msg_store.confirm_pack_moved(),
241
+ )
@@ -0,0 +1,206 @@
1
+ # Copyright 2020 Camptocamp SA (http://www.camptocamp.com)
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3
+ from .test_zone_picking_base import ZonePickingCommonCase
4
+
5
+ # pylint: disable=missing-return
6
+
7
+
8
+ class ZonePickingStartCase(ZonePickingCommonCase):
9
+ """Tests for endpoint used from start
10
+
11
+ * /scan_location
12
+
13
+ """
14
+
15
+ @classmethod
16
+ def setUpClassBaseData(cls, *args, **kwargs):
17
+ super().setUpClassBaseData(*args, **kwargs)
18
+ # create a picking w/ a different picking type
19
+ # which should be excluded from picking types list
20
+ bad_picking_type = cls.picking_type.sudo().copy(
21
+ {
22
+ "name": "Bad type",
23
+ "sequence_code": "WH/BAD",
24
+ "default_location_src_id": cls.zone_location.id,
25
+ "shopfloor_menu_ids": False,
26
+ }
27
+ )
28
+ cls.extra_picking = extra_picking = cls._create_picking(
29
+ lines=[(cls.product_b, 10)],
30
+ picking_type=bad_picking_type,
31
+ )
32
+ cls._fill_stock_for_moves(
33
+ extra_picking.move_ids, in_package=True, location=cls.zone_sublocation1
34
+ )
35
+ cls._update_qty_in_location(cls.zone_sublocation1, cls.product_b, 10)
36
+ extra_picking.action_assign()
37
+
38
+ def test_data_for_zone(self):
39
+ op_type_data = self.data.picking_type(self.menu.picking_type_ids[0])
40
+ zones_data = self.service._response_for_start()["data"]["start"]["zones"]
41
+ expected_sub1 = dict(
42
+ self.data.location(self.zone_sublocation1),
43
+ lines_count=1,
44
+ picking_count=1,
45
+ priority_lines_count=0,
46
+ priority_picking_count=0,
47
+ operation_types=[
48
+ dict(
49
+ op_type_data,
50
+ lines_count=1,
51
+ picking_count=1,
52
+ priority_lines_count=0,
53
+ priority_picking_count=0,
54
+ )
55
+ ],
56
+ )
57
+ expected_sub2 = dict(
58
+ self.data.location(self.zone_sublocation2),
59
+ lines_count=2,
60
+ picking_count=2,
61
+ priority_lines_count=0,
62
+ priority_picking_count=0,
63
+ operation_types=[
64
+ dict(
65
+ op_type_data,
66
+ lines_count=2,
67
+ picking_count=2,
68
+ priority_lines_count=0,
69
+ priority_picking_count=0,
70
+ )
71
+ ],
72
+ )
73
+ expected_sub3 = dict(
74
+ self.data.location(self.zone_sublocation3),
75
+ lines_count=2,
76
+ picking_count=2,
77
+ priority_lines_count=0,
78
+ priority_picking_count=0,
79
+ operation_types=[
80
+ dict(
81
+ op_type_data,
82
+ lines_count=2,
83
+ picking_count=2,
84
+ priority_lines_count=0,
85
+ priority_picking_count=0,
86
+ )
87
+ ],
88
+ )
89
+ expected_sub4 = dict(
90
+ self.data.location(self.zone_sublocation4),
91
+ lines_count=3,
92
+ picking_count=3,
93
+ priority_lines_count=0,
94
+ priority_picking_count=0,
95
+ operation_types=[
96
+ dict(
97
+ op_type_data,
98
+ lines_count=3,
99
+ picking_count=3,
100
+ priority_lines_count=0,
101
+ priority_picking_count=0,
102
+ )
103
+ ],
104
+ )
105
+ expected_sub5 = dict(
106
+ self.data.location(self.zone_sublocation5),
107
+ lines_count=2,
108
+ picking_count=1,
109
+ priority_lines_count=0,
110
+ priority_picking_count=0,
111
+ operation_types=[
112
+ dict(
113
+ op_type_data,
114
+ lines_count=2,
115
+ picking_count=1,
116
+ priority_lines_count=0,
117
+ priority_picking_count=0,
118
+ )
119
+ ],
120
+ )
121
+ self.assertEqual(
122
+ zones_data,
123
+ [expected_sub1, expected_sub2, expected_sub3, expected_sub4, expected_sub5],
124
+ )
125
+
126
+ def test_select_zone(self):
127
+ """Scanned location invalid, no location found."""
128
+ response = self.service.dispatch("select_zone")
129
+ self.assert_response_start(response)
130
+
131
+ def test_select_zone_with_loaded_buffer(self):
132
+ """Check loaded buffer info in select zone answer."""
133
+ zone_location = self.zone_location
134
+ picking_type = self.picking1.picking_type_id
135
+ move_line = self.picking5.move_line_ids[1]
136
+ # change the destination location on the move line
137
+ move_line.location_dest_id = self.zone_sublocation3
138
+ # and set the destination package
139
+ self.service._set_destination_package(
140
+ move_line,
141
+ move_line.reserved_uom_qty,
142
+ self.free_package,
143
+ )
144
+ response = self.service.dispatch("select_zone")
145
+ data = {
146
+ "zones": self.service._data_for_select_zone(zone_location.child_ids),
147
+ "buffer": {
148
+ "zone_location": self.service.data.location(zone_location),
149
+ "picking_type": self.service.data.picking_type(picking_type),
150
+ },
151
+ }
152
+ self.assert_response(
153
+ response,
154
+ next_state="start",
155
+ data=data,
156
+ )
157
+
158
+ def test_scan_location_wrong_barcode(self):
159
+ """Scanned location invalid, no location found."""
160
+ response = self.service.dispatch(
161
+ "scan_location",
162
+ params={"barcode": "UNKNOWN LOCATION"},
163
+ )
164
+ self.assert_response_start(
165
+ response,
166
+ message=self.service.msg_store.no_location_found(),
167
+ )
168
+
169
+ def test_scan_location_not_allowed(self):
170
+ """Scanned location not allowed because it's not a child of picking
171
+ types' source location.
172
+ """
173
+ response = self.service.dispatch(
174
+ "scan_location",
175
+ params={"barcode": self.customer_location.barcode},
176
+ )
177
+ self.assert_response_start(
178
+ response,
179
+ message=self.service.msg_store.location_not_allowed(),
180
+ )
181
+
182
+ def test_scan_location_no_move_lines(self):
183
+ """Scanned location valid, but no move lines found in it."""
184
+ sub1_lines = self.service._find_location_move_lines(self.zone_sublocation1)
185
+ # no more lines available
186
+ sub1_lines.picking_id.action_cancel()
187
+ response = self.service.dispatch(
188
+ "scan_location",
189
+ params={"barcode": self.zone_sublocation1.barcode},
190
+ )
191
+ self.assert_response_start(
192
+ response,
193
+ message=self.service.msg_store.no_lines_to_process(),
194
+ )
195
+
196
+ def test_scan_location_ok(self):
197
+ """Scanned location valid, list of picking types of related move lines."""
198
+ response = self.service.dispatch(
199
+ "scan_location",
200
+ params={"barcode": self.zone_location.barcode},
201
+ )
202
+ self.assert_response_select_picking_type(
203
+ response,
204
+ zone_location=self.zone_location,
205
+ picking_types=self.picking_type,
206
+ )