diff --git a/setup/stock_location_bin_name/odoo/addons/stock_location_bin_name b/setup/stock_location_bin_name/odoo/addons/stock_location_bin_name new file mode 120000 index 000000000..cb6599b26 --- /dev/null +++ b/setup/stock_location_bin_name/odoo/addons/stock_location_bin_name @@ -0,0 +1 @@ +../../../../stock_location_bin_name \ No newline at end of file diff --git a/setup/stock_location_bin_name/setup.py b/setup/stock_location_bin_name/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/stock_location_bin_name/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_location_bin_name/__init__.py b/stock_location_bin_name/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/stock_location_bin_name/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_location_bin_name/__manifest__.py b/stock_location_bin_name/__manifest__.py new file mode 100644 index 000000000..9d81d6f3c --- /dev/null +++ b/stock_location_bin_name/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2017 Syvain Van Hoof (Okia sprl) +# Copyright 2016-2019 Jacques-Etienne Baudoux (BCIM) +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +{ + "name": "Stock Location Bin Name", + "version": "13.0.1.0.0", + "author": "BCIM, Okia, Camptocamp, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "summary": "Compute bin stock location name automatically", + "category": "Stock Management", + "depends": ["stock_location_zone", "stock_location_position"], + "data": ["views/stock_location.xml"], + "installable": True, + "development_status": "Alpha", + "license": "AGPL-3", +} diff --git a/stock_location_bin_name/models/__init__.py b/stock_location_bin_name/models/__init__.py new file mode 100644 index 000000000..88493e35d --- /dev/null +++ b/stock_location_bin_name/models/__init__.py @@ -0,0 +1 @@ +from . import stock_location diff --git a/stock_location_bin_name/models/stock_location.py b/stock_location_bin_name/models/stock_location.py new file mode 100644 index 000000000..5a4c38b10 --- /dev/null +++ b/stock_location_bin_name/models/stock_location.py @@ -0,0 +1,67 @@ +# Copyright 2017 Syvain Van Hoof (Okia sprl) +# Copyright 2016-2019 Jacques-Etienne Baudoux (BCIM) +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +import string + +from odoo import api, fields, models + + +class PartialFormatter(string.Formatter): + def __init__(self, missing="~", bad_fmt="!"): + self.missing = missing + self.bad_fmt = bad_fmt + + def get_field(self, field_name, args, kwargs): + # Handle a key not found + try: + val = super().get_field(field_name, args, kwargs) + except (KeyError, AttributeError): + val = None, field_name + return val + + def format_field(self, value, spec): + # handle an invalid format + if value is None: + return self.missing + try: + return super().format_field(value, spec) + except ValueError: + if self.bad_fmt is not None: + return self.bad_fmt + else: + raise + + +class StockLocation(models.Model): + _inherit = "stock.location" + + location_name_format = fields.Char( + "Location Name Format", + help="Format string that will compute the name of the location. " + "Use location fields. Example: " + "'{area}-{corridor:0>2}.{rack:0>3}" + ".{level:0>2}'\n" + "Missing fields are replaced by '~' and formatting errors by '!'.", + ) + + @api.onchange("corridor", "row", "rack", "level", "posx", "posy", "posz") + def _onchange_attribute_compute_name(self): + for location in self: + if not location.location_kind == "bin": + continue + area = location + while area and not area.location_name_format: + area = area.location_id + if not area: + continue + template = area.location_name_format + # We don't want to use the full browse record as it would + # give too much access to internals for the users. + # We cannot use location.read() as we may have a NewId. + # We should have the record's values in the cache at this + # point. We must be cautious not to leak an environment through + # relational fields. + values = dict(location._cache) + values["area"] = area.name + location.name = PartialFormatter().format(template, **values) diff --git a/stock_location_bin_name/readme/CONTRIBUTORS.rst b/stock_location_bin_name/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..0425dda61 --- /dev/null +++ b/stock_location_bin_name/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* Syvain Van Hoof (Okia sprl) +* Jacques-Etienne Baudoux (BCIM) +* Guewen Baconnier (Camptocamp) +* Akim Juillerat diff --git a/stock_location_bin_name/readme/DESCRIPTION.rst b/stock_location_bin_name/readme/DESCRIPTION.rst new file mode 100644 index 000000000..d868c822f --- /dev/null +++ b/stock_location_bin_name/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows to compute automatically Bin location names based on +locations attributes. diff --git a/stock_location_bin_name/views/stock_location.xml b/stock_location_bin_name/views/stock_location.xml new file mode 100644 index 000000000..9cbcdc769 --- /dev/null +++ b/stock_location_bin_name/views/stock_location.xml @@ -0,0 +1,16 @@ + + + + stock.location.name.format + stock.location + + + + + + + +