Skip to content

feat: add GSTR-1 Reconciliation #3388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

karm1000
Copy link
Member

@karm1000 karm1000 commented May 19, 2025

Summary by CodeRabbit

  • New Features
    • Introduced a new "GSTR-1 Reconciliation" tool for GST India, enabling users to reconcile GSTR-1 returns for a selected company and fiscal year.
    • Added interactive form actions, including a "Generate" button to initiate reconciliation and automatic population of company GSTINs.
  • Tests
    • Added placeholder unit and integration test classes for future validation of the GSTR-1 Reconciliation feature.

Copy link

coderabbitai bot commented May 19, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

A new "GSTR-1 Reconciliation" feature is introduced for the GST India module, including a DocType definition, client-side event handlers, backend reconciliation logic, and test scaffolding. The implementation covers form setup, data fetching, reconciliation orchestration, and placeholders for unit and integration tests.

Changes

File(s) Change Summary
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.json Added new DocType "GSTR-1 Reconciliation" with fields for Company, Company GSTIN, Fiscal Year, and an HTML display area. Configured as a single-instance document with permissions and layout settings.
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.js Introduced client-side script for the DocType: loads external JS, sets default GSTIN, disables save, adds "Generate" action, and handles reconciliation event with backend API call.
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py Added backend class GSTR1Reconciliation with methods for orchestrating GSTR-1 reconciliation, fetching logs, preparing filters, summarizing data, and a whitelisted API for reconciliation.
india_compliance/gst_india/doctype/gstr_1_reconciliation/test_gstr_1_reconciliation.py Added test module with placeholder unit and integration test classes, and empty dependency lists for future test management.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ClientForm
    participant ServerAPI
    participant GSTNAPI
    participant Database

    User->>ClientForm: Open GSTR-1 Reconciliation form
    ClientForm->>ServerAPI: Fetch GSTINs for selected company
    ServerAPI->>Database: Query GSTINs
    Database-->>ServerAPI: Return GSTIN list
    ServerAPI-->>ClientForm: Return GSTINs
    ClientForm->>User: Display form with default GSTIN

    User->>ClientForm: Click "Generate"
    ClientForm->>ServerAPI: Call get_gstr_1_reconciliation
    ServerAPI->>Database: Validate fiscal year, fetch logs
    loop For each month in fiscal year
        ServerAPI->>GSTNAPI: Fetch government GSTR-1 data
        ServerAPI->>Database: Fetch books data
        ServerAPI->>ServerAPI: Reconcile and summarize data
    end
    ServerAPI-->>ClientForm: Return reconciliation summary
    ClientForm->>User: Display reconciliation results
Loading

Poem

In the ledger’s warren, a new DocType appears,
With scripts that fetch GSTINs, allaying user fears.
The backend reconciles, month by month,
While tests await their day—silent, calm, and blunt.
Hop along, dear data—your carrots now align!
🥕✨


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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: 6

🧹 Nitpick comments (5)
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py (1)

63-67: Unused is_queued flag – lost information
get_gov_gstr1_data() returns (gov_data, is_queued) but is_queued is never examined.
Consider short-circuiting further processing (or informing the user) when the data is still queued.

india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.js (2)

31-38: Optional chaining cleans up null-checks
The static analysis hint is valid. Modern JS allows gstin_list?.length and gstin_list?.[0], reducing branching noise.

-    if (gstin_list && gstin_list.length) {
-        frm.set_value("company_gstin", gstin_list[0]);
+    if (gstin_list?.length) {
+        frm.set_value("company_gstin", gstin_list[0]);
     }

Ensure Babel/TS config targets ES2020+.

🧰 Tools
🪛 Biome (1.9.4)

[error] 36-36: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


19-23: No error feedback from taxpayer_api_call
If the backend throws (e.g., missing OTP), the user receives no notification. Wrap the promise in frm.call style or attach .then/.catch to surface messages and optionally show a progress indicator.

india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.json (2)

20-24: Fields marked “In List View” have no effect on Single DocTypes
Because issingle = 1, the framework never shows a list view. Setting in_list_view is redundant noise—consider removing for clarity.


30-35: GSTIN as “Autocomplete” may bypass validation
A GSTIN is a fixed-length 15-char identifier. Using fieldtype: Data with a regex or a dedicated GSTIN Link DocType enforces correctness; free-text autocomplete could store invalid values.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between b7e7572 and 381d499.

📒 Files selected for processing (4)
  • india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.js (1 hunks)
  • india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.json (1 hunks)
  • india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py (1 hunks)
  • india_compliance/gst_india/doctype/gstr_1_reconciliation/test_gstr_1_reconciliation.py (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.js

[error] 36-36: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 Ruff (0.11.9)
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py

9-9: india_compliance.gst_india.api_classes.taxpayer_base.TaxpayerBaseAPI imported but unused

Remove unused import: india_compliance.gst_india.api_classes.taxpayer_base.TaxpayerBaseAPI

(F401)

🪛 GitHub Actions: Linters
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py

[error] 8-8: ESLint: 'india_compliance.gst_india.api_classes.taxpayer_base.TaxpayerBaseAPI' imported but unused. (flake8 F401)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Python Unit Tests
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary

Comment on lines 60 to 66
books_data = gstr_log.get_books_gstr1_data(gstr_log)

try:
gov_data, is_queued = gstr_log.get_gov_gstr1_data()
except frappe.ValidationError as error:
frappe.throw(title="GSTR-1 Generation Failed", msg=str(error))

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Suspicious extra argument in get_books_gstr1_data call
gstr_log.get_books_gstr1_data(gstr_log) passes the log instance to its own method. Unless the method signature explicitly requires an external log object, this is likely redundant and hides bugs if the API changes.

🤖 Prompt for AI Agents
In
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py
around lines 60 to 66, the method get_books_gstr1_data is called with gstr_log
passed as an argument, which is likely unnecessary since it is an instance
method. Remove the gstr_log argument from the call so it is invoked as
gstr_log.get_books_gstr1_data() to avoid redundant or incorrect parameter
passing.

Comment on lines +112 to +116
def summarize_data(self, data):
"""
Summarize the data for the given filters (Aggregate the data)
"""
pass
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

summarize_data stub blocks feature completion
The public method returns pass, so the overall API already advertised by the UI will always return empty summaries. Either implement the logic now or raise NotImplementedError to avoid silent failures.

🤖 Prompt for AI Agents
In
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py
at lines 112 to 116, the summarize_data method is currently a stub that returns
pass, causing the API to return empty summaries silently. To fix this, either
implement the actual data summarization logic as intended or replace the pass
statement with a raise NotImplementedError to explicitly indicate the method is
not yet implemented and prevent silent failures.

Comment on lines 8 to 14
from india_compliance.gst_india.api_classes.taxpayer_base import (
TaxpayerBaseAPI,
otp_handler,
)
from india_compliance.gst_india.doctype.gst_return_log.gst_return_log import (
get_gst_return_log,
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unused import to make linters green
TaxpayerBaseAPI is imported but never referenced, which triggers Ruff / flake8 F401 and fails the pipeline.

-from india_compliance.gst_india.api_classes.taxpayer_base import (
-    TaxpayerBaseAPI,
-    otp_handler,
-)
+from india_compliance.gst_india.api_classes.taxpayer_base import otp_handler
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from india_compliance.gst_india.api_classes.taxpayer_base import (
TaxpayerBaseAPI,
otp_handler,
)
from india_compliance.gst_india.doctype.gst_return_log.gst_return_log import (
get_gst_return_log,
)
from india_compliance.gst_india.api_classes.taxpayer_base import otp_handler
from india_compliance.gst_india.doctype.gst_return_log.gst_return_log import (
get_gst_return_log,
)
🧰 Tools
🪛 Ruff (0.11.9)

9-9: india_compliance.gst_india.api_classes.taxpayer_base.TaxpayerBaseAPI imported but unused

Remove unused import: india_compliance.gst_india.api_classes.taxpayer_base.TaxpayerBaseAPI

(F401)

🪛 GitHub Actions: Linters

[error] 8-8: ESLint: 'india_compliance.gst_india.api_classes.taxpayer_base.TaxpayerBaseAPI' imported but unused. (flake8 F401)

🤖 Prompt for AI Agents
In
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py
between lines 8 and 14, remove the unused import TaxpayerBaseAPI from
india_compliance.gst_india.api_classes.taxpayer_base to fix the F401 linting
error and make the pipeline pass.

Comment on lines 95 to 103
current_date = year_start_date
now_date = getdate()
# Ensure we do not go beyond the current date in the current year
if year_end_date.year == now_date.year:
last_date = now_date

while current_date <= last_date:
period = current_date.strftime("%m%Y")
log_name = f"GSTR-1-{period}-{self.company_gstin}"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

last_date may be undefined → possible UnboundLocalError
When the fiscal year is a past year (year_end_date.year != now_date.year), the else branch never sets last_date, yet it is referenced in the while loop.

-        if year_end_date.year == now_date.year:
-            last_date = now_date
+        if year_end_date.year == now_date.year:
+            last_date = now_date
+        else:
+            last_date = year_end_date
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
current_date = year_start_date
now_date = getdate()
# Ensure we do not go beyond the current date in the current year
if year_end_date.year == now_date.year:
last_date = now_date
while current_date <= last_date:
period = current_date.strftime("%m%Y")
log_name = f"GSTR-1-{period}-{self.company_gstin}"
current_date = year_start_date
now_date = getdate()
# Ensure we do not go beyond the current date in the current year
if year_end_date.year == now_date.year:
last_date = now_date
else:
last_date = year_end_date
while current_date <= last_date:
period = current_date.strftime("%m%Y")
log_name = f"GSTR-1-{period}-{self.company_gstin}"
🤖 Prompt for AI Agents
In
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.py
around lines 95 to 103, the variable last_date is only set inside the if block
when year_end_date.year equals now_date.year, but it is used later in the while
loop regardless. To fix this, initialize last_date to year_end_date before the
if statement so it is always defined, ensuring the loop has a valid end date
whether the fiscal year is current or past.

Comment on lines +15 to +17
frm.disable_save();
frm.page.set_primary_action(__("Generate"), () => frm.trigger("generate"));
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Primary action added on every refresh → duplicate handlers
refresh runs on each form reload; set_primary_action will bind a new click callback every time, causing multiple identical listeners. Guard with a flag or use frm.page.clear_primary_action() first.

🤖 Prompt for AI Agents
In
india_compliance/gst_india/doctype/gstr_1_reconciliation/gstr_1_reconciliation.js
around lines 15 to 17, the primary action is set on every form refresh, causing
duplicate click handlers. To fix this, clear existing primary actions first by
calling frm.page.clear_primary_action() before setting the new primary action,
or use a flag to ensure the handler is only bound once.

Comment on lines +14 to +21
class UnitTestGSTR1Reconciliation(UnitTestCase):
"""
Unit tests for GSTR1Reconciliation.
Use this class for testing individual functions and methods.
"""

pass

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Tests are placeholders – please add at least one sanity test
CI will mark the module as “collected 0 tests”, offering no regression guard. Suggest starting with:

def test_minimum_api_response(self):
    doc = frappe.get_doc({
        "doctype": "GSTR-1 Reconciliation",
        "company": "Test Company",
        "company_gstin": "27ABCDE1234F1Z5",
        "fiscal_year": "2024-25",
    })
    with self.assertRaises(frappe.ValidationError):
        doc.get_gstr_1_reconciliation()
🤖 Prompt for AI Agents
In
india_compliance/gst_india/doctype/gstr_1_reconciliation/test_gstr_1_reconciliation.py
around lines 14 to 21, the test class is empty and contains no actual tests,
causing the CI to report zero tests collected. Add at least one sanity test
method inside the UnitTestGSTR1Reconciliation class that creates a GSTR-1
Reconciliation document with minimal required fields and asserts that calling
get_gstr_1_reconciliation raises a ValidationError. This will ensure the test
suite runs and provides basic regression coverage.

@karm1000 karm1000 marked this pull request as draft May 19, 2025 07:19
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.

1 participant