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) for d in get_applied_pricing_rules(pricing_rules): if not d or not frappe.db.exists("Pricing Rule", d): continue pricing_rule = frappe.get_cached_doc('Pricing Rule', d) if pricing_rule.price_or_product_discount == 'Price': if pricing_rule.rate_or_discount == 'Discount Percentage': item_details.discount_percentage = 0.0 item_details.discount_amount = 0.0 if pricing_rule.rate_or_discount == 'Discount Amount': item_details.discount_amount = 0.0 if pricing_rule.margin_type in ['Percentage', 'Amount']: item_details.margin_rate_or_amount = 0.0 item_details.margin_type = None elif pricing_rule.get('free_item'): item_details.remove_free_item = (item_code if pricing_rule.get('same_item') else pricing_rule.get('free_item')) if pricing_rule.get("mixed_conditions") or pricing_rule.get("apply_rule_on_other"): items = get_pricing_rule_items(pricing_rule) item_details.apply_on = (frappe.scrub(pricing_rule.apply_rule_on_other) if pricing_rule.apply_rule_on_other else frappe.scrub(pricing_rule.get('apply_on'))) item_details.applied_on_items = ','.join(items) item_details.pricing_rules = '' return item_details
def calculate_margin(self, item): rate_with_margin = 0.0 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_rate_or_amount and ((pricing_rule.currency == self.doc.currency and pricing_rule.margin_type in ['Amount', 'Percentage']) or pricing_rule.margin_type == 'Percentage'): item.margin_type = pricing_rule.margin_type item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount has_margin = True if not has_margin: item.margin_type = None item.margin_rate_or_amount = 0.0 if not item.pricing_rules and flt(item.rate) > flt(item.price_list_rate): item.margin_type = "Amount" item.margin_rate_or_amount = flt(item.rate - item.price_list_rate, item.precision("margin_rate_or_amount")) item.rate_with_margin = item.rate elif 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 rate_with_margin = flt(item.price_list_rate) + flt(margin_value) base_rate_with_margin = flt(rate_with_margin) * flt(self.doc.conversion_rate) return rate_with_margin, base_rate_with_margin
def calculate_margin(self, item): rate_with_margin = 0.0 base_rate_with_margin = 0.0 if item.price_list_rate: if item.pricing_rules and not self.doc.ignore_pricing_rule: 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)\ 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 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 rate_with_margin = flt( item.price_list_rate) + flt(margin_value) base_rate_with_margin = flt(rate_with_margin) * flt( self.doc.conversion_rate) return rate_with_margin, base_rate_with_margin
def apply_pricing_rule_on_items(self, item, pricing_rule_args): if not pricing_rule_args.get("validate_applied_rule", 0): # if user changed the discount percentage then set user's discount percentage ? if pricing_rule_args.get("price_or_product_discount") == 'Price': item.set("pricing_rules", pricing_rule_args.get("pricing_rules")) item.set("discount_percentage", pricing_rule_args.get("discount_percentage")) item.set("discount_amount", pricing_rule_args.get("discount_amount")) if pricing_rule_args.get("pricing_rule_for") == "Rate": item.set("price_list_rate", pricing_rule_args.get("price_list_rate")) if item.get("price_list_rate"): item.rate = flt(item.price_list_rate * (1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate")) if item.get('discount_amount'): item.rate = item.price_list_rate - item.discount_amount elif pricing_rule_args.get('free_item_data'): apply_pricing_rule_for_free_items(self, pricing_rule_args.get('free_item_data')) elif pricing_rule_args.get("validate_applied_rule"): for pricing_rule in get_applied_pricing_rules(item): pricing_rule_doc = frappe.get_cached_doc("Pricing Rule", pricing_rule) for field in ['discount_percentage', 'discount_amount', 'rate']: if item.get(field) < pricing_rule_doc.get(field): title = get_link_to_form("Pricing Rule", pricing_rule) 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 remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None, rate=None): from erpnext.accounts.doctype.pricing_rule.utils import ( get_applied_pricing_rules, get_pricing_rule_items, ) for d in get_applied_pricing_rules(pricing_rules): if not d or not frappe.db.exists("Pricing Rule", d): continue pricing_rule = frappe.get_cached_doc("Pricing Rule", d) if pricing_rule.price_or_product_discount == "Price": if pricing_rule.rate_or_discount == "Discount Percentage": item_details.discount_percentage = 0.0 item_details.discount_amount = 0.0 item_details.rate = rate or 0.0 if pricing_rule.rate_or_discount == "Discount Amount": item_details.discount_amount = 0.0 if pricing_rule.margin_type in ["Percentage", "Amount"]: item_details.margin_rate_or_amount = 0.0 item_details.margin_type = None elif pricing_rule.get("free_item"): item_details.remove_free_item = (item_code if pricing_rule.get("same_item") else pricing_rule.get("free_item")) if pricing_rule.get("mixed_conditions") or pricing_rule.get( "apply_rule_on_other"): items = get_pricing_rule_items(pricing_rule) item_details.apply_on = ( frappe.scrub(pricing_rule.apply_rule_on_other) if pricing_rule.apply_rule_on_other else frappe.scrub( pricing_rule.get("apply_on"))) item_details.applied_on_items = ",".join(items) item_details.pricing_rules = "" item_details.pricing_rule_removed = True return item_details
def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False): from erpnext.accounts.doctype.pricing_rule.utils import ( get_pricing_rules, get_applied_pricing_rules, get_pricing_rule_items, get_product_discount_rule) if isinstance(doc, string_types): doc = json.loads(doc) if doc: doc = frappe.get_doc(doc) if (args.get('is_free_item') or args.get("parenttype") == "Material Request"): return {} item_details = frappe._dict({ "doctype": args.doctype, "name": args.name, "parent": args.parent, "parenttype": args.parenttype, "child_docname": args.get('child_docname'), "discount_percentage_on_rate": [], "discount_amount_on_rate": [] }) if args.ignore_pricing_rule or args.item_ignore_pricing_rule or not args.item_code: if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rules"): item_details = remove_pricing_rule_for_item( args.get("pricing_rules"), item_details, args.get('item_code')) return item_details update_args_for_pricing_rule(args) pricing_rules = (get_applied_pricing_rules(args) if for_validate and args.get("pricing_rules") else get_pricing_rules( args, doc)) if pricing_rules: rules = [] for pricing_rule in pricing_rules: if not pricing_rule: continue if isinstance(pricing_rule, string_types): pricing_rule = frappe.get_cached_doc("Pricing Rule", pricing_rule) pricing_rule.apply_rule_on_other_items = get_pricing_rule_items( pricing_rule) if pricing_rule.get('suggestion'): continue item_details.validate_applied_rule = pricing_rule.get( "validate_applied_rule", 0) item_details.price_or_product_discount = pricing_rule.get( "price_or_product_discount") rules.append(get_pricing_rule_details(args, pricing_rule)) if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other: item_details.update({ 'apply_rule_on_other_items': json.dumps(pricing_rule.apply_rule_on_other_items), 'price_or_product_discount': pricing_rule.price_or_product_discount, 'apply_rule_on': (frappe.scrub(pricing_rule.apply_rule_on_other) if pricing_rule.apply_rule_on_other else frappe.scrub( pricing_rule.get('apply_on'))) }) if pricing_rule.coupon_code_based == 1 and args.coupon_code == None: return item_details if not pricing_rule.validate_applied_rule: if pricing_rule.price_or_product_discount == "Price": apply_price_discount_rule(pricing_rule, item_details, args) else: get_product_discount_rule(pricing_rule, item_details, args, doc) item_details.has_pricing_rule = 1 item_details.pricing_rules = ','.join([d.pricing_rule for d in rules]) if not doc: return item_details elif args.get("pricing_rules"): item_details = remove_pricing_rule_for_item(args.get("pricing_rules"), item_details, args.get('item_code')) return item_details