fix: pricing rule not working for production discount

This commit is contained in:
Rohit Waghchaure 2019-12-13 16:18:38 +05:30
parent 60592e9d43
commit 21fe97e723
6 changed files with 76 additions and 32 deletions

View File

@ -1,4 +1,5 @@
{
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:title",
@ -439,19 +440,20 @@
},
{
"default": "0",
"depends_on": "eval:!doc.mixed_conditions",
"depends_on": "eval:!doc.mixed_conditions && doc.price_or_product_discount == 'Price'",
"fieldname": "same_item",
"fieldtype": "Check",
"label": "Same Item"
},
{
"depends_on": "eval:!doc.same_item || doc.mixed_conditions",
"depends_on": "eval:(!doc.same_item || doc.apply_on == 'Transaction') || doc.mixed_conditions",
"fieldname": "free_item",
"fieldtype": "Link",
"label": "Free Item",
"options": "Item"
},
{
"default": "0",
"fieldname": "free_qty",
"fieldtype": "Float",
"label": "Qty"
@ -554,7 +556,8 @@
],
"icon": "fa fa-gift",
"idx": 1,
"modified": "2019-10-15 12:39:40.399792",
"links": [],
"modified": "2019-12-13 15:48:48.331495",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule",

View File

@ -182,7 +182,7 @@ def get_serial_no_for_item(args):
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_applied_pricing_rules, get_pricing_rule_items, get_product_discount_rule)
if isinstance(doc, string_types):
doc = json.loads(doc)
@ -241,9 +241,11 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
return item_details
if (not pricing_rule.validate_applied_rule and
pricing_rule.price_or_product_discount == "Price"):
apply_price_discount_pricing_rule(pricing_rule, item_details, args)
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)
item_details.has_pricing_rule = 1
@ -293,7 +295,7 @@ def get_pricing_rule_details(args, pricing_rule):
'child_docname': args.get('child_docname')
})
def apply_price_discount_pricing_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
if ((pricing_rule.margin_type == 'Amount' and pricing_rule.currency == args.currency)

View File

@ -7,7 +7,7 @@ from __future__ import unicode_literals
import frappe, copy, json
from frappe import throw, _
from six import string_types
from frappe.utils import flt, cint, get_datetime
from frappe.utils import flt, cint, get_datetime, get_link_to_form
from erpnext.setup.doctype.item_group.item_group import get_child_item_groups
from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
from erpnext.stock.get_item_details import get_conversion_factor
@ -408,7 +408,8 @@ def apply_pricing_rule_on_transaction(doc):
conditions = get_other_conditions(conditions, values, doc)
pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule`
where {conditions} """.format(conditions = conditions), values, as_dict=1)
where {conditions} and `tabPricing Rule`.disable = 0
""".format(conditions = conditions), values, as_dict=1)
if pricing_rules:
pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
@ -420,39 +421,59 @@ def apply_pricing_rule_on_transaction(doc):
doc.set('apply_discount_on', d.apply_discount_on)
for field in ['additional_discount_percentage', 'discount_amount']:
if not d.get(field): continue
pr_field = ('discount_percentage'
if field == 'additional_discount_percentage' else field)
if not d.get(pr_field): continue
if d.validate_applied_rule and doc.get(field) < d.get(pr_field):
frappe.msgprint(_("User has not applied rule on the invoice {0}")
.format(doc.name))
else:
doc.set(field, d.get(pr_field))
doc.calculate_taxes_and_totals()
elif d.price_or_product_discount == 'Product':
apply_pricing_rule_for_free_items(doc, d)
item_details = frappe._dict()
get_product_discount_rule(d, item_details)
apply_pricing_rule_for_free_items(doc, item_details.free_item_data)
doc.set_missing_values()
def get_applied_pricing_rules(item_row):
return (item_row.get("pricing_rules").split(',')
if item_row.get("pricing_rules") else [])
def apply_pricing_rule_for_free_items(doc, pricing_rule):
if pricing_rule.get('free_item'):
def get_product_discount_rule(pricing_rule, item_details):
free_item = (pricing_rule.free_item
if not pricing_rule.same_item or pricing_rule.apply_on == 'Transaction' else item_details.item_code)
if not free_item:
frappe.throw(_("Free item not set in the pricing rule {0}")
.format(get_link_to_form("Pricing Rule", pricing_rule.name)))
item_details.free_item_data = {
'item_code': free_item,
'qty': pricing_rule.free_qty or 1,
'rate': pricing_rule.free_item_rate or 0,
'price_list_rate': pricing_rule.free_item_rate or 0,
'is_free_item': 1
}
item_data = frappe.get_cached_value('Item', free_item, ['item_name',
'description', 'stock_uom'], as_dict=1)
item_details.free_item_data.update(item_data)
item_details.free_item_data['uom'] = pricing_rule.free_item_uom or item_data.stock_uom
item_details.free_item_data['conversion_factor'] = get_conversion_factor(free_item,
item_details.free_item_data['uom']).get("conversion_factor", 1)
def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False):
if pricing_rule_args.get('item_code'):
items = [d.item_code for d in doc.items
if d.item_code == (d.item_code
if pricing_rule.get('same_item') else pricing_rule.get('free_item')) and d.is_free_item]
if d.item_code == (pricing_rule_args.get("item_code")) and d.is_free_item]
if not items:
doc.append('items', {
'item_code': pricing_rule.get('free_item'),
'qty': pricing_rule.get('free_qty'),
'uom': pricing_rule.get('free_item_uom'),
'rate': pricing_rule.get('free_item_rate') or 0,
'is_free_item': 1
})
doc.set_missing_values()
doc.append('items', pricing_rule_args)
def get_pricing_rule_items(pr_doc):
apply_on_data = []

View File

@ -319,8 +319,8 @@ class AccountsController(TransactionBase):
if item.get('discount_amount'):
item.rate = item.price_list_rate - item.discount_amount
elif pricing_rule_args.get('free_item'):
apply_pricing_rule_for_free_items(self, pricing_rule_args)
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):

View File

@ -735,10 +735,6 @@ class BuyingController(StockController):
if not self.get("items"):
return
earliest_schedule_date = min([d.schedule_date for d in self.get("items")])
if earliest_schedule_date:
self.schedule_date = earliest_schedule_date
if self.schedule_date:
for d in self.get('items'):
if not d.schedule_date:
@ -750,6 +746,10 @@ class BuyingController(StockController):
else:
frappe.throw(_("Please enter Reqd by Date"))
earliest_schedule_date = min([d.schedule_date for d in self.get("items")])
if earliest_schedule_date:
self.schedule_date = earliest_schedule_date
def validate_items(self):
# validate items to see if they have is_purchase_item or is_subcontracted_item enabled
if self.doctype=="Material Request": return

View File

@ -1305,6 +1305,10 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
me.remove_pricing_rule(frappe.get_doc(d.doctype, d.name));
}
if (d.free_item_data) {
me.apply_product_discount(d.free_item_data);
}
if (d.apply_rule_on_other_items) {
items_rule_dict[d.name] = d;
}
@ -1334,6 +1338,20 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
apply_product_discount: function(free_item_data) {
const items = this.frm.doc.items.filter(d => (d.item_code == free_item_data.item_code
&& d.is_free_item)) || [];
if (!items.length) {
let row_to_modify = frappe.model.add_child(this.frm.doc,
this.frm.doc.doctype + ' Item', 'items');
for (let key in free_item_data) {
row_to_modify[key] = free_item_data[key];
}
}
},
apply_price_list: function(item, reset_plc_conversion) {
// We need to reset plc_conversion_rate sometimes because the call to
// `erpnext.stock.get_item_details.apply_price_list` is sensitive to its value