forked from OCA/stock-logistics-warehouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by guewen
- Loading branch information
Showing
16 changed files
with
285 additions
and
2 deletions.
There are no files selected for viewing
This file contains 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 |
---|---|---|
@@ -1,2 +1,2 @@ | ||
product-attribute https://github.com/grindtildeath/product-attribute 13.0-mig-product_packaging_dimension | ||
stock-logistics-workflow https://github.com/grindtildeath/stock-logistics-workflow 13.0-mig-stock_quant_package_product_packaging | ||
product-attribute | ||
stock-logistics-warehouse |
This file contains 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 |
This file contains 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,15 @@ | ||
# Copyright 2020 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
{ | ||
"name": "Sale Stock Mto As Mts Orderpoint", | ||
"summary": "Materialize need from MTO route through orderpoint", | ||
"version": "13.0.1.2.0", | ||
"development_status": "Alpha", | ||
"category": "Operations/Inventory/Delivery", | ||
"website": "https://github.com/OCA/stock-logistics-workflow", | ||
"author": "Camptocamp, Odoo Community Association (OCA)", | ||
"license": "AGPL-3", | ||
"application": False, | ||
"installable": True, | ||
"depends": ["sale_stock", "stock_orderpoint_manual_procurement"], | ||
} |
This file contains 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 product | ||
from . import sale_order | ||
from . import stock_move | ||
from . import stock_warehouse |
This file contains 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,45 @@ | ||
# Copyright 2020 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo import models | ||
|
||
|
||
class ProductTemplate(models.Model): | ||
|
||
_inherit = "product.template" | ||
|
||
def write(self, vals): | ||
# Archive orderpoints when MTO route is removed | ||
if "route_ids" not in vals: | ||
return super().write(vals) | ||
mto_products = self._filter_mto_products() | ||
res = super().write(vals) | ||
not_mto_products = self._filter_mto_products(mto=False) | ||
# products to update are the intersection of both recordsets | ||
products_to_update = mto_products & not_mto_products | ||
if products_to_update: | ||
products_to_update._archive_orderpoints_on_mto_removal() | ||
return res | ||
|
||
def _filter_mto_products(self, mto=True): | ||
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False) | ||
if mto: | ||
func = lambda p: mto_route in p.route_ids # noqa | ||
else: | ||
func = lambda p: mto_route not in p.route_ids # noqa | ||
return self.filtered(func) | ||
|
||
def _get_orderpoints_to_archive_domain(self): | ||
warehouses = self.env["stock.warehouse"].search([]) | ||
locations = warehouses._get_locations_for_mto_orderpoints() | ||
return [ | ||
("product_id", "in", self.mapped("product_variant_ids").ids), | ||
("product_min_qty", "=", 0.0), | ||
("product_max_qty", "=", 0.0), | ||
("location_id", "in", locations.ids), | ||
] | ||
|
||
def _archive_orderpoints_on_mto_removal(self): | ||
domain = self._get_orderpoints_to_archive_domain() | ||
ops = self.env["stock.warehouse.orderpoint"].search(domain) | ||
if ops: | ||
ops.write({"active": False}) |
This file contains 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,79 @@ | ||
# Copyright 2020 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo import models | ||
|
||
|
||
class SaleOrderLine(models.Model): | ||
|
||
_inherit = "sale.order.line" | ||
|
||
def _action_launch_stock_rule(self, previous_product_uom_qty=False): | ||
res = super()._action_launch_stock_rule( | ||
previous_product_uom_qty=previous_product_uom_qty | ||
) | ||
self._run_orderpoints_for_mto_products() | ||
return res | ||
|
||
def _run_orderpoints_for_mto_products(self): | ||
orderpoints_to_procure_ids = [] | ||
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False) | ||
if not mto_route: | ||
return | ||
for line in self: | ||
delivery_move = line.move_ids.filtered( | ||
lambda m: m.picking_id.picking_type_code == "outgoing" | ||
and m.state not in ("done", "cancel") | ||
) | ||
if ( | ||
not delivery_move.is_from_mto_route | ||
or mto_route not in line.product_id.route_ids | ||
): | ||
continue | ||
orderpoint = line._get_mto_orderpoint() | ||
if orderpoint.procure_recommended_qty: | ||
orderpoints_to_procure_ids.append(orderpoint.id) | ||
wiz = ( | ||
self.env["make.procurement.orderpoint"] | ||
.with_context( | ||
**{ | ||
"active_model": "stock.warehouse.orderpoint", | ||
"active_ids": orderpoints_to_procure_ids, | ||
} | ||
) | ||
.create({}) | ||
) | ||
wiz.make_procurement() | ||
|
||
def _get_mto_orderpoint(self): | ||
self.ensure_one() | ||
warehouse = self.warehouse_id or self.order_id.warehouse_id | ||
orderpoint = ( | ||
self.env["stock.warehouse.orderpoint"] | ||
.with_context(active_test=False) | ||
.search( | ||
[ | ||
("product_id", "=", self.product_id.id), | ||
( | ||
"location_id", | ||
"=", | ||
warehouse._get_locations_for_mto_orderpoints().id, | ||
), | ||
], | ||
limit=1, | ||
) | ||
) | ||
if orderpoint and not orderpoint.active: | ||
orderpoint.write( | ||
{"active": True, "product_min_qty": 0.0, "product_max_qty": 0.0} | ||
) | ||
elif not orderpoint: | ||
orderpoint = self.env["stock.warehouse.orderpoint"].create( | ||
{ | ||
"product_id": self.product_id.id, | ||
"warehouse_id": warehouse.id, | ||
"location_id": warehouse._get_locations_for_mto_orderpoints().id, | ||
"product_min_qty": 0.0, | ||
"product_max_qty": 0.0, | ||
} | ||
) | ||
return orderpoint |
This file contains 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,18 @@ | ||
# Copyright 2020 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo import fields, models | ||
|
||
|
||
class StockMove(models.Model): | ||
|
||
_inherit = "stock.move" | ||
|
||
is_from_mto_route = fields.Boolean(compute="_compute_is_from_mto_route") | ||
|
||
def _compute_is_from_mto_route(self): | ||
mto_route = self.env.ref("stock.route_warehouse0_mto", raise_if_not_found=False) | ||
if not mto_route: | ||
self.update({"is_from_mto_route": False}) | ||
else: | ||
for move in self: | ||
move.is_from_mto_route = move.rule_id.route_id == mto_route |
11 changes: 11 additions & 0 deletions
11
sale_stock_mto_as_mts_orderpoint/models/stock_warehouse.py
This file contains 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 models | ||
|
||
|
||
class StockWarehouse(models.Model): | ||
|
||
_inherit = "stock.warehouse" | ||
|
||
def _get_locations_for_mto_orderpoints(self): | ||
return self.mapped("lot_stock_id") |
This file contains 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,12 @@ | ||
On the original MTO route, you have two options to configure the rule to pull | ||
from Stock: | ||
|
||
* Keep the triggering of another rule as Supply Method on stock.rule, will | ||
ensure that the need is materialized by the procure_recommended_qty on the | ||
orderpoint, if the ensuing procurement (purchase order/manufacturing order) | ||
having the MTO rule as origin is canceled. | ||
|
||
* Change the Supply Method on stock.rule to Take From Stock, will ensure that | ||
the need is materialized by the procure_recommended_qty on the orderpoint, | ||
if the ensuing procurement (purchase order/manufacturing order) having the | ||
orderpoint as origin is canceled. |
This file contains 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 @@ | ||
* Akim Juillerat <[email protected]> |
This file contains 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,13 @@ | ||
This module aims to materialize the triggering of another stock rule through | ||
an orderpoint in the procurement of MTO products from a sale order. | ||
|
||
When a sales order is confirmed, if the delivery order move is generated by | ||
the stock rule linked to the standard MTO route, and the MTO route is marked | ||
on the product, an orderpoint will be created on the Stock location of the | ||
warehouse, with min/max quantities of zero. | ||
|
||
This allows to regenerate procurement according to the procure_recommended_qty | ||
using module `stock_orderpoint_manual_procurement`. | ||
|
||
Finally, orderpoints with min/max quantities of zero will be archived if the | ||
MTO route is removed on the product. |
This file contains 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 @@ | ||
* Do not rely on original MTO record and have something configurable instead. |
This file contains 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 test_sale_stock_mto_as_mts_orderpoint |
75 changes: 75 additions & 0 deletions
75
sale_stock_mto_as_mts_orderpoint/tests/test_sale_stock_mto_as_mts_orderpoint.py
This file contains 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,75 @@ | ||
# Copyright 2020 Camptocamp SA | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) | ||
from odoo.tests.common import Form, SavepointCase | ||
|
||
|
||
class TestSaleStockMtoAsMtsOrderpoint(SavepointCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) | ||
ref = cls.env.ref | ||
cls.partner = ref("base.res_partner_2") | ||
cls.product = cls.env["product.product"].create( | ||
{"name": "Test MTO", "type": "product"} | ||
) | ||
cls.vendor_partner = ref("base.res_partner_12") | ||
cls.env["product.supplierinfo"].create( | ||
{ | ||
"name": cls.vendor_partner.id, | ||
"product_tmpl_id": cls.product.product_tmpl_id.id, | ||
"min_qty": 1.0, | ||
"price": 1.0, | ||
} | ||
) | ||
|
||
cls.warehouse = ref("stock.warehouse0") | ||
|
||
cls.mto_route = ref("stock.route_warehouse0_mto") | ||
cls.buy_route = ref("purchase_stock.route_warehouse0_buy") | ||
cls.product.write({"route_ids": [(6, 0, [cls.mto_route.id, cls.buy_route.id])]}) | ||
|
||
@classmethod | ||
def _create_sale_order(cls): | ||
sale_form = Form(cls.env["sale.order"]) | ||
sale_form.partner_id = cls.partner | ||
sale_form.warehouse_id = cls.warehouse | ||
with sale_form.order_line.new() as line_form: | ||
line_form.product_id = cls.product | ||
line_form.product_uom_qty = 1 | ||
return sale_form.save() | ||
|
||
def test_mto_as_mts_orderpoint(self): | ||
order = self._create_sale_order() | ||
orderpoint = self.env["stock.warehouse.orderpoint"].search( | ||
[("product_id", "=", self.product.id)] | ||
) | ||
self.assertFalse(orderpoint) | ||
order.action_confirm() | ||
orderpoint = self.env["stock.warehouse.orderpoint"].search( | ||
[("product_id", "=", self.product.id)] | ||
) | ||
self.assertEqual( | ||
orderpoint.location_id, self.warehouse._get_locations_for_mto_orderpoints(), | ||
) | ||
self.assertAlmostEqual(orderpoint.product_min_qty, 0.0) | ||
self.assertAlmostEqual(orderpoint.product_max_qty, 0.0) | ||
self.product.write({"route_ids": [(5, 0, 0)]}) | ||
orderpoint = self.env["stock.warehouse.orderpoint"].search( | ||
[("product_id", "=", self.product.id)] | ||
) | ||
self.assertFalse(orderpoint) | ||
orderpoint = ( | ||
self.env["stock.warehouse.orderpoint"] | ||
.with_context(active_test=False) | ||
.search([("product_id", "=", self.product.id)]) | ||
) | ||
self.assertTrue(orderpoint) | ||
|
||
def test_cancel_sale_order_orderpoint(self): | ||
order = self._create_sale_order() | ||
order.action_confirm() | ||
order.action_cancel() | ||
order.action_draft() | ||
order.action_confirm() | ||
self.assertEqual(order.state, "sale") |
1 change: 1 addition & 0 deletions
1
setup/sale_stock_mto_as_mts_orderpoint/odoo/addons/sale_stock_mto_as_mts_orderpoint
This file contains 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 @@ | ||
../../../../sale_stock_mto_as_mts_orderpoint |
This file contains 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,6 @@ | ||
import setuptools | ||
|
||
setuptools.setup( | ||
setup_requires=['setuptools-odoo'], | ||
odoo_addon=True, | ||
) |