Skip to content

Commit 940a40d

Browse files
committed
Merge PR #927 into 14.0
Signed-off-by sebalix
2 parents 1c6f6a8 + b56cb46 commit 940a40d

9 files changed

+537
-19
lines changed

stock_reception_screen_measuring_device/__manifest__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"name": "Stock Measuring Device on Reception Screen",
55
"summary": "Allow to use a measuring device from a reception screen."
66
"for packaging measurement",
7-
"version": "14.0.1.0.0",
7+
"version": "14.0.2.0.0",
88
"category": "Warehouse",
99
"author": "Camptocamp, Odoo Community Association (OCA)",
1010
"license": "AGPL-3",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2024 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
import logging
5+
6+
from odoo import SUPERUSER_ID, api
7+
8+
_logger = logging.getLogger(__name__)
9+
10+
11+
def populate_new_field(env):
12+
records_to_update = (
13+
env["stock.reception.screen"].search([("current_step", "!=", "done")]).exists()
14+
)
15+
_logger.info(
16+
"Set smaller_package_has_missing_dimensions on ongoing reception screens"
17+
)
18+
records_to_update._compute_smaller_package_has_missing_dimensions()
19+
20+
21+
def migrate(cr, version):
22+
if not version:
23+
return
24+
env = api.Environment(cr, SUPERUSER_ID, {})
25+
populate_new_field(env)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright 2021 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
import logging
5+
6+
_logger = logging.getLogger(__name__)
7+
8+
9+
def create_and_populate_new_fields(cr):
10+
cr.execute(
11+
"""
12+
ALTER TABLE stock_reception_screen
13+
ADD COLUMN IF NOT EXISTS smaller_package_has_missing_dimensions BOOLEAN;
14+
"""
15+
)
16+
# Set value to False for done reception screens.
17+
# Otherwise, let the ORM do its job in post migration
18+
_logger.info("Set smaller_package_has_missing_dimensions on done reception screens")
19+
cr.execute(
20+
"""
21+
UPDATE stock_reception_screen
22+
SET smaller_package_has_missing_dimensions = FALSE
23+
WHERE current_step = 'done';
24+
"""
25+
)
26+
27+
28+
def migrate(cr, version):
29+
create_and_populate_new_fields(cr)

stock_reception_screen_measuring_device/models/stock_reception_screen.py

+82-16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ class StockReceptionScreen(models.Model):
1818
store=True,
1919
help="Indicates if the package have any measurement missing.",
2020
)
21+
smaller_package_has_missing_dimensions = fields.Boolean(
22+
"Smaller Package Requires Measures?",
23+
compute="_compute_smaller_package_has_missing_dimensions",
24+
store=True,
25+
help="Indicates if any smaller package have any measurement missing.",
26+
)
2127
display_package_dimensions = fields.Char(
2228
string="Dimensions (lxhxw)",
2329
compute="_compute_package_dimensions",
@@ -27,16 +33,19 @@ class StockReceptionScreen(models.Model):
2733
help="A scan from the measuring device was requested",
2834
default=False,
2935
compute="_compute_scan_requested",
30-
store=True,
3136
)
3237

33-
@api.depends("product_packaging_id", "product_packaging_id.measuring_device_id")
38+
@api.depends(
39+
"current_move_product_id.packaging_ids.measuring_device_id",
40+
)
3441
def _compute_scan_requested(self):
3542
for record in self:
36-
record.scan_requested = (
37-
record.product_packaging_id
38-
and record.product_packaging_id.measuring_device_id
39-
)
43+
all_product_packagings = record.current_move_product_id.packaging_ids
44+
record.scan_requested = False
45+
for packaging in all_product_packagings:
46+
if packaging.measuring_device_id:
47+
record.scan_requested = True
48+
break
4049

4150
@api.depends(
4251
"product_packaging_id.packaging_length",
@@ -54,6 +63,20 @@ def _compute_package_dimensions(self):
5463
else:
5564
record.display_package_dimensions = False
5665

66+
@api.depends(
67+
"product_packaging_id",
68+
"product_packaging_id.qty",
69+
"current_move_product_id.packaging_ids.max_weight",
70+
"current_move_product_id.packaging_ids.packaging_length",
71+
"current_move_product_id.packaging_ids.width",
72+
"current_move_product_id.packaging_ids.height",
73+
)
74+
def _compute_smaller_package_has_missing_dimensions(self):
75+
for record in self:
76+
record.smaller_package_has_missing_dimensions = bool(
77+
record._get_smaller_package_without_dimensions()
78+
)
79+
5780
@api.depends(
5881
"product_packaging_id.max_weight",
5982
"product_packaging_id.packaging_length",
@@ -71,35 +94,78 @@ def _compute_package_has_missing_dimensions(self):
7194
else:
7295
record.package_has_missing_dimensions = False
7396

74-
def measure_current_packaging(self):
75-
self.ensure_one()
97+
@api.model
98+
def _measure_packaging(self, packaging):
7699
device = self.env["measuring.device"].search(
77100
[("is_default", "=", True)], limit=1
78101
)
79102
if not device:
80103
error_msg = _("No default device set, please configure one.")
81104
_logger.error(error_msg)
82-
self._notify(error_msg)
83-
return UserError(error_msg)
105+
self._notify_warning(error_msg)
106+
raise UserError(error_msg)
84107
if device._is_being_used():
85108
error_msg = _("Measurement machine already in use.")
86109
_logger.error(error_msg)
87-
self._notify(error_msg)
88-
return UserError(error_msg)
110+
self._notify_warning(error_msg)
111+
raise UserError(error_msg)
89112

90-
self.product_packaging_id._measuring_device_assign(device)
113+
packaging._measuring_device_assign(device)
114+
message = "MEASURE {}".format(packaging.packaging_type_id.display_name)
115+
# Letting the info on the screen, so the user knows which packaging to
116+
# needs to be measured
117+
self._notify_info(message, sticky=True)
91118
return True
92119

120+
def measure_current_packaging(self):
121+
self.ensure_one()
122+
return self._measure_packaging(self.product_packaging_id)
123+
124+
def _get_smaller_package_without_dimensions_domain(self):
125+
self.ensure_one()
126+
return [
127+
("product_id", "=", self.current_move_product_id.id),
128+
("qty", "<", self.product_packaging_id.qty),
129+
"|",
130+
"|",
131+
"|",
132+
("packaging_length", "=", 0),
133+
("width", "=", 0),
134+
("height", "=", 0),
135+
("max_weight", "=", 0),
136+
]
137+
138+
def _get_smaller_package_without_dimensions(self):
139+
self.ensure_one()
140+
domain = self._get_smaller_package_without_dimensions_domain()
141+
return self.env["product.packaging"].search(domain, order="qty desc", limit=1)
142+
143+
def measure_smaller_packaging(self):
144+
self.ensure_one()
145+
pack_without_dimensions = self._get_smaller_package_without_dimensions()
146+
if not pack_without_dimensions:
147+
error_msg = _("No available packaging without measurements.")
148+
raise UserError(error_msg)
149+
return self._measure_packaging(pack_without_dimensions)
150+
93151
def cancel_measure_current_packaging(self):
94152
self.ensure_one()
95-
self.product_packaging_id._measuring_device_release()
96-
return True
153+
assigned_packaging = self.current_move_product_id.packaging_ids.filtered(
154+
lambda p: p.measuring_device_id
155+
)
156+
assigned_packaging._measuring_device_release()
97157

98-
def _notify(self, message):
158+
def _notify_warning(self, message):
99159
"""Show a gentle notification on the wizard"""
100160
self.ensure_one()
101161
self.create_uid.with_user(self.create_uid.id).notify_warning(message=message)
102162

163+
def _notify_info(self, message, **kwargs):
164+
self.ensure_one()
165+
self.create_uid.with_user(self.create_uid.id).notify_info(
166+
message=message, **kwargs
167+
)
168+
103169
def reload(self):
104170
self.cancel_measure_current_packaging()
105171
return {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import test_reception_screen_measurement
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright 2024 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from odoo.addons.component.core import Component
5+
6+
7+
class FakeDevice(Component):
8+
_name = "device.component.fake"
9+
_inherit = "measuring.device.base"
10+
_usage = "fake"
11+
12+
def post_update_packaging_measures(self, measures, packaging, wizard_line):
13+
# Unassign measuring device when measuring is done
14+
packaging._measuring_device_release()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright 2024 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from odoo import fields, models
5+
6+
7+
class FakeMeasuringDevice(models.Model):
8+
_inherit = "measuring.device"
9+
10+
device_type = fields.Selection(selection_add=[("fake", "FAKE")])
11+
12+
def mocked_measure(self, measurements):
13+
self.ensure_one()
14+
self._update_packaging_measures(measurements)

0 commit comments

Comments
 (0)