fix: multiple pricing rules are not working on selling side
This commit is contained in:
parent
1dd54e457d
commit
a248dfb9a5
@ -60,6 +60,15 @@ class PricingRule(Document):
|
|||||||
if self.price_or_product_discount == 'Price' and not self.rate_or_discount:
|
if self.price_or_product_discount == 'Price' and not self.rate_or_discount:
|
||||||
throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError)
|
throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError)
|
||||||
|
|
||||||
|
if self.apply_discount_on_rate:
|
||||||
|
if not self.priority:
|
||||||
|
throw(_("As the field {0} is enabled, the field {1} is mandatory.")
|
||||||
|
.format(frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority")))
|
||||||
|
|
||||||
|
if self.priority and cint(self.priority) == 1:
|
||||||
|
throw(_("As the field {0} is enabled, the value of the field {1} should be more than 1.")
|
||||||
|
.format(frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority")))
|
||||||
|
|
||||||
def validate_applicable_for_selling_or_buying(self):
|
def validate_applicable_for_selling_or_buying(self):
|
||||||
if not self.selling and not self.buying:
|
if not self.selling and not self.buying:
|
||||||
throw(_("Atleast one of the Selling or Buying must be selected"))
|
throw(_("Atleast one of the Selling or Buying must be selected"))
|
||||||
@ -226,12 +235,11 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
|
|||||||
|
|
||||||
item_details = frappe._dict({
|
item_details = frappe._dict({
|
||||||
"doctype": args.doctype,
|
"doctype": args.doctype,
|
||||||
|
"has_margin": False,
|
||||||
"name": args.name,
|
"name": args.name,
|
||||||
"parent": args.parent,
|
"parent": args.parent,
|
||||||
"parenttype": args.parenttype,
|
"parenttype": args.parenttype,
|
||||||
"child_docname": args.get('child_docname'),
|
"child_docname": args.get('child_docname')
|
||||||
"discount_percentage_on_rate": [],
|
|
||||||
"discount_amount_on_rate": []
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if args.ignore_pricing_rule or not args.item_code:
|
if args.ignore_pricing_rule or not args.item_code:
|
||||||
@ -279,6 +287,10 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
|
|||||||
else:
|
else:
|
||||||
get_product_discount_rule(pricing_rule, item_details, args, doc)
|
get_product_discount_rule(pricing_rule, item_details, args, doc)
|
||||||
|
|
||||||
|
if not item_details.get("has_margin"):
|
||||||
|
item_details.margin_type = None
|
||||||
|
item_details.margin_rate_or_amount = 0.0
|
||||||
|
|
||||||
item_details.has_pricing_rule = 1
|
item_details.has_pricing_rule = 1
|
||||||
|
|
||||||
item_details.pricing_rules = frappe.as_json([d.pricing_rule for d in rules])
|
item_details.pricing_rules = frappe.as_json([d.pricing_rule for d in rules])
|
||||||
@ -330,13 +342,11 @@ def get_pricing_rule_details(args, pricing_rule):
|
|||||||
def apply_price_discount_rule(pricing_rule, item_details, args):
|
def apply_price_discount_rule(pricing_rule, item_details, args):
|
||||||
item_details.pricing_rule_for = pricing_rule.rate_or_discount
|
item_details.pricing_rule_for = pricing_rule.rate_or_discount
|
||||||
|
|
||||||
if ((pricing_rule.margin_type == 'Amount' and pricing_rule.currency == args.currency)
|
if ((pricing_rule.margin_type in ['Amount', 'Percentage'] and pricing_rule.currency == args.currency)
|
||||||
or (pricing_rule.margin_type == 'Percentage')):
|
or (pricing_rule.margin_type == 'Percentage')):
|
||||||
item_details.margin_type = pricing_rule.margin_type
|
item_details.margin_type = pricing_rule.margin_type
|
||||||
item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
|
item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
|
||||||
else:
|
item_details.has_margin = True
|
||||||
item_details.margin_type = None
|
|
||||||
item_details.margin_rate_or_amount = 0.0
|
|
||||||
|
|
||||||
if pricing_rule.rate_or_discount == 'Rate':
|
if pricing_rule.rate_or_discount == 'Rate':
|
||||||
pricing_rule_rate = 0.0
|
pricing_rule_rate = 0.0
|
||||||
@ -351,9 +361,9 @@ def apply_price_discount_rule(pricing_rule, item_details, args):
|
|||||||
if pricing_rule.rate_or_discount != apply_on: continue
|
if pricing_rule.rate_or_discount != apply_on: continue
|
||||||
|
|
||||||
field = frappe.scrub(apply_on)
|
field = frappe.scrub(apply_on)
|
||||||
if pricing_rule.apply_discount_on_rate:
|
if pricing_rule.apply_discount_on_rate and item_details.get("discount_percentage"):
|
||||||
discount_field = "{0}_on_rate".format(field)
|
# Apply discount on discounted rate
|
||||||
item_details[discount_field].append(pricing_rule.get(field, 0))
|
item_details[field] += ((100 - item_details[field]) * (pricing_rule.get(field, 0) / 100))
|
||||||
else:
|
else:
|
||||||
if field not in item_details:
|
if field not in item_details:
|
||||||
item_details.setdefault(field, 0)
|
item_details.setdefault(field, 0)
|
||||||
@ -361,14 +371,6 @@ def apply_price_discount_rule(pricing_rule, item_details, args):
|
|||||||
item_details[field] += (pricing_rule.get(field, 0)
|
item_details[field] += (pricing_rule.get(field, 0)
|
||||||
if pricing_rule else args.get(field, 0))
|
if pricing_rule else args.get(field, 0))
|
||||||
|
|
||||||
def set_discount_amount(rate, item_details):
|
|
||||||
for field in ['discount_percentage_on_rate', 'discount_amount_on_rate']:
|
|
||||||
for d in item_details.get(field):
|
|
||||||
dis_amount = (rate * d / 100
|
|
||||||
if field == 'discount_percentage_on_rate' else d)
|
|
||||||
rate -= dis_amount
|
|
||||||
item_details.rate = rate
|
|
||||||
|
|
||||||
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
|
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
|
||||||
from erpnext.accounts.doctype.pricing_rule.utils import (get_applied_pricing_rules,
|
from erpnext.accounts.doctype.pricing_rule.utils import (get_applied_pricing_rules,
|
||||||
get_pricing_rule_items)
|
get_pricing_rule_items)
|
||||||
|
@ -42,6 +42,7 @@ def get_pricing_rules(args, doc=None):
|
|||||||
if not pricing_rules: return []
|
if not pricing_rules: return []
|
||||||
|
|
||||||
if apply_multiple_pricing_rules(pricing_rules):
|
if apply_multiple_pricing_rules(pricing_rules):
|
||||||
|
pricing_rules = sorted_by_priority(pricing_rules)
|
||||||
for pricing_rule in pricing_rules:
|
for pricing_rule in pricing_rules:
|
||||||
pricing_rule = filter_pricing_rules(args, pricing_rule, doc)
|
pricing_rule = filter_pricing_rules(args, pricing_rule, doc)
|
||||||
if pricing_rule:
|
if pricing_rule:
|
||||||
@ -53,6 +54,20 @@ def get_pricing_rules(args, doc=None):
|
|||||||
|
|
||||||
return rules
|
return rules
|
||||||
|
|
||||||
|
def sorted_by_priority(pricing_rules):
|
||||||
|
# If more than one pricing rules, then sort by priority
|
||||||
|
pricing_rules_list = []
|
||||||
|
pricing_rule_dict = {}
|
||||||
|
for pricing_rule in pricing_rules:
|
||||||
|
if not pricing_rule.get("priority"): continue
|
||||||
|
|
||||||
|
pricing_rule_dict.setdefault(cint(pricing_rule.get("priority")), []).append(pricing_rule)
|
||||||
|
|
||||||
|
for key in sorted(pricing_rule_dict):
|
||||||
|
pricing_rules_list.append(pricing_rule_dict.get(key))
|
||||||
|
|
||||||
|
return pricing_rules_list or pricing_rules
|
||||||
|
|
||||||
def filter_pricing_rule_based_on_condition(pricing_rules, doc=None):
|
def filter_pricing_rule_based_on_condition(pricing_rules, doc=None):
|
||||||
filtered_pricing_rules = []
|
filtered_pricing_rules = []
|
||||||
if doc:
|
if doc:
|
||||||
|
@ -263,6 +263,7 @@ class AccountsController(TransactionBase):
|
|||||||
if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"):
|
if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"):
|
||||||
parent_dict.update({"customer": parent_dict.get("party_name")})
|
parent_dict.update({"customer": parent_dict.get("party_name")})
|
||||||
|
|
||||||
|
self.pricing_rules = []
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if item.get("item_code"):
|
if item.get("item_code"):
|
||||||
args = parent_dict.copy()
|
args = parent_dict.copy()
|
||||||
@ -301,6 +302,7 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
if ret.get("pricing_rules"):
|
if ret.get("pricing_rules"):
|
||||||
self.apply_pricing_rule_on_items(item, ret)
|
self.apply_pricing_rule_on_items(item, ret)
|
||||||
|
self.set_pricing_rule_details(item, ret)
|
||||||
|
|
||||||
if self.doctype == "Purchase Invoice":
|
if self.doctype == "Purchase Invoice":
|
||||||
self.set_expense_account(for_validate)
|
self.set_expense_account(for_validate)
|
||||||
@ -322,6 +324,9 @@ class AccountsController(TransactionBase):
|
|||||||
if item.get('discount_amount'):
|
if item.get('discount_amount'):
|
||||||
item.rate = item.price_list_rate - item.discount_amount
|
item.rate = item.price_list_rate - item.discount_amount
|
||||||
|
|
||||||
|
if item.get("apply_discount_on_discounted_rate") and pricing_rule_args.get("rate"):
|
||||||
|
item.rate = pricing_rule_args.get("rate")
|
||||||
|
|
||||||
elif pricing_rule_args.get('free_item_data'):
|
elif pricing_rule_args.get('free_item_data'):
|
||||||
apply_pricing_rule_for_free_items(self, pricing_rule_args.get('free_item_data'))
|
apply_pricing_rule_for_free_items(self, pricing_rule_args.get('free_item_data'))
|
||||||
|
|
||||||
@ -335,6 +340,18 @@ class AccountsController(TransactionBase):
|
|||||||
frappe.msgprint(_("Row {0}: user has not applied the rule {1} on the item {2}")
|
frappe.msgprint(_("Row {0}: user has not applied the rule {1} on the item {2}")
|
||||||
.format(item.idx, frappe.bold(title), frappe.bold(item.item_code)))
|
.format(item.idx, frappe.bold(title), frappe.bold(item.item_code)))
|
||||||
|
|
||||||
|
def set_pricing_rule_details(self, item_row, args):
|
||||||
|
pricing_rules = get_applied_pricing_rules(args.get("pricing_rules"))
|
||||||
|
if not pricing_rules: return
|
||||||
|
|
||||||
|
for pricing_rule in pricing_rules:
|
||||||
|
self.append("pricing_rules", {
|
||||||
|
"pricing_rule": pricing_rule,
|
||||||
|
"item_code": item_row.item_code,
|
||||||
|
"child_docname": item_row.name,
|
||||||
|
"rule_applied": True
|
||||||
|
})
|
||||||
|
|
||||||
def set_taxes(self):
|
def set_taxes(self):
|
||||||
if not self.meta.get_field("taxes"):
|
if not self.meta.get_field("taxes"):
|
||||||
return
|
return
|
||||||
|
@ -608,16 +608,19 @@ class calculate_taxes_and_totals(object):
|
|||||||
base_rate_with_margin = 0.0
|
base_rate_with_margin = 0.0
|
||||||
if item.price_list_rate:
|
if item.price_list_rate:
|
||||||
if item.pricing_rules and not self.doc.ignore_pricing_rule:
|
if item.pricing_rules and not self.doc.ignore_pricing_rule:
|
||||||
|
has_margin = False
|
||||||
for d in get_applied_pricing_rules(item.pricing_rules):
|
for d in get_applied_pricing_rules(item.pricing_rules):
|
||||||
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
|
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
|
||||||
|
|
||||||
if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\
|
if (pricing_rule.margin_type in ['Amount', 'Percentage'] and pricing_rule.currency == self.doc.currency)\
|
||||||
or (pricing_rule.margin_type == 'Percentage'):
|
or (pricing_rule.margin_type == 'Percentage'):
|
||||||
item.margin_type = pricing_rule.margin_type
|
item.margin_type = pricing_rule.margin_type
|
||||||
item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
|
item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
|
||||||
else:
|
has_margin = True
|
||||||
item.margin_type = None
|
|
||||||
item.margin_rate_or_amount = 0.0
|
if not has_margin:
|
||||||
|
item.margin_type = None
|
||||||
|
item.margin_rate_or_amount = 0.0
|
||||||
|
|
||||||
if item.margin_type and item.margin_rate_or_amount:
|
if item.margin_type and item.margin_rate_or_amount:
|
||||||
margin_value = item.margin_rate_or_amount if item.margin_type == 'Amount' else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
|
margin_value = item.margin_rate_or_amount if item.margin_type == 'Amount' else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
|
||||||
|
Loading…
x
Reference in New Issue
Block a user