Skip to content

feat: gstr export tool for 2a/2b#4502

Draft
Priyal208 wants to merge 8 commits into
resilient-tech:developfrom
Priyal208:gstr-export
Draft

feat: gstr export tool for 2a/2b#4502
Priyal208 wants to merge 8 commits into
resilient-tech:developfrom
Priyal208:gstr-export

Conversation

@Priyal208

@Priyal208 Priyal208 commented Jun 30, 2026

Copy link
Copy Markdown
Member

GST Return Export — Phase 1 (Sync GSTR-2A / 2B)

Adds a Desk tool to download GSTR-2A/2B from the GST portal and export it to Excel byte-for-byte identical to the portal's own file.

What it does

  • New GST Return Export doctype with Sync / Summary / Export actions (plain Frappe/Desk, async with realtime progress).
  • Persists the raw GSTN payload per period on the GST Return Log (store_raw_return_data / get_raw_return_data) — the export is raw-replay, not a lossy re-derivation from GST Inward Supply.
  • Excel exporter (gstr_2_export.py) fills the bundled portal templates label-by-label (survives template shifts): 2B invoice-level with code expansion + the four ITC-summary sheets from the portal's itcsumm; 2A item-level with per-invoice -Total rows; ISD invoice/credit-note routing, TCS computed columns, Read me header. Multi-period exports merge sections and sum itcsumm.
  • Summary section (returns_export): per-period aggregation from GST Inward Supply and a section-first range summary with ITC buckets, for the tool's summary view.
  • Sync fetches the 2A export-only sections (ECO/ECOA/TDS/TCS) best-effort, and reads legal/trade names verbatim from the GSTIN registry for portal-matching Read me headers.

Testing

  • Golden-workbook regression tests for 2A and 2B (committed goldens, per-cell comparison), value-assertion unit tests for the tricky logic, summary-aggregation and multi-period tests, sync raw-persistence + export-section tests, and controller endpoint tests.

Screenshots

image image Screenshot 2026-07-13 at 10 23 15 AM

@codacy-production

codacy-production Bot commented Jun 30, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 2 high

Alerts:
⚠ 2 issues (≤ 0 issues of at least minor severity)

Results:
2 new issues

Category Results
ErrorProne 2 high

View in Codacy

🟢 Metrics 422 complexity

Metric Results
Complexity 422

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@Priyal208 Priyal208 changed the title feat: (p1)scaffold gst return export tool and (p2)persist raw gstn 2a/2b payload feat: gstr export tool for 2a/2b Jun 30, 2026
@Priyal208
Priyal208 force-pushed the gstr-export branch 4 times, most recently from 68f9dd8 to 6de98f2 Compare June 30, 2026 11:02
Comment thread india_compliance/gst_india/doctype/gst_return_log/gst_return_log.json Outdated
Comment thread india_compliance/gst_india/doctype/gst_return_log/gst_return_log.py
Comment thread india_compliance/gst_india/utils/gstr_2/__init__.py
Comment thread india_compliance/gst_india/utils/returns_export/__init__.py
Comment thread india_compliance/gst_india/doctype/gst_return_summary/gst_return_summary.json Outdated
@@ -0,0 +1,16 @@
// GST Return Export summary. The number cards (NumberCardManager) and table

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

doctype css

},

setup_actions(frm) {
frm.add_custom_button(__("Show Summary"), () => render_summary(frm));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

btn sequence / what should be primary

frappe.throw(__("Select Company, GSTIN, GST Return and the period before syncing."));
}

const { message } = await fetch_summary(frm);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

gstr import log. can it be independent and used on change of period -> simple ux to suggest user some info is missing

Comment on lines +78 to +82
link.href = file_url;
link.download = file_name;
document.body.appendChild(link);
link.click();
link.remove();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

something better..
-> what if user doesn't have permissions for the file / to view any file?
-> maybe a new API request in backend to get file content and trigger it's download
-> what permissions check will you do for this?

return _ITC_REASON.get(value, "")


RAW_FIELDS_2B = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

mappings as part of classes.

const periods = data?.periods || [];
if (!periods.length) return render_summary_placeholder(frm);

const is_2b = gst_return === "GSTR-2B";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

split this for 2A / 2B. we need this for more returns

checked: !p.synced,
label: `${format_period(p.period)} · ${
p.synced
? __("synced {0}", [frappe.datetime.str_to_user(p.last_updated_on)])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ux: greyed / month name

gstin_info = frappe._dict(
gstin=response.gstin,
business_name=titlecase(business_name or ""),
legal_name=response.lgnm or "",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

comes in GSTR-2A. Not in 2B.



EXPORTERS = {
GSTR2AExporter.return_type: GSTR2AExporter,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

better name



def save_gstr_2a(gstin, return_period, json_data):
def save_gstr_2a(gstin, return_period, json_data, *, merge=False, empty_categories=None):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's first fix this and keep it consistant.

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