Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][IMP] stock_reception_screen_measuring_device: measure smaller packages #927

Open
wants to merge 2 commits into
base: 14.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion stock_reception_screen_measuring_device/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"name": "Stock Measuring Device on Reception Screen",
"summary": "Allow to use a measuring device from a reception screen."
"for packaging measurement",
"version": "14.0.1.0.0",
"version": "14.0.2.0.0",
"category": "Warehouse",
"author": "Camptocamp, Odoo Community Association (OCA)",
"license": "AGPL-3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging

from odoo import SUPERUSER_ID, api

_logger = logging.getLogger(__name__)


def populate_new_field(env):
records_to_update = (
env["stock.reception.screen"].search([("current_step", "!=", "done")]).exists()
)
_logger.info(
"Set smaller_package_has_missing_dimensions on ongoing reception screens"
)
records_to_update._compute_smaller_package_has_missing_dimensions()


def migrate(cr, version):
if not version:
return
env = api.Environment(cr, SUPERUSER_ID, {})
simahawk marked this conversation as resolved.
Show resolved Hide resolved
populate_new_field(env)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2021 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging

_logger = logging.getLogger(__name__)


def create_and_populate_new_fields(cr):
cr.execute(
"""
ALTER TABLE stock_reception_screen
ADD COLUMN IF NOT EXISTS smaller_package_has_missing_dimensions BOOLEAN;
"""
)
Comment on lines +10 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not blocking, but there are odoo.tools.sql.create_column helper for that.

# Set value to False for done reception screens.
# Otherwise, let the ORM do its job in post migration
_logger.info("Set smaller_package_has_missing_dimensions on done reception screens")
cr.execute(
"""
UPDATE stock_reception_screen
SET smaller_package_has_missing_dimensions = FALSE
WHERE current_step = 'done';
"""
)


def migrate(cr, version):
create_and_populate_new_fields(cr)
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ class StockReceptionScreen(models.Model):
store=True,
help="Indicates if the package have any measurement missing.",
)
smaller_package_has_missing_dimensions = fields.Boolean(
"Smaller Package Requires Measures?",
compute="_compute_smaller_package_has_missing_dimensions",
store=True,
help="Indicates if any smaller package have any measurement missing.",
)
display_package_dimensions = fields.Char(
string="Dimensions (lxhxw)",
compute="_compute_package_dimensions",
Expand All @@ -27,16 +33,19 @@ class StockReceptionScreen(models.Model):
help="A scan from the measuring device was requested",
default=False,
compute="_compute_scan_requested",
store=True,
)

@api.depends("product_packaging_id", "product_packaging_id.measuring_device_id")
@api.depends(
"current_move_product_id.packaging_ids.measuring_device_id",
simahawk marked this conversation as resolved.
Show resolved Hide resolved
)
def _compute_scan_requested(self):
for record in self:
record.scan_requested = (
record.product_packaging_id
and record.product_packaging_id.measuring_device_id
)
all_product_packagings = record.current_move_product_id.packaging_ids
record.scan_requested = False
for packaging in all_product_packagings:
if packaging.measuring_device_id:
record.scan_requested = True
break
simahawk marked this conversation as resolved.
Show resolved Hide resolved

@api.depends(
"product_packaging_id.packaging_length",
Expand All @@ -54,6 +63,20 @@ def _compute_package_dimensions(self):
else:
record.display_package_dimensions = False

@api.depends(
"product_packaging_id",
"product_packaging_id.qty",
"current_move_product_id.packaging_ids.max_weight",
"current_move_product_id.packaging_ids.packaging_length",
"current_move_product_id.packaging_ids.width",
"current_move_product_id.packaging_ids.height",
)
def _compute_smaller_package_has_missing_dimensions(self):
for record in self:
record.smaller_package_has_missing_dimensions = bool(
record._get_smaller_package_without_dimensions()
)

@api.depends(
"product_packaging_id.max_weight",
"product_packaging_id.packaging_length",
Expand All @@ -71,35 +94,78 @@ def _compute_package_has_missing_dimensions(self):
else:
record.package_has_missing_dimensions = False

def measure_current_packaging(self):
self.ensure_one()
@api.model
def _measure_packaging(self, packaging):
device = self.env["measuring.device"].search(
[("is_default", "=", True)], limit=1
)
if not device:
error_msg = _("No default device set, please configure one.")
_logger.error(error_msg)
self._notify(error_msg)
return UserError(error_msg)
self._notify_warning(error_msg)
raise UserError(error_msg)
if device._is_being_used():
error_msg = _("Measurement machine already in use.")
_logger.error(error_msg)
self._notify(error_msg)
return UserError(error_msg)
self._notify_warning(error_msg)
raise UserError(error_msg)

self.product_packaging_id._measuring_device_assign(device)
packaging._measuring_device_assign(device)
message = "MEASURE {}".format(packaging.name)
# Letting the info on the screen, so the user knows which packaging to
# needs to be measured
self._notify_info(message, sticky=True)
return True

def measure_current_packaging(self):
self.ensure_one()
return self._measure_packaging(self.product_packaging_id)

def _get_smaller_package_without_dimensions_domain(self):
self.ensure_one()
return [
("product_id", "=", self.current_move_product_id.id),
("qty", "<", self.product_packaging_id.qty),
"|",
"|",
"|",
("packaging_length", "=", 0),
("width", "=", 0),
("height", "=", 0),
("max_weight", "=", 0),
]

def _get_smaller_package_without_dimensions(self):
self.ensure_one()
domain = self._get_smaller_package_without_dimensions_domain()
return self.env["product.packaging"].search(domain, order="qty desc", limit=1)
mmequignon marked this conversation as resolved.
Show resolved Hide resolved

def measure_smaller_packaging(self):
self.ensure_one()
pack_without_dimensions = self._get_smaller_package_without_dimensions()
if not pack_without_dimensions:
error_msg = _("No available packaging without measurements.")
raise UserError(error_msg)
return self._measure_packaging(pack_without_dimensions)

def cancel_measure_current_packaging(self):
self.ensure_one()
self.product_packaging_id._measuring_device_release()
return True
assigned_packaging = self.current_move_product_id.packaging_ids.filtered(
lambda p: p.measuring_device_id
)
assigned_packaging._measuring_device_release()

def _notify(self, message):
def _notify_warning(self, message):
"""Show a gentle notification on the wizard"""
self.ensure_one()
self.create_uid.with_user(self.create_uid.id).notify_warning(message=message)

def _notify_info(self, message, **kwargs):
self.ensure_one()
self.create_uid.with_user(self.create_uid.id).notify_info(
message=message, **kwargs
)

def reload(self):
self.cancel_measure_current_packaging()
return {
Expand Down
1 change: 1 addition & 0 deletions stock_reception_screen_measuring_device/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_reception_screen_measurement
14 changes: 14 additions & 0 deletions stock_reception_screen_measuring_device/tests/fake_components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo.addons.component.core import Component


class FakeDevice(Component):
_name = "device.component.fake"
_inherit = "measuring.device.base"
_usage = "fake"

def post_update_packaging_measures(self, measures, packaging, wizard_line):
# Unassign measuring device when measuring is done
packaging._measuring_device_release()
14 changes: 14 additions & 0 deletions stock_reception_screen_measuring_device/tests/fake_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import fields, models


class FakeMeasuringDevice(models.Model):
_inherit = "measuring.device"

device_type = fields.Selection(selection_add=[("fake", "FAKE")])

def mocked_measure(self, measurements):
self.ensure_one()
self._update_packaging_measures(measurements)
Loading
Loading