odoo-addon-stock-barcodes 16.0.1.1.0.10__py3-none-any.whl → 16.0.2.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 +217 -12
- odoo/addons/stock_barcodes/__init__.py +1 -0
- odoo/addons/stock_barcodes/__manifest__.py +8 -3
- odoo/addons/stock_barcodes/data/stock_barcodes_action.xml +8 -0
- odoo/addons/stock_barcodes/data/stock_barcodes_option.xml +99 -1
- odoo/addons/stock_barcodes/i18n/stock_barcodes.pot +268 -79
- odoo/addons/stock_barcodes/models/__init__.py +1 -0
- odoo/addons/stock_barcodes/models/barcode_events_mixin.py +11 -0
- odoo/addons/stock_barcodes/models/stock_barcodes_action.py +137 -3
- odoo/addons/stock_barcodes/models/stock_picking.py +17 -2
- odoo/addons/stock_barcodes/models/stock_picking_type.py +35 -0
- odoo/addons/stock_barcodes/models/stock_quant.py +51 -1
- odoo/addons/stock_barcodes/readme/CONTRIBUTORS.rst +4 -0
- odoo/addons/stock_barcodes/readme/DESCRIPTION.rst +4 -0
- odoo/addons/stock_barcodes/readme/HISTORY.rst +12 -0
- odoo/addons/stock_barcodes/readme/USAGE.rst +191 -10
- odoo/addons/stock_barcodes/reports/__init__.py +1 -0
- odoo/addons/stock_barcodes/reports/barcode_actions_report.py +16 -0
- odoo/addons/stock_barcodes/reports/barcode_actions_report.xml +25 -0
- odoo/addons/stock_barcodes/reports/reports.xml +28 -0
- odoo/addons/stock_barcodes/static/description/index.html +189 -33
- odoo/addons/stock_barcodes/static/src/docs/barcodes_actions.pdf +0 -0
- odoo/addons/stock_barcodes/static/src/docs/barcodes_demo.pdf +0 -0
- odoo/addons/stock_barcodes/static/src/img/add_product.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/apply_inventory.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/apply_inventory_reason.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/barcode_interface_picking.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/confirm_all_quantity_items_picking.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/confirm_items_picking.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/create_barcode_action.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/form_add_product.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/form_add_product_quantity.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/form_add_product_reset.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/inventory_barcode_action.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_action_items.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_items.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_items_picking.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_items_picking_edit.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_items_picking_quantity.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_items_picking_scanned.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/list_picking.png +0 -0
- odoo/addons/stock_barcodes/static/src/img/print_barcodes.png +0 -0
- odoo/addons/stock_barcodes/static/src/scss/barcode.scss +135 -0
- odoo/addons/stock_barcodes/static/src/scss/stock.scss +285 -0
- odoo/addons/stock_barcodes/static/src/utils/barcodes_models_utils.esm.js +1 -0
- odoo/addons/stock_barcodes/static/src/views/actions/stock_barcode_main_menu.esm.js +88 -0
- odoo/addons/stock_barcodes/static/src/views/actions/stock_barcode_main_menu.scss +74 -0
- odoo/addons/stock_barcodes/static/src/views/actions/stock_barcode_main_menu.xml +45 -0
- odoo/addons/stock_barcodes/static/src/views/form/form_controller.esm.js +71 -0
- odoo/addons/stock_barcodes/static/src/views/form/form_view.esm.js +14 -0
- odoo/addons/stock_barcodes/static/src/views/kanban/kanban_record.esm.js +27 -0
- odoo/addons/stock_barcodes/static/src/views/{kanban_renderer.esm.js → kanban/kanban_renderer.esm.js} +78 -27
- odoo/addons/stock_barcodes/static/src/views/kanban/kanban_view.esm.js +8 -0
- odoo/addons/stock_barcodes/static/src/views/kanban/stock_barcodes_kanban.xml +28 -0
- odoo/addons/stock_barcodes/static/src/views/views.esm.js +35 -7
- odoo/addons/stock_barcodes/static/src/widgets/boolean_toggle.esm.js +46 -0
- odoo/addons/stock_barcodes/tests/common.py +25 -0
- odoo/addons/stock_barcodes/tests/test_stock_barcodes.py +65 -1
- odoo/addons/stock_barcodes/tests/test_stock_barcodes_picking.py +97 -13
- odoo/addons/stock_barcodes/views/stock_barcodes_action_view.xml +83 -9
- odoo/addons/stock_barcodes/views/stock_barcodes_menu.xml +1 -1
- odoo/addons/stock_barcodes/views/stock_picking_views.xml +29 -10
- odoo/addons/stock_barcodes/wizard/__init__.py +1 -0
- odoo/addons/stock_barcodes/wizard/stock_barcodes_candidate_picking.py +148 -0
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read.py +148 -55
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory.py +30 -2
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory_views.xml +101 -92
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking.py +77 -141
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking_views.xml +197 -219
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_todo.py +45 -0
- odoo/addons/stock_barcodes/wizard/stock_barcodes_read_views.xml +87 -170
- odoo_addon_stock_barcodes-16.0.2.0.0.dist-info/METADATA +435 -0
- odoo_addon_stock_barcodes-16.0.2.0.0.dist-info/RECORD +103 -0
- odoo/addons/stock_barcodes/static/src/css/stock.scss +0 -136
- odoo/addons/stock_barcodes/static/src/views/form_view.esm.js +0 -17
- odoo_addon_stock_barcodes-16.0.1.1.0.10.dist-info/METADATA +0 -230
- odoo_addon_stock_barcodes-16.0.1.1.0.10.dist-info/RECORD +0 -68
- {odoo_addon_stock_barcodes-16.0.1.1.0.10.dist-info → odoo_addon_stock_barcodes-16.0.2.0.0.dist-info}/WHEEL +0 -0
- {odoo_addon_stock_barcodes-16.0.1.1.0.10.dist-info → odoo_addon_stock_barcodes-16.0.2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2019 Sergio Teruel <sergio.teruel@tecnativa.com>
|
2
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
|
4
|
+
from odoo import models
|
5
|
+
|
6
|
+
|
7
|
+
class BarcodesEventsMixin(models.AbstractModel):
|
8
|
+
_inherit = "barcodes.barcode_events_mixin"
|
9
|
+
|
10
|
+
def send_bus_done(self, channel, type_channel, data=None):
|
11
|
+
self.env["bus.bus"]._sendone(channel, type_channel, data or {})
|
@@ -1,8 +1,22 @@
|
|
1
1
|
# Copyright 2019 Sergio Teruel <sergio.teruel@tecnativa.com>
|
2
2
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
-
|
3
|
+
import base64
|
4
|
+
import re
|
5
|
+
from io import BytesIO
|
6
|
+
|
7
|
+
import barcode
|
8
|
+
from barcode.writer import ImageWriter
|
9
|
+
|
10
|
+
from odoo import _, api, fields, models
|
11
|
+
from odoo.exceptions import ValidationError
|
4
12
|
from odoo.tools.safe_eval import safe_eval
|
5
13
|
|
14
|
+
REGEX = {
|
15
|
+
"context": r"^[^\s].*[^\s]$|^$",
|
16
|
+
"barcode": "^[a-zA-Z0-9-]+$",
|
17
|
+
}
|
18
|
+
FIELDS_NAME = {"barcode_options": "barcode_option_group_id"}
|
19
|
+
|
6
20
|
|
7
21
|
class StockBarcodesAction(models.Model):
|
8
22
|
_name = "stock.barcodes.action"
|
@@ -19,6 +33,118 @@ class StockBarcodesAction(models.Model):
|
|
19
33
|
key_shortcut = fields.Integer()
|
20
34
|
key_char_shortcut = fields.Char()
|
21
35
|
icon_class = fields.Char()
|
36
|
+
barcode = fields.Char()
|
37
|
+
barcode_image = fields.Image(
|
38
|
+
"Barcode image",
|
39
|
+
readonly=True,
|
40
|
+
compute="_compute_barcode_image",
|
41
|
+
attachment=True,
|
42
|
+
)
|
43
|
+
|
44
|
+
count_elements = fields.Integer(default=0, compute="_compute_count_elements")
|
45
|
+
|
46
|
+
@api.constrains("barcode")
|
47
|
+
def _constrains_barcode(self):
|
48
|
+
for action in self:
|
49
|
+
if not re.match(REGEX.get("barcode", False), action.barcode):
|
50
|
+
raise ValidationError(
|
51
|
+
_(
|
52
|
+
" The barcode {} is not correct."
|
53
|
+
"Use numbers, letters and dashes, without spaces."
|
54
|
+
"E.g. 15753, BC-5789,er-56 "
|
55
|
+
""
|
56
|
+
).format(action.barcode)
|
57
|
+
)
|
58
|
+
all_barcode = [bar for bar in action.mapped("barcode") if bar]
|
59
|
+
domain = [("barcode", "in", all_barcode)]
|
60
|
+
matched_actions = self.sudo().search(domain, order="id")
|
61
|
+
if len(matched_actions) > len(all_barcode):
|
62
|
+
raise ValidationError(
|
63
|
+
_(
|
64
|
+
""" Barcode has already been assigned to the action(s): {}."""
|
65
|
+
).format(", ".join(matched_actions.mapped("name")))
|
66
|
+
)
|
67
|
+
|
68
|
+
def _generate_barcode(self):
|
69
|
+
barcode_type = barcode.get_barcode_class("code128")
|
70
|
+
buffer = BytesIO()
|
71
|
+
barcode_instance = barcode_type(self.barcode, writer=ImageWriter())
|
72
|
+
barcode_instance.write(buffer)
|
73
|
+
buffer.seek(0)
|
74
|
+
image_base64 = base64.b64encode(buffer.getvalue())
|
75
|
+
return image_base64
|
76
|
+
|
77
|
+
@api.depends("barcode")
|
78
|
+
def _compute_barcode_image(self):
|
79
|
+
for action in self:
|
80
|
+
if action.barcode:
|
81
|
+
action.barcode_image = action._generate_barcode()
|
82
|
+
else:
|
83
|
+
action.barcode_image = False
|
84
|
+
|
85
|
+
@api.constrains("context")
|
86
|
+
def _constrains_context(self):
|
87
|
+
if self.context and not bool(
|
88
|
+
re.match(REGEX.get("context", False), self.context)
|
89
|
+
):
|
90
|
+
raise ValidationError(_("There can be no spaces at the beginning or end."))
|
91
|
+
|
92
|
+
def _count_elements(self):
|
93
|
+
domain = []
|
94
|
+
if self.context:
|
95
|
+
context_values = self.context.strip("{}").split(",")
|
96
|
+
|
97
|
+
def _map_context_values(x):
|
98
|
+
field_values = x.split(":")
|
99
|
+
field_name = field_values[0].split("search_default_")
|
100
|
+
if len(field_name) > 1:
|
101
|
+
field_name = field_name[1].strip("'")
|
102
|
+
field_value_format = field_values[1].replace("'", "").strip()
|
103
|
+
field_value = (
|
104
|
+
int(field_value_format)
|
105
|
+
if field_value_format.isdigit()
|
106
|
+
else field_value_format
|
107
|
+
)
|
108
|
+
if hasattr(
|
109
|
+
self.action_window_id.res_model,
|
110
|
+
FIELDS_NAME.get(field_name, field_name),
|
111
|
+
):
|
112
|
+
return (
|
113
|
+
"{}".format(FIELDS_NAME.get(field_name, field_name)),
|
114
|
+
"=",
|
115
|
+
field_value,
|
116
|
+
)
|
117
|
+
else:
|
118
|
+
return False
|
119
|
+
else:
|
120
|
+
return ()
|
121
|
+
|
122
|
+
domain = [
|
123
|
+
val_domain
|
124
|
+
for val_domain in list(
|
125
|
+
map(lambda x: _map_context_values(x), context_values)
|
126
|
+
)
|
127
|
+
]
|
128
|
+
search_count = (
|
129
|
+
list(filter(lambda x: x, domain))
|
130
|
+
if all(val_d is True for val_d in domain)
|
131
|
+
else []
|
132
|
+
)
|
133
|
+
return (
|
134
|
+
self.env[self.action_window_id.res_model].search_count(search_count)
|
135
|
+
if self.action_window_id.res_model
|
136
|
+
else 0
|
137
|
+
)
|
138
|
+
return 0
|
139
|
+
|
140
|
+
@api.depends("context")
|
141
|
+
def _compute_count_elements(self):
|
142
|
+
for barcode_action in self:
|
143
|
+
barcode_action.count_elements = (
|
144
|
+
barcode_action._count_elements()
|
145
|
+
if "search_default_" in barcode_action.context
|
146
|
+
else 0
|
147
|
+
)
|
22
148
|
|
23
149
|
def open_action(self):
|
24
150
|
action = self.action_window_id.sudo().read()[0]
|
@@ -29,8 +155,10 @@ class StockBarcodesAction(models.Model):
|
|
29
155
|
if self.context:
|
30
156
|
ctx.update(safe_eval(self.context))
|
31
157
|
if action_context.get("inventory_mode", False):
|
32
|
-
|
33
|
-
|
158
|
+
action = self.open_inventory_action(ctx)
|
159
|
+
else:
|
160
|
+
action["context"] = ctx
|
161
|
+
|
34
162
|
return action
|
35
163
|
|
36
164
|
def open_inventory_action(self, ctx):
|
@@ -53,3 +181,9 @@ class StockBarcodesAction(models.Model):
|
|
53
181
|
action["res_id"] = wiz.id
|
54
182
|
action["context"] = ctx
|
55
183
|
return action
|
184
|
+
|
185
|
+
def print_barcodes(self):
|
186
|
+
report_action = self.env.ref(
|
187
|
+
"stock_barcodes.action_report_barcode_actions"
|
188
|
+
).report_action(None, data={})
|
189
|
+
return report_action
|
@@ -28,7 +28,11 @@ class StockPicking(models.Model):
|
|
28
28
|
return vals
|
29
29
|
|
30
30
|
def action_barcode_scan(self, option_group=False):
|
31
|
-
option_group =
|
31
|
+
option_group = (
|
32
|
+
option_group
|
33
|
+
or self.picking_type_id.barcode_option_group_id
|
34
|
+
or self.env.ref("stock_barcodes.stock_barcodes_option_group_operation")
|
35
|
+
)
|
32
36
|
wiz = self.env["wiz.stock.barcodes.read.picking"].create(
|
33
37
|
self._prepare_barcode_wiz_vals(option_group)
|
34
38
|
)
|
@@ -52,7 +56,18 @@ class StockPicking(models.Model):
|
|
52
56
|
StockPicking, self.with_context(skip_backorder=True)
|
53
57
|
).button_validate()
|
54
58
|
else:
|
59
|
+
pickings_to_backorder = self._check_backorder()
|
60
|
+
if pickings_to_backorder:
|
61
|
+
return pickings_to_backorder._action_generate_backorder_wizard(
|
62
|
+
show_transfers=self._should_show_transfers()
|
63
|
+
)
|
55
64
|
res = super().button_validate()
|
56
65
|
if res is True and self.env.context.get("show_picking_type_action_tree", False):
|
57
|
-
|
66
|
+
res = self[:1].picking_type_id.get_action_picking_tree_ready()
|
67
|
+
|
68
|
+
if self.state == "done":
|
69
|
+
self.env["bus.bus"]._sendone(
|
70
|
+
"stock_barcodes_scan", "actions_barcode", {"valid_picking": True}
|
71
|
+
)
|
72
|
+
|
58
73
|
return res
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# Copyright 2019 Sergio Teruel <sergio.teruel@tecnativa.com>
|
2
2
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
|
+
from ast import literal_eval
|
4
|
+
|
3
5
|
from odoo import fields, models
|
4
6
|
|
5
7
|
|
@@ -67,3 +69,36 @@ class StockPickingType(models.Model):
|
|
67
69
|
)
|
68
70
|
option_group = self.new_picking_barcode_option_group_id
|
69
71
|
return picking.action_barcode_scan(option_group=option_group)
|
72
|
+
|
73
|
+
def get_action_picking_tree_ready(self):
|
74
|
+
context = dict(self.env.context)
|
75
|
+
if context.get("operations_mode", False):
|
76
|
+
return self._get_action(
|
77
|
+
"stock_barcodes.stock_barcodes_action_picking_tree_ready"
|
78
|
+
)
|
79
|
+
return super().get_action_picking_tree_ready()
|
80
|
+
|
81
|
+
def _get_action(self, action_xmlid):
|
82
|
+
action = self.env["ir.actions.actions"]._for_xml_id(action_xmlid)
|
83
|
+
if self:
|
84
|
+
action["display_name"] = self.display_name
|
85
|
+
|
86
|
+
default_immediate_tranfer = True
|
87
|
+
if (
|
88
|
+
self.env["ir.config_parameter"]
|
89
|
+
.sudo()
|
90
|
+
.get_param("stock.no_default_immediate_tranfer")
|
91
|
+
):
|
92
|
+
default_immediate_tranfer = False
|
93
|
+
|
94
|
+
context = {
|
95
|
+
"search_default_picking_type_id": [self.id],
|
96
|
+
"default_picking_type_id": self.id,
|
97
|
+
"default_immediate_transfer": default_immediate_tranfer,
|
98
|
+
"default_company_id": self.company_id.id,
|
99
|
+
}
|
100
|
+
|
101
|
+
action_context = literal_eval(action["context"].strip())
|
102
|
+
context = {**action_context, **context}
|
103
|
+
action["context"] = context
|
104
|
+
return action
|
@@ -2,12 +2,27 @@
|
|
2
2
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
3
3
|
from odoo import models
|
4
4
|
|
5
|
+
MODEL_UPDATE_INVENTORY = ["wiz.stock.barcodes.read.inventory"]
|
6
|
+
|
5
7
|
|
6
8
|
class StockQuant(models.Model):
|
7
|
-
|
9
|
+
_name = "stock.quant"
|
10
|
+
_inherit = ["stock.quant", "barcodes.barcode_events_mixin"]
|
8
11
|
|
9
12
|
def action_barcode_inventory_quant_unlink(self):
|
10
13
|
self.with_context(inventory_mode=True).action_set_inventory_quantity_to_zero()
|
14
|
+
context = dict(self.env.context)
|
15
|
+
params = context.get("params", {})
|
16
|
+
res_model = params.get("model", False)
|
17
|
+
res_id = params.get("id", False)
|
18
|
+
if res_id and res_model in MODEL_UPDATE_INVENTORY:
|
19
|
+
wiz_id = self.env[params["model"]].browse(params["id"])
|
20
|
+
wiz_id._compute_count_inventory_quants()
|
21
|
+
wiz_id.send_bus_done(
|
22
|
+
"stock_barcodes_form_update",
|
23
|
+
"count_apply_inventory",
|
24
|
+
{"count": wiz_id.count_inventory_quants},
|
25
|
+
)
|
11
26
|
|
12
27
|
def _get_fields_to_edit(self):
|
13
28
|
return [
|
@@ -28,3 +43,38 @@ class StockQuant(models.Model):
|
|
28
43
|
for fname in self._get_fields_to_edit():
|
29
44
|
wiz_barcode[fname] = quant[fname]
|
30
45
|
wiz_barcode.product_qty = quant.inventory_quantity
|
46
|
+
|
47
|
+
wiz_barcode.manual_entry = True
|
48
|
+
self.send_bus_done(
|
49
|
+
"stock_barcodes_scan",
|
50
|
+
"stock_barcodes_edit_manual",
|
51
|
+
{
|
52
|
+
"manual_entry": True,
|
53
|
+
},
|
54
|
+
)
|
55
|
+
|
56
|
+
def enable_current_operations(self):
|
57
|
+
self.send_bus_done(
|
58
|
+
"stock_barcodes_kanban_update",
|
59
|
+
"enable_operations",
|
60
|
+
{
|
61
|
+
"id": self.id,
|
62
|
+
},
|
63
|
+
)
|
64
|
+
|
65
|
+
def operation_quantities_rest(self):
|
66
|
+
self.write({"inventory_quantity": self.inventory_quantity - 1})
|
67
|
+
self.enable_current_operations()
|
68
|
+
|
69
|
+
def operation_quantities(self):
|
70
|
+
self.write({"inventory_quantity": self.inventory_quantity + 1})
|
71
|
+
self.enable_current_operations()
|
72
|
+
|
73
|
+
def action_apply_inventory(self):
|
74
|
+
res = super().action_apply_inventory()
|
75
|
+
self.send_bus_done(
|
76
|
+
"stock_barcodes_scan",
|
77
|
+
"actions_barcode",
|
78
|
+
{"apply_inventory": True},
|
79
|
+
)
|
80
|
+
return res
|
@@ -15,3 +15,15 @@
|
|
15
15
|
|
16
16
|
* [ADD] New feature.
|
17
17
|
Add security for users.
|
18
|
+
|
19
|
+
16.0.1.0.0 (2025-01-23)
|
20
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
21
|
+
* [IMP]
|
22
|
+
Improved views to optimize navigation and functionality.
|
23
|
+
Intuitive and mobile-friendly views.
|
24
|
+
Visual improvement of the main view accessed from the Barcodes menu.
|
25
|
+
|
26
|
+
* [ADD] New feature.
|
27
|
+
Barcode reading to barcode actions.
|
28
|
+
Generate PDF document for the barcodes of the selected barcode actions.
|
29
|
+
|
@@ -1,13 +1,74 @@
|
|
1
1
|
Barcode interface for inventory operations
|
2
2
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
3
3
|
|
4
|
-
To use the barcode interface on inventory
|
4
|
+
Option 1: To use the barcode interface on inventory
|
5
|
+
|
6
|
+
#. Go to *Inventory > operations > Inventory Adjustments*.
|
7
|
+
#. Create new inventory with "Select products manually" option.
|
8
|
+
#. Start inventory.
|
9
|
+
#. Click to "Scan barcodes" smart button.
|
10
|
+
#. Start reading barcodes.
|
11
|
+
|
12
|
+
Option 2: Use the barcode interface inventory directly from the Barcodes application
|
13
|
+
#. Go to *Barcodes*.
|
14
|
+
#. Select the *Inventory* option.
|
15
|
+
|
16
|
+
.. image:: /stock_barcodes/static/src/img/inventory_barcode_action.png
|
17
|
+
:height: 100
|
18
|
+
:width: 200
|
19
|
+
:alt: Inventory barcode action
|
20
|
+
|
21
|
+
#. Start scanning barcodes.
|
22
|
+
|
23
|
+
Actions
|
24
|
+
# Press the *+ Product* button to display the form for the new item.
|
25
|
+
|
26
|
+
.. image:: /stock_barcodes/static/src/img/add_product.png
|
27
|
+
:height: 100
|
28
|
+
:width: 200
|
29
|
+
:alt: Add product
|
30
|
+
|
31
|
+
# When you select a product, a numeric field is displayed to add the quantity.
|
32
|
+
|
33
|
+
.. image:: /stock_barcodes/static/src/img/form_add_product_quantity.png
|
34
|
+
:height: 100
|
35
|
+
:width: 200
|
36
|
+
:alt: Add quantity product
|
37
|
+
|
38
|
+
# When you press the button with the trash can icon, the values of the form are reset (except for the location) without closing it.
|
39
|
+
|
40
|
+
.. image:: /stock_barcodes/static/src/img/form_add_product_reset.png
|
41
|
+
:height: 100
|
42
|
+
:width: 200
|
43
|
+
:alt: Reset data form
|
44
|
+
|
45
|
+
# When you press the *Clean values* button, all fields are reset and the form is closed.
|
46
|
+
# When you press the *Confirm* button, the new item is added and the form is closed.
|
47
|
+
# When the eye icon is closed, the created items greater than zero are displayed, and if not, those less than or equal to zero.
|
48
|
+
|
49
|
+
.. image:: /stock_barcodes/static/src/img/list_items.png
|
50
|
+
:height: 100
|
51
|
+
:width: 200
|
52
|
+
:alt: Reset data form
|
53
|
+
|
54
|
+
# In the list, the trash can icon allows you to reset the quantity to zero and the edit icon allows you to change the item values.
|
55
|
+
|
56
|
+
.. image:: /stock_barcodes/static/src/img/list_action_items.png
|
57
|
+
:height: 100
|
58
|
+
:width: 200
|
59
|
+
:alt: Reset data form
|
60
|
+
|
61
|
+
# The *Apply* button is only displayed if there are items with quantities greater than zero, regardless of whether they were scanned or entered manually; If you press all the defined quantities will be processed after defining the reason for the inventory adjustment and then the main barcode menu will be displayed.
|
62
|
+
|
63
|
+
.. image:: /stock_barcodes/static/src/img/apply_inventory.png
|
64
|
+
:height: 100
|
65
|
+
:width: 200
|
66
|
+
:alt: Apply inventory
|
67
|
+
.. image:: /stock_barcodes/static/src/img/apply_inventory_reason.png
|
68
|
+
:height: 100
|
69
|
+
:width: 200
|
70
|
+
:alt: Apply inventory reason
|
5
71
|
|
6
|
-
#. Go to *Inventory > operations > Inventory Adjustments*.
|
7
|
-
#. Create new inventory with "Select products manually" option.
|
8
|
-
#. Start inventory.
|
9
|
-
#. Click to "Scan barcodes" smart button.
|
10
|
-
#. Start reading barcodes.
|
11
72
|
|
12
73
|
Barcode interface for picking operations
|
13
74
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
@@ -21,11 +82,109 @@ To use the barcode interface on picking operations:
|
|
21
82
|
#. Click on scanner button on any operation type.
|
22
83
|
#. Start reading barcodes.
|
23
84
|
|
24
|
-
To use the barcode interface on a picking:
|
85
|
+
Option 1: To use the barcode interface on a picking:
|
25
86
|
|
26
|
-
#. Go to *Inventory > Transfers*.
|
27
|
-
#. Click to "Scan barcodes" smart button.
|
28
|
-
#. Start reading barcodes.
|
87
|
+
#. Go to *Inventory > Transfers*.
|
88
|
+
#. Click to "Scan barcodes" smart button.
|
89
|
+
#. Start reading barcodes.
|
90
|
+
|
91
|
+
Option 2: Use the barcode interface picking directly from the Barcodes application
|
92
|
+
#. Go to *Barcodes*.
|
93
|
+
#. Select the option *OPERATIONS*.
|
94
|
+
|
95
|
+
.. image:: /stock_barcodes/static/src/img/inventory_barcode_action.png
|
96
|
+
:height: 100
|
97
|
+
:width: 200
|
98
|
+
:alt: Operation barcode action
|
99
|
+
|
100
|
+
# Select the type of picking.
|
101
|
+
# The pickings in ready status are displayed, select the one you want to start scanning.
|
102
|
+
|
103
|
+
.. image:: /stock_barcodes/static/src/img/list_picking.png
|
104
|
+
:height: 100
|
105
|
+
:width: 200
|
106
|
+
:alt: List picking
|
107
|
+
|
108
|
+
#. Start scanning barcodes.
|
109
|
+
|
110
|
+
.. image:: /stock_barcodes/static/src/img/barcode_interface_picking.png
|
111
|
+
:height: 100
|
112
|
+
:width: 200
|
113
|
+
:alt: List picking
|
114
|
+
|
115
|
+
Actions
|
116
|
+
# All the items that have been configured for the selected picking are listed.
|
117
|
+
|
118
|
+
.. image:: /stock_barcodes/static/src/img/list_items_picking.png
|
119
|
+
:height: 100
|
120
|
+
:width: 200
|
121
|
+
:alt: List picking
|
122
|
+
|
123
|
+
# The edit icon in the list allows you to modify the data.
|
124
|
+
|
125
|
+
.. image:: /stock_barcodes/static/src/img/list_items_picking_edit.png
|
126
|
+
:height: 100
|
127
|
+
:width: 200
|
128
|
+
:alt: Edit picking
|
129
|
+
|
130
|
+
# The button that contains a *+120* (in this case), allows you to define all the
|
131
|
+
remaining quantities. Once defined, this button disappears and if you want to change the
|
132
|
+
quantities, press the edit button.
|
133
|
+
|
134
|
+
.. image:: /stock_barcodes/static/src/img/list_items_picking_quantity.png
|
135
|
+
:height: 100
|
136
|
+
:width: 200
|
137
|
+
:alt: Quantity picking
|
138
|
+
|
139
|
+
# If there is at least one item with a quantity already defined, an eye icon is displayed,
|
140
|
+
which if closed shows the items and their quantities already scanned.
|
141
|
+
|
142
|
+
.. image:: /stock_barcodes/static/src/img/list_items_picking_scanned.png
|
143
|
+
:height: 100
|
144
|
+
:width: 200
|
145
|
+
:alt: Picking scanned
|
146
|
+
|
147
|
+
# When you press the *Validate* button, a wizard will be displayed to confirm the action.
|
148
|
+
If everything is correct, it is validated and you return to the picking list mentioned above.
|
149
|
+
|
150
|
+
.. image:: /stock_barcodes/static/src/img/confirm_items_picking.png
|
151
|
+
:height: 100
|
152
|
+
:width: 200
|
153
|
+
:alt: Picking scanned
|
154
|
+
|
155
|
+
# If there is an item whose quantity is zero, a wizard will be displayed after the one mentioned
|
156
|
+
above, to confirm if you want to process all the quantities. If positive, you will proceed
|
157
|
+
and be directed to the list mentioned above in the previous point.
|
158
|
+
|
159
|
+
.. image:: /stock_barcodes/static/src/img/confirm_all_quantity_items_picking.png
|
160
|
+
:height: 100
|
161
|
+
:width: 200
|
162
|
+
:alt: Picking scanned
|
163
|
+
|
164
|
+
# Press the *+ Product* button to display the form for the new item.
|
165
|
+
|
166
|
+
.. image:: /stock_barcodes/static/src/img/add_product.png
|
167
|
+
:height: 100
|
168
|
+
:width: 200
|
169
|
+
:alt: Add product
|
170
|
+
|
171
|
+
# When you select a product, a numeric field is displayed to add the quantity.
|
172
|
+
|
173
|
+
.. image:: /stock_barcodes/static/src/img/form_add_product_quantity.png
|
174
|
+
:height: 100
|
175
|
+
:width: 200
|
176
|
+
:alt: Add quantity product
|
177
|
+
|
178
|
+
# When you press the button with the trash can icon, the values of the form are reset (except for the location) without closing it.
|
179
|
+
|
180
|
+
.. image:: /stock_barcodes/static/src/img/form_add_product_reset.png
|
181
|
+
:height: 100
|
182
|
+
:width: 200
|
183
|
+
:alt: Reset data form
|
184
|
+
|
185
|
+
# When you press the *Clean values* button, all fields are reset and the form is closed.
|
186
|
+
# When you press the *Confirm* button, the new item is added and the form is closed.
|
187
|
+
# When adding the new item all the quantities are assigned to it, if you want to modify it, press the edit icon.
|
29
188
|
|
30
189
|
The barcode scanner interface has two operation modes. In both of them user
|
31
190
|
can scan:
|
@@ -77,3 +236,25 @@ Barcode scanning interface display 10 last records linked to model, the goal of
|
|
77
236
|
this log is show to user other reads with the same product and location done
|
78
237
|
by other users.
|
79
238
|
User can remove the last read scan.
|
239
|
+
|
240
|
+
Barcode interface for barcode actions
|
241
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
242
|
+
To use the barcode interface for actions:
|
243
|
+
|
244
|
+
#. Go to *Inventory > Configuration > Barcode Actions*.
|
245
|
+
#. Create a new barcode action and configure the barcode.
|
246
|
+
|
247
|
+
.. image:: /stock_barcodes/static/src/img/create_barcode_action.png
|
248
|
+
:height: 100
|
249
|
+
:width: 200
|
250
|
+
:alt: Print barcodes
|
251
|
+
|
252
|
+
#. Select the barcode actions you want to use, a button (PRINT BARCODES) will appear that allows you to print the configured barcodes to PDF.
|
253
|
+
|
254
|
+
.. image:: /stock_barcodes/static/src/img/print_barcodes.png
|
255
|
+
:height: 100
|
256
|
+
:width: 200
|
257
|
+
:alt: Print barcodes
|
258
|
+
|
259
|
+
#. Go to *Barcodes*.
|
260
|
+
#. Start scanning barcodes from actions.
|
@@ -0,0 +1 @@
|
|
1
|
+
from . import barcode_actions_report
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from odoo import api, models
|
2
|
+
|
3
|
+
|
4
|
+
class ReportStockBarcodesBarcodeActions(models.Model):
|
5
|
+
_name = "report.stock_barcodes.report_barcode_actions"
|
6
|
+
_description = "Print barcodes from barcode actions"
|
7
|
+
|
8
|
+
@api.model
|
9
|
+
def _get_report_values(self, docids, data=None):
|
10
|
+
datas = self.env["stock.barcodes.action"].search_read(
|
11
|
+
[("id", "in", docids), ("barcode", "!=", False)],
|
12
|
+
["name", "barcode", "barcode_image"],
|
13
|
+
)
|
14
|
+
return {
|
15
|
+
"barcodes": datas,
|
16
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<odoo>
|
2
|
+
<template id="report_barcode_actions">
|
3
|
+
<t t-call="web.html_container">
|
4
|
+
<t t-call="web.external_layout">
|
5
|
+
<div class="page">
|
6
|
+
<div class="row text-center mb-4">
|
7
|
+
<h1>Scan your actions and streamline your actions.</h1>
|
8
|
+
</div>
|
9
|
+
<div class="row">
|
10
|
+
<t t-foreach="barcodes" t-as="barcode">
|
11
|
+
<div class="col-4 text-center">
|
12
|
+
<h2 t-out="barcode['name']" />
|
13
|
+
<img
|
14
|
+
t-att-src="'data:image/png;base64,%s' % barcode['barcode_image'].decode('utf-8')"
|
15
|
+
width="100%"
|
16
|
+
height="160px"
|
17
|
+
/>
|
18
|
+
</div>
|
19
|
+
</t>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
</t>
|
23
|
+
</t>
|
24
|
+
</template>
|
25
|
+
</odoo>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<odoo>
|
2
|
+
<record id="paperformat_barcode_actions" model="report.paperformat">
|
3
|
+
<field name="name">A4</field>
|
4
|
+
<field name="default" eval="True" />
|
5
|
+
<field name="format">A4</field>
|
6
|
+
<field name="page_height">0</field>
|
7
|
+
<field name="page_width">0</field>
|
8
|
+
<field name="orientation">Portrait</field>
|
9
|
+
<field name="margin_top">30</field>
|
10
|
+
<field name="margin_bottom">5</field>
|
11
|
+
<field name="margin_left">7</field>
|
12
|
+
<field name="margin_right">7</field>
|
13
|
+
<field name="header_line" eval="False" />
|
14
|
+
<field name="header_spacing">5</field>
|
15
|
+
<field name="dpi">90</field>
|
16
|
+
</record>
|
17
|
+
|
18
|
+
<record id="action_report_barcode_actions" model="ir.actions.report">
|
19
|
+
<field name="name">Barcodes (PDF)</field>
|
20
|
+
<field name="model">stock.barcodes.action</field>
|
21
|
+
<field name="report_type">qweb-pdf</field>
|
22
|
+
<field name="report_name">stock_barcodes.report_barcode_actions</field>
|
23
|
+
<field name="report_file">stock_barcodes.report_barcode_actions</field>
|
24
|
+
<field name="print_report_name">'Barcodes - %s' % (object.name)</field>
|
25
|
+
<field name="binding_type">report</field>
|
26
|
+
<field name="paperformat_id" ref="paperformat_barcode_actions" />
|
27
|
+
</record>
|
28
|
+
</odoo>
|