mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-20 07:22:13 +00:00
* fix: priority not working for multiple pricing rules (#41516)
(cherry picked from commit 5cf5b18aea)
# Conflicts:
# erpnext/accounts/doctype/pricing_rule/pricing_rule.json
* chore: fix conflicts
---------
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
This commit is contained in:
@@ -74,15 +74,21 @@
|
|||||||
"discount_amount",
|
"discount_amount",
|
||||||
"discount_percentage",
|
"discount_percentage",
|
||||||
"for_price_list",
|
"for_price_list",
|
||||||
"section_break_13",
|
"dynamic_condition_tab",
|
||||||
"threshold_percentage",
|
|
||||||
"priority",
|
|
||||||
"condition",
|
"condition",
|
||||||
"column_break_66",
|
"section_break_13",
|
||||||
"apply_multiple_pricing_rules",
|
"apply_multiple_pricing_rules",
|
||||||
"apply_discount_on_rate",
|
"apply_discount_on_rate",
|
||||||
|
"column_break_66",
|
||||||
|
"threshold_percentage",
|
||||||
|
"validate_pricing_rule_section",
|
||||||
"validate_applied_rule",
|
"validate_applied_rule",
|
||||||
|
"column_break_texp",
|
||||||
"rule_description",
|
"rule_description",
|
||||||
|
"priority_section",
|
||||||
|
"has_priority",
|
||||||
|
"column_break_sayg",
|
||||||
|
"priority",
|
||||||
"help_section",
|
"help_section",
|
||||||
"pricing_rule_help",
|
"pricing_rule_help",
|
||||||
"reference_section",
|
"reference_section",
|
||||||
@@ -477,7 +483,7 @@
|
|||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "section_break_13",
|
"fieldname": "section_break_13",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Tab Break",
|
||||||
"label": "Advanced Settings"
|
"label": "Advanced Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -487,6 +493,7 @@
|
|||||||
"label": "Threshold for Suggestion (In Percentage)"
|
"label": "Threshold for Suggestion (In Percentage)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "has_priority",
|
||||||
"description": "Higher the number, higher the priority",
|
"description": "Higher the number, higher the priority",
|
||||||
"fieldname": "priority",
|
"fieldname": "priority",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@@ -513,6 +520,7 @@
|
|||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"depends_on": "eval:doc.price_or_product_discount == 'Price'",
|
"depends_on": "eval:doc.price_or_product_discount == 'Price'",
|
||||||
|
"description": "If enabled, then system will only validate the pricing rule and not apply automatically. User has to manually set the discount percentage / margin / free items to validate the pricing rule",
|
||||||
"fieldname": "validate_applied_rule",
|
"fieldname": "validate_applied_rule",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Validate Applied Rule"
|
"label": "Validate Applied Rule"
|
||||||
@@ -525,7 +533,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "help_section",
|
"fieldname": "help_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Help Article",
|
||||||
"options": "Simple"
|
"options": "Simple"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -603,12 +612,42 @@
|
|||||||
"fieldname": "apply_recursion_over",
|
"fieldname": "apply_recursion_over",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Apply Recursion Over (As Per Transaction UOM)"
|
"label": "Apply Recursion Over (As Per Transaction UOM)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "priority_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Priority"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dynamic_condition_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Dynamic Condition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "validate_pricing_rule_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Validate Pricing Rule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_texp",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_sayg",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Enable this checkbox even if you want to set the zero priority",
|
||||||
|
"fieldname": "has_priority",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Has Priority"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-gift",
|
"icon": "fa fa-gift",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-02-14 04:53:34.887358",
|
"modified": "2024-05-17 13:16:34.496704",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Pricing Rule",
|
"name": "Pricing Rule",
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ class PricingRule(Document):
|
|||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
from erpnext.accounts.doctype.pricing_rule_brand.pricing_rule_brand import PricingRuleBrand
|
from erpnext.accounts.doctype.pricing_rule_brand.pricing_rule_brand import PricingRuleBrand
|
||||||
from erpnext.accounts.doctype.pricing_rule_item_code.pricing_rule_item_code import (
|
from erpnext.accounts.doctype.pricing_rule_item_code.pricing_rule_item_code import PricingRuleItemCode
|
||||||
PricingRuleItemCode,
|
|
||||||
)
|
|
||||||
from erpnext.accounts.doctype.pricing_rule_item_group.pricing_rule_item_group import (
|
from erpnext.accounts.doctype.pricing_rule_item_group.pricing_rule_item_group import (
|
||||||
PricingRuleItemGroup,
|
PricingRuleItemGroup,
|
||||||
)
|
)
|
||||||
@@ -67,6 +65,7 @@ class PricingRule(Document):
|
|||||||
free_item_rate: DF.Currency
|
free_item_rate: DF.Currency
|
||||||
free_item_uom: DF.Link | None
|
free_item_uom: DF.Link | None
|
||||||
free_qty: DF.Float
|
free_qty: DF.Float
|
||||||
|
has_priority: DF.Check
|
||||||
is_cumulative: DF.Check
|
is_cumulative: DF.Check
|
||||||
is_recursive: DF.Check
|
is_recursive: DF.Check
|
||||||
item_groups: DF.Table[PricingRuleItemGroup]
|
item_groups: DF.Table[PricingRuleItemGroup]
|
||||||
@@ -156,6 +155,12 @@ class PricingRule(Document):
|
|||||||
frappe.throw(_("Duplicate {0} found in the table").format(self.apply_on))
|
frappe.throw(_("Duplicate {0} found in the table").format(self.apply_on))
|
||||||
|
|
||||||
def validate_mandatory(self):
|
def validate_mandatory(self):
|
||||||
|
if self.has_priority and not self.priority:
|
||||||
|
throw(_("Priority is mandatory"), frappe.MandatoryError, _("Please Set Priority"))
|
||||||
|
|
||||||
|
if self.priority and not self.has_priority:
|
||||||
|
self.has_priority = 1
|
||||||
|
|
||||||
for apply_on, field in apply_on_dict.items():
|
for apply_on, field in apply_on_dict.items():
|
||||||
if self.apply_on == apply_on and len(self.get(field) or []) < 1:
|
if self.apply_on == apply_on and len(self.get(field) or []) < 1:
|
||||||
throw(_("{0} is not added in the table").format(apply_on), frappe.MandatoryError)
|
throw(_("{0} is not added in the table").format(apply_on), frappe.MandatoryError)
|
||||||
|
|||||||
@@ -1157,6 +1157,62 @@ class TestPricingRule(unittest.TestCase):
|
|||||||
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
|
||||||
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")
|
||||||
|
|
||||||
|
def test_priority_of_multiple_pricing_rules(self):
|
||||||
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
|
||||||
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")
|
||||||
|
|
||||||
|
test_record = {
|
||||||
|
"doctype": "Pricing Rule",
|
||||||
|
"title": "_Test Pricing Rule 1",
|
||||||
|
"name": "_Test Pricing Rule 1",
|
||||||
|
"apply_on": "Item Code",
|
||||||
|
"currency": "USD",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selling": 1,
|
||||||
|
"price_or_product_discount": "Price",
|
||||||
|
"rate_or_discount": "Discount Percentage",
|
||||||
|
"discount_percentage": 10,
|
||||||
|
"has_priority": 1,
|
||||||
|
"priority": 1,
|
||||||
|
"company": "_Test Company",
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.get_doc(test_record.copy()).insert()
|
||||||
|
|
||||||
|
test_record = {
|
||||||
|
"doctype": "Pricing Rule",
|
||||||
|
"title": "_Test Pricing Rule 2",
|
||||||
|
"name": "_Test Pricing Rule 2",
|
||||||
|
"apply_on": "Item Code",
|
||||||
|
"currency": "USD",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selling": 1,
|
||||||
|
"price_or_product_discount": "Price",
|
||||||
|
"rate_or_discount": "Discount Percentage",
|
||||||
|
"discount_percentage": 20,
|
||||||
|
"has_priority": 1,
|
||||||
|
"priority": 3,
|
||||||
|
"company": "_Test Company",
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.get_doc(test_record.copy()).insert()
|
||||||
|
|
||||||
|
so = make_sales_order(item_code="_Test Item", qty=1, price_list_rate=1000, do_not_submit=True)
|
||||||
|
self.assertEqual(so.items[0].discount_percentage, 20)
|
||||||
|
self.assertEqual(so.items[0].rate, 800)
|
||||||
|
|
||||||
|
frappe.delete_doc_if_exists("Sales Order", so.name)
|
||||||
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
|
||||||
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")
|
||||||
|
|
||||||
|
|
||||||
test_dependencies = ["Campaign"]
|
test_dependencies = ["Campaign"]
|
||||||
|
|
||||||
@@ -1185,6 +1241,7 @@ def make_pricing_rule(**args):
|
|||||||
"priority": args.priority or 1,
|
"priority": args.priority or 1,
|
||||||
"discount_amount": args.discount_amount or 0.0,
|
"discount_amount": args.discount_amount or 0.0,
|
||||||
"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0,
|
"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0,
|
||||||
|
"has_priority": args.has_priority or 0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ def get_pricing_rules(args, doc=None):
|
|||||||
|
|
||||||
for apply_on in ["Item Code", "Item Group", "Brand"]:
|
for apply_on in ["Item Code", "Item Group", "Brand"]:
|
||||||
pricing_rules.extend(_get_pricing_rules(apply_on, args, values))
|
pricing_rules.extend(_get_pricing_rules(apply_on, args, values))
|
||||||
|
if pricing_rules and pricing_rules[0].has_priority:
|
||||||
|
continue
|
||||||
|
|
||||||
if pricing_rules and not apply_multiple_pricing_rules(pricing_rules):
|
if pricing_rules and not apply_multiple_pricing_rules(pricing_rules):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
@@ -364,3 +364,4 @@ erpnext.patches.v15_0.delete_orphaned_asset_movement_item_records
|
|||||||
erpnext.patches.v15_0.fix_debit_credit_in_transaction_currency
|
erpnext.patches.v15_0.fix_debit_credit_in_transaction_currency
|
||||||
erpnext.patches.v15_0.remove_cancelled_asset_capitalization_from_asset
|
erpnext.patches.v15_0.remove_cancelled_asset_capitalization_from_asset
|
||||||
erpnext.patches.v15_0.rename_purchase_receipt_amount_to_purchase_amount
|
erpnext.patches.v15_0.rename_purchase_receipt_amount_to_purchase_amount
|
||||||
|
erpnext.patches.v14_0.enable_set_priority_for_pricing_rules #1
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
pr_table = frappe.qb.DocType("Pricing Rule")
|
||||||
|
(
|
||||||
|
frappe.qb.update(pr_table)
|
||||||
|
.set(pr_table.has_priority, 1)
|
||||||
|
.where((pr_table.priority.isnotnull()) & (pr_table.priority != ""))
|
||||||
|
).run()
|
||||||
Reference in New Issue
Block a user