From be690ef817407759f8c24ddd0061d94b728bced9 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Tue, 14 Nov 2017 17:22:41 +0530 Subject: [PATCH] Rate with margin in customer and company currency (#11437) * field for company margin * added base_rate_with_margin * calculate company margin * test for item price * test for delivery note * test for sales order * test for quotation * test for sales invoice --- .../tests/test_sales_invoice_with_margin.js | 36 ++++++++++++++++++ .../sales_invoice_item.json | 35 ++++++++++++++++- erpnext/controllers/taxes_and_totals.py | 6 ++- .../public/js/controllers/taxes_and_totals.js | 2 + .../tests/test_quotation_with_margin.js | 36 ++++++++++++++++++ .../quotation_item/quotation_item.json | 35 ++++++++++++++++- .../tests/test_sales_order_with_margin.js | 38 +++++++++++++++++++ .../sales_order_item/sales_order_item.json | 35 ++++++++++++++++- .../test_delivery_note_with_margin.js | 37 ++++++++++++++++++ .../delivery_note_item.json | 35 ++++++++++++++++- .../doctype/item_price/test_item_price.js | 22 +++++++++++ erpnext/tests/ui/tests.txt | 5 +++ 12 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js create mode 100644 erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js create mode 100644 erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js create mode 100644 erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js create mode 100644 erpnext/stock/doctype/item_price/test_item_price.js diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js new file mode 100644 index 0000000000..60652c8add --- /dev/null +++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js @@ -0,0 +1,36 @@ +QUnit.module('Accounts'); + +QUnit.test("test sales invoice with margin", function(assert) { + assert.expect(3); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Sales Invoice', [ + {customer: 'Test Customer 1'}, + {selling_price_list: 'Test-Selling-USD'}, + {currency: 'USD'}, + {items: [ + [ + {'item_code': 'Test Product 3'}, + {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)}, + {'qty': 1}, + {'margin_type': 'Percentage'}, + {'margin_rate_or_amount': 20} + ] + ]} + ]); + }, + () => cur_frm.save(), + () => { + assert.ok(cur_frm.doc.items[0].rate_with_margin == 240, "Margin rate correct"); + assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 240, "Base margin rate correct"); + assert.ok(cur_frm.doc.total == 240, "Amount correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + 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 613f3847b9..becb90282d 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -729,6 +729,7 @@ "label": "Rate With Margin", "length": 0, "no_copy": 0, + "options": "currency", "permlevel": 0, "precision": "2", "print_hide": 1, @@ -803,6 +804,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", + "fieldname": "base_rate_with_margin", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rate With Margin (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -2166,7 +2199,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-09-27 08:31:37.827893", + "modified": "2017-11-03 11:33:36.004844", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index e85e56b4d6..e9672df0df 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -62,7 +62,7 @@ class calculate_taxes_and_totals(object): (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")) if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']: - item.rate_with_margin = self.calculate_margin(item) + item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item) item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\ if item.rate_with_margin > 0 else item.rate @@ -503,6 +503,7 @@ class calculate_taxes_and_totals(object): def calculate_margin(self, item): rate_with_margin = 0.0 + base_rate_with_margin = 0.0 if item.price_list_rate: if item.pricing_rule and not self.doc.ignore_pricing_rule: pricing_rule = frappe.get_doc('Pricing Rule', item.pricing_rule) @@ -512,8 +513,9 @@ class calculate_taxes_and_totals(object): if item.margin_type and item.margin_rate_or_amount: margin_value = item.margin_rate_or_amount if item.margin_type == 'Amount' else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100 rate_with_margin = flt(item.price_list_rate) + flt(margin_value) + base_rate_with_margin = flt(rate_with_margin) * flt(self.doc.conversion_rate) - return rate_with_margin + return rate_with_margin, base_rate_with_margin def set_item_wise_tax_breakup(self): self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 84624b8997..05c323bdc6 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -4,11 +4,13 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ setup: function() {}, apply_pricing_rule_on_item: function(item){ + if(item.margin_type == "Percentage"){ item.rate_with_margin = flt(item.price_list_rate) + flt(item.price_list_rate) * ( flt(item.margin_rate_or_amount) / 100); } else { item.rate_with_margin = flt(item.price_list_rate) + flt(item.margin_rate_or_amount); + item.base_rate_with_margin = flt(item.rate_with_margin) * flt(cur_frm.doc.conversion_rate); } item.rate = flt(item.rate_with_margin , precision("rate", item)); diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js new file mode 100644 index 0000000000..590a828362 --- /dev/null +++ b/erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js @@ -0,0 +1,36 @@ +QUnit.module('Selling'); + +QUnit.test("test quotation with margin", function(assert) { + assert.expect(3); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Quotation', [ + {customer: 'Test Customer 1'}, + {selling_price_list: 'Test-Selling-USD'}, + {currency: 'USD'}, + {items: [ + [ + {'item_code': 'Test Product 3'}, + {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)}, + {'qty': 1}, + {'margin_type': 'Percentage'}, + {'margin_rate_or_amount': 20} + ] + ]} + ]); + }, + () => cur_frm.save(), + () => { + assert.ok(cur_frm.doc.items[0].rate_with_margin == 240, "Margin rate correct"); + assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 240, "Base margin rate correct"); + assert.ok(cur_frm.doc.total == 240, "Amount correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index 3fc56fa2ce..f2e89ca029 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -714,6 +714,7 @@ "label": "Rate With Margin", "length": 0, "no_copy": 0, + "options": "currency", "permlevel": 0, "precision": "2", "print_hide": 1, @@ -789,6 +790,38 @@ "unique": 0, "width": "100px" }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", + "fieldname": "base_rate_with_margin", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rate With Margin (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1583,7 +1616,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2017-09-27 08:31:37.485134", + "modified": "2017-11-03 11:29:59.995384", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js new file mode 100644 index 0000000000..8575b78ce3 --- /dev/null +++ b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js @@ -0,0 +1,38 @@ +QUnit.module('Selling'); + +QUnit.test("test sales order with margin", function(assert) { + assert.expect(3); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Sales Order', [ + {customer:'Test Customer 1'}, + {selling_price_list: 'Test-Selling-USD'}, + {currency: 'USD'}, + {items: [ + [ + {'item_code': 'Test Product 3'}, + {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)}, + {'qty': 1}, + {'margin_type': 'Amount'}, + {'margin_rate_or_amount': 20} + ] + ]}, + ]); + }, + + () => cur_frm.save(), + () => { + // get_rate_details + assert.ok(cur_frm.doc.items[0].rate_with_margin == 220, "Margin rate correct"); + assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 220, "Base margin rate correct"); + assert.ok(cur_frm.doc.total == 220, "Amount correct"); + }, + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + 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 fd7b0f29b3..b772f510bd 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -744,6 +744,7 @@ "label": "Rate With Margin", "length": 0, "no_copy": 0, + "options": "currency", "permlevel": 0, "precision": "", "print_hide": 1, @@ -819,6 +820,38 @@ "unique": 0, "width": "70px" }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", + "fieldname": "base_rate_with_margin", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rate With Margin (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1963,7 +1996,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2017-09-27 08:31:37.129537", + "modified": "2017-11-03 11:33:48.453373", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js b/erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js new file mode 100644 index 0000000000..67c9f38aff --- /dev/null +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js @@ -0,0 +1,37 @@ +QUnit.module('Stock'); + +QUnit.test("test delivery note with margin", function(assert) { + assert.expect(3); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Delivery Note', [ + {customer:'Test Customer 1'}, + {selling_price_list: 'Test-Selling-USD'}, + {currency: 'USD'}, + {items: [ + [ + {'item_code': 'Test Product 3'}, + {'qty': 1}, + {'margin_type': 'Amount'}, + {'margin_rate_or_amount': 10} + ] + ]}, + ]); + }, + + () => cur_frm.save(), + () => { + // get_rate_details + assert.ok(cur_frm.doc.items[0].rate_with_margin == 210, "Margin rate correct"); + assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 210, "Base margin rate correct"); + assert.ok(cur_frm.doc.total == 210, "Amount correct"); + }, + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + 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 4e1ea4059c..72f1dfdb41 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -743,6 +743,7 @@ "label": "Rate With Margin", "length": 0, "no_copy": 0, + "options": "currency", "permlevel": 0, "precision": "2", "print_hide": 1, @@ -818,6 +819,38 @@ "unique": 0, "width": "100px" }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount", + "fieldname": "base_rate_with_margin", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rate With Margin (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "2", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1956,7 +1989,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-09-27 08:31:38.768846", + "modified": "2017-11-03 11:32:04.837794", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", diff --git a/erpnext/stock/doctype/item_price/test_item_price.js b/erpnext/stock/doctype/item_price/test_item_price.js new file mode 100644 index 0000000000..6383fb0518 --- /dev/null +++ b/erpnext/stock/doctype/item_price/test_item_price.js @@ -0,0 +1,22 @@ +QUnit.module('Stock'); + +QUnit.test("test item price", function(assert) { + assert.expect(2); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Item Price', [ + {price_list:'Test-Selling-USD'}, + {item_code: 'Test Product 3'}, + {price_list_rate: 200} + ]); + }, + () => cur_frm.save(), + () => { + assert.ok(cur_frm.doc.item_name == 'Test Product 3', "Item name correct"); + assert.ok(cur_frm.doc.price_list_rate == 200, "Price list rate correct"); + }, + () => frappe.timeout(0.3), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index cbaaf10762..3e40485d74 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -134,3 +134,8 @@ erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js erpnext/projects/doctype/task/tests/test_task_tree.js +erpnext/stock/doctype/item_price/test_item_price.js +erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js +erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js +erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js +erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js