From 68dfe9f653caf74722ec87d0abe8ca40b4f0cc52 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Mon, 16 Dec 2019 10:52:18 +0100 Subject: [PATCH] Migrate stock_location_tray to 13.0 --- stock_location_tray/README.rst | 21 +++++++--- stock_location_tray/__manifest__.py | 38 ++++++++----------- stock_location_tray/models/stock_location.py | 34 ++++++----------- .../models/stock_location_tray_type.py | 15 +++----- stock_location_tray/models/stock_move_line.py | 1 + .../static/description/index.html | 37 +++++++++++------- .../static/src/js/stock_location_tray.js | 2 +- stock_location_tray/tests/__init__.py | 1 - stock_location_tray/tests/common.py | 27 +++++-------- stock_location_tray/tests/test_location.py | 30 +++++---------- stock_location_tray/tests/test_tray_type.py | 20 ++++------ .../views/stock_location_tray_type_views.xml | 6 +-- .../views/stock_location_views.xml | 15 ++------ 13 files changed, 106 insertions(+), 141 deletions(-) diff --git a/stock_location_tray/README.rst b/stock_location_tray/README.rst index 6d7664f8c..d344b147b 100644 --- a/stock_location_tray/README.rst +++ b/stock_location_tray/README.rst @@ -14,13 +14,13 @@ Location Trays :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github - :target: https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_location_tray + :target: https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_location_tray :alt: OCA/stock-logistics-warehouse .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_location_tray + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_location_tray :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/153/12.0 + :target: https://runbot.odoo-community.org/runbot/153/13.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -30,7 +30,7 @@ A tray type defines a number of columns and rows. A location with a tray type becomes a tray, and sub-locations are automatically created according to the columns and rows of the tray type -.. figure:: https://raw.githubusercontent.com/OCA/stock-logistics-warehouse/12.0/stock_location_tray/static/description/location-tray.png +.. figure:: https://raw.githubusercontent.com/OCA/stock-logistics-warehouse/13.0/stock_location_tray/static/description/location-tray.png :alt: Location Tray :width: 600 px @@ -68,13 +68,22 @@ on the new tray type. The matrix widget on Tray locations can be clicked to reach a sub-location. Blue squares represent the locations that contain goods. +Known issues / Roadmap +====================== + +The buttons on operations opens a view with the tray matrix to show operators +where to pick/put goods. The issue is that Odoo allows only one modal popup +to be open at a time. The tray matrix replaces the operations window. We have +to find a way to prevent this. The tray matrix could be displayed through a +tooltip maybe, if we find how to render a widget in a tooltip. + Bug Tracker =========== Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -104,6 +113,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_location_tray/__manifest__.py b/stock_location_tray/__manifest__.py index 5dffe92b4..05fd877e6 100644 --- a/stock_location_tray/__manifest__.py +++ b/stock_location_tray/__manifest__.py @@ -1,27 +1,21 @@ # Copyright 2019 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'Location Trays', - 'summary': 'Organize a location as a matrix of cells', - 'version': '12.0.1.0.0', - 'category': 'Stock', - 'author': 'Camptocamp, Odoo Community Association (OCA)', - 'license': 'AGPL-3', - 'depends': [ - 'stock', - 'base_sparse_field', + "name": "Location Trays", + "summary": "Organize a location as a matrix of cells", + "version": "13.0.1.0.0", + "category": "Stock", + "author": "Camptocamp, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["stock", "base_sparse_field"], + "website": "https://github.com/OCA/stock-logistics-warehouse", + "demo": ["demo/stock_location_tray_type_demo.xml", "demo/stock_location_demo.xml"], + "data": [ + "views/stock_location_views.xml", + "views/stock_location_tray_type_views.xml", + "views/stock_location_tray_templates.xml", + "views/stock_move_line_views.xml", + "security/ir.model.access.csv", ], - 'website': 'https://github.com/OCA/stock-logistics-warehouse', - 'demo': [ - 'demo/stock_location_tray_type_demo.xml', - 'demo/stock_location_demo.xml', - ], - 'data': [ - 'views/stock_location_views.xml', - 'views/stock_location_tray_type_views.xml', - 'views/stock_location_tray_templates.xml', - 'views/stock_move_line_views.xml', - 'security/ir.model.access.csv', - ], - 'installable': True, + "installable": True, } diff --git a/stock_location_tray/models/stock_location.py b/stock_location_tray/models/stock_location.py index a7e3f1627..a365fb598 100644 --- a/stock_location_tray/models/stock_location.py +++ b/stock_location_tray/models/stock_location.py @@ -2,7 +2,9 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from collections import defaultdict + from odoo import _, api, exceptions, fields, models + from odoo.addons.base_sparse_field.models.fields import Serialized @@ -13,9 +15,7 @@ class StockLocation(models.Model): comodel_name="stock.location.tray.type", ondelete="restrict" ) cell_in_tray_type_id = fields.Many2one( - string="Cell Tray Type", - related="location_id.tray_type_id", - readonly=True, + string="Cell Tray Type", related="location_id.tray_type_id", readonly=True ) tray_cell_contains_stock = fields.Boolean( compute="_compute_tray_cell_contains_stock", @@ -30,7 +30,7 @@ class StockLocation(models.Model): " to inject positions. {x}, {y}, and {z} will be replaced by their" " corresponding position. Complex formatting (such as padding, ...)" " can be done using the format specification at " - " https://docs.python.org/2/library/string.html#formatstrings", + " https://docs.python.org/3/library/string.html#formatstrings", ) def _default_cell_name_format(self): @@ -40,14 +40,14 @@ class StockLocation(models.Model): def _compute_tray_cell_contains_stock(self): for location in self: if not location.cell_in_tray_type_id: - # we skip the others only for performance + # Not a tray cell so the value is irrelevant, + # best to skip them for performance. + location.tray_cell_contains_stock = False continue quants = location.quant_ids.filtered(lambda r: r.quantity > 0) location.tray_cell_contains_stock = bool(quants) - @api.depends( - "quant_ids.quantity", "tray_type_id", "location_id.tray_type_id" - ) + @api.depends("quant_ids.quantity", "tray_type_id", "location_id.tray_type_id") def _compute_tray_matrix(self): for location in self: if not (location.tray_type_id or location.cell_in_tray_type_id): @@ -65,7 +65,6 @@ class StockLocation(models.Model): "cells": cells, } - @api.multi def action_tray_matrix_click(self, coordX, coordY): self.ensure_one() if self.cell_in_tray_type_id: @@ -104,14 +103,10 @@ class StockLocation(models.Model): def _check_before_add_tray_type(self): if not self.tray_type_id and self.child_ids: raise exceptions.UserError( - _( - "Location %s has sub-locations, it cannot be converted" - " to a tray." - ) + _("Location %s has sub-locations, it cannot be converted" " to a tray.") % (self.display_name) ) - @api.multi def write(self, vals): for location in self: trays_to_update = False @@ -201,7 +196,6 @@ class StockLocation(models.Model): # using format_map allows to have missing replacement strings return template.format_map(defaultdict(str, x=x, y=y, z=z)) - @api.multi def _update_tray_sublocations(self): values = [] for location in self: @@ -213,10 +207,7 @@ class StockLocation(models.Model): # trap this check (_tray_check_active) to display a # contextual error message raise exceptions.UserError( - _( - "Trays cannot be modified when " - "they contain products." - ) + _("Trays cannot be modified when " "they contain products.") ) if not tray_type: @@ -226,9 +217,7 @@ class StockLocation(models.Model): posz = location.posz or 0 for row in range(1, tray_type.rows + 1): for col in range(1, tray_type.cols + 1): - cell_name = location._format_tray_sublocation_name( - col, row, posz - ) + cell_name = location._format_tray_sublocation_name(col, row, posz) subloc_values = { "name": cell_name, "posx": col, @@ -241,7 +230,6 @@ class StockLocation(models.Model): if values: self.create(values) - @api.multi def _create_tray_xmlids(self, module): """Create external IDs for generated cells diff --git a/stock_location_tray/models/stock_location_tray_type.py b/stock_location_tray/models/stock_location_tray_type.py index 57be763d3..49e77cc9f 100644 --- a/stock_location_tray/models/stock_location_tray_type.py +++ b/stock_location_tray/models/stock_location_tray_type.py @@ -3,6 +3,7 @@ from odoo import _, api, exceptions, fields, models from odoo.osv import expression + from odoo.addons.base_sparse_field.models.fields import Serialized @@ -19,8 +20,8 @@ class StockLocationTrayType(models.Model): depth = fields.Integer(help="Depth of the tray in mm") height = fields.Integer(help="Height of the tray in mm") - width_per_cell = fields.Float(compute='_compute_width_per_cell') - depth_per_cell = fields.Float(compute='_compute_depth_per_cell') + width_per_cell = fields.Float(compute="_compute_width_per_cell") + depth_per_cell = fields.Float(compute="_compute_depth_per_cell") active = fields.Boolean(default=True) tray_matrix = Serialized(compute="_compute_tray_matrix") @@ -33,7 +34,7 @@ class StockLocationTrayType(models.Model): for record in self: width = record.width if not width: - record.width_per_cell = 0. + record.width_per_cell = 0.0 continue record.width_per_cell = width / record.cols @@ -42,7 +43,7 @@ class StockLocationTrayType(models.Model): for record in self: depth = record.depth if not depth: - record.depth_per_cell = 0. + record.depth_per_cell = 0.0 continue record.depth_per_cell = depth / record.rows @@ -56,7 +57,6 @@ class StockLocationTrayType(models.Model): cells = self._generate_cells_matrix(default_state=1) record.tray_matrix = {"selected": [], "cells": cells} - @api.model def _name_search( self, name, args=None, operator="ilike", limit=100, name_get_uid=None ): @@ -65,9 +65,7 @@ class StockLocationTrayType(models.Model): if name: domain = ["|", ("name", operator, name), ("code", operator, name)] tray_ids = self._search( - expression.AND([domain, args]), - limit=limit, - access_rights_uid=name_get_uid, + expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid ) return self.browse(tray_ids).name_get() @@ -106,7 +104,6 @@ class StockLocationTrayType(models.Model): ).format(record.name, "\n".join(location_bullets)) ) - @api.multi def open_locations(self): action = self.env.ref("stock.action_location_form").read()[0] action["domain"] = [("tray_type_id", "in", self.ids)] diff --git a/stock_location_tray/models/stock_move_line.py b/stock_location_tray/models/stock_move_line.py index 10209517a..ab3984f57 100644 --- a/stock_location_tray/models/stock_move_line.py +++ b/stock_location_tray/models/stock_move_line.py @@ -2,6 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, models + from odoo.addons.base_sparse_field.models.fields import Serialized diff --git a/stock_location_tray/static/description/index.html b/stock_location_tray/static/description/index.html index 681833883..14023fe65 100644 --- a/stock_location_tray/static/description/index.html +++ b/stock_location_tray/static/description/index.html @@ -367,13 +367,13 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

Add an optional Tray Type on Stock Locations. A tray type defines a number of columns and rows. A location with a tray type becomes a tray, and sub-locations are automatically created according to the columns and rows of the tray type

-Location Tray +Location Tray

Table of contents

@@ -384,11 +384,12 @@ created according to the columns and rows of the tray type

  • Locations
  • -
  • Bug Tracker
  • -
  • Credits @@ -420,36 +421,44 @@ on the new tray type.

    Blue squares represent the locations that contain goods.

  • +
    +

    Known issues / Roadmap

    +

    The buttons on operations opens a view with the tray matrix to show operators +where to pick/put goods. The issue is that Odoo allows only one modal popup +to be open at a time. The tray matrix replaces the operations window. We have +to find a way to prevent this. The tray matrix could be displayed through a +tooltip maybe, if we find how to render a widget in a tooltip.

    +
    -

    Bug Tracker

    +

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • Camptocamp
    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    -

    This module is part of the OCA/stock-logistics-warehouse project on GitHub.

    +

    This module is part of the OCA/stock-logistics-warehouse project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    diff --git a/stock_location_tray/static/src/js/stock_location_tray.js b/stock_location_tray/static/src/js/stock_location_tray.js index a4ba05959..6921184a7 100644 --- a/stock_location_tray/static/src/js/stock_location_tray.js +++ b/stock_location_tray/static/src/js/stock_location_tray.js @@ -172,7 +172,7 @@ var LocationTrayMatrixField = DebouncedField.extend({ * */ _renderInDOM: function () { - this.canvas = this.$el.find('canvas').context; + this.canvas = this.$el[0]; var canvas = this.canvas; var ctx = canvas.getContext('2d'); this.resizeCanvasToDisplaySize(ctx.canvas); diff --git a/stock_location_tray/tests/__init__.py b/stock_location_tray/tests/__init__.py index ec80502cd..3f56218d4 100644 --- a/stock_location_tray/tests/__init__.py +++ b/stock_location_tray/tests/__init__.py @@ -1,3 +1,2 @@ from . import test_location from . import test_tray_type - diff --git a/stock_location_tray/tests/common.py b/stock_location_tray/tests/common.py index f2b13bc2b..88f7f432a 100644 --- a/stock_location_tray/tests/common.py +++ b/stock_location_tray/tests/common.py @@ -8,32 +8,25 @@ class LocationTrayTypeCase(common.SavepointCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.stock_location = cls.env.ref('stock.stock_location_stock') - cls.product = cls.env.ref( - 'product.product_delivery_02' - ) - cls.tray_location = cls.env.ref( - "stock_location_tray.stock_location_tray_demo" - ) + cls.wh = cls.env.ref("stock.warehouse0") + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.product = cls.env.ref("product.product_delivery_02") + cls.tray_location = cls.env.ref("stock_location_tray.stock_location_tray_demo") cls.tray_type_small_8x = cls.env.ref( - 'stock_location_tray.stock_location_tray_type_small_8x' + "stock_location_tray.stock_location_tray_type_small_8x" ) cls.tray_type_small_32x = cls.env.ref( - 'stock_location_tray.stock_location_tray_type_small_32x' + "stock_location_tray.stock_location_tray_type_small_32x" ) def _cell_for(self, tray, x=1, y=1): - cell = self.env['stock.location'].search( - [('location_id', '=', tray.id), ('posx', '=', x), ('posy', '=', y)] + cell = self.env["stock.location"].search( + [("location_id", "=", tray.id), ("posx", "=", x), ("posy", "=", y)] ) self.assertEqual( - len(cell), - 1, - "Cell x{}y{} not found for {}".format(x, y, tray.name), + len(cell), 1, "Cell x{}y{} not found for {}".format(x, y, tray.name) ) return cell def _update_quantity_in_cell(self, cell, product, quantity): - self.env['stock.quant']._update_available_quantity( - product, cell, quantity - ) + self.env["stock.quant"]._update_available_quantity(product, cell, quantity) diff --git a/stock_location_tray/tests/test_location.py b/stock_location_tray/tests/test_location.py index 1f0981255..d25fde098 100644 --- a/stock_location_tray/tests/test_location.py +++ b/stock_location_tray/tests/test_location.py @@ -18,9 +18,7 @@ class TestLocation(LocationTrayTypeCase): } ) - self.assertEqual( - len(tray_loc.child_ids), tray_type.cols * tray_type.rows # 8 - ) + self.assertEqual(len(tray_loc.child_ids), tray_type.cols * tray_type.rows) # 8 self.assertTrue( all( subloc.cell_in_tray_type_id == tray_type @@ -29,9 +27,7 @@ class TestLocation(LocationTrayTypeCase): ) def test_tray_has_stock(self): - cell = self.env.ref( - "stock_location_tray.stock_location_tray_demo_x3y2" - ) + cell = self.env.ref("stock_location_tray.stock_location_tray_demo_x3y2") self.assertFalse(cell.quant_ids) self.assertFalse(cell.tray_cell_contains_stock) self._update_quantity_in_cell(cell, self.product, 1) @@ -127,17 +123,13 @@ class TestLocation(LocationTrayTypeCase): ) def test_check_active_empty(self): - cell = self.env.ref( - "stock_location_tray.stock_location_tray_demo_x3y2" - ) + cell = self.env.ref("stock_location_tray.stock_location_tray_demo_x3y2") self.assertFalse(cell.tray_cell_contains_stock) # allowed to archive empty cell cell.active = False def test_check_active_not_empty(self): - cell = self.env.ref( - "stock_location_tray.stock_location_tray_demo_x3y2" - ) + cell = self.env.ref("stock_location_tray.stock_location_tray_demo_x3y2") self._update_quantity_in_cell(cell, self.product, 1) self.assertTrue(cell.tray_cell_contains_stock) @@ -151,13 +143,15 @@ class TestLocation(LocationTrayTypeCase): # restore state for the next test loop location.active = True location = location.location_id + if location == self.wh.lot_stock_id: + # we can't disable the Stock location anyway + break def test_change_tray_type_when_empty(self): tray_type = self.tray_type_small_32x self.tray_location.tray_type_id = tray_type self.assertEqual( - len(self.tray_location.child_ids), - tray_type.cols * tray_type.rows, # 32 + len(self.tray_location.child_ids), tray_type.cols * tray_type.rows # 32 ) def test_change_tray_type_error_when_not_empty(self): @@ -170,15 +164,11 @@ class TestLocation(LocationTrayTypeCase): self.tray_location.tray_type_id = tray_type def test_location_center_pos(self): - cell = self.env.ref( - "stock_location_tray.stock_location_tray_demo_x3y2" - ) + cell = self.env.ref("stock_location_tray.stock_location_tray_demo_x3y2") tray_type = cell.cell_in_tray_type_id number_of_x = 4 number_of_y = 2 - self.assertEqual( - (number_of_x, number_of_y), (tray_type.cols, tray_type.rows) - ) + self.assertEqual((number_of_x, number_of_y), (tray_type.cols, tray_type.rows)) total_width = 80 total_depth = 30 diff --git a/stock_location_tray/tests/test_tray_type.py b/stock_location_tray/tests/test_tray_type.py index bb9a8741f..d75013840 100644 --- a/stock_location_tray/tests/test_tray_type.py +++ b/stock_location_tray/tests/test_tray_type.py @@ -11,27 +11,21 @@ class TestLocationTrayType(LocationTrayTypeCase): def setUpClass(cls): super().setUpClass() cls.used_tray_type = cls.env.ref( - 'stock_location_tray.stock_location_tray_type_large_16x' + "stock_location_tray.stock_location_tray_type_large_16x" ) cls.unused_tray_type = cls.env.ref( - 'stock_location_tray.stock_location_tray_type_small_16x_3' + "stock_location_tray.stock_location_tray_type_small_16x_3" ) def test_tray_type(self): # any location created directly under the view is a shuttle - tray_type = self.env['stock.location.tray.type'].create( - { - 'name': 'Test Type', - 'code': '🐵', - 'usage': 'internal', - 'rows': 4, - 'cols': 6, - } + tray_type = self.env["stock.location.tray.type"].create( + {"name": "Test Type", "code": "🐵", "rows": 4, "cols": 6} ) self.assertEqual( tray_type.tray_matrix, { - 'selected': [], # no selection as this is the "model" + "selected": [], # no selection as this is the "model" # a "full" matrix is generated for display on the UI # fmt: off 'cells': [ @@ -49,7 +43,7 @@ class TestLocationTrayType(LocationTrayTypeCase): location.tray_type_id = self.used_tray_type location = self.used_tray_type.location_ids self.assertTrue(location) - message = 'cannot be archived.*{}.*'.format(location.name) + message = "cannot be archived.*{}.*".format(location.name) # we cannot archive used ones with self.assertRaisesRegex(exceptions.ValidationError, message): self.used_tray_type.active = False @@ -61,7 +55,7 @@ class TestLocationTrayType(LocationTrayTypeCase): location.tray_type_id = self.used_tray_type location = self.used_tray_type.location_ids self.assertTrue(location) - message = 'size cannot be changed.*{}.*'.format(location.name) + message = "size cannot be changed.*{}.*".format(location.name) # we cannot modify size of used ones with self.assertRaisesRegex(exceptions.ValidationError, message): self.used_tray_type.rows = 10 diff --git a/stock_location_tray/views/stock_location_tray_type_views.xml b/stock_location_tray/views/stock_location_tray_type_views.xml index a71c58c7a..15281b785 100644 --- a/stock_location_tray/views/stock_location_tray_type_views.xml +++ b/stock_location_tray/views/stock_location_tray_type_views.xml @@ -12,14 +12,13 @@ icon="fa-filter" name="open_locations" type="object" /> - +