Pricing Rule
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
new file mode 100644
index 0000000..356cc0d
--- /dev/null
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
@@ -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);
+});
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
index baefde2..5fbb08f 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
@@ -132,6 +132,13 @@
"permlevel": 0
},
{
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "permlevel": 0
+ },
+ {
"default": "Today",
"fieldname": "valid_from",
"fieldtype": "Date",
@@ -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",
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 39260a2..61e7ade 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -15,7 +15,6 @@
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 @@
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 "")
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 158dec2..d87456d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -77,16 +77,19 @@
},
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() {
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 26f3be7..d3b4606 100755
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index a5707bb..21b42a5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -155,8 +155,9 @@
},
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 @@
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() {
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 527213b..5b3bd9d 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index 05cde6a..c1072a3 100644
--- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -7,9 +7,11 @@
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
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index c50dc3b..032448f 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -62,7 +62,8 @@
},
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() {
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 23fb1c0..224f784 100755
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
index 11cb9d9..65dfe97 100644
--- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
+++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 9033065..683f72b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -97,11 +97,17 @@
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
diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js
index e12a30e..b336637 100644
--- a/erpnext/public/js/transaction.js
+++ b/erpnext/public/js/transaction.js
@@ -194,6 +194,7 @@
}
this.frm.script_manager.trigger("currency");
+ this.apply_pricing_rule()
}
},
@@ -225,7 +226,9 @@
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 @@
}
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 @@
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 {
diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js
index 31abbb3..9da0353 100644
--- a/erpnext/public/js/utils/party.js
+++ b/erpnext/public/js/utils/party.js
@@ -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 @@
frm.updating_party_details = true;
frm.set_value(r.message);
frm.updating_party_details = false;
+ if(callback) callback()
}
}
});
diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json
index 4e19ee7..a1807dd 100644
--- a/erpnext/selling/doctype/quotation_item/quotation_item.json
+++ b/erpnext/selling/doctype/quotation_item/quotation_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index 9d0ae0e..13ee085 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 1e9643a..b484100 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -104,7 +104,8 @@
},
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.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);
},
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index e093def..13307ef 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 0c8100c..548a7da 100755
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -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"
}
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index f9c7526..bd8cd3e 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -68,7 +68,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
# 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 @@
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