├── stock_request_mrp ├── readme │ ├── ROADMAP.md │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── tests │ └── __init__.py ├── __init__.py ├── pyproject.toml ├── static │ └── description │ │ └── icon.png ├── models │ ├── __init__.py │ ├── stock_rule.py │ ├── stock_request_order.py │ ├── stock_request.py │ └── mrp_production.py ├── security │ └── ir.model.access.csv ├── __manifest__.py ├── views │ ├── stock_request_views.xml │ ├── stock_request_order_views.xml │ └── mrp_production_views.xml ├── i18n │ ├── stock_request_mrp.pot │ ├── it.po │ └── es.po ├── hooks.py └── README.rst ├── stock_request ├── __init__.py ├── tests │ └── __init__.py ├── pyproject.toml ├── static │ └── description │ │ └── icon.png ├── readme │ ├── DESCRIPTION.md │ ├── ROADMAP.md │ ├── CONFIGURE.md │ ├── USAGE.md │ └── CONTRIBUTORS.md ├── models │ ├── __init__.py │ ├── res_company.py │ ├── stock_route.py │ ├── procurement_group.py │ ├── stock_rule.py │ ├── stock_picking.py │ ├── res_config_settings.py │ ├── stock_location.py │ ├── stock_warehouse.py │ ├── stock_move.py │ ├── stock_request_allocation.py │ └── stock_move_line.py ├── data │ └── stock_request_sequence_data.xml ├── __manifest__.py ├── views │ ├── stock_picking_views.xml │ ├── stock_move_views.xml │ ├── stock_request_menu.xml │ ├── product.xml │ └── stock_request_allocation_views.xml └── security │ └── ir.model.access.csv ├── stock_request_bom ├── __init__.py ├── models │ ├── __init__.py │ └── stock_request_order.py ├── tests │ ├── __init__.py │ └── test_stock_request_bom.py ├── readme │ ├── CONTRIBUTORS.md │ ├── USAGE.md │ └── DESCRIPTION.md ├── pyproject.toml ├── static │ └── description │ │ └── icon.png ├── __manifest__.py ├── views │ └── stock_request_order_views.xml ├── i18n │ ├── stock_request_bom.pot │ └── it.po └── README.rst ├── stock_request_purchase ├── __init__.py ├── tests │ └── __init__.py ├── pyproject.toml ├── readme │ ├── ROADMAP.md │ ├── DESCRIPTION.md │ ├── USAGE.md │ └── CONTRIBUTORS.md ├── static │ └── description │ │ └── icon.png ├── models │ ├── __init__.py │ ├── stock_rule.py │ ├── purchase_order.py │ ├── stock_request_order.py │ ├── stock_request.py │ └── purchase_order_line.py ├── security │ └── ir.model.access.csv ├── __manifest__.py ├── views │ ├── stock_request_views.xml │ ├── stock_request_order_views.xml │ └── purchase_order_views.xml ├── i18n │ ├── stock_request_purchase.pot │ ├── zh_CN.po │ ├── de.po │ ├── it.po │ └── es.po └── README.rst ├── stock_request_tier_validation ├── __init__.py ├── readme │ ├── CREDITS.md │ ├── INSTALL.md │ ├── DESCRIPTION.md │ ├── CONTRIBUTORS.md │ ├── CONFIGURE.md │ └── USAGE.md ├── tests │ ├── __init__.py │ └── test_stock_request_tier_validation.py ├── pyproject.toml ├── models │ ├── __init__.py │ ├── tier_definition.py │ ├── stock_request.py │ └── stock_request_order.py ├── static │ └── description │ │ └── icon.png ├── __manifest__.py ├── views │ ├── stock_request_order_view.xml │ └── stock_request_view.xml └── data │ └── stock_request_tier_definition.xml ├── stock_return_request ├── __init__.py ├── wizard │ ├── __init__.py │ ├── suggest_return_request_lot.py │ └── suggest_return_request.xml ├── pyproject.toml ├── tests │ └── __init__.py ├── models │ ├── __init__.py │ ├── stock_picking.py │ └── stock_move.py ├── static │ └── description │ │ └── icon.png ├── readme │ ├── ROADMAP.md │ ├── DESCRIPTION.md │ ├── INSTALL.md │ ├── USAGE.md │ └── CONTRIBUTORS.md ├── data │ └── stock_return_request_data.xml ├── __manifest__.py ├── security │ └── ir.model.access.csv └── README.rst ├── checklog-odoo.cfg ├── stock_request_kanban ├── tests │ ├── __init__.py │ └── base_test.py ├── pyproject.toml ├── static │ └── description │ │ └── icon.png ├── __init__.py ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── CONFIGURE.md │ └── USAGE.md ├── models │ ├── __init__.py │ ├── stock_request.py │ ├── product.py │ └── stock_request_kanban.py ├── wizard │ ├── __init__.py │ ├── wizard_stock_request_order_kanban_views.xml │ ├── wizard_stock_inventory_kanban.py │ ├── wizard_stock_request_kanban_abstract.py │ ├── wizard_stock_request_kanban.py │ ├── wizard_stock_request_kanban_views.xml │ ├── wizard_stock_inventory_kanban_views.xml │ └── wizard_stock_request_order_kanban.py ├── report │ └── report_paper_format.xml ├── data │ └── stock_request_sequence_data.xml ├── views │ ├── stock_request_order_views.xml │ ├── stock_request_menu.xml │ ├── stock_request_views.xml │ └── product_views.xml ├── __manifest__.py └── security │ └── ir.model.access.csv ├── prettier.config.cjs ├── setup └── _metapackage │ └── pyproject.toml ├── .editorconfig ├── .ruff.toml ├── .copier-answers.yml ├── .gitignore ├── .github └── workflows │ ├── pre-commit.yml │ ├── test.yml │ └── stale.yml ├── .pylintrc-mandatory ├── .pylintrc └── README.md /stock_request_mrp/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stock_request/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | -------------------------------------------------------------------------------- /stock_request_bom/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | -------------------------------------------------------------------------------- /stock_request_purchase/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | -------------------------------------------------------------------------------- /stock_request/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_stock_request 2 | -------------------------------------------------------------------------------- /stock_request_tier_validation/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | -------------------------------------------------------------------------------- /stock_request_bom/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import stock_request_order 2 | -------------------------------------------------------------------------------- /stock_request_bom/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_stock_request_bom 2 | -------------------------------------------------------------------------------- /stock_request_mrp/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_stock_request_mrp 2 | -------------------------------------------------------------------------------- /stock_return_request/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from . import wizard 3 | -------------------------------------------------------------------------------- /stock_request_purchase/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_stock_request_purchase 2 | -------------------------------------------------------------------------------- /stock_return_request/wizard/__init__.py: -------------------------------------------------------------------------------- 1 | from . import suggest_return_request_lot 2 | -------------------------------------------------------------------------------- /checklog-odoo.cfg: -------------------------------------------------------------------------------- 1 | [checklog-odoo] 2 | ignore= 3 | WARNING.* 0 failed, 0 error\(s\).* 4 | -------------------------------------------------------------------------------- /stock_request_mrp/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from .hooks import post_init_hook 3 | -------------------------------------------------------------------------------- /stock_request_tier_validation/readme/CREDITS.md: -------------------------------------------------------------------------------- 1 | ## Images 2 | 3 | - Enric Tobella (logo) 4 | -------------------------------------------------------------------------------- /stock_request_bom/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Joan Sisquella Andrés \ 2 | -------------------------------------------------------------------------------- /stock_request_mrp/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Héctor Villarreal \<\>. 2 | -------------------------------------------------------------------------------- /stock_request_tier_validation/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_stock_request_tier_validation 2 | -------------------------------------------------------------------------------- /stock_request_kanban/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_kanban 2 | from . import test_inventory_kanban 3 | -------------------------------------------------------------------------------- /stock_request/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_request_bom/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_request_mrp/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_request_kanban/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_request_purchase/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_return_request/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_request_tier_validation/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /stock_return_request/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_stock_return_request 2 | from . import test_stock_return_request_common 3 | -------------------------------------------------------------------------------- /stock_return_request/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import stock_move 2 | from . import stock_picking 3 | from . import stock_return_request 4 | -------------------------------------------------------------------------------- /stock_request/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_request/static/description/icon.png -------------------------------------------------------------------------------- /stock_request_bom/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_request_bom/static/description/icon.png -------------------------------------------------------------------------------- /stock_request_mrp/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_request_mrp/static/description/icon.png -------------------------------------------------------------------------------- /stock_request_purchase/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | - When a Stock Request is cancelled, it does not cancel the quantity 2 | included in the Purchase Order. 3 | -------------------------------------------------------------------------------- /stock_request_tier_validation/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import stock_request 2 | from . import stock_request_order 3 | from . import tier_definition 4 | -------------------------------------------------------------------------------- /stock_request_kanban/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_request_kanban/static/description/icon.png -------------------------------------------------------------------------------- /stock_request_purchase/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_request_purchase/static/description/icon.png -------------------------------------------------------------------------------- /stock_return_request/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_return_request/static/description/icon.png -------------------------------------------------------------------------------- /stock_request_mrp/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import mrp_production 2 | from . import stock_rule 3 | from . import stock_request 4 | from . import stock_request_order 5 | -------------------------------------------------------------------------------- /stock_request_tier_validation/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | This module depends on `base_tier_validation`. You can find it at 2 | [OCA/server-ux](https://github.com/OCA/server-ux) 3 | -------------------------------------------------------------------------------- /stock_return_request/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | - Products are returned in the default product UoM. Further 2 | implementation should be done to allow to use UoM convertions. 3 | -------------------------------------------------------------------------------- /stock_request_mrp/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows users to be able to display Manufacturing Orders 2 | that have been created as a consequence of Stock Requests. 3 | -------------------------------------------------------------------------------- /stock_request_purchase/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows for users to be able to display purchase orders that 2 | have been created as a consequence of Stock Requests. 3 | -------------------------------------------------------------------------------- /stock_request_tier_validation/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module extends the functionality of Stock Requests and Stock 2 | Request Orders to support a tier validation process. 3 | -------------------------------------------------------------------------------- /stock_request_tier_validation/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/stock-logistics-request/HEAD/stock_request_tier_validation/static/description/icon.png -------------------------------------------------------------------------------- /stock_request_bom/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | 1. Select a Product BOM and enter a Quantity BOM. 2 | 2. Stock request lines will auto-fill with BOM components. 3 | 3. Adjust quantity BOM as needed. 4 | -------------------------------------------------------------------------------- /stock_return_request/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows to return stock from a location to either suppliers, 2 | customers or internal locations reverting the corresponding pickings. 3 | -------------------------------------------------------------------------------- /stock_request/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module was written to allow users to request products that are 2 | frequently stocked by the company, to be transferred to their chosen 3 | location. 4 | -------------------------------------------------------------------------------- /stock_request_kanban/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from . import models 5 | from . import wizard 6 | -------------------------------------------------------------------------------- /stock_request_kanban/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Enric Tobella \<\> 2 | - Kitti Upariphutthiphong \<\> 3 | - Marco Colombo \< 4 | -------------------------------------------------------------------------------- /stock_request_purchase/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import purchase_order 2 | from . import purchase_order_line 3 | from . import stock_rule 4 | from . import stock_request 5 | from . import stock_request_order 6 | -------------------------------------------------------------------------------- /stock_request_tier_validation/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Lois Rilo \<\> 2 | - Héctor Villarreal \<\> 3 | - Pimolnat Suntian \<\> 4 | -------------------------------------------------------------------------------- /stock_request_purchase/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | In case that the confirmation of the Stock Request results in an 2 | immediate Purchase Order, the user will be able to display the PO's from 3 | the Stock Request form view. 4 | -------------------------------------------------------------------------------- /stock_return_request/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | The installation of this module entails the computation of the new 2 | stock.move field qty_returnable to store it in the DB, wich can be a 3 | heavy task depending on the amount of moves. 4 | -------------------------------------------------------------------------------- /stock_request/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | There is no way to achieve Storck Request and Stock Request Orders. It 2 | should be developed taking into account that only Cancel and Done stock 3 | request can be archived. 4 | 5 | It is also required to manage active field logically from Orders to SRs. 6 | -------------------------------------------------------------------------------- /stock_request_kanban/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from . import stock_request 5 | from . import stock_request_kanban 6 | from . import stock_inventory_kanban 7 | from . import product 8 | -------------------------------------------------------------------------------- /stock_return_request/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | To use this module, you need to: 2 | 3 | 1. Go to *Inventory \> Operations \> Return Request* and place a new 4 | return. 5 | 6 | To make a return to a customer: 7 | 8 | To make a return to a supplier: 9 | 10 | To make a return to an internal location: 11 | -------------------------------------------------------------------------------- /stock_return_request/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - [Tecnativa](https://www.tecnativa.com): 2 | - Sergio Teruel 3 | - Pedro M. Baeza 4 | - David Vidal 5 | - César A. Sánchez 6 | - Carlos Lopez 7 | - [Pro Thai](http://prothaitechnology.com): 8 | - Prapassorn Sornkaew \<\> 9 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from . import wizard_stock_request_kanban_abstract 5 | from . import wizard_stock_request_kanban 6 | from . import wizard_stock_request_order_kanban 7 | from . import wizard_stock_inventory_kanban 8 | -------------------------------------------------------------------------------- /stock_request_purchase/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Jordi Ballester \<\>. 2 | - Enric Tobella \<\> 3 | - Kitti Upariphutthiphong \<\> 4 | - Alan Ramos \<\> 5 | - Urvisha Desai \<\> 6 | - Bruno Zanotti \<\> 7 | -------------------------------------------------------------------------------- /stock_request_bom/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module enhances the stock request functionality by integrating with 2 | the Bill of Materials (BOM). 3 | 4 | Key Features: - Adds Product BOM and Quantity BOM fields to stock 5 | request orders. - Auto-completes stock request lines based on the 6 | selected BOM and quantity. - Allows updating and clearing BOM 7 | selections. 8 | -------------------------------------------------------------------------------- /stock_request_tier_validation/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | A default tier is created allowing Stock Request Manager to approve 2 | Stock Request and Stock Request Orders. 3 | 4 | In addition, you may want to add more tiers, so: 5 | 6 | 1. Go to *Settings \> Technical \> Tier Validations \> Tier 7 | Definition*. 8 | 2. Create as many tiers as you want for Stock Request model. 9 | -------------------------------------------------------------------------------- /stock_request_purchase/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_stock_request_purchase_user,stock.request purchase user,stock_request.model_stock_request,purchase.group_purchase_user,1,0,0,0 3 | access_stock_request_allocation_purchase_user,stock request allocation purchase user,stock_request.model_stock_request_allocation,purchase.group_purchase_user,1,0,0,0 4 | -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config} */ 2 | 3 | const config = { 4 | // https://github.com/prettier/prettier/issues/15388#issuecomment-1717746872 5 | plugins: [require.resolve("@prettier/plugin-xml")], 6 | bracketSpacing: false, 7 | printWidth: 88, 8 | proseWrap: "always", 9 | semi: true, 10 | trailingComma: "es5", 11 | xmlWhitespaceSensitivity: "preserve", 12 | }; 13 | 14 | module.exports = config; 15 | -------------------------------------------------------------------------------- /stock_request_kanban/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | On most companies there are products that must be purchased often but 2 | cannot be stored as a usual product because no consumption moves are 3 | made. Usually, they are stored as consumables or putaway rules are 4 | defined. In both cases, reordering rules cannot be used. This module 5 | allows to use stock request as reordering rules for this kind of 6 | products. 7 | 8 | It is created following the concept of lean kanban cards. 9 | -------------------------------------------------------------------------------- /stock_request/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import procurement_group 2 | from . import stock_request_abstract 3 | from . import stock_request 4 | from . import stock_request_allocation 5 | from . import stock_request_order 6 | from . import stock_move 7 | from . import stock_picking 8 | from . import stock_rule 9 | from . import stock_move_line 10 | from . import res_config_settings 11 | from . import stock_warehouse 12 | from . import stock_location 13 | from . import stock_route 14 | from . import res_company 15 | -------------------------------------------------------------------------------- /stock_request/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | To configure this module: 2 | 3 | - Go to Stock Requests \> Settings 4 | 5 | Users should be assigned to the groups 'Stock Request / User' or 'Stock 6 | Request / Manager'. 7 | 8 | \## Group Stock Request / User 9 | 10 | - Can see her/his own Stock Requests, and others that she/he's been 11 | granted permission to follow. 12 | - Can create/update only her/his Stock Requests. 13 | 14 | \## Group Stock Request / Manager 15 | 16 | - Can fully manage all Stock Requests 17 | -------------------------------------------------------------------------------- /stock_request_mrp/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | In case that the confirmation of the Stock Request results in an 2 | immediate Manufacturing Order, the user will be able to display the MO's 3 | from the Stock Request form view. 4 | 5 | Navigate to Stock Requests and create a new stock request. 6 | Upon confirmation of the stock request, the system will automatically generate the corresponding manufacturing order. 7 | View and manage the generated manufacturing orders directly from the stock request record or through Manufacturing. 8 | -------------------------------------------------------------------------------- /stock_request_mrp/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_stock_request_mrp_user,stock.request purchase user,stock_request.model_stock_request,mrp.group_mrp_user,1,0,0,0 3 | 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 4 | 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 5 | -------------------------------------------------------------------------------- /stock_request_tier_validation/models/tier_definition.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | from odoo import api, models 4 | 5 | 6 | class TierDefinition(models.Model): 7 | _inherit = "tier.definition" 8 | 9 | @api.model 10 | def _get_tier_validation_model_names(self): 11 | res = super()._get_tier_validation_model_names() 12 | res.extend(("stock.request", "stock.request.order")) 13 | return res 14 | -------------------------------------------------------------------------------- /stock_request/models/res_company.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 ForgeFlow S.L. 2 | # (http://www.forgeflow.com) 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | 6 | from odoo import fields, models 7 | 8 | 9 | class ResCompany(models.Model): 10 | _inherit = "res.company" 11 | 12 | stock_request_allow_virtual_loc = fields.Boolean( 13 | string="Allow Virtual locations on Stock Requests" 14 | ) 15 | stock_request_check_available_first = fields.Boolean( 16 | string="Check available stock first" 17 | ) 18 | -------------------------------------------------------------------------------- /stock_return_request/data/stock_return_request_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stock Return Request 5 | stock.return.request 6 | RR/ 7 | 5 8 | 1 9 | 1 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /stock_request/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | \## Creation 2 | 3 | - Go to 'Stock Requests / Stock Requests' and create a new Request. 4 | - Indicate a product, quantity and location. 5 | - Press 'Confirm'. 6 | 7 | Upon confirmation the request will be evaluated using the procurement 8 | rules for the selected location. 9 | 10 | In case that transfers are created, the user will be able to access to 11 | them from the button 'Transfers' available in the Stock Request. 12 | 13 | \## Cancel 14 | 15 | When the user cancels a Stock Request, the related pending stock moves 16 | will be also cancelled. 17 | -------------------------------------------------------------------------------- /stock_request_kanban/tests/base_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # Copyright 2017-2024 ForgeFlow, S.L. 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | from reportlab.graphics.barcode import getCodes 6 | 7 | from odoo.tests.common import TransactionCase 8 | 9 | 10 | class TestBaseKanban(TransactionCase): 11 | def pass_code(self, wizard, code): 12 | bcc = getCodes()[self.env["stock.request.kanban"].get_barcode_format()]( 13 | value=code 14 | ) 15 | bcc.validate() 16 | bcc.encode() 17 | wizard.on_barcode_scanned(bcc.encoded[1:-1]) 18 | -------------------------------------------------------------------------------- /setup/_metapackage/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "odoo-addons-oca-stock-logistics-request" 3 | version = "18.0.20250903.0" 4 | dependencies = [ 5 | "odoo-addon-stock_request==18.0.*", 6 | "odoo-addon-stock_request_bom==18.0.*", 7 | "odoo-addon-stock_request_kanban==18.0.*", 8 | "odoo-addon-stock_request_mrp==18.0.*", 9 | "odoo-addon-stock_request_purchase==18.0.*", 10 | "odoo-addon-stock_request_tier_validation==18.0.*", 11 | "odoo-addon-stock_return_request==18.0.*", 12 | ] 13 | classifiers=[ 14 | "Programming Language :: Python", 15 | "Framework :: Odoo", 16 | "Framework :: Odoo :: 18.0", 17 | ] 18 | -------------------------------------------------------------------------------- /stock_request_kanban/report/report_paper_format.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kanban format 5 | A4 6 | Portrait 7 | 0.0 8 | 0.0 9 | 0.0 10 | 0.0 11 | 0 12 | 72 13 | 14 | 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Configuration for known file extensions 2 | [*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}] 3 | charset = utf-8 4 | end_of_line = lf 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.{json,yml,yaml,rst,md}] 11 | indent_size = 2 12 | 13 | # Do not configure editor for libs and autogenerated content 14 | [{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] 15 | charset = unset 16 | end_of_line = unset 17 | indent_size = unset 18 | indent_style = unset 19 | insert_final_newline = false 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /stock_request_kanban/models/stock_request.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import fields, models 5 | 6 | 7 | class StockRequest(models.Model): 8 | _inherit = "stock.request" 9 | 10 | kanban_id = fields.Many2one("stock.request.kanban", readonly=True) 11 | 12 | def action_scan_kanban(self): 13 | return { 14 | "res_model": "wizard.stock.request.kanban", 15 | "views": [[False, "form"]], 16 | "target": "new", 17 | "type": "ir.actions.act_window", 18 | "context": self._context, 19 | } 20 | -------------------------------------------------------------------------------- /stock_request_tier_validation/models/stock_request.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | from odoo import api, models 4 | 5 | 6 | class StockRequest(models.Model): 7 | _name = "stock.request" 8 | _inherit = ["stock.request", "tier.validation"] 9 | _state_from = ["draft"] 10 | _state_to = ["open"] 11 | 12 | _tier_validation_manual_config = False 13 | 14 | @api.model 15 | def _get_under_validation_exceptions(self): 16 | res = super()._get_under_validation_exceptions() 17 | res.append("route_id") 18 | return res 19 | -------------------------------------------------------------------------------- /stock_request_tier_validation/models/stock_request_order.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | from odoo import api, models 4 | 5 | 6 | class StockRequestOrder(models.Model): 7 | _name = "stock.request.order" 8 | _inherit = ["stock.request.order", "tier.validation"] 9 | _state_from = ["draft"] 10 | _state_to = ["open"] 11 | 12 | _tier_validation_manual_config = False 13 | 14 | @api.model 15 | def _get_under_validation_exceptions(self): 16 | res = super()._get_under_validation_exceptions() 17 | res.append("route_id") 18 | return res 19 | -------------------------------------------------------------------------------- /stock_request_bom/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | { 4 | "name": "Stock Request BOM", 5 | "summary": "Stock Request with BOM Integration", 6 | "version": "18.0.1.0.1", 7 | "license": "LGPL-3", 8 | "website": "https://github.com/OCA/stock-logistics-request", 9 | "author": "ForgeFlow, Odoo Community Association (OCA)", 10 | "category": "Warehouse Management", 11 | "depends": ["stock_request", "mrp"], 12 | "data": [ 13 | "views/stock_request_order_views.xml", 14 | ], 15 | "installable": True, 16 | "auto_install": True, 17 | } 18 | -------------------------------------------------------------------------------- /stock_request_tier_validation/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | To use this module, you need to: 2 | 3 | 1. Create a Stock Request triggering at least one "Tier Definition". 4 | 2. Click on *Request Validation* button. 5 | 3. Under the tab *Reviews* have a look to pending reviews and their 6 | statuses. 7 | 4. Once all reviews are validated button to *Confirm* will be shown. 8 | 9 | Additional features: 10 | 11 | - You can filter the Stock Request requesting your review through the 12 | filter *Needs my Review*. 13 | - User with rights to confirm the Stock Request (validate all tiers that 14 | would be generated) can directly do the operation, this is, there is 15 | no need for her/him to request a validation. 16 | -------------------------------------------------------------------------------- /stock_request_purchase/models/stock_rule.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com). 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import models 5 | 6 | 7 | class StockRule(models.Model): 8 | _inherit = "stock.rule" 9 | 10 | def _update_purchase_order_line( 11 | self, product_id, product_qty, product_uom, company_id, values, line 12 | ): 13 | vals = super()._update_purchase_order_line( 14 | product_id, product_qty, product_uom, company_id, values, line 15 | ) 16 | if "stock_request_id" in values: 17 | vals["stock_request_ids"] = [(4, values["stock_request_id"])] 18 | return vals 19 | -------------------------------------------------------------------------------- /stock_request/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Jordi Ballester (EFICENT) \<\>. 2 | - Enric Tobella \<\> 3 | - Atte Isopuro \<\> 4 | - Lois Rilo \<\> 5 | - Raul Martin \<\> 6 | - Serpent Consulting Services Pvt. Ltd. \<\> 7 | - [Open Source Integrators](https://www.opensourceintegrators.com) 8 | - Maxime Chambreuil \<\> 9 | - Steve Campbell \<\> 10 | - Héctor Villarreal \<\> 11 | - Kitti U. \<\> 12 | - Bernat Puig \<\> 13 | - Oriol Miranda \<\> 14 | -------------------------------------------------------------------------------- /.ruff.toml: -------------------------------------------------------------------------------- 1 | 2 | target-version = "py310" 3 | fix = true 4 | 5 | [lint] 6 | extend-select = [ 7 | "B", 8 | "C90", 9 | "E501", # line too long (default 88) 10 | "I", # isort 11 | "UP", # pyupgrade 12 | ] 13 | extend-safe-fixes = ["UP008"] 14 | exclude = ["setup/*"] 15 | 16 | [format] 17 | exclude = ["setup/*"] 18 | 19 | [lint.per-file-ignores] 20 | "__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py 21 | "__manifest__.py" = ["B018"] # useless expression 22 | 23 | [lint.isort] 24 | section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"] 25 | 26 | [lint.isort.sections] 27 | "odoo" = ["odoo"] 28 | "odoo-addons" = ["odoo.addons"] 29 | 30 | [lint.mccabe] 31 | max-complexity = 16 32 | -------------------------------------------------------------------------------- /stock_request/data/stock_request_sequence_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stock Request 5 | stock.request 6 | SR/ 7 | 5 8 | 9 | 10 | 11 | Stock Request Order 12 | stock.request.order 13 | SRO/ 14 | 5 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /stock_request_kanban/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | If the barcode does not contain a CRC check digit on the kanban card, 2 | you should: 3 | 4 | - Access on Development mode 5 | - Access 'Settings / Technical / Parameters / System Parameters' 6 | - Create a parameter with name 'stock_request_kanban.crc' and set it to 7 | value to 0 8 | 9 | If the barcode contains a CRC check digit and you want to ignore it: 10 | 11 | - Create a paramenter with name 'stock_request_kanban.ignore_crc' and 12 | set it to value to 1 13 | 14 | If you want to change the format of the QR, you should: 15 | 16 | - Access on Development mode 17 | - Access 'Settings / Technical / Parameters / System Parameters' 18 | - Create a parameter with name 'stock_request_kanban.barcode_format' and 19 | set the format of the barcode 20 | -------------------------------------------------------------------------------- /stock_return_request/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Tecnativa - David Vidal 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | { 4 | "name": "Stock Return Request", 5 | "version": "18.0.1.0.1", 6 | "category": "Stock", 7 | "website": "https://github.com/OCA/stock-logistics-request", 8 | "author": "Tecnativa, " "Odoo Community Association (OCA)", 9 | "license": "AGPL-3", 10 | "application": False, 11 | "installable": True, 12 | "depends": [ 13 | "stock", 14 | ], 15 | "data": [ 16 | "security/ir.model.access.csv", 17 | "data/stock_return_request_data.xml", 18 | "views/stock_return_request_views.xml", 19 | "report/stock_return_report.xml", 20 | "wizard/suggest_return_request.xml", 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /stock_request_kanban/data/stock_request_sequence_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stock Request Kanban 5 | stock.request.kanban 6 | KB 7 | 5 8 | 9 | 10 | 11 | Stock Inventory Kanban 12 | stock.inventory.kanban 13 | IKB 14 | 5 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /stock_request_kanban/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | ## Creation 2 | 3 | - Go to 'Stock Requests / Stock Requests Kanban' and create a new 4 | Kanban. 5 | - Indicate a product, quantity and location. 6 | - Press 'Save'. 7 | - Print the kanban and put it in the storage of the product 8 | 9 | ## Request kanban 10 | 11 | This should be used if you want to create the kanban when the card is 12 | consumed. 13 | 14 | - Once the product is consumed, take the card 15 | - Go to 'Stock Requests / Order Kanban Card' 16 | - Scan the card 17 | - The stock request is created 18 | 19 | ## Request kanban batch 20 | 21 | This should be used when you will store the cards and create request 22 | orders for kanbans later. 23 | 24 | - Once the product is consumed, take the card and store it 25 | - Create a store request order 26 | - Press the scan button 27 | - Scan all the pending kanban cards 28 | -------------------------------------------------------------------------------- /stock_request_purchase/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | { 5 | "name": "Stock Request Purchase", 6 | "summary": "Internal request for stock", 7 | "version": "18.0.1.0.0", 8 | "license": "LGPL-3", 9 | "website": "https://github.com/OCA/stock-logistics-request", 10 | "author": "ForgeFlow, Odoo Community Association (OCA)", 11 | "maintainers": ["LoisRForgeFlow", "etobella"], 12 | "category": "Warehouse Management", 13 | "depends": ["stock_request", "purchase_stock"], 14 | "data": [ 15 | "security/ir.model.access.csv", 16 | "views/stock_request_views.xml", 17 | "views/stock_request_order_views.xml", 18 | "views/purchase_order_views.xml", 19 | ], 20 | "installable": True, 21 | "auto_install": True, 22 | } 23 | -------------------------------------------------------------------------------- /stock_return_request/models/stock_picking.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Tecnativa - David Vidal 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | from odoo import fields, models 4 | 5 | 6 | class StockPicking(models.Model): 7 | _inherit = "stock.picking" 8 | 9 | stock_return_request_id = fields.Many2one( 10 | comodel_name="stock.return.request", 11 | ) 12 | 13 | def _create_backorder(self): 14 | """When we make a backorder of a picking in a return request, we 15 | want to have it linked to the return request itself""" 16 | backorders = super()._create_backorder() 17 | rbo = backorders.filtered("backorder_id.stock_return_request_id") 18 | for backorder in rbo: 19 | backorder.stock_return_request_id = ( 20 | backorder.backorder_id.stock_return_request_id 21 | ) 22 | return backorders 23 | -------------------------------------------------------------------------------- /stock_request_tier_validation/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | { 4 | "name": "Stock Request Tier Validation", 5 | "summary": "Extends the functionality of Stock Requests to " 6 | "support a tier validation process.", 7 | "version": "18.0.1.0.0", 8 | "category": "Warehouse", 9 | "website": "https://github.com/OCA/stock-logistics-request", 10 | "author": "ForgeFlow, Odoo Community Association (OCA)", 11 | "maintainers": ["LoisRForgeFlow", "etobella"], 12 | "license": "AGPL-3", 13 | "application": False, 14 | "installable": True, 15 | "depends": ["stock_request", "base_tier_validation"], 16 | "data": [ 17 | "data/stock_request_tier_definition.xml", 18 | "views/stock_request_order_view.xml", 19 | "views/stock_request_view.xml", 20 | ], 21 | } 22 | -------------------------------------------------------------------------------- /stock_request_kanban/views/stock_request_order_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | stock.request.order.form 5 | stock.request.order 6 | 7 | 8 | 9 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /stock_request_tier_validation/tests/test_stock_request_tier_validation.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2020 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0). 3 | 4 | from odoo.tests import common 5 | 6 | 7 | class TestStockRequest(common.TransactionCase): 8 | @classmethod 9 | def setUpClass(cls): 10 | super().setUpClass() 11 | 12 | # common models 13 | cls.stock_request = cls.env["stock.request"] 14 | cls.request_order = cls.env["stock.request.order"] 15 | cls.tier_definition = cls.env["tier.definition"] 16 | 17 | def test_get_under_validation_exceptions(self): 18 | self.assertIn("route_id", self.stock_request._get_under_validation_exceptions()) 19 | self.assertIn("route_id", self.request_order._get_under_validation_exceptions()) 20 | 21 | def test_get_tier_validation_model_names(self): 22 | self.assertIn( 23 | "stock.request", self.tier_definition._get_tier_validation_model_names() 24 | ) 25 | self.assertIn( 26 | "stock.request.order", 27 | self.tier_definition._get_tier_validation_model_names(), 28 | ) 29 | -------------------------------------------------------------------------------- /stock_request/models/procurement_group.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Open Source Integrators 2 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). 3 | 4 | from odoo import api, models 5 | 6 | 7 | class ProcurementGroup(models.Model): 8 | _inherit = "procurement.group" 9 | 10 | @api.model 11 | def run(self, procurements, raise_user_error=True): 12 | indexes_to_pop = [] 13 | new_procs = [] 14 | for i, procurement in enumerate(procurements): 15 | if "stock_request_id" in procurement.values and procurement.values.get( 16 | "stock_request_id" 17 | ): 18 | req = self.env["stock.request"].browse( 19 | procurement.values.get("stock_request_id") 20 | ) 21 | if req.order_id: 22 | new_procs.append(procurement._replace(origin=req.order_id.name)) 23 | indexes_to_pop.append(i) 24 | if new_procs: 25 | indexes_to_pop.reverse() 26 | for index in indexes_to_pop: 27 | procurements.pop(index) 28 | procurements.extend(new_procs) 29 | return super().run(procurements, raise_user_error=raise_user_error) 30 | -------------------------------------------------------------------------------- /stock_request/models/stock_rule.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2020 ForgeFlow, S.L. 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import models 5 | 6 | 7 | class StockRule(models.Model): 8 | _inherit = "stock.rule" 9 | 10 | def _get_stock_move_values( 11 | self, 12 | product_id, 13 | product_qty, 14 | product_uom, 15 | location_id, 16 | name, 17 | origin, 18 | company_id, 19 | values, 20 | ): 21 | result = super()._get_stock_move_values( 22 | product_id, 23 | product_qty, 24 | product_uom, 25 | location_id, 26 | name, 27 | origin, 28 | company_id, 29 | values, 30 | ) 31 | if values.get("stock_request_id", False): 32 | result["allocation_ids"] = [ 33 | ( 34 | 0, 35 | 0, 36 | { 37 | "stock_request_id": values.get("stock_request_id"), 38 | "requested_product_uom_qty": product_qty, 39 | }, 40 | ) 41 | ] 42 | return result 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | /.venv 5 | /.pytest_cache 6 | /.ruff_cache 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | bin/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | eggs/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | *.eggs 27 | 28 | # Windows installers 29 | *.msi 30 | 31 | # Debian packages 32 | *.deb 33 | 34 | # Redhat packages 35 | *.rpm 36 | 37 | # MacOS packages 38 | *.dmg 39 | *.pkg 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | 53 | # Translations 54 | *.mo 55 | 56 | # Pycharm 57 | .idea 58 | 59 | # Eclipse 60 | .settings 61 | 62 | # Visual Studio cache/options directory 63 | .vs/ 64 | .vscode 65 | 66 | # OSX Files 67 | .DS_Store 68 | 69 | # Django stuff: 70 | *.log 71 | 72 | # Mr Developer 73 | .mr.developer.cfg 74 | .project 75 | .pydevproject 76 | 77 | # Rope 78 | .ropeproject 79 | 80 | # Sphinx documentation 81 | docs/_build/ 82 | 83 | # Backup files 84 | *~ 85 | *.swp 86 | 87 | # OCA rules 88 | !static/lib/ 89 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_request_order_kanban_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | wizard.stock.request.order.kanban.form 10 | wizard.stock.request.order.kanban 11 | primary 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Add Kanban 21 | wizard.stock.request.order.kanban 22 | form 23 | {'default_order_id': active_id} 24 | new 25 | 26 | 27 | -------------------------------------------------------------------------------- /stock_request_purchase/views/stock_request_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.form 7 | stock.request 8 | 9 | 10 |
11 | 16 | 26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /stock_request_purchase/views/stock_request_order_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.order.form 7 | stock.request.order 8 | 9 | 10 |
11 | 16 | 26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /stock_request_tier_validation/views/stock_request_order_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.select - stock_request_tier_validation 7 | stock.request.order 8 | 9 | 10 | 11 | 17 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /stock_request_mrp/views/stock_request_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.form - stock_request_mrp 7 | stock.request 8 | 9 | 10 |
11 | 16 | 26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /stock_request_mrp/views/stock_request_order_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.order.form - stock_request_mrp 7 | stock.request.order 8 | 9 | 10 |
11 | 16 | 26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /stock_request_tier_validation/data/stock_request_tier_definition.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Manager review 7 | 8 | domain 9 | 10 | group 11 | 15 | False 16 | 17 | 18 | Manager review 19 | 20 | domain 21 | 22 | group 23 | 27 | False 28 | 29 | 30 | -------------------------------------------------------------------------------- /stock_request_kanban/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018-22 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | { 5 | "name": "Stock Request kanban", 6 | "version": "18.0.1.0.1", 7 | "category": "Warehouse Management", 8 | "website": "https://github.com/OCA/stock-logistics-request", 9 | "author": "Creu Blanca, ForgeFlow, Odoo Community Association (OCA)", 10 | "maintainers": ["etobella", "LoisRForgeFlow"], 11 | "license": "LGPL-3", 12 | "summary": "Adds a stock request order, and takes stock requests as lines", 13 | "depends": ["stock_request", "barcodes"], 14 | "data": [ 15 | "data/stock_request_sequence_data.xml", 16 | "report/report_paper_format.xml", 17 | "wizard/wizard_stock_inventory_kanban_views.xml", 18 | "wizard/wizard_stock_request_kanban_views.xml", 19 | "wizard/wizard_stock_request_order_kanban_views.xml", 20 | "views/stock_request_order_views.xml", 21 | "views/stock_request_kanban_views.xml", 22 | "views/stock_inventory_kanban_views.xml", 23 | "views/stock_request_menu.xml", 24 | "views/stock_request_views.xml", 25 | "views/product_views.xml", 26 | "report/stock_request_kanban_templates.xml", 27 | "security/ir.model.access.csv", 28 | ], 29 | "installable": True, 30 | "application": False, 31 | } 32 | -------------------------------------------------------------------------------- /stock_request_tier_validation/views/stock_request_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.select - stock_request_tier_validation 7 | stock.request 8 | 9 | 10 | 11 | 12 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_inventory_kanban.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # Copyright 2017-2024 ForgeFlow, S.L. 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | from odoo import fields, models 6 | 7 | 8 | class WizardStockInventoryKanban(models.TransientModel): 9 | _name = "wizard.stock.inventory.kanban" 10 | _description = "Stock Inventory Kanban Wizard" 11 | _inherit = "wizard.stock.request.kanban.abstract" 12 | 13 | inventory_kanban_id = fields.Many2one("stock.inventory.kanban", readonly=True) 14 | 15 | def barcode_ending(self): 16 | res = super().barcode_ending() 17 | self.inventory_kanban_id.write({"scanned_kanban_ids": [(4, self.kanban_id.id)]}) 18 | return res 19 | 20 | def validate_kanban(self, barcode): 21 | res = super().validate_kanban(barcode) 22 | if not self.inventory_kanban_id.kanban_ids.filtered( 23 | lambda r: r == self.kanban_id 24 | ): 25 | self.status = self.env._("Barcode %s is not in the inventory") % barcode 26 | self.status_state = 1 27 | return False 28 | if self.inventory_kanban_id.scanned_kanban_ids.filtered( 29 | lambda r: r == self.kanban_id 30 | ): 31 | self.status = self.env._("Barcode %s is already scanned") % barcode 32 | self.status_state = 1 33 | return False 34 | return res 35 | -------------------------------------------------------------------------------- /stock_request/views/stock_move_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | stock.move.form 5 | stock.move 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /stock_request/views/stock_request_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 16 | 24 | 31 | 37 | 45 | 46 | -------------------------------------------------------------------------------- /stock_request/models/stock_picking.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2020 ForgeFlow, S.L. 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class StockPicking(models.Model): 8 | _inherit = "stock.picking" 9 | 10 | stock_request_ids = fields.One2many( 11 | comodel_name="stock.request", 12 | string="Stock Requests", 13 | compute="_compute_stock_request_ids", 14 | ) 15 | stock_request_count = fields.Integer( 16 | "Stock Request #", compute="_compute_stock_request_ids" 17 | ) 18 | 19 | @api.depends("move_ids") 20 | def _compute_stock_request_ids(self): 21 | for rec in self: 22 | rec.stock_request_ids = rec.move_ids.mapped("stock_request_ids") 23 | rec.stock_request_count = len(rec.stock_request_ids) 24 | 25 | def action_view_stock_request(self): 26 | """ 27 | :return dict: dictionary value for created view 28 | """ 29 | action = self.env["ir.actions.act_window"]._for_xml_id( 30 | "stock_request.action_stock_request_form" 31 | ) 32 | 33 | requests = self.mapped("stock_request_ids") 34 | if len(requests) > 1: 35 | action["domain"] = [("id", "in", requests.ids)] 36 | elif requests: 37 | action["views"] = [ 38 | (self.env.ref("stock_request.view_stock_request_form").id, "form") 39 | ] 40 | action["res_id"] = requests.id 41 | return action 42 | -------------------------------------------------------------------------------- /stock_request/models/res_config_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class ResConfigSettings(models.TransientModel): 8 | _inherit = "res.config.settings" 9 | 10 | group_stock_request_order = fields.Boolean( 11 | implied_group="stock_request.group_stock_request_order" 12 | ) 13 | 14 | module_stock_request_purchase = fields.Boolean( 15 | string="Stock Requests for Purchases" 16 | ) 17 | 18 | module_stock_request_kanban = fields.Boolean( 19 | string="Stock Requests Kanban integration" 20 | ) 21 | 22 | stock_request_check_available_first = fields.Boolean( 23 | related="company_id.stock_request_check_available_first", readonly=False 24 | ) 25 | stock_request_allow_virtual_loc = fields.Boolean( 26 | related="company_id.stock_request_allow_virtual_loc", readonly=False 27 | ) 28 | 29 | module_stock_request_analytic = fields.Boolean( 30 | string="Stock Requests Analytic integration" 31 | ) 32 | 33 | module_stock_request_submit = fields.Boolean( 34 | string="Submitted state in Stock Requests" 35 | ) 36 | 37 | module_stock_request_mrp = fields.Boolean(string="Stock Request for Manufacturing") 38 | 39 | # Dependencies 40 | @api.onchange("stock_request_allow_virtual_loc") 41 | def _onchange_stock_request_allow_virtual_loc(self): 42 | if self.stock_request_allow_virtual_loc: 43 | self.group_stock_multi_locations = True 44 | -------------------------------------------------------------------------------- /stock_request/views/product.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Request Stock 5 | ir.actions.server 6 | code 7 | 12 | 13 | 14 | 15 | action = records.env['stock.request.order']._create_from_product_multiselect(records) 16 | 17 | 18 | 22 | Request Stock 23 | ir.actions.server 24 | code 25 | 30 | 31 | 32 | 33 | action = records.env['stock.request.order']._create_from_product_multiselect(records) 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /stock_request/models/stock_location.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 ForgeFlow, S.L. 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import _, api, models 5 | from odoo.exceptions import ValidationError 6 | 7 | 8 | class StockLocation(models.Model): 9 | _inherit = "stock.location" 10 | 11 | @api.constrains("company_id") 12 | def _check_company_stock_request(self): 13 | if any( 14 | rec.company_id 15 | and self.env["stock.request"].search( 16 | [("company_id", "!=", rec.company_id.id), ("location_id", "=", rec.id)], 17 | limit=1, 18 | ) 19 | for rec in self 20 | ): 21 | raise ValidationError( 22 | _( 23 | "You cannot change the company of the location, as it is " 24 | "already assigned to stock requests that belong to " 25 | "another company." 26 | ) 27 | ) 28 | if any( 29 | rec.company_id 30 | and self.env["stock.request.order"].search( 31 | [ 32 | ("company_id", "!=", rec.company_id.id), 33 | ("warehouse_id", "=", rec.id), 34 | ], 35 | limit=1, 36 | ) 37 | for rec in self 38 | ): 39 | raise ValidationError( 40 | _( 41 | "You cannot change the company of the location, as it is " 42 | "already assigned to stock request orders that belong to " 43 | "another company." 44 | ) 45 | ) 46 | -------------------------------------------------------------------------------- /stock_request_kanban/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_stock_request_kanban_user,stock request kanban user,model_stock_request_kanban,stock_request.group_stock_request_user,1,1,1, 3 | access_stock_request_kanban_manager,stock request kanban manager,model_stock_request_kanban,stock_request.group_stock_request_manager,1,1,1,1 4 | access_stock_inventory_kanban_user,stock inventory kanban user,model_stock_inventory_kanban,stock_request.group_stock_request_user,1,1,1, 5 | access_stock_inventory_kanban_manager,stock inventory kanban manager,model_stock_inventory_kanban,stock_request.group_stock_request_manager,1,1,1,1 6 | access_wizard_stock_request_kanban_user,wizard stock request kanban user,model_wizard_stock_request_kanban,stock_request.group_stock_request_user,1,1,1, 7 | access_wizard_stock_request_kanban_manager,wizard stock request kanban manager,model_wizard_stock_request_kanban,stock_request.group_stock_request_manager,1,1,1,1 8 | access_wizard_stock_inventory_kanban_user,wizard stock inventory kanban user,model_wizard_stock_inventory_kanban,stock_request.group_stock_request_user,1,1,1, 9 | access_wizard_stock_inventory_kanban_manager,wizard stock inventory kanban manager,model_wizard_stock_inventory_kanban,stock_request.group_stock_request_manager,1,1,1,1 10 | access_wizard_stock_request_order_kanban_user,wizard stock request order kanban user,model_wizard_stock_request_order_kanban,stock_request.group_stock_request_user,1,1,1, 11 | access_wizard_stock_request_order_kanban_manager,wizard stock request order kanban manager,model_wizard_stock_request_order_kanban,stock_request.group_stock_request_manager,1,1,1,1 12 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_request_kanban_abstract.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # Copyright 2017-2024 ForgeFlow, S.L. 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | from odoo import fields, models 6 | 7 | 8 | class WizardStockRequestKanbanAbstract(models.AbstractModel): 9 | _name = "wizard.stock.request.kanban.abstract" 10 | _description = "Stock Request Kanban Abstract Wizard" 11 | _inherit = "barcodes.barcode_events_mixin" 12 | 13 | kanban_id = fields.Many2one("stock.request.kanban", readonly=True) 14 | status = fields.Text(readonly=True, default="Start scanning") 15 | status_state = fields.Integer(default=0, readonly=True) 16 | 17 | def on_barcode_scanned(self, barcode): 18 | self.kanban_id = self.env["stock.request.kanban"].search_barcode(barcode) 19 | if not self.kanban_id: 20 | self.status = ( 21 | self.env._( 22 | "Barcode %s does not correspond to any " 23 | "Kanban. Try with another barcode or " 24 | "press Close to finish scanning." 25 | ) 26 | % barcode 27 | ) 28 | self.status_state = 1 29 | return 30 | if self.validate_kanban(barcode): 31 | self.status_state = 0 32 | self.barcode_ending() 33 | return 34 | 35 | def barcode_ending(self): 36 | pass 37 | 38 | def validate_kanban(self, barcode): 39 | """ 40 | It must return True if the kanban is valid, False otherwise 41 | :param barcode: 42 | :return: 43 | """ 44 | return True 45 | -------------------------------------------------------------------------------- /stock_request/models/stock_warehouse.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 ForgeFlow, S.L. 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import _, api, models 5 | from odoo.exceptions import ValidationError 6 | 7 | 8 | class StockWarehouse(models.Model): 9 | _inherit = "stock.warehouse" 10 | 11 | @api.constrains("company_id") 12 | def _check_company_stock_request(self): 13 | if any( 14 | self.env["stock.request"].search( 15 | [ 16 | ("company_id", "!=", rec.company_id.id), 17 | ("warehouse_id", "=", rec.id), 18 | ], 19 | limit=1, 20 | ) 21 | for rec in self 22 | ): 23 | raise ValidationError( 24 | _( 25 | "You cannot change the company of the warehouse, as it is " 26 | "already assigned to stock requests that belong to " 27 | "another company." 28 | ) 29 | ) 30 | if any( 31 | self.env["stock.request.order"].search( 32 | [ 33 | ("company_id", "!=", rec.company_id.id), 34 | ("warehouse_id", "=", rec.id), 35 | ], 36 | limit=1, 37 | ) 38 | for rec in self 39 | ): 40 | raise ValidationError( 41 | _( 42 | "You cannot change the company of the warehouse, as it is " 43 | "already assigned to stock request orders that belong to " 44 | "another company." 45 | ) 46 | ) 47 | -------------------------------------------------------------------------------- /stock_return_request/wizard/suggest_return_request_lot.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Tecnativa - David Vidal 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | from odoo import api, fields, models 4 | 5 | 6 | class SuggestReturnRequestLot(models.TransientModel): 7 | _name = "suggest.return.request.lot" 8 | _description = "Suggest lots for the return request line" 9 | 10 | request_line_id = fields.Many2one( 11 | comodel_name="stock.return.request.line", 12 | required=True, 13 | readonly=True, 14 | ondelete="cascade", 15 | ) 16 | lot_suggestion_mode = fields.Selection( 17 | selection=[ 18 | ("sum", "Total by lot"), 19 | ("detail", "Total by move"), 20 | ], 21 | default="sum", 22 | ) 23 | suggested_lot_id = fields.Many2one("suggest.return.request.lot.line") 24 | 25 | @api.onchange("lot_suggestion_mode") 26 | def _onchange_lot_suggestion_mode(self): 27 | self.suggested_lot_id = False 28 | 29 | def action_confirm(self): 30 | self.request_line_id.lot_id = self.suggested_lot_id.lot_id.id 31 | 32 | 33 | class SuggestReturnRequestLotLine(models.TransientModel): 34 | _name = "suggest.return.request.lot.line" 35 | _description = "Suggest lots for the return request line" 36 | 37 | wizard_id = fields.Many2one( 38 | comodel_name="suggest.return.request.lot", 39 | ondelete="cascade", 40 | ) 41 | lot_id = fields.Many2one(comodel_name="stock.lot") 42 | name = fields.Char() 43 | lot_suggestion_mode = fields.Selection( 44 | selection=[ 45 | ("sum", "Total by lot"), 46 | ("detail", "Total by move"), 47 | ] 48 | ) 49 | -------------------------------------------------------------------------------- /stock_request_mrp/models/stock_request_order.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020-24 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class StockRequestOrder(models.Model): 8 | _inherit = "stock.request.order" 9 | 10 | production_ids = fields.One2many( 11 | "mrp.production", 12 | compute="_compute_production_ids", 13 | string="Manufacturing Orders", 14 | readonly=True, 15 | ) 16 | production_count = fields.Integer( 17 | string="Manufacturing Orders count", 18 | compute="_compute_production_ids", 19 | readonly=True, 20 | ) 21 | 22 | @api.depends("stock_request_ids") 23 | def _compute_production_ids(self): 24 | for req in self: 25 | req.production_ids = req.stock_request_ids.mapped("production_ids") 26 | req.production_count = len(req.production_ids) 27 | 28 | def action_view_mrp_production(self): 29 | action = self.env["ir.actions.act_window"]._for_xml_id( 30 | "mrp.mrp_production_action" 31 | ) 32 | productions = self.mapped("production_ids") 33 | if len(productions) > 1: 34 | action["domain"] = [("id", "in", productions.ids)] 35 | action["views"] = [ 36 | (self.env.ref("mrp.mrp_production_tree_view").id, "list"), 37 | (self.env.ref("mrp.mrp_production_form_view").id, "form"), 38 | ] 39 | elif productions: 40 | action["views"] = [ 41 | (self.env.ref("mrp.mrp_production_form_view").id, "form") 42 | ] 43 | action["res_id"] = productions.id 44 | return action 45 | -------------------------------------------------------------------------------- /stock_request_purchase/models/purchase_order.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class PurchaseOrder(models.Model): 8 | _inherit = "purchase.order" 9 | 10 | stock_request_ids = fields.Many2many( 11 | comodel_name="stock.request", 12 | string="Stock Requests", 13 | compute="_compute_stock_request_ids", 14 | ) 15 | stock_request_count = fields.Integer( 16 | "Stock Request #", compute="_compute_stock_request_ids" 17 | ) 18 | 19 | @api.depends("order_line") 20 | def _compute_stock_request_ids(self): 21 | for rec in self: 22 | rec.stock_request_ids = rec.order_line.mapped("stock_request_ids") 23 | rec.stock_request_count = len(rec.stock_request_ids) 24 | 25 | def _get_stock_requests(self): 26 | """Get all stock requests from action (allows inheritance by other modules).""" 27 | return self.mapped("stock_request_ids") 28 | 29 | def action_view_stock_request(self): 30 | """ 31 | :return dict: dictionary value for created view 32 | """ 33 | action = self.env["ir.actions.act_window"]._for_xml_id( 34 | "stock_request.action_stock_request_form" 35 | ) 36 | 37 | requests = self._get_stock_requests() 38 | if len(requests) > 1: 39 | action["domain"] = [("id", "in", requests.ids)] 40 | elif requests: 41 | action["views"] = [ 42 | (self.env.ref("stock_request.view_stock_request_form").id, "form") 43 | ] 44 | action["res_id"] = requests.id 45 | return action 46 | -------------------------------------------------------------------------------- /stock_return_request/wizard/suggest_return_request.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Suggested Lots for this Return Request Line 5 | suggest.return.request.lot 6 | 7 |
8 | 9 | 10 | 11 | 18 |
19 |
27 | 28 |
29 |
30 | 31 | 35 | Suggested Lots for this Return Request Line 36 | suggest.return.request.lot 37 | form 38 | new 39 | 40 |
41 | -------------------------------------------------------------------------------- /stock_request_bom/i18n/stock_request_bom.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_bom 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: stock_request_bom 17 | #. odoo-python 18 | #: code:addons/stock_request_bom/models/stock_request_order.py:0 19 | msgid "No BOM found for the selected product." 20 | msgstr "" 21 | 22 | #. module: stock_request_bom 23 | #: model:ir.model.fields,field_description:stock_request_bom.field_stock_request_order__product_bom_id 24 | msgid "Product BOM" 25 | msgstr "" 26 | 27 | #. module: stock_request_bom 28 | #: model:ir.model.fields,field_description:stock_request_bom.field_stock_request_order__quantity_bom 29 | msgid "Quantity BOM" 30 | msgstr "" 31 | 32 | #. module: stock_request_bom 33 | #: model:ir.model.fields,help:stock_request_bom.field_stock_request_order__product_bom_id 34 | msgid "Select a product with a BOM to auto-complete stock request lines." 35 | msgstr "" 36 | 37 | #. module: stock_request_bom 38 | #: model:ir.model.fields,help:stock_request_bom.field_stock_request_order__quantity_bom 39 | msgid "Specify the quantity for the Product BOM." 40 | msgstr "" 41 | 42 | #. module: stock_request_bom 43 | #: model:ir.model,name:stock_request_bom.model_stock_request_order 44 | msgid "Stock Request Order" 45 | msgstr "" 46 | 47 | #. module: stock_request_bom 48 | #. odoo-python 49 | #: code:addons/stock_request_bom/models/stock_request_order.py:0 50 | msgid "The quantity BOM must be a positive value." 51 | msgstr "" 52 | -------------------------------------------------------------------------------- /stock_request_mrp/views/mrp_production_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | mrp.production.form.inherit.stock.request.mrp - stock_request_mrp 9 | mrp.production 10 | 11 | 12 | 13 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /stock_return_request/models/stock_move.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Tecnativa - David Vidal 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | from odoo import fields, models 4 | 5 | 6 | class StockMove(models.Model): 7 | _inherit = "stock.move" 8 | 9 | qty_returnable = fields.Float( 10 | digits="Product Unit of Measure", 11 | string="Returnable Quantity", 12 | compute="_compute_qty_returnable", 13 | ) 14 | 15 | def _compute_qty_returnable(self): 16 | """Looks for chained returned moves to compute how much quantity 17 | from the original can be returned""" 18 | self.qty_returnable = 0 19 | for move in self.filtered(lambda x: x.state not in ["draft", "cancel"]): 20 | if not move.returned_move_ids: 21 | if move.state == "done": 22 | move.qty_returnable = move.quantity 23 | continue 24 | move.qty_returnable = move.quantity - sum( 25 | move.returned_move_ids.mapped("qty_returnable") 26 | ) 27 | 28 | def _get_lot_returnable_qty(self, lot_id, qty=0): 29 | """Looks for chained returned moves to compute how much quantity 30 | from the original can be returned for a given lot""" 31 | for move in self.filtered(lambda x: x.state not in ["draft", "cancel"]): 32 | mls = move.move_line_ids.filtered(lambda x: x.lot_id == lot_id) 33 | qty += sum(mls.mapped("quantity")) 34 | qty -= move.returned_move_ids._get_lot_returnable_qty(lot_id) 35 | return qty 36 | 37 | def _action_assign(self): 38 | if self.env.context.get("skip_assign_move", False): 39 | # Avoid assign stock moves allowing create stock move lines manually 40 | return 41 | return super()._action_assign() 42 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit.yml: -------------------------------------------------------------------------------- 1 | name: pre-commit 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "18.0*" 7 | push: 8 | branches: 9 | - "18.0" 10 | - "18.0-ocabot-*" 11 | 12 | jobs: 13 | pre-commit: 14 | runs-on: ubuntu-22.04 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/setup-python@v5 18 | with: 19 | python-version: "3.11" 20 | - name: Get python version 21 | run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV 22 | - uses: actions/cache@v4 23 | with: 24 | path: ~/.cache/pre-commit 25 | key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} 26 | - name: Install pre-commit 27 | run: pip install pre-commit 28 | - name: Run pre-commit 29 | run: pre-commit run --all-files --show-diff-on-failure --color=always 30 | env: 31 | # Consider valid a PR that changes README fragments but doesn't 32 | # change the README.rst file itself. It's not really a problem 33 | # because the bot will update it anyway after merge. This way, we 34 | # lower the barrier for functional contributors that want to fix the 35 | # readme fragments, while still letting developers get README 36 | # auto-generated (which also helps functionals when using runboat). 37 | # DOCS https://pre-commit.com/#temporarily-disabling-hooks 38 | SKIP: oca-gen-addon-readme 39 | - name: Check that all files generated by pre-commit are in git 40 | run: | 41 | newfiles="$(git ls-files --others --exclude-from=.gitignore)" 42 | if [ "$newfiles" != "" ] ; then 43 | echo "Please check-in the following files:" 44 | echo "$newfiles" 45 | exit 1 46 | fi 47 | -------------------------------------------------------------------------------- /stock_request_purchase/models/stock_request_order.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class StockRequestOrder(models.Model): 8 | _inherit = "stock.request.order" 9 | 10 | purchase_ids = fields.One2many( 11 | "purchase.order", 12 | compute="_compute_purchase_ids", 13 | string="Purchase Orders", 14 | readonly=True, 15 | ) 16 | purchase_count = fields.Integer(compute="_compute_purchase_ids", readonly=True) 17 | purchase_line_ids = fields.Many2many( 18 | "purchase.order.line", 19 | compute="_compute_purchase_ids", 20 | string="Purchase Order Lines", 21 | readonly=True, 22 | copy=False, 23 | ) 24 | 25 | @api.depends("stock_request_ids") 26 | def _compute_purchase_ids(self): 27 | for req in self: 28 | req.purchase_ids = req.stock_request_ids.mapped("purchase_ids") 29 | req.purchase_line_ids = req.stock_request_ids.mapped("purchase_line_ids") 30 | req.purchase_count = len(req.purchase_ids) 31 | 32 | def action_view_purchase(self): 33 | action = self.env["ir.actions.act_window"]._for_xml_id("purchase.purchase_rfq") 34 | purchases = self.mapped("purchase_ids") 35 | if len(purchases) > 1: 36 | action["domain"] = [("id", "in", purchases.ids)] 37 | action["views"] = [ 38 | (self.env.ref("purchase.purchase_order_tree").id, "list"), 39 | (self.env.ref("purchase.purchase_order_form").id, "form"), 40 | ] 41 | elif purchases: 42 | action["views"] = [ 43 | (self.env.ref("purchase.purchase_order_form").id, "form") 44 | ] 45 | action["res_id"] = purchases.id 46 | return action 47 | -------------------------------------------------------------------------------- /stock_request_kanban/models/product.py: -------------------------------------------------------------------------------- 1 | from odoo import fields, models 2 | 3 | 4 | class ProductTemplate(models.Model): 5 | _inherit = "product.template" 6 | 7 | kanban_card_count = fields.Integer( 8 | "# Kanban Cards", compute="_compute_kanban_card_count", compute_sudo=False 9 | ) 10 | 11 | def _compute_kanban_card_count(self): 12 | for product in self: 13 | count = 0 14 | for variant in product.product_variant_ids: 15 | count += self.env["stock.request.kanban"].search_count( 16 | [("product_id", "=", variant.id)] 17 | ) 18 | product.kanban_card_count = count 19 | 20 | def action_view_kanban_cards(self): 21 | self.ensure_one() 22 | action = self.env["ir.actions.act_window"]._for_xml_id( 23 | "stock_request_kanban.stock_request_kanban_action" 24 | ) 25 | action["context"] = {"default_product_id": self.product_variant_id.id} 26 | action["domain"] = [ 27 | ("active", "=", True), 28 | ("product_template_id", "=", self.id), 29 | ] 30 | return action 31 | 32 | 33 | class ProductProduct(models.Model): 34 | _inherit = "product.product" 35 | 36 | kanban_card_count = fields.Integer( 37 | "# Kanban Cards", compute="_compute_kanban_card_count", compute_sudo=False 38 | ) 39 | 40 | def _compute_kanban_card_count(self): 41 | for product in self: 42 | product.kanban_card_count += self.env["stock.request.kanban"].search_count( 43 | [("product_id", "=", product.id)] 44 | ) 45 | 46 | def action_view_kanban_cards(self): 47 | self.ensure_one() 48 | action = self.env["ir.actions.act_window"]._for_xml_id( 49 | "stock_request_kanban.stock_request_kanban_action" 50 | ) 51 | action["context"] = {"default_product_id": self.id} 52 | action["domain"] = [("active", "=", True), ("product_id", "=", self.id)] 53 | return action 54 | -------------------------------------------------------------------------------- /stock_request/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_stock_request_user,stock request user,model_stock_request,group_stock_request_user,1,1,1,1 3 | access_stock_request_manager,stock request manager,model_stock_request,group_stock_request_manager,1,1,1,1 4 | access_stock_request_stock_user,stock.request stock user,model_stock_request,stock.group_stock_user,1,0,0,0 5 | access_stock_request_allocation_user,stock request allocation user,model_stock_request_allocation,group_stock_request_user,1,1,1,1 6 | access_stock_request_allocation_manager,stock request allocation manager,model_stock_request_allocation,group_stock_request_manager,1,1,1,1 7 | access_stock_request_allocation_stock_user,stock.request.allocation stock user,model_stock_request_allocation,base.group_user,1,0,0,0 8 | access_stock_location_user,stock.location.user,stock.model_stock_location,group_stock_request_user,1,0,0,0 9 | access_stock_location_request_manager,stock.location request manager,stock.model_stock_location,group_stock_request_manager,1,0,0,0 10 | access_stock_rule_request_manager,stock_rule_request_manager,stock.model_stock_rule,group_stock_request_manager,1,0,0,0 11 | access_stock_rule_user,stock_rule_user,stock.model_stock_rule,group_stock_request_user,1,0,0,0 12 | access_stock_request_order_user,stock request user,model_stock_request_order,group_stock_request_user,1,1,1,0 13 | access_stock_request_order_manager,stock request manager,model_stock_request_order,group_stock_request_manager,1,1,1,1 14 | access_stock_request_user_warehouse,stock request user Warehouse,stock.model_stock_warehouse,group_stock_request_user,1,0,0,0 15 | access_stock_request_manager_warehouse,stock request manager Warehouse,stock.model_stock_warehouse,group_stock_request_manager,1,0,0,0 16 | access_stock_request_user_stock_move,stock request user stock move,stock.model_stock_move,group_stock_request_user,1,0,0,0 17 | access_stock_request_manager_stock_move,stock request manager stock move,stock.model_stock_move,group_stock_request_manager,1,0,0,0 18 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_request_kanban.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # Copyright 2017-2024 ForgeFlow, S.L. 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | from odoo import fields, models 6 | 7 | 8 | class WizardStockRequestKanban(models.TransientModel): 9 | _name = "wizard.stock.request.kanban" 10 | _description = "Stock Request Kanban Wizard" 11 | _inherit = "wizard.stock.request.kanban.abstract" 12 | 13 | stock_request_id = fields.Many2one("stock.request", readonly=True) 14 | 15 | def barcode_ending(self): 16 | res = super().barcode_ending() 17 | self.stock_request_id = self.env["stock.request"].create( 18 | self.stock_request_kanban_values() 19 | ) 20 | self.stock_request_ending() 21 | self.update_status() 22 | return res 23 | 24 | def stock_request_ending(self): 25 | self.stock_request_id.action_confirm() 26 | 27 | def update_status(self): 28 | self.update( 29 | { 30 | "status_state": 0, 31 | "status": self.env._( 32 | "Added kanban %(kanban)s for product %(product)s", 33 | kanban=self.stock_request_id.kanban_id.name, 34 | product=self.stock_request_id.product_id.display_name, 35 | ), 36 | } 37 | ) 38 | 39 | def stock_request_kanban_values(self): 40 | return { 41 | "company_id": self.kanban_id.company_id.id, 42 | "procurement_group_id": self.kanban_id.procurement_group_id.id or False, 43 | "location_id": self.kanban_id.location_id.id or False, 44 | "warehouse_id": self.kanban_id.warehouse_id.id or False, 45 | "product_id": self.kanban_id.product_id.id, 46 | "product_uom_id": self.kanban_id.product_uom_id.id or False, 47 | "route_id": self.kanban_id.route_id.id or False, 48 | "product_uom_qty": self.kanban_id.product_uom_qty, 49 | "kanban_id": self.kanban_id.id, 50 | } 51 | -------------------------------------------------------------------------------- /stock_request_mrp/models/stock_request.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020-24 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | from odoo.exceptions import ValidationError 6 | 7 | 8 | class StockRequest(models.Model): 9 | _inherit = "stock.request" 10 | 11 | production_ids = fields.Many2many( 12 | "mrp.production", 13 | "mrp_production_stock_request_rel", 14 | "stock_request_id", 15 | "mrp_production_id", 16 | string="Manufacturing Orders", 17 | readonly=True, 18 | copy=False, 19 | ) 20 | production_count = fields.Integer( 21 | string="Manufacturing Orders count", 22 | compute="_compute_production_ids", 23 | readonly=True, 24 | ) 25 | 26 | @api.depends("production_ids") 27 | def _compute_production_ids(self): 28 | for request in self: 29 | request.production_count = len(request.production_ids) 30 | 31 | @api.constrains("production_ids", "company_id") 32 | def _check_production_company_constrains(self): 33 | if any( 34 | any( 35 | production.company_id != req.company_id 36 | for production in req.production_ids 37 | ) 38 | for req in self 39 | ): 40 | raise ValidationError( 41 | self.env._( 42 | "You have linked to a Manufacture Order " 43 | "that belongs to another company." 44 | ) 45 | ) 46 | 47 | def action_view_mrp_production(self): 48 | action = self.env["ir.actions.act_window"]._for_xml_id( 49 | "mrp.mrp_production_action" 50 | ) 51 | productions = self.mapped("production_ids") 52 | if len(productions) > 1: 53 | action["domain"] = [("id", "in", productions.ids)] 54 | elif productions: 55 | action["views"] = [ 56 | (self.env.ref("mrp.mrp_production_form_view").id, "form") 57 | ] 58 | action["res_id"] = productions.id 59 | return action 60 | -------------------------------------------------------------------------------- /stock_request_bom/i18n/it.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_bom 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2025-09-04 12:43+0000\n" 10 | "Last-Translator: mymage \n" 11 | "Language-Team: none\n" 12 | "Language: it\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 5.10.4\n" 18 | 19 | #. module: stock_request_bom 20 | #. odoo-python 21 | #: code:addons/stock_request_bom/models/stock_request_order.py:0 22 | msgid "No BOM found for the selected product." 23 | msgstr "Nessuna DiBa trovata per il prodotto selezionato." 24 | 25 | #. module: stock_request_bom 26 | #: model:ir.model.fields,field_description:stock_request_bom.field_stock_request_order__product_bom_id 27 | msgid "Product BOM" 28 | msgstr "DiBa prodotto" 29 | 30 | #. module: stock_request_bom 31 | #: model:ir.model.fields,field_description:stock_request_bom.field_stock_request_order__quantity_bom 32 | msgid "Quantity BOM" 33 | msgstr "DiBa quantità" 34 | 35 | #. module: stock_request_bom 36 | #: model:ir.model.fields,help:stock_request_bom.field_stock_request_order__product_bom_id 37 | msgid "Select a product with a BOM to auto-complete stock request lines." 38 | msgstr "" 39 | "Selezionare un prodotto con una DiBa per auto completare le righe richiesta " 40 | "magazzino." 41 | 42 | #. module: stock_request_bom 43 | #: model:ir.model.fields,help:stock_request_bom.field_stock_request_order__quantity_bom 44 | msgid "Specify the quantity for the Product BOM." 45 | msgstr "Indicare la quantità per la DiBa prodotto." 46 | 47 | #. module: stock_request_bom 48 | #: model:ir.model,name:stock_request_bom.model_stock_request_order 49 | msgid "Stock Request Order" 50 | msgstr "Ordine richiesta di magazzino" 51 | 52 | #. module: stock_request_bom 53 | #. odoo-python 54 | #: code:addons/stock_request_bom/models/stock_request_order.py:0 55 | msgid "The quantity BOM must be a positive value." 56 | msgstr "La quantità DiBa deve essere un valore positivo." 57 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_request_kanban_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | wizard.stock.request.kanban.form 10 | wizard.stock.request.kanban 11 | 12 |
13 | 23 | 33 | 34 | 35 | 36 |
37 |
44 | 45 |
46 |
47 | 48 | Add Kanban 49 | wizard.stock.request.kanban 50 | form 51 | new 52 | 53 |
54 | -------------------------------------------------------------------------------- /stock_request_kanban/models/stock_request_kanban.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Creu Blanca 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from reportlab.graphics.barcode import getCodes 5 | 6 | from odoo import api, fields, models 7 | from odoo.exceptions import ValidationError 8 | 9 | 10 | class StockRequestKanban(models.Model): 11 | _name = "stock.request.kanban" 12 | _description = "Stock Request Kanban" 13 | _inherit = "stock.request.abstract" 14 | 15 | active = fields.Boolean(default=True) 16 | product_template_id = fields.Many2one(related="product_id.product_tmpl_id") 17 | image_128 = fields.Image(related="product_id.image_128") 18 | 19 | @api.model_create_multi 20 | def create(self, vals_list): 21 | for vals in vals_list: 22 | if vals.get("name", "/") == "/": 23 | vals["name"] = self.env["ir.sequence"].next_by_code( 24 | "stock.request.kanban" 25 | ) 26 | return super().create(vals_list) 27 | 28 | @api.model 29 | def get_barcode_format(self): 30 | return ( 31 | self.env["ir.config_parameter"] 32 | .sudo() 33 | .get_param("stock_request_kanban.barcode_format", default="Standard39") 34 | ) 35 | 36 | @api.model 37 | def _recompute_barcode(self, barcode): 38 | if ( 39 | self.env["ir.config_parameter"] 40 | .sudo() 41 | .get_param("stock_request_kanban.crc", default="1") 42 | == "0" 43 | ): 44 | return barcode 45 | if ( 46 | self.env["ir.config_parameter"] 47 | .sudo() 48 | .get_param("stock_request_kanban.ignore_crc", default="0") 49 | == "0" 50 | ): 51 | bcc = getCodes()[self.get_barcode_format()](value=barcode[:-1]) 52 | bcc.validate() 53 | bcc.encode() 54 | if bcc.encoded[1:-1] != barcode: 55 | raise ValidationError(self.env._("CRC is not valid")) 56 | return barcode[:-1] 57 | 58 | @api.model 59 | def search_barcode(self, barcode): 60 | recomputed_barcode = self._recompute_barcode(barcode) 61 | return self.env["stock.request.kanban"].search( 62 | [("name", "ilike", recomputed_barcode)] 63 | ) 64 | -------------------------------------------------------------------------------- /stock_request_kanban/views/product_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | product.product.stock.request.kanban 7 | product.product 8 | 9 | 10 |
11 | 25 |
26 |
27 |
28 | 29 | product.template.stock.request.kanban 30 | product.template 31 | 32 | 33 |
34 | 48 |
49 |
50 |
51 |
52 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_inventory_kanban_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | wizard.stock.inventory.kanban.form 10 | wizard.stock.inventory.kanban 11 | 12 |
13 | 23 | 33 | 34 | 35 | 36 |
37 |
44 | 45 |
46 |
47 | 48 | Add Kanban 49 | wizard.stock.inventory.kanban 50 | form 51 | {'default_inventory_kanban_id': active_id} 52 | new 53 | 54 |
55 | -------------------------------------------------------------------------------- /stock_request_purchase/views/purchase_order_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | purchase.order.form 7 | purchase.order 8 | 9 | 10 | 11 | 26 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | purchase.order.line.form2 40 | purchase.order.line 41 | 42 | 43 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /stock_request_kanban/wizard/wizard_stock_request_order_kanban.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # Copyright 2017-2024 ForgeFlow, S.L. 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | from odoo import fields, models 6 | from odoo.exceptions import ValidationError 7 | 8 | 9 | class WizardStockRequestOrderKanban(models.TransientModel): 10 | _name = "wizard.stock.request.order.kanban" 11 | _description = "Stock Request Order Kanban Wizard" 12 | _inherit = "wizard.stock.request.kanban" 13 | 14 | order_id = fields.Many2one("stock.request.order", required=True) 15 | 16 | def validate_kanban(self, barcode): 17 | res = super().validate_kanban(barcode) 18 | if self.order_id.stock_request_ids.filtered( 19 | lambda r: r.kanban_id == self.kanban_id 20 | ): 21 | self.status = self.env._("Barcode %s is on the order") % barcode 22 | self.status_state = 1 23 | return False 24 | if self.order_id.state != "draft": 25 | raise ValidationError( 26 | self.env._("Lines only can be added on orders with draft state") 27 | ) 28 | if not self.order_id.company_id: 29 | self.order_id.company_id = self.kanban_id.company_id 30 | elif self.order_id.company_id != self.kanban_id.company_id: 31 | raise ValidationError(self.env._("Company must be the same")) 32 | if ( 33 | self.kanban_id.procurement_group_id 34 | and self.order_id.procurement_group_id 35 | != self.kanban_id.procurement_group_id 36 | ): 37 | raise ValidationError(self.env._("Procurement group must be the same")) 38 | if self.order_id.location_id != self.kanban_id.location_id: 39 | raise ValidationError(self.env._("Location must be the same")) 40 | if self.order_id.warehouse_id != self.kanban_id.warehouse_id: 41 | raise ValidationError(self.env._("Warehouse must be the same")) 42 | return res 43 | 44 | def stock_request_kanban_values(self): 45 | res = super().stock_request_kanban_values() 46 | res["order_id"] = (self.order_id.id,) 47 | res["expected_date"] = fields.Datetime.to_string(self.order_id.expected_date) 48 | return res 49 | 50 | def stock_request_ending(self): 51 | return 52 | 53 | def barcode_ending(self): 54 | res = super().barcode_ending() 55 | self.order_id = self.stock_request_id.order_id 56 | return res 57 | -------------------------------------------------------------------------------- /stock_request_mrp/i18n/stock_request_mrp.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_mrp 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: stock_request_mrp 17 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.stock_request_order_form 18 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.view_stock_request_form 19 | msgid "MOs" 20 | msgstr "" 21 | 22 | #. module: stock_request_mrp 23 | #: model:ir.model,name:stock_request_mrp.model_mrp_production 24 | msgid "Manufacturing Order" 25 | msgstr "" 26 | 27 | #. module: stock_request_mrp 28 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_ids 29 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_ids 30 | msgid "Manufacturing Orders" 31 | msgstr "" 32 | 33 | #. module: stock_request_mrp 34 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_count 35 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_count 36 | msgid "Manufacturing Orders count" 37 | msgstr "" 38 | 39 | #. module: stock_request_mrp 40 | #: model:ir.model,name:stock_request_mrp.model_stock_request 41 | msgid "Stock Request" 42 | msgstr "" 43 | 44 | #. module: stock_request_mrp 45 | #: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_count 46 | msgid "Stock Request #" 47 | msgstr "" 48 | 49 | #. module: stock_request_mrp 50 | #: model:ir.model,name:stock_request_mrp.model_stock_request_order 51 | msgid "Stock Request Order" 52 | msgstr "" 53 | 54 | #. module: stock_request_mrp 55 | #: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_ids 56 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.mrp_production_form_view 57 | msgid "Stock Requests" 58 | msgstr "" 59 | 60 | #. module: stock_request_mrp 61 | #: model:ir.model,name:stock_request_mrp.model_stock_rule 62 | msgid "Stock Rule" 63 | msgstr "" 64 | 65 | #. module: stock_request_mrp 66 | #. odoo-python 67 | #: code:addons/stock_request_mrp/models/stock_request.py:0 68 | msgid "" 69 | "You have linked to a Manufacture Order that belongs to another company." 70 | msgstr "" 71 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "18.0*" 7 | push: 8 | branches: 9 | - "18.0" 10 | - "18.0-ocabot-*" 11 | 12 | jobs: 13 | unreleased-deps: 14 | runs-on: ubuntu-latest 15 | name: Detect unreleased dependencies 16 | steps: 17 | - uses: actions/checkout@v4 18 | - run: | 19 | for reqfile in requirements.txt test-requirements.txt ; do 20 | if [ -f ${reqfile} ] ; then 21 | result=0 22 | # reject non-comment lines that contain a / (i.e. URLs, relative paths) 23 | grep "^[^#].*/" ${reqfile} || result=$? 24 | if [ $result -eq 0 ] ; then 25 | echo "Unreleased dependencies found in ${reqfile}." 26 | exit 1 27 | fi 28 | fi 29 | done 30 | test: 31 | runs-on: ubuntu-22.04 32 | container: ${{ matrix.container }} 33 | name: ${{ matrix.name }} 34 | strategy: 35 | fail-fast: false 36 | matrix: 37 | include: 38 | - container: ghcr.io/oca/oca-ci/py3.10-odoo18.0:latest 39 | name: test with Odoo 40 | - container: ghcr.io/oca/oca-ci/py3.10-ocb18.0:latest 41 | name: test with OCB 42 | makepot: "true" 43 | services: 44 | postgres: 45 | image: postgres:12.0 46 | env: 47 | POSTGRES_USER: odoo 48 | POSTGRES_PASSWORD: odoo 49 | POSTGRES_DB: odoo 50 | ports: 51 | - 5432:5432 52 | env: 53 | OCA_ENABLE_CHECKLOG_ODOO: "1" 54 | steps: 55 | - uses: actions/checkout@v4 56 | with: 57 | persist-credentials: false 58 | - name: Install addons and dependencies 59 | run: oca_install_addons 60 | - name: Check licenses 61 | run: manifestoo -d . check-licenses 62 | - name: Check development status 63 | run: manifestoo -d . check-dev-status --default-dev-status=Beta 64 | - name: Initialize test db 65 | run: oca_init_test_database 66 | - name: Run tests 67 | run: oca_run_tests 68 | - uses: codecov/codecov-action@v4 69 | with: 70 | token: ${{ secrets.CODECOV_TOKEN }} 71 | - name: Update .pot files 72 | run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }} 73 | if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'OCA' }} 74 | -------------------------------------------------------------------------------- /stock_request_purchase/models/stock_request.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # Copyright 2023 Tecnativa - Víctor Martínez 3 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 4 | 5 | from odoo import _, api, fields, models 6 | from odoo.exceptions import ValidationError 7 | 8 | 9 | class StockRequest(models.Model): 10 | _inherit = "stock.request" 11 | 12 | purchase_ids = fields.One2many( 13 | "purchase.order", 14 | compute="_compute_purchase_ids", 15 | string="Purchase Orders", 16 | readonly=True, 17 | ) 18 | purchase_count = fields.Integer(compute="_compute_purchase_ids", readonly=True) 19 | purchase_line_ids = fields.Many2many( 20 | "purchase.order.line", string="Purchase Order Lines", readonly=True, copy=False 21 | ) 22 | 23 | @api.depends("purchase_line_ids") 24 | def _compute_purchase_ids(self): 25 | for request in self: 26 | request.purchase_ids = request.purchase_line_ids.mapped("order_id") 27 | request.purchase_count = len(request.purchase_ids) 28 | 29 | @api.constrains("purchase_line_ids", "company_id") 30 | def _check_purchase_company_constrains(self): 31 | if any( 32 | any(line.company_id != req.company_id for line in req.purchase_line_ids) 33 | for req in self 34 | ): 35 | raise ValidationError( 36 | _( 37 | "You have linked to a purchase order line " 38 | "that belongs to another company." 39 | ) 40 | ) 41 | 42 | def action_cancel(self): 43 | """Propagate the cancellation to the generated purchase orders.""" 44 | res = super().action_cancel() 45 | if not self.env.context.get("skip_cancel_po_from_stock_request"): 46 | self.sudo().purchase_ids.filtered( 47 | lambda x: x.state not in ("purchase", "done", "cancel") 48 | and x.stock_request_ids == self 49 | ).button_cancel() 50 | return res 51 | 52 | def action_view_purchase(self): 53 | action = self.env["ir.actions.act_window"]._for_xml_id("purchase.purchase_rfq") 54 | 55 | purchases = self.mapped("purchase_ids") 56 | if len(purchases) > 1: 57 | action["domain"] = [("id", "in", purchases.ids)] 58 | elif purchases: 59 | action["views"] = [ 60 | (self.env.ref("purchase.purchase_order_form").id, "form") 61 | ] 62 | action["res_id"] = purchases.id 63 | return action 64 | -------------------------------------------------------------------------------- /stock_request_mrp/models/mrp_production.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020-24 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class MrpProduction(models.Model): 8 | _inherit = "mrp.production" 9 | 10 | stock_request_ids = fields.Many2many( 11 | "stock.request", 12 | "mrp_production_stock_request_rel", 13 | "mrp_production_id", 14 | "stock_request_id", 15 | string="Stock Requests", 16 | ) 17 | stock_request_count = fields.Integer( 18 | "Stock Request #", compute="_compute_stock_request_ids" 19 | ) 20 | 21 | @api.depends("stock_request_ids") 22 | def _compute_stock_request_ids(self): 23 | for rec in self: 24 | rec.stock_request_count = len(rec.stock_request_ids) 25 | 26 | def _get_stock_requests(self): 27 | """Get all stock requests from action (allows inheritance by other modules).""" 28 | return self.mapped("stock_request_ids") 29 | 30 | def action_view_stock_request(self): 31 | """ 32 | :return dict: dictionary value for created view 33 | """ 34 | action = self.env["ir.actions.act_window"]._for_xml_id( 35 | "stock_request.action_stock_request_form" 36 | ) 37 | requests = self.mapped("stock_request_ids") 38 | requests = self._get_stock_requests() 39 | if len(requests) > 1: 40 | action["domain"] = [("id", "in", requests.ids)] 41 | elif requests: 42 | action["views"] = [ 43 | (self.env.ref("stock_request.view_stock_request_form").id, "form") 44 | ] 45 | action["res_id"] = requests.id 46 | return action 47 | 48 | def _get_move_finished_values( 49 | self, 50 | product_id, 51 | product_uom_qty, 52 | product_uom, 53 | operation_id=False, 54 | byproduct_id=False, 55 | cost_share=0, 56 | ): 57 | res = super()._get_move_finished_values( 58 | product_id, 59 | product_uom_qty, 60 | product_uom, 61 | operation_id=operation_id, 62 | byproduct_id=byproduct_id, 63 | cost_share=cost_share, 64 | ) 65 | if self.stock_request_ids: 66 | res["allocation_ids"] = [ 67 | ( 68 | 0, 69 | 0, 70 | { 71 | "stock_request_id": request.id, 72 | "requested_product_uom_qty": request.product_qty, 73 | }, 74 | ) 75 | for request in self.stock_request_ids 76 | ] 77 | return res 78 | -------------------------------------------------------------------------------- /stock_request/views/stock_request_allocation_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | stock.request.allocation.tree 7 | stock.request.allocation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | stock.request.allocation.form 28 | stock.request.allocation 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 53 | 54 | 55 | 56 |
57 |
58 |
59 |
60 | -------------------------------------------------------------------------------- /stock_request_mrp/i18n/it.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_mrp 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 15.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2023-12-18 09:34+0000\n" 10 | "Last-Translator: mymage \n" 11 | "Language-Team: none\n" 12 | "Language: it\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.17\n" 18 | 19 | #. module: stock_request_mrp 20 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.stock_request_order_form 21 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.view_stock_request_form 22 | msgid "MOs" 23 | msgstr "OP" 24 | 25 | #. module: stock_request_mrp 26 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_ids 27 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_ids 28 | msgid "Manufacturing Orders" 29 | msgstr "Ordini di produzione" 30 | 31 | #. module: stock_request_mrp 32 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_count 33 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_count 34 | msgid "Manufacturing Orders count" 35 | msgstr "Numero ordini di produzione" 36 | 37 | #. module: stock_request_mrp 38 | #: model:ir.model,name:stock_request_mrp.model_mrp_production 39 | msgid "Production Order" 40 | msgstr "Ordine di produzione" 41 | 42 | #. module: stock_request_mrp 43 | #: model:ir.model,name:stock_request_mrp.model_stock_request 44 | msgid "Stock Request" 45 | msgstr "Richiesta di magazzino" 46 | 47 | #. module: stock_request_mrp 48 | #: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_count 49 | msgid "Stock Request #" 50 | msgstr "N° richieste di magazzino" 51 | 52 | #. module: stock_request_mrp 53 | #: model:ir.model,name:stock_request_mrp.model_stock_request_order 54 | msgid "Stock Request Order" 55 | msgstr "Ordine richiesta di magazzino" 56 | 57 | #. module: stock_request_mrp 58 | #: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_ids 59 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.mrp_production_form_view 60 | msgid "Stock Requests" 61 | msgstr "Richieste di magazzino" 62 | 63 | #. module: stock_request_mrp 64 | #: model:ir.model,name:stock_request_mrp.model_stock_rule 65 | msgid "Stock Rule" 66 | msgstr "Regola di giacenza" 67 | 68 | #. module: stock_request_mrp 69 | #. odoo-python 70 | #: code:addons/stock_request_mrp/models/stock_request.py:0 71 | #, python-format 72 | msgid "You have linked to a Manufacture Order that belongs to another company." 73 | msgstr "" 74 | "È stato collegato un ordine di produzione che appartiene ad un'altra azienda." 75 | -------------------------------------------------------------------------------- /stock_request_mrp/i18n/es.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_mrp 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 15.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2023-11-11 18:36+0000\n" 10 | "Last-Translator: Ivorra78 \n" 11 | "Language-Team: none\n" 12 | "Language: es\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.17\n" 18 | 19 | #. module: stock_request_mrp 20 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.stock_request_order_form 21 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.view_stock_request_form 22 | msgid "MOs" 23 | msgstr "MOs" 24 | 25 | #. module: stock_request_mrp 26 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_ids 27 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_ids 28 | msgid "Manufacturing Orders" 29 | msgstr "Órdenes de Manufacturación" 30 | 31 | #. module: stock_request_mrp 32 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request__production_count 33 | #: model:ir.model.fields,field_description:stock_request_mrp.field_stock_request_order__production_count 34 | msgid "Manufacturing Orders count" 35 | msgstr "Recuento de Órdenes de Fabricación" 36 | 37 | #. module: stock_request_mrp 38 | #: model:ir.model,name:stock_request_mrp.model_mrp_production 39 | msgid "Production Order" 40 | msgstr "Orden de Producción" 41 | 42 | #. module: stock_request_mrp 43 | #: model:ir.model,name:stock_request_mrp.model_stock_request 44 | msgid "Stock Request" 45 | msgstr "Solicitud de Existencias" 46 | 47 | #. module: stock_request_mrp 48 | #: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_count 49 | msgid "Stock Request #" 50 | msgstr "Solicitud de Existencias #" 51 | 52 | #. module: stock_request_mrp 53 | #: model:ir.model,name:stock_request_mrp.model_stock_request_order 54 | msgid "Stock Request Order" 55 | msgstr "Solicitud de Pedido de Existencias" 56 | 57 | #. module: stock_request_mrp 58 | #: model:ir.model.fields,field_description:stock_request_mrp.field_mrp_production__stock_request_ids 59 | #: model_terms:ir.ui.view,arch_db:stock_request_mrp.mrp_production_form_view 60 | msgid "Stock Requests" 61 | msgstr "Solicitudes de Existencias" 62 | 63 | #. module: stock_request_mrp 64 | #: model:ir.model,name:stock_request_mrp.model_stock_rule 65 | msgid "Stock Rule" 66 | msgstr "Regla de Existencias" 67 | 68 | #. module: stock_request_mrp 69 | #. odoo-python 70 | #: code:addons/stock_request_mrp/models/stock_request.py:0 71 | #, python-format 72 | msgid "You have linked to a Manufacture Order that belongs to another company." 73 | msgstr "" 74 | "Se ha vinculado a una orden de Fabricación que pertenece a otra empresa." 75 | -------------------------------------------------------------------------------- /stock_request_purchase/models/purchase_order_line.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import _, api, fields, models 5 | from odoo.exceptions import ValidationError 6 | 7 | 8 | class PurchaseOrderLine(models.Model): 9 | _inherit = "purchase.order.line" 10 | 11 | stock_request_ids = fields.Many2many( 12 | comodel_name="stock.request", string="Stock Requests", copy=False 13 | ) 14 | 15 | def unlink(self): 16 | """ 17 | Cancel the stock.request 18 | related to the purchase order line 19 | because it does not occur automatically 20 | and causes inconsistency by keeping the SR state as 'In Progress' (open). 21 | """ 22 | stock_request_to_cancel = self.env["stock.request"] 23 | for purchase_line in self: 24 | stock_request_to_cancel |= purchase_line.stock_request_ids 25 | res = super().unlink() 26 | if stock_request_to_cancel: 27 | stock_request_to_cancel.action_cancel() 28 | return res 29 | 30 | def _prepare_stock_moves(self, picking): 31 | res = super()._prepare_stock_moves(picking) 32 | for re in res: 33 | re["allocation_ids"] = [ 34 | ( 35 | 0, 36 | 0, 37 | { 38 | "stock_request_id": request.id, 39 | "requested_product_uom_qty": request.product_qty, 40 | }, 41 | ) 42 | for request in self.stock_request_ids 43 | ] 44 | return res 45 | 46 | @api.model 47 | def _prepare_purchase_order_line_from_procurement( 48 | self, 49 | product_id, 50 | product_qty, 51 | product_uom, 52 | location_dest_id, 53 | name, 54 | origin, 55 | company_id, 56 | values, 57 | po, 58 | ): 59 | vals = super()._prepare_purchase_order_line_from_procurement( 60 | product_id, 61 | product_qty, 62 | product_uom, 63 | location_dest_id, 64 | name, 65 | origin, 66 | company_id, 67 | values, 68 | po, 69 | ) 70 | if "stock_request_id" in values: 71 | vals["stock_request_ids"] = [(4, values["stock_request_id"])] 72 | return vals 73 | 74 | @api.constrains("stock_request_ids") 75 | def _check_purchase_company_constrains(self): 76 | if any( 77 | any(req.company_id != pol.company_id for req in pol.stock_request_ids) 78 | for pol in self 79 | ): 80 | raise ValidationError( 81 | _( 82 | "You cannot link a purchase order line " 83 | "to a stock request that belongs to " 84 | "another company." 85 | ) 86 | ) 87 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 * * 0" 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Stale PRs and issues policy 12 | uses: actions/stale@v9 13 | with: 14 | repo-token: ${{ secrets.GITHUB_TOKEN }} 15 | # General settings. 16 | ascending: true 17 | remove-stale-when-updated: true 18 | # Pull Requests settings. 19 | # 120+30 day stale policy for PRs 20 | # * Except PRs marked as "no stale" 21 | days-before-pr-stale: 120 22 | days-before-pr-close: 30 23 | exempt-pr-labels: "no stale" 24 | stale-pr-label: "stale" 25 | stale-pr-message: > 26 | There hasn't been any activity on this pull request in the past 4 months, so 27 | it has been marked as stale and it will be closed automatically if no 28 | further activity occurs in the next 30 days. 29 | 30 | If you want this PR to never become stale, please ask a PSC member to apply 31 | the "no stale" label. 32 | # Issues settings. 33 | # 180+30 day stale policy for open issues 34 | # * Except Issues marked as "no stale" 35 | days-before-issue-stale: 180 36 | days-before-issue-close: 30 37 | exempt-issue-labels: "no stale,needs more information" 38 | stale-issue-label: "stale" 39 | stale-issue-message: > 40 | There hasn't been any activity on this issue in the past 6 months, so it has 41 | been marked as stale and it will be closed automatically if no further 42 | activity occurs in the next 30 days. 43 | 44 | If you want this issue to never become stale, please ask a PSC member to 45 | apply the "no stale" label. 46 | 47 | # 15+30 day stale policy for issues pending more information 48 | # * Issues that are pending more information 49 | # * Except Issues marked as "no stale" 50 | - name: Needs more information stale issues policy 51 | uses: actions/stale@v9 52 | with: 53 | repo-token: ${{ secrets.GITHUB_TOKEN }} 54 | ascending: true 55 | only-labels: "needs more information" 56 | exempt-issue-labels: "no stale" 57 | days-before-stale: 15 58 | days-before-close: 30 59 | days-before-pr-stale: -1 60 | days-before-pr-close: -1 61 | remove-stale-when-updated: true 62 | stale-issue-label: "stale" 63 | stale-issue-message: > 64 | This issue needs more information and there hasn't been any activity 65 | recently, so it has been marked as stale and it will be closed automatically 66 | if no further activity occurs in the next 30 days. 67 | 68 | If you think this is a mistake, please ask a PSC member to remove the "needs 69 | more information" label. 70 | -------------------------------------------------------------------------------- /.pylintrc-mandatory: -------------------------------------------------------------------------------- 1 | 2 | [MASTER] 3 | load-plugins=pylint_odoo 4 | score=n 5 | 6 | [ODOOLINT] 7 | readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" 8 | manifest-required-authors=Odoo Community Association (OCA) 9 | manifest-required-keys=license 10 | manifest-deprecated-keys=description,active 11 | license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 12 | valid-odoo-versions=18.0 13 | 14 | [MESSAGES CONTROL] 15 | disable=all 16 | 17 | enable=anomalous-backslash-in-string, 18 | api-one-deprecated, 19 | api-one-multi-together, 20 | assignment-from-none, 21 | attribute-deprecated, 22 | class-camelcase, 23 | dangerous-default-value, 24 | dangerous-view-replace-wo-priority, 25 | development-status-allowed, 26 | duplicate-id-csv, 27 | duplicate-key, 28 | duplicate-xml-fields, 29 | duplicate-xml-record-id, 30 | eval-referenced, 31 | eval-used, 32 | incoherent-interpreter-exec-perm, 33 | license-allowed, 34 | manifest-author-string, 35 | manifest-deprecated-key, 36 | manifest-required-author, 37 | manifest-required-key, 38 | manifest-version-format, 39 | method-compute, 40 | method-inverse, 41 | method-required-super, 42 | method-search, 43 | openerp-exception-warning, 44 | pointless-statement, 45 | pointless-string-statement, 46 | print-used, 47 | redundant-keyword-arg, 48 | redundant-modulename-xml, 49 | reimported, 50 | relative-import, 51 | return-in-init, 52 | rst-syntax-error, 53 | sql-injection, 54 | too-few-format-args, 55 | translation-field, 56 | translation-required, 57 | unreachable, 58 | use-vim-comment, 59 | wrong-tabs-instead-of-spaces, 60 | xml-syntax-error, 61 | attribute-string-redundant, 62 | character-not-valid-in-resource-link, 63 | consider-merging-classes-inherited, 64 | context-overridden, 65 | create-user-wo-reset-password, 66 | dangerous-filter-wo-user, 67 | dangerous-qweb-replace-wo-priority, 68 | deprecated-data-xml-node, 69 | deprecated-openerp-xml-node, 70 | duplicate-po-message-definition, 71 | except-pass, 72 | file-not-used, 73 | invalid-commit, 74 | manifest-maintainers-list, 75 | missing-newline-extrafiles, 76 | missing-readme, 77 | missing-return, 78 | odoo-addons-relative-import, 79 | old-api7-method-defined, 80 | po-msgstr-variables, 81 | po-syntax-error, 82 | renamed-field-parameter, 83 | resource-not-exist, 84 | str-format-used, 85 | test-folder-imported, 86 | translation-contains-variable, 87 | translation-positional-used, 88 | unnecessary-utf8-coding-comment, 89 | website-manifest-key-not-valid-uri, 90 | xml-attribute-translatable, 91 | xml-deprecated-qweb-directive, 92 | xml-deprecated-tree-attribute, 93 | external-request-timeout 94 | 95 | [REPORTS] 96 | msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} 97 | output-format=colorized 98 | reports=no 99 | -------------------------------------------------------------------------------- /stock_request/models/stock_move.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2020 ForgeFlow, S.L. 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import _, api, fields, models 5 | from odoo.exceptions import ValidationError 6 | 7 | 8 | class StockMove(models.Model): 9 | _inherit = "stock.move" 10 | 11 | allocation_ids = fields.One2many( 12 | comodel_name="stock.request.allocation", 13 | inverse_name="stock_move_id", 14 | string="Stock Request Allocation", 15 | ) 16 | 17 | stock_request_ids = fields.One2many( 18 | comodel_name="stock.request", 19 | string="Stock Requests", 20 | compute="_compute_stock_request_ids", 21 | ) 22 | 23 | @api.depends("allocation_ids") 24 | def _compute_stock_request_ids(self): 25 | for rec in self: 26 | rec.stock_request_ids = rec.allocation_ids.mapped("stock_request_id") 27 | 28 | def _merge_moves_fields(self): 29 | res = super()._merge_moves_fields() 30 | res["allocation_ids"] = [(4, m.id) for m in self.mapped("allocation_ids")] 31 | return res 32 | 33 | @api.constrains("company_id") 34 | def _check_company_stock_request(self): 35 | if any( 36 | self.env["stock.request.allocation"].search( 37 | [ 38 | ("company_id", "!=", rec.company_id.id), 39 | ("stock_move_id", "=", rec.id), 40 | ], 41 | limit=1, 42 | ) 43 | for rec in self 44 | ): 45 | raise ValidationError( 46 | _( 47 | "The company of the stock request must match with " 48 | "that of the location." 49 | ) 50 | ) 51 | 52 | def copy_data(self, default=None): 53 | if not default: 54 | default = {} 55 | if "allocation_ids" not in default: 56 | default["allocation_ids"] = [] 57 | for alloc in self.allocation_ids: 58 | default["allocation_ids"].append( 59 | ( 60 | 0, 61 | 0, 62 | { 63 | "stock_request_id": alloc.stock_request_id.id, 64 | "requested_product_uom_qty": alloc.requested_product_uom_qty, 65 | }, 66 | ) 67 | ) 68 | return super().copy_data(default) 69 | 70 | def _action_cancel(self): 71 | """Apply sudo to prevent requests ACL errors if the user does not have 72 | permissions (example: productions).""" 73 | res = super()._action_cancel() 74 | self.mapped("allocation_ids.stock_request_id").sudo().check_cancel() 75 | return res 76 | 77 | def _action_done(self, cancel_backorder=False): 78 | """Apply sudo to prevent requests ACL errors if the user does not have 79 | permissions (example: productions).""" 80 | res = super()._action_done(cancel_backorder=cancel_backorder) 81 | self.mapped("allocation_ids.stock_request_id").sudo().check_done() 82 | return res 83 | -------------------------------------------------------------------------------- /stock_request_mrp/hooks.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020-24 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | import logging 5 | 6 | from odoo import SUPERUSER_ID, api 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | def post_init_hook(env): 12 | """ 13 | The objective of this hook is to link existing MOs 14 | coming from a Stock Request. 15 | """ 16 | logger.info("Linking existing MOs coming from a Stock Request") 17 | link_existing_mos_to_stock_request(env) 18 | 19 | 20 | def link_existing_mos_to_stock_request(env): 21 | env = api.Environment(env.cr, SUPERUSER_ID, dict()) 22 | stock_request_obj = env["stock.request"] 23 | stock_request_order_obj = env["stock.request.order"] 24 | stock_request_allocation_obj = env["stock.request.allocation"] 25 | mrp_production_obj = env["mrp.production"] 26 | mos_with_sr = mrp_production_obj.search([("origin", "ilike", "SR/%")]) 27 | logger.info(f"Linking {len(mos_with_sr)} MOs records") 28 | stock_requests = stock_request_obj.search( 29 | [("name", "in", [mo.origin for mo in mos_with_sr])] 30 | ) 31 | for mo in mos_with_sr: 32 | stock_request = stock_requests.filtered(lambda x, mo=mo: x.name == mo.origin) 33 | if stock_request: 34 | # Link SR to MO 35 | mo.stock_request_ids = [(6, 0, stock_request.ids)] 36 | logger.info(f"MO {mo.name} linked to SR {stock_request.name}") 37 | if ( 38 | not stock_request_allocation_obj.search( 39 | [("stock_request_id", "=", stock_request.id)] 40 | ) 41 | and mo.state != "cancel" 42 | ): 43 | # Create allocation for finish move 44 | logger.info(f"Create allocation for {stock_request.name}") 45 | mo.move_finished_ids[0].allocation_ids = [ 46 | ( 47 | 0, 48 | 0, 49 | { 50 | "stock_request_id": request.id, 51 | "requested_product_uom_qty": request.product_qty, 52 | }, 53 | ) 54 | for request in mo.stock_request_ids 55 | ] 56 | 57 | # Update allocations 58 | logger.info(f"Updating Allocations for SR {stock_request.name}") 59 | for ml in mo.finished_move_line_ids.filtered( 60 | lambda m: m.exists() and m.move_id.allocation_ids 61 | ): 62 | quantity = ml.product_uom_id._compute_quantity( 63 | ml.quantity, ml.product_id.uom_id 64 | ) 65 | to_allocate_qty = ml.quantity 66 | for allocation in ml.move_id.allocation_ids: 67 | if allocation.open_product_qty: 68 | allocated_qty = min(allocation.open_product_qty, quantity) 69 | allocation.allocated_product_qty += allocated_qty 70 | to_allocate_qty -= allocated_qty 71 | stock_request.check_done() 72 | # Update production_ids from SROs 73 | stock_request_order_obj.search([])._compute_production_ids() 74 | -------------------------------------------------------------------------------- /stock_request/models/stock_request_allocation.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2020 ForgeFlow, S.L. 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class StockRequestAllocation(models.Model): 8 | _name = "stock.request.allocation" 9 | _description = "Stock Request Allocation" 10 | 11 | stock_request_id = fields.Many2one( 12 | string="Stock Request", 13 | comodel_name="stock.request", 14 | required=True, 15 | ondelete="cascade", 16 | ) 17 | company_id = fields.Many2one( 18 | string="Company", 19 | comodel_name="res.company", 20 | readonly=True, 21 | related="stock_request_id.company_id", 22 | store=True, 23 | ) 24 | stock_move_id = fields.Many2one( 25 | string="Stock Move", 26 | comodel_name="stock.move", 27 | required=True, 28 | ondelete="cascade", 29 | ) 30 | product_id = fields.Many2one( 31 | string="Product", 32 | comodel_name="product.product", 33 | related="stock_request_id.product_id", 34 | readonly=True, 35 | ) 36 | product_uom_id = fields.Many2one( 37 | string="UoM", 38 | comodel_name="uom.uom", 39 | related="stock_request_id.product_uom_id", 40 | readonly=True, 41 | ) 42 | requested_product_uom_qty = fields.Float( 43 | "Requested Quantity (UoM)", 44 | help="Quantity of the stock request allocated to the stock move, " 45 | "in the UoM of the Stock Request", 46 | ) 47 | requested_product_qty = fields.Float( 48 | "Requested Quantity", 49 | help="Quantity of the stock request allocated to the stock move, " 50 | "in the default UoM of the product", 51 | compute="_compute_requested_product_qty", 52 | ) 53 | allocated_product_qty = fields.Float( 54 | "Allocated Quantity", 55 | copy=False, 56 | help="Quantity of the stock request allocated to the stock move, " 57 | "in the default UoM of the product", 58 | ) 59 | open_product_qty = fields.Float( 60 | "Open Quantity", 61 | compute="_compute_open_product_qty", 62 | ) 63 | 64 | @api.depends( 65 | "stock_request_id.product_id", 66 | "stock_request_id.product_uom_id", 67 | "requested_product_uom_qty", 68 | ) 69 | def _compute_requested_product_qty(self): 70 | for rec in self: 71 | rec.requested_product_qty = rec.product_uom_id._compute_quantity( 72 | rec.requested_product_uom_qty, 73 | rec.product_id.uom_id, 74 | rounding_method="HALF-UP", 75 | ) 76 | 77 | @api.depends( 78 | "requested_product_qty", 79 | "allocated_product_qty", 80 | "stock_move_id", 81 | "stock_move_id.state", 82 | ) 83 | def _compute_open_product_qty(self): 84 | for rec in self: 85 | if rec.stock_move_id.state in ["cancel", "done"]: 86 | rec.open_product_qty = 0.0 87 | else: 88 | rec.open_product_qty = ( 89 | rec.requested_product_qty - rec.allocated_product_qty 90 | ) 91 | if rec.open_product_qty < 0.0: 92 | rec.open_product_qty = 0.0 93 | -------------------------------------------------------------------------------- /stock_request_bom/models/stock_request_order.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import _, api, fields, models 5 | from odoo.exceptions import UserError, ValidationError 6 | 7 | 8 | class StockRequestOrder(models.Model): 9 | _inherit = "stock.request.order" 10 | 11 | product_bom_id = fields.Many2one( 12 | "product.product", 13 | string="Product BOM", 14 | domain="[('bom_ids', '!=', False)]", 15 | help="Select a product with a BOM to auto-complete stock request lines.", 16 | ) 17 | quantity_bom = fields.Float( 18 | string="Quantity BOM", 19 | help="Specify the quantity for the Product BOM.", 20 | default=1.0, 21 | ) 22 | 23 | @api.constrains("quantity_bom") 24 | def _check_quantity_bom(self): 25 | for order in self: 26 | if order.quantity_bom <= 0: 27 | raise ValidationError(_("The quantity BOM must be a positive value.")) 28 | 29 | def _prepare_bom_line(self, product, line, line_qty): 30 | """Prepare a dictionary for a BOM line.""" 31 | return { 32 | "product_id": product.id, 33 | "product_uom_id": line.product_uom_id.id, 34 | "product_uom_qty": line_qty, 35 | "warehouse_id": self.warehouse_id.id, 36 | "location_id": self.location_id.id, 37 | "company_id": self.company_id.id, 38 | "requested_by": self.requested_by.id, 39 | "expected_date": self.expected_date, 40 | } 41 | 42 | def _get_bom_lines_recursive(self, bom, quantity): 43 | """Recursively fetch BOM lines for a given BOM and quantity.""" 44 | bom_lines = [] 45 | bom_done, lines_done = bom.explode(self.product_bom_id, quantity) 46 | for line, line_data in lines_done: 47 | product = line.product_id 48 | line_qty = line_data["qty"] 49 | sub_bom = self.env["mrp.bom"]._bom_find(product).get(product) 50 | if sub_bom: 51 | # Recursively fetch lines from the sub-BOM 52 | bom_lines += self._get_bom_lines_recursive( 53 | sub_bom, line_qty / sub_bom.product_qty 54 | ) 55 | else: 56 | # Add the line directly if no sub-BOM is found 57 | bom_lines.append( 58 | ( 59 | 0, 60 | 0, 61 | self._prepare_bom_line(product, line, line_qty), 62 | ) 63 | ) 64 | return bom_lines 65 | 66 | @api.onchange("product_bom_id", "quantity_bom") 67 | def _onchange_product_bom(self): 68 | if not self.product_bom_id: 69 | self.stock_request_ids = [(5, 0, 0)] 70 | return 71 | 72 | bom = ( 73 | self.env["mrp.bom"]._bom_find(self.product_bom_id).get(self.product_bom_id) 74 | ) 75 | if not bom: 76 | raise UserError(_("No BOM found for the selected product.")) 77 | # Clear the existing stock request lines 78 | self.stock_request_ids = [(5, 0, 0)] 79 | bom_lines = self._get_bom_lines_recursive(bom, self.quantity_bom) 80 | self.stock_request_ids = bom_lines 81 | -------------------------------------------------------------------------------- /stock_request/models/stock_move_line.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 ForgeFlow S.L. 2 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0). 3 | 4 | from markupsafe import Markup 5 | 6 | from odoo import _, api, models 7 | 8 | 9 | class StockMoveLine(models.Model): 10 | _inherit = "stock.move.line" 11 | 12 | @api.model 13 | def _stock_request_confirm_done_message_content(self, message_data): 14 | title = Markup("

%s

") % _( 15 | "Receipt confirmation %(picking_name)s for your Request " 16 | "%(request_name)s", 17 | picking_name=message_data["picking_name"], 18 | request_name=message_data["request_name"], 19 | ) 20 | 21 | body = Markup("

%s

") % _( 22 | "The following requested items from Stock Request %(request_name)s " 23 | "have now been received in %(location_name)s using Picking " 24 | "%(picking_name)s:", 25 | request_name=message_data["request_name"], 26 | location_name=message_data["location_name"], 27 | picking_name=message_data["picking_name"], 28 | ) 29 | 30 | items = Markup("
  • %s
") % _( 31 | "%(product_name)s : Transferred quantity %(product_qty)s %(product_uom)s", 32 | product_name=message_data["product_name"], 33 | product_qty=message_data["product_qty"], 34 | product_uom=message_data["product_uom"], 35 | ) 36 | 37 | message = title + body + items 38 | 39 | return message 40 | 41 | def _prepare_message_data(self, ml, request, allocated_qty): 42 | return { 43 | "request_name": request.name, 44 | "picking_name": ml.picking_id.name, 45 | "product_name": ml.product_id.display_name, 46 | "product_qty": allocated_qty, 47 | "product_uom": ml.product_uom_id.name, 48 | "location_name": ml.location_dest_id.display_name, 49 | } 50 | 51 | def _action_done(self): 52 | res = super()._action_done() 53 | for ml in self.filtered(lambda m: m.exists() and m.move_id.allocation_ids): 54 | qty_done = ml.product_uom_id._compute_quantity( 55 | ml.quantity, ml.product_id.uom_id 56 | ) 57 | 58 | # We do sudo because potentially the user that completes the move 59 | # may not have permissions for stock.request. 60 | to_allocate_qty = qty_done 61 | for allocation in ml.move_id.allocation_ids.sudo(): 62 | allocated_qty = 0.0 63 | if allocation.open_product_qty: 64 | allocated_qty = min(allocation.open_product_qty, to_allocate_qty) 65 | allocation.allocated_product_qty += allocated_qty 66 | to_allocate_qty -= allocated_qty 67 | if allocated_qty: 68 | request = allocation.stock_request_id 69 | message_data = self._prepare_message_data( 70 | ml, request, allocated_qty 71 | ) 72 | message = self._stock_request_confirm_done_message_content( 73 | message_data 74 | ) 75 | request.message_post(body=message, subtype_xmlid="mail.mt_comment") 76 | request.check_done() 77 | return res 78 | -------------------------------------------------------------------------------- /stock_request_purchase/i18n/stock_request_purchase.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_purchase 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: stock_request_purchase 17 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.stock_request_order_form 18 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.view_stock_request_form 19 | msgid "Purchase" 20 | msgstr "" 21 | 22 | #. module: stock_request_purchase 23 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_count 24 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_count 25 | msgid "Purchase Count" 26 | msgstr "" 27 | 28 | #. module: stock_request_purchase 29 | #: model:ir.model,name:stock_request_purchase.model_purchase_order 30 | msgid "Purchase Order" 31 | msgstr "" 32 | 33 | #. module: stock_request_purchase 34 | #: model:ir.model,name:stock_request_purchase.model_purchase_order_line 35 | msgid "Purchase Order Line" 36 | msgstr "" 37 | 38 | #. module: stock_request_purchase 39 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_line_ids 40 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_line_ids 41 | msgid "Purchase Order Lines" 42 | msgstr "" 43 | 44 | #. module: stock_request_purchase 45 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_ids 46 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_ids 47 | msgid "Purchase Orders" 48 | msgstr "" 49 | 50 | #. module: stock_request_purchase 51 | #: model:ir.model,name:stock_request_purchase.model_stock_request 52 | msgid "Stock Request" 53 | msgstr "" 54 | 55 | #. module: stock_request_purchase 56 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_count 57 | msgid "Stock Request #" 58 | msgstr "" 59 | 60 | #. module: stock_request_purchase 61 | #: model:ir.model,name:stock_request_purchase.model_stock_request_order 62 | msgid "Stock Request Order" 63 | msgstr "" 64 | 65 | #. module: stock_request_purchase 66 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_ids 67 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order_line__stock_request_ids 68 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_form 69 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_line_form2 70 | msgid "Stock Requests" 71 | msgstr "" 72 | 73 | #. module: stock_request_purchase 74 | #: model:ir.model,name:stock_request_purchase.model_stock_rule 75 | msgid "Stock Rule" 76 | msgstr "" 77 | 78 | #. module: stock_request_purchase 79 | #. odoo-python 80 | #: code:addons/stock_request_purchase/models/purchase_order_line.py:0 81 | msgid "" 82 | "You cannot link a purchase order line to a stock request that belongs to " 83 | "another company." 84 | msgstr "" 85 | 86 | #. module: stock_request_purchase 87 | #. odoo-python 88 | #: code:addons/stock_request_purchase/models/stock_request.py:0 89 | msgid "" 90 | "You have linked to a purchase order line that belongs to another company." 91 | msgstr "" 92 | -------------------------------------------------------------------------------- /stock_request_purchase/i18n/zh_CN.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_purchase 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 12.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2019-10-16 15:58+0000\n" 10 | "Last-Translator: 黎伟杰 <674416404@qq.com>\n" 11 | "Language-Team: none\n" 12 | "Language: zh_CN\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=1; plural=0;\n" 17 | "X-Generator: Weblate 3.8\n" 18 | 19 | #. module: stock_request_purchase 20 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.stock_request_order_form 21 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.view_stock_request_form 22 | msgid "Purchase" 23 | msgstr "采购" 24 | 25 | #. module: stock_request_purchase 26 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_count 27 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_count 28 | msgid "Purchase Count" 29 | msgstr "" 30 | 31 | #. module: stock_request_purchase 32 | #: model:ir.model,name:stock_request_purchase.model_purchase_order 33 | msgid "Purchase Order" 34 | msgstr "采购订单" 35 | 36 | #. module: stock_request_purchase 37 | #: model:ir.model,name:stock_request_purchase.model_purchase_order_line 38 | msgid "Purchase Order Line" 39 | msgstr "采购订单行" 40 | 41 | #. module: stock_request_purchase 42 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_line_ids 43 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_line_ids 44 | msgid "Purchase Order Lines" 45 | msgstr "采购订单行" 46 | 47 | #. module: stock_request_purchase 48 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_ids 49 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_ids 50 | msgid "Purchase Orders" 51 | msgstr "采购订单" 52 | 53 | #. module: stock_request_purchase 54 | #: model:ir.model,name:stock_request_purchase.model_stock_request 55 | msgid "Stock Request" 56 | msgstr "库存请求" 57 | 58 | #. module: stock_request_purchase 59 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_count 60 | msgid "Stock Request #" 61 | msgstr "库存请求 #" 62 | 63 | #. module: stock_request_purchase 64 | #: model:ir.model,name:stock_request_purchase.model_stock_request_order 65 | msgid "Stock Request Order" 66 | msgstr "库存请求单" 67 | 68 | #. module: stock_request_purchase 69 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_ids 70 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order_line__stock_request_ids 71 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_form 72 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_line_form2 73 | msgid "Stock Requests" 74 | msgstr "库存请求" 75 | 76 | #. module: stock_request_purchase 77 | #: model:ir.model,name:stock_request_purchase.model_stock_rule 78 | msgid "Stock Rule" 79 | msgstr "库存规则" 80 | 81 | #. module: stock_request_purchase 82 | #: code:addons/stock_request_purchase/models/purchase_order_line.py:0 83 | #, python-format 84 | msgid "" 85 | "You cannot link a purchase order line to a stock request that belongs to " 86 | "another company." 87 | msgstr "您无法将采购订单行链接到属于另一家公司的库存请求。" 88 | 89 | #. module: stock_request_purchase 90 | #: code:addons/stock_request_purchase/models/stock_request.py:0 91 | #, python-format 92 | msgid "" 93 | "You have linked to a purchase order line that belongs to another company." 94 | msgstr "您已链接到属于另一家公司的采购订单行。" 95 | -------------------------------------------------------------------------------- /stock_request_bom/README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://odoo-community.org/readme-banner-image 2 | :target: https://odoo-community.org/get-involved?utm_source=readme 3 | :alt: Odoo Community Association 4 | 5 | ================= 6 | Stock Request BOM 7 | ================= 8 | 9 | .. 10 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 11 | !! This file is generated by oca-gen-addon-readme !! 12 | !! changes will be overwritten. !! 13 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 14 | !! source digest: sha256:7d1cd4b0f0fbda9cde43436d12ebcd19ed9bfd4957f35a75cc3c0deadaacacac 15 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 16 | 17 | .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png 18 | :target: https://odoo-community.org/page/development-status 19 | :alt: Beta 20 | .. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png 21 | :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html 22 | :alt: License: LGPL-3 23 | .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--request-lightgray.png?logo=github 24 | :target: https://github.com/OCA/stock-logistics-request/tree/18.0/stock_request_bom 25 | :alt: OCA/stock-logistics-request 26 | .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png 27 | :target: https://translation.odoo-community.org/projects/stock-logistics-request-18-0/stock-logistics-request-18-0-stock_request_bom 28 | :alt: Translate me on Weblate 29 | .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png 30 | :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-request&target_branch=18.0 31 | :alt: Try me on Runboat 32 | 33 | |badge1| |badge2| |badge3| |badge4| |badge5| 34 | 35 | This module enhances the stock request functionality by integrating with 36 | the Bill of Materials (BOM). 37 | 38 | Key Features: - Adds Product BOM and Quantity BOM fields to stock 39 | request orders. - Auto-completes stock request lines based on the 40 | selected BOM and quantity. - Allows updating and clearing BOM 41 | selections. 42 | 43 | **Table of contents** 44 | 45 | .. contents:: 46 | :local: 47 | 48 | Usage 49 | ===== 50 | 51 | 1. Select a Product BOM and enter a Quantity BOM. 52 | 2. Stock request lines will auto-fill with BOM components. 53 | 3. Adjust quantity BOM as needed. 54 | 55 | Bug Tracker 56 | =========== 57 | 58 | Bugs are tracked on `GitHub Issues `_. 59 | In case of trouble, please check there if your issue has already been reported. 60 | If you spotted it first, help us to smash it by providing a detailed and welcomed 61 | `feedback `_. 62 | 63 | Do not contact contributors directly about support or help with technical issues. 64 | 65 | Credits 66 | ======= 67 | 68 | Authors 69 | ------- 70 | 71 | * ForgeFlow 72 | 73 | Contributors 74 | ------------ 75 | 76 | - Joan Sisquella Andrés 77 | 78 | Maintainers 79 | ----------- 80 | 81 | This module is maintained by the OCA. 82 | 83 | .. image:: https://odoo-community.org/logo.png 84 | :alt: Odoo Community Association 85 | :target: https://odoo-community.org 86 | 87 | OCA, or the Odoo Community Association, is a nonprofit organization whose 88 | mission is to support the collaborative development of Odoo features and 89 | promote its widespread use. 90 | 91 | This module is part of the `OCA/stock-logistics-request `_ project on GitHub. 92 | 93 | You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. 94 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | [MASTER] 4 | load-plugins=pylint_odoo 5 | score=n 6 | 7 | [ODOOLINT] 8 | readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" 9 | manifest-required-authors=Odoo Community Association (OCA) 10 | manifest-required-keys=license 11 | manifest-deprecated-keys=description,active 12 | license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 13 | valid-odoo-versions=18.0 14 | 15 | [MESSAGES CONTROL] 16 | disable=all 17 | 18 | # This .pylintrc contains optional AND mandatory checks and is meant to be 19 | # loaded in an IDE to have it check everything, in the hope this will make 20 | # optional checks more visible to contributors who otherwise never look at a 21 | # green travis to see optional checks that failed. 22 | # .pylintrc-mandatory containing only mandatory checks is used the pre-commit 23 | # config as a blocking check. 24 | 25 | enable=anomalous-backslash-in-string, 26 | api-one-deprecated, 27 | api-one-multi-together, 28 | assignment-from-none, 29 | attribute-deprecated, 30 | class-camelcase, 31 | dangerous-default-value, 32 | dangerous-view-replace-wo-priority, 33 | development-status-allowed, 34 | duplicate-id-csv, 35 | duplicate-key, 36 | duplicate-xml-fields, 37 | duplicate-xml-record-id, 38 | eval-referenced, 39 | eval-used, 40 | incoherent-interpreter-exec-perm, 41 | license-allowed, 42 | manifest-author-string, 43 | manifest-deprecated-key, 44 | manifest-required-author, 45 | manifest-required-key, 46 | manifest-version-format, 47 | method-compute, 48 | method-inverse, 49 | method-required-super, 50 | method-search, 51 | openerp-exception-warning, 52 | pointless-statement, 53 | pointless-string-statement, 54 | print-used, 55 | redundant-keyword-arg, 56 | redundant-modulename-xml, 57 | reimported, 58 | relative-import, 59 | return-in-init, 60 | rst-syntax-error, 61 | sql-injection, 62 | too-few-format-args, 63 | translation-field, 64 | translation-required, 65 | unreachable, 66 | use-vim-comment, 67 | wrong-tabs-instead-of-spaces, 68 | xml-syntax-error, 69 | attribute-string-redundant, 70 | character-not-valid-in-resource-link, 71 | consider-merging-classes-inherited, 72 | context-overridden, 73 | create-user-wo-reset-password, 74 | dangerous-filter-wo-user, 75 | dangerous-qweb-replace-wo-priority, 76 | deprecated-data-xml-node, 77 | deprecated-openerp-xml-node, 78 | duplicate-po-message-definition, 79 | except-pass, 80 | file-not-used, 81 | invalid-commit, 82 | manifest-maintainers-list, 83 | missing-newline-extrafiles, 84 | missing-readme, 85 | missing-return, 86 | odoo-addons-relative-import, 87 | old-api7-method-defined, 88 | po-msgstr-variables, 89 | po-syntax-error, 90 | renamed-field-parameter, 91 | resource-not-exist, 92 | str-format-used, 93 | test-folder-imported, 94 | translation-contains-variable, 95 | translation-positional-used, 96 | unnecessary-utf8-coding-comment, 97 | website-manifest-key-not-valid-uri, 98 | xml-attribute-translatable, 99 | xml-deprecated-qweb-directive, 100 | xml-deprecated-tree-attribute, 101 | external-request-timeout, 102 | # messages that do not cause the lint step to fail 103 | consider-merging-classes-inherited, 104 | create-user-wo-reset-password, 105 | dangerous-filter-wo-user, 106 | deprecated-module, 107 | file-not-used, 108 | invalid-commit, 109 | missing-manifest-dependency, 110 | missing-newline-extrafiles, 111 | missing-readme, 112 | no-utf8-coding-comment, 113 | odoo-addons-relative-import, 114 | old-api7-method-defined, 115 | redefined-builtin, 116 | too-complex, 117 | unnecessary-utf8-coding-comment 118 | 119 | 120 | [REPORTS] 121 | msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} 122 | output-format=colorized 123 | reports=no 124 | -------------------------------------------------------------------------------- /stock_request_purchase/i18n/de.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_purchase 4 | # 5 | # Translators: 6 | # Rudolf Schnapka , 2017 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 11.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2018-03-02 03:44+0000\n" 12 | "PO-Revision-Date: 2018-03-02 03:44+0000\n" 13 | "Last-Translator: Rudolf Schnapka , 2017\n" 14 | "Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" 15 | "Language: de\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 20 | 21 | #. module: stock_request_purchase 22 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.stock_request_order_form 23 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.view_stock_request_form 24 | msgid "Purchase" 25 | msgstr "Einkauf" 26 | 27 | #. module: stock_request_purchase 28 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_count 29 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_count 30 | msgid "Purchase Count" 31 | msgstr "" 32 | 33 | #. module: stock_request_purchase 34 | #: model:ir.model,name:stock_request_purchase.model_purchase_order 35 | msgid "Purchase Order" 36 | msgstr "" 37 | 38 | #. module: stock_request_purchase 39 | #: model:ir.model,name:stock_request_purchase.model_purchase_order_line 40 | msgid "Purchase Order Line" 41 | msgstr "Bestellposition" 42 | 43 | #. module: stock_request_purchase 44 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_line_ids 45 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_line_ids 46 | msgid "Purchase Order Lines" 47 | msgstr "Bestellpositionen" 48 | 49 | #. module: stock_request_purchase 50 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_ids 51 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_ids 52 | #, fuzzy 53 | msgid "Purchase Orders" 54 | msgstr "Bestellpositionen" 55 | 56 | #. module: stock_request_purchase 57 | #: model:ir.model,name:stock_request_purchase.model_stock_request 58 | msgid "Stock Request" 59 | msgstr "Bestandsanforderung" 60 | 61 | #. module: stock_request_purchase 62 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_count 63 | msgid "Stock Request #" 64 | msgstr "" 65 | 66 | #. module: stock_request_purchase 67 | #: model:ir.model,name:stock_request_purchase.model_stock_request_order 68 | #, fuzzy 69 | msgid "Stock Request Order" 70 | msgstr "Bestandsanforderung" 71 | 72 | #. module: stock_request_purchase 73 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_ids 74 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order_line__stock_request_ids 75 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_form 76 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_line_form2 77 | msgid "Stock Requests" 78 | msgstr "Bestandsanforderungen" 79 | 80 | #. module: stock_request_purchase 81 | #: model:ir.model,name:stock_request_purchase.model_stock_rule 82 | #, fuzzy 83 | msgid "Stock Rule" 84 | msgstr "Bestandsanforderung" 85 | 86 | #. module: stock_request_purchase 87 | #: code:addons/stock_request_purchase/models/purchase_order_line.py:0 88 | #, python-format 89 | msgid "" 90 | "You cannot link a purchase order line to a stock request that belongs to " 91 | "another company." 92 | msgstr "" 93 | 94 | #. module: stock_request_purchase 95 | #: code:addons/stock_request_purchase/models/stock_request.py:0 96 | #, python-format 97 | msgid "" 98 | "You have linked to a purchase order line that belongs to another company." 99 | msgstr "" 100 | -------------------------------------------------------------------------------- /stock_request_purchase/i18n/it.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_purchase 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 15.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2023-12-18 09:34+0000\n" 10 | "Last-Translator: mymage \n" 11 | "Language-Team: none\n" 12 | "Language: it\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.17\n" 18 | 19 | #. module: stock_request_purchase 20 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.stock_request_order_form 21 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.view_stock_request_form 22 | msgid "Purchase" 23 | msgstr "Acquisto" 24 | 25 | #. module: stock_request_purchase 26 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_count 27 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_count 28 | msgid "Purchase Count" 29 | msgstr "Conteggio acquisti" 30 | 31 | #. module: stock_request_purchase 32 | #: model:ir.model,name:stock_request_purchase.model_purchase_order 33 | msgid "Purchase Order" 34 | msgstr "Ordine di acquisto" 35 | 36 | #. module: stock_request_purchase 37 | #: model:ir.model,name:stock_request_purchase.model_purchase_order_line 38 | msgid "Purchase Order Line" 39 | msgstr "Riga ordine di acquisto" 40 | 41 | #. module: stock_request_purchase 42 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_line_ids 43 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_line_ids 44 | msgid "Purchase Order Lines" 45 | msgstr "Righe ordine di acquisto" 46 | 47 | #. module: stock_request_purchase 48 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_ids 49 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_ids 50 | msgid "Purchase Orders" 51 | msgstr "Ordini di acquisto" 52 | 53 | #. module: stock_request_purchase 54 | #: model:ir.model,name:stock_request_purchase.model_stock_request 55 | msgid "Stock Request" 56 | msgstr "Richiesta di magazzino" 57 | 58 | #. module: stock_request_purchase 59 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_count 60 | msgid "Stock Request #" 61 | msgstr "N° richieste di magazzino" 62 | 63 | #. module: stock_request_purchase 64 | #: model:ir.model,name:stock_request_purchase.model_stock_request_order 65 | msgid "Stock Request Order" 66 | msgstr "Ordine richiesta di magazzino" 67 | 68 | #. module: stock_request_purchase 69 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_ids 70 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order_line__stock_request_ids 71 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_form 72 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_line_form2 73 | msgid "Stock Requests" 74 | msgstr "Richieste di magazzino" 75 | 76 | #. module: stock_request_purchase 77 | #: model:ir.model,name:stock_request_purchase.model_stock_rule 78 | msgid "Stock Rule" 79 | msgstr "Regola di giacenza" 80 | 81 | #. module: stock_request_purchase 82 | #: code:addons/stock_request_purchase/models/purchase_order_line.py:0 83 | #, python-format 84 | msgid "" 85 | "You cannot link a purchase order line to a stock request that belongs to " 86 | "another company." 87 | msgstr "" 88 | "Non puoi collegare un ordine di acquisto ad una richiesta di magazzino che " 89 | "appartiene ad un'altra azienda." 90 | 91 | #. module: stock_request_purchase 92 | #: code:addons/stock_request_purchase/models/stock_request.py:0 93 | #, python-format 94 | msgid "" 95 | "You have linked to a purchase order line that belongs to another company." 96 | msgstr "" 97 | "È stata collegata una riga ordine di acquisto che appartiene ad un'altra " 98 | "azienda." 99 | -------------------------------------------------------------------------------- /stock_request_purchase/i18n/es.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * stock_request_purchase 4 | # 5 | # Translators: 6 | # enjolras , 2018 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 11.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2018-03-02 03:44+0000\n" 12 | "PO-Revision-Date: 2023-10-15 20:36+0000\n" 13 | "Last-Translator: Ivorra78 \n" 14 | "Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" 15 | "Language: es\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 20 | "X-Generator: Weblate 4.17\n" 21 | 22 | #. module: stock_request_purchase 23 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.stock_request_order_form 24 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.view_stock_request_form 25 | msgid "Purchase" 26 | msgstr "Compra" 27 | 28 | #. module: stock_request_purchase 29 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_count 30 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_count 31 | msgid "Purchase Count" 32 | msgstr "Conteo de compras" 33 | 34 | #. module: stock_request_purchase 35 | #: model:ir.model,name:stock_request_purchase.model_purchase_order 36 | msgid "Purchase Order" 37 | msgstr "Pedido de compra" 38 | 39 | #. module: stock_request_purchase 40 | #: model:ir.model,name:stock_request_purchase.model_purchase_order_line 41 | msgid "Purchase Order Line" 42 | msgstr "Línea de pedido de compra" 43 | 44 | #. module: stock_request_purchase 45 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_line_ids 46 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_line_ids 47 | msgid "Purchase Order Lines" 48 | msgstr "Líneas de pedido de compra" 49 | 50 | #. module: stock_request_purchase 51 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request__purchase_ids 52 | #: model:ir.model.fields,field_description:stock_request_purchase.field_stock_request_order__purchase_ids 53 | msgid "Purchase Orders" 54 | msgstr "Pedidos de compras" 55 | 56 | #. module: stock_request_purchase 57 | #: model:ir.model,name:stock_request_purchase.model_stock_request 58 | msgid "Stock Request" 59 | msgstr "Solicitud de existencias" 60 | 61 | #. module: stock_request_purchase 62 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_count 63 | msgid "Stock Request #" 64 | msgstr "Solicitud de existencias #" 65 | 66 | #. module: stock_request_purchase 67 | #: model:ir.model,name:stock_request_purchase.model_stock_request_order 68 | msgid "Stock Request Order" 69 | msgstr "Pedido de existencias" 70 | 71 | #. module: stock_request_purchase 72 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order__stock_request_ids 73 | #: model:ir.model.fields,field_description:stock_request_purchase.field_purchase_order_line__stock_request_ids 74 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_form 75 | #: model_terms:ir.ui.view,arch_db:stock_request_purchase.purchase_order_line_form2 76 | msgid "Stock Requests" 77 | msgstr "Solicitudes de existencias" 78 | 79 | #. module: stock_request_purchase 80 | #: model:ir.model,name:stock_request_purchase.model_stock_rule 81 | msgid "Stock Rule" 82 | msgstr "Regla de Abastecimiento" 83 | 84 | #. module: stock_request_purchase 85 | #: code:addons/stock_request_purchase/models/purchase_order_line.py:0 86 | #, python-format 87 | msgid "" 88 | "You cannot link a purchase order line to a stock request that belongs to " 89 | "another company." 90 | msgstr "" 91 | "No puede unir una línea de un pedido de compras a una solicitud de " 92 | "existencias que pertenece a otra compañía." 93 | 94 | #. module: stock_request_purchase 95 | #: code:addons/stock_request_purchase/models/stock_request.py:0 96 | #, python-format 97 | msgid "" 98 | "You have linked to a purchase order line that belongs to another company." 99 | msgstr "" 100 | "Ha seleccionada una línea de pedido de compras que pertenece a otra compañía." 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Runboat](https://img.shields.io/badge/runboat-Try%20me-875A7B.png)](https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-request&target_branch=18.0) 3 | [![Pre-commit Status](https://github.com/OCA/stock-logistics-request/actions/workflows/pre-commit.yml/badge.svg?branch=18.0)](https://github.com/OCA/stock-logistics-request/actions/workflows/pre-commit.yml?query=branch%3A18.0) 4 | [![Build Status](https://github.com/OCA/stock-logistics-request/actions/workflows/test.yml/badge.svg?branch=18.0)](https://github.com/OCA/stock-logistics-request/actions/workflows/test.yml?query=branch%3A18.0) 5 | [![codecov](https://codecov.io/gh/OCA/stock-logistics-request/branch/18.0/graph/badge.svg)](https://codecov.io/gh/OCA/stock-logistics-request) 6 | [![Translation Status](https://translation.odoo-community.org/widgets/stock-logistics-request-18-0/-/svg-badge.svg)](https://translation.odoo-community.org/engage/stock-logistics-request-18-0/?utm_source=widget) 7 | 8 | 9 | 10 | # Stock Request 11 | 12 | Record needs for products 13 | 14 | Are you looking for modules related to logistics? Or would like to contribute 15 | to? There are many repositories with specific purposes. Have a look at this 16 | [README](https://github.com/OCA/wms/blob/18.0/README.md). 17 | 18 | 19 | 20 | 21 | 22 | [//]: # (addons) 23 | 24 | Available addons 25 | ---------------- 26 | addon | version | maintainers | summary 27 | --- | --- | --- | --- 28 | [stock_request](stock_request/) | 18.0.1.1.3 | LoisRForgeFlow etobella | Internal request for stock 29 | [stock_request_bom](stock_request_bom/) | 18.0.1.0.1 | | Stock Request with BOM Integration 30 | [stock_request_kanban](stock_request_kanban/) | 18.0.1.0.1 | etobella LoisRForgeFlow | Adds a stock request order, and takes stock requests as lines 31 | [stock_request_mrp](stock_request_mrp/) | 18.0.1.0.0 | LoisRForgeFlow etobella | Manufacturing request for stock 32 | [stock_request_purchase](stock_request_purchase/) | 18.0.1.0.0 | LoisRForgeFlow etobella | Internal request for stock 33 | [stock_request_tier_validation](stock_request_tier_validation/) | 18.0.1.0.0 | LoisRForgeFlow etobella | Extends the functionality of Stock Requests to support a tier validation process. 34 | [stock_return_request](stock_return_request/) | 18.0.1.0.1 | | Stock Return Request 35 | 36 | [//]: # (end addons) 37 | 38 | 39 | 40 | ## Licenses 41 | 42 | This repository is licensed under [AGPL-3.0](LICENSE). 43 | 44 | However, each module can have a totally different license, as long as they adhere to Odoo Community Association (OCA) 45 | policy. Consult each module's `__manifest__.py` file, which contains a `license` key 46 | that explains its license. 47 | 48 | ---- 49 | OCA, or the [Odoo Community Association](http://odoo-community.org/), is a nonprofit 50 | organization whose mission is to support the collaborative development of Odoo features 51 | and promote its widespread use. 52 | -------------------------------------------------------------------------------- /stock_request_mrp/README.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Stock Request MRP 3 | ================= 4 | 5 | .. 6 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 7 | !! This file is generated by oca-gen-addon-readme !! 8 | !! changes will be overwritten. !! 9 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 10 | !! source digest: sha256:26e2c33578f4412cdccfcb7b146db45355a59c5500002207026dc703ff12d8da 11 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 12 | 13 | .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png 14 | :target: https://odoo-community.org/page/development-status 15 | :alt: Beta 16 | .. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png 17 | :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html 18 | :alt: License: LGPL-3 19 | .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--request-lightgray.png?logo=github 20 | :target: https://github.com/OCA/stock-logistics-request/tree/18.0/stock_request_mrp 21 | :alt: OCA/stock-logistics-request 22 | .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png 23 | :target: https://translation.odoo-community.org/projects/stock-logistics-request-18-0/stock-logistics-request-18-0-stock_request_mrp 24 | :alt: Translate me on Weblate 25 | .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png 26 | :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-request&target_branch=18.0 27 | :alt: Try me on Runboat 28 | 29 | |badge1| |badge2| |badge3| |badge4| |badge5| 30 | 31 | This module allows users to be able to display Manufacturing Orders that 32 | have been created as a consequence of Stock Requests. 33 | 34 | **Table of contents** 35 | 36 | .. contents:: 37 | :local: 38 | 39 | Usage 40 | ===== 41 | 42 | In case that the confirmation of the Stock Request results in an 43 | immediate Manufacturing Order, the user will be able to display the MO's 44 | from the Stock Request form view. 45 | 46 | Navigate to Stock Requests and create a new stock request. Upon 47 | confirmation of the stock request, the system will automatically 48 | generate the corresponding manufacturing order. View and manage the 49 | generated manufacturing orders directly from the stock request record or 50 | through Manufacturing. 51 | 52 | Known issues / Roadmap 53 | ====================== 54 | 55 | 56 | 57 | Bug Tracker 58 | =========== 59 | 60 | Bugs are tracked on `GitHub Issues `_. 61 | In case of trouble, please check there if your issue has already been reported. 62 | If you spotted it first, help us to smash it by providing a detailed and welcomed 63 | `feedback `_. 64 | 65 | Do not contact contributors directly about support or help with technical issues. 66 | 67 | Credits 68 | ======= 69 | 70 | Authors 71 | ------- 72 | 73 | * ForgeFlow 74 | 75 | Contributors 76 | ------------ 77 | 78 | - Héctor Villarreal . 79 | 80 | Maintainers 81 | ----------- 82 | 83 | This module is maintained by the OCA. 84 | 85 | .. image:: https://odoo-community.org/logo.png 86 | :alt: Odoo Community Association 87 | :target: https://odoo-community.org 88 | 89 | OCA, or the Odoo Community Association, is a nonprofit organization whose 90 | mission is to support the collaborative development of Odoo features and 91 | promote its widespread use. 92 | 93 | .. |maintainer-LoisRForgeFlow| image:: https://github.com/LoisRForgeFlow.png?size=40px 94 | :target: https://github.com/LoisRForgeFlow 95 | :alt: LoisRForgeFlow 96 | .. |maintainer-etobella| image:: https://github.com/etobella.png?size=40px 97 | :target: https://github.com/etobella 98 | :alt: etobella 99 | 100 | Current `maintainers `__: 101 | 102 | |maintainer-LoisRForgeFlow| |maintainer-etobella| 103 | 104 | This module is part of the `OCA/stock-logistics-request `_ project on GitHub. 105 | 106 | You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. 107 | -------------------------------------------------------------------------------- /stock_request_purchase/README.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | Stock Request Purchase 3 | ====================== 4 | 5 | .. 6 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 7 | !! This file is generated by oca-gen-addon-readme !! 8 | !! changes will be overwritten. !! 9 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 10 | !! source digest: sha256:a45fec687a4615be4844bc89d8e038cfc17954b16f3869b4ab2fd9fc1eb77b76 11 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 12 | 13 | .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png 14 | :target: https://odoo-community.org/page/development-status 15 | :alt: Beta 16 | .. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png 17 | :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html 18 | :alt: License: LGPL-3 19 | .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--request-lightgray.png?logo=github 20 | :target: https://github.com/OCA/stock-logistics-request/tree/18.0/stock_request_purchase 21 | :alt: OCA/stock-logistics-request 22 | .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png 23 | :target: https://translation.odoo-community.org/projects/stock-logistics-request-18-0/stock-logistics-request-18-0-stock_request_purchase 24 | :alt: Translate me on Weblate 25 | .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png 26 | :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-request&target_branch=18.0 27 | :alt: Try me on Runboat 28 | 29 | |badge1| |badge2| |badge3| |badge4| |badge5| 30 | 31 | This module allows for users to be able to display purchase orders that 32 | have been created as a consequence of Stock Requests. 33 | 34 | **Table of contents** 35 | 36 | .. contents:: 37 | :local: 38 | 39 | Usage 40 | ===== 41 | 42 | In case that the confirmation of the Stock Request results in an 43 | immediate Purchase Order, the user will be able to display the PO's from 44 | the Stock Request form view. 45 | 46 | Known issues / Roadmap 47 | ====================== 48 | 49 | - When a Stock Request is cancelled, it does not cancel the quantity 50 | included in the Purchase Order. 51 | 52 | Bug Tracker 53 | =========== 54 | 55 | Bugs are tracked on `GitHub Issues `_. 56 | In case of trouble, please check there if your issue has already been reported. 57 | If you spotted it first, help us to smash it by providing a detailed and welcomed 58 | `feedback `_. 59 | 60 | Do not contact contributors directly about support or help with technical issues. 61 | 62 | Credits 63 | ======= 64 | 65 | Authors 66 | ------- 67 | 68 | * ForgeFlow 69 | 70 | Contributors 71 | ------------ 72 | 73 | - Jordi Ballester . 74 | - Enric Tobella 75 | - Kitti Upariphutthiphong 76 | - Alan Ramos 77 | - Urvisha Desai 78 | - Bruno Zanotti 79 | 80 | Maintainers 81 | ----------- 82 | 83 | This module is maintained by the OCA. 84 | 85 | .. image:: https://odoo-community.org/logo.png 86 | :alt: Odoo Community Association 87 | :target: https://odoo-community.org 88 | 89 | OCA, or the Odoo Community Association, is a nonprofit organization whose 90 | mission is to support the collaborative development of Odoo features and 91 | promote its widespread use. 92 | 93 | .. |maintainer-LoisRForgeFlow| image:: https://github.com/LoisRForgeFlow.png?size=40px 94 | :target: https://github.com/LoisRForgeFlow 95 | :alt: LoisRForgeFlow 96 | .. |maintainer-etobella| image:: https://github.com/etobella.png?size=40px 97 | :target: https://github.com/etobella 98 | :alt: etobella 99 | 100 | Current `maintainers `__: 101 | 102 | |maintainer-LoisRForgeFlow| |maintainer-etobella| 103 | 104 | This module is part of the `OCA/stock-logistics-request `_ project on GitHub. 105 | 106 | You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. 107 | -------------------------------------------------------------------------------- /stock_return_request/README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://odoo-community.org/readme-banner-image 2 | :target: https://odoo-community.org/get-involved?utm_source=readme 3 | :alt: Odoo Community Association 4 | 5 | ==================== 6 | Stock Return Request 7 | ==================== 8 | 9 | .. 10 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 11 | !! This file is generated by oca-gen-addon-readme !! 12 | !! changes will be overwritten. !! 13 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 14 | !! source digest: sha256:f99b05e246bc54e930950e240cae6578369f7df6ff6d0019e07ca3f6ff4e61cc 15 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 16 | 17 | .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png 18 | :target: https://odoo-community.org/page/development-status 19 | :alt: Beta 20 | .. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png 21 | :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html 22 | :alt: License: AGPL-3 23 | .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--request-lightgray.png?logo=github 24 | :target: https://github.com/OCA/stock-logistics-request/tree/18.0/stock_return_request 25 | :alt: OCA/stock-logistics-request 26 | .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png 27 | :target: https://translation.odoo-community.org/projects/stock-logistics-request-18-0/stock-logistics-request-18-0-stock_return_request 28 | :alt: Translate me on Weblate 29 | .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png 30 | :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-request&target_branch=18.0 31 | :alt: Try me on Runboat 32 | 33 | |badge1| |badge2| |badge3| |badge4| |badge5| 34 | 35 | This module allows to return stock from a location to either suppliers, 36 | customers or internal locations reverting the corresponding pickings. 37 | 38 | **Table of contents** 39 | 40 | .. contents:: 41 | :local: 42 | 43 | Installation 44 | ============ 45 | 46 | The installation of this module entails the computation of the new 47 | stock.move field qty_returnable to store it in the DB, wich can be a 48 | heavy task depending on the amount of moves. 49 | 50 | Usage 51 | ===== 52 | 53 | To use this module, you need to: 54 | 55 | 1. Go to *Inventory > Operations > Return Request* and place a new 56 | return. 57 | 58 | To make a return to a customer: 59 | 60 | To make a return to a supplier: 61 | 62 | To make a return to an internal location: 63 | 64 | Known issues / Roadmap 65 | ====================== 66 | 67 | - Products are returned in the default product UoM. Further 68 | implementation should be done to allow to use UoM convertions. 69 | 70 | Bug Tracker 71 | =========== 72 | 73 | Bugs are tracked on `GitHub Issues `_. 74 | In case of trouble, please check there if your issue has already been reported. 75 | If you spotted it first, help us to smash it by providing a detailed and welcomed 76 | `feedback `_. 77 | 78 | Do not contact contributors directly about support or help with technical issues. 79 | 80 | Credits 81 | ======= 82 | 83 | Authors 84 | ------- 85 | 86 | * Tecnativa 87 | 88 | Contributors 89 | ------------ 90 | 91 | - `Tecnativa `__: 92 | 93 | - Sergio Teruel 94 | - Pedro M. Baeza 95 | - David Vidal 96 | - César A. Sánchez 97 | - Carlos Lopez 98 | 99 | - `Pro Thai `__: 100 | 101 | - Prapassorn Sornkaew 102 | 103 | Maintainers 104 | ----------- 105 | 106 | This module is maintained by the OCA. 107 | 108 | .. image:: https://odoo-community.org/logo.png 109 | :alt: Odoo Community Association 110 | :target: https://odoo-community.org 111 | 112 | OCA, or the Odoo Community Association, is a nonprofit organization whose 113 | mission is to support the collaborative development of Odoo features and 114 | promote its widespread use. 115 | 116 | This module is part of the `OCA/stock-logistics-request `_ project on GitHub. 117 | 118 | You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. 119 | -------------------------------------------------------------------------------- /stock_request_bom/tests/test_stock_request_bom.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 ForgeFlow S.L. 2 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0). 3 | 4 | from odoo.exceptions import UserError, ValidationError 5 | from odoo.tests import Form 6 | 7 | from odoo.addons.stock_request.tests.test_stock_request import TestStockRequest 8 | 9 | 10 | class TestStockRequestBOM(TestStockRequest): 11 | def setUp(self): 12 | super().setUp() 13 | self.mrp_user_group = self.env.ref("mrp.group_mrp_user") 14 | self.stock_request_user.write({"groups_id": [(4, self.mrp_user_group.id)]}) 15 | self.stock_request_manager.write({"groups_id": [(4, self.mrp_user_group.id)]}) 16 | self.route_manufacture = self.warehouse.manufacture_pull_id.route_id 17 | self.product.write({"route_ids": [(6, 0, self.route_manufacture.ids)]}) 18 | 19 | self.raw_1 = self._create_product("SL", "Sole", False) 20 | self.raw_2 = self._create_product("LC", "Lace", False) 21 | self.raw_3 = self._create_product("BT", "Button", False) 22 | 23 | self._update_qty_in_location(self.warehouse.lot_stock_id, self.raw_1, 10) 24 | self._update_qty_in_location(self.warehouse.lot_stock_id, self.raw_2, 10) 25 | self._update_qty_in_location(self.warehouse.lot_stock_id, self.raw_3, 10) 26 | 27 | self.bom = self._create_mrp_bom(self.product, [self.raw_1, self.raw_2]) 28 | self.bom_raw_2 = self._create_mrp_bom(self.raw_2, [self.raw_3]) 29 | 30 | def _update_qty_in_location(self, location, product, quantity): 31 | self.env["stock.quant"]._update_available_quantity(product, location, quantity) 32 | 33 | def _create_mrp_bom(self, product_id, raw_materials): 34 | bom = self.env["mrp.bom"].create( 35 | { 36 | "product_id": product_id.id, 37 | "product_tmpl_id": product_id.product_tmpl_id.id, 38 | "product_uom_id": product_id.uom_id.id, 39 | "product_qty": 1.0, 40 | "type": "normal", 41 | } 42 | ) 43 | for raw_mat in raw_materials: 44 | self.env["mrp.bom.line"].create( 45 | {"bom_id": bom.id, "product_id": raw_mat.id, "product_qty": 1} 46 | ) 47 | return bom 48 | 49 | def test_01_create_stock_request_with_bom(self): 50 | order_form = Form(self.request_order.with_user(self.stock_request_user)) 51 | order_form.product_bom_id = self.product 52 | order_form.quantity_bom = 2 53 | order = order_form.save() 54 | self.assertEqual(len(order.stock_request_ids), 2) 55 | 56 | product_ids = order.stock_request_ids.mapped("product_id") 57 | expected_products = {self.raw_1.id, self.raw_3.id} 58 | actual_products = {product.id for product in product_ids} 59 | self.assertEqual(expected_products, actual_products) 60 | 61 | def test_02_update_quantity_bom(self): 62 | order_form = Form(self.request_order.with_user(self.stock_request_user)) 63 | order_form.product_bom_id = self.product 64 | order_form.quantity_bom = 1 65 | order = order_form.save() 66 | for line in order.stock_request_ids: 67 | self.assertEqual(line.product_uom_qty, 1) 68 | 69 | order_form = Form(order) 70 | order_form.quantity_bom = 3 71 | order = order_form.save() 72 | for line in order.stock_request_ids: 73 | self.assertEqual(line.product_uom_qty, 3) 74 | 75 | def test_03_clear_product_bom(self): 76 | order_form = Form(self.request_order.with_user(self.stock_request_user)) 77 | order_form.product_bom_id = self.product 78 | order_form.quantity_bom = 1 79 | order = order_form.save() 80 | self.assertEqual(len(order.stock_request_ids), 2) 81 | self.request_order.write({"product_bom_id": False}) 82 | order_form = Form(order) 83 | order_form.product_bom_id = self.env["product.product"] 84 | order = order_form.save() 85 | self.assertEqual(len(order.stock_request_ids), 0) 86 | 87 | def test_04_invalid_quantity_bom(self): 88 | order_form = Form(self.request_order.with_user(self.stock_request_user)) 89 | order_form.product_bom_id = self.product 90 | order_form.quantity_bom = -1 91 | 92 | with self.assertRaises(ValidationError): 93 | order_form.save() 94 | 95 | def test_05_product_without_bom(self): 96 | product_without_bom = self._create_product("PWB", "Product Without BOM", False) 97 | order_form = Form(self.request_order.with_user(self.stock_request_user)) 98 | with self.assertRaises(UserError): 99 | order_form.product_bom_id = product_without_bom 100 | --------------------------------------------------------------------------------