fix: multiple pricing rules are not working on selling side
This commit is contained in:
		
							parent
							
								
									65820f6b6c
								
							
						
					
					
						commit
						2fe3b1807f
					
				| @ -60,6 +60,15 @@ class PricingRule(Document): | ||||
| 		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) | ||||
| 
 | ||||
| 		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): | ||||
| 		if not self.selling and not self.buying: | ||||
| 			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({ | ||||
| 		"doctype": args.doctype, | ||||
| 		"has_margin": False, | ||||
| 		"name": args.name, | ||||
| 		"parent": args.parent, | ||||
| 		"parenttype": args.parenttype, | ||||
| 		"child_docname": args.get('child_docname'), | ||||
| 		"discount_percentage_on_rate": [], | ||||
| 		"discount_amount_on_rate": [] | ||||
| 		"child_docname": args.get('child_docname') | ||||
| 	}) | ||||
| 
 | ||||
| 	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: | ||||
| 					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.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): | ||||
| 	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')): | ||||
| 		item_details.margin_type = pricing_rule.margin_type | ||||
| 		item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount | ||||
| 	else: | ||||
| 		item_details.margin_type = None | ||||
| 		item_details.margin_rate_or_amount = 0.0 | ||||
| 		item_details.has_margin = True | ||||
| 
 | ||||
| 	if pricing_rule.rate_or_discount == 'Rate': | ||||
| 		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 | ||||
| 
 | ||||
| 		field = frappe.scrub(apply_on) | ||||
| 		if pricing_rule.apply_discount_on_rate: | ||||
| 			discount_field = "{0}_on_rate".format(field) | ||||
| 			item_details[discount_field].append(pricing_rule.get(field, 0)) | ||||
| 		if pricing_rule.apply_discount_on_rate and item_details.get("discount_percentage"): | ||||
| 			# Apply discount on discounted rate | ||||
| 			item_details[field] += ((100 - item_details[field]) * (pricing_rule.get(field, 0) / 100)) | ||||
| 		else: | ||||
| 			if field not in item_details: | ||||
| 				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) | ||||
| 				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): | ||||
| 	from erpnext.accounts.doctype.pricing_rule.utils import (get_applied_pricing_rules, | ||||
| 		get_pricing_rule_items) | ||||
|  | ||||
| @ -42,6 +42,7 @@ def get_pricing_rules(args, doc=None): | ||||
| 	if not pricing_rules: return [] | ||||
| 
 | ||||
| 	if apply_multiple_pricing_rules(pricing_rules): | ||||
| 		pricing_rules = sorted_by_priority(pricing_rules) | ||||
| 		for pricing_rule in pricing_rules: | ||||
| 			pricing_rule = filter_pricing_rules(args, pricing_rule, doc) | ||||
| 			if pricing_rule: | ||||
| @ -53,6 +54,20 @@ def get_pricing_rules(args, doc=None): | ||||
| 
 | ||||
| 	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): | ||||
| 	filtered_pricing_rules = [] | ||||
| 	if doc: | ||||
|  | ||||
| @ -263,6 +263,7 @@ class AccountsController(TransactionBase): | ||||
| 			if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"): | ||||
| 				parent_dict.update({"customer": parent_dict.get("party_name")}) | ||||
| 
 | ||||
| 			self.pricing_rules = [] | ||||
| 			for item in self.get("items"): | ||||
| 				if item.get("item_code"): | ||||
| 					args = parent_dict.copy() | ||||
| @ -301,6 +302,7 @@ class AccountsController(TransactionBase): | ||||
| 
 | ||||
| 					if ret.get("pricing_rules"): | ||||
| 						self.apply_pricing_rule_on_items(item, ret) | ||||
| 						self.set_pricing_rule_details(item, ret) | ||||
| 
 | ||||
| 			if self.doctype == "Purchase Invoice": | ||||
| 				self.set_expense_account(for_validate) | ||||
| @ -322,6 +324,9 @@ class AccountsController(TransactionBase): | ||||
| 					if item.get('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'): | ||||
| 				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}") | ||||
| 							.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): | ||||
| 		if not self.meta.get_field("taxes"): | ||||
| 			return | ||||
|  | ||||
| @ -608,16 +608,19 @@ class calculate_taxes_and_totals(object): | ||||
| 		base_rate_with_margin = 0.0 | ||||
| 		if item.price_list_rate: | ||||
| 			if item.pricing_rules and not self.doc.ignore_pricing_rule: | ||||
| 				has_margin = False | ||||
| 				for d in get_applied_pricing_rules(item.pricing_rules): | ||||
| 					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'): | ||||
| 						item.margin_type = pricing_rule.margin_type | ||||
| 						item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount | ||||
| 					else: | ||||
| 						item.margin_type = None | ||||
| 						item.margin_rate_or_amount = 0.0 | ||||
| 						has_margin = True | ||||
| 
 | ||||
| 				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: | ||||
| 				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