Skip to content

fix: enhance item-wise tax detail handling and validation in GST transactions#3807

Merged
ljain112 merged 4 commits intoresilient-tech:developfrom
ljain112:fix-item-wise-tax-details
Nov 21, 2025
Merged

fix: enhance item-wise tax detail handling and validation in GST transactions#3807
ljain112 merged 4 commits intoresilient-tech:developfrom
ljain112:fix-item-wise-tax-details

Conversation

@ljain112
Copy link
Copy Markdown
Member

@ljain112 ljain112 commented Nov 21, 2025

depends on: frappe/erpnext#48692
depends_on: frappe/erpnext#50658

Summary by CodeRabbit

  • New Features

    • Documents now include explicit item-wise tax details for item-level tax processing.
  • Bug Fixes

    • Validation messages for item-wise tax mismatches made more specific.
    • Detection of missing rates/inconsistent amounts for actual charge-type tightened.
  • Improvements

    • Tax aggregation, rounding and propagation adjusted to work reliably with item-level tax structures.
  • Tests

    • Tests updated to reflect and assert the new item-wise tax detail behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 21, 2025

Walkthrough

Replace item-code keyed item-wise GST handling with item-name keyed structures across transaction processing, tax utilities, and post-install/patched compilation flows; adjust validation to compare provided item-wise tax details against computed taxes and update tests accordingly.

Changes

Cohort / File(s) Summary
Tests
india_compliance/gst_india/overrides/test_transaction.py
Adjusted test to set doc._item_wise_tax_details as a list of dicts and updated expected ValidationError text to "Item Wise Tax Details do not match with Taxes and Charges at the following rows...".
Transaction overrides
india_compliance/gst_india/overrides/transaction.py
Switched processing from item-code keyed tax details to item-name keyed _item_wise_tax_details. Added/changed methods: set_temp_item_wise_tax_detail_object, build_item_wise_tax_detail_from_data (stubs), get_item_name_wise_tax_details, get_tax_detail_by_item_name, set_item_defaults; updated get()/update flows, validation path (checks row.amount without row.rate for "Actual"), rounding and tax-difference propagation to use item-name mappings.
Tax utils (controller)
india_compliance/gst_india/utils/taxes_controller.py
Removed get_item_key. Added set_temp_item_wise_tax_detail_object and build_item_wise_tax_detail_from_data in CustomItemGSTDetails; these build a temporary _item_wise_tax_details on documents and translate JSON-like inputs into per-item_name tax structures.
Post-install patch
india_compliance/patches/post_install/improve_item_tax_template.py
Added get_item_taxes_for_docs(docs, doctype); extended _update_gst_details and compile_docs to accept item_taxes and populate item_wise_tax_details on compiled documents.
v14 patch update
india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
Updated compile_docs invocation to pass an empty list as the new item_taxes argument; minor formatting tweak.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Patch as compile_docs
  participant Doc as Document
  participant Utils as TaxesController
  participant ItemGST as ItemGSTDetails
  Note right of Patch `#f6f3e8`: New param item_taxes added
  Patch->>Doc: attach item_wise_tax_details (from item_taxes)
  Doc->>Utils: set_temp_item_wise_tax_detail_object()
  Utils->>Doc: build `_item_wise_tax_details` keyed by item_name
  Doc->>ItemGST: get(docs, doctype, company)
  ItemGST->>ItemGST: get_item_name_wise_tax_details()
  ItemGST->>ItemGST: set_item_defaults() & compute taxes per item_name
  ItemGST->>Doc: set_item_name_wise_tax_details() and validate
  alt mismatch detected
    ItemGST->>Doc: raise ValidationError("Item Wise Tax Details do not match...")
  else success
    ItemGST->>Doc: aggregate rounding & tax differences
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to:
    • correctness of item_name vs item_code mappings and lookups in transaction.py
    • construction and shape of _item_wise_tax_details in taxes_controller.py
    • all call sites of compile_docs now accepting an item_taxes argument (patch files and other integrations)
    • tests asserting the new ValidationError message

Possibly related PRs

Suggested labels

squash, backport version-14-hotfix, backport version-15-hotfix

Suggested reviewers

  • vorasmit
  • karm1000

Poem

🐇 I hopped through ledgers, name by name,

swapped keys for clarity in the tax-time game,
rows now match and tests align,
nibbling carrots for a cleaner design,
a tiny thump for smoother GST.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.81% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main changes: enhancing item-wise tax detail handling and validation in GST transactions, which aligns with the substantial refactoring across multiple files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06376cd and 1cec786.

📒 Files selected for processing (1)
  • india_compliance/gst_india/overrides/transaction.py (7 hunks)
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: ljain112
Repo: resilient-tech/india-compliance PR: 3807
File: india_compliance/gst_india/overrides/transaction.py:142-157
Timestamp: 2025-11-21T08:53:26.295Z
Learning: In the india_compliance/gst_india/overrides/transaction.py file, the `_item_wise_tax_details` field used in `validate_item_wise_tax_detail()` is populated from ERPNext (not from within the India Compliance codebase) before validation runs, as part of cross-repository changes.
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3399
File: india_compliance/gst_india/utils/gstr_1/test_gstr_1_books_data.py:791-822
Timestamp: 2025-05-29T15:22:04.761Z
Learning: In the india_compliance test suite, the IntegrationTestCase framework automatically handles database rollbacks after test completion, which means functions that modify global state (like GST Settings and Item Tax Templates) in setUpClass won't persist beyond the test run and don't require manual cleanup.
📚 Learning: 2025-11-21T08:53:26.295Z
Learnt from: ljain112
Repo: resilient-tech/india-compliance PR: 3807
File: india_compliance/gst_india/overrides/transaction.py:142-157
Timestamp: 2025-11-21T08:53:26.295Z
Learning: In the india_compliance/gst_india/overrides/transaction.py file, the `_item_wise_tax_details` field used in `validate_item_wise_tax_detail()` is populated from ERPNext (not from within the India Compliance codebase) before validation runs, as part of cross-repository changes.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-10-01T10:54:11.096Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3709
File: india_compliance/gst_india/utils/exporter.py:174-174
Timestamp: 2025-10-01T10:54:11.096Z
Learning: In india_compliance/gst_india/doctype/gstr_1/gstr_1_export.py, FIELD_TRANSFORMATIONS dictionary contains lambdas that are only called internally by DataProcessor.apply_transformations() with a single argument. These are separate from header transforms used with ExcelExporter.insert_data() which accept two arguments (value, row).

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-25T08:19:02.607Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3354
File: india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py:278-281
Timestamp: 2025-06-25T08:19:02.607Z
Learning: In the Summary of ITC Availed report (india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py), the summary dictionaries created by get_initial_summary() are never empty - they always contain tax field keys (igst_amount, cgst_amount, sgst_amount, cess_amount) with 0 values, so checking for empty dictionaries is unnecessary.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-04-25T10:12:24.584Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/account_wise_summary/account_wise_summary.py:81-87
Timestamp: 2025-04-25T10:12:24.584Z
Learning: When processing taxes in GST India reports, charges after GST rows with charge_type "On Previous Row Total" should not be used to compute taxable value, so a break statement is used to exit the tax processing loop once such a row is encountered.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-05-26T03:16:30.230Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py:0-0
Timestamp: 2025-05-26T03:16:30.230Z
Learning: In GST account-wise summary reports, the filtering logic `doc.company_gstin != IfNull(doc[counterparty_gstin_field], "")` is intentionally designed to exclude internal transfers (where company GSTIN equals party GSTIN) while including transactions with unregistered parties (empty GSTIN). Internal transfers are excluded as they are only for internal reporting purposes like stock transfers between branches.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-25T08:16:18.010Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3354
File: india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py:309-310
Timestamp: 2025-06-25T08:16:18.010Z
Learning: In the Summary of ITC Availed report (india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py), creating both a main entry and an additional indented entry for categories without subcategories is by design and intentional behavior for the report structure.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-07-22T11:45:43.432Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3532
File: india_compliance/gst_india/utils/e_waybill.py:327-336
Timestamp: 2025-07-22T11:45:43.432Z
Learning: In the e-waybill update functions (india_compliance/gst_india/utils/e_waybill.py), fields like place_of_change and state use hardcoded "-" values in old_values dictionaries because these values are not stored in the system, so there's no way to retrieve the actual previous values.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-19T08:21:29.308Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3451
File: india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_export.py:287-288
Timestamp: 2025-06-19T08:21:29.308Z
Learning: In GSTR-1 export code (india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_export.py), date fields like invoice date (DOC_DATE) and shipping bill date (SHIPPING_BILL_DATE) are mandatory by GST regulations and must exist, so transform functions using strftime() don't need None checks.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-09-30T13:12:35.995Z
Learnt from: ljain112
Repo: resilient-tech/india-compliance PR: 3691
File: india_compliance/gst_india/report/gst_balance/gst_balance.py:303-306
Timestamp: 2025-09-30T13:12:35.995Z
Learning: In the GST Balance Report (india_compliance/gst_india/report/gst_balance/gst_balance.py), the finance_book filter is intentionally designed to always include entries with empty or null finance_book values, even when a specific finance book is selected. This allows the report to show both entries specific to the selected finance book and general entries without a finance book assignment.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-05-29T15:22:04.761Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3399
File: india_compliance/gst_india/utils/gstr_1/test_gstr_1_books_data.py:791-822
Timestamp: 2025-05-29T15:22:04.761Z
Learning: In the india_compliance test suite, the IntegrationTestCase framework automatically handles database rollbacks after test completion, which means functions that modify global state (like GST Settings and Item Tax Templates) in setUpClass won't persist beyond the test run and don't require manual cleanup.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-20T11:11:54.124Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3459
File: india_compliance/gst_india/report/hsn_wise_summary_of_inward_supplies/hsn_wise_summary_of_inward_supplies.js:50-59
Timestamp: 2025-06-20T11:11:54.124Z
Learning: In the India Compliance codebase, for convenience features like automatic checkbox setting in report filters, extensive error handling may not be necessary if users can still manually control the feature when the automatic functionality fails.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-25T08:19:20.439Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3354
File: india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py:272-274
Timestamp: 2025-06-25T08:19:20.439Z
Learning: In the Summary of ITC Availed report (india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py), the summary dictionary is initialized with all valid categories containing tax field dictionaries with zero values, so summary.get(category) will never return an empty dictionary - only a populated dictionary or None.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-04-25T11:12:59.799Z
Learnt from: Ninad1306
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py:18-20
Timestamp: 2025-04-25T11:12:59.799Z
Learning: In India Compliance GST reports, date_range is defined as a mandatory filter in the report configuration, making additional defensive coding for its presence unnecessary as the Frappe framework enforces required filters before calling the execute function.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-11-11T12:44:44.690Z
Learnt from: ljain112
Repo: resilient-tech/india-compliance PR: 3784
File: india_compliance/gst_india/client_scripts/company.js:25-28
Timestamp: 2025-11-11T12:44:44.690Z
Learning: In india_compliance, when using erpnext.company.set_custom_query(frm, [field_name, filters]) in Company doctype client scripts, the function automatically adds company and is_group filters. The filters object parameter should only contain additional filters beyond these defaults (e.g., root_type). For default_gst_expense_account, no root_type filter is needed, so an empty object {} is passed.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
🧬 Code graph analysis (1)
india_compliance/gst_india/overrides/transaction.py (1)
india_compliance/gst_india/utils/taxes_controller.py (3)
  • build_item_wise_tax_detail_from_data (61-82)
  • set_temp_item_wise_tax_detail_object (37-59)
  • tax_amount_field (23-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Python Unit Tests
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (8)
india_compliance/gst_india/overrides/transaction.py (8)

142-157: LGTM! Validation logic correctly handles item-wise tax details.

The validation properly checks for "Actual" charge types with amount but no rate, which would break item-level tax computation. Based on learnings, _item_wise_tax_details is populated from ERPNext before this validation runs.


1191-1217: Code structure is appropriate for processing temporary tax details.

The variables item, tax_row are extracted from _item_wise_tax_details structure and used multiple times (lines 1192-1193, 1195, 1198, 1203, 1211-1217), justifying the variable extraction. The data structure differs from the persisted item_wise_tax_details used in get_item_name_wise_tax_details() (line 1275+), which uses string keys item_row and tax_row instead of object references.


1181-1181: Good addition: set_item_defaults() ensures clean initialization.

Calling set_item_defaults() at the start of set_item_name_wise_tax_details() ensures all items begin with zeroed GST fields, preventing stale values from affecting calculations. This is a defensive improvement over the previous approach.

Also applies to: 1231-1233


1183-1187: Correct handling of tax rounding differences.

The logic properly:

  1. Calculates expected tax totals from tax rows (lines 1183-1187)
  2. Subtracts computed per-item amounts (line 1209)
  3. Applies remaining rounding differences to the last taxable item (lines 1224-1229)

This ensures tax amounts reconcile despite rounding at the item level.

Also applies to: 1209-1209, 1224-1229


1235-1311: Well-structured method for building tax details from persisted data.

The method correctly:

  • Builds lookup maps for items and taxes (lines 1256-1270)
  • Processes persisted item_wise_tax_details structure with string keys (lines 1275-1306)
  • Includes defensive checks for missing items/taxes (lines 1280-1281)
  • Handles rounding differences consistently with the update path (lines 1307-1309)

The use of item.name as the key aligns with the PR's shift to item-name based processing.


1313-1321: LGTM! Method correctly uses item-name based key.

The method properly retrieves tax details using item.name as the key, aligning with the broader refactoring from item-code to item-name based processing.


1372-1376: Good defensive improvement: added null safety.

The null check at lines 1373-1374 prevents AttributeError if row is None, making the method more robust. This is especially important given it's called from multiple locations that process both temporary and persisted structures.


1400-1406: Stub methods are correct for the custom controller pattern.

These empty methods serve as extension points for custom tax controllers (like CustomItemGSTDetails in taxes_controller.py). The base class intentionally provides no-op behavior, allowing subclasses to implement custom data conversion logic when needed. Based on learnings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py (1)

92-113: Bill of Entry tax query omits gst_tax_type, breaking CustomItemGSTDetails processing

CustomItemGSTDetails.is_gst_tax_row filters rows using row.gst_tax_type and row.get(self.tax_details_field()), and get_item_name_wise_tax_details expects gst_tax_type to be present on each tax row. However, get_taxes_query() currently selects only tax_amount, account_head, parent, and item_wise_tax_rates. For the Bill of Entry patch run:

  • Every tax row will fail is_gst_tax_row, so no GST rows are processed.
  • CustomItemGSTDetails().get(...) will then produce only default (zero) item tax details, and build_query_and_update_gst_details will overwrite item GST fields with zeros.

You should include gst_tax_type in the query (and optionally name if needed later), for both Bill of Entry Taxes and India Compliance Taxes and Charges.

Example adjustment:

def get_taxes_query(docs, doctype, taxes):
    return (
        frappe.qb.from_(taxes)
        .select(
-            taxes.tax_amount,
-            taxes.account_head,
-            taxes.parent,
-            taxes.item_wise_tax_rates,
+            taxes.tax_amount,
+            taxes.account_head,
+            taxes.parent,
+            taxes.item_wise_tax_rates,
+            taxes.gst_tax_type,
        )
        .where(taxes.parenttype == doctype)
        .where(taxes.parent.isin(docs))
    )

(Adapt field names if the Bill of Entry tax doctypes use a slightly different schema.)

🧹 Nitpick comments (4)
india_compliance/patches/post_install/improve_item_tax_template.py (1)

424-471: compile_docs correctly aggregates item_wise_tax_details per voucher (small DRY opportunity)

The extended compile_docs now initialises each doc with taxes, items, and item_wise_tax_details and appends rows from all three sources, which matches how ItemGSTDetails.get_item_name_wise_tax_details expects to consume data. The repeated initialisation blocks for taxes/items/item_taxes are slightly duplicated; if you touch this again, consider a tiny helper like _get_or_init_doc(response, parent, doctype) to centralise the default structure.

india_compliance/gst_india/overrides/transaction.py (3)

138-158: validate_item_wise_tax_detail correctly targets problematic Actual charges, but depends on _item_wise_tax_details being populated

The new validation only inspects doc._item_wise_tax_details and throws when an “Actual” charge has an item-level amount but a zero/empty rate. That mirrors the intended error message and avoids touching non-Actual rows.

Just be aware that this check is a no-op unless some upstream code (e.g. CustomItemGSTDetails.set_temp_item_wise_tax_detail_object or ERPNext core) populates _item_wise_tax_details. If there are cases where item-wise details exist but _item_wise_tax_details is not set, you may want to either:

  • Populate _item_wise_tax_details earlier in the flow for those doctypes, or
  • Extend this validation to also look at item_wise_tax_details / other canonical structures.

1159-1232: Item-level recomputation via _item_wise_tax_details looks sound; just ensure row structure is consistent

The updated set_item_name_wise_tax_details plus set_item_defaults correctly:

  • Zero out all GST rate/amount fields per item.
  • Accumulate tax_differences from GST tax rows using tax_amount_field().
  • Walk doc._item_wise_tax_details entries { "item": ..., "tax": ..., "rate": ... } to compute per-item tax amounts and adjust the last taxable item for rounding.

This is coherent with the new _item_wise_tax_details structure introduced in CustomItemGSTDetails. The main assumption is that every entry has a non-None item and tax; if another caller ever inserts a malformed entry, item.update(...) and self.is_gst_tax_row(tax_row) will raise.

If you expect any external producers of _item_wise_tax_details, a small guard would harden this:

for row in self.doc.get("_item_wise_tax_details") or []:
    item = row.get("item")
    tax_row = row.get("tax")
    if not item or not tax_row:
        continue
    ...

Otherwise, the recomputation and rounding-difference handling look correct.


1253-1306: Guard against stale Item Wise Tax Detail rows referencing missing items

The refactored get_item_name_wise_tax_details builds item_map / tax_map keyed by row.name and then does:

tax_row = tax_map.get(row.get("tax_row"))
item = item_map.get(row.get("item_row"))
...
item_taxes = tax_details[item.name]

If an Item Wise Tax Detail entry points to an item_row (or tax_row) that no longer exists in doc.items / doc.taxes (e.g. due to manual data fixes or earlier partial deletions), item or tax_row can be None, and this will raise an exception.

The previous JSON-based implementation explicitly skipped unknown items; mirroring that behaviour here would make the patch more robust:

for row in self.doc.get("item_wise_tax_details") or []:
    tax_row = tax_map.get(row.get("tax_row"))
    item = item_map.get(row.get("item_row"))
    if not tax_row or not item or not self.is_gst_tax_row(tax_row):
        continue
    ...

That keeps the computation resilient to slightly inconsistent historical data, which is often what these patches are run against.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea52b09 and 7d1b44c.

📒 Files selected for processing (5)
  • india_compliance/gst_india/overrides/test_transaction.py (1 hunks)
  • india_compliance/gst_india/overrides/transaction.py (7 hunks)
  • india_compliance/gst_india/utils/taxes_controller.py (2 hunks)
  • india_compliance/patches/post_install/improve_item_tax_template.py (3 hunks)
  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py (1 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/account_wise_summary/account_wise_summary.py:81-87
Timestamp: 2025-04-25T10:12:24.584Z
Learning: When processing taxes in GST India reports, charges after GST rows with charge_type "On Previous Row Total" should not be used to compute taxable value, so a break statement is used to exit the tax processing loop once such a row is encountered.
📚 Learning: 2025-06-25T08:19:02.607Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3354
File: india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py:278-281
Timestamp: 2025-06-25T08:19:02.607Z
Learning: In the Summary of ITC Availed report (india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py), the summary dictionaries created by get_initial_summary() are never empty - they always contain tax field keys (igst_amount, cgst_amount, sgst_amount, cess_amount) with 0 values, so checking for empty dictionaries is unnecessary.

Applied to files:

  • india_compliance/gst_india/utils/taxes_controller.py
  • india_compliance/gst_india/overrides/test_transaction.py
  • india_compliance/gst_india/overrides/transaction.py
  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
  • india_compliance/patches/post_install/improve_item_tax_template.py
📚 Learning: 2025-10-01T10:54:11.096Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3709
File: india_compliance/gst_india/utils/exporter.py:174-174
Timestamp: 2025-10-01T10:54:11.096Z
Learning: In india_compliance/gst_india/doctype/gstr_1/gstr_1_export.py, FIELD_TRANSFORMATIONS dictionary contains lambdas that are only called internally by DataProcessor.apply_transformations() with a single argument. These are separate from header transforms used with ExcelExporter.insert_data() which accept two arguments (value, row).

Applied to files:

  • india_compliance/gst_india/utils/taxes_controller.py
  • india_compliance/gst_india/overrides/test_transaction.py
  • india_compliance/gst_india/overrides/transaction.py
  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
  • india_compliance/patches/post_install/improve_item_tax_template.py
📚 Learning: 2025-09-24T06:52:03.847Z
Learnt from: ljain112
Repo: resilient-tech/india-compliance PR: 3691
File: india_compliance/gst_india/report/gst_balance/gst_balance.js:46-67
Timestamp: 2025-09-24T06:52:03.847Z
Learning: In India Compliance GST reports, the get_accounting_dimensions() function does not include project and cost_center by default, so these filters need to be explicitly added when required in report configurations.

Applied to files:

  • india_compliance/gst_india/utils/taxes_controller.py
📚 Learning: 2025-04-25T10:12:24.584Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/account_wise_summary/account_wise_summary.py:81-87
Timestamp: 2025-04-25T10:12:24.584Z
Learning: When processing taxes in GST India reports, charges after GST rows with charge_type "On Previous Row Total" should not be used to compute taxable value, so a break statement is used to exit the tax processing loop once such a row is encountered.

Applied to files:

  • india_compliance/gst_india/utils/taxes_controller.py
  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-05-29T15:22:04.761Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3399
File: india_compliance/gst_india/utils/gstr_1/test_gstr_1_books_data.py:791-822
Timestamp: 2025-05-29T15:22:04.761Z
Learning: In the india_compliance test suite, the IntegrationTestCase framework automatically handles database rollbacks after test completion, which means functions that modify global state (like GST Settings and Item Tax Templates) in setUpClass won't persist beyond the test run and don't require manual cleanup.

Applied to files:

  • india_compliance/gst_india/overrides/test_transaction.py
📚 Learning: 2025-05-26T03:16:30.230Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py:0-0
Timestamp: 2025-05-26T03:16:30.230Z
Learning: In GST account-wise summary reports, the filtering logic `doc.company_gstin != IfNull(doc[counterparty_gstin_field], "")` is intentionally designed to exclude internal transfers (where company GSTIN equals party GSTIN) while including transactions with unregistered parties (empty GSTIN). Internal transfers are excluded as they are only for internal reporting purposes like stock transfers between branches.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-07-30T10:15:18.756Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3532
File: india_compliance/utils/change_log_utils.py:55-57
Timestamp: 2025-07-30T10:15:18.756Z
Learning: For e-Waybill update functions in india_compliance/gst_india/utils/e_waybill.py, HTML escaping in change log comments may not be required because the e-Waybill API data typically doesn't contain HTML tags and the risk of XSS through vehicle/transporter information fields is considered low by the project maintainers.

Applied to files:

  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
📚 Learning: 2025-07-22T11:45:43.432Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3532
File: india_compliance/gst_india/utils/e_waybill.py:327-336
Timestamp: 2025-07-22T11:45:43.432Z
Learning: In the e-waybill update functions (india_compliance/gst_india/utils/e_waybill.py), fields like place_of_change and state use hardcoded "-" values in old_values dictionaries because these values are not stored in the system, so there's no way to retrieve the actual previous values.

Applied to files:

  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
📚 Learning: 2025-06-19T08:21:29.308Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3451
File: india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_export.py:287-288
Timestamp: 2025-06-19T08:21:29.308Z
Learning: In GSTR-1 export code (india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_export.py), date fields like invoice date (DOC_DATE) and shipping bill date (SHIPPING_BILL_DATE) are mandatory by GST regulations and must exist, so transform functions using strftime() don't need None checks.

Applied to files:

  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
📚 Learning: 2025-09-29T05:06:10.320Z
Learnt from: ljain112
Repo: resilient-tech/india-compliance PR: 3693
File: india_compliance/gst_india/doctype/gst_invoice_management_system/gst_invoice_management_system.js:32-33
Timestamp: 2025-09-29T05:06:10.320Z
Learning: GST-related tool doctypes (like GST Invoice Management System, Purchase Reconciliation Tool, GSTR-1) use unconditional assignment of session default company in their setup() method: `frm.doc.company = frappe.defaults.get_user_default("Company");`. This is appropriate for these utility tools as they are meant to always start with the user's default company on each load, unlike regular documents that preserve saved company values.

Applied to files:

  • india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py
🧬 Code graph analysis (3)
india_compliance/gst_india/utils/taxes_controller.py (1)
india_compliance/gst_india/overrides/transaction.py (7)
  • set_temp_item_wise_tax_detail_object (1395-1397)
  • get_tax_details (1387-1393)
  • get (1130-1149)
  • get_item_name_wise_tax_details (1233-1306)
  • is_gst_tax_row (1367-1371)
  • tax_amount_field (1400-1401)
  • tax_details_field (1404-1405)
india_compliance/gst_india/overrides/transaction.py (1)
india_compliance/gst_india/utils/taxes_controller.py (4)
  • get_item_name_wise_tax_details (62-137)
  • set_temp_item_wise_tax_detail_object (38-60)
  • is_gst_tax_row (139-144)
  • tax_amount_field (24-25)
india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py (1)
india_compliance/patches/post_install/improve_item_tax_template.py (1)
  • compile_docs (441-471)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Python Unit Tests
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (6)
india_compliance/patches/post_install/improve_item_tax_template.py (1)

355-402: Wiring in item-wise tax details into the GST recomputation looks correct

_update_gst_details now fetching Item Wise Tax Detail rows and passing them into compile_docs, and get_taxes_for_docs selecting taxes.name plus base_tax_amount_after_discount_amount, lines up with the new ItemGSTDetails logic (which relies on tax row names and tax_amount_field="base_tax_amount_after_discount_amount"). The data flow from GL → taxes/items/item_taxes → ItemGSTDetails.get() is coherent and should allow item-wise breakdowns without changing existing semantics.

india_compliance/patches/v14/update_item_gst_details_and_gst_trearment_in_bill_of_entry.py (1)

74-83: Passing an empty item_taxes list into compile_docs is appropriate here

For Bill of Entry, there is no separate Item Wise Tax Detail table, so calling compile_docs(taxes, items, [], doctype=doctype) keeps this patch aligned with the new function signature without altering behaviour.

india_compliance/gst_india/utils/taxes_controller.py (2)

38-61: Temporary _item_wise_tax_details structure is consistent with ItemGSTDetails expectations

set_temp_item_wise_tax_detail_object building doc._item_wise_tax_details as a list of {item, tax, rate} entries is exactly what ItemGSTDetails.set_item_name_wise_tax_details consumes. The guard for missing items (item_map.get(item_name)) avoids issues if tax JSON refers to non-existent rows.


1395-1397: ItemGSTDetails.set_temp_item_wise_tax_detail_object hook is a sensible extension point

Leaving ItemGSTDetails.set_temp_item_wise_tax_detail_object as a no-op with a clear comment allows custom controllers (like CustomItemGSTDetails) to inject their own _item_wise_tax_details without impacting the core flow. This is a good, minimal hook design.

india_compliance/gst_india/overrides/transaction.py (1)

1368-1372: is_gst_tax_row now safely handles missing rows

Adding the early if not row: return guard and centralising the GST tax-type check into row.get("gst_tax_type") and row.gst_tax_type in GST_TAX_TYPES prevents accidental crashes when callers pass None or partially-populated tax rows. This is a good defensive improvement.

india_compliance/gst_india/overrides/test_transaction.py (1)

666-695: Updated invalid item-wise tax details test aligns with the new _item_wise_tax_details flow

Populating doc._item_wise_tax_details with a list of dicts containing item, tax, rate, amount, and taxable_amount, and asserting on the more specific message (“Item Wise Tax Details do not match with Taxes and Charges at the following rows...”), matches the new item-wise validation path introduced upstream. The shape of the test data is also compatible with your own helper methods that consume _item_wise_tax_details.

Just keep in mind this test is tightly coupled to ERPNext’s exact error string; if that changes again in the dependent PR, you’ll need to update the regex here as well.

Comment thread india_compliance/gst_india/utils/taxes_controller.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d1b44c and 06376cd.

📒 Files selected for processing (2)
  • india_compliance/gst_india/overrides/transaction.py (7 hunks)
  • india_compliance/gst_india/utils/taxes_controller.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • india_compliance/gst_india/utils/taxes_controller.py
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/account_wise_summary/account_wise_summary.py:81-87
Timestamp: 2025-04-25T10:12:24.584Z
Learning: When processing taxes in GST India reports, charges after GST rows with charge_type "On Previous Row Total" should not be used to compute taxable value, so a break statement is used to exit the tax processing loop once such a row is encountered.
📚 Learning: 2025-10-01T10:54:11.096Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3709
File: india_compliance/gst_india/utils/exporter.py:174-174
Timestamp: 2025-10-01T10:54:11.096Z
Learning: In india_compliance/gst_india/doctype/gstr_1/gstr_1_export.py, FIELD_TRANSFORMATIONS dictionary contains lambdas that are only called internally by DataProcessor.apply_transformations() with a single argument. These are separate from header transforms used with ExcelExporter.insert_data() which accept two arguments (value, row).

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-25T08:19:02.607Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3354
File: india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py:278-281
Timestamp: 2025-06-25T08:19:02.607Z
Learning: In the Summary of ITC Availed report (india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py), the summary dictionaries created by get_initial_summary() are never empty - they always contain tax field keys (igst_amount, cgst_amount, sgst_amount, cess_amount) with 0 values, so checking for empty dictionaries is unnecessary.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-04-25T10:12:24.584Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/account_wise_summary/account_wise_summary.py:81-87
Timestamp: 2025-04-25T10:12:24.584Z
Learning: When processing taxes in GST India reports, charges after GST rows with charge_type "On Previous Row Total" should not be used to compute taxable value, so a break statement is used to exit the tax processing loop once such a row is encountered.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-05-26T03:16:30.230Z
Learnt from: vorasmit
Repo: resilient-tech/india-compliance PR: 3344
File: india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py:0-0
Timestamp: 2025-05-26T03:16:30.230Z
Learning: In GST account-wise summary reports, the filtering logic `doc.company_gstin != IfNull(doc[counterparty_gstin_field], "")` is intentionally designed to exclude internal transfers (where company GSTIN equals party GSTIN) while including transactions with unregistered parties (empty GSTIN). Internal transfers are excluded as they are only for internal reporting purposes like stock transfers between branches.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-06-25T08:16:18.010Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3354
File: india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py:309-310
Timestamp: 2025-06-25T08:16:18.010Z
Learning: In the Summary of ITC Availed report (india_compliance/gst_india/report/summary_of_itc_availed/summary_of_itc_availed.py), creating both a main entry and an additional indented entry for categories without subcategories is by design and intentional behavior for the report structure.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
📚 Learning: 2025-07-22T11:45:43.432Z
Learnt from: karm1000
Repo: resilient-tech/india-compliance PR: 3532
File: india_compliance/gst_india/utils/e_waybill.py:327-336
Timestamp: 2025-07-22T11:45:43.432Z
Learning: In the e-waybill update functions (india_compliance/gst_india/utils/e_waybill.py), fields like place_of_change and state use hardcoded "-" values in old_values dictionaries because these values are not stored in the system, so there's no way to retrieve the actual previous values.

Applied to files:

  • india_compliance/gst_india/overrides/transaction.py
🧬 Code graph analysis (1)
india_compliance/gst_india/overrides/transaction.py (1)
india_compliance/gst_india/utils/taxes_controller.py (3)
  • build_item_wise_tax_detail_from_data (61-82)
  • set_temp_item_wise_tax_detail_object (37-59)
  • tax_amount_field (23-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Python Unit Tests
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (3)
india_compliance/gst_india/overrides/transaction.py (3)

1231-1233: LGTM: Clean initialization of item defaults.

The method properly initializes GST tax fields for all items using a copy of item_defaults to avoid shared reference issues.


1372-1376: LGTM: Good null-safety improvement.

The addition of null checks before accessing row attributes prevents potential AttributeError exceptions.


1275-1281: ****

The stub at line 1404 is intentionally designed for subclass override. CustomItemGSTDetails in india_compliance/gst_india/utils/taxes_controller.py (lines 61-82) properly overrides this method and populates item_wise_tax_details with the expected structure (item_row, tax_row, rate fields). The code works as designed through inheritance—no issue exists.

Likely an incorrect or invalid review comment.

Comment thread india_compliance/gst_india/overrides/transaction.py
Comment thread india_compliance/gst_india/overrides/transaction.py
Comment thread india_compliance/gst_india/overrides/transaction.py
Comment thread india_compliance/gst_india/overrides/transaction.py
Comment thread india_compliance/gst_india/overrides/transaction.py
@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 21, 2025

Codecov Report

❌ Patch coverage is 49.49495% with 50 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.51%. Comparing base (d5c8bc2) to head (1cec786).
⚠️ Report is 22 commits behind head on develop.

Files with missing lines Patch % Lines
...ndia_compliance/gst_india/overrides/transaction.py 46.15% 42 Missing ⚠️
...dia_compliance/gst_india/utils/taxes_controller.py 60.00% 8 Missing ⚠️

❌ Your patch status has failed because the patch coverage (49.49%) is below the target coverage (85.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #3807      +/-   ##
===========================================
- Coverage    69.58%   69.51%   -0.07%     
===========================================
  Files          182      182              
  Lines        17970    17965       -5     
===========================================
- Hits         12505    12489      -16     
- Misses        5465     5476      +11     
Files with missing lines Coverage Δ
...compliance/gst_india/overrides/test_transaction.py 99.05% <100.00%> (+<0.01%) ⬆️
...dia_compliance/gst_india/utils/taxes_controller.py 85.82% <60.00%> (-6.84%) ⬇️
...ndia_compliance/gst_india/overrides/transaction.py 83.31% <46.15%> (-0.04%) ⬇️

... and 3 files with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread india_compliance/gst_india/overrides/transaction.py
Comment thread india_compliance/gst_india/overrides/transaction.py Outdated
Comment thread india_compliance/gst_india/overrides/transaction.py Outdated
@ljain112 ljain112 merged commit f11849b into resilient-tech:develop Nov 21, 2025
14 checks passed
@ljain112 ljain112 deleted the fix-item-wise-tax-details branch November 21, 2025 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants