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"),