From 73be9553955ae1e05523ba38b13078e08c9e0e4d Mon Sep 17 00:00:00 2001
From: christian-ramos-tecnativa
Date: Wed, 31 Dec 2025 15:31:15 +0000
Subject: [PATCH 1/4] [ADD] maintenance_purchase_stock: New module
---
maintenance_purchase_stock/README.rst | 79 ++++
maintenance_purchase_stock/__init__.py | 1 +
maintenance_purchase_stock/__manifest__.py | 18 +
maintenance_purchase_stock/i18n/es.po | 26 ++
.../i18n/maintenance_purchase_stock.pot | 24 +
maintenance_purchase_stock/models/__init__.py | 1 +
.../models/purchase_order.py | 28 ++
maintenance_purchase_stock/pyproject.toml | 3 +
.../readme/CONTRIBUTORS.md | 2 +
.../readme/DESCRIPTION.md | 2 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 427 ++++++++++++++++++
maintenance_purchase_stock/tests/__init__.py | 1 +
.../tests/test_maintenance_purchase_stock.py | 116 +++++
14 files changed, 728 insertions(+)
create mode 100644 maintenance_purchase_stock/README.rst
create mode 100644 maintenance_purchase_stock/__init__.py
create mode 100644 maintenance_purchase_stock/__manifest__.py
create mode 100644 maintenance_purchase_stock/i18n/es.po
create mode 100644 maintenance_purchase_stock/i18n/maintenance_purchase_stock.pot
create mode 100644 maintenance_purchase_stock/models/__init__.py
create mode 100644 maintenance_purchase_stock/models/purchase_order.py
create mode 100644 maintenance_purchase_stock/pyproject.toml
create mode 100644 maintenance_purchase_stock/readme/CONTRIBUTORS.md
create mode 100644 maintenance_purchase_stock/readme/DESCRIPTION.md
create mode 100644 maintenance_purchase_stock/static/description/icon.png
create mode 100644 maintenance_purchase_stock/static/description/index.html
create mode 100644 maintenance_purchase_stock/tests/__init__.py
create mode 100644 maintenance_purchase_stock/tests/test_maintenance_purchase_stock.py
diff --git a/maintenance_purchase_stock/README.rst b/maintenance_purchase_stock/README.rst
new file mode 100644
index 000000000..2377de305
--- /dev/null
+++ b/maintenance_purchase_stock/README.rst
@@ -0,0 +1,79 @@
+==========================
+Maintenance Purchase Stock
+==========================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:9b4e0b44d941b38aadf91a2912f84cf907a7e32f5e5573d36779fd044fa0f7f9
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmaintenance-lightgray.png?logo=github
+ :target: https://github.com/OCA/maintenance/tree/18.0/maintenance_purchase_stock
+ :alt: OCA/maintenance
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/maintenance-18-0/maintenance-18-0-maintenance_purchase_stock
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/maintenance&target_branch=18.0
+ :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+Adapt the module "Maintenance Purchase" to create the equipments at
+product reception
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+-------
+
+* Tecnativa
+
+Contributors
+------------
+
+- Tecnativa
+
+ - Christian Ramos
+
+Maintainers
+-----------
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+This module is part of the `OCA/maintenance `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/maintenance_purchase_stock/__init__.py b/maintenance_purchase_stock/__init__.py
new file mode 100644
index 000000000..0650744f6
--- /dev/null
+++ b/maintenance_purchase_stock/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/maintenance_purchase_stock/__manifest__.py b/maintenance_purchase_stock/__manifest__.py
new file mode 100644
index 000000000..7bd7ad96b
--- /dev/null
+++ b/maintenance_purchase_stock/__manifest__.py
@@ -0,0 +1,18 @@
+# Copyright 2025 Tecnativa
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+{
+ "name": "Maintenance Purchase Stock",
+ "summary": """
+ Create Equipments when recieving purchased products""",
+ "version": "18.0.1.0.0",
+ "license": "AGPL-3",
+ "author": "Tecnativa, Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/maintenance",
+ "depends": [
+ "maintenance_purchase",
+ "purchase_stock",
+ ],
+ "data": [],
+ "demo": [],
+}
diff --git a/maintenance_purchase_stock/i18n/es.po b/maintenance_purchase_stock/i18n/es.po
new file mode 100644
index 000000000..4441a05f3
--- /dev/null
+++ b/maintenance_purchase_stock/i18n/es.po
@@ -0,0 +1,26 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * maintenance_purchase
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 18.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: Ivorra78 \n"
+"Language-Team: none\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.17\n"
+
+#. module: maintenance_purchase_stock
+#: model:ir.model,name:maintenance_purchase_stock.model_purchase_order
+msgid "Purchase Order"
+msgstr "Orden de Compra"
+
+#. module: maintenance_purchase_stock
+#: model:ir.model,name:maintenance_purchase_stock.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr "Línea de Orden de Compra"
diff --git a/maintenance_purchase_stock/i18n/maintenance_purchase_stock.pot b/maintenance_purchase_stock/i18n/maintenance_purchase_stock.pot
new file mode 100644
index 000000000..979e38e6e
--- /dev/null
+++ b/maintenance_purchase_stock/i18n/maintenance_purchase_stock.pot
@@ -0,0 +1,24 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * maintenance_purchase_stock
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 18.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: maintenance_purchase_stock
+#: model:ir.model,name:maintenance_purchase_stock.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
+#. module: maintenance_purchase_stock
+#: model:ir.model,name:maintenance_purchase_stock.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
diff --git a/maintenance_purchase_stock/models/__init__.py b/maintenance_purchase_stock/models/__init__.py
new file mode 100644
index 000000000..9f0353064
--- /dev/null
+++ b/maintenance_purchase_stock/models/__init__.py
@@ -0,0 +1 @@
+from . import purchase_order
diff --git a/maintenance_purchase_stock/models/purchase_order.py b/maintenance_purchase_stock/models/purchase_order.py
new file mode 100644
index 000000000..ed67387b0
--- /dev/null
+++ b/maintenance_purchase_stock/models/purchase_order.py
@@ -0,0 +1,28 @@
+# Copyright 2025 Tecnativa
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import api, models
+
+
+class PurchaseOrder(models.Model):
+ _inherit = "purchase.order"
+
+ def _get_lines_to_create_equipments(self):
+ return (
+ super()
+ ._get_lines_to_create_equipments()
+ .filtered(lambda x: x.qty_received > len(x.equipment_ids))
+ )
+
+
+class PurchaseOrderLine(models.Model):
+ _inherit = "purchase.order.line"
+
+ def _qty_to_create_equipments(self):
+ return int(self.qty_received - len(self.equipment_ids))
+
+ @api.depends("move_ids.state", "move_ids.product_uom", "move_ids.quantity")
+ def _compute_qty_received(self):
+ res = super()._compute_qty_received()
+ self.order_id._create_equipments()
+ return res
diff --git a/maintenance_purchase_stock/pyproject.toml b/maintenance_purchase_stock/pyproject.toml
new file mode 100644
index 000000000..4231d0ccc
--- /dev/null
+++ b/maintenance_purchase_stock/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["whool"]
+build-backend = "whool.buildapi"
diff --git a/maintenance_purchase_stock/readme/CONTRIBUTORS.md b/maintenance_purchase_stock/readme/CONTRIBUTORS.md
new file mode 100644
index 000000000..060fc5f38
--- /dev/null
+++ b/maintenance_purchase_stock/readme/CONTRIBUTORS.md
@@ -0,0 +1,2 @@
+- Tecnativa
+ - Christian Ramos
diff --git a/maintenance_purchase_stock/readme/DESCRIPTION.md b/maintenance_purchase_stock/readme/DESCRIPTION.md
new file mode 100644
index 000000000..bf8486ae0
--- /dev/null
+++ b/maintenance_purchase_stock/readme/DESCRIPTION.md
@@ -0,0 +1,2 @@
+Adapt the module "Maintenance Purchase" to create the equipments
+at product reception
diff --git a/maintenance_purchase_stock/static/description/icon.png b/maintenance_purchase_stock/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
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
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/maintenance_purchase_stock/static/description/index.html b/maintenance_purchase_stock/static/description/index.html
new file mode 100644
index 000000000..4960ffbb5
--- /dev/null
+++ b/maintenance_purchase_stock/static/description/index.html
@@ -0,0 +1,427 @@
+
+
+
+
+
+Maintenance Purchase Stock
+
+
+
+
+
Maintenance Purchase Stock
+
+
+

+
Adapt the module “Maintenance Purchase” to create the equipments at
+product reception
+
Table of contents
+
+
+
+
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
This module is part of the OCA/maintenance project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/maintenance_purchase_stock/tests/__init__.py b/maintenance_purchase_stock/tests/__init__.py
new file mode 100644
index 000000000..2eb753c46
--- /dev/null
+++ b/maintenance_purchase_stock/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_maintenance_purchase_stock
diff --git a/maintenance_purchase_stock/tests/test_maintenance_purchase_stock.py b/maintenance_purchase_stock/tests/test_maintenance_purchase_stock.py
new file mode 100644
index 000000000..e505b6ca8
--- /dev/null
+++ b/maintenance_purchase_stock/tests/test_maintenance_purchase_stock.py
@@ -0,0 +1,116 @@
+# Copyright 2025 Tecnativa
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo.tests import tagged
+
+from odoo.addons.base.tests.common import BaseCommon
+
+
+@tagged("post_install", "-at_install")
+class TestMaintenancePurchaseStock(BaseCommon):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ cls.Equipment = cls.env["maintenance.equipment"]
+ cls.EquipmentCategory = cls.env["maintenance.equipment.category"]
+ cls.MaintenanceEquipmentCategory = cls.env["maintenance.equipment.category"]
+ cls.PurchaseOrder = cls.env["purchase.order"]
+ cls.PurchaseOrderLine = cls.env["purchase.order.line"]
+ cls.ProductCategory = cls.env["product.category"]
+ cls.ProductProduct = cls.env["product.product"]
+ cls.ResPartner = cls.env["res.partner"]
+
+ cls.partner = cls.ResPartner.create(
+ {
+ "name": "partner",
+ }
+ )
+ uom_unit = cls.env.ref("uom.product_uom_unit")
+ cls.maintenance_equipment_category1 = cls.MaintenanceEquipmentCategory.create(
+ {"name": "My Maintenance Equipment Category 1"}
+ )
+ cls.maintenance_equipment_category2 = cls.MaintenanceEquipmentCategory.create(
+ {"name": "My Maintenance Equipment Category 2"}
+ )
+ cls.product_category01 = cls.ProductCategory.create(
+ {
+ "name": "My Product Category 1",
+ }
+ )
+ cls.product_category02 = cls.ProductCategory.create(
+ {
+ "name": "My Product Category 2",
+ }
+ )
+ cls.product_order_maintenance = cls.ProductProduct.create(
+ {
+ "name": "My Product",
+ "standard_price": 235.0,
+ "list_price": 280.0,
+ "type": "consu",
+ "uom_id": uom_unit.id,
+ "uom_po_id": uom_unit.id,
+ "purchase_method": "purchase",
+ "default_code": "PROD_ORDER",
+ "taxes_id": False,
+ "categ_id": cls.product_category01.id,
+ "purchase_equipment_category_id": cls.maintenance_equipment_category1.id, # noqa E501
+ }
+ )
+ cls.product_order_no_maintenance = cls.ProductProduct.create(
+ {
+ "name": "My Product",
+ "standard_price": 235.0,
+ "list_price": 280.0,
+ "type": "consu",
+ "uom_id": uom_unit.id,
+ "uom_po_id": uom_unit.id,
+ "purchase_method": "purchase",
+ "default_code": "PROD_ORDER",
+ "taxes_id": False,
+ "categ_id": cls.product_category02.id,
+ }
+ )
+ cls.purchase_order = cls.PurchaseOrder.with_context(
+ tracking_disable=True
+ ).create(
+ {
+ "partner_id": cls.partner.id,
+ }
+ )
+ PurchaseOrderLine = cls.PurchaseOrderLine
+ cls.purchase_line_order01 = PurchaseOrderLine.create(
+ {
+ "name": cls.product_order_maintenance.name,
+ "product_id": cls.product_order_maintenance.id,
+ "product_qty": 10.0,
+ "product_uom": cls.product_order_maintenance.uom_id.id,
+ "price_unit": cls.product_order_maintenance.list_price,
+ "order_id": cls.purchase_order.id,
+ "taxes_id": False,
+ }
+ )
+ cls.purchase_line_order02 = PurchaseOrderLine.create(
+ {
+ "name": cls.product_order_no_maintenance.name,
+ "product_id": cls.product_order_no_maintenance.id,
+ "product_qty": 10.0,
+ "product_uom": cls.product_order_no_maintenance.uom_id.id,
+ "price_unit": cls.product_order_no_maintenance.list_price,
+ "order_id": cls.purchase_order.id,
+ "taxes_id": False,
+ }
+ )
+
+ def test_equipment_count(self):
+ self.purchase_order.button_approve()
+ self.assertEqual(self.purchase_order.equipment_count, 0)
+ self.assertEqual(self.purchase_line_order01.equipment_count, 0)
+ self.assertEqual(self.purchase_line_order02.equipment_count, 0)
+ self.purchase_order.picking_ids.button_validate()
+ self.purchase_order.order_line._compute_qty_received()
+ self.purchase_order.order_line._compute_equipment_count()
+ self.purchase_order._compute_equipment_count()
+ self.assertEqual(self.purchase_order.equipment_count, 10)
+ self.assertEqual(self.purchase_line_order01.equipment_count, 10)
From c74d482780b4d365d2e2195d867f86738880519f Mon Sep 17 00:00:00 2001
From: Vincent Van Rossem
Date: Thu, 9 Apr 2026 15:30:04 +0200
Subject: [PATCH 2/4] [IMP] maintenance_purchase_stock: pre-commit auto fixes
---
maintenance_purchase_stock/README.rst | 14 +++++++-------
.../static/description/index.html | 6 +++---
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/maintenance_purchase_stock/README.rst b/maintenance_purchase_stock/README.rst
index 2377de305..a1f7d0ef0 100644
--- a/maintenance_purchase_stock/README.rst
+++ b/maintenance_purchase_stock/README.rst
@@ -17,13 +17,13 @@ Maintenance Purchase Stock
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmaintenance-lightgray.png?logo=github
- :target: https://github.com/OCA/maintenance/tree/18.0/maintenance_purchase_stock
+ :target: https://github.com/OCA/maintenance/tree/17.0/maintenance_purchase_stock
:alt: OCA/maintenance
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/maintenance-18-0/maintenance-18-0-maintenance_purchase_stock
+ :target: https://translation.odoo-community.org/projects/maintenance-17-0/maintenance-17-0-maintenance_purchase_stock
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
- :target: https://runboat.odoo-community.org/builds?repo=OCA/maintenance&target_branch=18.0
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/maintenance&target_branch=17.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -42,7 +42,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues `_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -57,9 +57,9 @@ Authors
Contributors
------------
-- Tecnativa
+- Tecnativa
- - Christian Ramos
+ - Christian Ramos
Maintainers
-----------
@@ -74,6 +74,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-This module is part of the `OCA/maintenance `_ project on GitHub.
+This module is part of the `OCA/maintenance `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/maintenance_purchase_stock/static/description/index.html b/maintenance_purchase_stock/static/description/index.html
index 4960ffbb5..11137c2b6 100644
--- a/maintenance_purchase_stock/static/description/index.html
+++ b/maintenance_purchase_stock/static/description/index.html
@@ -369,7 +369,7 @@ Maintenance Purchase Stock
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:9b4e0b44d941b38aadf91a2912f84cf907a7e32f5e5573d36779fd044fa0f7f9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

Adapt the module “Maintenance Purchase” to create the equipments at
product reception
Table of contents
@@ -389,7 +389,7 @@
Bugs are tracked on GitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
-feedback.
+feedback.
Do not contact contributors directly about support or help with technical issues.
@@ -418,7 +418,7 @@
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-
This module is part of the OCA/maintenance project on GitHub.
+
This module is part of the OCA/maintenance project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
From 843ad4006221df6dfee2bafe789800500e2df6df Mon Sep 17 00:00:00 2001
From: Vincent Van Rossem
Date: Thu, 9 Apr 2026 15:32:54 +0200
Subject: [PATCH 3/4] [BACKPORT] maintenance_purchase_stock: Backport from 18.0
to 17.0
---
maintenance_purchase_stock/__manifest__.py | 2 +-
maintenance_purchase_stock/models/__init__.py | 1 +
.../models/purchase_order.py | 8 +-------
maintenance_purchase_stock/models/stock_move.py | 14 ++++++++++++++
4 files changed, 17 insertions(+), 8 deletions(-)
create mode 100644 maintenance_purchase_stock/models/stock_move.py
diff --git a/maintenance_purchase_stock/__manifest__.py b/maintenance_purchase_stock/__manifest__.py
index 7bd7ad96b..a5d50f31f 100644
--- a/maintenance_purchase_stock/__manifest__.py
+++ b/maintenance_purchase_stock/__manifest__.py
@@ -5,7 +5,7 @@
"name": "Maintenance Purchase Stock",
"summary": """
Create Equipments when recieving purchased products""",
- "version": "18.0.1.0.0",
+ "version": "17.0.1.0.0",
"license": "AGPL-3",
"author": "Tecnativa, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/maintenance",
diff --git a/maintenance_purchase_stock/models/__init__.py b/maintenance_purchase_stock/models/__init__.py
index 9f0353064..aa008762d 100644
--- a/maintenance_purchase_stock/models/__init__.py
+++ b/maintenance_purchase_stock/models/__init__.py
@@ -1 +1,2 @@
from . import purchase_order
+from . import stock_move
diff --git a/maintenance_purchase_stock/models/purchase_order.py b/maintenance_purchase_stock/models/purchase_order.py
index ed67387b0..17bab2503 100644
--- a/maintenance_purchase_stock/models/purchase_order.py
+++ b/maintenance_purchase_stock/models/purchase_order.py
@@ -1,7 +1,7 @@
# Copyright 2025 Tecnativa
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from odoo import api, models
+from odoo import models
class PurchaseOrder(models.Model):
@@ -20,9 +20,3 @@ class PurchaseOrderLine(models.Model):
def _qty_to_create_equipments(self):
return int(self.qty_received - len(self.equipment_ids))
-
- @api.depends("move_ids.state", "move_ids.product_uom", "move_ids.quantity")
- def _compute_qty_received(self):
- res = super()._compute_qty_received()
- self.order_id._create_equipments()
- return res
diff --git a/maintenance_purchase_stock/models/stock_move.py b/maintenance_purchase_stock/models/stock_move.py
new file mode 100644
index 000000000..91e6d124e
--- /dev/null
+++ b/maintenance_purchase_stock/models/stock_move.py
@@ -0,0 +1,14 @@
+# Copyright 2025 Tecnativa
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import models
+
+
+class StockMove(models.Model):
+ _inherit = "stock.move"
+
+ def _action_done(self, cancel_backorder=False):
+ res = super()._action_done(cancel_backorder=cancel_backorder)
+ purchase_orders = self.mapped("purchase_line_id.order_id")
+ purchase_orders._create_equipments()
+ return res
From 150ba286b69f3eaf7e75c271e48054d7217284a3 Mon Sep 17 00:00:00 2001
From: Vincent Van Rossem
Date: Thu, 9 Apr 2026 15:41:27 +0200
Subject: [PATCH 4/4] [DO NOT MERGE] add test-requirements.txt
---
test-requirements.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test-requirements.txt
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 000000000..8003724b6
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1 @@
+odoo-addon-maintenance_purchase @ git+https://github.com/OCA/maintenance.git@refs/pull/552/head#subdirectory=maintenance_purchase