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,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")