From b45d90153c9c18627f1fa26594411116c2356a2b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 25 May 2021 22:34:58 +0530 Subject: [PATCH 01/14] fix: Add non group filter for account --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index a7fcbd7e3be..a4022ef40a5 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -97,7 +97,8 @@ frappe.ui.form.on('Payment Entry', { return { filters: { "company": frm.doc.company, - "root_type": ["in", ["Asset", "Liability"]] + "root_type": ["in", ["Asset", "Liability"]], + "is_group": 0 } } }); From c368c5b20ba207e0ecf9973e380c99fbe3947706 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 27 May 2021 13:27:17 +0530 Subject: [PATCH 02/14] fix: Create new supplier for test case --- .../purchase_invoice/test_purchase_invoice.py | 15 ++++++++++----- .../doctype/purchase_order/test_purchase_order.py | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 319808ac959..2610a69471f 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -16,6 +16,7 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_tra from erpnext.projects.doctype.project.test_project import make_project from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account from erpnext.stock.doctype.item.test_item import create_item +from erpnext.buying.doctype.supplier.test_supplier import create_supplier test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"] test_ignore = ["Serial No"] @@ -955,11 +956,15 @@ class TestPurchaseInvoice(unittest.TestCase): from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_purchase_invoice + # create a new supplier to test + supplier = create_supplier(supplier_name = '_Test TDS Advance Supplier', + tax_withholding_category = 'TDS - 194 - Dividends - Individual') + # Update tax withholding category with current fiscal year and rate details update_tax_witholding_category('_Test Company', 'TDS Payable - _TC', nowdate()) # Create Purchase Order with TDS applied - po = create_purchase_order(do_not_save=1, rate=3000) + po = create_purchase_order(do_not_save=1, supplier=supplier.name, rate=3000) po.apply_tds = 1 po.tax_withholding_category = 'TDS - 194 - Dividends - Individual' po.save() @@ -976,8 +981,8 @@ class TestPurchaseInvoice(unittest.TestCase): # Check GLE for Payment Entry expected_gle = [ ['_Test Account Excise Duty - _TC', 3000, 0], - ['Cash - _TC', 0, 24000], - ['Creditors - _TC', 24000, 0], + ['Cash - _TC', 0, 27000], + ['Creditors - _TC', 27000, 0], ['TDS Payable - _TC', 0, 3000], ] @@ -1002,8 +1007,8 @@ class TestPurchaseInvoice(unittest.TestCase): expected_gle = [ ['_Test Account Excise Duty - _TC', 0, 3000], ['Cost of Goods Sold - _TC', 30000, 0], - ['Creditors - _TC', 0, 24000], - ['TDS Payable - _TC', 6000, 3000], + ['Creditors - _TC', 0, 27000], + ['TDS Payable - _TC', 3000, 3000], ] gl_entries = frappe.db.sql("""select account, debit, credit diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index aaa98f2f1f4..39171960d8c 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -1111,7 +1111,7 @@ def create_purchase_order(**args): po.schedule_date = add_days(nowdate(), 1) po.company = args.company or "_Test Company" - po.supplier = args.customer or "_Test Supplier" + po.supplier = args.supplier or "_Test Supplier" po.is_subcontracted = args.is_subcontracted or "No" po.currency = args.currency or frappe.get_cached_value('Company', po.company, "default_currency") po.conversion_factor = args.conversion_factor or 1 From 8106d70e7028a8d6fc117e6e096a8ac8caed294f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 27 May 2021 16:40:37 +0530 Subject: [PATCH 03/14] fix: Update GL Entry ordering --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 2610a69471f..07f9b42fbf3 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1005,8 +1005,8 @@ class TestPurchaseInvoice(unittest.TestCase): # Check GLE for Purchase Invoice # Zero net effect on final TDS Payable on invoice expected_gle = [ + ['_Test Account Cost for Goods Sold - _TC', 30000, 0], ['_Test Account Excise Duty - _TC', 0, 3000], - ['Cost of Goods Sold - _TC', 30000, 0], ['Creditors - _TC', 0, 27000], ['TDS Payable - _TC', 3000, 3000], ] From 10e8316240e7ba4fabeeb049503711c46fb89c18 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 27 May 2021 17:43:53 +0530 Subject: [PATCH 04/14] fix: Debug Test --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 07f9b42fbf3..8bb9d7dacf3 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1016,6 +1016,9 @@ class TestPurchaseInvoice(unittest.TestCase): where voucher_type='Purchase Invoice' and voucher_no=%s order by account asc""", (purchase_invoice.name), as_dict=1) + for gle in gl_entries: + print(gle.account, gle.debit, gle.credit) + for i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.debit) From 223efec26e50356a0dfd664479a2ccbfec05ac7a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 27 May 2021 20:09:45 +0530 Subject: [PATCH 05/14] fix: Split GL Entry --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 8bb9d7dacf3..1ec49d178f8 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1008,7 +1008,8 @@ class TestPurchaseInvoice(unittest.TestCase): ['_Test Account Cost for Goods Sold - _TC', 30000, 0], ['_Test Account Excise Duty - _TC', 0, 3000], ['Creditors - _TC', 0, 27000], - ['TDS Payable - _TC', 3000, 3000], + ['TDS Payable - _TC', 0, 3000], + ['TDS Payable - _TC', 3000, 0] ] gl_entries = frappe.db.sql("""select account, debit, credit From 12fb02ed2ab9958d0bb2f23a99d42e35e9d691de Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 27 May 2021 20:10:50 +0530 Subject: [PATCH 06/14] fix: Remove GL Entry from print --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 1ec49d178f8..1c4350f8dcb 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1017,9 +1017,6 @@ class TestPurchaseInvoice(unittest.TestCase): where voucher_type='Purchase Invoice' and voucher_no=%s order by account asc""", (purchase_invoice.name), as_dict=1) - for gle in gl_entries: - print(gle.account, gle.debit, gle.credit) - for i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.debit) From 16b309e66e24bcdd62eeba6de3688698f7434215 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Jun 2021 11:07:18 +0530 Subject: [PATCH 07/14] fix: Labeling and other fixes --- .../advance_taxes_and_charges.json | 80 ++++--------- .../doctype/payment_entry/payment_entry.js | 6 +- .../doctype/payment_entry/payment_entry.json | 5 +- .../purchase_taxes_and_charges.json | 105 +++++++----------- .../sales_taxes_and_charges.json | 38 ++++--- .../public/js/controllers/taxes_and_totals.js | 2 +- 6 files changed, 92 insertions(+), 144 deletions(-) diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json index aac7eb6bcb8..c127601259c 100644 --- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json +++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json @@ -36,10 +36,8 @@ "label": "Type", "oldfieldname": "charge_type", "oldfieldtype": "Select", - "options": "\nActual\nOn Paid Amount\nIncluded In Paid Amount\nOn Previous Row Amount\nOn Previous Row Total", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "options": "\nActual\nOn Paid Amount\nOn Previous Row Amount\nOn Previous Row Total", + "reqd": 1 }, { "depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1", @@ -47,9 +45,7 @@ "fieldtype": "Data", "label": "Reference Row #", "oldfieldname": "row_id", - "oldfieldtype": "Data", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Data" }, { "columns": 2, @@ -61,15 +57,11 @@ "oldfieldtype": "Link", "options": "Account", "reqd": 1, - "search_index": 1, - "show_days": 1, - "show_seconds": 1 + "search_index": 1 }, { "fieldname": "col_break_1", "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1, "width": "50%" }, { @@ -80,16 +72,12 @@ "oldfieldtype": "Small Text", "print_width": "300px", "reqd": 1, - "show_days": 1, - "show_seconds": 1, "width": "300px" }, { "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", - "label": "Accounting Dimensions", - "show_days": 1, - "show_seconds": 1 + "label": "Accounting Dimensions" }, { "default": ":Company", @@ -98,21 +86,15 @@ "label": "Cost Center", "oldfieldname": "cost_center_other_charges", "oldfieldtype": "Link", - "options": "Cost Center", - "show_days": 1, - "show_seconds": 1 + "options": "Cost Center" }, { "fieldname": "dimension_col_break", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "section_break_8", - "fieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Section Break" }, { "columns": 2, @@ -121,15 +103,11 @@ "in_list_view": 1, "label": "Rate", "oldfieldname": "rate", - "oldfieldtype": "Currency", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Currency" }, { "fieldname": "section_break_9", - "fieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Section Break" }, { "columns": 2, @@ -137,9 +115,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Amount", - "options": "currency", - "show_days": 1, - "show_seconds": 1 + "options": "currency" }, { "columns": 2, @@ -148,15 +124,11 @@ "in_list_view": 1, "label": "Total", "options": "currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_13", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "base_tax_amount", @@ -165,9 +137,7 @@ "oldfieldname": "tax_amount", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "base_total", @@ -176,48 +146,38 @@ "oldfieldname": "total", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "add_deduct_tax", "fieldtype": "Select", "label": "Add Or Deduct", "options": "Add\nDeduct", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "default": "0", "fieldname": "included_in_paid_amount", "fieldtype": "Check", - "label": "Included In Paid Amount", - "show_days": 1, - "show_seconds": 1 + "label": "Included In Paid Amount" }, { "fieldname": "allocated_amount", "fieldtype": "Currency", "label": "Allocated Amount", - "options": "currency", - "show_days": 1, - "show_seconds": 1 + "options": "currency" }, { "fieldname": "base_allocated_amount", "fieldtype": "Currency", "label": "Allocated Amount (Company Currency)", - "options": "Company:company:default_currency", - "show_days": 1, - "show_seconds": 1 + "options": "Company:company:default_currency" } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-11-29 19:06:14.666460", + "modified": "2021-05-31 02:03:57.444647", "modified_by": "Administrator", "module": "Accounts", "name": "Advance Taxes and Charges", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index a4022ef40a5..b1cf9e02e61 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -230,7 +230,7 @@ frappe.ui.form.on('Payment Entry', { var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: ""; frm.set_currency_labels(["base_paid_amount", "base_received_amount", "base_total_allocated_amount", - "difference_amount", "base_paid_amount_after_tax"], company_currency); + "difference_amount", "base_paid_amount_after_tax", "base_received_amount_after_tax"], company_currency); frm.set_currency_labels(["paid_amount"], frm.doc.paid_from_account_currency); frm.set_currency_labels(["received_amount"], frm.doc.paid_to_account_currency); @@ -238,11 +238,13 @@ frappe.ui.form.on('Payment Entry', { var party_account_currency = frm.doc.payment_type=="Receive" ? frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency; - frm.set_currency_labels(["total_allocated_amount", "unallocated_amount"], party_account_currency); + frm.set_currency_labels(["total_allocated_amount", "unallocated_amount", + "total_taxes_and_charges"], party_account_currency); var currency_field = (frm.doc.payment_type=="Receive") ? "paid_from_account_currency" : "paid_to_account_currency" frm.set_df_property("total_allocated_amount", "options", currency_field); frm.set_df_property("unallocated_amount", "options", currency_field); + frm.set_df_property("total_taxes_and_charges", "options", currency_field); frm.set_df_property("party_balance", "options", currency_field); frm.set_currency_labels(["total_amount", "outstanding_amount", "allocated_amount"], diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 1e2bd8194a4..0b4178a547e 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -335,6 +335,7 @@ "reqd": 1 }, { + "depends_on": "doc.received_amount", "fieldname": "base_received_amount", "fieldtype": "Currency", "label": "Received Amount (Company Currency)", @@ -683,6 +684,7 @@ "fieldname": "advance_tax_account", "fieldtype": "Link", "label": "Advance Tax Account", + "mandatory_depends_on": "doc.base_total_taxes_and_charges", "options": "Account" }, { @@ -692,6 +694,7 @@ "options": "paid_to_account_currency" }, { + "depends_on": "doc.received_amount", "fieldname": "base_received_amount_after_tax", "fieldtype": "Currency", "label": "Received Amount After Tax (Company Currency)", @@ -701,7 +704,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-05-20 02:04:56.766124", + "modified": "2021-05-31 01:54:18.378910", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json index 0db0b6823d2..f6703315fa7 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json @@ -12,6 +12,7 @@ "charge_type", "row_id", "included_in_print_rate", + "included_in_paid_amount", "col_break1", "account_head", "description", @@ -21,6 +22,7 @@ "cost_center", "dimension_col_break", "section_break_9", + "currency", "tax_amount", "tax_amount_after_discount_amount", "total", @@ -39,9 +41,7 @@ "oldfieldname": "category", "oldfieldtype": "Select", "options": "Valuation and Total\nValuation\nTotal", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "default": "Add", @@ -51,9 +51,7 @@ "oldfieldname": "add_deduct_tax", "oldfieldtype": "Select", "options": "Add\nDeduct", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "columns": 2, @@ -65,9 +63,7 @@ "oldfieldname": "charge_type", "oldfieldtype": "Select", "options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1", @@ -75,9 +71,7 @@ "fieldtype": "Data", "label": "Reference Row #", "oldfieldname": "row_id", - "oldfieldtype": "Data", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Data" }, { "default": "0", @@ -85,15 +79,11 @@ "fieldname": "included_in_print_rate", "fieldtype": "Check", "label": "Is this Tax included in Basic Rate?", - "report_hide": 1, - "show_days": 1, - "show_seconds": 1 + "report_hide": 1 }, { "fieldname": "col_break1", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "columns": 2, @@ -104,9 +94,7 @@ "oldfieldname": "account_head", "oldfieldtype": "Link", "options": "Account", - "reqd": 1, - "show_days": 1, - "show_seconds": 1 + "reqd": 1 }, { "default": ":Company", @@ -115,9 +103,7 @@ "label": "Cost Center", "oldfieldname": "cost_center", "oldfieldtype": "Link", - "options": "Cost Center", - "show_days": 1, - "show_seconds": 1 + "options": "Cost Center" }, { "fieldname": "description", @@ -127,15 +113,11 @@ "oldfieldtype": "Small Text", "print_width": "300px", "reqd": 1, - "show_days": 1, - "show_seconds": 1, "width": "300px" }, { "fieldname": "section_break_10", - "fieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Section Break" }, { "columns": 2, @@ -144,15 +126,11 @@ "in_list_view": 1, "label": "Rate", "oldfieldname": "rate", - "oldfieldtype": "Currency", - "show_days": 1, - "show_seconds": 1 + "oldfieldtype": "Currency" }, { "fieldname": "section_break_9", - "fieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Section Break" }, { "columns": 2, @@ -162,9 +140,7 @@ "label": "Amount", "oldfieldname": "tax_amount", "oldfieldtype": "Currency", - "options": "currency", - "show_days": 1, - "show_seconds": 1 + "options": "currency" }, { "fieldname": "tax_amount_after_discount_amount", @@ -172,9 +148,7 @@ "label": "Tax Amount After Discount Amount", "options": "currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "columns": 2, @@ -185,15 +159,11 @@ "oldfieldname": "total", "oldfieldtype": "Currency", "options": "currency", - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "column_break_14", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "base_tax_amount", @@ -201,9 +171,7 @@ "label": "Amount (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "base_total", @@ -211,9 +179,7 @@ "hidden": 1, "label": "Total (Company Currency)", "options": "Company:company:default_currency", - "print_hide": 1, - "show_days": 1, - "show_seconds": 1 + "print_hide": 1 }, { "fieldname": "base_tax_amount_after_discount_amount", @@ -221,9 +187,7 @@ "label": "Tax Amount After Discount Amount", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "item_wise_tax_detail", @@ -233,28 +197,37 @@ "oldfieldname": "item_wise_tax_detail", "oldfieldtype": "Small Text", "print_hide": 1, - "read_only": 1, - "show_days": 1, - "show_seconds": 1 + "read_only": 1 }, { "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", - "label": "Accounting Dimensions", - "show_days": 1, - "show_seconds": 1 + "label": "Accounting Dimensions" }, { "fieldname": "dimension_col_break", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" + }, + { + "fetch_from": "account_head.account_currency", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Account Currency", + "options": "Currency", + "read_only": 1 + }, + { + "default": "0", + "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry", + "fieldname": "included_in_paid_amount", + "fieldtype": "Check", + "label": "Included In Paid Amount" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2020-11-29 19:11:58.826078", + "modified": "2021-05-31 03:41:38.298937", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Taxes and Charges", diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json index 3c8cb6b8518..36fd634b507 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json @@ -1,8 +1,10 @@ { + "actions": [], "creation": "2013-04-24 11:39:32", "doctype": "DocType", "document_type": "Setup", "editable_grid": 1, + "engine": "InnoDB", "field_order": [ "charge_type", "row_id", @@ -10,12 +12,14 @@ "col_break_1", "description", "included_in_print_rate", + "included_in_paid_amount", "accounting_dimensions_section", "cost_center", "dimension_col_break", "section_break_8", "rate", "section_break_9", + "currency", "tax_amount", "total", "tax_amount_after_discount_amount", @@ -23,8 +27,7 @@ "base_tax_amount", "base_total", "base_tax_amount_after_discount_amount", - "item_wise_tax_detail", - "parenttype" + "item_wise_tax_detail" ], "fields": [ { @@ -173,17 +176,6 @@ "oldfieldtype": "Small Text", "read_only": 1 }, - { - "fieldname": "parenttype", - "fieldtype": "Data", - "hidden": 1, - "in_filter": 1, - "label": "Parenttype", - "oldfieldname": "parenttype", - "oldfieldtype": "Data", - "print_hide": 1, - "search_index": 1 - }, { "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", @@ -192,15 +184,33 @@ { "fieldname": "dimension_col_break", "fieldtype": "Column Break" + }, + { + "fetch_from": "account_head.account_currency", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Account Currency", + "options": "Currency", + "read_only": 1 + }, + { + "default": "0", + "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry", + "fieldname": "included_in_paid_amount", + "fieldtype": "Check", + "label": "Included In Paid Amount" } ], "idx": 1, + "index_web_pages_for_search": 1, "istable": 1, - "modified": "2019-05-25 22:59:38.740883", + "links": [], + "modified": "2021-05-31 05:40:32.856780", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Taxes and Charges", "owner": "Administrator", "permissions": [], + "sort_field": "modified", "sort_order": "ASC" } \ No newline at end of file diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 2e133bed2eb..3097f72201a 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -464,7 +464,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ }, calculate_totals: function() { - // Changing sequence can cause rounding_adjustmentng issue and on-screen discrepency + // Changing sequence can because of rounding adjustment issue and on-screen discrepancy var me = this; var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0; this.frm.doc.grand_total = flt(tax_count From af13348817aacdf91b6c73bf8a95a2f5b9413ab9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 8 Jun 2021 16:35:47 +0530 Subject: [PATCH 08/14] refactor: Advance taxes and charges calculation --- .../advance_taxes_and_charges.json | 11 +- .../doctype/payment_entry/payment_entry.js | 162 +++++++++++++---- .../doctype/payment_entry/payment_entry.py | 163 +++++++++++++----- 3 files changed, 255 insertions(+), 81 deletions(-) diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json index c127601259c..3e4e679c913 100644 --- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json +++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json @@ -19,6 +19,7 @@ "section_break_8", "rate", "section_break_9", + "currency", "tax_amount", "total", "allocated_amount", @@ -172,12 +173,20 @@ "fieldtype": "Currency", "label": "Allocated Amount (Company Currency)", "options": "Company:company:default_currency" + }, + { + "fetch_from": "account_head.account_currency", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Account Currency", + "options": "Currency", + "read_only": 1 } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-05-31 02:03:57.444647", + "modified": "2021-06-08 07:04:44.287002", "modified_by": "Administrator", "module": "Accounts", "name": "Advance Taxes and Charges", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index b1cf9e02e61..6a3b717b12f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -1071,7 +1071,7 @@ frappe.ui.form.on('Payment Entry', { } me.frm.add_child("taxes", tax); } - frm.trigger('calculate_taxes'); + frm.events.apply_taxes(frm); frm.events.set_unallocated_amount(frm); } } @@ -1079,52 +1079,112 @@ frappe.ui.form.on('Payment Entry', { }); }, + apply_taxes: function(frm) { + frm.events.initialize_taxes(frm); + frm.events.determine_exclusive_rate(frm); + frm.events.calculate_taxes(frm); + }, + + initialize_taxes: function(frm) { + $.each(frm.doc["taxes"] || [], function(i, tax) { + tax.item_wise_tax_detail = {}; + let tax_fields = ["total", "tax_fraction_for_current_item", + "grand_total_fraction_for_current_item"]; + + if (cstr(tax.charge_type) != "Actual") { + tax_fields.push("tax_amount"); + } + + $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0; }); + + frm.doc.paid_amount_after_tax = frm.doc.paid_amount; + }); + }, + + determine_exclusive_rate: function(frm) { + let has_inclusive_tax = false; + $.each(frm.doc["taxes"] || [], function(i, row) { + if(cint(row.included_in_paid_amount)) has_inclusive_tax = true; + }); + if(has_inclusive_tax==false) return; + + let cumulated_tax_fraction = 0.0; + $.each(frm.doc["taxes"] || [], function(i, tax) { + let current_tax_fraction = frm.events.get_current_tax_fraction(frm, tax); + tax.tax_fraction_for_current_item = current_tax_fraction[0]; + + if(i==0) { + tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item; + } else { + tax.grand_total_fraction_for_current_item = + me.frm.doc["taxes"][i-1].grand_total_fraction_for_current_item + + tax.tax_fraction_for_current_item; + } + + cumulated_tax_fraction += tax.tax_fraction_for_current_item; + frm.doc.paid_amount_after_tax = flt(frm.doc.paid_amount/(1+cumulated_tax_fraction)) + }); + }, + + get_current_tax_fraction: function(frm, tax) { + let current_tax_fraction = 0.0; + + if(cint(tax.included_in_paid_amount)) { + let tax_rate = tax.rate; + + if (tax.charge_type == "Actual") { + current_tax_fraction = tax.tax_amount/frm.doc.paid_amount_after_tax; + } else if(tax.charge_type == "On Paid Amount") { + current_tax_fraction = (tax_rate / 100.0); + } else if(tax.charge_type == "On Previous Row Amount") { + current_tax_fraction = (tax_rate / 100.0) * + frm.doc["taxes"][cint(tax.row_id) - 1].tax_fraction_for_current_item; + } else if(tax.charge_type == "On Previous Row Total") { + current_tax_fraction = (tax_rate / 100.0) * + frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item; + } + } + + if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") { + current_tax_fraction *= -1; + inclusive_tax_amount_per_qty *= -1; + } + return current_tax_fraction; + }, + + calculate_taxes: function(frm) { frm.doc.total_taxes_and_charges = 0.0; frm.doc.base_total_taxes_and_charges = 0.0; - $.each(me.frm.doc["taxes"] || [], function(i, tax) { - let tax_rate = tax.rate; - let current_tax_amount = 0.0; + let actual_tax_dict = {}; - // To set row_id by default as previous row. - if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) { - if (tax.idx === 1) { - frappe.throw(__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")); - } - if (!tax.row_id) { - tax.row_id = tax.idx - 1; - } + // maintain actual tax rate based on idx + $.each(frm.doc["taxes"] || [], function(i, tax) { + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] = flt(tax.tax_amount, precision("tax_amount", tax)); } + }); - if(tax.charge_type == "Actual") { - current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)); - } else if(tax.charge_type == "On Paid Amount") { - current_tax_amount = (tax_rate / 100.0) * frm.doc.paid_amount; - } else if(tax.charge_type == "On Previous Row Amount") { - current_tax_amount = (tax_rate / 100.0) * - frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount; + $.each(me.frm.doc["taxes"] || [], function(i, tax) { + let current_tax_amount = frm.events.get_current_tax_amount(frm, tax); - } else if(tax.charge_type == "On Previous Row Total") { - current_tax_amount = (tax_rate / 100.0) * - frm.doc["taxes"][cint(tax.row_id) - 1].total; + // Adjust divisional loss to the last item + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] -= current_tax_amount; + if (i == frm.doc["taxes"].length - 1) { + current_tax_amount += actual_tax_dict[tax.idx]; + } } tax.tax_amount = current_tax_amount; tax.base_tax_amount = tax.tax_amount * frm.doc.source_exchange_rate; - current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0; - let applicable_tax_amount = 0 - - if (!tax.included_in_paid_amount) { - applicable_tax_amount = current_tax_amount - } - if(i==0) { - tax.total = flt(frm.doc.paid_amount + applicable_tax_amount, precision("total", tax)); + tax.total = flt(frm.doc.paid_amount_after_tax + current_tax_amount, precision("total", tax)); } else { - tax.total = flt(frm.doc["taxes"][i-1].total + applicable_tax_amount, precision("total", tax)); + tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax)); } tax.base_total = tax.total * frm.doc.source_exchange_rate; @@ -1136,6 +1196,36 @@ frappe.ui.form.on('Payment Entry', { frm.refresh_field('base_total_taxes_and_charges'); }); }, + + get_current_tax_amount: function(frm, tax) { + let tax_rate = tax.rate; + let current_tax_amount = 0.0; + + // To set row_id by default as previous row. + if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) { + if (tax.idx === 1) { + frappe.throw( + __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")); + } + if (!tax.row_id) { + tax.row_id = tax.idx - 1; + } + } + if(tax.charge_type == "Actual") { + current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)) + } else if(tax.charge_type == "On Paid Amount") { + current_tax_amount = flt((tax_rate / 100.0) * frm.doc.paid_amount_after_tax); + } else if(tax.charge_type == "On Previous Row Amount") { + current_tax_amount = flt((tax_rate / 100.0) * + frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount); + + } else if(tax.charge_type == "On Previous Row Total") { + current_tax_amount = flt((tax_rate / 100.0) * + frm.doc["taxes"][cint(tax.row_id) - 1].total); + } + + return current_tax_amount; + }, }); @@ -1184,27 +1274,27 @@ frappe.ui.form.on('Payment Entry Reference', { frappe.ui.form.on('Advance Taxes and Charges', { rate: function(frm) { - frm.events.calculate_taxes(frm); + frm.events.apply_taxes(frm); frm.events.set_unallocated_amount(frm); }, tax_amount : function(frm) { - frm.events.calculate_taxes(frm); + frm.events.apply_taxes(frm); frm.events.set_unallocated_amount(frm); }, row_id: function(frm) { - frm.events.calculate_taxes(frm); + frm.events.apply_taxes(frm); frm.events.set_unallocated_amount(frm); }, taxes_remove: function(frm) { - frm.events.calculate_taxes(frm); + frm.events.apply_taxes(frm); frm.events.set_unallocated_amount(frm); }, included_in_paid_amount: function(frm) { - frm.events.calculate_taxes(frm); + frm.events.apply_taxes(frm); frm.events.set_unallocated_amount(frm); } }) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index d9601566707..83d52fa5f63 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -54,7 +54,7 @@ class PaymentEntry(AccountsController): self.validate_mandatory() self.validate_reference_documents() self.set_tax_withholding() - self.calculate_taxes() + self.apply_taxes() self.set_amounts() self.clear_unallocated_reference_document_rows() self.validate_payment_against_negative_invoice() @@ -65,7 +65,6 @@ class PaymentEntry(AccountsController): self.validate_allocated_amount() self.validate_paid_invoices() self.ensure_supplier_is_not_blocked() - self.set_advance_tax_account() self.set_status() def on_submit(self): @@ -311,14 +310,6 @@ class PaymentEntry(AccountsController): + "

" + _("If this is undesirable please cancel the corresponding Payment Entry."), title=_("Warning"), indicator="orange") - def set_advance_tax_account(self): - if self.get('taxes') and not self.advance_tax_account: - unrealized_profit_loss_account = frappe.db.get_value('Company', self.company, 'unrealized_profit_loss_account') - if not unrealized_profit_loss_account: - frappe.throw(_("Please select advance tax account or add Unrealized Profit / Loss Account in company master")) - - self.advance_tax_account = unrealized_profit_loss_account - def validate_journal_entry(self): for d in self.get("references"): if d.allocated_amount and d.reference_doctype == "Journal Entry": @@ -461,6 +452,11 @@ class PaymentEntry(AccountsController): for d in to_remove: self.remove(d) + def apply_taxes(self): + self.initialize_taxes() + self.determine_exclusive_rate() + self.calculate_taxes() + def set_amounts(self): self.set_received_amount() self.set_amounts_in_company_currency() @@ -715,12 +711,12 @@ class PaymentEntry(AccountsController): if account_currency != self.company_currency: frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency)) - if self.payment_type == 'Pay': + if (self.payment_type == 'Pay' and self.advance_tax_account) or self.payment_type == 'Receive': dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit" - rev_dr_cr = "credit" if d.add_deduct_tax == "Add" else "debit" - elif self.payment_type == 'Receive': + elif (self.payment_type == 'Receive' and self.advance_tax_account) or self.payment_type == 'Pay': dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit" - rev_dr_cr = "debit" if d.add_deduct_tax == "Add" else "credit" + + payment_or_advance_account = self.get_party_account_for_taxes() gl_entries.append( self.get_gl_dict({ @@ -733,15 +729,16 @@ class PaymentEntry(AccountsController): "cost_center": d.cost_center }, account_currency, item=d)) + #Intentionally use -1 to get net values in party account gl_entries.append( self.get_gl_dict({ - "account": self.advance_tax_account, + "account": payment_or_advance_account, "against": self.party if self.payment_type=="Receive" else self.paid_from, - rev_dr_cr: d.base_tax_amount, - rev_dr_cr + "_in_account_currency": d.base_tax_amount + dr_or_cr: -1 * d.base_tax_amount, + dr_or_cr + "_in_account_currency": -1*d.base_tax_amount if account_currency==self.company_currency else d.tax_amount, - "cost_center": d.cost_center or self.cost_center + "cost_center": self.cost_center, }, account_currency, item=d)) def add_deductions_gl_entries(self, gl_entries): @@ -762,6 +759,14 @@ class PaymentEntry(AccountsController): }, item=d) ) + def get_party_account_for_taxes(self): + if self.advance_tax_account: + return self.advance_tax_account + elif self.payment_type == 'Pay': + return self.paid_from + elif self.payment_type == 'Receive': + return self.paid_to + def update_advance_paid(self): if self.payment_type in ("Receive", "Pay") and self.party: for d in self.get("references"): @@ -808,32 +813,52 @@ class PaymentEntry(AccountsController): self.append('deductions', row) self.set_unallocated_amount() + def initialize_taxes(self): + for tax in self.get("taxes"): + tax_fields = ["total", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] + + if tax.charge_type != "Actual": + tax_fields.append("tax_amount") + + for fieldname in tax_fields: + tax.set(fieldname, 0.0) + + self.paid_amount_after_tax = self.paid_amount + + def determine_exclusive_rate(self): + if not any((cint(tax.included_in_paid_amount) for tax in self.get("taxes"))): + return + + cumulated_tax_fraction = 0 + total_inclusive_tax_amount_per_qty = 0 + for i, tax in enumerate(self.get("taxes")): + + tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax) + if i==0: + tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item + else: + tax.grand_total_fraction_for_current_item = \ + self.get("taxes")[i-1].grand_total_fraction_for_current_item \ + + tax.tax_fraction_for_current_item + + cumulated_tax_fraction += tax.tax_fraction_for_current_item + + self.paid_amount_after_tax = flt(self.paid_amount/(1+cumulated_tax_fraction)) + def calculate_taxes(self): self.total_taxes_and_charges = 0.0 self.base_total_taxes_and_charges = 0.0 + actual_tax_dict = dict([[tax.idx, flt(tax.tax_amount, tax.precision("tax_amount"))] + for tax in self.get("taxes") if tax.charge_type == "Actual"]) + for i, tax in enumerate(self.get('taxes')): - tax_rate = tax.rate - - # To set row_id by default as previous row. - if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]: - if tax.idx == 1: - frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")) - - if not tax.row_id: - tax.row_id = tax.idx - 1 + current_tax_amount = self.get_current_tax_amount(tax) if tax.charge_type == "Actual": - current_tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) - elif tax.charge_type == "On Paid Amount": - current_tax_amount = (tax_rate / 100.0) * self.paid_amount - elif tax.charge_type == "On Previous Row Amount": - current_tax_amount = (tax_rate / 100.0) * \ - self.get('taxes')[cint(tax.row_id) - 1].tax_amount - - elif tax.charge_type == "On Previous Row Total": - current_tax_amount = (tax_rate / 100.0) * \ - self.get('taxes')[cint(tax.row_id) - 1].total + actual_tax_dict[tax.idx] -= current_tax_amount + if i == len(self.get("taxes")) - 1: + current_tax_amount += actual_tax_dict[tax.idx] tax.tax_amount = current_tax_amount tax.base_tax_amount = tax.tax_amount * self.source_exchange_rate @@ -843,21 +868,68 @@ class PaymentEntry(AccountsController): else: current_tax_amount *= 1.0 - if not tax.included_in_paid_amount: - applicable_tax = current_tax_amount - else: - applicable_tax = 0 - if i == 0: - tax.total = flt(self.paid_amount + applicable_tax, self.precision("total", tax)) + tax.total = flt(self.paid_amount_after_tax + current_tax_amount, self.precision("total", tax)) else: - tax.total = flt(self.get('taxes')[i-1].total + applicable_tax, self.precision("total", tax)) + tax.total = flt(self.get('taxes')[i-1].total + current_tax_amount, self.precision("total", tax)) tax.base_total = tax.total * self.source_exchange_rate self.total_taxes_and_charges += current_tax_amount self.base_total_taxes_and_charges += current_tax_amount * self.source_exchange_rate + if self.get('taxes'): + self.paid_amount_after_tax = self.get('taxes')[-1].base_total + + def get_current_tax_amount(self, tax): + tax_rate = tax.rate + + # To set row_id by default as previous row. + if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]: + if tax.idx == 1: + frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")) + + if not tax.row_id: + tax.row_id = tax.idx - 1 + + if tax.charge_type == "Actual": + current_tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) + elif tax.charge_type == "On Paid Amount": + current_tax_amount = (tax_rate / 100.0) * self.paid_amount_after_tax + elif tax.charge_type == "On Previous Row Amount": + current_tax_amount = (tax_rate / 100.0) * \ + self.get('taxes')[cint(tax.row_id) - 1].tax_amount + + elif tax.charge_type == "On Previous Row Total": + current_tax_amount = (tax_rate / 100.0) * \ + self.get('taxes')[cint(tax.row_id) - 1].total + + return current_tax_amount + + def get_current_tax_fraction(self, tax): + current_tax_fraction = 0 + + if cint(tax.included_in_paid_amount): + tax_rate = tax.rate + + if tax.charge_type == 'Actual': + current_tax_fraction = tax.tax_amount/self.paid_amount_after_tax + elif tax.charge_type == "On Paid Amount": + current_tax_fraction = tax_rate / 100.0 + + elif tax.charge_type == "On Previous Row Amount": + current_tax_fraction = (tax_rate / 100.0) * \ + self.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item + + elif tax.charge_type == "On Previous Row Total": + current_tax_fraction = (tax_rate / 100.0) * \ + self.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item + + if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct": + current_tax_fraction *= -1.0 + + return current_tax_fraction + @frappe.whitelist() def get_outstanding_reference_documents(args): @@ -1426,6 +1498,9 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= pe.apply_tax_withholding_amount = 1 pe.tax_withholding_category = doc.tax_withholding_category + if not pe.advance_tax_account: + pe.advance_tax_account = frappe.db.get_value('Company', pe.company, 'unrealized_profit_loss_account') + return pe def get_bank_cash_account(doc, bank_account): From 60de73b9047c3c27561b9731639472b30b432225 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 9 Jun 2021 13:45:42 +0530 Subject: [PATCH 09/14] fix: Debug test --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 1c4350f8dcb..f0519ed79e0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1017,6 +1017,9 @@ class TestPurchaseInvoice(unittest.TestCase): where voucher_type='Purchase Invoice' and voucher_no=%s order by account asc""", (purchase_invoice.name), as_dict=1) + for i, gle in enumerate(gl_entries): + print(gle.account, gle.debit, gle.credit) + for i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.debit) From bc490e246edfa90aa0b8845028a44fab8b47185a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 9 Jun 2021 14:18:23 +0530 Subject: [PATCH 10/14] fix: Debug tests --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index f0519ed79e0..0683467c7f7 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -991,6 +991,9 @@ class TestPurchaseInvoice(unittest.TestCase): where voucher_type='Payment Entry' and voucher_no=%s order by account asc""", (payment_entry.name), as_dict=1) + for i, gle in enumerate(gl_entries): + print(gle.account, gle.debit, gle.credit) + for i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.debit) From 2924ff830e7203a409ae1ec0e058fea36f8ad030 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 9 Jun 2021 18:26:16 +0530 Subject: [PATCH 11/14] fix: Test case --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 -- .../doctype/purchase_invoice/test_purchase_invoice.py | 8 +------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 83d52fa5f63..df3c6164a7b 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -830,9 +830,7 @@ class PaymentEntry(AccountsController): return cumulated_tax_fraction = 0 - total_inclusive_tax_amount_per_qty = 0 for i, tax in enumerate(self.get("taxes")): - tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax) if i==0: tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 0683467c7f7..10531e045ab 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -991,9 +991,6 @@ class TestPurchaseInvoice(unittest.TestCase): where voucher_type='Payment Entry' and voucher_no=%s order by account asc""", (payment_entry.name), as_dict=1) - for i, gle in enumerate(gl_entries): - print(gle.account, gle.debit, gle.credit) - for i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.debit) @@ -1011,8 +1008,8 @@ class TestPurchaseInvoice(unittest.TestCase): ['_Test Account Cost for Goods Sold - _TC', 30000, 0], ['_Test Account Excise Duty - _TC', 0, 3000], ['Creditors - _TC', 0, 27000], - ['TDS Payable - _TC', 0, 3000], ['TDS Payable - _TC', 3000, 0] + ['TDS Payable - _TC', 0, 3000], ] gl_entries = frappe.db.sql("""select account, debit, credit @@ -1020,9 +1017,6 @@ class TestPurchaseInvoice(unittest.TestCase): where voucher_type='Purchase Invoice' and voucher_no=%s order by account asc""", (purchase_invoice.name), as_dict=1) - for i, gle in enumerate(gl_entries): - print(gle.account, gle.debit, gle.credit) - for i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.debit) From 88c0cd6f7a7fe3ed8bdb42d76a92804155806e76 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 9 Jun 2021 22:55:10 +0530 Subject: [PATCH 12/14] fix: Add multiple fixes --- .../advance_taxes_and_charges.json | 4 ++-- erpnext/accounts/doctype/payment_entry/payment_entry.js | 2 +- erpnext/accounts/doctype/payment_entry/payment_entry.json | 7 +++++-- erpnext/accounts/doctype/payment_entry/payment_entry.py | 5 ++++- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 3 --- .../doctype/purchase_invoice/test_purchase_invoice.py | 1 + .../purchase_taxes_and_charges.json | 4 ++-- .../sales_taxes_and_charges/sales_taxes_and_charges.json | 4 ++-- erpnext/controllers/accounts_controller.py | 5 ++++- 9 files changed, 21 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json index 3e4e679c913..4d634994319 100644 --- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json +++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json @@ -160,7 +160,7 @@ "default": "0", "fieldname": "included_in_paid_amount", "fieldtype": "Check", - "label": "Included In Paid Amount" + "label": "Considered In Paid Amount" }, { "fieldname": "allocated_amount", @@ -186,7 +186,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-06-08 07:04:44.287002", + "modified": "2021-06-09 11:46:58.373170", "modified_by": "Administrator", "module": "Accounts", "name": "Advance Taxes and Charges", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 6a3b717b12f..939f3546ff6 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -1133,7 +1133,7 @@ frappe.ui.form.on('Payment Entry', { let tax_rate = tax.rate; if (tax.charge_type == "Actual") { - current_tax_fraction = tax.tax_amount/frm.doc.paid_amount_after_tax; + current_tax_fraction = tax.tax_amount/(frm.doc.paid_amount_after_tax + frm.doc.tax_amount); } else if(tax.charge_type == "On Paid Amount") { current_tax_fraction = (tax_rate / 100.0); } else if(tax.charge_type == "On Previous Row Amount") { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 0b4178a547e..54623dd6cd5 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -681,13 +681,16 @@ "hide_border": 1 }, { + "depends_on": "eval:doc.apply_tax_withholding_amount", + "description": "Provisional tax account for advance tax. Taxes are parked in this account until payments are allocated to invoices", "fieldname": "advance_tax_account", "fieldtype": "Link", "label": "Advance Tax Account", - "mandatory_depends_on": "doc.base_total_taxes_and_charges", + "mandatory_depends_on": "eval:doc.apply_tax_withholding_amount", "options": "Account" }, { + "depends_on": "eval:doc.received_amount", "fieldname": "received_amount_after_tax", "fieldtype": "Currency", "label": "Received Amount After Tax", @@ -704,7 +707,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-05-31 01:54:18.378910", + "modified": "2021-06-09 11:55:04.215050", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index df3c6164a7b..17a78a2f875 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -395,6 +395,9 @@ class PaymentEntry(AccountsController): if not self.apply_tax_withholding_amount: return + if not self.advance_tax_account: + frappe.throw(_("Advance TDS account is mandatory for advance TDS deduction")) + reference_doclist = [] net_total = self.paid_amount included_in_paid_amount = 0 @@ -911,7 +914,7 @@ class PaymentEntry(AccountsController): tax_rate = tax.rate if tax.charge_type == 'Actual': - current_tax_fraction = tax.tax_amount/self.paid_amount_after_tax + current_tax_fraction = tax.tax_amount/ (self.paid_amount_after_tax + tax.tax_amount) elif tax.charge_type == "On Paid Amount": current_tax_fraction = tax_rate / 100.0 diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 934c731cf13..0ee0bc7e11f 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -68,9 +68,6 @@ class PurchaseInvoice(BuyingController): super(PurchaseInvoice, self).validate() - # apply tax withholding only if checked and applicable - self.set_tax_withholding() - if not self.is_return: self.po_required() self.pr_required() diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 10531e045ab..3ce568a2b6b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -975,6 +975,7 @@ class TestPurchaseInvoice(unittest.TestCase): # Create Payment Entry Against the order payment_entry = get_payment_entry(dt='Purchase Order', dn=po.name) + payment_entry.paid_from = 'Cash - _TC' payment_entry.save() payment_entry.submit() diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json index f6703315fa7..9b07645ccc9 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json @@ -221,13 +221,13 @@ "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry", "fieldname": "included_in_paid_amount", "fieldtype": "Check", - "label": "Included In Paid Amount" + "label": "Considered In Paid Amount" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2021-05-31 03:41:38.298937", + "modified": "2021-06-09 11:48:25.335733", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Taxes and Charges", diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json index 36fd634b507..170d34e651c 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json @@ -198,14 +198,14 @@ "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry", "fieldname": "included_in_paid_amount", "fieldtype": "Check", - "label": "Included In Paid Amount" + "label": "Considered In Paid Amount" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-05-31 05:40:32.856780", + "modified": "2021-06-09 11:48:04.691596", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Taxes and Charges", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 333fd171e42..52b7b4492ac 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -116,6 +116,8 @@ class AccountsController(TransactionBase): if self.doctype == 'Purchase Invoice': self.calculate_paid_amount() + # apply tax withholding only if checked and applicable + self.set_tax_withholding() if self.doctype in ['Purchase Invoice', 'Sales Invoice']: pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid" @@ -737,7 +739,8 @@ class AccountsController(TransactionBase): def allocate_advance_taxes(self, gl_entries): tax_map = self.get_tax_map() for pe in self.get("advances"): - if pe.reference_type == "Payment Entry": + if pe.reference_type == "Payment Entry" and \ + frappe.db.get_value('Payment Entry', pe.reference_name, 'advance_tax_account'): pe = frappe.get_doc("Payment Entry", pe.reference_name) for tax in pe.get("taxes"): account_currency = get_account_currency(tax.account_head) From 1e898c0f5bec8d2a5aebeda55dc154fde46ff240 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 10 Jun 2021 10:34:49 +0530 Subject: [PATCH 13/14] fix: Failing test case --- .../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 3ce568a2b6b..c706b440d26 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1009,8 +1009,8 @@ class TestPurchaseInvoice(unittest.TestCase): ['_Test Account Cost for Goods Sold - _TC', 30000, 0], ['_Test Account Excise Duty - _TC', 0, 3000], ['Creditors - _TC', 0, 27000], - ['TDS Payable - _TC', 3000, 0] - ['TDS Payable - _TC', 0, 3000], + ['TDS Payable - _TC', 3000, 0], + ['TDS Payable - _TC', 0, 3000] ] gl_entries = frappe.db.sql("""select account, debit, credit From bcbb1c68b4b74e8127d1d845362d3d00dd0845b1 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 10 Jun 2021 12:26:21 +0530 Subject: [PATCH 14/14] fix: GL Entry ordering --- .../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index c706b440d26..82c717ad985 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1000,6 +1000,7 @@ class TestPurchaseInvoice(unittest.TestCase): # Create Purchase Invoice against Purchase Order purchase_invoice = get_mapped_purchase_invoice(po.name) purchase_invoice.allocate_advances_automatically = 1 + purchase_invoice.items[0].expense_account = '_Test Account Cost for Goods Sold - _TC' purchase_invoice.save() purchase_invoice.submit() @@ -1009,8 +1010,7 @@ class TestPurchaseInvoice(unittest.TestCase): ['_Test Account Cost for Goods Sold - _TC', 30000, 0], ['_Test Account Excise Duty - _TC', 0, 3000], ['Creditors - _TC', 0, 27000], - ['TDS Payable - _TC', 3000, 0], - ['TDS Payable - _TC', 0, 3000] + ['TDS Payable - _TC', 3000, 3000] ] gl_entries = frappe.db.sql("""select account, debit, credit