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,324 @@
|
|
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 collections import namedtuple
|
4
|
+
|
5
|
+
from odoo import models
|
6
|
+
from odoo.tests.common import Form
|
7
|
+
|
8
|
+
from odoo.addons.shopfloor_base.tests.common import CommonCase as BaseCommonCase
|
9
|
+
|
10
|
+
|
11
|
+
# pylint: disable=missing-return
|
12
|
+
class CommonCase(BaseCommonCase):
|
13
|
+
@classmethod
|
14
|
+
def setUpShopfloorApp(cls):
|
15
|
+
cls.shopfloor_app = cls.env.ref("shopfloor.app_demo").with_user(
|
16
|
+
cls.shopfloor_user
|
17
|
+
)
|
18
|
+
|
19
|
+
@classmethod
|
20
|
+
def setUpClassVars(cls):
|
21
|
+
super().setUpClassVars()
|
22
|
+
stock_location = cls.env.ref("stock.stock_location_stock")
|
23
|
+
cls.stock_location = stock_location
|
24
|
+
cls.customer_location = cls.env.ref("stock.stock_location_customers")
|
25
|
+
cls.dispatch_location = cls.env.ref("stock.location_dispatch_zone")
|
26
|
+
cls.packing_location = cls.env.ref("stock.location_pack_zone")
|
27
|
+
cls.input_location = cls.env.ref("stock.stock_location_company")
|
28
|
+
cls.shelf1 = cls.env.ref("stock.stock_location_components")
|
29
|
+
cls.shelf2 = cls.env.ref("stock.stock_location_14")
|
30
|
+
|
31
|
+
@classmethod
|
32
|
+
def _shopfloor_user_values(cls):
|
33
|
+
vals = super()._shopfloor_user_values()
|
34
|
+
vals["groups_id"] = [
|
35
|
+
(
|
36
|
+
6,
|
37
|
+
0,
|
38
|
+
[
|
39
|
+
cls.env.ref("stock.group_stock_user").id,
|
40
|
+
cls.env.ref("stock.group_stock_multi_locations").id,
|
41
|
+
],
|
42
|
+
)
|
43
|
+
]
|
44
|
+
return vals
|
45
|
+
|
46
|
+
@classmethod
|
47
|
+
def setUpClassBaseData(cls):
|
48
|
+
super().setUpClassBaseData()
|
49
|
+
cls.customer = cls.env["res.partner"].sudo().create({"name": "Customer"})
|
50
|
+
|
51
|
+
cls.customer_location.sudo().barcode = "CUSTOMERS"
|
52
|
+
cls.dispatch_location.sudo().barcode = "DISPATCH"
|
53
|
+
cls.packing_location.sudo().barcode = "PACKING"
|
54
|
+
cls.input_location.sudo().barcode = "INPUT"
|
55
|
+
cls.shelf1.sudo().barcode = "SHELF1"
|
56
|
+
cls.shelf2.sudo().barcode = "SHELF2"
|
57
|
+
|
58
|
+
cls.product_a = (
|
59
|
+
cls.env["product.product"]
|
60
|
+
.sudo()
|
61
|
+
.create(
|
62
|
+
{
|
63
|
+
"name": "Product A",
|
64
|
+
"type": "product",
|
65
|
+
"default_code": "A",
|
66
|
+
"barcode": "A",
|
67
|
+
"weight": 2,
|
68
|
+
}
|
69
|
+
)
|
70
|
+
)
|
71
|
+
cls.product_a_packaging = (
|
72
|
+
cls.env["product.packaging"]
|
73
|
+
.sudo()
|
74
|
+
.create(
|
75
|
+
{
|
76
|
+
"name": "Box",
|
77
|
+
"product_id": cls.product_a.id,
|
78
|
+
"barcode": "ProductABox",
|
79
|
+
"qty": 3.0,
|
80
|
+
}
|
81
|
+
)
|
82
|
+
)
|
83
|
+
cls.product_b = (
|
84
|
+
cls.env["product.product"]
|
85
|
+
.sudo()
|
86
|
+
.create(
|
87
|
+
{
|
88
|
+
"name": "Product B",
|
89
|
+
"type": "product",
|
90
|
+
"default_code": "B",
|
91
|
+
"barcode": "B",
|
92
|
+
"weight": 3,
|
93
|
+
}
|
94
|
+
)
|
95
|
+
)
|
96
|
+
cls.product_b_packaging = (
|
97
|
+
cls.env["product.packaging"]
|
98
|
+
.sudo()
|
99
|
+
.create(
|
100
|
+
{
|
101
|
+
"name": "Box",
|
102
|
+
"product_id": cls.product_b.id,
|
103
|
+
"barcode": "ProductBBox",
|
104
|
+
}
|
105
|
+
)
|
106
|
+
)
|
107
|
+
cls.product_c = (
|
108
|
+
cls.env["product.product"]
|
109
|
+
.sudo()
|
110
|
+
.create(
|
111
|
+
{
|
112
|
+
"name": "Product C",
|
113
|
+
"type": "product",
|
114
|
+
"default_code": "C",
|
115
|
+
"barcode": "C",
|
116
|
+
"weight": 3,
|
117
|
+
}
|
118
|
+
)
|
119
|
+
)
|
120
|
+
cls.product_c_packaging = (
|
121
|
+
cls.env["product.packaging"]
|
122
|
+
.sudo()
|
123
|
+
.create(
|
124
|
+
{
|
125
|
+
"name": "Box",
|
126
|
+
"product_id": cls.product_c.id,
|
127
|
+
"barcode": "ProductCBox",
|
128
|
+
"qty": 3,
|
129
|
+
}
|
130
|
+
)
|
131
|
+
)
|
132
|
+
cls.product_d = (
|
133
|
+
cls.env["product.product"]
|
134
|
+
.sudo()
|
135
|
+
.create(
|
136
|
+
{
|
137
|
+
"name": "Product D",
|
138
|
+
"type": "product",
|
139
|
+
"default_code": "D",
|
140
|
+
"barcode": "D",
|
141
|
+
"weight": 3,
|
142
|
+
}
|
143
|
+
)
|
144
|
+
)
|
145
|
+
cls.product_d_packaging = (
|
146
|
+
cls.env["product.packaging"]
|
147
|
+
.sudo()
|
148
|
+
.create(
|
149
|
+
{
|
150
|
+
"name": "Box",
|
151
|
+
"product_id": cls.product_d.id,
|
152
|
+
"barcode": "ProductDBox",
|
153
|
+
}
|
154
|
+
)
|
155
|
+
)
|
156
|
+
|
157
|
+
@classmethod
|
158
|
+
def _create_picking(cls, picking_type=None, lines=None, confirm=True, **kw):
|
159
|
+
picking_form = Form(cls.env["stock.picking"])
|
160
|
+
picking_form.picking_type_id = picking_type or cls.picking_type
|
161
|
+
picking_form.partner_id = cls.customer
|
162
|
+
if lines is None:
|
163
|
+
lines = [(cls.product_a, 10), (cls.product_b, 10)]
|
164
|
+
for product, qty in lines:
|
165
|
+
with picking_form.move_ids_without_package.new() as move:
|
166
|
+
move.product_id = product
|
167
|
+
move.product_uom_qty = qty
|
168
|
+
for k, v in kw.items():
|
169
|
+
setattr(picking_form, k, v)
|
170
|
+
picking = picking_form.save()
|
171
|
+
if confirm:
|
172
|
+
picking.action_confirm()
|
173
|
+
return picking
|
174
|
+
|
175
|
+
@classmethod
|
176
|
+
def _update_qty_in_location(
|
177
|
+
cls, location, product, quantity, package=None, lot=None
|
178
|
+
):
|
179
|
+
quants = cls.env["stock.quant"]._gather(
|
180
|
+
product, location, lot_id=lot, package_id=package, strict=True
|
181
|
+
)
|
182
|
+
# this method adds the quantity to the current quantity, so remove it
|
183
|
+
quantity -= sum(quants.mapped("quantity"))
|
184
|
+
cls.env["stock.quant"]._update_available_quantity(
|
185
|
+
product, location, quantity, package_id=package, lot_id=lot
|
186
|
+
)
|
187
|
+
|
188
|
+
@classmethod
|
189
|
+
def _fill_stock_for_moves(
|
190
|
+
cls, moves, in_package=False, same_package=True, in_lot=False, location=False
|
191
|
+
):
|
192
|
+
"""Satisfy stock for given moves.
|
193
|
+
|
194
|
+
:param moves: stock.move recordset
|
195
|
+
:param in_package: stock.quant.package record or simple boolean
|
196
|
+
If a package record is given, it will be used as package.
|
197
|
+
If a boolean true is given, a new package will be created for each move.
|
198
|
+
:param same_package:
|
199
|
+
modify the behavior of `in_package` to use the same package for all moves.
|
200
|
+
:param in_lot: stock.lot record or simple boolean
|
201
|
+
If a lot record is given, it will be used as lot.
|
202
|
+
If a boolean true is given, a new lot will be created.
|
203
|
+
"""
|
204
|
+
product_packages = {}
|
205
|
+
product_locations = {}
|
206
|
+
package = None
|
207
|
+
if in_package:
|
208
|
+
if isinstance(in_package, models.BaseModel):
|
209
|
+
package = in_package
|
210
|
+
else:
|
211
|
+
package = cls.env["stock.quant.package"].create({})
|
212
|
+
for move in moves:
|
213
|
+
key = (move.product_id, location or move.location_id)
|
214
|
+
product_locations.setdefault(key, 0)
|
215
|
+
product_locations[key] += move.product_qty
|
216
|
+
if in_package:
|
217
|
+
if isinstance(in_package, models.BaseModel):
|
218
|
+
package = in_package
|
219
|
+
if not package or package and not same_package:
|
220
|
+
package = cls.env["stock.quant.package"].create({})
|
221
|
+
product_packages[key] = package
|
222
|
+
for (product, location), qty in product_locations.items():
|
223
|
+
lot = None
|
224
|
+
if in_lot:
|
225
|
+
if isinstance(in_lot, models.BaseModel):
|
226
|
+
lot = in_lot
|
227
|
+
else:
|
228
|
+
lot = cls.env["stock.lot"].create(
|
229
|
+
{"product_id": product.id, "company_id": cls.env.company.id}
|
230
|
+
)
|
231
|
+
if not (in_lot or in_package):
|
232
|
+
# always add more quantity in stock to avoid to trigger the
|
233
|
+
# "zero checks" in tests, not for lots which must have a qty
|
234
|
+
# of 1 and not for packages because we need the strict number
|
235
|
+
# of units to pick a package
|
236
|
+
qty *= 2
|
237
|
+
cls._update_qty_in_location(
|
238
|
+
location, product, qty, package=package, lot=lot
|
239
|
+
)
|
240
|
+
|
241
|
+
# used by _create_package_in_location
|
242
|
+
PackageContent = namedtuple(
|
243
|
+
"PackageContent",
|
244
|
+
# recordset of the product,
|
245
|
+
# quantity in float
|
246
|
+
# recordset of the lot (optional)
|
247
|
+
"product quantity lot",
|
248
|
+
)
|
249
|
+
|
250
|
+
def _create_package_in_location(self, location, content):
|
251
|
+
"""Create a package and quants in a location
|
252
|
+
|
253
|
+
content is a list of PackageContent
|
254
|
+
"""
|
255
|
+
package = self.env["stock.quant.package"].create({})
|
256
|
+
for product, quantity, lot in content:
|
257
|
+
self._update_qty_in_location(
|
258
|
+
location, product, quantity, package=package, lot=lot
|
259
|
+
)
|
260
|
+
return package
|
261
|
+
|
262
|
+
def _create_lot(self, product):
|
263
|
+
return self.env["stock.lot"].create(
|
264
|
+
{"product_id": product.id, "company_id": self.env.company.id}
|
265
|
+
)
|
266
|
+
|
267
|
+
|
268
|
+
class PickingBatchMixin:
|
269
|
+
|
270
|
+
BatchProduct = namedtuple(
|
271
|
+
"BatchProduct",
|
272
|
+
# browse record of the product,
|
273
|
+
# quantity in float
|
274
|
+
"product quantity",
|
275
|
+
)
|
276
|
+
|
277
|
+
@classmethod
|
278
|
+
def _create_picking_batch(cls, products):
|
279
|
+
"""Create a picking batch
|
280
|
+
|
281
|
+
:param products: list of list of BatchProduct. The outer list creates
|
282
|
+
pickings and the innerr list creates moves in these pickings
|
283
|
+
"""
|
284
|
+
batch_form = Form(cls.env["stock.picking.batch"].sudo())
|
285
|
+
for transfer in products:
|
286
|
+
picking_form = Form(cls.env["stock.picking"].sudo())
|
287
|
+
picking_form.picking_type_id = cls.picking_type
|
288
|
+
picking_form.location_id = cls.stock_location
|
289
|
+
picking_form.origin = "test"
|
290
|
+
picking_form.partner_id = cls.customer
|
291
|
+
for batch_product in transfer:
|
292
|
+
product = batch_product.product
|
293
|
+
quantity = batch_product.quantity
|
294
|
+
with picking_form.move_ids_without_package.new() as move:
|
295
|
+
move.product_id = product
|
296
|
+
move.product_uom_qty = quantity
|
297
|
+
picking = picking_form.save()
|
298
|
+
batch_form.picking_ids.add(picking)
|
299
|
+
|
300
|
+
batch = batch_form.save()
|
301
|
+
batch.picking_ids.action_confirm()
|
302
|
+
batch.picking_ids.action_assign()
|
303
|
+
return batch
|
304
|
+
|
305
|
+
@classmethod
|
306
|
+
def _simulate_batch_selected(
|
307
|
+
cls, batches, in_package=False, in_lot=False, fill_stock=True
|
308
|
+
):
|
309
|
+
"""Create a state as if a batch was selected by the user
|
310
|
+
|
311
|
+
* The picking batch is in progress
|
312
|
+
* It is assigned to the current user
|
313
|
+
* All the move lines are available
|
314
|
+
|
315
|
+
Note: currently, this method create a source package that contains
|
316
|
+
all the products of the batch. It is enough for the current tests.
|
317
|
+
"""
|
318
|
+
pickings = batches.mapped("picking_ids")
|
319
|
+
if fill_stock:
|
320
|
+
cls._fill_stock_for_moves(
|
321
|
+
pickings.mapped("move_ids"), in_package=in_package, in_lot=in_lot
|
322
|
+
)
|
323
|
+
pickings.action_assign()
|
324
|
+
batches.write({"state": "in_progress", "user_id": cls.env.uid})
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright 2021 Camptocamp SA
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
3
|
+
"""Test data models to get a mapping between carrier and delivery packaging.
|
4
|
+
|
5
|
+
Add a new "test" value for 'delivery_type' field of carrier and
|
6
|
+
'package_carrier_type' field of packaging for test purpose because
|
7
|
+
Shopfloor do not depend on 'delivery_*' modules adding the different
|
8
|
+
delivery types.
|
9
|
+
"""
|
10
|
+
from odoo import fields, models
|
11
|
+
|
12
|
+
|
13
|
+
class DeliveryCarrierTest(models.Model):
|
14
|
+
_inherit = "delivery.carrier"
|
15
|
+
|
16
|
+
delivery_type = fields.Selection(
|
17
|
+
selection_add=[("test", "TEST")], ondelete={"test": "set default"}
|
18
|
+
)
|
19
|
+
test_default_packaging_id = fields.Many2one(
|
20
|
+
"stock.package.type", string="Default Package Type"
|
21
|
+
)
|
22
|
+
|
23
|
+
|
24
|
+
class StockPackageType(models.Model):
|
25
|
+
_inherit = "stock.package.type"
|
26
|
+
|
27
|
+
package_carrier_type = fields.Selection(
|
28
|
+
selection_add=[("test", "TEST")], ondelete={"test": "set default"}
|
29
|
+
)
|