From a615a7a265fd0b40f388a0b3fd474605ea337ebc Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Wed, 11 Sep 2019 12:04:32 +0200 Subject: [PATCH] Rework stock_location_zone --- stock_location_zone/__manifest__.py | 5 +- stock_location_zone/models/__init__.py | 1 - stock_location_zone/models/stock_location.py | 192 +++++++----------- .../models/stock_picking_zone.py | 26 --- stock_location_zone/readme/CONFIGURE.rst | 5 - stock_location_zone/readme/CONTRIBUTORS.rst | 1 + stock_location_zone/readme/DESCRIPTION.rst | 12 +- .../security/ir.model.access.csv | 3 - stock_location_zone/views/stock_location.xml | 35 ++-- .../views/stock_picking_zone.xml | 41 ---- 10 files changed, 98 insertions(+), 223 deletions(-) delete mode 100644 stock_location_zone/models/stock_picking_zone.py delete mode 100644 stock_location_zone/readme/CONFIGURE.rst delete mode 100644 stock_location_zone/security/ir.model.access.csv delete mode 100644 stock_location_zone/views/stock_picking_zone.xml diff --git a/stock_location_zone/__manifest__.py b/stock_location_zone/__manifest__.py index 3ed81d847..c1249a352 100644 --- a/stock_location_zone/__manifest__.py +++ b/stock_location_zone/__manifest__.py @@ -7,16 +7,13 @@ 'version': '12.0.1.0.0', '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.", + 'summary': "Classify locations with zones.", 'category': 'Stock Management', 'depends': [ 'stock', ], 'data': [ - 'views/stock_picking_zone.xml', 'views/stock_location.xml', - 'security/ir.model.access.csv', ], 'installable': True, 'development_status': 'Alpha', diff --git a/stock_location_zone/models/__init__.py b/stock_location_zone/models/__init__.py index 408b07ec6..88493e35d 100644 --- a/stock_location_zone/models/__init__.py +++ b/stock_location_zone/models/__init__.py @@ -1,2 +1 @@ -from . import stock_picking_zone from . import stock_location diff --git a/stock_location_zone/models/stock_location.py b/stock_location_zone/models/stock_location.py index d1bee86ce..b9c20857d 100644 --- a/stock_location_zone/models/stock_location.py +++ b/stock_location_zone/models/stock_location.py @@ -3,103 +3,92 @@ # Copyright 2019 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from psycopg2 import sql - -from odoo import _, api, 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 - ) +from odoo import api, fields, models, _ class StockLocation(models.Model): _inherit = 'stock.location' - # FIXME: add in selection: shuttle, tray (module vertical lift) - kind = fields.Selection([ - ('zone', 'Picking Zone'), - ('area', 'Area'), - ('bin', 'Bin')], - string='Kind') + is_zone = fields.Boolean( + string='Is a Zone Location?', + help='Mark to define this location as a zone', + ) - picking_zone_id = fields.Many2one( - 'stock.picking.zone', - string='Picking zone', + zone_location_id = fields.Many2one( + 'stock.location', + string='Location zone', + compute='_compute_zone_location_id', + store=True, index=True, ) - picking_type_id = fields.Many2one( - related='picking_zone_id.picking_type_id', - help="Picking type for operations from this location", - oldname='barcode_picking_type_id') + location_kind = fields.Selection( + [ + ('zone', 'Zone'), + ('area', 'Area'), + ('bin', 'Bin'), + ('stock', 'Main Stock'), + ('other', 'Other'), + ], + string='Location Kind', + compute='_compute_location_kind', + help='Group location according to their kinds:' + '* Zone: locations that are flagged as being zones' + '* Area: locations with children that are part of a zone' + '* Bin: locations without children that are part of a zone' + '* Stock: internal locations whose parent is a view' + '* Other: any other location', + ) - area = fields.Char( - 'Area', - compute='_compute_area', store=True, - oldname='zone') + _sql_constraints = [( + 'name_zone_unique', + 'EXCLUDE (name WITH =, zone_location_id WITH =)' + ' WHERE (zone_location_id IS NOT NULL)', + 'Another location with the same name exists in the same zone.' + ' Please rename the location.' + )] - @api.depends('name', 'kind', 'location_id.area') - def _compute_area(self): + @api.depends('is_zone', 'usage', 'location_id.usage', 'zone_location_id', + 'child_ids') + def _compute_location_kind(self): for location in self: - if location.kind == 'area': - location.area = location.name + if location.is_zone: + location.location_kind = 'zone' + continue + # Internal locations whose parent is view are main stocks + if ( + location.usage == 'internal' + and location.location_id.usage == 'view' + ): + location.location_kind = 'stock' + continue + # Internal locations having a zone and no children are bins + if ( + location.usage == 'internal' + and location.zone_location_id + and not location.child_ids + ): + location.location_kind = 'bin' + continue + # Internal locations having a zone and children are areas + if ( + location.usage == 'internal' + and location.zone_location_id + and location.child_ids + ): + location.location_kind = 'area' + continue + # All the rest are other locations + location.location_kind = 'other' + + @api.depends('is_zone', 'location_id.zone_location_id') + def _compute_zone_location_id(self): + for location in self: + if location.is_zone: + location.zone_location_id = location else: - location.area = location.location_id.area - - corridor = fields.Char('Corridor', help="Street") - row = fields.Char('Row', help="Side in the street") - rack = fields.Char('Rack', oldname='shelf', help="House number") - level = fields.Char('Level', help="Height on the shelf") - posx = fields.Integer('Box (X)') - posy = fields.Integer('Box (Y)') - posz = fields.Integer('Box (Z)') - - 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}'") - - @api.multi - @api.onchange('corridor', 'row', 'rack', 'level', - 'posx', 'posy', 'posz') - def _compute_name(self): - for location in self: - if not 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. - location.name = template.format(**location._cache) + location.zone_location_id = \ + location.location_id.zone_location_id @api.multi @api.returns('self', lambda value: value.id) @@ -107,38 +96,5 @@ class StockLocation(models.Model): self.ensure_one() default = dict(default or {}) if 'name' not in default: - default['name'] = _("%s (copy)") % (self.name) + 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 deleted file mode 100644 index 57d586c11..000000000 --- a/stock_location_zone/models/stock_picking_zone.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2017 Syvain Van Hoof (Okia sprl) -# Copyright 2017-2019 Jacques-Etienne Baudoux (BCIM sprl) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -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) - picking_type_id = fields.Many2one( - 'stock.picking.type', - string='Pick Type', - help="Picking type for operations from this location", - ) - - _sql_constraints = [ - ( - 'unique_picking_zone', - 'unique (code)', - 'The picking zone code must be unique', - ) - ] diff --git a/stock_location_zone/readme/CONFIGURE.rst b/stock_location_zone/readme/CONFIGURE.rst deleted file mode 100644 index 1d20f0c1c..000000000 --- a/stock_location_zone/readme/CONFIGURE.rst +++ /dev/null @@ -1,5 +0,0 @@ -In Inventory Settings, you must have: - - * Storage Locations - -Set coordinate attibute on the locations. diff --git a/stock_location_zone/readme/CONTRIBUTORS.rst b/stock_location_zone/readme/CONTRIBUTORS.rst index 8ef4d90eb..0425dda61 100644 --- a/stock_location_zone/readme/CONTRIBUTORS.rst +++ b/stock_location_zone/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * Syvain Van Hoof (Okia sprl) * Jacques-Etienne Baudoux (BCIM) * Guewen Baconnier (Camptocamp) +* Akim Juillerat diff --git a/stock_location_zone/readme/DESCRIPTION.rst b/stock_location_zone/readme/DESCRIPTION.rst index ba44b8538..02fe9ddb4 100644 --- a/stock_location_zone/readme/DESCRIPTION.rst +++ b/stock_location_zone/readme/DESCRIPTION.rst @@ -1,2 +1,10 @@ -Add coordinate attributes on stock location. -Define picking zone with links to picking type. +This module introduces Zone concept on stock locations to allow better +classification of stock locations in a warehouse. + +Locations are then classified by location kinds that could be: + +* Zone: locations that are flagged as being zones +* Area: locations with children that are part of a zone +* Bin: locations without children that are part of a zone +* Stock: internal locations whose parent is a view +* Other: any other location diff --git a/stock_location_zone/security/ir.model.access.csv b/stock_location_zone/security/ir.model.access.csv deleted file mode 100644 index af4479339..000000000 --- a/stock_location_zone/security/ir.model.access.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_picking_zone,access_picking_zone,model_stock_picking_zone,base.group_user,1,0,0,0 -access_picking_zone_manager,access_picking_zone_manager,model_stock_picking_zone,base.group_system,1,1,1,1 diff --git a/stock_location_zone/views/stock_location.xml b/stock_location_zone/views/stock_location.xml index aa2fdd5b2..a5911aa2d 100644 --- a/stock_location_zone/views/stock_location.xml +++ b/stock_location_zone/views/stock_location.xml @@ -6,22 +6,13 @@ stock.location - + + + - - - + + - - - - - - - - - - @@ -30,17 +21,15 @@ stock.location - - - - - - - - + + + + + + + - diff --git a/stock_location_zone/views/stock_picking_zone.xml b/stock_location_zone/views/stock_picking_zone.xml deleted file mode 100644 index 9ac330587..000000000 --- a/stock_location_zone/views/stock_picking_zone.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - stock.picking.zone.view.filter - stock.picking.zone - - - - - - - - - stock.picking.zone.view.tree - stock.picking.zone - - - - - - - - - - - Picking Zones - stock.picking.zone - ir.actions.act_window - form - -

- Define the picking zones of your warehouses -

-
-
- - -