-
-
Notifications
You must be signed in to change notification settings - Fork 19
[MIG][18.0] stock_available_to_promise_release_carrier_alternative (was delivery_carrier_preference) #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
OCA-git-bot
merged 9 commits into
OCA:18.0
from
camptocamp:18.0-stock_available_to_promise_release_carrier_alternative
Oct 30, 2025
Merged
[MIG][18.0] stock_available_to_promise_release_carrier_alternative (was delivery_carrier_preference) #17
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9265cf8
[ADD] stock_available_to_promise_release_carrier_alternative
grindtildeath 9b0a855
[FIX] stock_available_to_promise_release_carrier_alternative: procure…
mmequignon bd515c3
[FIX] stock_available_to_promise_release_carrier_alternative: dependency
jbaudoux dba9a52
[IMP] stock_available_to_promise_release_carrier_alternative: backord…
jbaudoux 724d3e8
[IMP] stock_available_to_promise_release_carrier_alternative: carrier…
jbaudoux 6df6e94
[IMP] stock_available_to_promise_release_carrier_alternative: date & set
jbaudoux c62646e
[FIX] stock_available_to_promise_release_carrier_alternative: re-release
TDu 6c65997
stock_available_to_promise_release_carrier_alternative: domain
jbaudoux 433e0b5
stock_available_to_promise_release_carrier_alternative: fix tests
jbaudoux File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
stock_available_to_promise_release_carrier_alternative/README.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| ======================================================== | ||
| Stock Available to Promise Release - Carrier Alternative | ||
| ======================================================== | ||
|
|
||
| .. | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! This file is generated by oca-gen-addon-readme !! | ||
| !! changes will be overwritten. !! | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! source digest: sha256:0360a786d5b6302d09d1f60fa6f6ab6aee9b16dcc0148712292e165492828868 | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
|
||
| .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
| :target: https://odoo-community.org/page/development-status | ||
| :alt: Beta | ||
| .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png | ||
| :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--reservation-lightgray.png?logo=github | ||
| :target: https://github.com/OCA/stock-logistics-reservation/tree/18.0/stock_available_to_promise_release_carrier_alternative | ||
| :alt: OCA/stock-logistics-reservation | ||
| .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
| :target: https://translation.odoo-community.org/projects/stock-logistics-reservation-18-0/stock-logistics-reservation-18-0-stock_available_to_promise_release_carrier_alternative | ||
| :alt: Translate me on Weblate | ||
| .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png | ||
| :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-reservation&target_branch=18.0 | ||
| :alt: Try me on Runboat | ||
|
|
||
| |badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
|
||
| This module allows to define preferred shipping methods in order to fine | ||
| tune the selection of proper delivery carrier from delivery operations | ||
| according to the quantity available to promise. | ||
|
|
||
| Moreover it provides the possibility to force the recomputation of | ||
| preferred delivery carrier on the release of operations for Delivery | ||
| Orders. | ||
|
|
||
| **Table of contents** | ||
|
|
||
| .. contents:: | ||
| :local: | ||
|
|
||
| Configuration | ||
| ============= | ||
|
|
||
| Go to any delivery method in order to define its alternative delivery | ||
| methods. | ||
|
|
||
| At release, a new carrier might be selected among alternative carriers. | ||
| This has to comply with a few rules, such as carrier max weight and | ||
| volume. You also can add extra rules by editing a delivery method's | ||
| Picking Domain. | ||
|
|
||
| Bug Tracker | ||
| =========== | ||
|
|
||
| Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-reservation/issues>`_. | ||
| In case of trouble, please check there if your issue has already been reported. | ||
| If you spotted it first, help us to smash it by providing a detailed and welcomed | ||
| `feedback <https://github.com/OCA/stock-logistics-reservation/issues/new?body=module:%20stock_available_to_promise_release_carrier_alternative%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
|
||
| Do not contact contributors directly about support or help with technical issues. | ||
|
|
||
| Credits | ||
| ======= | ||
|
|
||
| Authors | ||
| ------- | ||
|
|
||
| * Camptocamp | ||
| * BCIM | ||
|
|
||
| Contributors | ||
| ------------ | ||
|
|
||
| - Jacques-Etienne Baudoux <je@bcim.be> | ||
| - Matthieu Méquignon <matthieu.mequignon@camptocamp.com> | ||
|
|
||
| Maintainers | ||
| ----------- | ||
|
|
||
| This module is maintained by the OCA. | ||
|
|
||
| .. image:: https://odoo-community.org/logo.png | ||
| :alt: Odoo Community Association | ||
| :target: https://odoo-community.org | ||
|
|
||
| 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-reservation <https://github.com/OCA/stock-logistics-reservation/tree/18.0/stock_available_to_promise_release_carrier_alternative>`_ project on GitHub. | ||
|
|
||
| You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
1 change: 1 addition & 0 deletions
1
stock_available_to_promise_release_carrier_alternative/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import models |
21 changes: 21 additions & 0 deletions
21
stock_available_to_promise_release_carrier_alternative/__manifest__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Copyright 2020 Camptocamp SA | ||
| # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
| { | ||
| "name": "Stock Available to Promise Release - Carrier Alternative", | ||
| "summary": "Advanced selection of preferred shipping methods", | ||
| "version": "18.0.1.0.0", | ||
| "category": "Operations/Inventory/Delivery", | ||
| "website": "https://github.com/OCA/stock-logistics-reservation", | ||
| "author": "Camptocamp, BCIM, Odoo Community Association (OCA)", | ||
| "license": "AGPL-3", | ||
| "application": False, | ||
| "installable": True, | ||
| "depends": [ | ||
| "delivery_carrier_picking_valid", | ||
| "stock_available_to_promise_release", | ||
| "delivery_procurement_group_carrier", | ||
| ], | ||
| "data": [ | ||
| "views/delivery_carrier.xml", | ||
| ], | ||
| } |
4 changes: 4 additions & 0 deletions
4
stock_available_to_promise_release_carrier_alternative/models/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| from . import procurement_group | ||
| from . import stock_move | ||
| from . import stock_picking | ||
| from . import delivery_carrier |
22 changes: 22 additions & 0 deletions
22
stock_available_to_promise_release_carrier_alternative/models/delivery_carrier.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Copyright 2025 Camptocamp SA | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) | ||
|
|
||
| from odoo import fields, models | ||
|
|
||
| ALTERNATIVE_CARRIER_IDS_HELP = """ | ||
| Change delivery to one of those alternative carriers if the conditions are met. | ||
| Evaluated carriers are this carrier and those alternatives sorted by sequence. | ||
| The first valid carrier will be selected | ||
| """ | ||
|
|
||
|
|
||
| class DeliveryCarrier(models.Model): | ||
| _inherit = "delivery.carrier" | ||
|
|
||
| alternative_carrier_ids = fields.Many2many( | ||
| comodel_name="delivery.carrier", | ||
| relation="carrier_alternative_carrier_rel", | ||
| column1="carrier_id", | ||
| column2="alternative_id", | ||
| help=ALTERNATIVE_CARRIER_IDS_HELP, | ||
| ) |
11 changes: 11 additions & 0 deletions
11
stock_available_to_promise_release_carrier_alternative/models/procurement_group.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Copyright 2020 Camptocamp SA | ||
| # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class ProcurementGroup(models.Model): | ||
| _inherit = "procurement.group" | ||
|
|
||
| picking_ids = fields.One2many( | ||
| comodel_name="stock.picking", inverse_name="group_id", readonly=True | ||
| ) |
55 changes: 55 additions & 0 deletions
55
stock_available_to_promise_release_carrier_alternative/models/stock_move.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Copyright 2020 Camptocamp SA | ||
| # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
|
|
||
| from odoo import models | ||
| from odoo.tools import groupby | ||
|
|
||
|
|
||
| class StockMove(models.Model): | ||
| _inherit = "stock.move" | ||
|
|
||
| def _get_processible_quantity(self): | ||
| self.ensure_one() | ||
| # use available promised qty to estimate the shipping weight | ||
| return self.ordered_available_to_promise_uom_qty | ||
|
|
||
| def _get_new_picking_values(self): | ||
| vals = super()._get_new_picking_values() | ||
| # Take the carrier_id from the group only when we have a related line | ||
| # (i.e. we are in an OUT). It reflects the code of the super method in | ||
| # "delivery" which takes the carrier of the related SO through SO line | ||
| if self.sale_line_id: | ||
| if group_carrier := self.group_id.carrier_id: | ||
| vals["carrier_id"] = group_carrier.id | ||
| return vals | ||
|
|
||
| def _before_release(self): | ||
| # Apply alternative carrier before updating the date | ||
| self = self._apply_alternative_carrier() | ||
| return super()._before_release() | ||
|
|
||
| def _apply_alternative_carrier(self): | ||
| for picking, moves_list in groupby(self, key=lambda move: move.picking_id): | ||
| if not picking.carrier_id.alternative_carrier_ids: | ||
| continue | ||
| # Don't apply alternative carrier when there is already a released move | ||
| if any( | ||
| not move.need_release and move.state != "cancel" | ||
| for move in picking.move_ids | ||
| ): | ||
| continue | ||
| # For computing the best carrier, we need the released moves | ||
| # to be isolated in a dedicated picking. | ||
| # This is for instance required to have the picking estimated | ||
| # shipping weight only for the released moves | ||
| moves = self.browse().union(*moves_list) | ||
| with self.env.cr.savepoint() as savepoint: | ||
| all_need_release_moves = picking.move_ids.filtered("need_release") | ||
| if moves != all_need_release_moves: | ||
| moves._unreleased_to_backorder(split_order=True) | ||
| picking = moves.picking_id | ||
| # If a better carrier is found, assign it, otherwise rollback | ||
| carrier_changed = picking._apply_alternative_carrier() | ||
| if not carrier_changed: | ||
| savepoint.rollback() | ||
| return self |
66 changes: 66 additions & 0 deletions
66
stock_available_to_promise_release_carrier_alternative/models/stock_picking.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # Copyright 2025 Camptocamp SA | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) | ||
| from odoo import models | ||
|
|
||
|
|
||
| class StockPicking(models.Model): | ||
| _inherit = "stock.picking" | ||
|
|
||
| def _apply_alternative_carrier(self): | ||
| self.ensure_one() | ||
| carrier = self._get_preferred_carrier() | ||
| if not carrier: | ||
| return False | ||
| if carrier == self.carrier_id: | ||
| return False | ||
| # Set a context key to not trigger a carrier change on the | ||
| # procurement group | ||
| self.with_context(skip_align_group_carrier=True).carrier_id = carrier | ||
mmequignon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| defaults = { | ||
| "carrier_id": carrier.id, | ||
| "name": self.env._( | ||
| "%s - Alternative carrier %s", self.group_id.name, carrier.name | ||
| ), | ||
| } | ||
| self.group_id = self.group_id.copy(default=defaults) | ||
| active_moves = self.move_ids.filtered( | ||
| lambda m: m.state not in ("done", "cancel") | ||
| ) | ||
| active_moves.group_id = self.group_id | ||
| # Manage the carrier route, but skip when the route was forced | ||
| if ( | ||
| (rerouted_moves := active_moves.filtered(lambda m: not m.route_ids)) | ||
| and (routes := carrier.route_ids.filtered("active")) | ||
| and ( | ||
| rule := self.env["procurement.group"]._get_rule( | ||
| self.env["product.product"], | ||
| self.location_dest_id, | ||
| {"route_ids": routes}, | ||
| ) | ||
| ) | ||
| ): | ||
| rerouted_moves.write( | ||
| { | ||
| "location_id": rule.location_src_id.id, | ||
| "rule_id": rule.id, | ||
| "picking_type_id": rule.picking_type_id.id, | ||
| "procure_method": rule.procure_method, | ||
| "propagate_cancel": rule.propagate_cancel, | ||
| } | ||
| ) | ||
| rerouted_moves._unreleased_to_backorder(split_order=True) | ||
| # If all moves are moved to another picking, the initial picking will | ||
| # be draft. Force it to cancel. | ||
| if not self.move_ids: | ||
| self.state = "cancel" | ||
| return True | ||
|
|
||
| def _get_preferred_carrier(self): | ||
| self.ensure_one() | ||
| picking_carrier = self.carrier_id | ||
| # we consider current carrier as well allowing to configure better | ||
| # carriers as alternative or less restrictive carrier as fallback | ||
| possible_carriers = picking_carrier | picking_carrier.alternative_carrier_ids | ||
| for carrier in possible_carriers.sorted("sequence"): | ||
| if carrier._match_picking(self): | ||
| return carrier | ||
3 changes: 3 additions & 0 deletions
3
stock_available_to_promise_release_carrier_alternative/pyproject.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [build-system] | ||
| requires = ["whool"] | ||
| build-backend = "whool.buildapi" |
5 changes: 5 additions & 0 deletions
5
stock_available_to_promise_release_carrier_alternative/readme/CONFIGURE.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| Go to any delivery method in order to define its alternative delivery methods. | ||
|
|
||
| At release, a new carrier might be selected among alternative carriers. | ||
| This has to comply with a few rules, such as carrier max weight and volume. | ||
| You also can add extra rules by editing a delivery method's Picking Domain. |
2 changes: 2 additions & 0 deletions
2
stock_available_to_promise_release_carrier_alternative/readme/CONTRIBUTORS.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| - Jacques-Etienne Baudoux \<je@bcim.be\> | ||
| - Matthieu Méquignon \<matthieu.mequignon@camptocamp.com\> |
7 changes: 7 additions & 0 deletions
7
stock_available_to_promise_release_carrier_alternative/readme/DESCRIPTION.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| This module allows to define preferred shipping methods in order to fine | ||
| tune the selection of proper delivery carrier from delivery operations | ||
| according to the quantity available to promise. | ||
|
|
||
| Moreover it provides the possibility to force the recomputation of | ||
| preferred delivery carrier on the release of operations for Delivery | ||
| Orders. |
Binary file added
BIN
+9.23 KB
stock_available_to_promise_release_carrier_alternative/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.