From b09dc46e68356c1c06c63dca9d2e5cc4aa2a10e0 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 23 Dec 2013 15:49:08 +0530 Subject: [PATCH 1/8] [flat discount] first commit --- .../doctype/sales_invoice/sales_invoice.py | 4 +- .../doctype/sales_invoice/sales_invoice.txt | 9 +- .../sales_invoice/test_sales_invoice.py | 94 +++++++++++++------ .../sales_taxes_and_charges.txt | 13 ++- controllers/accounts_controller.py | 27 ++++-- controllers/buying_controller.py | 5 +- controllers/selling_controller.py | 61 ++++++++---- public/js/transaction.js | 24 +++-- selling/sales_common.js | 58 ++++++++++-- 9 files changed, 218 insertions(+), 77 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index bfba30fa1b..d065dedd70 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -556,12 +556,12 @@ class DocType(SellingController): def make_tax_gl_entries(self, gl_entries): for tax in self.doclist.get({"parentfield": "other_charges"}): - if flt(tax.tax_amount): + if flt(tax.tax_amount_after_flat_discount): gl_entries.append( self.get_gl_dict({ "account": tax.account_head, "against": self.doc.debit_to, - "credit": flt(tax.tax_amount), + "credit": flt(tax.tax_amount_after_flat_discount), "remarks": self.doc.remarks, "cost_center": tax.cost_center }) diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 99bfe5cdf0..66cc0d930a 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-11-18 15:16:50", + "modified": "2013-12-19 11:10:11", "modified_by": "Administrator", "owner": "Administrator" }, @@ -362,6 +362,13 @@ "read_only": 1, "reqd": 1 }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "taxes", diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 9b740d1061..bc6d01ce60 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -16,7 +16,7 @@ class TestSalesInvoice(unittest.TestCase): w.submit() return w - def test_double_submission(self): + def atest_double_submission(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -27,7 +27,7 @@ class TestSalesInvoice(unittest.TestCase): w = webnotes.bean(w2) self.assertRaises(DocstatusTransitionError, w.submit) - def test_timestamp_change(self): + def atest_timestamp_change(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -42,9 +42,8 @@ class TestSalesInvoice(unittest.TestCase): time.sleep(1) self.assertRaises(TimestampMismatchError, w2.save) - def test_sales_invoice_calculation_base_currency(self): + def atest_sales_invoice_calculation_base_currency(self): si = webnotes.bean(copy=test_records[2]) - si.run_method("calculate_taxes_and_totals") si.insert() expected_values = { @@ -87,7 +86,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 1627.05) - def test_sales_invoice_calculation_export_currency(self): + def atest_sales_invoice_calculation_export_currency(self): si = webnotes.bean(copy=test_records[2]) si.doc.currency = "USD" si.doc.conversion_rate = 50 @@ -136,8 +135,53 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 32.54) + + def test_sales_invoice_flat_discount(self): + si = webnotes.bean(copy=test_records[3]) + si.doc.flat_discount = 22.98 + si.insert() + + expected_values = { + "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", + "base_ref_rate", "basic_rate", "amount"], + "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 492.44], + "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 738.68], + } + + # check if children are saved + self.assertEquals(len(si.doclist.get({"parentfield": "entries"})), + len(expected_values)-1) + + # check if item values are calculated + for d in si.doclist.get({"parentfield": "entries"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.doc.net_total, 1231.12) + self.assertEquals(si.doc.net_total_export, 1578.3) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "tax_amount_after_flat_discount", "total"], + "_Test Account Excise Duty - _TC": [140, 137.89, 1369.01], + "_Test Account Education Cess - _TC": [2.8, 2.76, 1371.77], + "_Test Account S&H Education Cess - _TC": [1.4, 1.38, 1373.15], + "_Test Account CST - _TC": [27.88, 27.46, 1400.61], + "_Test Account VAT - _TC": [156.25, 153.89, 1554.5], + "_Test Account Customs Duty - _TC": [125, 123.11, 1677.61], + "_Test Account Shipping Charges - _TC": [100, 100, 1777.61], + "_Test Account Discount - _TC": [-180.33, -177.61, 1600] + } + + for d in si.doclist.get({"parentfield": "other_charges"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) - def test_inclusive_rate_validations(self): + self.assertEquals(si.doc.grand_total, 1600) + self.assertEquals(si.doc.grand_total_export, 1600) + + def atest_inclusive_rate_validations(self): si = webnotes.bean(copy=test_records[2]) for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): tax.idx = i+1 @@ -148,16 +192,15 @@ class TestSalesInvoice(unittest.TestCase): si.doclist[i].included_in_print_rate = 1 # tax type "Actual" cannot be inclusive - self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals") + self.assertRaises(webnotes.ValidationError, si.insert) # taxes above included type 'On Previous Row Total' should also be included si.doclist[3].included_in_print_rate = 0 - self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals") + self.assertRaises(webnotes.ValidationError, si.insert) - def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): + def atest_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) - si.run_method("calculate_taxes_and_totals") si.insert() expected_values = { @@ -200,7 +243,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1622.98) self.assertEquals(si.doc.grand_total_export, 1622.98) - def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): + def atest_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) si.doc.currency = "USD" @@ -211,7 +254,6 @@ class TestSalesInvoice(unittest.TestCase): si.doclist[2].adj_rate = 20 si.doclist[9].rate = 5000 - si.run_method("calculate_taxes_and_totals") si.insert() expected_values = { @@ -254,11 +296,11 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 65205.16) self.assertEquals(si.doc.grand_total_export, 1304.1) - def test_outstanding(self): + def atest_outstanding(self): w = self.make() self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total) - def test_payment(self): + def atest_payment(self): webnotes.conn.sql("""delete from `tabGL Entry`""") w = self.make() @@ -277,7 +319,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Sales Invoice", w.doc.name, "outstanding_amount"), 561.8) - def test_time_log_batch(self): + def atest_time_log_batch(self): tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001") tlb.submit() @@ -300,7 +342,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing") - def test_sales_invoice_gl_entry_without_aii(self): + def atest_sales_invoice_gl_entry_without_aii(self): self.clear_stock_account_balance() set_perpetual_inventory(0) si = webnotes.bean(copy=test_records[1]) @@ -333,7 +375,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) - def test_pos_gl_entry_with_aii(self): + def atest_pos_gl_entry_with_aii(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -393,7 +435,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): + def atest_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): self.clear_stock_account_balance() set_perpetual_inventory() webnotes.delete_doc("Account", "_Test Warehouse No Account - _TC") @@ -404,7 +446,6 @@ class TestSalesInvoice(unittest.TestCase): pr = webnotes.bean(copy=pr_test_records[0]) pr.doc.naming_series = "_T-Purchase Receipt-" pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC" - pr.run_method("calculate_taxes_and_totals") pr.insert() pr.submit() @@ -449,7 +490,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) set_perpetual_inventory(0) - def test_sales_invoice_gl_entry_with_aii_no_item_code(self): + def atest_sales_invoice_gl_entry_with_aii_no_item_code(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -477,7 +518,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): + def atest_sales_invoice_gl_entry_with_aii_non_stock_item(self): self.clear_stock_account_balance() set_perpetual_inventory() si_copy = webnotes.copy_doclist(test_records[1]) @@ -509,7 +550,6 @@ class TestSalesInvoice(unittest.TestCase): as pr_test_records pr = webnotes.bean(copy=pr_test_records[0]) pr.doc.naming_series = "_T-Purchase Receipt-" - pr.run_method("calculate_taxes_and_totals") pr.insert() pr.submit() @@ -530,7 +570,7 @@ class TestSalesInvoice(unittest.TestCase): ps = webnotes.bean(copy=pos_setting_test_records[0]) ps.insert() - def test_sales_invoice_with_advance(self): + def atest_sales_invoice_with_advance(self): from accounts.doctype.journal_voucher.test_journal_voucher \ import test_records as jv_test_records @@ -565,7 +605,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(not webnotes.conn.sql("""select name from `tabJournal Voucher Detail` where against_invoice=%s""", si.doc.name)) - def test_recurring_invoice(self): + def atest_recurring_invoice(self): from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date today = now_datetime().date() @@ -705,7 +745,7 @@ class TestSalesInvoice(unittest.TestCase): webnotes.conn.sql("delete from tabBin") webnotes.conn.sql("delete from `tabGL Entry`") - def test_serialized(self): + def atest_serialized(self): from stock.doctype.stock_entry.test_stock_entry import make_serialized_item from stock.doctype.serial_no.serial_no import get_serial_nos @@ -727,7 +767,7 @@ class TestSalesInvoice(unittest.TestCase): return si - def test_serialized_cancel(self): + def atest_serialized_cancel(self): from stock.doctype.serial_no.serial_no import get_serial_nos si = self.test_serialized() si.cancel() @@ -739,7 +779,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(webnotes.conn.get_value("Serial No", serial_nos[0], "delivery_document_no")) - def test_serialize_status(self): + def atest_serialize_status(self): from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos from stock.doctype.stock_entry.test_stock_entry import make_serialized_item diff --git a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt index b006c1d85c..3b31623e41 100644 --- a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt +++ b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-24 11:39:32", "docstatus": 0, - "modified": "2013-12-17 12:38:08", + "modified": "2013-12-20 12:31:08", "modified_by": "Administrator", "owner": "Administrator" }, @@ -131,12 +131,21 @@ "options": "Company:company:default_currency", "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "tax_amount_after_flat_discount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Tax Amount After Flat Discount", + "options": "Company:company:default_currency", + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "item_wise_tax_detail", "fieldtype": "Small Text", "hidden": 1, - "label": "Item Wise Tax Detail ", + "label": "Item Wise Tax Detail", "oldfieldname": "item_wise_tax_detail", "oldfieldtype": "Small Text", "read_only": 1 diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 5388ee120a..c76258ac27 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -16,7 +16,10 @@ class AccountsController(TransactionBase): self.set_missing_values(for_validate=True) self.validate_date_with_fiscal_year() if self.meta.get_field("currency"): + self.flat_discount_applied = False self.calculate_taxes_and_totals() + if hasattr(self, "apply_flat_discount"): + self.apply_flat_discount() self.validate_value("grand_total", ">=", 0) self.set_total_in_words() @@ -141,7 +144,7 @@ class AccountsController(TransactionBase): else: validate_conversion_rate(self.doc.currency, self.doc.conversion_rate, self.meta.get_label("conversion_rate"), self.doc.company) - + self.doc.conversion_rate = flt(self.doc.conversion_rate) self.item_doclist = self.doclist.get({"parentfield": self.fname}) self.tax_doclist = self.doclist.get({"parentfield": self.other_fname}) @@ -163,11 +166,16 @@ class AccountsController(TransactionBase): def initialize_taxes(self): for tax in self.tax_doclist: tax.item_wise_tax_detail = {} - for fieldname in ["tax_amount", "total", - "tax_amount_for_current_item", "grand_total_for_current_item", - "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]: - tax.fields[fieldname] = 0.0 - + tax_fields = ["total", "tax_amount_after_flat_discount", + "tax_amount_for_current_item", "grand_total_for_current_item", + "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] + + if not self.flat_discount_applied: + tax_fields.append("tax_amount") + + for fieldname in tax_fields: + tax.fields[fieldname] = 0.0 + self.validate_on_previous_row(tax) self.validate_inclusive_tax(tax) self.round_floats_in(tax) @@ -247,7 +255,10 @@ class AccountsController(TransactionBase): tax.tax_amount_for_current_item = current_tax_amount # accumulate tax amount into tax.tax_amount - tax.tax_amount += current_tax_amount + if not self.flat_discount_applied: + tax.tax_amount += current_tax_amount + + tax.tax_amount_after_flat_discount += current_tax_amount if tax.category: # if just for valuation, do not add the tax amount in total @@ -270,7 +281,7 @@ class AccountsController(TransactionBase): # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item - + def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) current_tax_amount = 0.0 diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index b52d51cf31..5e265e720f 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import webnotes from webnotes import _, msgprint from webnotes.utils import flt, _round - from buying.utils import get_item_details from setup.utils import get_company_currency @@ -162,6 +161,10 @@ class BuyingController(StockController): if not self.meta.get_field("item_tax_amount", parentfield=self.fname): for item in self.item_doclist: del item.fields["item_tax_amount"] + + if not self.meta.get_field("tax_amount_after_flat_discount", parentfield=self.other_fname): + for tax in self.tax_doclist: + del tax.fields["tax_amount_after_flat_discount"] def set_item_tax_amount(self, item, tax, current_tax_amount): """ diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 67c1462662..ede6ca9242 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -121,7 +121,7 @@ class SellingController(StockController): cumulated_tax_fraction += tax.tax_fraction_for_current_item - if cumulated_tax_fraction: + if cumulated_tax_fraction and not self.flat_discount_applied: item.amount = flt((item.export_amount * self.doc.conversion_rate) / (1 + cumulated_tax_fraction), self.precision("amount", item)) @@ -158,22 +158,23 @@ class SellingController(StockController): return current_tax_fraction def calculate_item_values(self): - for item in self.item_doclist: - self.round_floats_in(item) - - if item.adj_rate == 100: - item.export_rate = 0 - elif not item.export_rate: - item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)), - self.precision("export_rate", item)) - - item.export_amount = flt(item.export_rate * item.qty, - self.precision("export_amount", item)) + if not self.flat_discount_applied: + for item in self.item_doclist: + self.round_floats_in(item) + + if item.adj_rate == 100: + item.export_rate = 0 + elif not item.export_rate: + item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)), + self.precision("export_rate", item)) + + item.export_amount = flt(item.export_rate * item.qty, + self.precision("export_amount", item)) + + self._set_in_company_currency(item, "ref_rate", "base_ref_rate") + self._set_in_company_currency(item, "export_rate", "basic_rate") + self._set_in_company_currency(item, "export_amount", "amount") - self._set_in_company_currency(item, "ref_rate", "base_ref_rate") - self._set_in_company_currency(item, "export_rate", "basic_rate") - self._set_in_company_currency(item, "export_amount", "amount") - def calculate_net_total(self): self.doc.net_total = self.doc.net_total_export = 0.0 @@ -184,6 +185,7 @@ class SellingController(StockController): self.round_floats_in(self.doc, ["net_total", "net_total_export"]) def calculate_totals(self): + self.total_tax_excluding_actual = 0.0 self.doc.grand_total = flt(self.tax_doclist and \ self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total")) self.doc.grand_total_export = flt(self.doc.grand_total / self.doc.conversion_rate, @@ -191,12 +193,33 @@ class SellingController(StockController): self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total, self.precision("other_charges_total")) - self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export, - self.precision("other_charges_total_export")) + self.doc.other_charges_total_export = flt(self.doc.grand_total_export - + self.doc.net_total_export + flt(self.doc.flat_discount), self.precision("other_charges_total_export")) self.doc.rounded_total = _round(self.doc.grand_total) self.doc.rounded_total_export = _round(self.doc.grand_total_export) - + + if self.doc.flat_discount: + # calculate total tax for flat discount excluding actual + for tax in self.tax_doclist: + if tax.charge_type != "Actual": + self.total_tax_excluding_actual += tax.tax_amount + + self.total_amount_for_flat_discount = flt(self.doc.net_total + + self.total_tax_excluding_actual, self.precision("grand_total")) + + def apply_flat_discount(self): + distributed_amount = 0.0 + + if self.doc.flat_discount and self.total_amount_for_flat_discount: + # calculate item amount after flat discount + for item in self.item_doclist: + distributed_amount = self.doc.flat_discount * item.amount / self.total_amount_for_flat_discount + item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) + + self.flat_discount_applied = True + self.calculate_taxes_and_totals() + def calculate_outstanding_amount(self): # NOTE: # write_off_amount is only for POS Invoice diff --git a/public/js/transaction.js b/public/js/transaction.js index 4c4a810ed2..f06fc6b735 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -146,7 +146,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, validate: function() { + this.flat_discount_applied = false; this.calculate_taxes_and_totals(); + this.apply_flat_discount && this.apply_flat_discount(); }, set_default_values: function() { @@ -528,12 +530,18 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ initialize_taxes: function() { var me = this; + $.each(this.frm.tax_doclist, function(i, tax) { tax.item_wise_tax_detail = {}; - $.each(["tax_amount", "total", - "tax_amount_for_current_item", "grand_total_for_current_item", - "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"], - function(i, fieldname) { tax[fieldname] = 0.0 }); + tax_fields = ["total", "tax_amount_for_current_item", "grand_total_for_current_item", + "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] + + if (me.flat_discount_applied) + tax_fields.push("tax_amount_after_flat_discount"); + else + tax_fields.push("tax_amount"); + + $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); me.validate_on_previous_row(tax); me.validate_inclusive_tax(tax); @@ -567,7 +575,10 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ tax.tax_amount_for_current_item = current_tax_amount; // accumulate tax amount into tax.tax_amount - tax.tax_amount += current_tax_amount; + if (me.flat_discount_applied) + tax.tax_amount_after_flat_discount += current_tax_amount; + else + tax.tax_amount += current_tax_amount; // for buying if(tax.category) { @@ -617,9 +628,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ } else if(tax.charge_type == "On Previous Row Total") { current_tax_amount = (tax_rate / 100.0) * this.frm.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item; - } - + current_tax_amount = flt(current_tax_amount, precision("tax_amount", tax)); // store tax breakup for each item diff --git a/selling/sales_common.js b/selling/sales_common.js index dddc2b568d..d8fdb706b0 100644 --- a/selling/sales_common.js +++ b/selling/sales_common.js @@ -225,6 +225,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.calculate_taxes_and_totals(); }, + + flat_discount: function() { + this.flat_discount_applied = false; + this.calculate_taxes_and_totals(); + this.apply_flat_discount(); + }, commission_rate: function() { this.calculate_commission(); @@ -310,15 +316,17 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ calculate_item_values: function() { var me = this; - $.each(this.frm.item_doclist, function(i, item) { - wn.model.round_floats_in(item); - item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item)); - - me._set_in_company_currency(item, "ref_rate", "base_ref_rate"); - me._set_in_company_currency(item, "export_rate", "basic_rate"); - me._set_in_company_currency(item, "export_amount", "amount"); - }); + if (!this.flat_discount_applied) { + $.each(this.frm.item_doclist, function(i, item) { + wn.model.round_floats_in(item); + item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item)); + + me._set_in_company_currency(item, "ref_rate", "base_ref_rate"); + me._set_in_company_currency(item, "export_rate", "basic_rate"); + me._set_in_company_currency(item, "export_amount", "amount"); + }); + } }, determine_exclusive_rate: function() { @@ -341,7 +349,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ cumulated_tax_fraction += tax.tax_fraction_for_current_item; }); - if(cumulated_tax_fraction) { + if(cumulated_tax_fraction && !me.flat_discount_applied) { item.amount = flt( (item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), precision("amount", item)); @@ -396,7 +404,10 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ }, calculate_totals: function() { + var me = this; var tax_count = this.frm.tax_doclist.length; + this.total_tax_excluding_actual = 0.0; + this.frm.doc.grand_total = flt( tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total, precision("grand_total")); @@ -406,11 +417,38 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("other_charges_total")); this.frm.doc.other_charges_total_export = flt( - this.frm.doc.grand_total_export - this.frm.doc.net_total_export, + this.frm.doc.grand_total_export - this.frm.doc.net_total_export + this.frm.doc.flat_discount, precision("other_charges_total_export")); this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total); this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export); + + // calculate total amount for flat discount + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type != "Actual") { + me.total_tax_excluding_actual += flt(tax.tax_amount, precision("tax_amount", tax)); + } + }); + + this.total_amount_for_flat_discount = flt(this.frm.doc.net_total + + this.total_tax_excluding_actual, precision("grand_total")); + }, + + apply_flat_discount: function() { + var me = this; + var distributed_amount = 0.0; + + if (this.frm.doc.flat_discount && this.total_amount_for_flat_discount) { + // calculate item amount after flat discount + $.each(this.frm.item_doclist, function(i, item) { + distributed_amount = flt(me.frm.doc.flat_discount * item.amount / me.total_amount_for_flat_discount, + precision("amount", item)); + item.amount -= distributed_amount; + }); + + this.flat_discount_applied = true; + this.calculate_taxes_and_totals(); + } }, calculate_outstanding_amount: function() { From 63aa5fd67351e3478819d316f89f44aa0a4e73f4 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 24 Dec 2013 20:30:03 +0530 Subject: [PATCH 2/8] [flat discount] implemented flat discount on server side --- .../sales_invoice/test_sales_invoice.py | 86 +++++++++++-------- controllers/accounts_controller.py | 50 +++++++---- controllers/selling_controller.py | 42 +++++---- 3 files changed, 108 insertions(+), 70 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index bc6d01ce60..46a3f26d48 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -16,7 +16,7 @@ class TestSalesInvoice(unittest.TestCase): w.submit() return w - def atest_double_submission(self): + def test_double_submission(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -27,7 +27,7 @@ class TestSalesInvoice(unittest.TestCase): w = webnotes.bean(w2) self.assertRaises(DocstatusTransitionError, w.submit) - def atest_timestamp_change(self): + def test_timestamp_change(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -42,7 +42,7 @@ class TestSalesInvoice(unittest.TestCase): time.sleep(1) self.assertRaises(TimestampMismatchError, w2.save) - def atest_sales_invoice_calculation_base_currency(self): + def test_sales_invoice_calculation_base_currency(self): si = webnotes.bean(copy=test_records[2]) si.insert() @@ -86,7 +86,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 1627.05) - def atest_sales_invoice_calculation_export_currency(self): + def test_sales_invoice_calculation_export_currency(self): si = webnotes.bean(copy=test_records[2]) si.doc.currency = "USD" si.doc.conversion_rate = 50 @@ -138,14 +138,25 @@ class TestSalesInvoice(unittest.TestCase): def test_sales_invoice_flat_discount(self): si = webnotes.bean(copy=test_records[3]) - si.doc.flat_discount = 22.98 + si.doc.flat_discount = 104.95 + si.doclist.append({ + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account Service Tax - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Service Tax", + "rate": 10, + "row_id": 8, + "idx": 9 + }) si.insert() expected_values = { "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", "base_ref_rate", "basic_rate", "amount"], - "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 492.44], - "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 738.68], + "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 465.37], + "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 698.08], } # check if children are saved @@ -158,30 +169,31 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) # check net total - self.assertEquals(si.doc.net_total, 1231.12) + self.assertEquals(si.doc.net_total, 1163.45) self.assertEquals(si.doc.net_total_export, 1578.3) # check tax calculation expected_values = { "keys": ["tax_amount", "tax_amount_after_flat_discount", "total"], - "_Test Account Excise Duty - _TC": [140, 137.89, 1369.01], - "_Test Account Education Cess - _TC": [2.8, 2.76, 1371.77], - "_Test Account S&H Education Cess - _TC": [1.4, 1.38, 1373.15], - "_Test Account CST - _TC": [27.88, 27.46, 1400.61], - "_Test Account VAT - _TC": [156.25, 153.89, 1554.5], - "_Test Account Customs Duty - _TC": [125, 123.11, 1677.61], - "_Test Account Shipping Charges - _TC": [100, 100, 1777.61], - "_Test Account Discount - _TC": [-180.33, -177.61, 1600] + "_Test Account Excise Duty - _TC": [140, 130.31, 1293.76], + "_Test Account Education Cess - _TC": [2.8, 2.61, 1296.37], + "_Test Account S&H Education Cess - _TC": [1.4, 1.31, 1297.68], + "_Test Account CST - _TC": [27.88, 25.96, 1323.64], + "_Test Account VAT - _TC": [156.25, 145.43, 1469.07], + "_Test Account Customs Duty - _TC": [125, 116.35, 1585.42], + "_Test Account Shipping Charges - _TC": [100, 100, 1685.42], + "_Test Account Discount - _TC": [-180.33, -168.54, 1516.88], + "_Test Account Service Tax - _TC": [-18.03, -16.88, 1500] } for d in si.doclist.get({"parentfield": "other_charges"}): for i, k in enumerate(expected_values["keys"]): - self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) - self.assertEquals(si.doc.grand_total, 1600) - self.assertEquals(si.doc.grand_total_export, 1600) + self.assertEquals(si.doc.grand_total, 1500) + self.assertEquals(si.doc.grand_total_export, 1500) - def atest_inclusive_rate_validations(self): + def test_inclusive_rate_validations(self): si = webnotes.bean(copy=test_records[2]) for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): tax.idx = i+1 @@ -198,7 +210,7 @@ class TestSalesInvoice(unittest.TestCase): si.doclist[3].included_in_print_rate = 0 self.assertRaises(webnotes.ValidationError, si.insert) - def atest_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): + def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) si.insert() @@ -238,12 +250,12 @@ class TestSalesInvoice(unittest.TestCase): for d in si.doclist.get({"parentfield": "other_charges"}): for i, k in enumerate(expected_values["keys"]): - self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) self.assertEquals(si.doc.grand_total, 1622.98) self.assertEquals(si.doc.grand_total_export, 1622.98) - def atest_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): + def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) si.doc.currency = "USD" @@ -291,16 +303,16 @@ class TestSalesInvoice(unittest.TestCase): for d in si.doclist.get({"parentfield": "other_charges"}): for i, k in enumerate(expected_values["keys"]): - self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) self.assertEquals(si.doc.grand_total, 65205.16) self.assertEquals(si.doc.grand_total_export, 1304.1) - def atest_outstanding(self): + def test_outstanding(self): w = self.make() self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total) - def atest_payment(self): + def test_payment(self): webnotes.conn.sql("""delete from `tabGL Entry`""") w = self.make() @@ -319,7 +331,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Sales Invoice", w.doc.name, "outstanding_amount"), 561.8) - def atest_time_log_batch(self): + def test_time_log_batch(self): tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001") tlb.submit() @@ -342,7 +354,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing") - def atest_sales_invoice_gl_entry_without_aii(self): + def test_sales_invoice_gl_entry_without_aii(self): self.clear_stock_account_balance() set_perpetual_inventory(0) si = webnotes.bean(copy=test_records[1]) @@ -375,7 +387,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) - def atest_pos_gl_entry_with_aii(self): + def test_pos_gl_entry_with_aii(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -435,7 +447,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def atest_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): + def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): self.clear_stock_account_balance() set_perpetual_inventory() webnotes.delete_doc("Account", "_Test Warehouse No Account - _TC") @@ -490,7 +502,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) set_perpetual_inventory(0) - def atest_sales_invoice_gl_entry_with_aii_no_item_code(self): + def test_sales_invoice_gl_entry_with_aii_no_item_code(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -518,7 +530,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def atest_sales_invoice_gl_entry_with_aii_non_stock_item(self): + def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): self.clear_stock_account_balance() set_perpetual_inventory() si_copy = webnotes.copy_doclist(test_records[1]) @@ -570,7 +582,7 @@ class TestSalesInvoice(unittest.TestCase): ps = webnotes.bean(copy=pos_setting_test_records[0]) ps.insert() - def atest_sales_invoice_with_advance(self): + def test_sales_invoice_with_advance(self): from accounts.doctype.journal_voucher.test_journal_voucher \ import test_records as jv_test_records @@ -605,7 +617,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(not webnotes.conn.sql("""select name from `tabJournal Voucher Detail` where against_invoice=%s""", si.doc.name)) - def atest_recurring_invoice(self): + def test_recurring_invoice(self): from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date today = now_datetime().date() @@ -745,7 +757,7 @@ class TestSalesInvoice(unittest.TestCase): webnotes.conn.sql("delete from tabBin") webnotes.conn.sql("delete from `tabGL Entry`") - def atest_serialized(self): + def test_serialized(self): from stock.doctype.stock_entry.test_stock_entry import make_serialized_item from stock.doctype.serial_no.serial_no import get_serial_nos @@ -767,7 +779,7 @@ class TestSalesInvoice(unittest.TestCase): return si - def atest_serialized_cancel(self): + def test_serialized_cancel(self): from stock.doctype.serial_no.serial_no import get_serial_nos si = self.test_serialized() si.cancel() @@ -779,7 +791,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(webnotes.conn.get_value("Serial No", serial_nos[0], "delivery_document_no")) - def atest_serialize_status(self): + def test_serialize_status(self): from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos from stock.doctype.stock_entry.test_stock_entry import make_serialized_item diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index c76258ac27..41d4859357 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -148,6 +148,10 @@ class AccountsController(TransactionBase): self.doc.conversion_rate = flt(self.doc.conversion_rate) self.item_doclist = self.doclist.get({"parentfield": self.fname}) self.tax_doclist = self.doclist.get({"parentfield": self.other_fname}) + + # for buying + if not hasattr(self, "flat_discount_applied"): + self.flat_discount_applied = False self.calculate_item_values() self.initialize_taxes() @@ -232,24 +236,26 @@ class AccountsController(TransactionBase): _on_previous_row_error("1 - %d" % (tax.row_id,)) def calculate_taxes(self): - for item in self.item_doclist: + # maintain actual tax rate based on idx + actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist + if tax.charge_type == "Actual"]) + + for n, item in enumerate(self.item_doclist): item_tax_map = self._load_item_tax_rate(item.item_tax_rate) for i, tax in enumerate(self.tax_doclist): # tax_amount represents the amount of tax for the current step current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map) + + # Adjust divisional loss to the last item + if tax.charge_type == "Actual": + actual_tax_dict[tax.idx] -= current_tax_amount; + if n == len(self.item_doclist) - 1: + current_tax_amount += actual_tax_dict[tax.idx] if hasattr(self, "set_item_tax_amount"): self.set_item_tax_amount(item, tax, current_tax_amount) - # case when net total is 0 but there is an actual type charge - # in this case add the actual amount to tax.tax_amount - # and tax.grand_total_for_current_item for the first such iteration - if tax.charge_type=="Actual" and \ - not (current_tax_amount or self.doc.net_total or tax.tax_amount): - zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax)) - current_tax_amount += zero_net_total_adjustment - # store tax_amount for current item as it will be used for # charge type = 'On Previous Row Amount' tax.tax_amount_for_current_item = current_tax_amount @@ -271,17 +277,31 @@ class AccountsController(TransactionBase): # note: grand_total_for_current_item contains the contribution of # item's amount, previously applied tax and the current tax on that item if i==0: - tax.grand_total_for_current_item = flt(item.amount + - current_tax_amount, self.precision("total", tax)) - + tax.grand_total_for_current_item = flt(item.amount + current_tax_amount, + self.precision("total", tax)) else: tax.grand_total_for_current_item = \ - flt(self.tax_doclist[i-1].grand_total_for_current_item + + flt(self.tax_doclist[i-1].grand_total_for_current_item + current_tax_amount, self.precision("total", tax)) + # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item + # set precision in the last item iteration + if n == len(self.item_doclist) - 1: + tax.total = flt(tax.total, self.precision("total", tax)) + tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + self.precision("tax_amount", tax)) + + # adjust discount loss in last tax iteration + if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied: + flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + + flat_discount_loss, self.precision("tax_amount", tax)) + tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) + def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) current_tax_amount = 0.0 @@ -300,9 +320,9 @@ class AccountsController(TransactionBase): elif tax.charge_type == "On Previous Row Total": current_tax_amount = (tax_rate / 100.0) * \ self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item - + current_tax_amount = flt(current_tax_amount, self.precision("tax_amount", tax)) - + # store tax breakup for each item key = item.item_code or item.item_name if tax.item_wise_tax_detail.get(key): diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index ede6ca9242..2571c3c83e 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -185,7 +185,6 @@ class SellingController(StockController): self.round_floats_in(self.doc, ["net_total", "net_total_export"]) def calculate_totals(self): - self.total_tax_excluding_actual = 0.0 self.doc.grand_total = flt(self.tax_doclist and \ self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total")) self.doc.grand_total_export = flt(self.doc.grand_total / self.doc.conversion_rate, @@ -199,26 +198,33 @@ class SellingController(StockController): self.doc.rounded_total = _round(self.doc.grand_total) self.doc.rounded_total_export = _round(self.doc.grand_total_export) - if self.doc.flat_discount: - # calculate total tax for flat discount excluding actual - for tax in self.tax_doclist: - if tax.charge_type != "Actual": - self.total_tax_excluding_actual += tax.tax_amount - - self.total_amount_for_flat_discount = flt(self.doc.net_total + - self.total_tax_excluding_actual, self.precision("grand_total")) - def apply_flat_discount(self): - distributed_amount = 0.0 + if self.doc.flat_discount: + total_amount_for_flat_discount = self.get_flat_discountable_amount() - if self.doc.flat_discount and self.total_amount_for_flat_discount: - # calculate item amount after flat discount - for item in self.item_doclist: - distributed_amount = self.doc.flat_discount * item.amount / self.total_amount_for_flat_discount - item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) + if total_amount_for_flat_discount: + # calculate item amount after flat discount + for item in self.item_doclist: + distributed_amount = self.doc.flat_discount * item.amount / total_amount_for_flat_discount + item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) - self.flat_discount_applied = True - self.calculate_taxes_and_totals() + self.flat_discount_applied = True + self.calculate_taxes_and_totals() + + def get_flat_discountable_amount(self): + actual_taxes_dict = {} + + for tax in self.tax_doclist: + if tax.charge_type == "Actual": + actual_taxes_dict.setdefault(tax.idx, tax.tax_amount) + elif tax.row_id in actual_taxes_dict: + actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * \ + flt(tax.rate) / 100 + actual_taxes_dict.setdefault(tax.idx, actual_tax_amount) + + total_amount_for_flat_discount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()), + self.precision("grand_total")) + return total_amount_for_flat_discount def calculate_outstanding_amount(self): # NOTE: From c53dbc7cdfec972872abd7febe60220acf75f0c3 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 25 Dec 2013 19:46:20 +0530 Subject: [PATCH 3/8] [flat discount] implemented flat discount on client side --- .../sales_invoice/test_sales_invoice.py | 53 ++++++++++++++- .../purchase_common/purchase_common.js | 8 +++ controllers/accounts_controller.py | 31 +++++---- public/js/transaction.js | 67 +++++++++++++------ selling/sales_common.js | 53 +++++++++------ stock/doctype/item/item.js | 3 +- stock/doctype/item/item.py | 4 +- 7 files changed, 162 insertions(+), 57 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 46a3f26d48..86308905b5 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -192,7 +192,57 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1500) self.assertEquals(si.doc.grand_total_export, 1500) - + + def test_flat_discount_gl_entry(self): + si = webnotes.bean(copy=test_records[3]) + si.doc.flat_discount = 104.95 + si.doclist.append({ + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account Service Tax - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Service Tax", + "rate": 10, + "row_id": 8, + "idx": 9 + }) + si.insert() + si.submit() + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc""", si.doc.name, as_dict=1) + + self.assertTrue(gl_entries) + + expected_values = sorted([ + [si.doc.debit_to, 1500, 0.0], + [test_records[3][1]["income_account"], 0.0, 1163.45], + [test_records[3][3]["account_head"], 0.0, 130.31], + [test_records[3][4]["account_head"], 0.0, 2.61], + [test_records[3][5]["account_head"], 0.0, 1.31], + [test_records[3][6]["account_head"], 0.0, 25.96], + [test_records[3][7]["account_head"], 0.0, 145.43], + [test_records[3][8]["account_head"], 0.0, 116.35], + [test_records[3][9]["account_head"], 0.0, 100], + [test_records[3][10]["account_head"], 168.54, 0.0], + ["_Test Account Service Tax - _TC", 16.88, 0.0], + ]) + + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + # cancel + si.cancel() + + gle = webnotes.conn.sql("""select * from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name) + + self.assertFalse(gle) + def test_inclusive_rate_validations(self): si = webnotes.bean(copy=test_records[2]) for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): @@ -418,7 +468,6 @@ class TestSalesInvoice(unittest.TestCase): from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s order by account asc, debit asc""", si.doc.name, as_dict=1) self.assertTrue(gl_entries) - # print gl_entries stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"}) diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 9661f6edaf..92d127b267 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -360,6 +360,14 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }); } } + + if(this.frm.tax_doclist.length) { + if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_flat_discount", this.frm.doctype)) { + $.each(this.frm.tax_doclist, function(i, tax) { + delete tax["tax_amount_after_flat_discount"]; + }); + } + } }, calculate_outstanding_amount: function() { diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 41d4859357..bcb50da44c 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -227,11 +227,11 @@ class AccountsController(TransactionBase): "charge_type": tax.charge_type, }, raise_exception=True) elif tax.charge_type == "On Previous Row Amount" and \ - not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate): + not cint(self.tax_doclist[cint(tax.row_id) - 1].included_in_print_rate): # referred row should also be inclusive _on_previous_row_error(tax.row_id) elif tax.charge_type == "On Previous Row Total" and \ - not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:tax.row_id - 1]]): + not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:cint(tax.row_id) - 1]]): # all rows about the reffered tax should be inclusive _on_previous_row_error("1 - %d" % (tax.row_id,)) @@ -249,7 +249,7 @@ class AccountsController(TransactionBase): # Adjust divisional loss to the last item if tax.charge_type == "Actual": - actual_tax_dict[tax.idx] -= current_tax_amount; + actual_tax_dict[tax.idx] -= current_tax_amount if n == len(self.item_doclist) - 1: current_tax_amount += actual_tax_dict[tax.idx] @@ -283,24 +283,29 @@ class AccountsController(TransactionBase): tax.grand_total_for_current_item = \ flt(self.tax_doclist[i-1].grand_total_for_current_item + current_tax_amount, self.precision("total", tax)) - # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item # set precision in the last item iteration if n == len(self.item_doclist) - 1: - tax.total = flt(tax.total, self.precision("total", tax)) - tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, - self.precision("tax_amount", tax)) + self.round_off_totals(tax) - # adjust discount loss in last tax iteration + # adjust flat discount loss in last tax iteration if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied: - flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + - flat_discount_loss, self.precision("tax_amount", tax)) - tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) + self.adjust_flat_discount_loss(tax) + + def round_off_totals(self, tax): + tax.total = flt(tax.total, self.precision("total", tax)) + tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + self.precision("tax_amount", tax)) + + def adjust_flat_discount_loss(self, tax): + flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + + flat_discount_loss, self.precision("tax_amount", tax)) + tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) diff --git a/public/js/transaction.js b/public/js/transaction.js index f06fc6b735..542a1c1411 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -516,7 +516,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ this.validate_conversion_rate(); this.frm.item_doclist = this.get_item_doclist(); this.frm.tax_doclist = this.get_tax_doclist(); - + this.calculate_item_values(); this.initialize_taxes(); this.determine_exclusive_rate && this.determine_exclusive_rate(); @@ -533,12 +533,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ $.each(this.frm.tax_doclist, function(i, tax) { tax.item_wise_tax_detail = {}; - tax_fields = ["total", "tax_amount_for_current_item", "grand_total_for_current_item", + tax_fields = ["total", "tax_amount_after_flat_discount", + "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] - if (me.flat_discount_applied) - tax_fields.push("tax_amount_after_flat_discount"); - else + if (!me.flat_discount_applied) tax_fields.push("tax_amount"); $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); @@ -551,34 +550,41 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ calculate_taxes: function() { var me = this; + var actual_tax_dict = {}; + // maintain actual tax rate based on idx + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] = flt(tax.rate); + } + }); + $.each(this.frm.item_doclist, function(n, item) { var item_tax_map = me._load_item_tax_rate(item.item_tax_rate); - + $.each(me.frm.tax_doclist, function(i, tax) { // tax_amount represents the amount of tax for the current step var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map); - me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount); - - // case when net total is 0 but there is an actual type charge - // in this case add the actual amount to tax.tax_amount - // and tax.grand_total_for_current_item for the first such iteration - if(tax.charge_type == "Actual" && - !(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) { - var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax)); - current_tax_amount += zero_net_total_adjustment; + // Adjust divisional loss to the last item + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] -= current_tax_amount; + if (n == me.frm.item_doclist.length - 1) { + current_tax_amount += actual_tax_dict[tax.idx] } - + } + + me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount); + // store tax_amount for current item as it will be used for // charge type = 'On Previous Row Amount' tax.tax_amount_for_current_item = current_tax_amount; // accumulate tax amount into tax.tax_amount - if (me.flat_discount_applied) - tax.tax_amount_after_flat_discount += current_tax_amount; - else + if (!me.flat_discount_applied) tax.tax_amount += current_tax_amount; + + tax.tax_amount_after_flat_discount += current_tax_amount; // for buying if(tax.category) { @@ -603,9 +609,32 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ // in tax.total, accumulate grand total for each item tax.total += tax.grand_total_for_current_item; + + // set precision in the last item iteration + if (n == me.frm.item_doclist.length - 1) { + me.round_off_totals(tax); + + // adjust flat discount loss in last tax iteration + if ((i == me.frm.tax_doclist.length - 1) && me.flat_discount_applied) + me.adjust_flat_discount_loss(tax); + } }); }); }, + + round_off_totals: function(tax) { + tax.total = flt(tax.total, precision("total", tax)); + tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)); + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + precision("tax_amount", tax)); + }, + + adjust_flat_discount_loss: function(tax) { + var flat_discount_loss = this.frm.doc.grand_total - this.frm.doc.flat_discount - tax.total; + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + + flat_discount_loss, precision("tax_amount", tax)); + tax.total = flt(tax.total + flat_discount_loss, precision("total", tax)); + }, get_current_tax_amount: function(item, tax, item_tax_map) { var tax_rate = this._get_tax_rate(tax, item_tax_map); diff --git a/selling/sales_common.js b/selling/sales_common.js index d8fdb706b0..91ec01dfcf 100644 --- a/selling/sales_common.js +++ b/selling/sales_common.js @@ -353,7 +353,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ item.amount = flt( (item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), precision("amount", item)); - + item.basic_rate = flt(item.amount / item.qty, precision("basic_rate", item)); if(item.adj_rate == 100) { @@ -393,20 +393,19 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ calculate_net_total: function() { var me = this; - this.frm.doc.net_total = this.frm.doc.net_total_export = 0.0; + $.each(this.frm.item_doclist, function(i, item) { me.frm.doc.net_total += item.amount; me.frm.doc.net_total_export += item.export_amount; }); - + wn.model.round_floats_in(this.frm.doc, ["net_total", "net_total_export"]); }, calculate_totals: function() { var me = this; var tax_count = this.frm.tax_doclist.length; - this.total_tax_excluding_actual = 0.0; this.frm.doc.grand_total = flt( tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total, @@ -416,40 +415,54 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("other_charges_total")); - this.frm.doc.other_charges_total_export = flt( - this.frm.doc.grand_total_export - this.frm.doc.net_total_export + this.frm.doc.flat_discount, + this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export - + this.frm.doc.net_total_export + this.frm.doc.flat_discount, precision("other_charges_total_export")); this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total); this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export); - - // calculate total amount for flat discount - $.each(this.frm.tax_doclist, function(i, tax) { - if (tax.charge_type != "Actual") { - me.total_tax_excluding_actual += flt(tax.tax_amount, precision("tax_amount", tax)); - } - }); - - this.total_amount_for_flat_discount = flt(this.frm.doc.net_total + - this.total_tax_excluding_actual, precision("grand_total")); }, apply_flat_discount: function() { var me = this; var distributed_amount = 0.0; - if (this.frm.doc.flat_discount && this.total_amount_for_flat_discount) { + if (this.frm.doc.flat_discount) { + var total_amount_for_flat_discount = this.get_flat_discountable_amount(); // calculate item amount after flat discount $.each(this.frm.item_doclist, function(i, item) { - distributed_amount = flt(me.frm.doc.flat_discount * item.amount / me.total_amount_for_flat_discount, - precision("amount", item)); - item.amount -= distributed_amount; + distributed_amount = me.frm.doc.flat_discount * item.amount / total_amount_for_flat_discount; + item.amount = flt(item.amount - distributed_amount, precision("amount", item)); }); this.flat_discount_applied = true; this.calculate_taxes_and_totals(); } }, + + get_flat_discountable_amount: function() { + var me = this; + var total_actual_tax = 0.0; + var actual_taxes_dict = {}; + + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type == "Actual") + actual_taxes_dict[tax.idx] = tax.tax_amount; + else if (actual_taxes_dict[tax.row_id] !== null) { + actual_tax_amount = flt(actual_taxes_dict[tax.row_id]) * flt(tax.rate) / 100; + actual_taxes_dict[tax.idx] = actual_tax_amount; + } + }); + + $.each(actual_taxes_dict, function(key, value) { + if (value) + total_actual_tax += value; + }); + + total_amount_for_flat_discount = flt(this.frm.doc.grand_total - total_actual_tax, + precision("grand_total")); + return total_amount_for_flat_discount; + }, calculate_outstanding_amount: function() { // NOTE: diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index c9aa75e7b7..6a1a7ef1c2 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -97,7 +97,8 @@ cur_frm.fields_dict['default_sales_cost_center'].get_query = function(doc) { cur_frm.fields_dict['item_tax'].grid.get_field("tax_type").get_query = function(doc, cdt, cdn) { return{ filters:[ - ['Account', 'account_type', 'in', 'Tax, Chargeable'], + ['Account', 'account_type', 'in', + 'Tax, Chargeable, Income Account, Expense Account'], ['Account', 'docstatus', '!=', 2] ] } diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index b5884b4111..0c4d5dd596 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -154,8 +154,8 @@ class DocType(DocListController, WebsiteGenerator): if d.tax_type: account_type = webnotes.conn.get_value("Account", d.tax_type, "account_type") - if account_type not in ['Tax', 'Chargeable']: - msgprint("'%s' is not Tax / Chargeable Account" % d.tax_type, raise_exception=1) + if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']: + msgprint("'%s' is not Tax / Chargeable / Income / Expense Account" % d.tax_type, raise_exception=1) else: if d.tax_type in check_list: msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1) From aebb844da974fac347bb1b76f8bf393fe7d70910 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 26 Dec 2013 18:05:41 +0530 Subject: [PATCH 4/8] [flat discount] added flat discount in print format and all selling doctypes --- .../Print Format/POS Invoice/POS Invoice.txt | 4 +-- .../Sales Invoice Classic.txt | 4 +-- .../Sales Invoice Modern.txt | 4 +-- .../Sales Invoice Spartan.txt | 4 +-- .../doctype/sales_invoice/sales_invoice.js | 6 ++-- .../doctype/sales_invoice/sales_invoice.txt | 17 ++++----- .../sales_taxes_and_charges_master.js | 36 ++++++++++++------- .../report/sales_register/sales_register.py | 5 +-- .../Quotation Classic/Quotation Classic.txt | 4 +-- .../Quotation Modern/Quotation Modern.txt | 4 +-- .../Quotation Spartan/Quotation Spartan.txt | 4 +-- .../Sales Order Classic.txt | 4 +-- .../Sales Order Modern/Sales Order Modern.txt | 4 +-- .../Sales Order Spartan.txt | 4 +-- selling/doctype/quotation/quotation.txt | 10 ++++-- selling/doctype/sales_order/sales_order.txt | 9 ++++- .../Delivery Note Classic.txt | 4 +-- .../Delivery Note Modern.txt | 4 +-- .../Delivery Note Spartan.txt | 4 +-- stock/doctype/delivery_note/delivery_note.txt | 13 +++++-- 20 files changed, 90 insertions(+), 58 deletions(-) diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index aab8e18491..d2cfa6d18a 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-09-13 17:17:47", + "modified": "2013-12-26 14:19:13", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt b/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt index fc99597766..4e8b12b943 100644 --- a/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt +++ b/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-08-07 20:14:53", + "modified": "2013-12-26 17:33:08", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt b/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt index 07946f7fcc..6808c009e6 100644 --- a/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt +++ b/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-08-07 20:12:16", + "modified": "2013-12-26 17:33:05", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt b/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt index 57c02fe2ec..45905fc2e1 100644 --- a/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt +++ b/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-08-07 19:50:51", + "modified": "2013-12-26 17:34:00", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index 7784005578..b3d784b383 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -25,7 +25,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte } // toggle to pos view if is_pos is 1 in user_defaults - if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos)) { + if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || this.frm.doc.is_pos)) { if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) { this.frm.set_value("is_pos", 1); this.is_pos(function() { @@ -144,8 +144,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte me.set_default_values(); me.set_dynamic_labels(); me.calculate_taxes_and_totals(); - - if(callback_fn) callback_fn() + + if(callback_fn) callback_fn(); } } }); diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 66cc0d930a..82a1eb5172 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-12-19 11:10:11", + "modified": "2013-12-26 17:50:21", "modified_by": "Administrator", "owner": "Administrator" }, @@ -362,13 +362,6 @@ "read_only": 1, "reqd": 1 }, - { - "doctype": "DocField", - "fieldname": "flat_discount", - "fieldtype": "Currency", - "label": "Flat Discount", - "options": "Company:company:default_currency" - }, { "doctype": "DocField", "fieldname": "taxes", @@ -459,6 +452,14 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency", + "print_hide": 0 + }, { "doctype": "DocField", "fieldname": "totals", diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index e2e5047028..0c5daf3667 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -19,6 +19,10 @@ cur_frm.pformat.net_total_export = function(doc) { return ''; } +cur_frm.pformat.flat_discount = function(doc) { + return ''; +} + cur_frm.pformat.grand_total_export = function(doc) { return ''; } @@ -33,10 +37,10 @@ cur_frm.pformat.in_words_export = function(doc) { cur_frm.pformat.other_charges= function(doc){ //function to make row of table - var make_row = function(title,val,bold){ + var make_row = function(title, val, bold){ var bstart = ''; var bend = ''; - return ''+(bold?bstart:'')+title+(bold?bend:'')+'' - +''+format_currency(val, doc.currency)+'' + return '' + (bold?bstart:'') + title + (bold?bend:'') + '' + +'' + format_currency(val, doc.currency) + '' +'' } @@ -52,7 +56,7 @@ cur_frm.pformat.other_charges= function(doc){ out =''; if (!doc.print_without_amount) { - var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges'); + var cl = getchildren('Sales Taxes and Charges', doc.name, 'other_charges'); // outer table var out='
'; @@ -60,6 +64,7 @@ cur_frm.pformat.other_charges= function(doc){ // main table out +=''; + if(!print_hide('net_total_export')) { out += make_row('Net Total', doc.net_total_export, 1); } @@ -68,26 +73,31 @@ cur_frm.pformat.other_charges= function(doc){ if(cl.length){ for(var i=0;i' + out += '' } - out +='
' + doc.in_words_export + '
'; + out += ''; } return out; } @@ -99,7 +109,7 @@ cur_frm.cscript.charge_type = function(doc, cdt, cdn) { d.charge_type = ''; } validated = false; - refresh_field('charge_type',d.name,'other_charges'); + refresh_field('charge_type', d.name, 'other_charges'); cur_frm.cscript.row_id(doc, cdt, cdn); cur_frm.cscript.rate(doc, cdt, cdn); cur_frm.cscript.tax_amount(doc, cdt, cdn); @@ -122,7 +132,7 @@ cur_frm.cscript.row_id = function(doc, cdt, cdn) { } } validated = false; - refresh_field('row_id',d.name,'other_charges'); + refresh_field('row_id', d.name, 'other_charges'); } /*---------------------- Get rate if account_head has account_type as TAX or CHARGEABLE-------------------------------------*/ @@ -152,7 +162,7 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) { d.rate = ''; } validated = false; - refresh_field('rate',d.name,'other_charges'); + refresh_field('rate', d.name, 'other_charges'); } cur_frm.cscript.tax_amount = function(doc, cdt, cdn) { @@ -166,5 +176,5 @@ cur_frm.cscript.tax_amount = function(doc, cdt, cdn) { d.tax_amount = ''; } validated = false; - refresh_field('tax_amount',d.name,'other_charges'); + refresh_field('tax_amount', d.name, 'other_charges'); }; \ No newline at end of file diff --git a/accounts/report/sales_register/sales_register.py b/accounts/report/sales_register/sales_register.py index 49b914e4a3..98ef93662d 100644 --- a/accounts/report/sales_register/sales_register.py +++ b/accounts/report/sales_register/sales_register.py @@ -79,7 +79,7 @@ def get_columns(invoice_list): tax_accounts = webnotes.conn.sql_list("""select distinct account_head from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' - and docstatus = 1 and ifnull(tax_amount, 0) != 0 + and docstatus = 1 and ifnull(tax_amount_after_flat_discount, 0) != 0 and parent in (%s) order by account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) @@ -126,7 +126,8 @@ def get_invoice_income_map(invoice_list): return invoice_income_map def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts): - tax_details = webnotes.conn.sql("""select parent, account_head, sum(tax_amount) as tax_amount + tax_details = webnotes.conn.sql("""select parent, account_head, + sum(tax_amount_after_flat_discount) as tax_amount from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) diff --git a/selling/Print Format/Quotation Classic/Quotation Classic.txt b/selling/Print Format/Quotation Classic/Quotation Classic.txt index e7588c4522..dc845290fe 100644 --- a/selling/Print Format/Quotation Classic/Quotation Classic.txt +++ b/selling/Print Format/Quotation Classic/Quotation Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:55:11", + "modified": "2013-12-26 17:45:37", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Quotation Modern/Quotation Modern.txt b/selling/Print Format/Quotation Modern/Quotation Modern.txt index 20d380dcbf..8b4b0d8f65 100644 --- a/selling/Print Format/Quotation Modern/Quotation Modern.txt +++ b/selling/Print Format/Quotation Modern/Quotation Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 20:12:11", + "modified": "2013-12-26 17:45:15", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Quotation Spartan/Quotation Spartan.txt b/selling/Print Format/Quotation Spartan/Quotation Spartan.txt index c5b4cb92b3..c4a1362ad3 100644 --- a/selling/Print Format/Quotation Spartan/Quotation Spartan.txt +++ b/selling/Print Format/Quotation Spartan/Quotation Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:53:01", + "modified": "2013-12-26 17:45:50", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Sales Order Classic/Sales Order Classic.txt b/selling/Print Format/Sales Order Classic/Sales Order Classic.txt index 7f2748ac0c..1d36ee6a77 100644 --- a/selling/Print Format/Sales Order Classic/Sales Order Classic.txt +++ b/selling/Print Format/Sales Order Classic/Sales Order Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:45:49", + "modified": "2013-12-26 17:35:51", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Sales Order Modern/Sales Order Modern.txt b/selling/Print Format/Sales Order Modern/Sales Order Modern.txt index e4102b2359..157c8eb29c 100644 --- a/selling/Print Format/Sales Order Modern/Sales Order Modern.txt +++ b/selling/Print Format/Sales Order Modern/Sales Order Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 20:12:23", + "modified": "2013-12-26 17:34:24", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt b/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt index 105b65b21b..8dce87eca4 100644 --- a/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt +++ b/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:45:59", + "modified": "2013-12-26 17:35:29", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/doctype/quotation/quotation.txt b/selling/doctype/quotation/quotation.txt index 93346d3029..ce8a0d502b 100644 --- a/selling/doctype/quotation/quotation.txt +++ b/selling/doctype/quotation/quotation.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:08", "docstatus": 0, - "modified": "2013-12-14 17:25:46", + "modified": "2013-12-26 17:54:55", "modified_by": "Administrator", "owner": "Administrator" }, @@ -458,6 +458,13 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "totals", @@ -863,7 +870,6 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", - "match": "customer", "role": "Customer", "submit": 0, "write": 0 diff --git a/selling/doctype/sales_order/sales_order.txt b/selling/doctype/sales_order/sales_order.txt index 7a1af77947..34309cc1a5 100644 --- a/selling/doctype/sales_order/sales_order.txt +++ b/selling/doctype/sales_order/sales_order.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-18 12:39:59", "docstatus": 0, - "modified": "2013-11-03 14:20:16", + "modified": "2013-12-26 17:55:43", "modified_by": "Administrator", "owner": "Administrator" }, @@ -477,6 +477,13 @@ "read_only": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "totals", diff --git a/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt b/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt index 163dffaa87..d16b67fea6 100644 --- a/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt +++ b/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:31:11", "docstatus": 0, - "modified": "2013-08-07 19:44:55", + "modified": "2013-12-26 17:36:51", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt b/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt index f4323a9e1f..9965634355 100644 --- a/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt +++ b/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:31:11", "docstatus": 0, - "modified": "2013-08-07 20:12:29", + "modified": "2013-12-26 17:36:26", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt b/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt index 03fbef521e..2623d76183 100644 --- a/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt +++ b/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:31:11", "docstatus": 0, - "modified": "2013-08-07 19:44:37", + "modified": "2013-12-26 17:37:14", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/stock/doctype/delivery_note/delivery_note.txt b/stock/doctype/delivery_note/delivery_note.txt index 480d45d014..9784b5a8fc 100644 --- a/stock/doctype/delivery_note/delivery_note.txt +++ b/stock/doctype/delivery_note/delivery_note.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:09", "docstatus": 0, - "modified": "2013-12-14 17:26:12", + "modified": "2013-12-26 18:01:33", "modified_by": "Administrator", "owner": "Administrator" }, @@ -465,7 +465,7 @@ "fieldname": "other_charges_total_export", "fieldtype": "Currency", "label": "Taxes and Charges Total", - "options": "company", + "options": "Company:company:default_currency", "print_hide": 1, "read_only": 1 }, @@ -487,6 +487,13 @@ "read_only": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "totals", @@ -1058,7 +1065,7 @@ }, { "doctype": "DocPerm", - "match": "customer", + "match": "customer_name", "role": "Customer" } ] \ No newline at end of file From 13fa595282788ff67c6bfcabe53942582a03daf7 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 26 Dec 2013 18:14:44 +0530 Subject: [PATCH 5/8] [flat discount] pos print format fixed --- accounts/Print Format/POS Invoice/POS Invoice.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index d2cfa6d18a..0907c4a865 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-12-26 14:19:13", + "modified": "2013-12-26 18:13:48", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", From 2b1d8854d5aa8c9cf85a34d344a1d283097a7797 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 26 Dec 2013 20:31:42 +0530 Subject: [PATCH 6/8] [flat discount] added flat discount in pos --- accounts/doctype/sales_invoice/pos.js | 82 ++++++++++++++++----------- patches/patch_list.py | 29 ++++++---- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index adbdca1b63..81f6ae9124 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -30,12 +30,14 @@ erpnext.POS = Class.extend({ \
\
\ - \ - \ - \ - \ - \ -
Net Total
\ +
\ + \ + \ + \ + \ + \ +
Net Total
\ +
\ \ +
\ + \ + \ + \ + \ + \ +
Flat Discount\ + \ +
\ +
\
\ \ \ @@ -82,6 +95,10 @@ erpnext.POS = Class.extend({ me.refresh(); }); + this.wrapper.find('input.flat-discount').on("change", function() { + wn.model.set_value(me.frm.doctype, me.frm.docname, "flat_discount", this.value); + }); + this.call_function("delete-items", function() {me.remove_selected_item();}); this.call_function("make-payment", function() {me.make_payment();}); }, @@ -112,9 +129,9 @@ erpnext.POS = Class.extend({ }, make: function() { this.make_party(); - this.make_item_group(); - this.make_search(); this.make_barcode(); + this.make_search(); + this.make_item_group(); this.make_item_list(); }, make_party: function() { @@ -137,23 +154,23 @@ erpnext.POS = Class.extend({ me.party.toLowerCase(), this.value); }); }, - make_item_group: function() { + make_barcode: function() { var me = this; - this.item_group = wn.ui.form.make_control({ + this.barcode = wn.ui.form.make_control({ df: { - "fieldtype": "Link", - "options": "Item Group", - "label": "Item Group", - "fieldname": "pos_item_group", - "placeholder": "Item Group" + "fieldtype": "Data", + "label": "Barcode", + "fieldname": "pos_barcode", + "placeholder": "Barcode / Serial No" }, - parent: this.wrapper.find(".item-group-area"), + parent: this.wrapper.find(".barcode-area"), only_input: true, }); - this.item_group.make_input(); - this.item_group.$input.on("change", function() { - if(!me.item_group.autocomplete_open) - me.make_item_list(); + this.barcode.make_input(); + this.barcode.$input.on("keypress", function() { + if(me.barcode_timeout) + clearTimeout(me.barcode_timeout); + me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000); }); }, make_search: function() { @@ -176,23 +193,23 @@ erpnext.POS = Class.extend({ me.item_timeout = setTimeout(function() { me.make_item_list(); }, 1000); }); }, - make_barcode: function() { + make_item_group: function() { var me = this; - this.barcode = wn.ui.form.make_control({ + this.item_group = wn.ui.form.make_control({ df: { - "fieldtype": "Data", - "label": "Barcode", - "fieldname": "pos_barcode", - "placeholder": "Barcode / Serial No" + "fieldtype": "Link", + "options": "Item Group", + "label": "Item Group", + "fieldname": "pos_item_group", + "placeholder": "Item Group" }, - parent: this.wrapper.find(".barcode-area"), + parent: this.wrapper.find(".item-group-area"), only_input: true, }); - this.barcode.make_input(); - this.barcode.$input.on("keypress", function() { - if(me.barcode_timeout) - clearTimeout(me.barcode_timeout); - me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000); + this.item_group.make_input(); + this.item_group.$input.on("change", function() { + if(!me.item_group.autocomplete_open) + me.make_item_list(); }); }, make_item_list: function() { @@ -321,6 +338,7 @@ erpnext.POS = Class.extend({ refresh: function() { var me = this; this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]); + this.wrapper.find('input.flat-discount').val(this.frm.doc.flat_discount); this.barcode.set_input(""); this.show_items_in_item_cart(); diff --git a/patches/patch_list.py b/patches/patch_list.py index 608ba77168..b567eb1c19 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -173,18 +173,18 @@ patch_list = [ "patches.july_2013.p05_custom_doctypes_in_list_view", "patches.july_2013.p06_same_sales_rate", "patches.july_2013.p07_repost_billed_amt_in_sales_cycle", - "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-07-22", - "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-07-22", - "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-07-22", - "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-07-22", - "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-07-22", - "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-07-22", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-12-26", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-12-26", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-12-26", "patches.july_2013.p08_custom_print_format_net_total_export", "patches.july_2013.p09_remove_website_pyc", "patches.july_2013.p10_change_partner_user_to_website_user", @@ -263,4 +263,9 @@ patch_list = [ "patches.1311.p08_email_digest_recipients", "execute:webnotes.delete_doc('DocType', 'Warehouse Type')", "patches.1312.p02_update_item_details_in_item_price", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2013-12-26", + "execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2013-12-26", ] \ No newline at end of file From 31ccf9a80bd7fa61e3debe40904995995cd370c0 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 27 Dec 2013 14:21:39 +0530 Subject: [PATCH 7/8] [flat discount] fixed test cases for stock entry --- accounts/doctype/sales_invoice/pos.js | 3 ++- buying/doctype/purchase_order/test_purchase_order.py | 1 - stock/doctype/stock_entry/stock_entry.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index 81f6ae9124..9e11fa80d2 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -53,7 +53,8 @@ erpnext.POS = Class.extend({
\
\ \ - \ + \ + \ \
Flat DiscountFlat Discount\ \ diff --git a/buying/doctype/purchase_order/test_purchase_order.py b/buying/doctype/purchase_order/test_purchase_order.py index f6c435c6fb..23d5ea4dca 100644 --- a/buying/doctype/purchase_order/test_purchase_order.py +++ b/buying/doctype/purchase_order/test_purchase_order.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt - from __future__ import unicode_literals import unittest import webnotes diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 2e7e2a4066..8eddbd4560 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -290,7 +290,7 @@ class DocType(StockController): if not returnable_qty: webnotes.throw("{item}: {item_code} {returned}".format( item=_("Item"), item_code=item.item_code, - returned=_("already returned though some other documents"))) + returned=_("already returned though some other documents")), StockOverReturnError) elif item.transfer_qty > returnable_qty: webnotes.throw("{item}: {item_code}, {returned}: {qty}".format( item=_("Item"), item_code=item.item_code, From 57738a0ff3e0880d40515b5be46a4b89aaab6962 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 3 Jan 2014 18:15:07 +0530 Subject: [PATCH 8/8] flat discount replaced to discount amount --- .../Print Format/POS Invoice/POS Invoice.txt | 2 +- .../Sales Invoice Classic.txt | 2 +- .../Sales Invoice Modern.txt | 2 +- .../Sales Invoice Spartan.txt | 2 +- erpnext/accounts/doctype/sales_invoice/pos.js | 12 +++--- .../doctype/sales_invoice/sales_invoice.py | 4 +- .../doctype/sales_invoice/sales_invoice.txt | 6 +-- .../sales_invoice/test_sales_invoice.py | 10 ++--- .../sales_taxes_and_charges.txt | 6 +-- .../sales_taxes_and_charges_master.js | 8 ++-- .../report/sales_register/sales_register.py | 4 +- .../purchase_common/purchase_common.js | 4 +- erpnext/controllers/accounts_controller.py | 42 +++++++++---------- erpnext/controllers/buying_controller.py | 6 +-- erpnext/controllers/selling_controller.py | 28 ++++++------- erpnext/patches.txt | 20 ++++++++- erpnext/public/js/transaction.js | 37 +++++++++------- .../Quotation Classic/Quotation Classic.txt | 2 +- .../Quotation Modern/Quotation Modern.txt | 2 +- .../Quotation Spartan/Quotation Spartan.txt | 2 +- .../Sales Order Classic.txt | 2 +- .../Sales Order Modern/Sales Order Modern.txt | 2 +- .../Sales Order Spartan.txt | 2 +- .../selling/doctype/quotation/quotation.txt | 6 +-- .../doctype/sales_order/sales_order.txt | 6 +-- erpnext/selling/sales_common.js | 38 ++++++++--------- .../Delivery Note Classic.txt | 2 +- .../Delivery Note Modern.txt | 2 +- .../Delivery Note Spartan.txt | 2 +- .../doctype/delivery_note/delivery_note.txt | 6 +-- 30 files changed, 144 insertions(+), 125 deletions(-) diff --git a/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt b/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt index 0907c4a865..980195642f 100644 --- a/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt b/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt index 4e8b12b943..09fcb91476 100644 --- a/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt +++ b/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt b/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt index 6808c009e6..a85a11abc8 100644 --- a/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt +++ b/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt b/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt index 45905fc2e1..e0850e1e9a 100644 --- a/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt +++ b/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/doctype/sales_invoice/pos.js b/erpnext/accounts/doctype/sales_invoice/pos.js index 1da6f735f6..1b14f05dc1 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.js +++ b/erpnext/accounts/doctype/sales_invoice/pos.js @@ -50,13 +50,13 @@ erpnext.POS = Class.extend({
\
\ -
\ +
\ \ \ - \ + \ \ \ \ @@ -96,8 +96,8 @@ erpnext.POS = Class.extend({ me.refresh(); }); - this.wrapper.find('input.flat-discount').on("change", function() { - wn.model.set_value(me.frm.doctype, me.frm.docname, "flat_discount", this.value); + this.wrapper.find('input.discount-amount').on("change", function() { + wn.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", this.value); }); this.call_function("delete-items", function() {me.remove_selected_item();}); @@ -339,7 +339,7 @@ erpnext.POS = Class.extend({ refresh: function() { var me = this; this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]); - this.wrapper.find('input.flat-discount').val(this.frm.doc.flat_discount); + this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount); this.barcode.set_input(""); this.show_items_in_item_cart(); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 55c2ecaa59..4a059441fe 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -556,12 +556,12 @@ class DocType(SellingController): def make_tax_gl_entries(self, gl_entries): for tax in self.doclist.get({"parentfield": "other_charges"}): - if flt(tax.tax_amount_after_flat_discount): + if flt(tax.tax_amount_after_discount_amount): gl_entries.append( self.get_gl_dict({ "account": tax.account_head, "against": self.doc.debit_to, - "credit": flt(tax.tax_amount_after_flat_discount), + "credit": flt(tax.tax_amount_after_discount_amount), "remarks": self.doc.remarks, "cost_center": tax.cost_center }) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt b/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt index 0fcb79d86b..66f7d32c3d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-12-26 17:50:21", + "modified": "2014-01-03 14:52:16", "modified_by": "Administrator", "owner": "Administrator" }, @@ -457,9 +457,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency", "print_hide": 0 }, diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4b49eb4715..709507abc1 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -136,9 +136,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 32.54) - def test_sales_invoice_flat_discount(self): + def test_sales_invoice_discount_amount(self): si = webnotes.bean(copy=test_records[3]) - si.doc.flat_discount = 104.95 + si.doc.discount_amount = 104.95 si.doclist.append({ "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", @@ -174,7 +174,7 @@ class TestSalesInvoice(unittest.TestCase): # check tax calculation expected_values = { - "keys": ["tax_amount", "tax_amount_after_flat_discount", "total"], + "keys": ["tax_amount", "tax_amount_after_discount_amount", "total"], "_Test Account Excise Duty - _TC": [140, 130.31, 1293.76], "_Test Account Education Cess - _TC": [2.8, 2.61, 1296.37], "_Test Account S&H Education Cess - _TC": [1.4, 1.31, 1297.68], @@ -193,9 +193,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1500) self.assertEquals(si.doc.grand_total_export, 1500) - def test_flat_discount_gl_entry(self): + def test_discount_amount_gl_entry(self): si = webnotes.bean(copy=test_records[3]) - si.doc.flat_discount = 104.95 + si.doc.discount_amount = 104.95 si.doclist.append({ "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt index 1b3b6f8939..f3c41a649f 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-24 11:39:32", "docstatus": 0, - "modified": "2013-12-20 19:21:45", + "modified": "2014-01-03 15:04:25", "modified_by": "Administrator", "owner": "Administrator" }, @@ -133,10 +133,10 @@ }, { "doctype": "DocField", - "fieldname": "tax_amount_after_flat_discount", + "fieldname": "tax_amount_after_discount_amount", "fieldtype": "Currency", "hidden": 1, - "label": "Tax Amount After Flat Discount", + "label": "Tax Amount After Discount Amount", "options": "Company:company:default_currency", "read_only": 1 }, diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index 2ac6be7a25..0e9b3db6c0 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -19,7 +19,7 @@ cur_frm.pformat.net_total_export = function(doc) { return ''; } -cur_frm.pformat.flat_discount = function(doc) { +cur_frm.pformat.discount_amount = function(doc) { return ''; } @@ -77,9 +77,9 @@ cur_frm.pformat.other_charges= function(doc){ } } - // flat discount - if(!print_hide('flat_discount') && doc.flat_discount) { - out += make_row('Flat Discount', doc.flat_discount, 0); + // Discount Amount + if(!print_hide('discount_amount') && doc.discount_amount) { + out += make_row('Discount Amount', convert_rate(doc.discount_amount), 0); } // grand total diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 98ef93662d..8fab6a9d97 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -79,7 +79,7 @@ def get_columns(invoice_list): tax_accounts = webnotes.conn.sql_list("""select distinct account_head from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' - and docstatus = 1 and ifnull(tax_amount_after_flat_discount, 0) != 0 + and docstatus = 1 and ifnull(tax_amount_after_discount_amount, 0) != 0 and parent in (%s) order by account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) @@ -127,7 +127,7 @@ def get_invoice_income_map(invoice_list): def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts): tax_details = webnotes.conn.sql("""select parent, account_head, - sum(tax_amount_after_flat_discount) as tax_amount + sum(tax_amount_after_discount_amount) as tax_amount from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 29e4781d29..f528f6cf1b 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -362,9 +362,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ } if(this.frm.tax_doclist.length) { - if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_flat_discount", this.frm.doctype)) { + if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_discount_amount", this.frm.doctype)) { $.each(this.frm.tax_doclist, function(i, tax) { - delete tax["tax_amount_after_flat_discount"]; + delete tax["tax_amount_after_discount_amount"]; }); } } diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 9b8dc2963d..e7393eb735 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -16,10 +16,7 @@ class AccountsController(TransactionBase): self.set_missing_values(for_validate=True) self.validate_date_with_fiscal_year() if self.meta.get_field("currency"): - self.flat_discount_applied = False self.calculate_taxes_and_totals() - if hasattr(self, "apply_flat_discount"): - self.apply_flat_discount() self.validate_value("grand_total", ">=", 0) self.set_total_in_words() @@ -136,6 +133,12 @@ class AccountsController(TransactionBase): self.doclist.append(tax) def calculate_taxes_and_totals(self): + self.discount_amount_applied = False + self._calculate_taxes_and_totals() + if self.meta.get_field(self.doc.doctype, "discount_amount"): + self.apply_discount_amount() + + def _calculate_taxes_and_totals(self): # validate conversion rate company_currency = get_company_currency(self.doc.company) if not self.doc.currency or self.doc.currency == company_currency: @@ -148,10 +151,6 @@ class AccountsController(TransactionBase): self.doc.conversion_rate = flt(self.doc.conversion_rate) self.item_doclist = self.doclist.get({"parentfield": self.fname}) self.tax_doclist = self.doclist.get({"parentfield": self.other_fname}) - - # for buying - if not hasattr(self, "flat_discount_applied"): - self.flat_discount_applied = False self.calculate_item_values() self.initialize_taxes() @@ -164,17 +163,14 @@ class AccountsController(TransactionBase): self.calculate_totals() self._cleanup() - # TODO - # print format: show net_total_export instead of net_total - def initialize_taxes(self): for tax in self.tax_doclist: tax.item_wise_tax_detail = {} - tax_fields = ["total", "tax_amount_after_flat_discount", + tax_fields = ["total", "tax_amount_after_discount_amount", "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] - if not self.flat_discount_applied: + if not self.discount_amount_applied: tax_fields.append("tax_amount") for fieldname in tax_fields: @@ -261,10 +257,10 @@ class AccountsController(TransactionBase): tax.tax_amount_for_current_item = current_tax_amount # accumulate tax amount into tax.tax_amount - if not self.flat_discount_applied: + if not self.discount_amount_applied: tax.tax_amount += current_tax_amount - tax.tax_amount_after_flat_discount += current_tax_amount + tax.tax_amount_after_discount_amount += current_tax_amount if tax.category: # if just for valuation, do not add the tax amount in total @@ -291,21 +287,21 @@ class AccountsController(TransactionBase): if n == len(self.item_doclist) - 1: self.round_off_totals(tax) - # adjust flat discount loss in last tax iteration - if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied: - self.adjust_flat_discount_loss(tax) + # adjust Discount Amount loss in last tax iteration + if i == (len(self.tax_doclist) - 1) and self.discount_amount_applied: + self.adjust_discount_amount_loss(tax) def round_off_totals(self, tax): tax.total = flt(tax.total, self.precision("total", tax)) tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount, self.precision("tax_amount", tax)) - def adjust_flat_discount_loss(self, tax): - flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + - flat_discount_loss, self.precision("tax_amount", tax)) - tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) + def adjust_discount_amount_loss(self, tax): + discount_amount_loss = self.doc.grand_total - flt(self.doc.discount_amount) - tax.total + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount + + discount_amount_loss, self.precision("tax_amount", tax)) + tax.total = flt(tax.total + discount_amount_loss, self.precision("total", tax)) def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index be07670450..f630f5ae83 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -147,7 +147,7 @@ class BuyingController(StockController): def _cleanup(self): super(BuyingController, self)._cleanup() - # except in purchase invoice, rate field is purchase_rate + # except in purchase invoice, rate field is purchase_rate # reset fieldname of rate if self.doc.doctype != "Purchase Invoice": df = self.meta.get_field("rate", parentfield=self.fname) @@ -161,9 +161,9 @@ class BuyingController(StockController): for item in self.item_doclist: del item.fields["item_tax_amount"] - if not self.meta.get_field("tax_amount_after_flat_discount", parentfield=self.other_fname): + if not self.meta.get_field("tax_amount_after_discount_amount", parentfield=self.other_fname): for tax in self.tax_doclist: - del tax.fields["tax_amount_after_flat_discount"] + del tax.fields["tax_amount_after_discount_amount"] def set_item_tax_amount(self, item, tax, current_tax_amount): """ diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 9e0fa1b2aa..04bcfaeb04 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -121,7 +121,7 @@ class SellingController(StockController): cumulated_tax_fraction += tax.tax_fraction_for_current_item - if cumulated_tax_fraction and not self.flat_discount_applied: + if cumulated_tax_fraction and not self.discount_amount_applied: item.amount = flt((item.export_amount * self.doc.conversion_rate) / (1 + cumulated_tax_fraction), self.precision("amount", item)) @@ -158,7 +158,7 @@ class SellingController(StockController): return current_tax_fraction def calculate_item_values(self): - if not self.flat_discount_applied: + if not self.discount_amount_applied: for item in self.item_doclist: self.round_floats_in(item) @@ -193,25 +193,25 @@ class SellingController(StockController): self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total, self.precision("other_charges_total")) self.doc.other_charges_total_export = flt(self.doc.grand_total_export - - self.doc.net_total_export + flt(self.doc.flat_discount), self.precision("other_charges_total_export")) + self.doc.net_total_export + flt(self.doc.discount_amount), self.precision("other_charges_total_export")) self.doc.rounded_total = _round(self.doc.grand_total) self.doc.rounded_total_export = _round(self.doc.grand_total_export) - def apply_flat_discount(self): - if self.doc.flat_discount: - total_amount_for_flat_discount = self.get_flat_discountable_amount() + def apply_discount_amount(self): + if self.doc.discount_amount: + grand_total_for_discount_amount = self.get_grand_total_for_discount_amount() - if total_amount_for_flat_discount: - # calculate item amount after flat discount + if grand_total_for_discount_amount: + # calculate item amount after Discount Amount for item in self.item_doclist: - distributed_amount = self.doc.flat_discount * item.amount / total_amount_for_flat_discount + distributed_amount = flt(self.doc.discount_amount) * item.amount / grand_total_for_discount_amount item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) - self.flat_discount_applied = True - self.calculate_taxes_and_totals() + self.discount_amount_applied = True + self._calculate_taxes_and_totals() - def get_flat_discountable_amount(self): + def get_grand_total_for_discount_amount(self): actual_taxes_dict = {} for tax in self.tax_doclist: @@ -222,9 +222,9 @@ class SellingController(StockController): flt(tax.rate) / 100 actual_taxes_dict.setdefault(tax.idx, actual_tax_amount) - total_amount_for_flat_discount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()), + grand_total_for_discount_amount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()), self.precision("grand_total")) - return total_amount_for_flat_discount + return grand_total_for_discount_amount def calculate_outstanding_amount(self): # NOTE: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index c1ab098298..f39e214245 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -1,3 +1,21 @@ erpnext.patches.4_0.update_user_properties erpnext.patches.4_0.move_warehouse_user_to_restrictions -erpnext.patches.4_0.new_permissions \ No newline at end of file +erpnext.patches.4_0.new_permissions + +execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2014-01-03 \ No newline at end of file diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js index e716c278ae..7db7aef51d 100644 --- a/erpnext/public/js/transaction.js +++ b/erpnext/public/js/transaction.js @@ -146,9 +146,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, validate: function() { - this.flat_discount_applied = false; this.calculate_taxes_and_totals(); - this.apply_flat_discount && this.apply_flat_discount(); }, set_default_values: function() { @@ -513,6 +511,13 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, calculate_taxes_and_totals: function() { + this.discount_amount_applied = false; + this._calculate_taxes_and_totals(); + if (wn.meta.get_docfield(this.frm.doc.doctype, "discount_amount")) + this.apply_discount_amount(); + }, + + _calculate_taxes_and_totals: function() { this.validate_conversion_rate(); this.frm.item_doclist = this.get_item_doclist(); this.frm.tax_doclist = this.get_tax_doclist(); @@ -524,7 +529,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ this.calculate_taxes(); this.calculate_totals(); this._cleanup(); - + this.show_item_wise_taxes(); }, @@ -533,11 +538,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ $.each(this.frm.tax_doclist, function(i, tax) { tax.item_wise_tax_detail = {}; - tax_fields = ["total", "tax_amount_after_flat_discount", + tax_fields = ["total", "tax_amount_after_discount_amount", "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] - if (!me.flat_discount_applied) + if (!me.discount_amount_applied) tax_fields.push("tax_amount"); $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); @@ -581,10 +586,10 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ tax.tax_amount_for_current_item = current_tax_amount; // accumulate tax amount into tax.tax_amount - if (!me.flat_discount_applied) + if (!me.discount_amount_applied) tax.tax_amount += current_tax_amount; - tax.tax_amount_after_flat_discount += current_tax_amount; + tax.tax_amount_after_discount_amount += current_tax_amount; // for buying if(tax.category) { @@ -614,9 +619,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ if (n == me.frm.item_doclist.length - 1) { me.round_off_totals(tax); - // adjust flat discount loss in last tax iteration - if ((i == me.frm.tax_doclist.length - 1) && me.flat_discount_applied) - me.adjust_flat_discount_loss(tax); + // adjust Discount Amount loss in last tax iteration + if ((i == me.frm.tax_doclist.length - 1) && me.discount_amount_applied) + me.adjust_discount_amount_loss(tax); } }); }); @@ -625,15 +630,15 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ round_off_totals: function(tax) { tax.total = flt(tax.total, precision("total", tax)); tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)); - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount, precision("tax_amount", tax)); }, - adjust_flat_discount_loss: function(tax) { - var flat_discount_loss = this.frm.doc.grand_total - this.frm.doc.flat_discount - tax.total; - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + - flat_discount_loss, precision("tax_amount", tax)); - tax.total = flt(tax.total + flat_discount_loss, precision("total", tax)); + adjust_discount_amount_loss: function(tax) { + var discount_amount_loss = this.frm.doc.grand_total - flt(this.frm.doc.discount_amount) - tax.total; + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount + + discount_amount_loss, precision("tax_amount", tax)); + tax.total = flt(tax.total + discount_amount_loss, precision("total", tax)); }, get_current_tax_amount: function(item, tax, item_tax_map) { diff --git a/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt b/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt index dc845290fe..05c3c598ca 100644 --- a/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt +++ b/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n
Flat DiscountDiscount Amount\ - \
\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t
\n\t\t\t\t\t\n\t\t\t

\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
Name
Address
Contact
\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t
Quotation Date
\n
\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt b/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt index 8b4b0d8f65..35850e62eb 100644 --- a/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt +++ b/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt b/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt index c4a1362ad3..3b4452666b 100644 --- a/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt +++ b/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt b/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt index 1d36ee6a77..7ee19c0f2d 100644 --- a/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt +++ b/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt b/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt index 157c8eb29c..7cf481d7b8 100644 --- a/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt +++ b/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt b/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt index 8dce87eca4..8da27b7d70 100644 --- a/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt +++ b/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/doctype/quotation/quotation.txt b/erpnext/selling/doctype/quotation/quotation.txt index 5453cb4e18..4795653262 100644 --- a/erpnext/selling/doctype/quotation/quotation.txt +++ b/erpnext/selling/doctype/quotation/quotation.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:08", "docstatus": 0, - "modified": "2013-12-26 17:54:55", + "modified": "2014-01-03 14:54:05", "modified_by": "Administrator", "owner": "Administrator" }, @@ -462,9 +462,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency" }, { diff --git a/erpnext/selling/doctype/sales_order/sales_order.txt b/erpnext/selling/doctype/sales_order/sales_order.txt index 2469a467f6..2dc62f334a 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.txt +++ b/erpnext/selling/doctype/sales_order/sales_order.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-18 12:39:59", "docstatus": 0, - "modified": "2013-12-26 17:55:43", + "modified": "2014-01-03 14:51:19", "modified_by": "Administrator", "owner": "Administrator" }, @@ -482,9 +482,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency" }, { diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 4562c2b217..330e725ed8 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -226,10 +226,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.calculate_taxes_and_totals(); }, - flat_discount: function() { - this.flat_discount_applied = false; + discount_amount: function() { this.calculate_taxes_and_totals(); - this.apply_flat_discount(); }, commission_rate: function() { @@ -317,7 +315,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ calculate_item_values: function() { var me = this; - if (!this.flat_discount_applied) { + if (!this.discount_amount_applied) { $.each(this.frm.item_doclist, function(i, item) { wn.model.round_floats_in(item); item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item)); @@ -349,7 +347,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ cumulated_tax_fraction += tax.tax_fraction_for_current_item; }); - if(cumulated_tax_fraction && !me.flat_discount_applied) { + if(cumulated_tax_fraction && !me.discount_amount_applied) { item.amount = flt( (item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), precision("amount", item)); @@ -416,31 +414,33 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("other_charges_total")); this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export - - this.frm.doc.net_total_export + this.frm.doc.flat_discount, + this.frm.doc.net_total_export + flt(this.frm.doc.discount_amount), precision("other_charges_total_export")); this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total); this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export); }, - apply_flat_discount: function() { + apply_discount_amount: function() { var me = this; var distributed_amount = 0.0; - if (this.frm.doc.flat_discount) { - var total_amount_for_flat_discount = this.get_flat_discountable_amount(); - // calculate item amount after flat discount - $.each(this.frm.item_doclist, function(i, item) { - distributed_amount = me.frm.doc.flat_discount * item.amount / total_amount_for_flat_discount; - item.amount = flt(item.amount - distributed_amount, precision("amount", item)); - }); + if (this.frm.doc.discount_amount) { + var grand_total_for_discount_amount = this.get_grand_total_for_discount_amount(); + // calculate item amount after Discount Amount + if (grand_total_for_discount_amount) { + $.each(this.frm.item_doclist, function(i, item) { + distributed_amount = flt(me.frm.doc.discount_amount) * item.amount / grand_total_for_discount_amount; + item.amount = flt(item.amount - distributed_amount, precision("amount", item)); + }); - this.flat_discount_applied = true; - this.calculate_taxes_and_totals(); + this.discount_amount_applied = true; + this._calculate_taxes_and_totals(); + } } }, - get_flat_discountable_amount: function() { + get_grand_total_for_discount_amount: function() { var me = this; var total_actual_tax = 0.0; var actual_taxes_dict = {}; @@ -459,9 +459,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ total_actual_tax += value; }); - total_amount_for_flat_discount = flt(this.frm.doc.grand_total - total_actual_tax, + grand_total_for_discount_amount = flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total")); - return total_amount_for_flat_discount; + return grand_total_for_discount_amount; }, calculate_outstanding_amount: function() { diff --git a/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt b/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt index d16b67fea6..d4c0cc1983 100644 --- a/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt +++ b/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt b/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt index 9965634355..3b36f6f1c0 100644 --- a/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt +++ b/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt b/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt index 2623d76183..072d411004 100644 --- a/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt +++ b/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.txt b/erpnext/stock/doctype/delivery_note/delivery_note.txt index c328874959..b2677a39e5 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.txt +++ b/erpnext/stock/doctype/delivery_note/delivery_note.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:09", "docstatus": 0, - "modified": "2013-12-26 18:01:33", + "modified": "2014-01-03 14:53:03", "modified_by": "Administrator", "owner": "Administrator" }, @@ -492,9 +492,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency" }, {