From 8c8fa17a9b305c9ff1946180839f580ee0149d90 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 15:11:18 +0530 Subject: [PATCH 01/19] [new fields] added Margin type (Percetage/Amount) and Rate field to capture Margin details in Pricing Rule, Sales Order Item, Quotation Item --- .../doctype/pricing_rule/pricing_rule.json | 98 ++++++++++++++++++- .../sales_order_item/sales_order_item.json | 49 ++++++++++ 2 files changed, 146 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index eb77ae2372..c099cec90d 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -727,6 +727,102 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "margin", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Type of Margin", + "length": 0, + "no_copy": 0, + "options": "Percentage\nAmount", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_33", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "rate", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Rate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -928,7 +1024,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-01-15 04:05:11.633824", + "modified": "2016-01-18 15:04:26.489659", "modified_by": "Administrator", "module": "Accounts", "name": "Pricing Rule", 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 fb65ee8f1a..9710e39c78 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -455,6 +455,31 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Type", + "length": 0, + "no_copy": 0, + "options": "Percentage\nAmount", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -536,6 +561,30 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "rate_or_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Rate or Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, From ea60c635ab551b11b1122bdeae71f9805d7c407d Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 15:19:29 +0530 Subject: [PATCH 02/19] changed the description of rate fields depending on margin type and if ignore pricing is unchecked returned the rate=0 --- erpnext/accounts/doctype/pricing_rule/pricing_rule.js | 5 +++++ erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js index 854f5b3888..70c039725f 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js @@ -89,3 +89,8 @@ cur_frm.cscript.selling = function() { cur_frm.cscript.buying = function() { cur_frm.cscript.set_options_for_applicable_for(); } + +//Dynamically change the description based on type of margin +cur_frm.cscript.type = function(doc){ + cur_frm.set_df_property('rate', 'description', doc.type=='Percentage'?'In Percentage %':'In Amount') +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index cd6bcf450b..59f0322acd 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -126,6 +126,12 @@ def get_pricing_rule_for_item(args): }) if args.ignore_pricing_rule or not args.item_code: + # if ignore pricing rule then set the rate or amount field to zero + if item_details.doctype in ["Quotation Item", "Sales Order Item"]: + item_details.update({ + "type":"Percentage", + "rate_or_amount": 0.00 + }) return item_details if not (args.item_group and args.brand): From 1e9c1640fa9d244810f4b7860d2679e185eada04 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:21:25 +0530 Subject: [PATCH 03/19] triggers on Margin type and Margin rate fields to calculate the revised Total Margin and Rate --- erpnext/selling/sales_common.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 25045fa98c..ece6adc4e2 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -307,6 +307,19 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } } }) + }, + rate_or_amount: function(doc, cdt, cdn) { + // calculated the revised total margin and rate on margin rate changes + item = locals[cdt][cdn]; + cur_frm.cscript.calculate_revised_margin_and_rate(item) + this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); + cur_frm.refresh_fields(); + }, + type: function(doc, cdt, cdn){ + // calculate the revised total margin and rate on margin type changes + item = locals[cdt][cdn]; + cur_frm.cscript.calculate_revised_margin_and_rate(item) + this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); } }); @@ -326,3 +339,18 @@ frappe.ui.form.on(cur_frm.doctype,"project", function(frm) { }) } }) + +cur_frm.cscript.calculate_revised_margin_and_rate = function(item){ + // calculate rate + + if(item.type == "Percentage") + item.total_margin = item.price_list_rate + item.price_list_rate * ( item.rate_or_amount / 100); + else + item.total_margin = item.price_list_rate + item.rate_or_amount; + + // subtracting the discount from total margin + item.rate = item.total_margin - item.total_margin * ( item.discount_percentage / 100 ); + item.amount = item.qty * item.rate + + cur_frm.refresh_fields(); +} \ No newline at end of file From 5738dd473cee418cdf9abbbb1fe7bdebaa1fc86d Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:24:57 +0530 Subject: [PATCH 04/19] set the target.ignore_pricing_rule to 0 --- erpnext/selling/doctype/quotation/quotation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 3c8add44f7..c180c415bd 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -91,7 +91,9 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): if customer: target.customer = customer.name target.customer_name = customer.customer_name - target.ignore_pricing_rule = 1 + # changed from 1 to 0, because margin is applied based on pricing rule. + # User will manually disabled pricing rule on sales order. + target.ignore_pricing_rule = 0 target.flags.ignore_permissions = ignore_permissions target.run_method("set_missing_values") target.run_method("calculate_taxes_and_totals") From c97becbd154a881755755a61ba0b38db37c851de Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:28:21 +0530 Subject: [PATCH 05/19] added document type in args --- erpnext/controllers/accounts_controller.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index bcaa9fbac9..dae1227ff1 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -138,6 +138,10 @@ class AccountsController(TransactionBase): for fieldname in self.meta.get_valid_columns(): parent_dict[fieldname] = self.get(fieldname) + if self.doctype in ["Quotation", "Sales Order"]: + document_type = "Quotation Item" if self.doctype == "Quotation" else "Sales Order Item" + parent_dict.update({"document_type": document_type}) + for item in self.get("items"): if item.get("item_code"): args = parent_dict.copy() From 36b51891637aaa2fd70f4fd4affa26030964740a Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:31:10 +0530 Subject: [PATCH 06/19] calculated the rate and total margin --- erpnext/controllers/taxes_and_totals.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index d4a64f2e7f..57a41d1870 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -59,6 +59,10 @@ class calculate_taxes_and_totals(object): item.rate = flt(item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")) + if item.doctype in ['Quotation Item', 'Sales Order Item']: + item.total_margin = self.calculate_margin(item) + item.rate = item.total_margin if item.total_margin > 0 else item.rate + item.net_rate = item.rate item.amount = flt(item.rate * item.qty, item.precision("amount")) item.net_amount = item.amount @@ -434,4 +438,18 @@ class calculate_taxes_and_totals(object): self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount), self.doc.precision("outstanding_amount")) elif self.doc.doctype == "Purchase Invoice": - self.doc.outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount")) \ No newline at end of file + self.doc.outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount")) + + def calculate_margin(self, item): + total_margin = 0.0 + if item.price_list_rate: + if item.pricing_rule: + pricing_rule = frappe.get_doc('Pricing Rule', item.pricing_rule) + if not item.type: item.type = pricing_rule.type + if not item.rate_or_amount: item.rate_or_amount = pricing_rule.rate + + if item.type and item.rate_or_amount: + margin_value = item.rate_or_amount if item.type == 'Amount' else flt(item.price_list_rate) * flt(item.rate_or_amount) / 100 + total_margin = flt(item.price_list_rate) + flt(margin_value) + + return total_margin From c79415eb96a819e77e0df8716704cd1caf5505e7 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:32:24 +0530 Subject: [PATCH 07/19] added rate and total margin in price_list --- erpnext/public/js/controllers/transaction.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 6de5154817..757dee0404 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -643,6 +643,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "parenttype": d.parenttype, "parent": d.parent }); + + // if doctype is Quotation Item / Sales Order Iten then add Margin Type and rate in item_list + if (d.doctype == "Quotation Item" || d.doctype == "Sales Order Item"){ + item_list[0]["type"] = d.type + item_list[0]["rate_or_amount"] = d.rate_or_amount + } } }; @@ -957,5 +963,3 @@ frappe.ui.form.on(cur_frm.doctype, "discount_amount", function(frm) { frm.cscript.calculate_taxes_and_totals(); }); - - From b8b56f127f392038cf61457a30381a12e586e7bf Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:33:02 +0530 Subject: [PATCH 08/19] fetched the markup type and rate of selected item --- erpnext/stock/get_item_details.py | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 7808e5006c..9713d86718 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -86,8 +86,76 @@ def get_item_details(args): get_gross_profit(out) + if args.document_type in ["Quotation Item", "Sales Order Item"]: + data = set_margin_fields(out.pricing_rule, out.price_list_rate) + out.update(data) + + # calculate rate by appling discount to total_margin + if(args.total_margin): + out["rate"] = discount_on_total_margin(args.total_margin, out.discount_percentage); + else: + out["rate"] = discount_on_total_margin(data.get("total_margin"), out.discount_percentage) + return out +def set_margin_fields(pricing_rule=None, price_list_rate=None): + """ + Todo: get the values of Margin (type and rate) + calculate the the Margin Amount, discount etc + """ + # margin_details dict will hold the all data variable regrading margin + margin_details = frappe._dict({}) + if pricing_rule and price_list_rate: + margin_details.update(get_margin_details(pricing_rule)) + margin_details.update(calculate_total_margin(margin_details.get("type"),margin_details.get("rate_or_amount"), price_list_rate)) + + return margin_details + +def get_margin_details(pricing_rule): + """ + get the margin details from pricing_rule + """ + margin_details = frappe._dict({ + "type":"Percentage", + "rate_or_amount":0.0, + }) + + records = frappe.db.sql("""SELECT type, rate FROM `tabPricing Rule` WHERE name = '%s'""" % pricing_rule, as_dict = 1) + + for record in records: + margin_details["type"] = record.get("type") + margin_details["rate_or_amount"] = record.get("rate") + + return margin_details + +def calculate_total_margin(margin_type,rate_or_amount,price_list_rate): + """ + calculate margin amount as follows + if type is percentage then calculate percentage of price_list_rate + """ + + data = frappe._dict({ + "total_margin":0.0, + "margin_amt":0.0, + }) + + if margin_type == "Amount": + data["margin_amt"] = rate_or_amount + else: + data["margin_amt"] = price_list_rate * ( rate_or_amount / 100 ) + + data["total_margin"] = price_list_rate + data["margin_amt"] + + return data + +def discount_on_total_margin(total_margin, discount): + """ + calculate the rate by appling discount on total_margin if any + """ + if discount: + total_margin = total_margin - (total_margin * (discount / 100)) + return total_margin + def process_args(args): if isinstance(args, basestring): args = json.loads(args) From e40736c1055747cab45adb8ce6a511b9889000fd Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 18 Jan 2016 16:33:57 +0530 Subject: [PATCH 09/19] test case for quotation --- .../doctype/quotation/test_quotation.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 3f30d05b7d..7bbc11efe0 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -32,5 +32,31 @@ class TestQuotation(unittest.TestCase): sales_order.transaction_date = "2013-05-12" sales_order.insert() + def test_create_quotation_with_margin(self): + from erpnext.selling.doctype.quotation.quotation import make_sales_order + from erpnext.selling.doctype.sales_order.sales_order \ + import make_material_request, make_delivery_note, make_sales_invoice + + test_records[0]['items'][0]['price_list_rate'] = 1500 + test_records[0]['items'][0]['type'] = 'Percentage' + test_records[0]['items'][0]['rate_or_amount'] = 20 + quotation = frappe.copy_doc(test_records[0]) + quotation.insert() + + self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name) + quotation.submit() + + sales_order = make_sales_order(quotation.name) + sales_order.delivery_date = "2016-01-02" + sales_order.naming_series = "_T-Quotation-" + sales_order.transaction_date = "2016-01-01" + sales_order.insert() + sales_order.submit() + + dn = make_delivery_note(sales_order.name) + dn.save() + + si = make_sales_invoice(sales_order.name) + si.save() test_records = frappe.get_test_records('Quotation') From 5e76a1cffad48132af72b7f0c7982459d079af76 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Tue, 19 Jan 2016 19:49:40 +0530 Subject: [PATCH 10/19] [fix] added eval for total margin and margin rate field --- erpnext/accounts/doctype/pricing_rule/pricing_rule.json | 4 ++-- erpnext/selling/doctype/quotation_item/quotation_item.json | 1 + .../selling/doctype/sales_order_item/sales_order_item.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index c099cec90d..170bf6fa72 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -764,7 +764,7 @@ "label": "Type of Margin", "length": 0, "no_copy": 0, - "options": "Percentage\nAmount", + "options": "\nPercentage\nAmount", "permlevel": 0, "precision": "", "print_hide": 0, @@ -1024,7 +1024,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-01-18 15:04:26.489659", + "modified": "2016-01-18 17:00:59.492217", "modified_by": "Administrator", "module": "Accounts", "name": "Pricing Rule", diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index b58568f46a..061e972a57 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -458,6 +458,7 @@ "allow_on_submit": 0, "bold": 1, "collapsible": 0, + "depends_on": "", "fieldname": "rate", "fieldtype": "Currency", "hidden": 0, 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 9710e39c78..3a44befd9c 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -468,7 +468,7 @@ "label": "Margin Type", "length": 0, "no_copy": 0, - "options": "Percentage\nAmount", + "options": "\nPercentage\nAmount", "permlevel": 0, "precision": "", "print_hide": 0, From 46c97c6e9542fc42f0b7d059fbb8661782d5507a Mon Sep 17 00:00:00 2001 From: mbauskar Date: Tue, 19 Jan 2016 19:51:11 +0530 Subject: [PATCH 11/19] [fix] discount percentage fix --- erpnext/controllers/accounts_controller.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index dae1227ff1..8e4b0a1225 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -170,7 +170,10 @@ class AccountsController(TransactionBase): item.set(fieldname, value) if ret.get("pricing_rule"): - item.set("discount_percentage", ret.get("discount_percentage")) + # if user changed the discount percentage then set user's discount percentage ? + discount_percentage = ret.get("discount_percentage") if item.get("discount_percentage") == \ + ret.get("discount_percentage") else item.get("discount_percentage") + item.set("discount_percentage", discount_percentage) if ret.get("pricing_rule_for") == "Price": item.set("pricing_list_rate", ret.get("pricing_list_rate")) From 1e428ae400e429ef8c7ba1f042caeec34d5f3019 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Tue, 19 Jan 2016 19:52:22 +0530 Subject: [PATCH 12/19] [fix] function to calculate the revised margin and rate --- erpnext/selling/sales_common.js | 50 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index ece6adc4e2..82b1342b00 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -308,18 +308,45 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } }) }, + + rate: function(doc, cdt, cdn){ + // if user changes the rate then set margin Rate or amount to 0 + item = locals[cdt][cdn]; + item.type = ""; + item.rate_or_amount = 0.0; + cur_frm.refresh_fields(); + }, + rate_or_amount: function(doc, cdt, cdn) { // calculated the revised total margin and rate on margin rate changes item = locals[cdt][cdn]; - cur_frm.cscript.calculate_revised_margin_and_rate(item) - this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); + this.calculate_revised_margin_and_rate(item) cur_frm.refresh_fields(); }, + type: function(doc, cdt, cdn){ // calculate the revised total margin and rate on margin type changes item = locals[cdt][cdn]; - cur_frm.cscript.calculate_revised_margin_and_rate(item) - this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); + this.calculate_revised_margin_and_rate(item, doc,cdt, cdn) + cur_frm.refresh_fields(); + }, + + calculate_revised_margin_and_rate: function(item){ + if(in_list(["Percentage", "Amount"], item.type)){ + if(item.type == "Percentage") + item.total_margin = item.price_list_rate + item.price_list_rate * ( item.rate_or_amount / 100); + else + item.total_margin = item.price_list_rate + item.rate_or_amount; + item.rate = flt(item.total_margin * (1 - item.discount_percentage / 100.0), + precision("rate", item)); + console.log(item.rate) + } + else{ + item.rate_or_amount = 0.0; + item.total_margin = 0.0; + item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0), + precision("rate", item)); + } } }); @@ -339,18 +366,3 @@ frappe.ui.form.on(cur_frm.doctype,"project", function(frm) { }) } }) - -cur_frm.cscript.calculate_revised_margin_and_rate = function(item){ - // calculate rate - - if(item.type == "Percentage") - item.total_margin = item.price_list_rate + item.price_list_rate * ( item.rate_or_amount / 100); - else - item.total_margin = item.price_list_rate + item.rate_or_amount; - - // subtracting the discount from total margin - item.rate = item.total_margin - item.total_margin * ( item.discount_percentage / 100 ); - item.amount = item.qty * item.rate - - cur_frm.refresh_fields(); -} \ No newline at end of file From dcd8b7773d3bf110192ddcd52d8dc6c1414275f0 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Wed, 20 Jan 2016 12:39:57 +0530 Subject: [PATCH 13/19] [fix] calculated rate on py side, added depends on for sales order item --- .../doctype/pricing_rule/pricing_rule.py | 4 +-- erpnext/controllers/taxes_and_totals.py | 3 ++- .../sales_order_item/sales_order_item.json | 26 +++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 59f0322acd..78bae96ebd 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -129,9 +129,9 @@ def get_pricing_rule_for_item(args): # if ignore pricing rule then set the rate or amount field to zero if item_details.doctype in ["Quotation Item", "Sales Order Item"]: item_details.update({ - "type":"Percentage", + "type":"", "rate_or_amount": 0.00 - }) + }) return item_details if not (args.item_group and args.brand): diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 57a41d1870..57baf15b52 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -61,7 +61,8 @@ class calculate_taxes_and_totals(object): if item.doctype in ['Quotation Item', 'Sales Order Item']: item.total_margin = self.calculate_margin(item) - item.rate = item.total_margin if item.total_margin > 0 else item.rate + item.rate = flt(item.total_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\ + if item.total_margin > 0 else item.rate item.net_rate = item.rate item.amount = flt(item.rate * item.qty, item.precision("amount")) 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 3a44befd9c..84c4652641 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -565,6 +565,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "depends_on": "eval: doc.type != \"\"", "fieldname": "rate_or_amount", "fieldtype": "Float", "hidden": 0, @@ -585,6 +586,31 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval: doc.type != \"\"", + "fieldname": "total_margin", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Total Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, From 6f60339e750b77c3ecaee9f48934f7b9bbc9a43b Mon Sep 17 00:00:00 2001 From: mbauskar Date: Thu, 21 Jan 2016 16:10:22 +0530 Subject: [PATCH 14/19] [fix] total margin calculations --- erpnext/stock/get_item_details.py | 46 ++++++++++++++----------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 9713d86718..1a79a429ef 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -87,24 +87,24 @@ def get_item_details(args): get_gross_profit(out) if args.document_type in ["Quotation Item", "Sales Order Item"]: - data = set_margin_fields(out.pricing_rule, out.price_list_rate) - out.update(data) - # calculate rate by appling discount to total_margin if(args.total_margin): out["rate"] = discount_on_total_margin(args.total_margin, out.discount_percentage); - else: + elif not args.type: + data = set_margin_fields(out.pricing_rule, out.price_list_rate) out["rate"] = discount_on_total_margin(data.get("total_margin"), out.discount_percentage) + out.update(data) return out def set_margin_fields(pricing_rule=None, price_list_rate=None): - """ - Todo: get the values of Margin (type and rate) - calculate the the Margin Amount, discount etc - """ # margin_details dict will hold the all data variable regrading margin - margin_details = frappe._dict({}) + margin_details = frappe._dict({ + "type":"", + "rate_or_amount": 0.0, + "total_margin": 0.0 + }) + if pricing_rule and price_list_rate: margin_details.update(get_margin_details(pricing_rule)) margin_details.update(calculate_total_margin(margin_details.get("type"),margin_details.get("rate_or_amount"), price_list_rate)) @@ -116,11 +116,11 @@ def get_margin_details(pricing_rule): get the margin details from pricing_rule """ margin_details = frappe._dict({ - "type":"Percentage", + "type":"", "rate_or_amount":0.0, }) - records = frappe.db.sql("""SELECT type, rate FROM `tabPricing Rule` WHERE name = '%s'""" % pricing_rule, as_dict = 1) + records = frappe.db.get_values("Pricing Rule", pricing_rule, ["type", "rate"], as_dict=True) for record in records: margin_details["type"] = record.get("type") @@ -133,20 +133,14 @@ def calculate_total_margin(margin_type,rate_or_amount,price_list_rate): calculate margin amount as follows if type is percentage then calculate percentage of price_list_rate """ - - data = frappe._dict({ - "total_margin":0.0, - "margin_amt":0.0, - }) - - if margin_type == "Amount": - data["margin_amt"] = rate_or_amount + default = frappe._dict({ "total_margin":0.0 }) + if not margin_type: + return default + elif margin_type == "Amount": + default.total_margin = price_list_rate + rate_or_amount else: - data["margin_amt"] = price_list_rate * ( rate_or_amount / 100 ) - - data["total_margin"] = price_list_rate + data["margin_amt"] - - return data + default.total_margin = price_list_rate + ( price_list_rate * ( rate_or_amount / 100 ) ) + return default def discount_on_total_margin(total_margin, discount): """ @@ -169,6 +163,8 @@ def process_args(args): args.item_code = get_item_code(barcode=args.barcode) elif not args.item_code and args.serial_no: args.item_code = get_item_code(serial_no=args.serial_no) + + set_transaction_type(args) set_transaction_type(args) @@ -579,4 +575,4 @@ def get_gross_profit(out): }) return out - \ No newline at end of file + From b6d19bcfc252a85abbc368a7e0c53bffa2c2bbe2 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Thu, 21 Jan 2016 19:59:13 +0530 Subject: [PATCH 15/19] [fixes] minor fixes, added eval on pricing rule, Sales Order Item, Quotation Item --- erpnext/accounts/doctype/pricing_rule/pricing_rule.json | 5 ++++- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 4 +++- .../selling/doctype/sales_order_item/sales_order_item.json | 1 + erpnext/selling/sales_common.js | 1 - erpnext/stock/get_item_details.py | 1 - 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index 170bf6fa72..57b4aca563 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -731,6 +731,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "depends_on": "eval: doc.selling == 1", "fieldname": "margin", "fieldtype": "Section Break", "hidden": 0, @@ -755,6 +756,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "default": "Percentage", "fieldname": "type", "fieldtype": "Select", "hidden": 0, @@ -803,6 +805,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "default": "0", "fieldname": "rate", "fieldtype": "Float", "hidden": 0, @@ -1024,7 +1027,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-01-18 17:00:59.492217", + "modified": "2016-01-21 19:10:54.861787", "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 78bae96ebd..7802272ef4 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -168,7 +168,9 @@ def get_pricing_rule_for_item(args): "discount_percentage": 0.0 }) else: - item_details.discount_percentage = pricing_rule.discount_percentage + # if user changed the discount percentage then set discount_percentage of user + item_details.discount_percentage = pricing_rule.discount_percentage if args.discount_percentage == pricing_rule.discount_percentage\ + else args.discount_percentage return item_details 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 84c4652641..96a9fbd5e1 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -459,6 +459,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "depends_on": "eval:doc.price_list_rate", "fieldname": "type", "fieldtype": "Select", "hidden": 0, diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 82b1342b00..3eb528f6a2 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -302,7 +302,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ callback: function(r) { if(!r.exc){ var doc = frappe.model.sync(r.message); - console.log(r.message) frappe.set_route("Form", r.message.doctype, r.message.name); } } diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 1a79a429ef..68d26ac76e 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -497,7 +497,6 @@ def apply_price_list(args, as_doc=False): # update the value if fieldname in item and fieldname not in ("name", "doctype"): item[fieldname] = children[i][fieldname] - return args else: return { From 75b6fbb6a75436ce34ab4c6acfcc4732e7c9c9d9 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Fri, 22 Jan 2016 16:49:03 +0530 Subject: [PATCH 16/19] [fix] apply pricing rule added type and rate on ignore pricing rule trigger --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 3 ++- erpnext/selling/sales_common.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 7802272ef4..b9c4cbb735 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -161,6 +161,8 @@ def get_pricing_rule_for_item(args): if pricing_rule: item_details.pricing_rule = pricing_rule.name item_details.pricing_rule_for = pricing_rule.price_or_discount + item_details.type = pricing_rule.type + item_details.rate_or_amount = pricing_rule.rate if pricing_rule.price_or_discount == "Price": item_details.update({ "price_list_rate": pricing_rule.price/flt(args.conversion_rate) \ @@ -171,7 +173,6 @@ def get_pricing_rule_for_item(args): # if user changed the discount percentage then set discount_percentage of user item_details.discount_percentage = pricing_rule.discount_percentage if args.discount_percentage == pricing_rule.discount_percentage\ else args.discount_percentage - return item_details def get_pricing_rules(args): diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 3eb528f6a2..e0c603ab11 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -338,7 +338,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ item.total_margin = item.price_list_rate + item.rate_or_amount; item.rate = flt(item.total_margin * (1 - item.discount_percentage / 100.0), precision("rate", item)); - console.log(item.rate) } else{ item.rate_or_amount = 0.0; From c1331d0e8e6270461b5fcd3f59a0135a94301676 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Fri, 29 Jan 2016 15:44:56 +0530 Subject: [PATCH 17/19] [minor-fix] pricing rule test-case fix --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index b9c4cbb735..0dcfc1fe5c 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -171,8 +171,8 @@ def get_pricing_rule_for_item(args): }) else: # if user changed the discount percentage then set discount_percentage of user - item_details.discount_percentage = pricing_rule.discount_percentage if args.discount_percentage == pricing_rule.discount_percentage\ - else args.discount_percentage + item_details.discount_percentage = args.discount_percentage if args.discount_percentage != pricing_rule.discount_percentage\ + and args.discount_percentage > 0 else pricing_rule.discount_percentage return item_details def get_pricing_rules(args): From a720c89535e1f1c64319d9bca1502af1dee16361 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 8 Feb 2016 17:31:03 +0530 Subject: [PATCH 18/19] [docs] documentation for adding margin in Quoation and SO --- .../img/selling/margin-item-price-list.png | Bin 0 -> 50896 bytes .../img/selling/margin-pricing-rule.png | Bin 0 -> 30588 bytes .../img/selling/margin-quotation-item.png | Bin 0 -> 37611 bytes .../en/selling/articles/adding-margin.md | 37 ++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 erpnext/docs/assets/img/selling/margin-item-price-list.png create mode 100644 erpnext/docs/assets/img/selling/margin-pricing-rule.png create mode 100644 erpnext/docs/assets/img/selling/margin-quotation-item.png create mode 100644 erpnext/docs/user/manual/en/selling/articles/adding-margin.md diff --git a/erpnext/docs/assets/img/selling/margin-item-price-list.png b/erpnext/docs/assets/img/selling/margin-item-price-list.png new file mode 100644 index 0000000000000000000000000000000000000000..49617559f5600b38e9c684127a56e97655d5c1a4 GIT binary patch literal 50896 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 literal 0 HcmV?d00001 diff --git a/erpnext/docs/assets/img/selling/margin-pricing-rule.png b/erpnext/docs/assets/img/selling/margin-pricing-rule.png new file mode 100644 index 0000000000000000000000000000000000000000..6dba884a3f7d10a9bec1c5b4117d54e54b9849ed GIT binary patch literal 30588 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
  • 2DUm~qLouQ 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 literal 0 HcmV?d00001 diff --git a/erpnext/docs/assets/img/selling/margin-quotation-item.png b/erpnext/docs/assets/img/selling/margin-quotation-item.png new file mode 100644 index 0000000000000000000000000000000000000000..d5ee8a3e523777a8d35ba41479e3f2ef0842c291 GIT binary patch literal 37611 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

    X$2DD-})1=f+S-W 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 literal 0 HcmV?d00001 diff --git a/erpnext/docs/user/manual/en/selling/articles/adding-margin.md b/erpnext/docs/user/manual/en/selling/articles/adding-margin.md new file mode 100644 index 0000000000..2a9ddfa25e --- /dev/null +++ b/erpnext/docs/user/manual/en/selling/articles/adding-margin.md @@ -0,0 +1,37 @@ +#Adding Margin + +User Can apply the margin on Quotation Item and Sales Order Item using following two options. +1)Price Rule: With the help of this method user can apply the margin on Quotation and Sales Order based on condition. you can find the section margin on pricing rule where a user has to select the type of margin whether it is Percentage or Amount and rate or amount. The system will apply the margin on quotation item and sales order item if pricing rule is enabled. + +To setup Pricing Rule, go to: + +`Selling > Setup > Pricing Rule` or `Accounts > Setup > Pricing Rule` + +####Adding Margin in Pricing Rule + +Adding Margin in Pricing Rule + +Total Margin is calculated as follows: +`Rate = Price List Rate + Margin Rate` + +So, In order to apply the Margin you need to add the Price List for the Item + +To add Price List, go to: + +`Selling > Setup > Item Price` or `Stock > Setup > Item Price` + +####Adding Item Price + +Adding Margin in Pricing Rule + +2) Apply margin direct on Item: If user wants to apply the margin without pricing rule, they can use this option. In Quotation Item and Sales Order Item, user can select the margin type and rate or amount. The system will calculate the margin and apply it on price list rate to calculate the rate of the product. + +To add margin directly on Quotation or Sales Order, go to: + +`Selling > Document > Quotation` + +add item and scroll down to section where you can find the Margin Type + +####Adding Margin in Quotation + +Adding Margin in Quotation From a52472cf5b16649adf8b77d43a0d62857f67b04a Mon Sep 17 00:00:00 2001 From: mbauskar Date: Sat, 5 Mar 2016 15:10:25 +0530 Subject: [PATCH 19/19] [fixes] added fields in SI and DN, moved the margin calculation to to pricing_rule.py --- .../doctype/pricing_rule/pricing_rule.json | 53 +++- .../doctype/pricing_rule/pricing_rule.py | 16 +- .../doctype/pricing_rule/test_pricing_rule.py | 48 ++++ .../sales_invoice/test_sales_invoice.py | 13 + .../sales_invoice_item.json | 240 ++++++++++++++-- erpnext/controllers/accounts_controller.py | 8 +- erpnext/controllers/taxes_and_totals.py | 14 +- erpnext/public/js/controllers/transaction.js | 6 +- .../selling/doctype/quotation/quotation.py | 4 +- .../doctype/quotation/test_quotation.py | 17 +- .../quotation_item/quotation_item.json | 189 ++++++++++-- .../doctype/sales_order/test_sales_order.py | 15 + .../sales_order_item/sales_order_item.json | 268 +++++++++++------- erpnext/selling/sales_common.js | 29 +- .../delivery_note_item.json | 236 +++++++++++++-- erpnext/stock/get_item_details.py | 65 ----- 16 files changed, 912 insertions(+), 309 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index 57b4aca563..23fc76d480 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -17,6 +17,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "", @@ -40,6 +41,7 @@ "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Title", @@ -65,6 +67,7 @@ "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Apply On", @@ -90,6 +93,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Item Code", @@ -115,6 +119,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Brand", @@ -140,6 +145,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Item Group", @@ -164,6 +170,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -188,6 +195,7 @@ "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Priority", @@ -212,6 +220,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Disable", @@ -235,6 +244,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -258,6 +268,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Selling", @@ -281,6 +292,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Buying", @@ -304,6 +316,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -328,6 +341,7 @@ "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Applicable For", @@ -353,6 +367,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer", @@ -378,6 +393,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer Group", @@ -403,6 +419,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Territory", @@ -428,6 +445,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Sales Partner", @@ -453,6 +471,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Campaign", @@ -478,6 +497,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Supplier", @@ -503,6 +523,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Supplier Type", @@ -527,6 +548,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -550,6 +572,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Min Qty", @@ -573,6 +596,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -596,6 +620,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Max Qty", @@ -619,6 +644,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -643,6 +669,7 @@ "fieldtype": "Date", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Valid From", @@ -666,6 +693,7 @@ "fieldtype": "Date", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Valid Upto", @@ -689,6 +717,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -711,6 +740,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Company", @@ -736,6 +766,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Margin", @@ -757,13 +788,14 @@ "bold": 0, "collapsible": 0, "default": "Percentage", - "fieldname": "type", + "fieldname": "margin_type", "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "label": "Type of Margin", + "label": "Margin Type", "length": 0, "no_copy": 0, "options": "\nPercentage\nAmount", @@ -786,6 +818,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -806,13 +839,15 @@ "bold": 0, "collapsible": 0, "default": "0", - "fieldname": "rate", + "depends_on": "eval:doc.margin_type", + "fieldname": "margin_rate_or_amount", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "label": "Rate", + "label": "Margin Rate or Amount", "length": 0, "no_copy": 0, "permlevel": 0, @@ -834,6 +869,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "", @@ -858,6 +894,7 @@ "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price or Discount", @@ -882,6 +919,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -905,6 +943,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price", @@ -929,6 +968,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Discount on Price List Rate (%)", @@ -953,6 +993,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "For Price List", @@ -977,6 +1018,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "", @@ -1001,6 +1043,7 @@ "fieldtype": "HTML", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Pricing Rule Help", @@ -1027,7 +1070,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-01-21 19:10:54.861787", + "modified": "2016-03-16 17:35:25.935271", "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 0dcfc1fe5c..431675ef1c 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -124,14 +124,8 @@ def get_pricing_rule_for_item(args): "name": args.name, "pricing_rule": None }) - + if args.ignore_pricing_rule or not args.item_code: - # if ignore pricing rule then set the rate or amount field to zero - if item_details.doctype in ["Quotation Item", "Sales Order Item"]: - item_details.update({ - "type":"", - "rate_or_amount": 0.00 - }) return item_details if not (args.item_group and args.brand): @@ -161,8 +155,8 @@ def get_pricing_rule_for_item(args): if pricing_rule: item_details.pricing_rule = pricing_rule.name item_details.pricing_rule_for = pricing_rule.price_or_discount - item_details.type = pricing_rule.type - item_details.rate_or_amount = pricing_rule.rate + item_details.margin_type = pricing_rule.margin_type + item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount if pricing_rule.price_or_discount == "Price": item_details.update({ "price_list_rate": pricing_rule.price/flt(args.conversion_rate) \ @@ -170,9 +164,7 @@ def get_pricing_rule_for_item(args): "discount_percentage": 0.0 }) else: - # if user changed the discount percentage then set discount_percentage of user - item_details.discount_percentage = args.discount_percentage if args.discount_percentage != pricing_rule.discount_percentage\ - and args.discount_percentage > 0 else pricing_rule.discount_percentage + item_details.discount_percentage = pricing_rule.discount_percentage return item_details def get_pricing_rules(args): diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index d8d74bc707..814c5c0acf 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -86,6 +86,54 @@ class TestPricingRule(unittest.TestCase): frappe.db.sql("delete from `tabPricing Rule`") + def test_pricing_rule_for_margin(self): + from erpnext.stock.get_item_details import get_item_details + from frappe import MandatoryError + + frappe.db.sql("delete from `tabPricing Rule`") + + test_record = { + "doctype": "Pricing Rule", + "title": "_Test Pricing Rule", + "apply_on": "Item Code", + "item_code": "_Test FG Item 2", + "selling": 1, + "price_or_discount": "Discount Percentage", + "price": 0, + "margin_type": "Percentage", + "margin_rate_or_amount": 10, + "company": "_Test Company" + } + frappe.get_doc(test_record.copy()).insert() + + item_price = frappe.get_doc({ + "doctype": "Item Price", + "price_list": "_Test Price List 2", + "item_code": "_Test FG Item 2", + "price_list_rate": 100 + }) + + item_price.insert(ignore_permissions=True) + + args = frappe._dict({ + "item_code": "_Test FG Item 2", + "company": "_Test Company", + "price_list": "_Test Price List", + "currency": "_Test Currency", + "doctype": "Sales Order", + "conversion_rate": 1, + "price_list_currency": "_Test Currency", + "plc_conversion_rate": 1, + "order_type": "Sales", + "customer": "_Test Customer", + "name": None + }) + details = get_item_details(args) + self.assertEquals(details.get("margin_type"), "Percentage") + self.assertEquals(details.get("margin_rate_or_amount"), 10) + + frappe.db.sql("delete from `tabPricing Rule`") + def test_pricing_rule_for_variants(self): from erpnext.stock.get_item_details import get_item_details from frappe import MandatoryError diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index fc8ca632a6..bac24d8027 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -910,6 +910,19 @@ class TestSalesInvoice(unittest.TestCase): self.assertRaises(InvalidAccountCurrency, si5.submit) + def test_create_so_with_margin(self): + si = create_sales_invoice(item_code="_Test Item", qty=1, do_not_submit=True) + price_list_rate = si.items[0].price_list_rate + si.items[0].margin_type = 'Percentage' + si.items[0].margin_rate_or_amount = 25 + si.insert() + + self.assertNotEquals(si.get("items")[0].rate, flt((price_list_rate*25)/100 + price_list_rate)) + si.items[0].margin_rate_or_amount = 25 + si.submit() + + self.assertNotEquals(si.get("items")[0].rate, flt((price_list_rate*25)/100 + price_list_rate)) + def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") args = frappe._dict(args) 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 79f5f555c2..41bff7c47e 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -17,6 +17,7 @@ "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Barcode", @@ -40,6 +41,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, "label": "Item", @@ -66,6 +68,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -88,6 +91,7 @@ "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Item Name", @@ -113,6 +117,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer's Item Code", @@ -136,6 +141,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Edit Description", @@ -160,6 +166,7 @@ "fieldtype": "Text Editor", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Description", @@ -187,6 +194,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -210,6 +218,7 @@ "fieldtype": "Image", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Image View", @@ -235,6 +244,7 @@ "fieldtype": "Attach", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Image", @@ -259,6 +269,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "", @@ -282,6 +293,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Quantity", @@ -307,6 +319,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price List Rate", @@ -325,32 +338,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "price_list_rate", - "fieldname": "discount_percentage", - "fieldtype": "Percent", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Discount on Price List Rate (%)", - "length": 0, - "no_copy": 0, - "oldfieldname": "adj_rate", - "oldfieldtype": "Float", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -359,6 +346,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -381,6 +369,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "UOM", @@ -405,6 +394,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price List Rate (Company Currency)", @@ -423,6 +413,161 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "discount_and_margin", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Discount and Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "discount_percentage", + "fieldtype": "Percent", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Discount on Price List Rate (%)", + "length": 0, + "no_copy": 0, + "oldfieldname": "adj_rate", + "oldfieldtype": "Float", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_19", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "margin_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Type", + "length": 0, + "no_copy": 0, + "options": "\nPercentage\nAmount", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "margin_rate_or_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Rate or Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "total_margin", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Total Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -431,6 +576,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -453,6 +599,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Rate", @@ -479,6 +626,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Amount", @@ -505,6 +653,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -527,6 +676,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Rate (Company Currency)", @@ -553,6 +703,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Amount (Company Currency)", @@ -579,6 +730,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Pricing Rule", @@ -603,6 +755,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -626,6 +779,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Rate", @@ -651,6 +805,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Amount", @@ -676,6 +831,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -699,6 +855,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Rate (Company Currency)", @@ -724,6 +881,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Amount (Company Currency)", @@ -750,6 +908,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Drop Ship", @@ -774,6 +933,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Delivered By Supplier", @@ -798,6 +958,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Accounting Details", @@ -821,6 +982,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Income Account", @@ -849,6 +1011,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Expense Account", @@ -874,6 +1037,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -897,6 +1061,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Cost Center", @@ -926,6 +1091,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Stock Details", @@ -949,6 +1115,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Warehouse", @@ -975,6 +1142,7 @@ "fieldtype": "Link", "hidden": 1, "ignore_user_permissions": 1, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer Warehouse (Optional)", @@ -1000,6 +1168,7 @@ "fieldtype": "Small Text", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, "label": "Serial No", @@ -1025,6 +1194,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Batch No", @@ -1050,6 +1220,7 @@ "fieldtype": "Link", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Item Group", @@ -1076,6 +1247,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Brand Name", @@ -1101,6 +1273,7 @@ "fieldtype": "Small Text", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Item Tax Rate", @@ -1126,6 +1299,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -1148,6 +1322,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Available Batch Qty at Warehouse", @@ -1174,6 +1349,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Available Qty at Warehouse", @@ -1199,6 +1375,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "References", @@ -1223,6 +1400,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Time Log Batch", @@ -1247,6 +1425,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Sales Order", @@ -1273,6 +1452,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Sales Order Item", @@ -1298,6 +1478,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -1321,6 +1502,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Delivery Note", @@ -1347,6 +1529,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Delivery Note Item", @@ -1372,6 +1555,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Delivered Qty", @@ -1397,6 +1581,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -1420,6 +1605,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Page Break", @@ -1445,7 +1631,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-02-01 11:16:58.288462", + "modified": "2016-03-22 11:09:35.263922", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 8e4b0a1225..97cbd7dba4 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -138,8 +138,8 @@ class AccountsController(TransactionBase): for fieldname in self.meta.get_valid_columns(): parent_dict[fieldname] = self.get(fieldname) - if self.doctype in ["Quotation", "Sales Order"]: - document_type = "Quotation Item" if self.doctype == "Quotation" else "Sales Order Item" + if self.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]: + document_type = "{} Item".format(self.doctype) parent_dict.update({"document_type": document_type}) for item in self.get("items"): @@ -171,9 +171,7 @@ class AccountsController(TransactionBase): if ret.get("pricing_rule"): # if user changed the discount percentage then set user's discount percentage ? - discount_percentage = ret.get("discount_percentage") if item.get("discount_percentage") == \ - ret.get("discount_percentage") else item.get("discount_percentage") - item.set("discount_percentage", discount_percentage) + item.set("discount_percentage", ret.get("discount_percentage")) if ret.get("pricing_rule_for") == "Price": item.set("pricing_list_rate", ret.get("pricing_list_rate")) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 57baf15b52..67cec8a50e 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -59,11 +59,11 @@ class calculate_taxes_and_totals(object): item.rate = flt(item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")) - if item.doctype in ['Quotation Item', 'Sales Order Item']: + if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']: item.total_margin = self.calculate_margin(item) item.rate = flt(item.total_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\ if item.total_margin > 0 else item.rate - + item.net_rate = item.rate item.amount = flt(item.rate * item.qty, item.precision("amount")) item.net_amount = item.amount @@ -444,13 +444,13 @@ class calculate_taxes_and_totals(object): def calculate_margin(self, item): total_margin = 0.0 if item.price_list_rate: - if item.pricing_rule: + if item.pricing_rule and not self.doc.ignore_pricing_rule: pricing_rule = frappe.get_doc('Pricing Rule', item.pricing_rule) - if not item.type: item.type = pricing_rule.type - if not item.rate_or_amount: item.rate_or_amount = pricing_rule.rate + item.margin_type = pricing_rule.margin_type + item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount - if item.type and item.rate_or_amount: - margin_value = item.rate_or_amount if item.type == 'Amount' else flt(item.price_list_rate) * flt(item.rate_or_amount) / 100 + 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 total_margin = flt(item.price_list_rate) + flt(margin_value) return total_margin diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 757dee0404..1efe4b71d7 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -645,9 +645,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }); // if doctype is Quotation Item / Sales Order Iten then add Margin Type and rate in item_list - if (d.doctype == "Quotation Item" || d.doctype == "Sales Order Item"){ - item_list[0]["type"] = d.type - item_list[0]["rate_or_amount"] = d.rate_or_amount + if (in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item"]), d.doctype){ + item_list[0]["margin_type"] = d.margin_type + item_list[0]["margin_rate_or_amount"] = d.margin_rate_or_amount } } }; diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index c180c415bd..3c8add44f7 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -91,9 +91,7 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): if customer: target.customer = customer.name target.customer_name = customer.customer_name - # changed from 1 to 0, because margin is applied based on pricing rule. - # User will manually disabled pricing rule on sales order. - target.ignore_pricing_rule = 0 + target.ignore_pricing_rule = 1 target.flags.ignore_permissions = ignore_permissions target.run_method("set_missing_values") target.run_method("calculate_taxes_and_totals") diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 7bbc11efe0..e3b359daf6 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -2,7 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json +import frappe from frappe.utils import flt import unittest @@ -35,14 +35,18 @@ class TestQuotation(unittest.TestCase): def test_create_quotation_with_margin(self): from erpnext.selling.doctype.quotation.quotation import make_sales_order from erpnext.selling.doctype.sales_order.sales_order \ - import make_material_request, make_delivery_note, make_sales_invoice + import make_delivery_note, make_sales_invoice + + total_margin = flt((1500*18.75)/100 + 1500) test_records[0]['items'][0]['price_list_rate'] = 1500 - test_records[0]['items'][0]['type'] = 'Percentage' - test_records[0]['items'][0]['rate_or_amount'] = 20 + test_records[0]['items'][0]['margin_type'] = 'Percentage' + test_records[0]['items'][0]['margin_rate_or_amount'] = 18.75 + quotation = frappe.copy_doc(test_records[0]) quotation.insert() + self.assertEquals(quotation.get("items")[0].rate, total_margin) self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name) quotation.submit() @@ -51,12 +55,17 @@ class TestQuotation(unittest.TestCase): sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = "2016-01-01" sales_order.insert() + + self.assertEquals(quotation.get("items")[0].rate, total_margin) + sales_order.submit() dn = make_delivery_note(sales_order.name) + self.assertEquals(quotation.get("items")[0].rate, total_margin) dn.save() si = make_sales_invoice(sales_order.name) + self.assertEquals(quotation.get("items")[0].rate, total_margin) si.save() test_records = frappe.get_test_records('Quotation') diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index 061e972a57..2c02e03e6e 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -7,6 +7,7 @@ "custom": 0, "docstatus": 0, "doctype": "DocType", + "document_type": "Document", "fields": [ { "allow_on_submit": 0, @@ -321,35 +322,6 @@ "unique": 0, "width": "100px" }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "price_list_rate", - "fieldname": "discount_percentage", - "fieldtype": "Percent", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Discount on Price List Rate (%)", - "length": 0, - "no_copy": 0, - "oldfieldname": "adj_rate", - "oldfieldtype": "Float", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": "100px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, - "width": "100px" - }, { "allow_on_submit": 0, "bold": 0, @@ -431,6 +403,163 @@ "unique": 0, "width": "100px" }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "discount_and_margin", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Discount and Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "discount_percentage", + "fieldtype": "Percent", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Discount on Price List Rate (%)", + "length": 0, + "no_copy": 0, + "oldfieldname": "adj_rate", + "oldfieldtype": "Float", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": "100px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "100px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_18", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "margin_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Type", + "length": 0, + "no_copy": 0, + "options": "\nPercentage\nAmount", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "margin_rate_or_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Rate or Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "total_margin", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Total Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -1098,7 +1227,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2016-02-26 18:30:22.286356", + "modified": "2016-03-22 11:12:36.533712", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index edd7cdfc4d..4ba6ff063d 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -415,6 +415,21 @@ class TestSalesOrder(unittest.TestCase): self.assertEquals(get_reserved_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"), existing_reserved_qty) + def test_create_so_with_margin(self): + so = make_sales_order(item_code="_Test Item", qty=1, do_not_submit=True) + so.items[0].price_list_rate = price_list_rate = 100 + so.items[0].margin_type = 'Percentage' + so.items[0].margin_rate_or_amount = 25 + so.insert() + + new_so = frappe.copy_doc(so) + new_so.save(ignore_permissions=True) + + self.assertEquals(new_so.get("items")[0].rate, flt((price_list_rate*25)/100 + price_list_rate)) + new_so.items[0].margin_rate_or_amount = 25 + new_so.submit() + + self.assertEquals(new_so.get("items")[0].rate, flt((price_list_rate*25)/100 + price_list_rate)) def make_sales_order(**args): so = frappe.new_doc("Sales Order") 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 96a9fbd5e1..b81393f2ca 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -322,35 +322,6 @@ "unique": 0, "width": "70px" }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "price_list_rate", - "fieldname": "discount_percentage", - "fieldtype": "Percent", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Discount on Price List Rate (%)", - "length": 0, - "no_copy": 0, - "oldfieldname": "adj_rate", - "oldfieldtype": "Float", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": "70px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, - "width": "70px" - }, { "allow_on_submit": 0, "bold": 0, @@ -432,6 +403,163 @@ "unique": 0, "width": "100px" }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "discount_and_margin", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Discount and Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "discount_percentage", + "fieldtype": "Percent", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Discount on Price List Rate (%)", + "length": 0, + "no_copy": 0, + "oldfieldname": "adj_rate", + "oldfieldtype": "Float", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": "70px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "70px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_19", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "margin_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Type", + "length": 0, + "no_copy": 0, + "options": "\nPercentage\nAmount", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "margin_rate_or_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Rate or Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "total_margin", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Total Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -459,34 +587,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "depends_on": "eval:doc.price_list_rate", - "fieldname": "type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Margin Type", - "length": 0, - "no_copy": 0, - "options": "\nPercentage\nAmount", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, + "depends_on": "eval: doc.type != \"\"", "fieldname": "rate", - "fieldtype": "Currency", + "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -528,6 +631,7 @@ "oldfieldtype": "Currency", "options": "currency", "permlevel": 0, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": "100px", @@ -562,56 +666,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval: doc.type != \"\"", - "fieldname": "rate_or_amount", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Margin Rate or Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "2", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval: doc.type != \"\"", - "fieldname": "total_margin", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Total Margin", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -1468,7 +1522,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2016-02-26 11:08:24.708912", + "modified": "2016-03-22 11:09:12.915922", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index e0c603ab11..bfefb9fa5b 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -122,10 +122,13 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ var item = frappe.get_doc(cdt, cdn); frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]); - item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0), - precision("rate", item)); - - this.set_gross_profit(item); + // check if child doctype is Sales Order Item/Qutation Item and calculate the rate + if(in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item"]), cdt) + this.calculate_revised_margin_and_rate(item, doc,cdt, cdn); + else + item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0), + precision("rate", item)); + this.calculate_taxes_and_totals(); }, @@ -311,31 +314,33 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ rate: function(doc, cdt, cdn){ // if user changes the rate then set margin Rate or amount to 0 item = locals[cdt][cdn]; - item.type = ""; - item.rate_or_amount = 0.0; + item.margin_type = ""; + item.margin_rate_or_amount = 0.0; cur_frm.refresh_fields(); }, - rate_or_amount: function(doc, cdt, cdn) { + margin_rate_or_amount: function(doc, cdt, cdn) { // calculated the revised total margin and rate on margin rate changes item = locals[cdt][cdn]; this.calculate_revised_margin_and_rate(item) + this.calculate_taxes_and_totals(); cur_frm.refresh_fields(); }, - type: function(doc, cdt, cdn){ + margin_type: function(doc, cdt, cdn){ // calculate the revised total margin and rate on margin type changes item = locals[cdt][cdn]; this.calculate_revised_margin_and_rate(item, doc,cdt, cdn) + this.calculate_taxes_and_totals(); cur_frm.refresh_fields(); }, calculate_revised_margin_and_rate: function(item){ - if(in_list(["Percentage", "Amount"], item.type)){ - if(item.type == "Percentage") - item.total_margin = item.price_list_rate + item.price_list_rate * ( item.rate_or_amount / 100); + if(in_list(["Percentage", "Amount"], item.margin_type)){ + if(item.margin_type == "Percentage") + item.total_margin = item.price_list_rate + item.price_list_rate * ( item.margin_rate_or_amount / 100); else - item.total_margin = item.price_list_rate + item.rate_or_amount; + item.total_margin = item.price_list_rate + item.margin_rate_or_amount; item.rate = flt(item.total_margin * (1 - item.discount_percentage / 100.0), precision("rate", item)); } 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 6ed16ce51b..6f49793f90 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -17,6 +17,7 @@ "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Barcode", @@ -40,6 +41,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, "label": "Item Code", @@ -68,6 +70,7 @@ "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Item Name", @@ -95,6 +98,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -117,6 +121,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer's Item Code", @@ -140,6 +145,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Description", @@ -164,6 +170,7 @@ "fieldtype": "Text Editor", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Description", @@ -191,6 +198,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -214,6 +222,7 @@ "fieldtype": "Attach", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Image", @@ -238,6 +247,7 @@ "fieldtype": "Image", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Image View", @@ -263,6 +273,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Quantity and Rate", @@ -286,6 +297,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Quantity", @@ -313,6 +325,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price List Rate", @@ -333,34 +346,6 @@ "unique": 0, "width": "100px" }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "price_list_rate", - "fieldname": "discount_percentage", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Discount on Price List Rate (%)", - "length": 0, - "no_copy": 0, - "oldfieldname": "adj_rate", - "oldfieldtype": "Float", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "print_width": "100px", - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, - "width": "100px" - }, { "allow_on_submit": 0, "bold": 0, @@ -369,6 +354,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -391,6 +377,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "UOM", @@ -419,6 +406,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Price List Rate (Company Currency)", @@ -439,6 +427,163 @@ "unique": 0, "width": "100px" }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "discount_and_margin", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Discount and Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "discount_percentage", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Discount on Price List Rate (%)", + "length": 0, + "no_copy": 0, + "oldfieldname": "adj_rate", + "oldfieldtype": "Float", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": "100px", + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "100px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_19", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "price_list_rate", + "fieldname": "margin_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Type", + "length": 0, + "no_copy": 0, + "options": "\nPercentage\nAmount", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "margin_rate_or_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Margin Rate or Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate", + "fieldname": "total_margin", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Total Margin", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -447,6 +592,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -469,6 +615,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Rate", @@ -497,6 +644,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Amount", @@ -525,6 +673,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -547,6 +696,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Rate (Company Currency)", @@ -575,6 +725,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Amount (Company Currency)", @@ -603,6 +754,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Pricing Rule", @@ -627,6 +779,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -650,6 +803,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Rate", @@ -675,6 +829,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Amount", @@ -700,6 +855,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -723,6 +879,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Rate (Company Currency)", @@ -748,6 +905,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Net Amount (Company Currency)", @@ -773,6 +931,7 @@ "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Warehouse and Reference", @@ -796,6 +955,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "From Warehouse", @@ -826,6 +986,7 @@ "fieldtype": "Link", "hidden": 1, "ignore_user_permissions": 1, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Customer Warehouse (Optional)", @@ -851,6 +1012,7 @@ "fieldtype": "Text", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, "label": "Serial No", @@ -876,6 +1038,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, "label": "Batch No", @@ -902,6 +1065,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Available Qty at From Warehouse", @@ -930,6 +1094,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Available Batch Qty at From Warehouse", @@ -957,6 +1122,7 @@ "fieldtype": "Link", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Item Group", @@ -983,6 +1149,7 @@ "fieldtype": "Link", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Brand Name", @@ -1011,6 +1178,7 @@ "fieldtype": "Small Text", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Item Tax Rate", @@ -1036,6 +1204,7 @@ "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "length": 0, @@ -1058,6 +1227,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Expense Account", @@ -1084,6 +1254,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Cost Center", @@ -1109,6 +1280,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Against Sales Order", @@ -1133,6 +1305,7 @@ "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Against Sales Invoice", @@ -1157,6 +1330,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Against Sales Order Item", @@ -1184,6 +1358,7 @@ "fieldtype": "Data", "hidden": 1, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, "label": "Against Sales Invoice Item", @@ -1208,6 +1383,7 @@ "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Installed Qty", @@ -1235,6 +1411,7 @@ "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Billed Amt", @@ -1260,6 +1437,7 @@ "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, "label": "Page Break", @@ -1287,7 +1465,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-02-01 11:16:23.749244", + "modified": "2016-03-22 11:10:15.168345", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 68d26ac76e..9032c7fb83 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -86,70 +86,8 @@ def get_item_details(args): get_gross_profit(out) - if args.document_type in ["Quotation Item", "Sales Order Item"]: - # calculate rate by appling discount to total_margin - if(args.total_margin): - out["rate"] = discount_on_total_margin(args.total_margin, out.discount_percentage); - elif not args.type: - data = set_margin_fields(out.pricing_rule, out.price_list_rate) - out["rate"] = discount_on_total_margin(data.get("total_margin"), out.discount_percentage) - out.update(data) - return out -def set_margin_fields(pricing_rule=None, price_list_rate=None): - # margin_details dict will hold the all data variable regrading margin - margin_details = frappe._dict({ - "type":"", - "rate_or_amount": 0.0, - "total_margin": 0.0 - }) - - if pricing_rule and price_list_rate: - margin_details.update(get_margin_details(pricing_rule)) - margin_details.update(calculate_total_margin(margin_details.get("type"),margin_details.get("rate_or_amount"), price_list_rate)) - - return margin_details - -def get_margin_details(pricing_rule): - """ - get the margin details from pricing_rule - """ - margin_details = frappe._dict({ - "type":"", - "rate_or_amount":0.0, - }) - - records = frappe.db.get_values("Pricing Rule", pricing_rule, ["type", "rate"], as_dict=True) - - for record in records: - margin_details["type"] = record.get("type") - margin_details["rate_or_amount"] = record.get("rate") - - return margin_details - -def calculate_total_margin(margin_type,rate_or_amount,price_list_rate): - """ - calculate margin amount as follows - if type is percentage then calculate percentage of price_list_rate - """ - default = frappe._dict({ "total_margin":0.0 }) - if not margin_type: - return default - elif margin_type == "Amount": - default.total_margin = price_list_rate + rate_or_amount - else: - default.total_margin = price_list_rate + ( price_list_rate * ( rate_or_amount / 100 ) ) - return default - -def discount_on_total_margin(total_margin, discount): - """ - calculate the rate by appling discount on total_margin if any - """ - if discount: - total_margin = total_margin - (total_margin * (discount / 100)) - return total_margin - def process_args(args): if isinstance(args, basestring): args = json.loads(args) @@ -165,9 +103,6 @@ def process_args(args): args.item_code = get_item_code(serial_no=args.serial_no) set_transaction_type(args) - - set_transaction_type(args) - return args @frappe.whitelist()