From 9128bf41652d66fddb486835f65a091cb2b96f16 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Tue, 27 Aug 2019 11:22:50 +0200 Subject: [PATCH] Add corrections to stock_location_zone * Allow copy of stock locations (was blocked by constraint on unique name) * Correct loop in _compute_name returning too early if a record had no parent with a 'location_name_format' * Rename field pick_type_id to picking_type_id for coherency * Add missing _description on stock.picking.zone * Correct location_name_format format when the record is a NewId --- stock_location_zone/__manifest__.py | 2 +- stock_location_zone/models/stock_location.py | 94 ++++++++++++++++--- .../models/stock_picking_zone.py | 5 +- .../views/stock_picking_zone.xml | 2 +- 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/stock_location_zone/__manifest__.py b/stock_location_zone/__manifest__.py index 95808d17e..08b4873c0 100644 --- a/stock_location_zone/__manifest__.py +++ b/stock_location_zone/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Stock Location Zone', 'version': '12.0.1.0.0', - 'author': "BCIM, Okia, Odoo Community Association (OCA)", + 'author': "BCIM, Okia, Camptocamp, Odoo Community Association (OCA)", 'website': "https://github.com/OCA/stock-logistics-warehouse", 'summary': "Add coordinate attributes on stock location. " "Define picking zone with links to picking type.", diff --git a/stock_location_zone/models/stock_location.py b/stock_location_zone/models/stock_location.py index d3af3f071..33d8b3517 100644 --- a/stock_location_zone/models/stock_location.py +++ b/stock_location_zone/models/stock_location.py @@ -2,7 +2,32 @@ # Copyright 2018-2019 Jacques-Etienne Baudoux (BCIM sprl) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import _, api, fields, models +from psycopg2 import sql + +from odoo import _, api, exceptions, fields, models, SUPERUSER_ID +from odoo.tools.sql import index_exists, _schema + + +def create_unique_index_where(cr, indexname, tablename, expressions, where): + """Create the given unique index unless it exists.""" + if index_exists(cr, indexname): + return + + args = ', '.join(expressions) + # pylint: disable=sql-injection + cr.execute( + sql.SQL( + 'CREATE UNIQUE INDEX {} ON {} ({}) WHERE {}').format( + sql.Identifier(indexname), + sql.Identifier(tablename), + sql.SQL(args), + sql.SQL(where), + ) + ) + _schema.debug( + "Table %r: created unique index %r (%s) WHERE {}", + tablename, indexname, args, where + ) class StockLocation(models.Model): @@ -18,10 +43,12 @@ class StockLocation(models.Model): picking_zone_id = fields.Many2one( 'stock.picking.zone', - string='Picking zone') + string='Picking zone', + index=True, + ) picking_type_id = fields.Many2one( - related='picking_zone_id.pick_type_id', + related='picking_zone_id.picking_type_id', help="Picking type for operations from this location", oldname='barcode_picking_type_id') @@ -61,18 +88,57 @@ class StockLocation(models.Model): if not location.kind == 'bin': continue area = location - while not area.location_name_format: - if not area.location_id: - return + while area and not area.location_name_format: area = area.location_id - location.name = area.location_name_format\ - .format(**location.read()) + 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. + location.name = template.format(**location._cache) - _sql_constraints = [ - ( - 'unique_location_name', - 'UNIQUE(name, location_id)', - _('The location name must be unique'), + @api.multi + @api.returns('self', lambda value: value.id) + def copy(self, default=None): + self.ensure_one() + default = dict(default or {}) + if 'name' not in default: + default['name'] = _("%s (copy)") % (self.name) + return super().copy(default=default) + + @api.model_cr + def init(self): + env = api.Environment(self._cr, SUPERUSER_ID, {}) + self._init_zone_index(env) + + def _init_zone_index(self, env): + """Add unique index on name per zone + + We cannot use _sql_constraints because it doesn't support + WHERE conditions. We need to apply the unique constraint + only within the same zone, otherwise the constraint fails + even on demo data (locations created automatically for + warehouses). + """ + index_name = 'stock_location_unique_name_zone_index' + create_unique_index_where( + env.cr, index_name, self._table, + ['name', 'picking_zone_id'], + 'picking_zone_id IS NOT NULL' ) - ] + @classmethod + def _init_constraints_onchanges(cls): + # As the unique index created in this model acts as a unique + # constraints but cannot be registered in '_sql_constraints' + # (it doesn't support WHERE clause), associate an error + # message manually (reproduce what _sql_constraints does). + key = 'unique_name_zone' + message = ('Another location with the same name exists in the same' + ' zone. Please rename the location.') + cls.pool._sql_error[cls._table + '_' + key] = message + super()._init_constraints_onchanges() diff --git a/stock_location_zone/models/stock_picking_zone.py b/stock_location_zone/models/stock_picking_zone.py index 2cee46aca..57d586c11 100644 --- a/stock_location_zone/models/stock_picking_zone.py +++ b/stock_location_zone/models/stock_picking_zone.py @@ -7,14 +7,15 @@ from odoo import fields, models class PickingZone(models.Model): _name = 'stock.picking.zone' + _description = "Stock Picking Zone" name = fields.Char('Name', required=True, translate=True) code = fields.Char('Code', required=True) - pick_type_id = fields.Many2one( + picking_type_id = fields.Many2one( 'stock.picking.type', string='Pick Type', help="Picking type for operations from this location", - ) + ) _sql_constraints = [ ( diff --git a/stock_location_zone/views/stock_picking_zone.xml b/stock_location_zone/views/stock_picking_zone.xml index 9c352b6a7..9ac330587 100644 --- a/stock_location_zone/views/stock_picking_zone.xml +++ b/stock_location_zone/views/stock_picking_zone.xml @@ -17,7 +17,7 @@ - +