odoo-addon-stock-barcodes 15.0.2.0.0.11__py3-none-any.whl → 15.0.3.0.0__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/stock_barcodes/README.rst +1 -1
- odoo/addons/stock_barcodes/__manifest__.py +1 -1
- odoo/addons/stock_barcodes/i18n/stock_barcodes.pot +107 -7
- odoo/addons/stock_barcodes/models/stock_barcodes_option.py +16 -0
- odoo/addons/stock_barcodes/models/stock_move_line.py +12 -2
- odoo/addons/stock_barcodes/models/stock_picking_type.py +10 -6
- odoo/addons/stock_barcodes/models/stock_quant.py +21 -2
- odoo/addons/stock_barcodes/static/description/index.html +1 -2
- odoo/addons/stock_barcodes/static/src/css/stock.scss +17 -0
- odoo/addons/stock_barcodes/static/src/js/basic_controller.js +10 -0
- odoo/addons/stock_barcodes/views/stock_barcodes_menu.xml +1 -0
- odoo/addons/stock_barcodes/views/stock_barcodes_option_view.xml +8 -0
- odoo/addons/stock_barcodes/views/stock_picking_views.xml +1 -0
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read.py +116 -23
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory.py +27 -11
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory_views.xml +35 -1
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking.py +129 -37
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking_views.xml +10 -1
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_todo.py +2 -7
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_todo_view.xml +13 -1
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_views.xml +57 -16
- {odoo_addon_stock_barcodes-15.0.2.0.0.11.dist-info → odoo_addon_stock_barcodes-15.0.3.0.0.dist-info}/METADATA +2 -2
- {odoo_addon_stock_barcodes-15.0.2.0.0.11.dist-info → odoo_addon_stock_barcodes-15.0.3.0.0.dist-info}/RECORD +25 -25
- {odoo_addon_stock_barcodes-15.0.2.0.0.11.dist-info → odoo_addon_stock_barcodes-15.0.3.0.0.dist-info}/WHEEL +1 -1
- {odoo_addon_stock_barcodes-15.0.2.0.0.11.dist-info → odoo_addon_stock_barcodes-15.0.3.0.0.dist-info}/top_level.txt +0 -0
@@ -92,6 +92,12 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
92
92
|
)
|
93
93
|
display_assign_serial = fields.Boolean(compute="_compute_display_assign_serial")
|
94
94
|
keep_result_package = fields.Boolean()
|
95
|
+
total_product_uom_qty = fields.Float(
|
96
|
+
string="Product Demand", digits="Product Unit of Measure", store=False
|
97
|
+
)
|
98
|
+
total_product_qty_done = fields.Float(
|
99
|
+
string="Product Qty. Done", digits="Product Unit of Measure", store=False
|
100
|
+
)
|
95
101
|
|
96
102
|
@api.depends("res_id")
|
97
103
|
def _compute_action_ids(self):
|
@@ -149,6 +155,17 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
149
155
|
if self.packaging_id:
|
150
156
|
self.product_qty = self.packaging_qty * self.packaging_id.qty
|
151
157
|
|
158
|
+
@api.onchange(
|
159
|
+
"product_id",
|
160
|
+
"lot_id",
|
161
|
+
"package_id",
|
162
|
+
"result_package_id",
|
163
|
+
"packaging_qty",
|
164
|
+
"product_qty",
|
165
|
+
)
|
166
|
+
def onchange_visible_force_done(self):
|
167
|
+
self.visible_force_done = False
|
168
|
+
|
152
169
|
def _set_messagge_info(self, message_type, message):
|
153
170
|
"""
|
154
171
|
Set message type and message description.
|
@@ -191,7 +208,24 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
191
208
|
)
|
192
209
|
return False
|
193
210
|
self.action_product_scaned_post(product)
|
194
|
-
|
211
|
+
if (
|
212
|
+
self.option_group_id.fill_fields_from_lot
|
213
|
+
and self.location_id
|
214
|
+
and self.product_id
|
215
|
+
):
|
216
|
+
quant_domain = [
|
217
|
+
("location_id", "=", self.location_id.id),
|
218
|
+
("product_id", "=", product.id),
|
219
|
+
]
|
220
|
+
if self.lot_id:
|
221
|
+
quant_domain.append(("lot_id", "=", self.lot_id.id))
|
222
|
+
if self.package_id:
|
223
|
+
quant_domain.append(("package_id", "=", self.package_id.id))
|
224
|
+
if self.owner_id:
|
225
|
+
quant_domain.append(("owner_id", "=", self.owner_id.id))
|
226
|
+
quants = self.env["stock.quant"].search(quant_domain)
|
227
|
+
if quants:
|
228
|
+
self.set_info_from_quants(quants)
|
195
229
|
return True
|
196
230
|
return False
|
197
231
|
|
@@ -205,6 +239,7 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
205
239
|
if self.option_group_id.fill_fields_from_lot:
|
206
240
|
quant_domain = [
|
207
241
|
("lot_id.name", "=", self.barcode),
|
242
|
+
("product_id", "=", self.product_id.id),
|
208
243
|
("quantity", ">", 0.0),
|
209
244
|
]
|
210
245
|
if self.location_id:
|
@@ -255,14 +290,18 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
255
290
|
("package_id.name", "=", self.barcode),
|
256
291
|
("quantity", ">", 0.0),
|
257
292
|
]
|
258
|
-
if self.location_id
|
293
|
+
if self.option_group_id.get_option_value("location_id", "forced"):
|
259
294
|
quant_domain.append(("location_id", "=", self.location_id.id))
|
260
|
-
else:
|
261
|
-
quant_domain.append(("location_id.usage", "=", "internal"))
|
262
295
|
if self.owner_id:
|
263
296
|
quant_domain.append(("owner_id", "=", self.owner_id.id))
|
264
297
|
quants = self.env["stock.quant"].search(quant_domain)
|
265
|
-
|
298
|
+
internal_quants = quants.filtered(lambda q: q.location_id.usage == "internal")
|
299
|
+
if internal_quants:
|
300
|
+
quants = internal_quants
|
301
|
+
elif quants:
|
302
|
+
self = self.with_context(ignore_quant_location=True)
|
303
|
+
# self._set_messagge_info("more_match", _("Package located external location"))
|
304
|
+
else:
|
266
305
|
# self._set_messagge_info("more_match", _("Package not fount or empty"))
|
267
306
|
return False
|
268
307
|
self.set_info_from_quants(quants)
|
@@ -282,21 +321,30 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
282
321
|
"""
|
283
322
|
Fill wizard fields from stock quants
|
284
323
|
"""
|
324
|
+
if self.env.context.get("skip_set_info_from_quants"):
|
325
|
+
return
|
326
|
+
ignore_quant_location = self.env.context.get(
|
327
|
+
"ignore_quant_location", self.option_group_id.ignore_quant_location
|
328
|
+
)
|
285
329
|
if len(quants) == 1:
|
286
330
|
# All ok
|
287
331
|
self.action_product_scaned_post(quants.product_id)
|
288
332
|
self.package_id = quants.package_id
|
333
|
+
self.result_package_id = quants.package_id
|
289
334
|
if quants.lot_id:
|
290
335
|
self.action_lot_scaned_post(quants.lot_id)
|
291
336
|
if quants.owner_id:
|
292
337
|
self.owner_id = quants.owner_id
|
293
338
|
# Review conditions
|
294
|
-
if
|
339
|
+
if (
|
340
|
+
not ignore_quant_location
|
341
|
+
and not self.option_group_id.get_option_value("location_id", "forced")
|
342
|
+
and self.option_group_id.code != "IN"
|
343
|
+
):
|
295
344
|
self.location_id = quants.location_id
|
296
|
-
if
|
297
|
-
"
|
298
|
-
|
299
|
-
]:
|
345
|
+
if self.option_group_id.code != "OUT" and not self.env.context.get(
|
346
|
+
"skip_update_quantity_from_lot", False
|
347
|
+
):
|
300
348
|
self.product_qty = quants.quantity
|
301
349
|
elif len(quants) > 1:
|
302
350
|
# More than one record found with same barcode.
|
@@ -305,19 +353,20 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
305
353
|
products = quants.mapped("product_id")
|
306
354
|
if len(products) == 1:
|
307
355
|
self.action_product_scaned_post(products[0])
|
308
|
-
|
309
|
-
if
|
310
|
-
self.package_id =
|
356
|
+
package = quants[0].package_id
|
357
|
+
if not quants.filtered(lambda q: q.package_id != package):
|
358
|
+
self.package_id = package
|
311
359
|
lots = quants.mapped("lot_id")
|
312
360
|
if len(lots) == 1:
|
313
361
|
self.action_lot_scaned_post(lots[0])
|
314
|
-
|
315
|
-
if
|
316
|
-
self.owner_id =
|
317
|
-
|
318
|
-
|
319
|
-
if
|
320
|
-
self.location_id
|
362
|
+
owner = quants[0].owner_id
|
363
|
+
if not quants.filtered(lambda q: q.owner_id != owner):
|
364
|
+
self.owner_id = owner
|
365
|
+
if not ignore_quant_location:
|
366
|
+
locations = quants.mapped("location_id")
|
367
|
+
if len(locations) == 1:
|
368
|
+
if not self.location_id and self.option_group_id.code != "IN":
|
369
|
+
self.location_id = locations
|
321
370
|
|
322
371
|
def process_barcode_packaging_id(self):
|
323
372
|
domain = self._barcode_domain(self.barcode)
|
@@ -388,11 +437,17 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
388
437
|
self.product_id.tracking == "none" or self.auto_lot or self.lot_name
|
389
438
|
):
|
390
439
|
continue
|
440
|
+
if self._option_required_hook(option):
|
441
|
+
continue
|
391
442
|
self._set_messagge_info("info", option.name)
|
392
443
|
self.action_show_step()
|
393
444
|
return False
|
394
445
|
return True
|
395
446
|
|
447
|
+
def _option_required_hook(self, option_required):
|
448
|
+
"""Hook to evaluate is an option is required"""
|
449
|
+
return False
|
450
|
+
|
396
451
|
def _scanned_location(self, barcode):
|
397
452
|
location = self.env["stock.location"].search(self._barcode_domain(barcode))
|
398
453
|
if location:
|
@@ -403,7 +458,8 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
403
458
|
return False
|
404
459
|
|
405
460
|
def _barcode_domain(self, barcode):
|
406
|
-
|
461
|
+
field_name = self.env.context.get("barcode_domain_field", "barcode")
|
462
|
+
return [(field_name, "=", barcode)]
|
407
463
|
|
408
464
|
def _clean_barcode_scanned(self, barcode):
|
409
465
|
return barcode.rstrip()
|
@@ -436,7 +492,10 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
436
492
|
result_ok = self.check_lot_contidion()
|
437
493
|
if not result_ok:
|
438
494
|
return False
|
439
|
-
if
|
495
|
+
if (
|
496
|
+
not self.product_qty
|
497
|
+
and not self._name == "wiz.stock.barcodes.read.inventory"
|
498
|
+
):
|
440
499
|
self._set_messagge_info("info", _("Waiting quantities"))
|
441
500
|
return False
|
442
501
|
if (
|
@@ -480,6 +539,16 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
480
539
|
def action_done(self):
|
481
540
|
if not self.manual_entry and not self.product_qty and not self.is_manual_qty:
|
482
541
|
self.product_qty = 1.0
|
542
|
+
limit_product_qty = float(
|
543
|
+
self.env["ir.config_parameter"]
|
544
|
+
.sudo()
|
545
|
+
.get_param("stock_barcodes.limit_product_qty", "999999")
|
546
|
+
)
|
547
|
+
if self.product_qty > limit_product_qty:
|
548
|
+
# HACK: Some times users scan a barcode into input element.
|
549
|
+
# At this time, to prevent this we check that the quantity be realistic.
|
550
|
+
self._set_messagge_info("more_match", _("The quantity is huge"))
|
551
|
+
return False
|
483
552
|
if not self.check_done_conditions():
|
484
553
|
return False
|
485
554
|
if not self.env.context.get("_stock_barcodes_skip_read_log"):
|
@@ -517,7 +586,11 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
517
586
|
self.set_product_qty()
|
518
587
|
|
519
588
|
def set_product_qty(self):
|
520
|
-
if
|
589
|
+
if (
|
590
|
+
self.manual_entry
|
591
|
+
or self.is_manual_qty
|
592
|
+
or self.option_group_id.get_option_value("product_qty", "filled_default")
|
593
|
+
):
|
521
594
|
return
|
522
595
|
elif self.packaging_id:
|
523
596
|
self.packaging_qty = 1.0
|
@@ -748,3 +821,23 @@ class WizStockBarcodesRead(models.AbstractModel):
|
|
748
821
|
|
749
822
|
def action_keep_result_package(self):
|
750
823
|
self.keep_result_package = not self.keep_result_package
|
824
|
+
|
825
|
+
def display_notification(
|
826
|
+
self, message, message_type="warning", title=False, sticky=True
|
827
|
+
):
|
828
|
+
"""Send notifications to web client
|
829
|
+
message_type:
|
830
|
+
[options.type='warning'] 'info', 'success', 'warning', 'danger' or ''
|
831
|
+
See web/static/src/legacy/js/core/service_mixins.js#L241 to implement more
|
832
|
+
options.
|
833
|
+
sticky: Permanent notification until user removes it
|
834
|
+
"""
|
835
|
+
if self.option_group_id.display_notification:
|
836
|
+
message = {"message": message, "type": message_type, "sticky": sticky}
|
837
|
+
if title:
|
838
|
+
message["title"] = title
|
839
|
+
self.env["bus.bus"]._sendone(
|
840
|
+
"stock_barcodes-{}".format(self.ids[0]),
|
841
|
+
"stock_barcodes_notify-{}".format(self.ids[0]),
|
842
|
+
message,
|
843
|
+
)
|
@@ -17,18 +17,31 @@ class WizStockBarcodesReadInventory(models.TransientModel):
|
|
17
17
|
inventory_quant_ids = fields.Many2many(
|
18
18
|
comodel_name="stock.quant", compute="_compute_inventory_quant_ids"
|
19
19
|
)
|
20
|
+
display_read_quant = fields.Boolean(string="Read items")
|
20
21
|
|
22
|
+
@api.depends("display_read_quant")
|
21
23
|
def _compute_inventory_quant_ids(self):
|
22
24
|
for wiz in self:
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
domain = [
|
26
|
+
("user_id", "=", self.env.user.id),
|
27
|
+
("inventory_date", "<=", fields.Date.context_today(self)),
|
28
|
+
]
|
29
|
+
if self.display_read_quant:
|
30
|
+
domain.append(("inventory_quantity_set", "=", True))
|
31
|
+
order = "write_date DESC"
|
32
|
+
else:
|
33
|
+
domain.append(("inventory_quantity_set", "=", False))
|
34
|
+
order = None
|
35
|
+
quants = self.env["stock.quant"].search(domain, order=order)
|
36
|
+
if order is None:
|
37
|
+
quants = quants.sorted(
|
38
|
+
lambda q: (
|
39
|
+
q.location_id.posx,
|
40
|
+
q.location_id.posy,
|
41
|
+
q.location_id.posz,
|
42
|
+
q.location_id.name,
|
43
|
+
)
|
44
|
+
)
|
32
45
|
wiz.inventory_quant_ids = quants
|
33
46
|
|
34
47
|
def _prepare_stock_quant_values(self):
|
@@ -48,10 +61,10 @@ class WizStockBarcodesReadInventory(models.TransientModel):
|
|
48
61
|
"<=",
|
49
62
|
fields.Date.context_today(self).strftime("%Y-%m-%d"),
|
50
63
|
),
|
51
|
-
("inventory_quantity_set", "=", True),
|
52
64
|
("product_id", "=", self.product_id.id),
|
53
65
|
("location_id", "=", self.location_id.id),
|
54
66
|
("lot_id", "=", self.lot_id.id),
|
67
|
+
("package_id", "=", self.package_id.id),
|
55
68
|
]
|
56
69
|
|
57
70
|
def _add_inventory_quant(self):
|
@@ -64,7 +77,10 @@ class WizStockBarcodesReadInventory(models.TransientModel):
|
|
64
77
|
):
|
65
78
|
self._serial_tracking_message_fail()
|
66
79
|
return False
|
67
|
-
|
80
|
+
if self.option_group_id.accumulate_read_quantity:
|
81
|
+
quant.inventory_quantity += self.product_qty
|
82
|
+
else:
|
83
|
+
quant.inventory_quantity = self.product_qty
|
68
84
|
else:
|
69
85
|
if self.product_id.tracking == "serial" and self.product_qty != 1:
|
70
86
|
self._serial_tracking_message_fail()
|
@@ -25,6 +25,11 @@
|
|
25
25
|
/>
|
26
26
|
</div>
|
27
27
|
</group>
|
28
|
+
<field name="location_id" position="attributes">
|
29
|
+
<attribute
|
30
|
+
name="domain"
|
31
|
+
>[('usage', 'in', ['internal', 'transit'])]</attribute>
|
32
|
+
</field>
|
28
33
|
<group name="scan_fields" position="after">
|
29
34
|
<group
|
30
35
|
string="Inventory quants"
|
@@ -62,6 +67,14 @@
|
|
62
67
|
groups="uom.group_uom"
|
63
68
|
options="{'no_open': True}"
|
64
69
|
/>
|
70
|
+
<button
|
71
|
+
name="action_barcode_inventory_quant_edit"
|
72
|
+
type="object"
|
73
|
+
icon="fa-pencil"
|
74
|
+
class="btn mt0"
|
75
|
+
context="{'wiz_barcode_id': parent.id}"
|
76
|
+
>
|
77
|
+
</button>
|
65
78
|
<button
|
66
79
|
name="action_barcode_inventory_quant_unlink"
|
67
80
|
type="object"
|
@@ -93,6 +106,18 @@
|
|
93
106
|
</span>
|
94
107
|
</div>
|
95
108
|
<div class="col-3 text-right">
|
109
|
+
<button
|
110
|
+
name="action_barcode_inventory_quant_edit"
|
111
|
+
type="object"
|
112
|
+
class="btn mt0"
|
113
|
+
context="{'wiz_barcode_id': parent.id}"
|
114
|
+
>
|
115
|
+
<i
|
116
|
+
class="fa fa-pencil"
|
117
|
+
title="Edit inventory quantity"
|
118
|
+
style="font-size:1.5em"
|
119
|
+
/>
|
120
|
+
</button>
|
96
121
|
<button
|
97
122
|
name="action_barcode_inventory_quant_unlink"
|
98
123
|
type="object"
|
@@ -129,6 +154,15 @@
|
|
129
154
|
</field>
|
130
155
|
</group>
|
131
156
|
</group>
|
157
|
+
<div name="manual_entry" position="after">
|
158
|
+
<div class="d-flex" name="display_read_quant">
|
159
|
+
<field
|
160
|
+
name="display_read_quant"
|
161
|
+
widget="FieldBarcodeBooleanToggle"
|
162
|
+
/>
|
163
|
+
<label for="display_read_quant" />
|
164
|
+
</div>
|
165
|
+
</div>
|
132
166
|
<button name="action_clean_values" position="before">
|
133
167
|
<button
|
134
168
|
name="apply_inventory"
|
@@ -138,7 +172,7 @@
|
|
138
172
|
data-hotkey="7"
|
139
173
|
groups="stock.group_stock_manager"
|
140
174
|
>
|
141
|
-
<span>Apply
|
175
|
+
<span>Apply</span>
|
142
176
|
</button>
|
143
177
|
</button>
|
144
178
|
</field>
|