Pricing Rule

This commit is contained in:
Nabin Hait 2014-05-28 12:49:20 +05:30
parent 62ec60188b
commit a3dd72a759
20 changed files with 296 additions and 158 deletions

View File

@ -0,0 +1,64 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Pricing Rule", "refresh", function(frm) {
var help_content = ['<table class="table table-bordered" style="background-color: #f9f9f9;">',
'<tr><td>',
'<h4><i class="icon-hand-right"></i> ',
__('Notes'),
':</h4>',
'<ul>',
'<li>',
__("Pricing Rule is made to overwrite Price List / define discount percentage, based on some criteria."),
'</li>',
'<li>',
__("If selected Pricing Rule is made for 'Price', it will overwrite Price List. Pricing Rule price is the final price, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field."),
'</li>',
'<li>',
__('Discount Percentage can be applied either against a Price List or for all Price List.'),
'</li>',
'<li>',
__('To not apply Pricing Rule in a particular transaction, all applicable Pricing Rules should be disabled.'),
'</li>',
'</ul>',
'</td></tr>',
'<tr><td>',
'<h4><i class="icon-question-sign"></i> ',
__('How Pricing Rule is applied?'),
'</h4>',
'<ol>',
'<li>',
__("Pricing Rule is first selected based on 'Apply On' field, which can be Item, Item Group or Brand."),
'</li>',
'<li>',
__("Then Pricing Rules are filtered out based on Customer, Customer Group, Territory, Supplier, Supplier Type, Campaign, Sales Partner etc."),
'</li>',
'<li>',
__('Pricing Rules are further filtered based on quantity.'),
'</li>',
'<li>',
__('If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions.'),
'</li>',
'<li>',
__('Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:'),
'<ul>',
'<li>',
__('Item Code > Item Group > Brand'),
'</li>',
'<li>',
__('Customer > Customer Group > Territory'),
'</li>',
'<li>',
__('Supplier > Supplier Type'),
'</li>',
'</ul>',
'</li>',
'<li>',
__('If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict.'),
'</li>',
'</ol>',
'</td></tr>',
'</table>'].join("\n");
set_field_options("pricing_rule_help", help_content);
});

View File

@ -131,6 +131,13 @@
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"permlevel": 0
},
{
"default": "Today",
"fieldname": "valid_from",
@ -198,12 +205,25 @@
"label": "For Price List",
"options": "Price List",
"permlevel": 0
},
{
"fieldname": "help_section",
"fieldtype": "Section Break",
"label": "",
"options": "Simple",
"permlevel": 0
},
{
"fieldname": "pricing_rule_help",
"fieldtype": "HTML",
"label": "Pricing Rule Help",
"permlevel": 0
}
],
"icon": "icon-gift",
"idx": 1,
"istable": 0,
"modified": "2014-05-12 16:24:52.005162",
"modified": "2014-05-27 15:14:34.849671",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule",

View File

@ -15,7 +15,6 @@ class PricingRule(Document):
self.validate_min_max_qty()
self.cleanup_fields_value()
def validate_mandatory(self):
for field in ["apply_on", "applicable_for", "price_or_discount"]:
tocheck = frappe.scrub(self.get(field) or "")
@ -26,7 +25,6 @@ class PricingRule(Document):
if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty):
throw(_("Min Qty can not be greater than Max Qty"))
def cleanup_fields_value(self):
for logic_field in ["apply_on", "applicable_for", "price_or_discount"]:
fieldname = frappe.scrub(self.get(logic_field) or "")

View File

@ -77,16 +77,19 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
},
supplier: function() {
var me = this;
if(this.frm.updating_party_details)
return;
erpnext.utils.get_party_details(this.frm,
"erpnext.accounts.party.get_party_details", {
erpnext.utils.get_party_details(this.frm, "erpnext.accounts.party.get_party_details",
{
posting_date: this.frm.doc.posting_date,
party: this.frm.doc.supplier,
party_type: "Supplier",
account: this.frm.doc.debit_to,
price_list: this.frm.doc.buying_price_list,
})
}, function() {
me.apply_pricing_rule();
})
},
credit_to: function() {

View File

@ -1,6 +1,6 @@
{
"autoname": "EVD.######",
"creation": "2013-05-22 12:43:10.000000",
"creation": "2013-05-22 12:43:10",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -193,17 +193,9 @@
"reqd": 1
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -429,9 +421,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:27:53.000000",
"modified": "2014-05-28 12:43:40.647183",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -155,8 +155,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
customer: function() {
if(this.frm.updating_party_details)
return;
var me = this;
if(this.frm.updating_party_details) return;
erpnext.utils.get_party_details(this.frm,
"erpnext.accounts.party.get_party_details", {
posting_date: this.frm.doc.posting_date,
@ -164,7 +165,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
party_type: "Customer",
account: this.frm.doc.debit_to,
price_list: this.frm.doc.selling_price_list,
})
}, function() {
me.apply_pricing_rule();
})
},
debit_to: function() {

View File

@ -1,6 +1,6 @@
{
"autoname": "INVD.######",
"creation": "2013-06-04 11:02:19.000000",
"creation": "2013-06-04 11:02:19",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -201,17 +201,9 @@
"reqd": 1
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -456,9 +448,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:04:19.000000",
"modified": "2014-05-28 12:42:28.209942",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -7,9 +7,11 @@ from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
if not filters.get("account"): return
columns = get_columns()
if not filters.get("account"): return columns, []
data = get_entries(filters)
from erpnext.accounts.utils import get_balance_on

View File

@ -62,7 +62,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
},
supplier: function() {
erpnext.utils.get_party_details(this.frm);
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function(){me.apply_pricing_rule()});
},
supplier_address: function() {

View File

@ -1,6 +1,6 @@
{
"autoname": "POD/.#####",
"creation": "2013-05-24 19:29:06.000000",
"creation": "2013-05-24 19:29:06",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -252,17 +252,9 @@
"reqd": 1
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -474,9 +466,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:26:25.000000",
"modified": "2014-05-28 12:42:53.018610",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -1,6 +1,6 @@
{
"autoname": "SQI-.#####",
"creation": "2013-05-22 12:43:10.000000",
"creation": "2013-05-22 12:43:10",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -195,17 +195,9 @@
"reqd": 1
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -354,9 +346,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:25:38.000000",
"modified": "2014-05-28 12:44:17.347236",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -97,11 +97,17 @@ class AccountsController(TransactionBase):
args = item.as_dict()
args.update(parent_dict)
ret = get_item_details(args)
for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and \
item.get(fieldname) is None and value is not None:
item.set(fieldname, value)
if ret.get("pricing_rule"):
for field in ["base_price_list_rate", "price_list_rate",
"discount_percentage", "base_rate", "rate"]:
item.set(field, ret.get(field))
def set_taxes(self, tax_parentfield, tax_master_field):
if not self.meta.get_field(tax_parentfield):
return

View File

@ -194,6 +194,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
}
this.frm.script_manager.trigger("currency");
this.apply_pricing_rule()
}
},
@ -225,7 +226,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
this.frm.doc.plc_conversion_rate !== this.frm.doc.conversion_rate) {
this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate);
}
if(flt(this.frm.doc.conversion_rate)>0.0) this.calculate_taxes_and_totals();
if(flt(this.frm.doc.conversion_rate)>0.0) {
this.apply_pricing_rule();
}
},
get_price_list_currency: function(buying_or_selling) {
@ -278,12 +281,12 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
}
if(this.frm.doc.price_list_currency === this.frm.doc.currency) {
this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate);
this.calculate_taxes_and_totals();
this.apply_pricing_rule();
}
},
qty: function(doc, cdt, cdn) {
this.calculate_taxes_and_totals();
this.apply_pricing_rule(frappe.get_doc(cdt, cdn));
},
// tax rate
@ -326,6 +329,52 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
this.calculate_taxes_and_totals();
},
apply_pricing_rule: function(item) {
var me = this;
var _apply_pricing_rule = function(item) {
return me.frm.call({
method: "erpnext.stock.get_item_details.apply_pricing_rule",
child: item,
args: {
args: {
item_code: item.item_code,
item_group: item.item_group,
brand: item.brand,
qty: item.qty,
customer: me.frm.doc.customer,
customer_group: me.frm.doc.customer_group,
territory: me.frm.doc.territory,
supplier: me.frm.doc.supplier,
supplier_type: me.frm.doc.supplier_type,
currency: me.frm.doc.currency,
conversion_rate: me.frm.doc.conversion_rate,
price_list: me.frm.doc.selling_price_list ||
me.frm.doc.buying_price_list,
plc_conversion_rate: me.frm.doc.plc_conversion_rate,
company: me.frm.doc.company,
transaction_date: me.frm.doc.transaction_date || me.frm.doc.posting_date,
campaign: me.frm.doc.campaign,
sales_partner: me.frm.doc.sales_partner
}
},
callback: function(r) {
if(!r.exc) {
me.frm.script_manager.trigger("price_list_rate", item.doctype, item.name);
}
}
});
}
if(item) _apply_pricing_rule(item);
else {
$.each(this.get_item_doclist(), function(n, item) {
_apply_pricing_rule(item);
});
}
},
included_in_print_rate: function(doc, cdt, cdn) {
var tax = frappe.get_doc(cdt, cdn);
try {

View File

@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
frappe.provide("erpnext.utils");
erpnext.utils.get_party_details = function(frm, method, args) {
erpnext.utils.get_party_details = function(frm, method, args, callback) {
if(!method) {
method = "erpnext.accounts.party.get_party_details";
}
@ -33,6 +33,7 @@ erpnext.utils.get_party_details = function(frm, method, args) {
frm.updating_party_details = true;
frm.set_value(r.message);
frm.updating_party_details = false;
if(callback) callback()
}
}
});

View File

@ -1,6 +1,6 @@
{
"autoname": "QUOD/.#####",
"creation": "2013-03-07 11:42:57.000000",
"creation": "2013-03-07 11:42:57",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -231,17 +231,9 @@
"width": "100px"
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -353,9 +345,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:20:34.000000",
"modified": "2014-05-28 12:41:40.811916",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -1,6 +1,6 @@
{
"autoname": "SOD/.#####",
"creation": "2013-03-07 11:42:58.000000",
"creation": "2013-03-07 11:42:58",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -217,17 +217,9 @@
"width": "100px"
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -439,9 +431,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:20:05.000000",
"modified": "2014-05-27 14:41:14.996650",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -104,7 +104,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
},
customer: function() {
erpnext.utils.get_party_details(this.frm);
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function(){me.apply_pricing_rule()});
},
customer_address: function() {
@ -119,6 +120,14 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
erpnext.utils.get_contact_details(this.frm);
},
sales_partner: function() {
this.apply_pricing_rule();
},
campaign: function() {
this.apply_pricing_rule();
},
barcode: function(doc, cdt, cdn) {
this.item_code(doc, cdt, cdn);
},

View File

@ -1,6 +1,6 @@
{
"autoname": "DND/.#######",
"creation": "2013-04-22 13:15:44.000000",
"creation": "2013-04-22 13:15:44",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -225,17 +225,9 @@
"width": "100px"
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -437,9 +429,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:20:58.000000",
"modified": "2014-05-28 12:42:05.788579",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -1,6 +1,6 @@
{
"autoname": "GRND/.#######",
"creation": "2013-05-24 19:29:10.000000",
"creation": "2013-05-24 19:29:10",
"docstatus": 0,
"doctype": "DocType",
"fields": [
@ -256,17 +256,9 @@
"width": "100px"
},
{
"fieldname": "pricing_rule_for_price",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule For Price",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "pricing_rule_for_discount",
"fieldtype": "Link",
"label": "Pricing Rule For Discount",
"label": "Pricing Rule",
"options": "Pricing Rule",
"permlevel": 0,
"read_only": 1
@ -553,9 +545,12 @@
],
"idx": 1,
"istable": 1,
"modified": "2014-02-28 11:27:09.000000",
"modified": "2014-05-28 12:43:16.669040",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
"owner": "Administrator"
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -68,7 +68,12 @@ def get_item_details(args):
if args.transaction_type == "selling" and cint(args.is_pos):
out.update(get_pos_settings_item_details(args.company, args))
apply_pricing_rule(out, args)
# update args with out, if key or value not exists
for key, value in out.iteritems():
if args.get(key) is None:
args[key] = value
out.update(apply_pricing_rule(args))
if args.get("doctype") in ("Sales Invoice", "Delivery Note"):
if item_doc.has_serial_no == "Yes" and not args.serial_no:
@ -243,36 +248,50 @@ def get_pos_settings(company):
return pos_settings and pos_settings[0] or None
def apply_pricing_rule(out, args):
args_dict = frappe._dict().update(args)
args_dict.update(out)
all_pricing_rules = get_pricing_rules(args_dict)
@frappe.whitelist()
def apply_pricing_rule(args):
if isinstance(args, basestring):
args = json.loads(args)
rule_for_price = False
for rule_for in ["price", "discount_percentage"]:
pricing_rules = filter(lambda x: x[rule_for] > 0.0, all_pricing_rules)
if rule_for_price:
pricing_rules = filter(lambda x: not x["for_price_list"], pricing_rules)
args = frappe._dict(args)
out = frappe._dict()
pricing_rule = filter_pricing_rules(args_dict, pricing_rules)
if not args.get("item_group") or not args.get("brand"):
args.item_group, args.brand = frappe.db.get_value("Item",
args.item_code, ["item_group", "brand"])
if pricing_rule:
if rule_for == "discount_percentage":
out["discount_percentage"] = pricing_rule["discount_percentage"]
out["pricing_rule_for_discount"] = pricing_rule["name"]
else:
out["base_price_list_rate"] = pricing_rule["price"]
out["price_list_rate"] = pricing_rule["price"] * \
flt(args_dict.plc_conversion_rate) / flt(args_dict.conversion_rate)
out["pricing_rule_for_price"] = pricing_rule["name"]
rule_for_price = True
if not args.get("customer_group") or not args.get("territory"):
args.customer_group, args.territory = frappe.db.get_value("Customer",
args.customer, ["customer_group", "territory"])
def get_pricing_rules(args_dict):
if not args.get("supplier_type"):
args.supplier_type = frappe.db.get_value("Supplier", args.supplier, "supplier_type")
pricing_rules = get_pricing_rules(args)
pricing_rule = filter_pricing_rules(args, pricing_rules)
if pricing_rule:
out.pricing_rule = pricing_rule.name
if pricing_rule.price_or_discount == "Price":
out.base_price_list_rate = pricing_rule.price
out.price_list_rate = pricing_rule.price*flt(args.plc_conversion_rate)/flt(args.conversion_rate)
out.base_rate = out.base_price_list_rate
out.rate = out.price_list_rate
out.discount_percentage = 0.0
else:
out.discount_percentage = pricing_rule.discount_percentage
else:
out.pricing_rule = None
return out
def get_pricing_rules(args):
def _get_tree_conditions(doctype, allow_blank=True):
field = frappe.scrub(doctype)
condition = ""
if args_dict.get(field):
lft, rgt = frappe.db.get_value(doctype, args_dict[field], ["lft", "rgt"])
if args.get(field):
lft, rgt = frappe.db.get_value(doctype, args[field], ["lft", "rgt"])
parent_groups = frappe.db.sql_list("""select name from `tab%s`
where lft<=%s and rgt>=%s""" % (doctype, '%s', '%s'), (lft, rgt))
@ -284,8 +303,8 @@ def get_pricing_rules(args_dict):
conditions = ""
for field in ["customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
if args_dict.get(field):
for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
if args.get(field):
conditions += " and ifnull("+field+", '') in (%("+field+")s, '')"
else:
conditions += " and ifnull("+field+", '') = ''"
@ -297,8 +316,7 @@ def get_pricing_rules(args_dict):
conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
if args_dict.get("transaction_date"):
if args.get("transaction_date"):
conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
and ifnull(valid_upto, '2500-12-31')"""
@ -307,13 +325,13 @@ def get_pricing_rules(args_dict):
and docstatus < 2 and ifnull(disable, 0) = 0 {conditions}
order by priority desc, name desc""".format(
item_group_condition=_get_tree_conditions("Item Group", False), conditions=conditions),
args_dict, as_dict=1)
args, as_dict=1)
def filter_pricing_rules(args_dict, pricing_rules):
def filter_pricing_rules(args, pricing_rules):
# filter for qty
if pricing_rules and args_dict.get("qty"):
pricing_rules = filter(lambda x: (args_dict.qty>=flt(x.min_qty)
and (args_dict.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
if pricing_rules and args.get("qty"):
pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty)
and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
# find pricing rule with highest priority
if pricing_rules:
@ -323,15 +341,19 @@ def filter_pricing_rules(args_dict, pricing_rules):
# apply internal priority
all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
"supplier", "supplier_type", "campaign", "for_price_list", "sales_partner"]
"supplier", "supplier_type", "campaign", "sales_partner"]
if len(pricing_rules) > 1:
for field_set in [["item_code", "item_group", "brand"],
["customer", "customer_group", "territory"], ["supplier", "supplier_type"]]:
remaining_fields = list(set(all_fields) - set(field_set))
if if_all_rules_same(pricing_rules, remaining_fields):
pricing_rules = apply_internal_priority(pricing_rules, field_set, args_dict)
pricing_rules = apply_internal_priority(pricing_rules, field_set, args)
break
if len(pricing_rules) > 1:
price_or_discount = list(set([d.price_or_discount for d in pricing_rules]))
if len(price_or_discount) == 1 and price_or_discount[0] == "Discount Percentage":
pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules)
if len(pricing_rules) > 1:
frappe.throw(_("Multiple Price Rule exists with same criteria, please resolve \
@ -350,11 +372,11 @@ def if_all_rules_same(pricing_rules, fields):
return all_rules_same
def apply_internal_priority(pricing_rules, field_set, args_dict):
def apply_internal_priority(pricing_rules, field_set, args):
filtered_rules = []
for field in field_set:
if args_dict.get(field):
filtered_rules = filter(lambda x: x[field]==args_dict[field], pricing_rules)
if args.get(field):
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
if filtered_rules: break
return filtered_rules or pricing_rules