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.
Files changed (79) hide show
  1. odoo/addons/stock_barcodes/README.rst +217 -12
  2. odoo/addons/stock_barcodes/__init__.py +1 -0
  3. odoo/addons/stock_barcodes/__manifest__.py +8 -3
  4. odoo/addons/stock_barcodes/data/stock_barcodes_action.xml +8 -0
  5. odoo/addons/stock_barcodes/data/stock_barcodes_option.xml +99 -1
  6. odoo/addons/stock_barcodes/i18n/stock_barcodes.pot +268 -79
  7. odoo/addons/stock_barcodes/models/__init__.py +1 -0
  8. odoo/addons/stock_barcodes/models/barcode_events_mixin.py +11 -0
  9. odoo/addons/stock_barcodes/models/stock_barcodes_action.py +137 -3
  10. odoo/addons/stock_barcodes/models/stock_picking.py +17 -2
  11. odoo/addons/stock_barcodes/models/stock_picking_type.py +35 -0
  12. odoo/addons/stock_barcodes/models/stock_quant.py +51 -1
  13. odoo/addons/stock_barcodes/readme/CONTRIBUTORS.rst +4 -0
  14. odoo/addons/stock_barcodes/readme/DESCRIPTION.rst +4 -0
  15. odoo/addons/stock_barcodes/readme/HISTORY.rst +12 -0
  16. odoo/addons/stock_barcodes/readme/USAGE.rst +191 -10
  17. odoo/addons/stock_barcodes/reports/__init__.py +1 -0
  18. odoo/addons/stock_barcodes/reports/barcode_actions_report.py +16 -0
  19. odoo/addons/stock_barcodes/reports/barcode_actions_report.xml +25 -0
  20. odoo/addons/stock_barcodes/reports/reports.xml +28 -0
  21. odoo/addons/stock_barcodes/static/description/index.html +189 -33
  22. odoo/addons/stock_barcodes/static/src/docs/barcodes_actions.pdf +0 -0
  23. odoo/addons/stock_barcodes/static/src/docs/barcodes_demo.pdf +0 -0
  24. odoo/addons/stock_barcodes/static/src/img/add_product.png +0 -0
  25. odoo/addons/stock_barcodes/static/src/img/apply_inventory.png +0 -0
  26. odoo/addons/stock_barcodes/static/src/img/apply_inventory_reason.png +0 -0
  27. odoo/addons/stock_barcodes/static/src/img/barcode_interface_picking.png +0 -0
  28. odoo/addons/stock_barcodes/static/src/img/confirm_all_quantity_items_picking.png +0 -0
  29. odoo/addons/stock_barcodes/static/src/img/confirm_items_picking.png +0 -0
  30. odoo/addons/stock_barcodes/static/src/img/create_barcode_action.png +0 -0
  31. odoo/addons/stock_barcodes/static/src/img/form_add_product.png +0 -0
  32. odoo/addons/stock_barcodes/static/src/img/form_add_product_quantity.png +0 -0
  33. odoo/addons/stock_barcodes/static/src/img/form_add_product_reset.png +0 -0
  34. odoo/addons/stock_barcodes/static/src/img/inventory_barcode_action.png +0 -0
  35. odoo/addons/stock_barcodes/static/src/img/list_action_items.png +0 -0
  36. odoo/addons/stock_barcodes/static/src/img/list_items.png +0 -0
  37. odoo/addons/stock_barcodes/static/src/img/list_items_picking.png +0 -0
  38. odoo/addons/stock_barcodes/static/src/img/list_items_picking_edit.png +0 -0
  39. odoo/addons/stock_barcodes/static/src/img/list_items_picking_quantity.png +0 -0
  40. odoo/addons/stock_barcodes/static/src/img/list_items_picking_scanned.png +0 -0
  41. odoo/addons/stock_barcodes/static/src/img/list_picking.png +0 -0
  42. odoo/addons/stock_barcodes/static/src/img/print_barcodes.png +0 -0
  43. odoo/addons/stock_barcodes/static/src/scss/barcode.scss +135 -0
  44. odoo/addons/stock_barcodes/static/src/scss/stock.scss +285 -0
  45. odoo/addons/stock_barcodes/static/src/utils/barcodes_models_utils.esm.js +1 -0
  46. odoo/addons/stock_barcodes/static/src/views/actions/stock_barcode_main_menu.esm.js +88 -0
  47. odoo/addons/stock_barcodes/static/src/views/actions/stock_barcode_main_menu.scss +74 -0
  48. odoo/addons/stock_barcodes/static/src/views/actions/stock_barcode_main_menu.xml +45 -0
  49. odoo/addons/stock_barcodes/static/src/views/form/form_controller.esm.js +71 -0
  50. odoo/addons/stock_barcodes/static/src/views/form/form_view.esm.js +14 -0
  51. odoo/addons/stock_barcodes/static/src/views/kanban/kanban_record.esm.js +27 -0
  52. odoo/addons/stock_barcodes/static/src/views/{kanban_renderer.esm.js → kanban/kanban_renderer.esm.js} +78 -27
  53. odoo/addons/stock_barcodes/static/src/views/kanban/kanban_view.esm.js +8 -0
  54. odoo/addons/stock_barcodes/static/src/views/kanban/stock_barcodes_kanban.xml +28 -0
  55. odoo/addons/stock_barcodes/static/src/views/views.esm.js +35 -7
  56. odoo/addons/stock_barcodes/static/src/widgets/boolean_toggle.esm.js +46 -0
  57. odoo/addons/stock_barcodes/tests/common.py +25 -0
  58. odoo/addons/stock_barcodes/tests/test_stock_barcodes.py +65 -1
  59. odoo/addons/stock_barcodes/tests/test_stock_barcodes_picking.py +97 -13
  60. odoo/addons/stock_barcodes/views/stock_barcodes_action_view.xml +83 -9
  61. odoo/addons/stock_barcodes/views/stock_barcodes_menu.xml +1 -1
  62. odoo/addons/stock_barcodes/views/stock_picking_views.xml +29 -10
  63. odoo/addons/stock_barcodes/wizard/__init__.py +1 -0
  64. odoo/addons/stock_barcodes/wizard/stock_barcodes_candidate_picking.py +148 -0
  65. odoo/addons/stock_barcodes/wizard/stock_barcodes_read.py +148 -55
  66. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory.py +30 -2
  67. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_inventory_views.xml +101 -92
  68. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking.py +77 -141
  69. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_picking_views.xml +197 -219
  70. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_todo.py +45 -0
  71. odoo/addons/stock_barcodes/wizard/stock_barcodes_read_views.xml +87 -170
  72. odoo_addon_stock_barcodes-16.0.2.0.0.dist-info/METADATA +435 -0
  73. odoo_addon_stock_barcodes-16.0.2.0.0.dist-info/RECORD +103 -0
  74. odoo/addons/stock_barcodes/static/src/css/stock.scss +0 -136
  75. odoo/addons/stock_barcodes/static/src/views/form_view.esm.js +0 -17
  76. odoo_addon_stock_barcodes-16.0.1.1.0.10.dist-info/METADATA +0 -230
  77. odoo_addon_stock_barcodes-16.0.1.1.0.10.dist-info/RECORD +0 -68
  78. {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
  79. {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
@@ -17,7 +17,18 @@ 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
+ count_inventory_quants = fields.Integer(
21
+ compute="_compute_count_inventory_quants", store=True
22
+ )
23
+ display_read_quant = fields.Boolean(string="Read items", default=True)
24
+
25
+ def action_display_read_quant(self):
26
+ self.display_read_quant = not self.display_read_quant
27
+
28
+ @api.depends("inventory_quant_ids")
29
+ def _compute_count_inventory_quants(self):
30
+ for wiz in self:
31
+ wiz.count_inventory_quants = len(wiz.inventory_quant_ids)
21
32
 
22
33
  @api.depends("display_read_quant")
23
34
  def _compute_inventory_quant_ids(self):
@@ -26,7 +37,7 @@ class WizStockBarcodesReadInventory(models.TransientModel):
26
37
  ("user_id", "=", self.env.user.id),
27
38
  ("inventory_date", "<=", fields.Date.context_today(self)),
28
39
  ]
29
- if self.display_read_quant:
40
+ if wiz.display_read_quant:
30
41
  domain.append(("inventory_quantity_set", "=", True))
31
42
  order = "write_date DESC"
32
43
  else:
@@ -44,6 +55,13 @@ class WizStockBarcodesReadInventory(models.TransientModel):
44
55
  )
45
56
  wiz.inventory_quant_ids = quants
46
57
 
58
+ # UPDATE: Count elements for apply in inventory
59
+ wiz.send_bus_done(
60
+ "stock_barcodes_form_update",
61
+ "count_apply_inventory",
62
+ {"count": wiz.count_inventory_quants},
63
+ )
64
+
47
65
  def _prepare_stock_quant_values(self):
48
66
  return {
49
67
  "product_id": self.product_id.id,
@@ -114,6 +132,16 @@ class WizStockBarcodesReadInventory(models.TransientModel):
114
132
  def action_clean_values(self):
115
133
  res = super().action_clean_values()
116
134
  self.inventory_product_qty = 0.0
135
+ self.package_id = False
136
+ # Hide Form Edit
137
+ self.manual_entry = False
138
+ self.send_bus_done(
139
+ "stock_barcodes_scan",
140
+ "stock_barcodes_edit_manual",
141
+ {
142
+ "manual_entry": False,
143
+ },
144
+ )
117
145
  return res
118
146
 
119
147
  @api.onchange("product_id")
@@ -15,7 +15,7 @@
15
15
  <div class="mt4">
16
16
  <strong class="d-none d-sm-block">Package</strong>
17
17
  <span
18
- class="fa fa-inbox d-sm-none oe_span_small_icon"
18
+ class="fa fa-inbox fa-2x d-sm-none oe_span_small_icon"
19
19
  title="package"
20
20
  />
21
21
  <field
@@ -29,89 +29,48 @@
29
29
  </div>
30
30
  </group>
31
31
  <field name="location_id" position="attributes">
32
- <attribute
33
- name="domain"
34
- >[('usage', 'in', ['internal', 'transit'])]</attribute>
32
+ <attribute name="domain">[('usage', 'in', ['internal', 'transit'])]
33
+ </attribute>
35
34
  </field>
36
35
  <group name="scan_fields" position="after">
37
36
  <group
38
37
  string="Inventory quants"
39
38
  attrs="{'invisible': [('inventory_quant_ids', '=', [])]}"
40
39
  col="2"
40
+ class="px-3"
41
41
  >
42
42
  <field
43
43
  name="inventory_quant_ids"
44
44
  options="{'no_open': True}"
45
45
  nolabel="1"
46
46
  colspan="2"
47
- mode="tree,kanban"
47
+ mode="kanban"
48
48
  >
49
- <tree>
50
- <field name="product_id" options="{'no_open': True}" />
51
- <field
52
- name="location_id"
53
- options="{'no_open': True}"
54
- groups="stock.group_stock_multi_locations"
55
- optional="show"
56
- />
57
- <field
58
- name="lot_id"
59
- groups="stock.group_production_lot"
60
- options="{'no_open': True}"
61
- optional="show"
62
- />
63
- <field
64
- name="package_id"
65
- groups="stock.group_tracking_lot"
66
- options="{'no_open': True}"
67
- optional="show"
68
- />
69
- <field name="inventory_quantity" />
70
- <field
71
- name="product_uom_id"
72
- groups="uom.group_uom"
73
- options="{'no_open': True}"
74
- />
75
- <button
76
- name="action_barcode_inventory_quant_edit"
77
- type="object"
78
- icon="fa-pencil"
79
- class="btn mt0"
80
- context="{'wiz_barcode_id': parent.id}"
81
- >
82
- </button>
83
- <button
84
- name="action_barcode_inventory_quant_unlink"
85
- type="object"
86
- class="btn"
87
- icon="fa-trash"
88
- title="Remove quant"
89
- context="{'wiz_barcode_id': parent.id}"
90
- />
91
- </tree>
92
- <kanban class="o_kanban_mobile">
49
+ <kanban
50
+ class="o_kanban_mobile"
51
+ js_class="stock_barcodes_kanban"
52
+ >
93
53
  <field name="product_id" />
94
54
  <field name="inventory_quantity" />
95
55
  <field name="product_uom_id" />
96
56
  <templates>
97
57
  <t t-name="kanban-box">
98
- <div t-attf-class="oe_kanban_card">
99
- <div class="row">
100
- <div class="col-7">
101
- <strong>
102
- <span>
103
- <field name="product_id" />
104
- </span>
105
- </strong>
58
+ <div t-on-click="onCustomGlobalClick">
59
+ <div class="row w-auto">
60
+ <div class="col-8 col-md-10">
61
+ <field name="product_id" class="h2" />
106
62
  </div>
107
- <div class="col-2">
108
- <span
109
- class="float-end text-end fw-bold"
110
- >
111
- <field name="inventory_quantity" />
112
- </span>
113
- </div>
114
- <div class="col-3 text-end">
63
+ <div
64
+ class="col-4 col-md-2 d-flex justify-content-end align-items-center"
65
+ >
66
+ <img
67
+ t-att-src="kanban_image('product.product', 'image_128', record.product_id.raw_value)"
68
+ role="img"
69
+ t-att-title="record.product_id.value"
70
+ height="40"
71
+ width="40"
72
+ t-att-alt="record.product_id.value"
73
+ />
115
74
  <button
116
75
  name="action_barcode_inventory_quant_edit"
117
76
  type="object"
@@ -121,33 +80,62 @@
121
80
  <i
122
81
  class="fa fa-pencil"
123
82
  title="Edit inventory quantity"
124
- style="font-size:1.5em"
125
83
  />
126
84
  </button>
85
+ </div>
86
+ </div>
87
+ <div class="row">
88
+ <div
89
+ class="col-8 col-md-10 d-flex justify-content-start align-items-center"
90
+ >
91
+ <span
92
+ t-if="record.lot_id.raw_value"
93
+ class="h3"
94
+ >Lot S/N:&#32;&#32;</span>
95
+ <field
96
+ t-if="record.lot_id.raw_value"
97
+ name="lot_id"
98
+ class="h2"
99
+ />
100
+ </div>
101
+ <div
102
+ class="col-4 col-md-2 d-flex justify-content-end align-items-center"
103
+ >
104
+ <span class="fw-bold mx-3">
105
+ <field name="inventory_quantity" />
106
+ </span>
127
107
  <button
128
108
  name="action_barcode_inventory_quant_unlink"
129
109
  type="object"
130
- icon="fa-trash"
131
- title="Reset inventory quantity"
132
110
  class="btn mt0"
133
111
  context="{'wiz_barcode_id': parent.id}"
134
- />
112
+ >
113
+ <i
114
+ class="fa fa-trash"
115
+ title="Reset inventory quantity"
116
+ />
117
+ </button>
135
118
  </div>
136
119
  </div>
137
- <div class="row">
138
- <div class="col-4">
139
- Loc: <field name="location_id" />
120
+ <div
121
+ t-attf-class="row oe_kanban_operations oe_kanban_operations-#{record.id.raw_value} d-none"
122
+ >
123
+ <div
124
+ class="d-flex justify-content-end align-items-center"
125
+ >
126
+ <button
127
+ name="operation_quantities_rest"
128
+ type="object"
129
+ class="btn btn-lg btn-op-rest text-white ms-2 ms-sm-4 mx-2"
130
+ >-1
131
+ </button>
132
+ <button
133
+ name="operation_quantities"
134
+ type="object"
135
+ class="btn btn-lg btn-op-sum text-white"
136
+ >+1
137
+ </button>
140
138
  </div>
141
- <t t-if="record.lot_id.raw_value">
142
- <div class="col-4">
143
- Lot: <field name="lot_id" />
144
- </div>
145
- </t>
146
- <t t-if="record.package_id.raw_value">
147
- <div class="col-4">
148
- Package: <field name="package_id" />
149
- </div>
150
- </t>
151
139
  </div>
152
140
  </div>
153
141
  </t>
@@ -156,22 +144,43 @@
156
144
  </field>
157
145
  </group>
158
146
  </group>
159
- <div name="manual_entry" position="after">
160
- <div class="d-flex" name="display_read_quant">
161
- <field name="display_read_quant" widget="barcode_boolean_toggle" />
162
- <label for="display_read_quant" />
163
- </div>
164
- </div>
147
+ <xpath
148
+ expr="//div[hasclass('oe_stock_barcodes_bottombar')]//div[hasclass('dropup')]"
149
+ position="inside"
150
+ >
151
+ <field
152
+ name="display_read_quant"
153
+ widget="barcode_boolean_toggle"
154
+ class="d-none"
155
+ />
156
+ <button
157
+ name="action_display_read_quant"
158
+ type="object"
159
+ title="Read items"
160
+ icon="fa-eye fa-2x"
161
+ attrs="{'invisible': [('display_read_quant', '=', True)]}"
162
+ />
163
+
164
+ <button
165
+ name="action_display_read_quant"
166
+ type="object"
167
+ title="Read items"
168
+ icon="fa-eye-slash fa-2x"
169
+ attrs="{'invisible': [('display_read_quant', '=', False)]}"
170
+ />
171
+ </xpath>
165
172
  <button name="action_clean_values" position="before">
166
173
  <button
167
174
  name="apply_inventory"
168
175
  type="object"
169
- class="btn-primary ms-auto oe_kanban_action_button btn-sm"
170
- attrs="{'invisible': ['|', ('display_menu', '=', True), ('inventory_quant_ids', '=', [])]}"
176
+ icon="fa-check fa-2x"
177
+ class="btn-primary w-100 oe_kanban_action_button btn-sm d-flex justify-content-center align-items-center fs-1"
178
+ attrs="{'invisible': ['|', '|',('display_menu', '=', True), ('inventory_quant_ids', '=', []), ('display_read_quant', '=', False)]}"
171
179
  data-hotkey="7"
172
180
  groups="stock.group_stock_manager"
173
181
  >
174
- <span>Apply</span>
182
+ <span class="d-none d-lg-block">Apply</span>
183
+ (<span class="count_apply_inventory" />)
175
184
  </button>
176
185
  </button>
177
186
  </field>
@@ -190,6 +199,6 @@
190
199
  }
191
200
  </field>
192
201
  <field name="view_id" ref="view_stock_barcodes_read_inventory_form" />
193
- <field name="target">current</field>
202
+ <field name="target">fullscreen</field>
194
203
  </record>
195
204
  </odoo>
@@ -29,13 +29,16 @@ class WizStockBarcodesReadPicking(models.TransientModel):
29
29
  picking_ids = fields.Many2many(
30
30
  comodel_name="stock.picking", string="Pickings", readonly=True
31
31
  )
32
+ candidate_picking_id = fields.Many2one(
33
+ comodel_name="stock.picking", related="candidate_picking_ids.picking_id"
34
+ )
32
35
  candidate_picking_ids = fields.One2many(
33
36
  comodel_name="wiz.candidate.picking",
34
37
  inverse_name="wiz_barcode_id",
35
38
  string="Candidate pickings",
36
39
  readonly=True,
37
40
  )
38
- # TODO: Remove this field
41
+
39
42
  picking_product_qty = fields.Float(
40
43
  string="Picking quantities", digits="Product Unit of Measure", readonly=True
41
44
  )
@@ -43,7 +46,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
43
46
  [("incoming", "Vendors"), ("outgoing", "Customers"), ("internal", "Internal")],
44
47
  "Type of Operation",
45
48
  )
46
- # TODO: Check if move_line_ids is used
49
+
47
50
  move_line_ids = fields.One2many(
48
51
  comodel_name="stock.move.line", compute="_compute_move_line_ids"
49
52
  )
@@ -66,7 +69,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
66
69
  comodel_name="wiz.stock.barcodes.read.todo"
67
70
  )
68
71
  show_detailed_operations = fields.Boolean(
69
- related="option_group_id.show_detailed_operations"
72
+ related="option_group_id.show_detailed_operations", default=True, store=True
70
73
  )
71
74
  keep_screen_values = fields.Boolean(related="option_group_id.keep_screen_values")
72
75
  # Extended from stock_barcodes_read base model
@@ -79,6 +82,16 @@ class WizStockBarcodesReadPicking(models.TransientModel):
79
82
  todo_line_is_extra_line = fields.Boolean(related="todo_line_id.is_extra_line")
80
83
  forced_todo_key = fields.Char()
81
84
  qty_available = fields.Float(compute="_compute_qty_available")
85
+ partner_id = fields.Many2one("res.partner", related="picking_id.partner_id")
86
+ enable_add_product = fields.Boolean(compute="_compute_enable_add_product")
87
+
88
+ def action_show_detailed_operations(self):
89
+ self.show_detailed_operations = not self.show_detailed_operations
90
+
91
+ @api.depends("picking_state")
92
+ def _compute_enable_add_product(self):
93
+ for rec in self:
94
+ rec.enable_add_product = rec.picking_state != "done"
82
95
 
83
96
  @api.depends("todo_line_id")
84
97
  def _compute_todo_line_display_ids(self):
@@ -95,7 +108,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
95
108
  )
96
109
  )
97
110
  else:
98
- self.pending_move_ids = False
111
+ self.pending_move_ids = self.todo_line_ids
99
112
 
100
113
  @api.depends(
101
114
  "todo_line_ids", "todo_line_ids.qty_done", "picking_id.move_line_ids.qty_done"
@@ -225,7 +238,6 @@ class WizStockBarcodesReadPicking(models.TransientModel):
225
238
  return move_lines
226
239
 
227
240
  def fill_pending_moves(self):
228
- # TODO: Unify method
229
241
  self.fill_todo_records()
230
242
 
231
243
  def get_moves_or_move_lines(self):
@@ -304,7 +316,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
304
316
  def action_done(self):
305
317
  res = super().action_done()
306
318
  if res:
307
- move_dic = self._process_stock_move_line()
319
+ move_dic = self.with_context(**self.env.context)._process_stock_move_line()
308
320
  if move_dic:
309
321
  self[self._field_candidate_ids].scan_count += 1
310
322
  if self.env.context.get("force_create_move"):
@@ -353,7 +365,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
353
365
  picking = self.env.context.get("picking", self.picking_id)
354
366
  if not picking:
355
367
  raise ValidationError(
356
- _("You can not add extra moves if you have " "not set a picking")
368
+ _("You can not add extra moves if you have not set a picking")
357
369
  )
358
370
  # If we move all package units the result package is the same
359
371
  if (
@@ -512,10 +524,12 @@ class WizStockBarcodesReadPicking(models.TransientModel):
512
524
  )
513
525
  else:
514
526
  moves_todo = StockMove.search(domain)
515
- if not getattr(
516
- self,
517
- "_search_candidate_%s" % self.picking_mode,
518
- )(moves_todo):
527
+ try:
528
+ getattr(
529
+ self,
530
+ "_search_candidate_%s" % self.picking_mode,
531
+ )(moves_todo)
532
+ except AttributeError:
519
533
  return False
520
534
  sml_vals = {}
521
535
  candidate_lines = self._get_candidate_stock_move_lines(moves_todo, sml_vals)
@@ -583,6 +597,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
583
597
  self._set_focus_on_qty_input("product_qty")
584
598
  return False
585
599
  move_lines_dic = {}
600
+ context = self.env.context
586
601
  for line in lines:
587
602
  if line.reserved_uom_qty and len(lines) > 1:
588
603
  assigned_qty = min(
@@ -597,6 +612,9 @@ class WizStockBarcodesReadPicking(models.TransientModel):
597
612
  and self.result_package_id == self.package_id
598
613
  ):
599
614
  qty_done = assigned_qty
615
+ elif context.get("no_increase_qty_done", False) and assigned_qty > 0:
616
+ # Do not increase the quantity, if the quantity is > 0
617
+ qty_done = assigned_qty
600
618
  else:
601
619
  qty_done = line.qty_done + assigned_qty
602
620
  sml_vals.update(
@@ -605,7 +623,7 @@ class WizStockBarcodesReadPicking(models.TransientModel):
605
623
  "result_package_id": self.result_package_id.id,
606
624
  }
607
625
  )
608
- # Add or remove result_package_id
626
+ # Add or remove result_pselfackage_id
609
627
  package_qty_available = sum(
610
628
  self.package_id.quant_ids.filtered(
611
629
  lambda q: q.lot_id == self.lot_id
@@ -660,6 +678,8 @@ class WizStockBarcodesReadPicking(models.TransientModel):
660
678
  for sml in stock_move_lines:
661
679
  if not sml.move_id:
662
680
  self.create_new_stock_move(sml)
681
+ elif sml.move_id and context.get("force_create_move", False):
682
+ sml.move_id.product_uom_qty = self.product_qty
663
683
  move_lines_dic[sml.id] = sml.qty_done
664
684
  # Ensure that the state of stock_move linked to the sml read is assigned
665
685
  stock_move_lines.move_id.filtered(
@@ -775,12 +795,22 @@ class WizStockBarcodesReadPicking(models.TransientModel):
775
795
  raise ValidationError(_("No pending lines for this product"))
776
796
 
777
797
  def action_put_in_pack(self):
778
- self.picking_id.action_put_in_pack()
798
+ for picking in self.mapped("picking_id"):
799
+ picking.action_put_in_pack()
779
800
 
780
801
  def action_clean_values(self):
781
802
  res = super().action_clean_values()
782
803
  self.selected_pending_move_id = False
783
804
  self.visible_force_done = False
805
+ # Hide Form Edit
806
+ self.manual_entry = False
807
+ self.send_bus_done(
808
+ "stock_barcodes_scan",
809
+ "stock_barcodes_edit_manual",
810
+ {
811
+ "manual_entry": False,
812
+ },
813
+ )
784
814
  return res
785
815
 
786
816
  def _option_required_hook(self, option_required):
@@ -948,138 +978,44 @@ class WizStockBarcodesReadPicking(models.TransientModel):
948
978
  list(todo_vals.values())
949
979
  )
950
980
 
951
-
952
- class WizCandidatePicking(models.TransientModel):
953
- """
954
- TODO: explain
955
- """
956
-
957
- _name = "wiz.candidate.picking"
958
- _description = "Candidate pickings for barcode interface"
959
- # To prevent remove the record wizard until 2 days old
960
- _transient_max_hours = 48
961
-
962
- wiz_barcode_id = fields.Many2one(
963
- comodel_name="wiz.stock.barcodes.read.picking", readonly=True
964
- )
965
- picking_id = fields.Many2one(
966
- comodel_name="stock.picking", string="Picking", readonly=True
967
- )
968
- wiz_picking_id = fields.Many2one(
969
- comodel_name="stock.picking",
970
- related="wiz_barcode_id.picking_id",
971
- string="Wizard Picking",
972
- readonly=True,
973
- )
974
- name = fields.Char(
975
- related="picking_id.name", readonly=True, string="Candidate Picking"
976
- )
977
- partner_id = fields.Many2one(
978
- comodel_name="res.partner",
979
- related="picking_id.partner_id",
980
- readonly=True,
981
- string="Partner",
982
- )
983
- state = fields.Selection(related="picking_id.state", readonly=True)
984
- date = fields.Datetime(
985
- related="picking_id.date", readonly=True, string="Creation Date"
986
- )
987
- product_qty_reserved = fields.Float(
988
- "Reserved",
989
- compute="_compute_picking_quantity",
990
- digits="Product Unit of Measure",
991
- readonly=True,
992
- )
993
- product_uom_qty = fields.Float(
994
- "Demand",
995
- compute="_compute_picking_quantity",
996
- digits="Product Unit of Measure",
997
- readonly=True,
998
- )
999
- product_qty_done = fields.Float(
1000
- "Done",
1001
- compute="_compute_picking_quantity",
1002
- digits="Product Unit of Measure",
1003
- readonly=True,
1004
- )
1005
- # For reload kanban view
1006
- scan_count = fields.Integer()
1007
- is_pending = fields.Boolean(compute="_compute_is_pending")
1008
- note = fields.Html(related="picking_id.note")
1009
-
1010
- @api.depends("scan_count")
1011
- def _compute_picking_quantity(self):
1012
- for candidate in self:
1013
- qty_reserved = 0
1014
- qty_demand = 0
1015
- qty_done = 0
1016
- candidate.product_qty_reserved = sum(
1017
- candidate.picking_id.mapped("move_ids.reserved_availability")
1018
- )
1019
- for move in candidate.picking_id.move_ids:
1020
- qty_reserved += move.reserved_availability
1021
- qty_demand += move.product_uom_qty
1022
- qty_done += move.quantity_done
1023
- candidate.update(
1024
- {
1025
- "product_qty_reserved": qty_reserved,
1026
- "product_uom_qty": qty_demand,
1027
- "product_qty_done": qty_done,
1028
- }
1029
- )
1030
-
1031
- @api.depends("scan_count")
1032
- def _compute_is_pending(self):
1033
- for rec in self:
1034
- rec.is_pending = bool(rec.wiz_barcode_id.pending_move_ids)
1035
-
1036
- def _get_wizard_barcode_read(self):
1037
- return self.env["wiz.stock.barcodes.read.picking"].browse(
1038
- self.env.context["wiz_barcode_id"]
1039
- )
1040
-
1041
- def action_lock_picking(self):
1042
- wiz = self._get_wizard_barcode_read()
1043
- picking_id = self.env.context["picking_id"]
1044
- wiz.picking_id = picking_id
1045
- wiz._set_candidate_pickings(wiz.picking_id)
1046
- return wiz.action_confirm()
1047
-
1048
- def action_unlock_picking(self):
1049
- wiz = self._get_wizard_barcode_read()
1050
- wiz.update(
1051
- {
1052
- "picking_id": False,
1053
- "candidate_picking_ids": False,
1054
- "message_type": False,
1055
- "message": False,
1056
- }
981
+ def action_validate_picking(self):
982
+ # for candidate_picking in self.candidate_picking_ids:
983
+ valid, result = self.candidate_picking_ids.with_context(
984
+ wiz_barcode_id=self.id,
985
+ picking_id=self.picking_id.id,
986
+ skip_sms=True,
987
+ skip_immediate=True,
988
+ ).action_validate_picking()
989
+ if not valid:
990
+ return result
991
+ action = self.env["ir.actions.actions"]._for_xml_id(
992
+ "stock_barcodes.stock_barcodes_action_picking_tree_ready"
1057
993
  )
1058
- return wiz.action_cancel()
1059
994
 
1060
- def _get_picking_to_validate(self):
1061
- """Inject context show_picking_type_action_tree to redirect to picking list
1062
- after validate picking in barcodes environment.
1063
- The stock_barcodes_validate_picking key allows to know when a picking has been
1064
- validated from stock barcodes interface.
1065
- """
1066
- return (
1067
- self.env["stock.picking"]
1068
- .browse(self.env.context.get("picking_id", False))
1069
- .with_context(
1070
- show_picking_type_action_tree=True, stock_barcodes_validate_picking=True
995
+ if self.picking_id and self.picking_id.picking_type_id:
996
+ context = self.env.context.copy()
997
+ context.update(safe_eval(action["context"]))
998
+ context.update(
999
+ {"search_default_picking_type_id": self.picking_id.picking_type_id.id}
1071
1000
  )
1072
- )
1001
+ action["context"] = context
1073
1002
 
1074
- def action_validate_picking(self):
1075
- picking = self._get_picking_to_validate()
1076
- return picking.button_validate()
1003
+ return action
1077
1004
 
1078
1005
  def action_open_picking(self):
1079
- picking = self.env["stock.picking"].browse(
1080
- self.env.context.get("picking_id", False)
1081
- )
1082
- return picking.with_context(control_panel_hidden=False).get_formview_action()
1006
+ for candidate_picking in self.candidate_picking_ids:
1007
+ candidate_picking.with_context(
1008
+ wiz_barcode_id=self.id, picking_id=self.picking_id.id
1009
+ ).action_open_picking()
1083
1010
 
1084
- def action_put_in_pack(self):
1085
- self.picking_id.action_put_in_pack()
1011
+ def action_unlock_picking(self):
1012
+ for candidate_picking in self.candidate_picking_ids:
1013
+ candidate_picking.with_context(
1014
+ wiz_barcode_id=self.id
1015
+ ).action_unlock_picking()
1016
+
1017
+ def action_lock_picking(self):
1018
+ for candidate_picking in self.candidate_picking_ids:
1019
+ candidate_picking.with_context(
1020
+ wiz_barcode_id=self.id, picking_id=self.picking_id.id
1021
+ ).action_lock_picking()