diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4c9a4d318..a35bde3036 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,6 @@ exclude: | (?x) # NOT INSTALLABLE ADDONS - ^stock_release_channel/| # END NOT INSTALLABLE ADDONS # Files and folders generated by bots, to avoid loops ^setup/|/static/description/index\.html$| diff --git a/setup/stock_release_channel/odoo/addons/stock_release_channel b/setup/stock_release_channel/odoo/addons/stock_release_channel new file mode 120000 index 0000000000..affde1dccc --- /dev/null +++ b/setup/stock_release_channel/odoo/addons/stock_release_channel @@ -0,0 +1 @@ +../../../../stock_release_channel \ No newline at end of file diff --git a/setup/stock_release_channel/setup.py b/setup/stock_release_channel/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/stock_release_channel/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_release_channel/README.rst b/stock_release_channel/README.rst index 9fe61557a5..84b6c6a511 100644 --- a/stock_release_channel/README.rst +++ b/stock_release_channel/README.rst @@ -14,13 +14,13 @@ Stock Release Channels :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwms-lightgray.png?logo=github - :target: https://github.com/OCA/wms/tree/14.0/stock_release_channel + :target: https://github.com/OCA/wms/tree/16.0/stock_release_channel :alt: OCA/wms .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/wms-14-0/wms-14-0-stock_release_channel + :target: https://translation.odoo-community.org/projects/wms-16-0/wms-16-0-stock_release_channel :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/285/14.0 + :target: https://runbot.odoo-community.org/runbot/285/16.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -70,7 +70,7 @@ 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. @@ -88,6 +88,7 @@ Contributors * Guewen Baconnier * Matthieu Méquignon * Sébastien Alix +* Jacques-Etienne Baudoux Design ~~~~~~ @@ -124,6 +125,6 @@ Current `maintainer `__: |maintainer-sebalix| -This module is part of the `OCA/wms `_ project on GitHub. +This module is part of the `OCA/wms `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_release_channel/__manifest__.py b/stock_release_channel/__manifest__.py index 629980edf7..ae69059f4e 100644 --- a/stock_release_channel/__manifest__.py +++ b/stock_release_channel/__manifest__.py @@ -4,19 +4,18 @@ { "name": "Stock Release Channels", "summary": "Manage workload in WMS with release channels", - "version": "14.0.1.0.0", + "version": "16.0.1.0.0", "development_status": "Beta", "license": "AGPL-3", "author": "Camptocamp, Odoo Community Association (OCA)", "maintainers": ["sebalix"], "website": "https://github.com/OCA/wms", "depends": [ - "sale_stock", + "web", "stock_available_to_promise_release", # OCA/wms "queue_job", # OCA/queue ], "data": [ - "views/assets.xml", "views/stock_release_channel_views.xml", "views/stock_picking_views.xml", "data/stock_release_channel_data.xml", @@ -24,5 +23,11 @@ "data/ir_cron_data.xml", "security/stock_release_channel.xml", ], - "installable": False, + "assets": { + "web.assets_backend": [ + "stock_release_channel/static/src/scss/stock_release_channel.scss", + "stock_release_channel/static/src/js/progressbar_fractional_widget.js", + ], + }, + "installable": True, } diff --git a/stock_release_channel/models/__init__.py b/stock_release_channel/models/__init__.py index 0c03017164..66e7660731 100644 --- a/stock_release_channel/models/__init__.py +++ b/stock_release_channel/models/__init__.py @@ -1,4 +1,3 @@ -from . import sale_order_line from . import stock_move from . import stock_picking from . import stock_release_channel diff --git a/stock_release_channel/models/sale_order_line.py b/stock_release_channel/models/sale_order_line.py deleted file mode 100644 index 876f202a6c..0000000000 --- a/stock_release_channel/models/sale_order_line.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2020 Camptocamp -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -from odoo import models - - -class SaleOrderLine(models.Model): - _inherit = "sale.order.line" - - def _action_launch_stock_rule(self, previous_product_uom_qty=False): - # As the user who confirms the order might not have enough access rights to process - # the order (using orderpoints, assign channels, etc...) we use sudo here - self = self.sudo() - result = super()._action_launch_stock_rule( - previous_product_uom_qty=previous_product_uom_qty - ) - pickings = self.move_ids.picking_id - # ensure we assign a channel on any picking OUT generated for the sale, - # if moves are assigned to an existing transfer, we recompute the - # channel - pickings._delay_assign_release_channel() - return result diff --git a/stock_release_channel/models/stock_move.py b/stock_release_channel/models/stock_move.py index c701484ecc..e653533211 100644 --- a/stock_release_channel/models/stock_move.py +++ b/stock_release_channel/models/stock_move.py @@ -1,4 +1,5 @@ # Copyright 2020 Camptocamp +# Copyright 2022 Jacques-Etienne Baudoux (BCIM) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) from odoo import models @@ -11,5 +12,13 @@ def release_available_to_promise(self): # after releasing, we re-assign a release channel, # as we may release only partially, the channel may # change - super().release_available_to_promise() + res = super().release_available_to_promise() self.picking_id.assign_release_channel() + return res + + def _action_confirm(self, merge=True, merge_into=False): + moves = super()._action_confirm(merge=merge, merge_into=merge_into) + pickings = moves.filtered("need_release").picking_id + if pickings: + pickings._delay_assign_release_channel() + return moves diff --git a/stock_release_channel/models/stock_release_channel.py b/stock_release_channel/models/stock_release_channel.py index 07442365ba..8832941ad7 100644 --- a/stock_release_channel/models/stock_release_channel.py +++ b/stock_release_channel/models/stock_release_channel.py @@ -36,6 +36,22 @@ class StockReleaseChannel(models.Model): release_forbidden = fields.Boolean(string="Forbid to release this channel") sequence = fields.Integer(default=lambda self: self._default_sequence()) color = fields.Integer() + warehouse_id = fields.Many2one( + "stock.warehouse", + string="Warehouse", + index=True, + help="Warehouse for which this channel is relevant", + ) + picking_type_ids = fields.Many2many( + "stock.picking.type", + "stock_release_channel_warehouse_rel", + "channel_id", + "picking_type_id", + string="Operation Types", + domain="warehouse_id" + " and [('warehouse_id', '=', warehouse_id), ('code', '=', 'outgoing')]" + " or [('code', '=', 'outgoing')]", + ) rule_domain = fields.Char( string="Domain", default=[], @@ -289,8 +305,10 @@ def _query_get_chain(self, pickings): return (query, (tuple(pickings.ids),)) def _compute_picking_chain(self): - self.env["stock.move"].flush(["move_dest_ids", "move_orig_ids", "picking_id"]) - self.env["stock.picking"].flush(["state"]) + self.env["stock.move"].flush_model( + ["move_dest_ids", "move_orig_ids", "picking_id"] + ) + self.env["stock.picking"].flush_model(["state"]) for channel in self: domain = self._field_picking_domains()["count_picking_released"] domain += [("release_channel_id", "=", channel.id)] @@ -363,13 +381,17 @@ def assign_release_channel(self, pickings): return # do a single query rather than one for each rule*picking for channel in self.sudo().search([]): - domain = channel._prepare_domain() - - if domain: - current = pickings.filtered_domain(domain) + if channel.picking_type_ids: + current = pickings.filtered( + lambda p: p.picking_type_id in channel.picking_type_ids + ) else: current = pickings + domain = channel._prepare_domain() + if domain: + current = current.filtered_domain(domain) + if not current: continue @@ -378,7 +400,7 @@ def assign_release_channel(self, pickings): if not current: continue - + current = channel._assign_release_channel_additional_filter(current) current.release_channel_id = channel pickings -= current @@ -394,6 +416,10 @@ def assign_release_channel(self, pickings): ) return True + def _assign_release_channel_additional_filter(self, pickings): + self.ensure_one() + return pickings + def _eval_context(self, pickings): """Prepare the context used when for the python rule evaluation @@ -421,9 +447,12 @@ def _eval_code(self, pickings): safe_eval(expr, eval_context, mode="exec", nocopy=True) except Exception as err: raise exceptions.UserError( - _("Error when evaluating the channel's code:\n %s \n(%s)") - % (self.name, err) - ) + _( + "Error when evaluating the channel's code:\n %(name)s \n(%(error)s)", + name=self.name, + error=err, + ) + ) from err # normally "pickings" is always set as we set it in the eval context, # but let assume the worst case with someone using "del pickings" return eval_context.get("pickings", self.env["stock.picking"].browse()) @@ -537,7 +566,7 @@ def get_action_picking_form(self): action["context"] = {} if not self.last_done_picking_id: raise exceptions.UserError( - _("Channel %s has no validated transfer yet.") % (self.name,) + _("Channel %(name)s has no validated transfer yet.", name=self.name) ) action["res_id"] = self.last_done_picking_id.id return action diff --git a/stock_release_channel/readme/CONTRIBUTORS.rst b/stock_release_channel/readme/CONTRIBUTORS.rst index 9e4b7298a7..3e31e70c52 100644 --- a/stock_release_channel/readme/CONTRIBUTORS.rst +++ b/stock_release_channel/readme/CONTRIBUTORS.rst @@ -1,6 +1,7 @@ * Guewen Baconnier * Matthieu Méquignon * Sébastien Alix +* Jacques-Etienne Baudoux Design ~~~~~~ diff --git a/stock_release_channel/static/description/index.html b/stock_release_channel/static/description/index.html index 7fdef34593..dc15ae41d9 100644 --- a/stock_release_channel/static/description/index.html +++ b/stock_release_channel/static/description/index.html @@ -3,7 +3,7 @@ - + Stock Release Channels