From eea25adb9f9c91740d95e2968e69f3e6e29bf72d Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Wed, 27 Mar 2024 16:28:26 +0530 Subject: [PATCH 1/4] fix: validate for cess non-advol --- .../doctype/bill_of_entry/bill_of_entry.py | 52 ++++++++++++++----- .../gst_india/overrides/transaction.py | 36 +++++++++---- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py index a4b7ebe07e..0ef0a455a3 100644 --- a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py +++ b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py @@ -24,6 +24,7 @@ validate_charge_type_for_cess_non_advol_accounts, ) from india_compliance.gst_india.utils import get_gst_accounts_by_type +from india_compliance.gst_india.utils.__init__ import get_gst_accounts_by_tax_type class BOEGSTDetails(ItemGSTDetails): @@ -252,11 +253,17 @@ def validate_purchase_invoice(self): ) def validate_taxes(self): + cess_non_advol_account = get_gst_accounts_by_tax_type( + self.company, "cess_non_advol" + ) + input_accounts = get_gst_accounts_by_type(self.company, "Input", throw=True) taxable_value_map = {} + item_qty = {} for row in self.get("items"): taxable_value_map[row.name] = row.taxable_value + item_qty[row.name] = row.qty for tax in self.taxes: if not tax.tax_amount: @@ -291,20 +298,37 @@ def validate_taxes(self): ) # validating total tax - total_tax = 0 - for item, rate in item_wise_tax_rates.items(): - item_taxable_value = taxable_value_map.get(item, 0) - total_tax += item_taxable_value * rate / 100 - - tax_difference = abs(total_tax - tax.tax_amount) - - if tax_difference > 1: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" - " is incorrect. Try setting the Charge Type to On Net Total." - ).format(row.idx, tax.tax_amount) - ) + if tax.account_head in cess_non_advol_account: + total_tax = 0 + for item, rate in item_wise_tax_rates.items(): + qty = item_qty.get(item, 0) + total_tax += qty * rate + + tax_difference = abs(total_tax - tax.tax_amount) + + if tax_difference > 1: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" + " is incorrect. Try setting the Charge Type to On Net Total." + ).format(row.idx, tax.tax_amount) + ) + + else: + total_tax = 0 + for item, rate in item_wise_tax_rates.items(): + item_taxable_value = taxable_value_map.get(item, 0) + total_tax += item_taxable_value * rate / 100 + + tax_difference = abs(total_tax - tax.tax_amount) + + if tax_difference > 1: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" + " is incorrect. Try setting the Charge Type to On Net Total." + ).format(row.idx, tax.tax_amount) + ) def get_gl_entries(self): # company_currency is required by get_gl_dict diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index cdbf91c4f5..e968c987d5 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -125,9 +125,13 @@ def validate_item_wise_tax_detail(doc, gst_accounts): item_taxable_values = defaultdict(float) + cess_non_advol_account = get_gst_accounts_by_tax_type(doc.company, "cess_non_advol") + item_qty = defaultdict(float) + for row in doc.items: item_key = row.item_code or row.item_name item_taxable_values[item_key] += row.taxable_value + item_qty[item_key] += row.qty for row in doc.taxes: if row.account_head not in gst_accounts: @@ -150,16 +154,28 @@ def validate_item_wise_tax_detail(doc, gst_accounts): # Sales Invoice is created with manual tax amount. So, when a sales return is created, # the tax amount is not recalculated, causing the issue. - item_taxable_value = item_taxable_values.get(item_name, 0) - tax_difference = abs(item_taxable_value * tax_rate / 100 - tax_amount) + if row.account_head in cess_non_advol_account: + total_qty = item_qty.get(item_name, 0) + tax_difference = abs(total_qty * tax_rate - tax_amount) + + if tax_difference > 1: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1} as computed for Item {2}" + " is incorrect. Try setting the Charge Type to On Net Total.hello sir ji" + ).format(row.idx, tax_amount, bold(item_name)) + ) + else: + item_taxable_value = item_taxable_values.get(item_name, 0) + tax_difference = abs(item_taxable_value * tax_rate / 100 - tax_amount) - if tax_difference > 1: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1} as computed for Item {2}" - " is incorrect. Try setting the Charge Type to On Net Total." - ).format(row.idx, tax_amount, bold(item_name)) - ) + if tax_difference > 1: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1} as computed for Item {2}" + " is incorrect. Try setting the Charge Type to On Net Total." + ).format(row.idx, tax_amount, bold(item_name)) + ) def get_tds_amount(doc): @@ -452,7 +468,7 @@ def validate_charge_type_for_cess_non_advol_accounts(cess_non_advol_accounts, ta ) if ( - tax_row.charge_type != "On Item Quantity" + tax_row.charge_type not in ["On Item Quantity", "Actual"] and tax_row.account_head in cess_non_advol_accounts ): frappe.throw( From d25d28be31aef81a070f1252d0f274dc309d76c1 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Thu, 28 Mar 2024 10:41:39 +0530 Subject: [PATCH 2/4] fix: remove duplicate code --- .../doctype/bill_of_entry/bill_of_entry.py | 59 ++++++++----------- .../gst_india/overrides/transaction.py | 41 ++++++------- 2 files changed, 42 insertions(+), 58 deletions(-) diff --git a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py index 0ef0a455a3..a595f55fce 100644 --- a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py +++ b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py @@ -24,7 +24,6 @@ validate_charge_type_for_cess_non_advol_accounts, ) from india_compliance.gst_india.utils import get_gst_accounts_by_type -from india_compliance.gst_india.utils.__init__ import get_gst_accounts_by_tax_type class BOEGSTDetails(ItemGSTDetails): @@ -253,10 +252,6 @@ def validate_purchase_invoice(self): ) def validate_taxes(self): - cess_non_advol_account = get_gst_accounts_by_tax_type( - self.company, "cess_non_advol" - ) - input_accounts = get_gst_accounts_by_type(self.company, "Input", throw=True) taxable_value_map = {} item_qty = {} @@ -298,37 +293,29 @@ def validate_taxes(self): ) # validating total tax - if tax.account_head in cess_non_advol_account: - total_tax = 0 - for item, rate in item_wise_tax_rates.items(): - qty = item_qty.get(item, 0) - total_tax += qty * rate - - tax_difference = abs(total_tax - tax.tax_amount) - - if tax_difference > 1: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" - " is incorrect. Try setting the Charge Type to On Net Total." - ).format(row.idx, tax.tax_amount) - ) - - else: - total_tax = 0 - for item, rate in item_wise_tax_rates.items(): - item_taxable_value = taxable_value_map.get(item, 0) - total_tax += item_taxable_value * rate / 100 - - tax_difference = abs(total_tax - tax.tax_amount) - - if tax_difference > 1: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" - " is incorrect. Try setting the Charge Type to On Net Total." - ).format(row.idx, tax.tax_amount) - ) + total_tax = 0 + for item, rate in item_wise_tax_rates.items(): + multiplier = ( + item_qty.get(item, 0) + if tax.account_head in input_accounts.cess_non_advol_account + else taxable_value_map.get(item, 0) / 100 + ) + total_tax += multiplier * rate + + tax_difference = abs(total_tax - tax.tax_amount) + + column = ( + "cess non-advol" + if tax.account_head in input_accounts.cess_non_advol_account + else "Net Total" + ) + if tax_difference > 1: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" + " is incorrect. Try setting the Charge Type to On {2}." + ).format(row.idx, tax.tax_amount, column) + ) def get_gl_entries(self): # company_currency is required by get_gl_dict diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index e968c987d5..b28387e121 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -154,28 +154,25 @@ def validate_item_wise_tax_detail(doc, gst_accounts): # Sales Invoice is created with manual tax amount. So, when a sales return is created, # the tax amount is not recalculated, causing the issue. - if row.account_head in cess_non_advol_account: - total_qty = item_qty.get(item_name, 0) - tax_difference = abs(total_qty * tax_rate - tax_amount) - - if tax_difference > 1: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1} as computed for Item {2}" - " is incorrect. Try setting the Charge Type to On Net Total.hello sir ji" - ).format(row.idx, tax_amount, bold(item_name)) - ) - else: - item_taxable_value = item_taxable_values.get(item_name, 0) - tax_difference = abs(item_taxable_value * tax_rate / 100 - tax_amount) - - if tax_difference > 1: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1} as computed for Item {2}" - " is incorrect. Try setting the Charge Type to On Net Total." - ).format(row.idx, tax_amount, bold(item_name)) - ) + multiplier = ( + item_qty.get(item_name, 0) + if row.account_head in cess_non_advol_account + else item_taxable_values.get(item_name, 0) / 100 + ) + tax_difference = abs(multiplier * tax_rate - tax_amount) + + column = ( + "cess non-advol" + if row.account_head in cess_non_advol_account + else "Net Total" + ) + if tax_difference > 1: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" + " is incorrect. Try setting the Charge Type to On {2}." + ).format(row.idx, tax_amount, column) + ) def get_tds_amount(doc): From 1f971dded98688deab7cd54b7ee075a2a457ce7d Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 29 Mar 2024 18:53:09 +0530 Subject: [PATCH 3/4] fix: changes as per view --- .../doctype/bill_of_entry/bill_of_entry.py | 18 ++++++------- .../gst_india/overrides/transaction.py | 27 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py index a595f55fce..09babbf74b 100644 --- a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py +++ b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py @@ -254,11 +254,11 @@ def validate_purchase_invoice(self): def validate_taxes(self): input_accounts = get_gst_accounts_by_type(self.company, "Input", throw=True) taxable_value_map = {} - item_qty = {} + item_qty_map = {} for row in self.get("items"): taxable_value_map[row.name] = row.taxable_value - item_qty[row.name] = row.qty + item_qty_map[row.name] = row.qty for tax in self.taxes: if not tax.tax_amount: @@ -294,22 +294,22 @@ def validate_taxes(self): # validating total tax total_tax = 0 + is_non_cess_advol = ( + tax.account_head == input_accounts.cess_non_advol_account + ) + for item, rate in item_wise_tax_rates.items(): multiplier = ( - item_qty.get(item, 0) - if tax.account_head in input_accounts.cess_non_advol_account + item_qty_map.get(item, 0) + if is_non_cess_advol else taxable_value_map.get(item, 0) / 100 ) total_tax += multiplier * rate tax_difference = abs(total_tax - tax.tax_amount) - column = ( - "cess non-advol" - if tax.account_head in input_accounts.cess_non_advol_account - else "Net Total" - ) if tax_difference > 1: + column = "On Item Quantity" if is_non_cess_advol else "Net Total" frappe.throw( _( "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index b28387e121..bab5a2d5af 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -124,14 +124,14 @@ def validate_item_wise_tax_detail(doc, gst_accounts): return item_taxable_values = defaultdict(float) + item_qty_map = defaultdict(float) cess_non_advol_account = get_gst_accounts_by_tax_type(doc.company, "cess_non_advol") - item_qty = defaultdict(float) for row in doc.items: item_key = row.item_code or row.item_name item_taxable_values[item_key] += row.taxable_value - item_qty[item_key] += row.qty + item_qty_map[item_key] += row.qty for row in doc.taxes: if row.account_head not in gst_accounts: @@ -154,24 +154,25 @@ def validate_item_wise_tax_detail(doc, gst_accounts): # Sales Invoice is created with manual tax amount. So, when a sales return is created, # the tax amount is not recalculated, causing the issue. + + is_cess_non_advol = row.account_head in cess_non_advol_account multiplier = ( - item_qty.get(item_name, 0) - if row.account_head in cess_non_advol_account + item_qty_map.get(item_name, 0) + if is_cess_non_advol else item_taxable_values.get(item_name, 0) / 100 ) tax_difference = abs(multiplier * tax_rate - tax_amount) - column = ( - "cess non-advol" - if row.account_head in cess_non_advol_account - else "Net Total" - ) if tax_difference > 1: + correct_charge_type = ( + "On Item Quantity" if is_cess_non_advol else "On Net Total" + ) + frappe.throw( _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" - " is incorrect. Try setting the Charge Type to On {2}." - ).format(row.idx, tax_amount, column) + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1} as computed for Item {2}" + " is incorrect. Try setting the Charge Type to {3}" + ).format(row.idx, tax_amount, bold(item_name), correct_charge_type) ) @@ -470,7 +471,7 @@ def validate_charge_type_for_cess_non_advol_accounts(cess_non_advol_accounts, ta ): frappe.throw( _( - "Row #{0}: Charge Type must be On Item Quantity" + "Row #{0}: Charge Type must be On Item Quantity / Actual" " as it is a Cess Non Advol Account" ).format(tax_row.idx), title=_("Invalid Charge Type"), From 00a72e562f9b7454c3472dff2d92326eb43f9eb9 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Thu, 11 Apr 2024 12:01:57 +0530 Subject: [PATCH 4/4] chore: fix type, less nesting --- .../doctype/bill_of_entry/bill_of_entry.py | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py index 09babbf74b..9241025e09 100644 --- a/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py +++ b/india_compliance/gst_india/doctype/bill_of_entry/bill_of_entry.py @@ -280,42 +280,43 @@ def validate_taxes(self): [input_accounts.cess_non_advol_account], tax ) - if tax.charge_type == "Actual": - - item_wise_tax_rates = json.loads(tax.item_wise_tax_rates) - if not item_wise_tax_rates: - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, this would" - " not compute item taxes, and your further reporting will be affected." - ).format(tax.idx), - title=_("Invalid Charge Type"), - ) + if tax.charge_type != "Actual": + continue - # validating total tax - total_tax = 0 - is_non_cess_advol = ( - tax.account_head == input_accounts.cess_non_advol_account + item_wise_tax_rates = json.loads(tax.item_wise_tax_rates) + if not item_wise_tax_rates: + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, this would" + " not compute item taxes, and your further reporting will be affected." + ).format(tax.idx), + title=_("Invalid Charge Type"), ) - for item, rate in item_wise_tax_rates.items(): - multiplier = ( - item_qty_map.get(item, 0) - if is_non_cess_advol - else taxable_value_map.get(item, 0) / 100 - ) - total_tax += multiplier * rate + # validating total tax + total_tax = 0 + is_non_cess_advol = ( + tax.account_head == input_accounts.cess_non_advol_account + ) - tax_difference = abs(total_tax - tax.tax_amount) + for item, rate in item_wise_tax_rates.items(): + multiplier = ( + item_qty_map.get(item, 0) + if is_non_cess_advol + else taxable_value_map.get(item, 0) / 100 + ) + total_tax += multiplier * rate - if tax_difference > 1: - column = "On Item Quantity" if is_non_cess_advol else "Net Total" - frappe.throw( - _( - "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" - " is incorrect. Try setting the Charge Type to On {2}." - ).format(row.idx, tax.tax_amount, column) - ) + tax_difference = abs(total_tax - tax.tax_amount) + + if tax_difference > 1: + column = "On Item Quantity" if is_non_cess_advol else "On Net Total" + frappe.throw( + _( + "Tax Row #{0}: Charge Type is set to Actual. However, Tax Amount {1}" + " is incorrect. Try setting the Charge Type to {2}." + ).format(row.idx, tax.tax_amount, column) + ) def get_gl_entries(self): # company_currency is required by get_gl_dict