Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions sale_pricelist_global_rule/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
==========================
Sale pricelist global rule
==========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:5cb63290b669d0a75e8eb06e51a6be5653dc3de78c4fbab7a7700fa5a2a852dd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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%2Fsale--workflow-lightgray.png?logo=github
:target: https://github.com/OCA/sale-workflow/tree/18.0/sale_pricelist_global_rule
:alt: OCA/sale-workflow
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_pricelist_global_rule
: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/sale-workflow&target_branch=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module introduces a new apply-on option **``3_global``** in the
field ``display_applied_on``.

When this option is selected, the module displays a new field
``global_applied_on``, allowing the user to choose how the global
pricelist rule should be applied:

- **Global – Product Template**
- **Global – Product Category**
- **Global – Ancestor Product Category**

This expands Odoo’s standard behavior by allowing pricelist rules to be
computed based on cumulative quantities across templates, categories, or
ancestor category trees.

--------------

Cumulative Quantities in Pricelists
-----------------------------------

This module allows configured pricelists to be applied to a sales order
by considering cumulative quantities across all lines.

**Global by Product Template**

If a pricelist rule has a min_quantity = 15, and a sales order contains:

- Line 1: Variant 1, quantity = 8
- Line 2: Variant 2, quantity = 8

**Global by Product Category**

Similarly, if a pricelist rule has a min_quantity = 20 for products
within a category, and a sales order includes:

- Line 1: Product 1, quantity = 10
- Line 2: Product 2, quantity = 10

In standard Odoo, pricelist rules would not apply since no single line
meets the minimum quantity. With this module, however, cumulative
quantities across lines allow the pricelist rule to apply, as they meet
the minimum threshold (16 in the product template example and 20 in the
product category example).

**Global by Ancestor Product Category**

This option allows defining a rule on an *ancestor category*, and it
will apply to all products that belong to this category or any of its
descendants. The minimum quantity check is performed on the **total
ordered quantity** across all descendant categories.

For example, suppose we have the following category tree:

- Cat A

- Cat B
- Cat C

- Cat D

And a pricelist rule is configured on *Cat C* with a minimum quantity =
5 and a 20% discount. If a sales order contains:

- Line 1: Product in Cat C, quantity = 4
- Line 2: Product in Cat D, quantity = 2

Then the total for Cat C’s branch = 6 (4 + 2), which meets the minimum
threshold of 5. As a result, the 20% discount rule applies to both
lines.

**Table of contents**

.. contents::
:local:

Configuration
=============

- Go to **Sales → Products → Pricelists**.
- Create a new Pricelist and add at least one line with the *Apply On*
option set to **Global - Product Template**, **Global - Product Category**, or
**Global - Ancestor Product Category**.
- When using *Ancestor Product Category*, select the top-level or ancestor
category that will include all of its descendant categories.
- Choose the specific product, template, or category for the rule.
- Set the computation mode (e.g., percentage discount) and save.

Usage
=====

- Go to Sales -> Orders -> Quotations.
- Create a new record and fill the required fields.
- Choose a Pricelist that has a global rule configured (either by
Category or Product).
- Click the **Recompute pricelist global** button to update prices
according to the specified pricelist rules.
- When using **Ancestor Product Category**, the system will sum the ordered
quantities of all products belonging to the selected ancestor category
and all its descendants.
If the accumulated quantity meets the rule’s minimum quantity, the
discount will be applied to each matching order line.
- When multiple percentage-based rules apply, the system automatically
selects the **highest discount available**, ensuring that the most
beneficial rule is applied to the sale order.

Known issues / Roadmap
======================

- Implement automatic application of the pricelist whenever changes are
made to order lines (such as prices, quantities, etc.) or to the
pricelist itself, eliminating the need for manual button clicks.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-workflow/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 <https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_pricelist_global_rule%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
-------

* Tecnativa

Contributors
------------

- `Tecnativa <https://www.tecnativa.com>`__

- Pedro M. Baeza
- Carlos López

- `Komit-consulting <https://komit-consulting.com/>`__

- Duc Truong

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/sale-workflow <https://github.com/OCA/sale-workflow/tree/18.0/sale_pricelist_global_rule>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions sale_pricelist_global_rule/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
14 changes: 14 additions & 0 deletions sale_pricelist_global_rule/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "Sale pricelist global rule",
"version": "18.0.1.0.0",
"summary": "Apply a global rule to all sale order",
"author": "Tecnativa, Odoo Community Association (OCA)",
"category": "Sales Management",
"website": "https://github.com/OCA/sale-workflow",
"depends": [
"sale",
],
"data": ["views/product_pricelist_item_views.xml", "views/sale_order_views.xml"],
"installable": True,
"license": "AGPL-3",
}
111 changes: 111 additions & 0 deletions sale_pricelist_global_rule/i18n/it.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_pricelist_global_rule
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-02-25 15:06+0000\n"
"Last-Translator: mymage <[email protected]>\n"
"Language-Team: none\n"
"Language: it\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 5.6.2\n"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields,field_description:sale_pricelist_global_rule.field_product_pricelist_item__applied_on
msgid "Apply On"
msgstr "Applica a"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields.selection,name:sale_pricelist_global_rule.selection__product_pricelist_item__applied_on__3_2_global_product_category
msgid "Global - Product category"
msgstr "Globale - Categoria prodotto"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields.selection,name:sale_pricelist_global_rule.selection__product_pricelist_item__applied_on__3_1_global_product_template
msgid "Global - Product template"
msgstr "Globale - Modello prodotto"

#. module: sale_pricelist_global_rule
#. odoo-python
#: code:addons/sale_pricelist_global_rule/models/product_pricelist.py:0
#, python-format
msgid "Global category: %s"
msgstr "Categoria globale: %s"

#. module: sale_pricelist_global_rule
#. odoo-python
#: code:addons/sale_pricelist_global_rule/models/product_pricelist.py:0
#, python-format
msgid "Global product: %s"
msgstr "Prodotto globale: %s"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields,field_description:sale_pricelist_global_rule.field_sale_order__has_pricelist_global
msgid "Has Pricelist Global"
msgstr "Ha listino globale"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields,field_description:sale_pricelist_global_rule.field_sale_order__need_recompute_pricelist_global
msgid "Need Recompute Pricelist Global"
msgstr "Richiede ricalcolo listino globale"

#. module: sale_pricelist_global_rule
#. odoo-python
#: code:addons/sale_pricelist_global_rule/models/product_pricelist.py:0
#, python-format
msgid ""
"Please specify the category for which this global rule should be applied"
msgstr ""
"Indicare la categoria per la quale questa regola globale dovrebbe essere "
"applicata"

#. module: sale_pricelist_global_rule
#. odoo-python
#: code:addons/sale_pricelist_global_rule/models/product_pricelist.py:0
#, python-format
msgid ""
"Please specify the product for which this global rule should be applied"
msgstr ""
"Indicare il prodotto per il quale questa regola globale dovrebbe essere "
"applicata"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields,help:sale_pricelist_global_rule.field_product_pricelist_item__applied_on
msgid "Pricelist Item applicable on selected option"
msgstr "Riga listino applicabile all'opzione selezionata"

#. module: sale_pricelist_global_rule
#: model:ir.model,name:sale_pricelist_global_rule.model_product_pricelist_item
msgid "Pricelist Rule"
msgstr "Regola listino prezzi"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields,field_description:sale_pricelist_global_rule.field_product_pricelist_item__global_product_tmpl_id
msgid "Product"
msgstr "Prodotto"

#. module: sale_pricelist_global_rule
#: model:ir.model.fields,field_description:sale_pricelist_global_rule.field_product_pricelist_item__global_categ_id
msgid "Product Category"
msgstr "Categoria prodotto"

#. module: sale_pricelist_global_rule
#: model_terms:ir.ui.view,arch_db:sale_pricelist_global_rule.view_sale_order_form
msgid "Recompute pricelist global"
msgstr "Ricalcola listino globale"

#. module: sale_pricelist_global_rule
#: model:ir.model,name:sale_pricelist_global_rule.model_sale_order
msgid "Sales Order"
msgstr "Ordine di vendita"

#. module: sale_pricelist_global_rule
#: model:ir.model,name:sale_pricelist_global_rule.model_sale_order_line
msgid "Sales Order Line"
msgstr "Riga ordine di vendita"
Loading
Loading