diff --git a/deltatech_purchase_add_extra_line/README.rst b/deltatech_purchase_add_extra_line/README.rst new file mode 100644 index 0000000000..5eeb9d231e --- /dev/null +++ b/deltatech_purchase_add_extra_line/README.rst @@ -0,0 +1,105 @@ +======================= +Purchase Add Extra Line +======================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:c062bc9c14aec836be0e0e0622364b98825b7133ec9c7093f624fe57f88ddb88 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-dhongu%2Fdeltatech-lightgray.png?logo=github + :target: https://github.com/dhongu/deltatech/tree/18.0/deltatech_purchase_add_extra_line + :alt: dhongu/deltatech + +|badge1| |badge2| |badge3| + +Purchase Add Extra Line Extension +================================= + +This module introduces an automated process for adding extra lines +(e.g., service fees, handling charges, or supplementary products) to +Purchase Orders in Odoo. It's designed to help procurement teams +consistently apply additional costs or items based on the primary +products being purchased. + +Key Features +============ + +1. **Configurable Extra Products**: + + - Allows users to define an **Extra Product** directly on the product + template. + - Enables automated adding of this extra line whenever the primary + product is added to a Purchase Order. + +2. **Flexible Pricing Logic**: + + - The unit price for the extra line can be computed as a + **percentage** of the primary product's price. + - If the percentage is set to zero, the system uses the standard + **List Price** of the extra product. + +3. **Procurement Efficiency**: + + - Reduces manual entry errors and ensures that all mandatory + supplementary costs or items are included in every relevant + Purchase Order. + +Usage +===== + +1. Go to **Purchase > Products > Products**. +2. Open a product and locate the **Extra Line Configuration** (typically + in the Purchase or a dedicated tab). +3. Select the **Extra Product** you want to associate and set the + **Percentage** (if applicable). +4. Create a new **Purchase Order** and add the primary product to the + order lines. +5. The system will automatically add the extra product as a separate + line with the pre-calculated price. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `Terrabit Issues `_. +In case of trouble, please check there if your issue has already been reported. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Terrabit +* Dorin Hongu + +Maintainers +----------- + +.. |maintainer-dhongu| image:: https://github.com/dhongu.png?size=40px + :target: https://github.com/dhongu + :alt: dhongu + +Current maintainer: + +|maintainer-dhongu| + +This module is part of the `dhongu/deltatech `_ project on GitHub. + +You are welcome to contribute. \ No newline at end of file diff --git a/deltatech_purchase_add_extra_line/__init__.py b/deltatech_purchase_add_extra_line/__init__.py new file mode 100644 index 0000000000..58fcc5c01e --- /dev/null +++ b/deltatech_purchase_add_extra_line/__init__.py @@ -0,0 +1,4 @@ +# © 2025 Deltatech +# See README.rst file on addons root folder for license details + +from . import models diff --git a/deltatech_purchase_add_extra_line/__manifest__.py b/deltatech_purchase_add_extra_line/__manifest__.py new file mode 100644 index 0000000000..1b729b11ae --- /dev/null +++ b/deltatech_purchase_add_extra_line/__manifest__.py @@ -0,0 +1,17 @@ +# © 2025 Deltatech +# See README.rst file on addons root folder for license details + +{ + "name": "Purchase Add Extra Line", + "summary": "Purchase Add Extra Line", + "version": "19.0.1.0.2", + "category": "Sales", + "author": "Terrabit, Dorin Hongu", + "website": "https://www.terrabit.ro", + "depends": ["purchase"], + "license": "LGPL-3", + "data": ["views/product_view.xml", "views/purchase_view.xml"], + "images": ["static/description/main_screenshot.png"], + "development_status": "Production/Stable", + "maintainers": ["dhongu"], +} diff --git a/deltatech_purchase_add_extra_line/models/__init__.py b/deltatech_purchase_add_extra_line/models/__init__.py new file mode 100644 index 0000000000..ef4fbed961 --- /dev/null +++ b/deltatech_purchase_add_extra_line/models/__init__.py @@ -0,0 +1,6 @@ +# © 2025 Deltatech +# See README.rst file on addons root folder for license details + + +from . import product_template +from . import purchase diff --git a/deltatech_purchase_add_extra_line/models/product_template.py b/deltatech_purchase_add_extra_line/models/product_template.py new file mode 100644 index 0000000000..dd272a661c --- /dev/null +++ b/deltatech_purchase_add_extra_line/models/product_template.py @@ -0,0 +1,14 @@ +# © 2025 Deltatech +# Dorin Hongu Products > Products**. +2. Open a product and locate the **Extra Line Configuration** (typically in the Purchase or a dedicated tab). +3. Select the **Extra Product** you want to associate and set the **Percentage** (if applicable). +4. Create a new **Purchase Order** and add the primary product to the order lines. +5. The system will automatically add the extra product as a separate line with the pre-calculated price. diff --git a/deltatech_purchase_add_extra_line/static/description/icon.png b/deltatech_purchase_add_extra_line/static/description/icon.png new file mode 100644 index 0000000000..ad6e34df77 Binary files /dev/null and b/deltatech_purchase_add_extra_line/static/description/icon.png differ diff --git a/deltatech_purchase_add_extra_line/static/description/index.html b/deltatech_purchase_add_extra_line/static/description/index.html new file mode 100644 index 0000000000..a506e5648e --- /dev/null +++ b/deltatech_purchase_add_extra_line/static/description/index.html @@ -0,0 +1,446 @@ + + + + + +Purchase Add Extra Line + + + +
+

Purchase Add Extra Line

+ + +

Production/Stable License: LGPL-3 dhongu/deltatech

+
+

Purchase Add Extra Line Extension

+

This module introduces an automated process for adding extra lines +(e.g., service fees, handling charges, or supplementary products) to +Purchase Orders in Odoo. It’s designed to help procurement teams +consistently apply additional costs or items based on the primary +products being purchased.

+
+
+

Key Features

+
    +
  1. Configurable Extra Products:
      +
    • Allows users to define an Extra Product directly on the product +template.
    • +
    • Enables automated adding of this extra line whenever the primary +product is added to a Purchase Order.
    • +
    +
  2. +
  3. Flexible Pricing Logic:
      +
    • The unit price for the extra line can be computed as a +percentage of the primary product’s price.
    • +
    • If the percentage is set to zero, the system uses the standard +List Price of the extra product.
    • +
    +
  4. +
  5. Procurement Efficiency:
      +
    • Reduces manual entry errors and ensures that all mandatory +supplementary costs or items are included in every relevant +Purchase Order.
    • +
    +
  6. +
+
+
+

Usage

+
    +
  1. Go to Purchase > Products > Products.
  2. +
  3. Open a product and locate the Extra Line Configuration (typically +in the Purchase or a dedicated tab).
  4. +
  5. Select the Extra Product you want to associate and set the +Percentage (if applicable).
  6. +
  7. Create a new Purchase Order and add the primary product to the +order lines.
  8. +
  9. The system will automatically add the extra product as a separate +line with the pre-calculated price.
  10. +
+

Table of contents

+
+
+

Bug Tracker

+

Bugs are tracked on Terrabit Issues. +In case of trouble, please check there if your issue has already been reported.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Terrabit
  • +
  • Dorin Hongu
  • +
+
+
+

Maintainers

+

Current maintainer:

+

dhongu

+

This module is part of the dhongu/deltatech project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/deltatech_purchase_add_extra_line/static/description/logo-terrabit.png b/deltatech_purchase_add_extra_line/static/description/logo-terrabit.png new file mode 100644 index 0000000000..8b23ccdd37 Binary files /dev/null and b/deltatech_purchase_add_extra_line/static/description/logo-terrabit.png differ diff --git a/deltatech_purchase_add_extra_line/static/description/main_screenshot.png b/deltatech_purchase_add_extra_line/static/description/main_screenshot.png new file mode 100644 index 0000000000..4292c67867 Binary files /dev/null and b/deltatech_purchase_add_extra_line/static/description/main_screenshot.png differ diff --git a/deltatech_purchase_add_extra_line/tests/__init__.py b/deltatech_purchase_add_extra_line/tests/__init__.py new file mode 100644 index 0000000000..cdc51e8650 --- /dev/null +++ b/deltatech_purchase_add_extra_line/tests/__init__.py @@ -0,0 +1,5 @@ +# © 2025 Deltatech +# Dorin Hongu +# See README.rst file on addons root folder for license details + +from odoo.tests import Form +from odoo.tests.common import TransactionCase + + +class TestPurchaseAddExtraLine(TransactionCase): + def setUp(self): + super().setUp() + # Create a vendor + self.vendor = self.env["res.partner"].create({"name": "Vendor A", "supplier_rank": 1}) + + seller_ids = [(0, 0, {"partner_id": self.vendor.id})] + + # Extra product (will be auto-added) + self.extra_product = self.env["product.product"].create( + { + "name": "Extra Product", + "type": "consu", + "standard_price": 20.0, + "list_price": 30.0, + "seller_ids": seller_ids, + } + ) + # Main product configured to add the extra product + self.main_product = self.env["product.product"].create( + { + "name": "Main Product", + "type": "consu", + "standard_price": 100.0, + "list_price": 150.0, + "seller_ids": seller_ids, + "extra_product_id": self.extra_product.id, + "extra_percent": 10.0, # price of extra line = 10% of main line price + "extra_qty": 2.0, # qty of extra line = 2x main qty + } + ) + + def test_purchase_extra_line_creation_update_and_unlink(self): + # Create RFQ + po_form = Form(self.env["purchase.order"]) + po_form.partner_id = self.vendor + with po_form.order_line.new() as line_form: + line_form.product_id = self.main_product + line_form.product_qty = 5 + po = po_form.save() + + # After saving, an extra line should be present + self.assertEqual(len(po.order_line), 2, "There should be two lines: main and extra") + + # Identify lines + main_line = po.order_line.filtered(lambda l: l.product_id == self.main_product) + self.assertEqual(len(main_line), 1, "Exactly one main line expected") + extra_line = po.order_line.filtered(lambda l: l.product_id == self.extra_product) + self.assertEqual(len(extra_line), 1, "Exactly one extra line expected") + + # Both lines should share the same line_uuid + self.assertTrue(main_line.line_uuid, "Main line must have a line_uuid set") + self.assertEqual( + main_line.line_uuid, + extra_line.line_uuid, + "Main and extra lines should share the same line_uuid", + ) + + # Quantities and price unit checks + self.assertEqual( + extra_line.product_qty, + 5 * 2.0, + "Extra line quantity should be main_qty * extra_qty", + ) + # price_unit of extra line = main price * extra_percent / 100 + self.assertAlmostEqual( + extra_line.price_unit, + main_line.price_unit * 0.10, + msg="Extra line price should be 10% of main line price", + ) + + # Update main quantity and re-check propagation + main_line.product_qty = 7 + # In a real form, onchange would handle this; call method explicitly for the test + main_line.check_extra_product() + self.assertEqual( + extra_line.product_qty, + 7 * 2.0, + "After update, extra line quantity should follow main qty", + ) + + # Deleting main line should remove the paired extra line too + main_line.unlink() + self.assertEqual(len(po.order_line), 0, "Both main and extra lines should be removed after unlink") diff --git a/deltatech_purchase_add_extra_line/views/product_view.xml b/deltatech_purchase_add_extra_line/views/product_view.xml new file mode 100644 index 0000000000..264260bcbd --- /dev/null +++ b/deltatech_purchase_add_extra_line/views/product_view.xml @@ -0,0 +1,19 @@ + + + + + product.template.form + product.template + + + + + + + + + + + + + diff --git a/deltatech_purchase_add_extra_line/views/purchase_view.xml b/deltatech_purchase_add_extra_line/views/purchase_view.xml new file mode 100644 index 0000000000..90135bce6f --- /dev/null +++ b/deltatech_purchase_add_extra_line/views/purchase_view.xml @@ -0,0 +1,15 @@ + + + + + purchase.order.form.extra + purchase.order + + + + + + + + +