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..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 @@ -254,9 +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_map = {} for row in self.get("items"): taxable_value_map[row.name] = row.taxable_value + item_qty_map[row.name] = row.qty for tax in self.taxes: if not tax.tax_amount: @@ -278,33 +280,43 @@ def validate_taxes(self): [input_accounts.cess_non_advol_account], tax ) - if tax.charge_type == "Actual": + if tax.charge_type != "Actual": + continue - 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"), - ) + 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"), + ) + + # validating total tax + total_tax = 0 + is_non_cess_advol = ( + tax.account_head == input_accounts.cess_non_advol_account + ) - # 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 + 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 - tax_difference = abs(total_tax - tax.tax_amount) + 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_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 diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index 9cbd974257..7d440e7694 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -124,10 +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") for row in doc.items: item_key = row.item_code or row.item_name item_taxable_values[item_key] += row.taxable_value + item_qty_map[item_key] += row.qty for row in doc.taxes: if row.account_head not in gst_accounts: @@ -150,15 +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. - item_taxable_value = item_taxable_values.get(item_name, 0) - tax_difference = abs(item_taxable_value * tax_rate / 100 - tax_amount) + + is_cess_non_advol = row.account_head in cess_non_advol_account + multiplier = ( + 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) 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} as computed for Item {2}" - " is incorrect. Try setting the Charge Type to On Net Total." - ).format(row.idx, tax_amount, bold(item_name)) + " is incorrect. Try setting the Charge Type to {3}" + ).format(row.idx, tax_amount, bold(item_name), correct_charge_type) ) @@ -452,12 +466,12 @@ 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( _( - "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"),