odoo-addon-stock-barcodes 15.0.3.1.6__py3-none-any.whl → 16.0.1.0.0.18__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 (59) hide show
  1. odoo/addons/stock_barcodes/README.rst +6 -6
  2. odoo/addons/stock_barcodes/__manifest__.py +8 -7
  3. odoo/addons/stock_barcodes/data/stock_barcodes_option.xml +1 -2
  4. odoo/addons/stock_barcodes/hooks.py +15 -13
  5. odoo/addons/stock_barcodes/i18n/es.po +2 -2
  6. odoo/addons/stock_barcodes/i18n/it.po +5 -5
  7. odoo/addons/stock_barcodes/i18n/stock_barcodes.pot +190 -160
  8. odoo/addons/stock_barcodes/models/__init__.py +1 -1
  9. odoo/addons/stock_barcodes/models/stock_barcodes_action.py +2 -1
  10. odoo/addons/stock_barcodes/models/stock_barcodes_option.py +2 -4
  11. odoo/addons/stock_barcodes/models/stock_move.py +37 -0
  12. odoo/addons/stock_barcodes/models/stock_move_line.py +8 -14
  13. odoo/addons/stock_barcodes/models/stock_picking.py +9 -36
  14. odoo/addons/stock_barcodes/models/stock_picking_type.py +5 -6
  15. odoo/addons/stock_barcodes/models/stock_quant.py +3 -4
  16. odoo/addons/stock_barcodes/security/ir.model.access.csv +0 -2
  17. odoo/addons/stock_barcodes/static/description/index.html +9 -11
  18. odoo/addons/stock_barcodes/static/src/css/stock.scss +41 -5
  19. odoo/addons/stock_barcodes/static/src/utils/barcode_handler_field.esm.js +36 -0
  20. odoo/addons/stock_barcodes/static/src/utils/barcodes_models_utils.esm.js +25 -0
  21. odoo/addons/stock_barcodes/static/src/views/form_view.esm.js +17 -0
  22. odoo/addons/stock_barcodes/static/src/views/kanban_renderer.esm.js +149 -0
  23. odoo/addons/stock_barcodes/static/src/views/view_compiler.esm.js +16 -0
  24. odoo/addons/stock_barcodes/static/src/views/views.esm.js +193 -0
  25. odoo/addons/stock_barcodes/static/src/widgets/boolean_toggle.esm.js +26 -0
  26. odoo/addons/stock_barcodes/static/src/widgets/numeric_step.esm.js +40 -0
  27. odoo/addons/stock_barcodes/static/src/widgets/numeric_step.xml +17 -0
  28. odoo/addons/stock_barcodes/static/src/widgets/view_button.esm.js +8 -0
  29. odoo/addons/stock_barcodes/static/src/widgets/view_button.xml +14 -0
  30. odoo/addons/stock_barcodes/tests/common.py +167 -0
  31. odoo/addons/stock_barcodes/tests/test_stock_barcodes.py +4 -172
  32. odoo/addons/stock_barcodes/tests/test_stock_barcodes_new_lot.py +2 -2
  33. odoo/addons/stock_barcodes/tests/test_stock_barcodes_picking.py +8 -8
  34. odoo/addons/stock_barcodes/views/stock_barcodes_option_view.xml +1 -1
  35. odoo/addons/stock_barcodes/views/stock_picking_views.xml +4 -3
  36. odoo/addons/stock_barcodes/wizard/stock_barcodes_read.py +45 -91
  37. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory.py +1 -4
  38. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory_views.xml +14 -15
  39. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking.py +256 -92
  40. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking_views.xml +59 -37
  41. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_todo.py +33 -107
  42. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_todo_view.xml +70 -28
  43. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_views.xml +172 -189
  44. odoo/addons/stock_barcodes/wizard/stock_production_lot.py +2 -2
  45. odoo/addons/stock_barcodes/wizard/stock_production_lot_views.xml +6 -8
  46. {odoo_addon_stock_barcodes-15.0.3.1.6.dist-info → odoo_addon_stock_barcodes-16.0.1.0.0.18.dist-info}/METADATA +11 -11
  47. odoo_addon_stock_barcodes-16.0.1.0.0.18.dist-info/RECORD +66 -0
  48. {odoo_addon_stock_barcodes-15.0.3.1.6.dist-info → odoo_addon_stock_barcodes-16.0.1.0.0.18.dist-info}/WHEEL +1 -1
  49. odoo/addons/stock_barcodes/migrations/15.0.1.0.0/pre-migration.py +0 -14
  50. odoo/addons/stock_barcodes/models/stock_barcodes_read_log.py +0 -51
  51. odoo/addons/stock_barcodes/static/src/css/stock.css +0 -5
  52. odoo/addons/stock_barcodes/static/src/js/barcodes_models_mixin.js +0 -34
  53. odoo/addons/stock_barcodes/static/src/js/basic_controller.js +0 -412
  54. odoo/addons/stock_barcodes/static/src/js/basic_fields.js +0 -59
  55. odoo/addons/stock_barcodes/static/src/js/form_view.js +0 -24
  56. odoo/addons/stock_barcodes/static/src/js/kanban_renderer.js +0 -47
  57. odoo/addons/stock_barcodes/static/src/js/numeric_step.js +0 -43
  58. odoo_addon_stock_barcodes-15.0.3.1.6.dist-info/RECORD +0 -62
  59. {odoo_addon_stock_barcodes-15.0.3.1.6.dist-info → odoo_addon_stock_barcodes-16.0.1.0.0.18.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from . import stock_barcodes_action
2
2
  from . import stock_barcodes_option
3
- from . import stock_barcodes_read_log
3
+ from . import stock_move
4
4
  from . import stock_move_line
5
5
  from . import stock_picking
6
6
  from . import stock_picking_type
@@ -40,10 +40,11 @@ class StockBarcodesAction(models.Model):
40
40
  vals = {
41
41
  "option_group_id": option_group.id,
42
42
  "manual_entry": option_group.manual_entry,
43
+ "display_read_quant": option_group.display_read_quant,
43
44
  }
44
45
  if option_group.get_option_value("location_id", "filled_default"):
45
46
  vals["location_id"] = (
46
- self.env["stock.warehouse"].search([])[:1].lot_stock_id.id
47
+ self.env["stock.warehouse"].search([], limit=1).lot_stock_id.id
47
48
  )
48
49
  wiz = self.env["wiz.stock.barcodes.read.inventory"].create(vals)
49
50
  action = self.env["ir.actions.actions"]._for_xml_id(
@@ -35,13 +35,10 @@ class StockBarcodesOptionGroup(models.Model):
35
35
  string="Show pending moves", help="Shows a list of movements to process"
36
36
  )
37
37
  source_pending_moves = fields.Selection(
38
- [("move_line_ids", "Detailed operations"), ("move_lines", "Operations")],
38
+ [("move_line_ids", "Detailed operations"), ("move_ids", "Operations")],
39
39
  default="move_line_ids",
40
40
  help="Origin of the data to generate the movements to process",
41
41
  )
42
- show_scan_log = fields.Boolean(
43
- string="Show scan log", help="Displays a log of the scans processed"
44
- )
45
42
  ignore_filled_fields = fields.Boolean(
46
43
  string="Ignore filled fields",
47
44
  )
@@ -103,6 +100,7 @@ class StockBarcodesOptionGroup(models.Model):
103
100
  ("location_dest_id", "Destination Location"),
104
101
  ]
105
102
  )
103
+ display_read_quant = fields.Boolean(string="Read items on inventory mode")
106
104
 
107
105
  def get_option_value(self, field_name, attribute):
108
106
  option = self.option_ids.filtered(lambda op: op.field_name == field_name)[:1]
@@ -0,0 +1,37 @@
1
+ # Copyright 2024 Tecnativa - Sergio Teruel
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
3
+
4
+ from odoo import fields, models
5
+
6
+
7
+ class StockMove(models.Model):
8
+ _inherit = "stock.move"
9
+
10
+ barcode_backorder_action = fields.Selection(
11
+ [
12
+ ("pending", "Pending"),
13
+ ("create_backorder", "Create Backorder"),
14
+ ("skip_backorder", "No Backorder"),
15
+ ],
16
+ string="Backorder action",
17
+ default="pending",
18
+ )
19
+
20
+ def _action_done(self, cancel_backorder=False):
21
+ moves_cancel_backorder = self.browse()
22
+ if not cancel_backorder:
23
+ moves_cancel_backorder = self.filtered(
24
+ lambda sm: sm.barcode_backorder_action == "skip_backorder"
25
+ )
26
+ super(StockMove, moves_cancel_backorder)._action_done(cancel_backorder=True)
27
+ moves_backorder = self - moves_cancel_backorder
28
+ moves_backorder.barcode_backorder_action = "pending"
29
+ return super(StockMove, moves_backorder)._action_done(
30
+ cancel_backorder=cancel_backorder
31
+ )
32
+
33
+ def copy_data(self, default=None):
34
+ vals_list = super().copy_data(default=default)
35
+ for vals in vals_list:
36
+ vals.pop("barcode_backorder_action", None)
37
+ return vals_list
@@ -15,10 +15,10 @@ class StockMoveLine(models.Model):
15
15
  store=True,
16
16
  )
17
17
 
18
- @api.depends("qty_done", "product_uom_qty")
18
+ @api.depends("qty_done", "reserved_uom_qty")
19
19
  def _compute_barcode_scan_state(self):
20
20
  for line in self:
21
- if line.qty_done >= line.product_uom_qty:
21
+ if line.qty_done >= line.reserved_uom_qty:
22
22
  line.barcode_scan_state = "done"
23
23
  else:
24
24
  line.barcode_scan_state = "pending"
@@ -28,19 +28,13 @@ class StockMoveLine(models.Model):
28
28
 
29
29
  def action_barcode_detailed_operation_unlink(self):
30
30
  for sml in self:
31
- if sml.product_uom_qty:
32
- sml._barcodes_process_line_to_unlink()
33
- else:
34
- sml.unlink()
31
+ stock_move = sml.move_id
32
+ stock_move.barcode_backorder_action = "pending"
33
+ sml.unlink()
35
34
  # HACK: To force refresh wizard values
36
35
  wiz_barcode = self.env["wiz.stock.barcodes.read.picking"].browse(
37
36
  self.env.context.get("wiz_barcode_id", False)
38
37
  )
39
- if wiz_barcode.option_group_id.barcode_guided_mode == "guided":
40
- wiz_barcode.todo_line_id.line_ids = wiz_barcode.todo_line_id.line_ids
41
- if not any(wiz_barcode.todo_line_id.line_ids.mapped("qty_done")):
42
- wiz_barcode.fill_todo_records()
43
- wiz_barcode.determine_todo_action()
44
- else:
45
- wiz_barcode.fill_todo_records()
46
- wiz_barcode.todo_line_id.line_ids = wiz_barcode.todo_line_id.line_ids
38
+ stock_move._action_assign()
39
+ wiz_barcode.fill_todo_records()
40
+ wiz_barcode.determine_todo_action()
@@ -1,7 +1,6 @@
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
  from odoo import models
4
- from odoo.tools.float_utils import float_compare
5
4
 
6
5
 
7
6
  class StockPicking(models.Model):
@@ -19,7 +18,7 @@ class StockPicking(models.Model):
19
18
  }
20
19
  if self.picking_type_id.code == "outgoing":
21
20
  vals["location_dest_id"] = self.location_dest_id.id
22
- if self.picking_type_id.code == "incoming":
21
+ elif self.picking_type_id.code == "incoming":
23
22
  vals["location_id"] = self.location_id.id
24
23
 
25
24
  if option_group.get_option_value("location_id", "filled_default"):
@@ -33,8 +32,8 @@ class StockPicking(models.Model):
33
32
  wiz = self.env["wiz.stock.barcodes.read.picking"].create(
34
33
  self._prepare_barcode_wiz_vals(option_group)
35
34
  )
36
- wiz.determine_todo_action()
37
35
  wiz.fill_pending_moves()
36
+ wiz.determine_todo_action()
38
37
  action = self.env["ir.actions.actions"]._for_xml_id(
39
38
  "stock_barcodes.action_stock_barcodes_read_picking"
40
39
  )
@@ -42,41 +41,15 @@ class StockPicking(models.Model):
42
41
  return action
43
42
 
44
43
  def button_validate(self):
45
- if (
46
- self.picking_type_id.barcode_option_group_id.auto_put_in_pack
47
- and not self.move_line_ids.mapped("result_package_id")
48
- ):
49
- self.action_put_in_pack()
50
- create_backorder = False
51
- # Variable initialized as True to optimize break loop
52
- skip_backorder = True
44
+ put_in_pack_picks = self.filtered(
45
+ lambda p: p.picking_type_id.barcode_option_group_id.auto_put_in_pack
46
+ and not p.move_line_ids.result_package_id
47
+ )
48
+ if put_in_pack_picks:
49
+ put_in_pack_picks.action_put_in_pack()
53
50
  if self.env.context.get("stock_barcodes_validate_picking", False):
54
- # Avoid backorder when all move lines are processed (done or done_forced)
55
- prec = self.env["decimal.precision"].precision_get(
56
- "Product Unit of Measure"
57
- )
58
- for move in self.move_lines.filtered(lambda sm: sm.state != "cancel"):
59
- if (
60
- float_compare(
61
- move.quantity_done, move.product_uom_qty, precision_digits=prec
62
- )
63
- < 0
64
- ):
65
- # In normal conditions backorder will be created
66
- create_backorder = True
67
- if not move.move_line_ids or any(
68
- sml.barcode_scan_state in ["pending"]
69
- for sml in move.move_line_ids
70
- ):
71
- # If any move are not processed we can not skip backorder
72
- skip_backorder = False
73
- break
74
- if create_backorder and skip_backorder:
75
51
  res = super(
76
- StockPicking,
77
- self.with_context(
78
- picking_ids_not_to_backorder=self.ids, skip_backorder=True
79
- ),
52
+ StockPicking, self.with_context(skip_backorder=True)
80
53
  ).button_validate()
81
54
  else:
82
55
  res = super().button_validate()
@@ -26,17 +26,15 @@ class StockPickingType(models.Model):
26
26
  "picking_mode": "picking",
27
27
  }
28
28
  if self.code == "outgoing":
29
- location_dest_id = (
29
+ vals["location_dest_id"] = (
30
30
  self.default_location_dest_id.id
31
31
  or self.env.ref("stock.stock_location_customers").id
32
32
  )
33
- vals["location_dest_id"] = location_dest_id
34
- if self.code == "incoming":
35
- location_src_id = (
33
+ elif self.code == "incoming":
34
+ vals["location_id"] = (
36
35
  self.default_location_src_id.id
37
36
  or self.env.ref("stock.stock_location_suppliers").id
38
37
  )
39
- vals["location_id"] = location_src_id
40
38
  if self.barcode_option_group_id.get_option_value(
41
39
  "location_id", "filled_default"
42
40
  ):
@@ -46,8 +44,8 @@ class StockPickingType(models.Model):
46
44
  ):
47
45
  vals["location_dest_id"] = self.default_location_dest_id.id
48
46
  wiz = self.env["wiz.stock.barcodes.read.picking"].create(vals)
49
- wiz.determine_todo_action()
50
47
  wiz.fill_pending_moves()
48
+ wiz.determine_todo_action()
51
49
  action = self.env["ir.actions.actions"]._for_xml_id(
52
50
  "stock_barcodes.action_stock_barcodes_read_picking"
53
51
  )
@@ -55,6 +53,7 @@ class StockPickingType(models.Model):
55
53
  return action
56
54
 
57
55
  def action_barcode_new_picking(self):
56
+ self.ensure_one()
58
57
  picking = (
59
58
  self.env["stock.picking"]
60
59
  .with_context(default_immediate_transfer=True)
@@ -16,7 +16,6 @@ class StockQuant(models.Model):
16
16
  "product_uom_id",
17
17
  "lot_id",
18
18
  "package_id",
19
- "product_qty",
20
19
  ]
21
20
 
22
21
  def action_barcode_inventory_quant_edit(self):
@@ -25,7 +24,7 @@ class StockQuant(models.Model):
25
24
  wiz_barcode_id
26
25
  )
27
26
  for quant in self:
28
- for fname in quant._fields:
29
- if fname in self._get_fields_to_edit():
30
- wiz_barcode[fname] = quant[fname]
27
+ # Try to assign fields with the same name between quant and the scan wizard
28
+ for fname in self._get_fields_to_edit():
29
+ wiz_barcode[fname] = quant[fname]
31
30
  wiz_barcode.product_qty = quant.inventory_quantity
@@ -1,6 +1,4 @@
1
1
  id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2
- access_stock_barcodes_read_log,access_stock_barcodes_read_log,model_stock_barcodes_read_log,base.group_user,1,1,1,1
3
- access_stock_barcodes_read_log_line,access_stock_barcodes_read_log_line,model_stock_barcodes_read_log_line,base.group_user,1,1,1,1
4
2
  access_wiz_stock_barcodes_read_picking,access_wiz_stock_barcodes_read_picking,model_wiz_stock_barcodes_read_picking,base.group_user,1,1,1,1
5
3
  access_wiz_candidate_picking,access_wiz_candidate_picking,model_wiz_candidate_picking,base.group_user,1,1,1,1
6
4
  access_wiz_stock_barcodes_new_lot,access_wiz_stock_barcodes_new_lot,model_wiz_stock_barcodes_new_lot,base.group_user,1,1,1,1
@@ -1,3 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
1
2
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
3
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
4
  <head>
@@ -8,11 +9,10 @@
8
9
 
9
10
  /*
10
11
  :Author: David Goodger (goodger@python.org)
11
- :Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
12
+ :Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
12
13
  :Copyright: This stylesheet has been placed in the public domain.
13
14
 
14
15
  Default cascading style sheet for the HTML output of Docutils.
15
- Despite the name, some widely supported CSS2 features are used.
16
16
 
17
17
  See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
18
18
  customize this style sheet.
@@ -275,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
275
275
  margin-left: 2em ;
276
276
  margin-right: 2em }
277
277
 
278
- pre.code .ln { color: gray; } /* line numbers */
278
+ pre.code .ln { color: grey; } /* line numbers */
279
279
  pre.code, code { background-color: #eeeeee }
280
280
  pre.code .comment, code .comment { color: #5C6576 }
281
281
  pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@ span.option {
301
301
  span.pre {
302
302
  white-space: pre }
303
303
 
304
- span.problematic, pre.problematic {
304
+ span.problematic {
305
305
  color: red }
306
306
 
307
307
  span.section-subtitle {
@@ -367,9 +367,9 @@ ul.auto-toc {
367
367
  !! This file is generated by oca-gen-addon-readme !!
368
368
  !! changes will be overwritten. !!
369
369
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
370
- !! source digest: sha256:6658299983dc274c7a7bbc0ed6f36e8a9b679249c86b3295a92c78fdf305c00f
370
+ !! source digest: sha256:f6453112d1afcb3f171e5f468a06e4927c98ed93493c10c8af4e4aef077de7fd
371
371
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
372
- <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-barcode/tree/15.0/stock_barcodes"><img alt="OCA/stock-logistics-barcode" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--barcode-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-barcode-15-0/stock-logistics-barcode-15-0-stock_barcodes"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-barcode&amp;target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372
+ <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-barcode/tree/16.0/stock_barcodes"><img alt="OCA/stock-logistics-barcode" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--barcode-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-barcode-16-0/stock-logistics-barcode-16-0-stock_barcodes"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-barcode&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
373
373
  <p>This module provides a barcode reader interface for stock module.</p>
374
374
  <p>This module contains a base wizard read barcode that can be extended by
375
375
  other modules.</p>
@@ -518,7 +518,7 @@ Add security for users.</li>
518
518
  <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-barcode/issues">GitHub Issues</a>.
519
519
  In case of trouble, please check there if your issue has already been reported.
520
520
  If you spotted it first, help us to smash it by providing a detailed and welcomed
521
- <a class="reference external" href="https://github.com/OCA/stock-logistics-barcode/issues/new?body=module:%20stock_barcodes%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
521
+ <a class="reference external" href="https://github.com/OCA/stock-logistics-barcode/issues/new?body=module:%20stock_barcodes%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
522
522
  <p>Do not contact contributors directly about support or help with technical issues.</p>
523
523
  </div>
524
524
  <div class="section" id="credits">
@@ -557,13 +557,11 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
557
557
  <div class="section" id="maintainers">
558
558
  <h2><a class="toc-backref" href="#toc-entry-16">Maintainers</a></h2>
559
559
  <p>This module is maintained by the OCA.</p>
560
- <a class="reference external image-reference" href="https://odoo-community.org">
561
- <img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
562
- </a>
560
+ <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
563
561
  <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
564
562
  mission is to support the collaborative development of Odoo features and
565
563
  promote its widespread use.</p>
566
- <p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-barcode/tree/15.0/stock_barcodes">OCA/stock-logistics-barcode</a> project on GitHub.</p>
564
+ <p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-barcode/tree/16.0/stock_barcodes">OCA/stock-logistics-barcode</a> project on GitHub.</p>
567
565
  <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
568
566
  </div>
569
567
  </div>
@@ -12,15 +12,29 @@
12
12
  border-width: 1px 0 0 0;
13
13
  }
14
14
 
15
+ // Avoid too big small buttons from core
16
+ .o_web_client.o_touch_device {
17
+ .oe_stock_barcordes_form {
18
+ .btn {
19
+ &,
20
+ .btn-sm {
21
+ padding: 0.25rem 0.5rem;
22
+ }
23
+ }
24
+ }
25
+ }
26
+
15
27
  .oe_stock_barcordes_form {
16
28
  padding: 0 !important;
17
29
  height: 100%;
18
-
19
- .o_group {
30
+ // Recover useless space
31
+ div[name="_barcode_scanned"] {
32
+ min-height: 0 !important;
33
+ }
34
+ .o_group .scan_fields {
20
35
  &.o_inner_group {
21
36
  margin-bottom: 0 !important;
22
37
  }
23
-
24
38
  margin: 0 !important;
25
39
  }
26
40
 
@@ -32,12 +46,27 @@
32
46
  border: 0 !important;
33
47
  }
34
48
 
49
+ // In Odoo 16 the flat input styling lacks proper usability
35
50
  .o_field_widget {
36
- margin-bottom: 0 !important;
51
+ margin-bottom: 1px !important;
52
+ .o_input {
53
+ border-radius: 3px;
54
+ border-width: 1px;
55
+ background-color: white;
56
+ }
57
+ .o_x2m_control_panel {
58
+ margin: 0px !important;
59
+ }
37
60
  }
38
61
 
39
62
  .o_kanban_record {
40
- padding: 0.3em;
63
+ flex-basis: 100%;
64
+
65
+ .btn-full-width {
66
+ margin: -9px;
67
+ width: calc(100% + 18px);
68
+ height: calc(100% + 18px);
69
+ }
41
70
 
42
71
  &.o_kanban_ghost {
43
72
  display: none;
@@ -82,6 +111,13 @@
82
111
  width: 100% !important;
83
112
  }
84
113
 
114
+ // The kanban view adds some pre-styles that we want to be able to tweak
115
+ div[name="menu_actions"] {
116
+ div[role="article"] {
117
+ margin-top: 10px !important;
118
+ }
119
+ }
120
+
85
121
  // Dropdown that is desactivated at lg width
86
122
  @media (min-width: 992px) {
87
123
  .d-lg-flex-no-dropdown {
@@ -0,0 +1,36 @@
1
+ /** @odoo-module **/
2
+ import {BarcodeHandlerField} from "@barcodes/barcode_handler_field";
3
+ import {patch} from "@web/core/utils/patch";
4
+ import {useService} from "@web/core/utils/hooks";
5
+ const {useEffect} = owl;
6
+
7
+ patch(BarcodeHandlerField.prototype, "stock_barcodes.BarcodeHandlerField", {
8
+ /* eslint-disable no-unused-vars */
9
+ setup() {
10
+ this._super(...arguments);
11
+ const busService = useService("bus_service");
12
+ this.orm = useService("orm");
13
+ const notifyChanges = async ({detail: notifications}) => {
14
+ for (const {payload, type} of notifications) {
15
+ if (type === "stock_barcodes_refresh_data") {
16
+ await this.env.model.root.load();
17
+ this.env.model.notify();
18
+ }
19
+ }
20
+ };
21
+ useEffect(() => {
22
+ busService.addChannel("barcode_reload");
23
+ busService.addEventListener("notification", notifyChanges);
24
+ return () => {
25
+ busService.deleteChannel("barcode_reload");
26
+ busService.removeEventListener("notification", notifyChanges);
27
+ };
28
+ });
29
+ },
30
+ onBarcodeScanned(event) {
31
+ this._super(...arguments);
32
+ if (this.props.record.resModel.includes("wiz.stock.barcodes.read")) {
33
+ $("#dummy_on_barcode_scanned").click();
34
+ }
35
+ },
36
+ });
@@ -0,0 +1,25 @@
1
+ /** @odoo-module */
2
+ /* Copyright 2022 Tecnativa - Alexandre D. Díaz
3
+ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
4
+
5
+ // Models allowed to have extra keybinding features
6
+ export const barcodeModels = [
7
+ "stock.barcodes.action",
8
+ "stock.picking",
9
+ "stock.picking.type",
10
+ "wiz.candidate.picking",
11
+ "wiz.stock.barcodes.new.lot",
12
+ "wiz.stock.barcodes.read",
13
+ "wiz.stock.barcodes.read.inventory",
14
+ "wiz.stock.barcodes.read.picking",
15
+ "wiz.stock.barcodes.read.todo",
16
+ ];
17
+
18
+ /**
19
+ * Helper to know if the given model is allowed
20
+ *
21
+ * @returns {Boolean}
22
+ */
23
+ export function isAllowedBarcodeModel(modelName) {
24
+ return barcodeModels.includes(modelName);
25
+ }
@@ -0,0 +1,17 @@
1
+ /** @odoo-module */
2
+ /* Copyright 2021 Tecnativa - Alexandre D. Díaz
3
+ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
4
+
5
+ import {FormController} from "@web/views/form/form_controller";
6
+ import {patch} from "@web/core/utils/patch";
7
+
8
+ patch(FormController.prototype, "Allow display.controlPanel overriding", {
9
+ setup() {
10
+ this._super(...arguments);
11
+ // Adds support to use control_pannel_hidden from the
12
+ // context to disable the control panel
13
+ if (this.props.context.control_panel_hidden) {
14
+ this.display.controlPanel = false;
15
+ }
16
+ },
17
+ });
@@ -0,0 +1,149 @@
1
+ /** @odoo-module */
2
+ /* Copyright 2022 Tecnativa - Alexandre D. Díaz
3
+ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
4
+
5
+ import {KanbanRenderer} from "@web/views/kanban/kanban_renderer";
6
+ import {isAllowedBarcodeModel} from "../utils/barcodes_models_utils.esm";
7
+ import {patch} from "@web/core/utils/patch";
8
+ import {useBus} from "@web/core/utils/hooks";
9
+ import {useHotkey} from "@web/core/hotkeys/hotkey_hook";
10
+ import {useRef} from "@odoo/owl";
11
+
12
+ patch(KanbanRenderer.prototype, "add hotkey", {
13
+ setup() {
14
+ const rootRef = useRef("root");
15
+ useHotkey(
16
+ "Enter",
17
+ ({target}) => {
18
+ if (!target.classList.contains("o_kanban_record")) {
19
+ return;
20
+ }
21
+
22
+ // Open first link
23
+ let firstLink = null;
24
+ if (isAllowedBarcodeModel(this.props.list.resModel)) {
25
+ firstLink = target.querySelector(
26
+ ".oe_kanban_action_button,.oe_btn_quick_action"
27
+ );
28
+ }
29
+ if (!firstLink) {
30
+ firstLink = target.querySelector(
31
+ ".oe_kanban_global_click, a, button"
32
+ );
33
+ }
34
+ if (firstLink && firstLink instanceof HTMLElement) {
35
+ firstLink.click();
36
+ }
37
+ return;
38
+ },
39
+ {area: () => rootRef.el}
40
+ );
41
+
42
+ this._super(...arguments);
43
+
44
+ if (isAllowedBarcodeModel(this.props.list.resModel)) {
45
+ if (this.env.searchModel) {
46
+ useBus(this.env.searchModel, "focus-view", () => {
47
+ const {model} = this.props.list;
48
+ if (model.useSampleModel || !model.hasData()) {
49
+ return;
50
+ }
51
+ const cards = Array.from(
52
+ rootRef.el.querySelectorAll(".o_kanban_record")
53
+ );
54
+ const firstCard = cards.find(
55
+ (card) =>
56
+ card.querySelectorAll("button[name='action_barcode_scan']")
57
+ .length > 0
58
+ );
59
+ if (firstCard) {
60
+ // Focus first kanban card
61
+ firstCard.focus();
62
+ }
63
+ });
64
+ }
65
+ }
66
+ },
67
+
68
+ // eslint-disable-next-line complexity
69
+ // This is copied from the base kanban_renderer.
70
+ // We want to only focus card with barcode when isAllowedBarcodeModel returns true
71
+ // Since there is no way to hook and change the candidate cards that are selectable
72
+ // (cards line 84) we cannot inherit and change the result. And even if we called
73
+ // super it would not respect inheritability
74
+ /**
75
+ * Redefines focusNextCard to select only kanban card with a barcode
76
+ * when isAllowBarcodeModel returns true for the current model
77
+ *
78
+ * @param {Node} area
79
+ * @param {String} direction
80
+ */
81
+ focusNextCard(area, direction) {
82
+ const {isGrouped} = this.props.list;
83
+ const closestCard = document.activeElement.closest(".o_kanban_record");
84
+ if (!closestCard) {
85
+ return;
86
+ }
87
+ const groups = isGrouped
88
+ ? [...area.querySelectorAll(".o_kanban_group")]
89
+ : [area];
90
+ let cards = [...groups]
91
+ .map((group) => [...group.querySelectorAll(".o_kanban_record")])
92
+ .filter((group) => group.length);
93
+
94
+ if (isAllowedBarcodeModel(this.props.list.resModel)) {
95
+ cards = cards.map((group) => {
96
+ const result = group.filter((card) => {
97
+ return (
98
+ card.querySelectorAll('button[name="action_barcode_scan"]')
99
+ .length > 0
100
+ );
101
+ });
102
+ return result;
103
+ });
104
+ }
105
+
106
+ let iGroup = null;
107
+ let iCard = null;
108
+ for (iGroup = 0; iGroup < cards.length; iGroup++) {
109
+ const i = cards[iGroup].indexOf(closestCard);
110
+ if (i !== -1) {
111
+ iCard = i;
112
+ break;
113
+ }
114
+ }
115
+ if (iCard === undefined) {
116
+ iCard = 0;
117
+ iGroup = 0;
118
+ }
119
+ // Find next card to focus
120
+ let nextCard = null;
121
+ switch (direction) {
122
+ case "down":
123
+ nextCard = iCard < cards[iGroup].length - 1 && cards[iGroup][iCard + 1];
124
+ break;
125
+ case "up":
126
+ nextCard = iCard > 0 && cards[iGroup][iCard - 1];
127
+ break;
128
+ case "right":
129
+ if (isGrouped) {
130
+ nextCard = iGroup < cards.length - 1 && cards[iGroup + 1][0];
131
+ } else {
132
+ nextCard = iCard < cards[0].length - 1 && cards[0][iCard + 1];
133
+ }
134
+ break;
135
+ case "left":
136
+ if (isGrouped) {
137
+ nextCard = iGroup > 0 && cards[iGroup - 1][0];
138
+ } else {
139
+ nextCard = iCard > 0 && cards[0][iCard - 1];
140
+ }
141
+ break;
142
+ }
143
+
144
+ if (nextCard && nextCard instanceof HTMLElement) {
145
+ nextCard.focus();
146
+ return true;
147
+ }
148
+ },
149
+ });