diff --git a/setup/stock_request_mrp/odoo/addons/stock_request_mrp b/setup/stock_request_mrp/odoo/addons/stock_request_mrp new file mode 120000 index 000000000000..a1de8b111db9 --- /dev/null +++ b/setup/stock_request_mrp/odoo/addons/stock_request_mrp @@ -0,0 +1 @@ +../../../../stock_request_mrp \ No newline at end of file diff --git a/setup/stock_request_mrp/setup.py b/setup/stock_request_mrp/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/stock_request_mrp/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_request_mrp/README.rst b/stock_request_mrp/README.rst new file mode 100644 index 000000000000..3ca40cef5e37 --- /dev/null +++ b/stock_request_mrp/README.rst @@ -0,0 +1,87 @@ +================= +Stock Request MRP +================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-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/13.0/stock_request_mrp + :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-13-0/stock-logistics-warehouse-13-0-stock_request_mrp + :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/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows for users to be able to display manufacturing orders that have +been created as a consequence of Stock Requests. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +In case that the confirmation of the Stock Request results in an immediate +Manufacturing Order, the user will be able to display the MO's from the Stock +Request form view. + +Known issues / Roadmap +====================== + +* When a Stock Request is cancelled, it does not cancel the quantity included + in the Manufacturing Order. + +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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ForgeFlow + +Contributors +~~~~~~~~~~~~ + +* Héctor Villarreal . + +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-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_request_mrp/__init__.py b/stock_request_mrp/__init__.py new file mode 100644 index 000000000000..cc6b6354ad8f --- /dev/null +++ b/stock_request_mrp/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .hooks import post_init_hook diff --git a/stock_request_mrp/__manifest__.py b/stock_request_mrp/__manifest__.py new file mode 100644 index 000000000000..3f7d2af8c0ba --- /dev/null +++ b/stock_request_mrp/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Stock Request MRP", + "summary": "Manufacturing request for stock", + "version": "15.0.1.0.0", + "license": "LGPL-3", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "category": "Warehouse Management", + "depends": ["stock_request", "mrp"], + "data": [ + "security/ir.model.access.csv", + "views/stock_request_views.xml", + "views/stock_request_order_views.xml", + "views/mrp_production_views.xml", + ], + "installable": True, + "auto_install": True, + "post_init_hook": "post_init_hook", +} diff --git a/stock_request_mrp/hooks.py b/stock_request_mrp/hooks.py new file mode 100644 index 000000000000..5f2a6891341e --- /dev/null +++ b/stock_request_mrp/hooks.py @@ -0,0 +1,73 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +import logging + +from odoo import SUPERUSER_ID, api + +logger = logging.getLogger(__name__) + + +def post_init_hook(cr, registry): + """ + The objective of this hook is to link existing MOs + coming from a Stock Request. + """ + logger.info("Linking existing MOs coming from a Stock Request") + link_existing_mos_to_stock_request(cr) + + +def link_existing_mos_to_stock_request(cr): + env = api.Environment(cr, SUPERUSER_ID, dict()) + stock_request_obj = env["stock.request"] + stock_request_order_obj = env["stock.request.order"] + stock_request_allocation_obj = env["stock.request.allocation"] + mrp_production_obj = env["mrp.production"] + mos_with_sr = mrp_production_obj.search([("origin", "ilike", "SR/%")]) + logger.info("Linking %s MOs records" % len(mos_with_sr)) + stock_requests = stock_request_obj.search( + [("name", "in", [mo.origin for mo in mos_with_sr])] + ) + for mo in mos_with_sr: + stock_request = stock_requests.filtered(lambda x: x.name == mo.origin) + if stock_request: + # Link SR to MO + mo.stock_request_ids = [(6, 0, stock_request.ids)] + logger.info("MO {} linked to SR {}".format(mo.name, stock_request.name)) + if ( + not stock_request_allocation_obj.search( + [("stock_request_id", "=", stock_request.id)] + ) + and mo.state != "cancel" + ): + # Create allocation for finish move + logger.info("Create allocation for {}".format(stock_request.name)) + mo.move_finished_ids[0].allocation_ids = [ + ( + 0, + 0, + { + "stock_request_id": request.id, + "requested_product_uom_qty": request.product_qty, + }, + ) + for request in mo.stock_request_ids + ] + + # Update allocations + logger.info("Updating Allocations for SR %s" % stock_request.name) + for ml in mo.finished_move_line_ids.filtered( + lambda m: m.exists() and m.move_id.allocation_ids + ): + qty_done = ml.product_uom_id._compute_quantity( + ml.qty_done, ml.product_id.uom_id + ) + to_allocate_qty = ml.qty_done + for allocation in ml.move_id.allocation_ids: + if allocation.open_product_qty: + allocated_qty = min(allocation.open_product_qty, qty_done) + allocation.allocated_product_qty += allocated_qty + to_allocate_qty -= allocated_qty + stock_request.check_done() + # Update production_ids from SROs + stock_request_order_obj.search([])._compute_production_ids() diff --git a/stock_request_mrp/i18n/stock_request_mrp.pot b/stock_request_mrp/i18n/stock_request_mrp.pot new file mode 100644 index 000000000000..5fe73f15b56a --- /dev/null +++ b/stock_request_mrp/i18n/stock_request_mrp.pot @@ -0,0 +1,70 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_request_mrp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_request_mrp +#: model_terms:ir.ui.view,arch_db:stock_request_mrp.stock_request_order_form +#: model_terms:ir.ui.view,arch_db:stock_request_mrp.view_stock_request_form +msgid "MOs" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_ids +#: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_ids +msgid "Manufacturing Orders" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_count +#: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_count +msgid "Manufacturing Orders count" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model,name:stock_request_mrp.model_mrp_production +msgid "Production Order" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model,name:stock_request_mrp.model_stock_request +msgid "Stock Request" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_count +msgid "Stock Request #" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model,name:stock_request_mrp.model_stock_request_order +msgid "Stock Request Order" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_ids +#: model_terms:ir.ui.view,arch_db:stock_request_mrp.mrp_production_form_view +msgid "Stock Requests" +msgstr "" + +#. module: stock_request_mrp +#: model:ir.model,name:stock_request_mrp.model_stock_rule +msgid "Stock Rule" +msgstr "" + +#. module: stock_request_mrp +#: code:addons/stock_request_mrp/models/stock_request.py:0 +#, python-format +msgid "" +"You have linked to a Manufacture Order that belongs to another company." +msgstr "" diff --git a/stock_request_mrp/models/__init__.py b/stock_request_mrp/models/__init__.py new file mode 100644 index 000000000000..ee37123b3c8d --- /dev/null +++ b/stock_request_mrp/models/__init__.py @@ -0,0 +1,4 @@ +from . import mrp_production +from . import stock_rule +from . import stock_request +from . import stock_request_order diff --git a/stock_request_mrp/models/mrp_production.py b/stock_request_mrp/models/mrp_production.py new file mode 100644 index 000000000000..e03424aa5f52 --- /dev/null +++ b/stock_request_mrp/models/mrp_production.py @@ -0,0 +1,71 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + stock_request_ids = fields.Many2many( + "stock.request", + "mrp_production_stock_request_rel", + "mrp_production_id", + "stock_request_id", + string="Stock Requests", + ) + stock_request_count = fields.Integer( + "Stock Request #", compute="_compute_stock_request_ids" + ) + + @api.depends("stock_request_ids") + def _compute_stock_request_ids(self): + for rec in self: + rec.stock_request_count = len(rec.stock_request_ids) + + def action_view_stock_request(self): + """ + :return dict: dictionary value for created view + """ + action = self.env.ref("stock_request.action_stock_request_form").read()[0] + + requests = self.mapped("stock_request_ids") + if len(requests) > 1: + action["domain"] = [("id", "in", requests.ids)] + elif requests: + action["views"] = [ + (self.env.ref("stock_request.view_stock_request_form").id, "form") + ] + action["res_id"] = requests.id + return action + + def _get_move_finished_values( + self, + product_id, + product_uom_qty, + product_uom, + operation_id=False, + byproduct_id=False, + cost_share=0, + ): + res = super()._get_move_finished_values( + product_id, + product_uom_qty, + product_uom, + operation_id=operation_id, + byproduct_id=byproduct_id, + cost_share=cost_share, + ) + if self.stock_request_ids: + res["allocation_ids"] = [ + ( + 0, + 0, + { + "stock_request_id": request.id, + "requested_product_uom_qty": request.product_qty, + }, + ) + for request in self.stock_request_ids + ] + return res diff --git a/stock_request_mrp/models/stock_request.py b/stock_request_mrp/models/stock_request.py new file mode 100644 index 000000000000..3d7e483c9843 --- /dev/null +++ b/stock_request_mrp/models/stock_request.py @@ -0,0 +1,56 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class StockRequest(models.Model): + _inherit = "stock.request" + + production_ids = fields.Many2many( + "mrp.production", + "mrp_production_stock_request_rel", + "stock_request_id", + "mrp_production_id", + string="Manufacturing Orders", + readonly=True, + ) + production_count = fields.Integer( + string="Manufacturing Orders count", + compute="_compute_production_ids", + readonly=True, + ) + + @api.depends("production_ids") + def _compute_production_ids(self): + for request in self: + request.production_count = len(request.production_ids) + + @api.constrains("production_ids", "company_id") + def _check_production_company_constrains(self): + if any( + any( + production.company_id != req.company_id + for production in req.production_ids + ) + for req in self + ): + raise ValidationError( + _( + "You have linked to a Manufacture Order " + "that belongs to another company." + ) + ) + + def action_view_mrp_production(self): + action = self.env.ref("mrp.mrp_production_action").read()[0] + productions = self.mapped("production_ids") + if len(productions) > 1: + action["domain"] = [("id", "in", productions.ids)] + elif productions: + action["views"] = [ + (self.env.ref("mrp.mrp_production_form_view").id, "form") + ] + action["res_id"] = productions.id + return action diff --git a/stock_request_mrp/models/stock_request_order.py b/stock_request_mrp/models/stock_request_order.py new file mode 100644 index 000000000000..5ad225c09299 --- /dev/null +++ b/stock_request_mrp/models/stock_request_order.py @@ -0,0 +1,42 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class StockRequestOrder(models.Model): + _inherit = "stock.request.order" + + production_ids = fields.One2many( + "mrp.production", + compute="_compute_production_ids", + string="Manufacturing Orders", + readonly=True, + ) + production_count = fields.Integer( + string="Manufacturing Orders count", + compute="_compute_production_ids", + readonly=True, + ) + + @api.depends("stock_request_ids") + def _compute_production_ids(self): + for req in self: + req.production_ids = req.stock_request_ids.mapped("production_ids") + req.production_count = len(req.production_ids) + + def action_view_mrp_production(self): + action = self.env.ref("mrp.mrp_production_action").read()[0] + productions = self.mapped("production_ids") + if len(productions) > 1: + action["domain"] = [("id", "in", productions.ids)] + action["views"] = [ + (self.env.ref("mrp.mrp_production_tree_view").id, "tree"), + (self.env.ref("mrp.mrp_production_form_view").id, "form"), + ] + elif productions: + action["views"] = [ + (self.env.ref("mrp.mrp_production_form_view").id, "form") + ] + action["res_id"] = productions.id + return action diff --git a/stock_request_mrp/models/stock_rule.py b/stock_request_mrp/models/stock_rule.py new file mode 100644 index 000000000000..3cf358b4e111 --- /dev/null +++ b/stock_request_mrp/models/stock_rule.py @@ -0,0 +1,34 @@ +# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from odoo import models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _prepare_mo_vals( + self, + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + bom, + ): + res = super()._prepare_mo_vals( + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + bom, + ) + if "stock_request_id" in values: + res["stock_request_ids"] = [(4, values["stock_request_id"])] + return res diff --git a/stock_request_mrp/readme/CONTRIBUTORS.rst b/stock_request_mrp/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000000..45e6392e8741 --- /dev/null +++ b/stock_request_mrp/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Héctor Villarreal . diff --git a/stock_request_mrp/readme/DESCRIPTION.rst b/stock_request_mrp/readme/DESCRIPTION.rst new file mode 100644 index 000000000000..99ce461663c2 --- /dev/null +++ b/stock_request_mrp/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows for users to be able to display manufacturing orders that have +been created as a consequence of Stock Requests. diff --git a/stock_request_mrp/readme/ROADMAP.rst b/stock_request_mrp/readme/ROADMAP.rst new file mode 100644 index 000000000000..879b69590925 --- /dev/null +++ b/stock_request_mrp/readme/ROADMAP.rst @@ -0,0 +1,2 @@ +* When a Stock Request is cancelled, it does not cancel the quantity included + in the Manufacturing Order. diff --git a/stock_request_mrp/readme/USAGE.rst b/stock_request_mrp/readme/USAGE.rst new file mode 100644 index 000000000000..c3eeaf348b31 --- /dev/null +++ b/stock_request_mrp/readme/USAGE.rst @@ -0,0 +1,3 @@ +In case that the confirmation of the Stock Request results in an immediate +Manufacturing Order, the user will be able to display the MO's from the Stock +Request form view. diff --git a/stock_request_mrp/security/ir.model.access.csv b/stock_request_mrp/security/ir.model.access.csv new file mode 100644 index 000000000000..207639cd61a0 --- /dev/null +++ b/stock_request_mrp/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_stock_request_mrp_user,stock.request purchase user,stock_request.model_stock_request,mrp.group_mrp_user,1,0,0,0 +access_stock_request_allocation_mrp_user,stock request allocation purchase user,stock_request.model_stock_request_allocation,mrp.group_mrp_user,1,0,0,0 +access_stock_request_mrp_bom_user,stock request mrp bom user,mrp.model_mrp_bom,stock_request.group_stock_request_user,1,0,0,0 diff --git a/stock_request_mrp/static/description/icon.png b/stock_request_mrp/static/description/icon.png new file mode 100644 index 000000000000..d4f6a65aca34 Binary files /dev/null and b/stock_request_mrp/static/description/icon.png differ diff --git a/stock_request_mrp/static/description/index.html b/stock_request_mrp/static/description/index.html new file mode 100644 index 000000000000..68f178877e9d --- /dev/null +++ b/stock_request_mrp/static/description/index.html @@ -0,0 +1,435 @@ + + + + + + +Stock Request MRP + + + +
+

Stock Request MRP

+ + +

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

+

This module allows for users to be able to display manufacturing orders that have +been created as a consequence of Stock Requests.

+

Table of contents

+ +
+

Usage

+

In case that the confirmation of the Stock Request results in an immediate +Manufacturing Order, the user will be able to display the MO’s from the Stock +Request form view.

+
+
+

Known issues / Roadmap

+
    +
  • When a Stock Request is cancelled, it does not cancel the quantity included +in the Manufacturing Order.
  • +
+
+
+

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.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

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.

+

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

+
+
+
+ + diff --git a/stock_request_mrp/tests/__init__.py b/stock_request_mrp/tests/__init__.py new file mode 100644 index 000000000000..cf5db6649282 --- /dev/null +++ b/stock_request_mrp/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_request_mrp diff --git a/stock_request_mrp/tests/test_stock_request_mrp.py b/stock_request_mrp/tests/test_stock_request_mrp.py new file mode 100644 index 000000000000..4421eac0f843 --- /dev/null +++ b/stock_request_mrp/tests/test_stock_request_mrp.py @@ -0,0 +1,209 @@ +# Copyright 2016-20 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0). + +from odoo import fields +from odoo.tests import common + + +class TestStockRequestMrp(common.TransactionCase): + def setUp(self): + super().setUp() + + # common models + self.stock_request = self.env["stock.request"] + + # refs + self.stock_request_user_group = self.env.ref( + "stock_request.group_stock_request_user" + ) + self.stock_request_manager_group = self.env.ref( + "stock_request.group_stock_request_manager" + ) + self.mrp_user_group = self.env.ref("mrp.group_mrp_user") + self.main_company = self.env.ref("base.main_company") + self.warehouse = self.env.ref("stock.warehouse0") + self.categ_unit = self.env.ref("uom.product_uom_categ_unit") + + # common data + self.company_2 = self.env["res.company"].create({"name": "Comp2"}) + self.wh2 = self.env["stock.warehouse"].search( + [("company_id", "=", self.company_2.id)], limit=1 + ) + self.stock_request_user = self._create_user( + "stock_request_user", + [self.stock_request_user_group.id, self.mrp_user_group.id], + [self.main_company.id, self.company_2.id], + ) + self.stock_request_manager = self._create_user( + "stock_request_manager", + [self.stock_request_manager_group.id, self.mrp_user_group.id], + [self.main_company.id, self.company_2.id], + ) + self.route_manufacture = self.warehouse.manufacture_pull_id.route_id + self.product = self._create_product( + "SH", "Shoes", False, self.route_manufacture.ids + ) + + self.raw_1 = self._create_product("SL", "Sole", False, []) + self._update_qty_in_location(self.warehouse.lot_stock_id, self.raw_1, 10) + self.raw_2 = self._create_product("LC", "Lace", False, []) + self._update_qty_in_location(self.warehouse.lot_stock_id, self.raw_2, 10) + + self.bom = self._create_mrp_bom(self.product, [self.raw_1, self.raw_2]) + + self.uom_pair = self.env["uom.uom"].create( + { + "name": "Test-Pair", + "category_id": self.categ_unit.id, + "factor_inv": 2, + "uom_type": "bigger", + "rounding": 0.001, + } + ) + + def _update_qty_in_location(self, location, product, quantity): + self.env["stock.quant"]._update_available_quantity(product, location, quantity) + + def _create_user(self, name, group_ids, company_ids): + return ( + self.env["res.users"] + .with_context(no_reset_password=True) + .create( + { + "name": name, + "password": "demo", + "login": name, + "email": str(name) + "@test.com", + "groups_id": [(6, 0, group_ids)], + "company_ids": [(6, 0, company_ids)], + } + ) + ) + + def _create_product(self, default_code, name, company_id, route_ids): + return self.env["product.product"].create( + { + "name": name, + "default_code": default_code, + "uom_id": self.env.ref("uom.product_uom_unit").id, + "company_id": company_id, + "type": "product", + "route_ids": [(6, 0, route_ids)], + } + ) + + def _create_mrp_bom(self, product_id, raw_materials): + bom = self.env["mrp.bom"].create( + { + "product_id": product_id.id, + "product_tmpl_id": product_id.product_tmpl_id.id, + "product_uom_id": product_id.uom_id.id, + "product_qty": 1.0, + "type": "normal", + } + ) + for raw_mat in raw_materials: + self.env["mrp.bom.line"].create( + {"bom_id": bom.id, "product_id": raw_mat.id, "product_qty": 1} + ) + + return bom + + def test_create_request_01(self): + """Single Stock request with buy rule""" + expected_date = fields.Datetime.now() + vals = { + "company_id": self.main_company.id, + "warehouse_id": self.warehouse.id, + "location_id": self.warehouse.lot_stock_id.id, + "expected_date": expected_date, + "stock_request_ids": [ + ( + 0, + 0, + { + "product_id": self.product.id, + "product_uom_id": self.product.uom_id.id, + "product_uom_qty": 5.0, + "company_id": self.main_company.id, + "warehouse_id": self.warehouse.id, + "location_id": self.warehouse.lot_stock_id.id, + "expected_date": expected_date, + }, + ) + ], + } + + order = ( + self.env["stock.request.order"] + .with_user(self.stock_request_user) + .create(vals) + ) + + order.action_confirm() + self.assertEqual(order.state, "open") + self.assertEqual(order.stock_request_ids.state, "open") + + order.refresh() + + self.assertEqual(len(order.production_ids), 1) + self.assertEqual(len(order.stock_request_ids.production_ids), 1) + self.assertEqual(order.stock_request_ids.qty_in_progress, 5.0) + + manufacturing_order = order.production_ids[0] + self.assertEqual( + manufacturing_order.company_id, order.stock_request_ids[0].company_id + ) + manufacturing_order.action_confirm() + manufacturing_order.write( + {"qty_producing": manufacturing_order.product_uom_qty} + ) + manufacturing_order._set_qty_producing() + + manufacturing_order.with_context(skip_immediate=True).button_mark_done() + self.assertEqual(order.stock_request_ids.qty_in_progress, 0.0) + self.assertEqual(order.stock_request_ids.qty_done, 5.0) + + def test_view_actions(self): + expected_date = fields.Datetime.now() + vals = { + "company_id": self.main_company.id, + "warehouse_id": self.warehouse.id, + "location_id": self.warehouse.lot_stock_id.id, + "expected_date": expected_date, + "stock_request_ids": [ + ( + 0, + 0, + { + "product_id": self.product.id, + "product_uom_id": self.product.uom_id.id, + "product_uom_qty": 5.0, + "company_id": self.main_company.id, + "warehouse_id": self.warehouse.id, + "location_id": self.warehouse.lot_stock_id.id, + "expected_date": expected_date, + }, + ) + ], + } + + order = self.env["stock.request.order"].create(vals) + + order.action_confirm() + + stock_request = order.stock_request_ids + + action = stock_request.action_view_mrp_production() + + self.assertEqual("views" in action.keys(), True) + self.assertEqual(action["res_id"], stock_request.production_ids[0].id) + + action = stock_request.production_ids[0].action_view_stock_request() + self.assertEqual(action["type"], "ir.actions.act_window") + self.assertEqual(action["res_id"], stock_request.id) + + action = order.action_view_mrp_production() + + self.assertEqual("views" in action.keys(), True) + self.assertEqual(action["res_id"], order.production_ids[0].id) diff --git a/stock_request_mrp/views/mrp_production_views.xml b/stock_request_mrp/views/mrp_production_views.xml new file mode 100644 index 000000000000..879c86062271 --- /dev/null +++ b/stock_request_mrp/views/mrp_production_views.xml @@ -0,0 +1,37 @@ + + + + + mrp.production.form.inherit.stock.request.mrp + mrp.production + + + + + + + + + + + + + + diff --git a/stock_request_mrp/views/stock_request_order_views.xml b/stock_request_mrp/views/stock_request_order_views.xml new file mode 100644 index 000000000000..d8aa04770f86 --- /dev/null +++ b/stock_request_mrp/views/stock_request_order_views.xml @@ -0,0 +1,25 @@ + + + + + stock.request.order.form + stock.request.order + + + +
+ + +
+
+
+
diff --git a/stock_request_mrp/views/stock_request_views.xml b/stock_request_mrp/views/stock_request_views.xml new file mode 100644 index 000000000000..b3cf2ee27994 --- /dev/null +++ b/stock_request_mrp/views/stock_request_views.xml @@ -0,0 +1,25 @@ + + + + + stock.request.form + stock.request + + + +
+ + +
+
+
+