<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Archit Mittal</title>
    <description>The latest articles on DEV Community by Archit Mittal (@automate-archit).</description>
    <link>https://dev.to/automate-archit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F583571%2Fc2c0b665-b457-4281-a519-d6e76245e21f.png</url>
      <title>DEV Community: Archit Mittal</title>
      <link>https://dev.to/automate-archit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/automate-archit"/>
    <language>en</language>
    <item>
      <title>The ₹0 Automation Stack: Enterprise-Grade Workflows Without Paying for SaaS</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sun, 21 Jun 2026 08:04:38 +0000</pubDate>
      <link>https://dev.to/automate-archit/the-0-automation-stack-enterprise-grade-workflows-without-paying-for-saas-32gl</link>
      <guid>https://dev.to/automate-archit/the-0-automation-stack-enterprise-grade-workflows-without-paying-for-saas-32gl</guid>
      <description>&lt;p&gt;₹37,500 per month. That was the SaaS bill a Jaipur-based textile exporter was paying for automating invoices, GST reconciliation, and shipping notifications across three platforms. Three dashboards, three logins, three support tickets every time something broke.&lt;/p&gt;

&lt;p&gt;I replaced all of it with Python scripts running on a ₹500/month VPS. The recurring cost dropped to effectively zero — and the workflows actually became more reliable.&lt;/p&gt;

&lt;p&gt;This isn't a hypothetical framework. This is the exact stack I've deployed across 11 Indian businesses over the past 18 months, from CA firms filing ITR returns to stock traders screening 150+ equities before market open. Every tool in this stack is free. Every workflow runs in production today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Indian Businesses Overpay for Automation
&lt;/h2&gt;

&lt;p&gt;Most business owners discover automation through SaaS marketing. The pitch is compelling: drag-and-drop workflows, no coding required, instant results. What the pricing page doesn't tell you is that the "Starter" plan handles 100 tasks per month, and your GST reconciliation alone burns through that in three days.&lt;/p&gt;

&lt;p&gt;The real cost isn't the subscription — it's the upgrade treadmill. You start at ₹2,000/month, hit the task limit by week two, upgrade to ₹8,000/month, then discover that the webhook integration you need is locked behind the "Business" tier at ₹25,000/month.&lt;/p&gt;

&lt;p&gt;For businesses processing under 10,000 transactions monthly — which includes the vast majority of Indian SMBs, freelancers, and professional firms — a Python-based stack isn't just cheaper. It's more flexible, more transparent, and entirely under your control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack: Seven Layers, Zero Recurring Cost
&lt;/h2&gt;

&lt;p&gt;Here's every component of the automation stack I deploy for clients. Each layer is free, battle-tested, and replaceable without rebuilding the entire system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Layer 1 — Logic &amp;amp; Scripting: Python 3.11+&lt;/strong&gt;&lt;br&gt;
The backbone of every automation. Handles API calls, data transformation, conditional logic, and error handling. Free forever, runs anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 — Data Processing: Pandas + OpenPyXL&lt;/strong&gt;&lt;br&gt;
Reads Excel sheets, CSVs, and bank statements. Cleans, matches, and transforms data. This single library replaces most of what businesses pay ₹10,000+/month for in data integration tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3 — Database: SQLite (small) or PostgreSQL (scale)&lt;/strong&gt;&lt;br&gt;
SQLite ships with Python — zero setup. For anything above 50,000 records or multi-user access, PostgreSQL (free, open-source) handles it. Supabase offers free-tier hosted PostgreSQL if you don't want to manage a database server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 4 — Scheduling: cron + Python schedule library&lt;/strong&gt;&lt;br&gt;
cron handles time-based triggers on Linux. The Python schedule library handles interval-based logic within scripts. Together they replace paid workflow schedulers entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 5 — Notifications: Telegram Bot API + Gmail SMTP&lt;/strong&gt;&lt;br&gt;
Telegram bots are free, instant, and support rich formatting (tables, buttons, file attachments). Gmail SMTP handles email alerts up to 500/day. WhatsApp Business API is free under 1,000 messages/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 6 — Web Scraping &amp;amp; Browser Automation: Selenium + BeautifulSoup&lt;/strong&gt;&lt;br&gt;
For workflows that need to interact with websites that don't offer APIs — government portals, legacy ERP dashboards, bank statement downloads. Free, mature, well-documented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 7 — Hosting: VPS (₹500/month) or Home Server (₹0)&lt;/strong&gt;&lt;br&gt;
A basic VPS from providers like Hetzner or DigitalOcean runs the entire stack. For truly zero cost, an old laptop running Ubuntu works — I have a client whose stock screener runs on a repurposed 2018 ThinkPad.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Real Numbers: SaaS vs. ₹0 Stack
&lt;/h2&gt;

&lt;p&gt;Here's the cost comparison from three actual client deployments. These aren't projections — these are real invoices I've seen versus the cost of what replaced them.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workflow&lt;/th&gt;
&lt;th&gt;SaaS Cost (Monthly)&lt;/th&gt;
&lt;th&gt;₹0 Stack Cost (Monthly)&lt;/th&gt;
&lt;th&gt;Annual Savings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Invoice processing + GST filing&lt;/td&gt;
&lt;td&gt;₹18,000&lt;/td&gt;
&lt;td&gt;₹0&lt;/td&gt;
&lt;td&gt;₹2,16,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bank reconciliation (3 accounts)&lt;/td&gt;
&lt;td&gt;₹12,000&lt;/td&gt;
&lt;td&gt;₹0&lt;/td&gt;
&lt;td&gt;₹1,44,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stock screening + WhatsApp alerts&lt;/td&gt;
&lt;td&gt;₹47,000 (advisory fee)&lt;/td&gt;
&lt;td&gt;₹0&lt;/td&gt;
&lt;td&gt;₹5,64,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily MIS report generation&lt;/td&gt;
&lt;td&gt;₹8,500&lt;/td&gt;
&lt;td&gt;₹0&lt;/td&gt;
&lt;td&gt;₹1,02,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Total annual savings across these four workflows: ₹10,26,000.&lt;/strong&gt; The one-time setup cost for all four was ₹1,45,000. Payback period: under 2 months.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Trade-Off Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;I'd be dishonest if I said this stack has no downsides. It does. The primary trade-off is setup time and maintenance ownership.&lt;/p&gt;

&lt;p&gt;A SaaS tool gives you a working automation in 20 minutes. A Python script takes 2-8 hours to build, test, and deploy. If something breaks at 2 AM, there's no support chat — you debug it yourself, or your automation consultant does.&lt;/p&gt;

&lt;p&gt;This matters. For a solopreneur who needs a quick Slack-to-email bridge, paying ₹2,000/month for a SaaS tool makes perfect sense. The ₹0 stack wins when you have workflows that are core to your business operations, when the SaaS bill has crossed ₹10,000/month, or when you need customisation that no drag-and-drop builder can handle.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Start: The First Workflow to Automate
&lt;/h2&gt;

&lt;p&gt;If you've never built a ₹0 automation before, start with the workflow that causes the most daily friction. For most Indian businesses, that's one of these three: bank statement download and matching, invoice data extraction from PDFs, or daily/weekly report generation from spreadsheets.&lt;/p&gt;

&lt;p&gt;Pick one. Build a Python script that handles the happy path — the 80% case where everything works normally. Add error handling and a Telegram notification for failures. Run it manually for a week to build trust. Then schedule it with cron and forget about it.&lt;/p&gt;

&lt;p&gt;That single workflow will teach you more about automation than any SaaS trial. And once it's running, it runs forever — no subscription renewal, no "your plan has been downgraded," no surprise pricing changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Reliability Question
&lt;/h3&gt;

&lt;p&gt;Skeptics ask: "Is a free stack reliable enough for production?" Fair question. My answer: a CA firm has been running Python-based ITR automation through two consecutive filing seasons — over 1,200 returns processed, zero missed deadlines. The scripts have error handling, retry logic, and instant Telegram alerts if anything fails. That's more observability than most SaaS dashboards provide.&lt;/p&gt;

&lt;p&gt;Reliability isn't about how much you pay. It's about how well you handle failures. A ₹0 script with proper logging and alerting beats a ₹20,000/month SaaS tool where failures disappear into a "contact support" black hole.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;In upcoming articles, I'll walk through specific implementations: automated bank reconciliation with Python and Pandas, stock screening bots that replace expensive advisory services, and GST reconciliation pipelines that file-ready returns without manual intervention.&lt;/p&gt;

&lt;p&gt;Every implementation will follow the same philosophy: zero recurring cost, production-grade reliability, and real rupee numbers from real Indian businesses.&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>How a Weekend Python Script Saved a CA Firm 209 Hours During ITR Season</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:59:28 +0000</pubDate>
      <link>https://dev.to/automate-archit/how-a-weekend-python-script-saved-a-ca-firm-209-hours-during-itr-season-4k90</link>
      <guid>https://dev.to/automate-archit/how-a-weekend-python-script-saved-a-ca-firm-209-hours-during-itr-season-4k90</guid>
      <description>&lt;p&gt;₹3,12,000. That's what Rajesh Sharma's CA firm in Jaipur spent every ITR season hiring three temporary data entry operators for two months. They'd sit in a back room extracting numbers from Form 16 PDFs, cross-checking PAN details against the income tax portal, and pre-filling ITR forms — one cell at a time, one return at a time, 340 returns total.&lt;/p&gt;

&lt;p&gt;Last July, a single Python script replaced that entire process. Built in one weekend. Running cost: ₹0. Time saved across the season: 209 hours.&lt;/p&gt;

&lt;p&gt;This is not a theoretical tutorial. This is what actually happened, with real numbers, real friction, and the parts that almost went wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: ITR Season Is a Two-Month Data Entry Marathon
&lt;/h2&gt;

&lt;p&gt;If you've never worked inside a CA firm during July-September, here's what it looks like. Clients send Form 16 PDFs over WhatsApp — sometimes as photos, sometimes as scanned copies with coffee stains. The firm's staff manually opens each PDF, types salary figures into a master Excel sheet, cross-references PAN numbers on the income tax portal, and fills in the ITR form fields one by one.&lt;/p&gt;

&lt;p&gt;Rajesh's firm handled 340 individual ITRs last year. Each return took an average of 38 minutes of pure data processing before a CA even looked at it for deductions and exemptions. That's 215 hours of someone staring at PDFs and typing numbers into boxes.&lt;/p&gt;

&lt;p&gt;The three temporary hires cost ₹1,04,000 each for the season — ₹3,12,000 total. And they still made errors. Rajesh's senior CA spent another 40+ hours catching and fixing data entry mistakes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Har saal yahi hota tha. Teen log hire karo, train karo, phir unki galtiyan dhundo. It felt like we were paying people to create problems we'd solve ourselves." (Every year the same thing. Hire three people, train them, then find their mistakes.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Script: What It Actually Does
&lt;/h2&gt;

&lt;p&gt;I didn't build Rajesh an AI platform. I didn't sell him a subscription. I built a Python script that does three things — and does them well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 1: PDF Text Extraction
&lt;/h3&gt;

&lt;p&gt;The script uses an open-source PDF library to read every Form 16 PDF in a folder. It extracts employer name, PAN, salary breakdowns (basic, HRA, special allowance), TDS deducted, and Section 80C/80D declarations. For scanned or photo PDFs — which made up about 30% of the documents — it falls back to OCR using Tesseract, another free tool.&lt;/p&gt;

&lt;p&gt;This stage alone eliminated about 70% of the manual typing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: Validation and Cross-Check
&lt;/h3&gt;

&lt;p&gt;Every extracted PAN is validated against a checksum algorithm (PAN numbers follow a specific format — the script catches typos instantly). Salary totals are cross-checked: does basic + HRA + special allowance + other components equal gross salary? If not, the return gets flagged for manual review instead of silently carrying an error forward.&lt;/p&gt;

&lt;p&gt;This is where the script outperformed humans consistently. The temporary hires caught about 60% of calculation mismatches. The script catches 100% — because it doesn't get tired at 4 PM on a Thursday.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: Pre-Filled Output
&lt;/h3&gt;

&lt;p&gt;The script generates a structured spreadsheet with every field mapped to the ITR form layout. Rajesh's CAs open the sheet, review the numbers, apply their professional judgment on deductions and exemptions, and file. The 38-minute-per-return data processing step dropped to about 6 minutes of review.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Numbers:&lt;/strong&gt;&lt;br&gt;
Before: 38 min/return x 340 returns = 215 hours of data processing&lt;br&gt;
After: 6 min/return x 340 returns = 34 hours of CA review&lt;br&gt;
Net saving: ~209 hours (after accounting for the 28 returns flagged for manual processing)&lt;br&gt;
Cost saving: ₹3,12,000 in seasonal hiring — replaced by a script with ₹0 running cost&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Almost Went Wrong
&lt;/h2&gt;

&lt;p&gt;I'd be lying if I said the script worked perfectly from day one. Two things nearly derailed it.&lt;/p&gt;

&lt;p&gt;The first problem was PDF variety. Indian employers don't follow a standard Form 16 template. Some PDFs had salary components in tables, others in plain text paragraphs, and a few used formats I'd never seen — with Devanagari headers mixed into English content. The first version of the script handled about 75% of PDFs correctly. I spent the second day of that weekend writing fallback extraction logic for edge cases. By the end, it handled 92% automatically — the remaining 8% (28 returns) got flagged for manual processing.&lt;/p&gt;

&lt;p&gt;The second problem was trust. Rajesh didn't trust the script's output initially — and he shouldn't have. We ran a parallel test: his staff processed the first 50 returns manually while the script processed the same 50. We compared outputs line by line. The script matched human output on 47 returns and was actually &lt;em&gt;more accurate&lt;/em&gt; on the other 3 (the staff had made small transcription errors).&lt;/p&gt;

&lt;p&gt;That parallel test took an extra day but bought something no amount of demos could: Rajesh's confidence that the numbers were right.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Jab tak maine apni aankhon se comparison nahi dekha, mujhe yakeen nahi aaya. But the numbers don't lie." (Until I saw the comparison with my own eyes, I didn't believe it. But the numbers don't lie.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why This Matters Beyond One CA Firm
&lt;/h2&gt;

&lt;p&gt;India has over 3.5 lakh practising Chartered Accountants. The vast majority of small and mid-size firms still process ITRs the way Rajesh used to — manually, with seasonal hires, under deadline pressure that leads to errors and late nights.&lt;/p&gt;

&lt;p&gt;The automation here isn't complicated. It's not an AI model that needs training data or a cloud platform that costs ₹50,000/month. It's a Python script using free libraries, running on the same laptop the CA already owns. The total infrastructure cost is zero.&lt;/p&gt;

&lt;p&gt;What it requires is someone who understands both the accounting workflow and the code — or a CA willing to work with someone who does. That intersection is where the real value lives. Not in the technology itself, but in knowing which 80% of the process is pure data movement and which 20% genuinely needs a Chartered Accountant's brain.&lt;/p&gt;

&lt;p&gt;If you're a CA firm owner reading this: you don't need to learn Python. You need to find someone who can spend a weekend understanding your Form 16 processing workflow and write a script tailored to it. The ROI pays for itself before August.&lt;/p&gt;

&lt;p&gt;And if you're a developer looking for freelance projects: ITR season starts in July. CA firms start panicking in June. That's your window. The ones who've done it manually for 20 years are the ones most ready to try something different — they just need someone to show them it works.&lt;/p&gt;

</description>
      <category>python</category>
      <category>aiops</category>
    </item>
    <item>
      <title>Claude Code vs Cursor vs Copilot: An Honest Review After 40 Production Automations</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:56:41 +0000</pubDate>
      <link>https://dev.to/automate-archit/claude-code-vs-cursor-vs-copilot-an-honest-review-after-40-production-automations-1oee</link>
      <guid>https://dev.to/automate-archit/claude-code-vs-cursor-vs-copilot-an-honest-review-after-40-production-automations-1oee</guid>
      <description>&lt;p&gt;₹40,000 to ₹70,000 — that's the extra monthly capacity my consulting practice has picked up since switching my primary dev loop to Claude Code six months ago. Forty production automations shipped in that window: bank reconciliation pipelines, stock screeners, ITR-prep bots, expense categorizers, GST filing helpers, a couple of trading systems I still babysit.&lt;/p&gt;

&lt;p&gt;This post is the scorecard. What Claude Code gets right, where it still breaks, and how I decide when to reach for it versus Cursor versus plain GitHub Copilot. No sponsored angle, no affiliate link. I pay for all three out of pocket. What follows is what I'd tell a friend over chai.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context — Who This Review Is For
&lt;/h2&gt;

&lt;p&gt;I'm not a web app engineer. I build finance and trading automations in Python, glue them to broker APIs and Google Sheets, and ship scripts that run on cron jobs or Railway containers. If you build similar back-end, script-first work, this review will transfer cleanly. If you're writing React all day, your mileage will differ.&lt;/p&gt;

&lt;p&gt;The bar I measure against is brutal. A client automation has to work on day one against real production data, handle every edge case a CA firm can dream up, and be debuggable by me at 11 PM when a trade doesn't fire. No tolerance for "it worked on my machine."&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude Code Gets Right — The Four Wins That Actually Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Multi-file reasoning at a level nothing else touches
&lt;/h3&gt;

&lt;p&gt;Most AI coding assistants play well inside a single file. Claude Code holds an entire repo in its head. I asked it to refactor a bank-reconciliation project that spans eleven modules and 2,300 lines — it traced every call site, flagged one circular import I'd never noticed, and proposed a clean split in a single turn. Cursor starts to struggle past six or seven files. Copilot gives up around two.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. It asks the right questions before writing code
&lt;/h3&gt;

&lt;p&gt;This surprised me. When I told Claude Code to "add retry logic to the Zerodha order function," it didn't just write it. It asked whether the retry should respect the broker's rate limits, what to do on partial fills, and whether idempotency keys were available. Those are the questions a senior engineer would ask. The answers shape whether the automation is safe for real money or a ticking time bomb.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Long-running tasks stay coherent
&lt;/h3&gt;

&lt;p&gt;I regularly hand Claude Code a task that takes 20-40 minutes — "refactor the GST prep pipeline, add test coverage, run the suite, fix any regressions." It plans, executes, self-corrects, and comes back with a diff that's ready to review. The agentic loop is tight. No hallucinated file paths. No code that assumes packages that don't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. It respects the code that's already there
&lt;/h3&gt;

&lt;p&gt;Copilot rewrites style aggressively. Claude Code reads the file, matches existing conventions, and produces diffs that don't feel foreign two weeks later. For a consulting practice where I hand off code to clients' in-house teams, that matters more than it sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Claude Code Still Breaks
&lt;/h2&gt;

&lt;p&gt;Honest time. Three real failure modes I've hit.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Indian fintech APIs are still weak ground
&lt;/h3&gt;

&lt;p&gt;Ask Claude Code about the Zerodha Kite Connect SDK and it gets 80% right. The last 20% — ticker formats for F&amp;amp;O, post-2024 margin changes, specific error codes — is where it hallucinates plausibly. I always double-check anything broker-specific against the official docs. For one client I caught it confidently using a parameter name that was deprecated nine months ago. The test suite caught it before production did. Barely.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Long debug sessions can loop
&lt;/h3&gt;

&lt;p&gt;If the first three fixes don't resolve an issue, it sometimes cycles — tries approach A, moves to B, comes back to A wrapped in a helper. I've learned to stop the loop manually, paste the stack trace into a fresh context, and state the constraint explicitly ("do not change the signature of X"). The second attempt almost always lands.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cost at scale needs discipline
&lt;/h3&gt;

&lt;p&gt;Unconstrained, a single long agentic task can burn through tokens fast. For a big refactor I'll sometimes spend the equivalent of a cheap dinner in one session. That's still trivial against the time saved, but only if you're measuring. The techniques in how I cut a client's AI API bill from ₹85K to ₹12K/month apply here too — set bounded budgets, use smaller models for simple sub-tasks, and don't let agentic loops run without a ceiling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code vs Cursor vs Copilot — When I Use Each
&lt;/h2&gt;

&lt;p&gt;Simple rule of thumb, from six months of real use:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task Type&lt;/th&gt;
&lt;th&gt;My Pick&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New automation from scratch&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Plans across files, asks clarifying questions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-file editing at speed&lt;/td&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;Faster inline completions, tight editor loop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boilerplate-heavy typing&lt;/td&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;Cheapest, good at the obvious stuff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large refactor across 10+ files&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Nothing else holds this much context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Working in a legacy repo I don't know&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Reads and understands before writing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pair-programming over screen-share&lt;/td&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;Inline suggestions are less disruptive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All three stay installed. Picking the right one is like picking the right screwdriver — the mistake is treating one tool as the answer to every problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rupee Impact — What 40 Automations Looks Like in Numbers
&lt;/h2&gt;

&lt;p&gt;A summary from my consulting log since switching:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Build time:&lt;/strong&gt; 38% lower than my pre-Claude baseline on average.&lt;br&gt;
&lt;strong&gt;Client revisions:&lt;/strong&gt; Down by roughly half — better first drafts mean fewer "can you also..." cycles.&lt;br&gt;
&lt;strong&gt;Debugging time:&lt;/strong&gt; Up slightly, because I now take on projects I wouldn't have before.&lt;br&gt;
&lt;strong&gt;Capacity:&lt;/strong&gt; ₹40,000-₹70,000 of extra billable capacity per month. Over six months, a real second income line without hiring anyone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Non-Obvious Tip Most Teams Miss
&lt;/h2&gt;

&lt;p&gt;The setting that changed my workflow most: &lt;strong&gt;a CLAUDE.md file at the root of every project.&lt;/strong&gt; Claude Code reads it automatically. I put project context, naming conventions, the specific broker API version we're using, and our testing rules. It's the difference between getting a generic Python suggestion and getting a suggestion that knows we use Pandas 2.2, pytest, and a specific way of mocking Kite Connect.&lt;/p&gt;

&lt;p&gt;If you skip this step, you're using maybe 60% of the tool. I've seen teams adopt Claude Code, get indifferent results, and blame the model. Nine times out of ten, the CLAUDE.md was missing or empty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Switch?
&lt;/h2&gt;

&lt;p&gt;If you're already on Cursor and happy, don't rip it out. Layer Claude Code on top for planning and large refactors and see how the split feels for a month. If you're still on Copilot-only and doing anything more complex than boilerplate, the jump to Claude Code is the single highest-ROI tooling change I've made as an automation consultant this year.&lt;/p&gt;

&lt;p&gt;"Jo tool sahi kaam karta hai, wohi chuno." (Pick the tool that does the actual job.)&lt;/p&gt;

&lt;p&gt;Not everything should be automated, and not every process should be shipped with an AI pair programmer either. For production automations where quality and context matter more than keystroke speed, Claude Code is the best tool I've used. The ceiling is high. The floor is higher than any other assistant I've tried.&lt;/p&gt;

&lt;p&gt;Which AI coding tool are you reaching for most right now — and for what kind of work?&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>The CFO's AI Playbook: 5 Finance Automations Every Indian Business Should Run in 2026</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:53:49 +0000</pubDate>
      <link>https://dev.to/automate-archit/the-cfos-ai-playbook-5-finance-automations-every-indian-business-should-run-in-2026-2ld8</link>
      <guid>https://dev.to/automate-archit/the-cfos-ai-playbook-5-finance-automations-every-indian-business-should-run-in-2026-2ld8</guid>
      <description>&lt;p&gt;Over 60% of APAC finance leaders say AI-led automation is their top priority for 2026. For Indian businesses, that stat hides a quieter truth: most SMBs have no idea &lt;em&gt;which&lt;/em&gt; automation to start with.&lt;/p&gt;

&lt;p&gt;I've built finance automations for CA firms, D2C brands, trading desks, family-run manufacturers, and a few fintech startups. The pattern is always the same. Five finance processes eat the most hours, hide the most errors, and respond best to a simple Python layer on top of whatever ledger you already use.&lt;/p&gt;

&lt;p&gt;This is the playbook. No enterprise suite. No subscriptions you don't need.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Bank Reconciliation — The Single Biggest Time Sink
&lt;/h2&gt;

&lt;p&gt;Every finance team I meet has the same nightmare. Statements from three or four banks. Tally or Zoho on the other side. An Excel sheet in the middle. Eight hours a month — sometimes more — matching rows.&lt;/p&gt;

&lt;p&gt;We replaced it with a Python script that pulls statements from email attachments, categorizes transactions using keyword rules, cross-references entries with Tally, and flags only the mismatches. Eight hours dropped to fifteen minutes of review.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Tu 2 saal pehle kyu nahi mila?" (Why didn't I meet you two years ago?)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Cash Application — Matching Payments to Invoices
&lt;/h2&gt;

&lt;p&gt;In India, money arrives in more shapes than most tools expect: UPI, NEFT, RTGS, IMPS, cheques, partial payments, grouped settlements where one transfer covers four invoices.&lt;/p&gt;

&lt;p&gt;I build a three-layer pipeline. Layer one parses payment references. Layer two tries deterministic matches. Layer three hands ambiguous ones to a lightweight AI model that suggests matches with a confidence score.&lt;/p&gt;

&lt;p&gt;A D2C brand went from a seven-day receivables gap to same-day application. Their working capital position shifted by roughly ₹14 lakhs.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Real-Time P&amp;amp;L Reporting
&lt;/h2&gt;

&lt;p&gt;Most Indian SMB founders see their P&amp;amp;L twenty days after the month ends. A scheduled Python script pulls trial balance data overnight, categorizes new entries, and renders a dashboard with revenue, gross margin, operating expenses and EBITDA as of yesterday.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You stop making capital decisions on twenty-day-old data. For a business doing ₹30L/month, a single well-timed cut based on real-time numbers can move EBITDA by 2-3 percentage points.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. GST Filing Prep
&lt;/h2&gt;

&lt;p&gt;GSTR-1, GSTR-3B, and the quarterly reconciliations. I build GST prep bots that run on the 28th of every month. They pull sales and purchase data, compute filing figures, pull vendor GSTR-2A data via the GSTN API, flag reconciliation mismatches, and produce a filing-ready summary.&lt;/p&gt;

&lt;p&gt;A small manufacturing client went from three anxious days a month to a two-hour review window.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Expense Categorization
&lt;/h2&gt;

&lt;p&gt;Miscategorized expenses are a silent killer in Indian SMB P&amp;amp;Ls. Expense categorization automation uses an AI model trained on your own chart of accounts. High-confidence entries auto-categorize. The ambiguous 10-15% goes to a review queue.&lt;/p&gt;

&lt;p&gt;For a client with ~800 expense entries a month, this shifted their finance lead's time from 6 hours of categorization to 45 minutes of review. Accuracy went from ~82% to 97%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Five Automations at a Glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Automation&lt;/th&gt;
&lt;th&gt;Time Saved / Month&lt;/th&gt;
&lt;th&gt;Typical Rollout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bank reconciliation&lt;/td&gt;
&lt;td&gt;6-10 hours&lt;/td&gt;
&lt;td&gt;2-4 weekends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cash application&lt;/td&gt;
&lt;td&gt;15-25 hours&lt;/td&gt;
&lt;td&gt;3-6 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time P&amp;amp;L&lt;/td&gt;
&lt;td&gt;8-12 hours + faster decisions&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GST filing prep&lt;/td&gt;
&lt;td&gt;12-20 hours&lt;/td&gt;
&lt;td&gt;3-5 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expense categorization&lt;/td&gt;
&lt;td&gt;4-8 hours&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Stack all five and you're recovering 45-75 hours of skilled finance time every month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Start
&lt;/h2&gt;

&lt;p&gt;Do not try to build all five at once. Start with bank reconciliation — bounded, high-ROI, and an immediate win. Once it's running reliably for two months, pick the next one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Jo kaam AI se ho sakta hai, AI kare. Jo judgment se hota hai, woh humans ke paas rahe." (Let AI do what AI can do. Let judgment stay with humans.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which of these five is eating the most hours in your finance team right now?&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>Stock Screener Automation: How a Trader Replaced ₹47K/Month Advisory with a Python Script</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:46:15 +0000</pubDate>
      <link>https://dev.to/automate-archit/stock-screener-automation-how-a-trader-replaced-47kmonth-advisory-with-a-python-script-43bn</link>
      <guid>https://dev.to/automate-archit/stock-screener-automation-how-a-trader-replaced-47kmonth-advisory-with-a-python-script-43bn</guid>
      <description>&lt;p&gt;₹47,000 every month. That's what my friend Rohit was paying a fund advisory service to tell him which stocks matched his criteria. Six filters — RSI below 40, volume spike above 200% of 20-day average, 200-DMA crossover, sector rotation signals, delivery percentage above 60%, and promoter holding changes in the last quarter.&lt;/p&gt;

&lt;p&gt;One Sunday afternoon, a Python script, and a free broker API later — Rohit doesn't pay that ₹47,000 anymore. "Bhai, pehle 2 ghante screening mein jaate the. Ab chai peete peete list aa jaati hai."&lt;/p&gt;

&lt;p&gt;This is the story of how a retail trader replaced an expensive advisory with a script that costs literally nothing to run — and why this pattern applies to far more than just stock screening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: 2 Hours Every Morning, Staring at Screens
&lt;/h2&gt;

&lt;p&gt;Rohit is a swing trader based in Pune. He's been trading for seven years, and his edge has always been discipline — he never enters a trade without all six of his filters confirming. The problem was execution speed. Every morning before market open, he'd manually check 150+ stocks across three different screening tools, cross-reference the results, and build his watchlist.&lt;/p&gt;

&lt;p&gt;Two hours. Every single trading day. That's roughly 500 hours a year spent on a task that follows the exact same logic every time.&lt;/p&gt;

&lt;p&gt;The advisory service he subscribed to ran similar filters, but their shortlist arrived at 9:30 AM — 15 minutes after market open. By then, the best entry prices on momentum stocks were already gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: A Python Script That Runs Before You Wake Up
&lt;/h2&gt;

&lt;p&gt;The script connects to Rohit's broker API at 9:15 AM — one minute before market opens. It pulls the previous day's closing data for all NSE-listed stocks (roughly 2,000 symbols). Then it runs six filters in sequence.&lt;/p&gt;

&lt;p&gt;The entire filtering process takes about 12 seconds. By 9:16 AM, Rohit receives a WhatsApp message with a shortlist of 5-12 stocks that passed all six filters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The numbers that matter:&lt;/strong&gt; 2 hours/day reduced to 0 active time. ₹47,000/month advisory cancelled. Total recurring cost: ₹0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why This Works Better Than an Advisory Service
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speed.&lt;/strong&gt; An automated script delivers results in seconds. A team of analysts takes 30-45 minutes. In momentum trading, those minutes are the difference between a 2% gain and a missed entry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customisation.&lt;/strong&gt; Rohit's six filters are specific to his trading style. The advisory service overlapped about 70% with what he wanted. That remaining 30% mismatch meant he was still doing manual screening on top of the advisory's shortlist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adaptability.&lt;/strong&gt; When Rohit wanted to add a seventh filter last month (institutional buying from bulk deal data), it was live by Saturday evening. Try asking an advisory service to customise their methodology for one subscriber.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost Breakdown: ₹5.64L/Year Saved
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Advisory Service&lt;/th&gt;
&lt;th&gt;Python Script&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monthly cost&lt;/td&gt;
&lt;td&gt;₹47,000&lt;/td&gt;
&lt;td&gt;₹0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annual cost&lt;/td&gt;
&lt;td&gt;₹5,64,000&lt;/td&gt;
&lt;td&gt;₹2,000 (one-time API fee)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery time&lt;/td&gt;
&lt;td&gt;9:30 AM (15 min after open)&lt;/td&gt;
&lt;td&gt;9:16 AM (before open)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customisation&lt;/td&gt;
&lt;td&gt;Fixed filters&lt;/td&gt;
&lt;td&gt;Fully custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual screening still needed&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What You Actually Need to Build This
&lt;/h2&gt;

&lt;p&gt;You need Python 3.x with Pandas, a broker API account (Kite Connect from Zerodha at ₹2,000 one-time, or Fyers API v3 which is completely free), a server or always-on machine, and the WhatsApp Business API for notifications.&lt;/p&gt;

&lt;p&gt;If you've ever written an IF statement in Excel, you can understand the logic behind a stock screener script.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Lesson
&lt;/h2&gt;

&lt;p&gt;Rohit's story isn't really about stock screening. It's about a pattern: &lt;strong&gt;the most expensive services are often the ones running the simplest logic on publicly available data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The sweet spot for automation is repetitive tasks with clear rules and expensive human execution. Before you automate anything, ask yourself: Is the logic explicit enough to explain to a 10-year-old? Does the task repeat on a predictable schedule? Is the current cost of doing it manually more than the one-time cost of building the script?&lt;/p&gt;

&lt;p&gt;If all three answers are yes, you've found your next automation project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened After
&lt;/h2&gt;

&lt;p&gt;Six months in, Rohit's trading performance improved — not because the script picked better stocks, but because it freed his morning for what actually matters: reading quarterly results, analysing management commentary, and making judgment calls.&lt;/p&gt;

&lt;p&gt;That's what good automation does. It doesn't replace your expertise. It removes the mechanical layer so you can spend 100% of your time on the work that actually moves the needle.&lt;/p&gt;

</description>
      <category>python</category>
      <category>trading</category>
      <category>automation</category>
      <category>finance</category>
    </item>
    <item>
      <title>Why I Tell Clients NOT to Automate Everything — The Over-Automation Trap</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:44:43 +0000</pubDate>
      <link>https://dev.to/automate-archit/why-i-tell-clients-not-to-automate-everything-the-over-automation-trap-2p17</link>
      <guid>https://dev.to/automate-archit/why-i-tell-clients-not-to-automate-everything-the-over-automation-trap-2p17</guid>
      <description>&lt;p&gt;₹1,20,000. That's how much a client spent building an automated follow-up system I had to tell him to rip out thirty days later.&lt;/p&gt;

&lt;p&gt;I'm an automation consultant. My entire business depends on people wanting to automate things. And yet, the most valuable advice I give — the advice clients actually remember — is telling them what &lt;em&gt;not&lt;/em&gt; to automate.&lt;/p&gt;

&lt;p&gt;This might sound counterintuitive. But after building automation systems for CA firms, traders, e-commerce brands, and service businesses across India, I've developed a rule: &lt;strong&gt;the best automation experts say "no" more often than they say "yes."&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The ₹1.2 Lakh Mistake That Changed How I Consult
&lt;/h2&gt;

&lt;p&gt;A client ran a high-ticket consulting practice. His close rate was exceptional — north of 40% — because every prospect felt personally attended to. He'd send WhatsApp voice notes, check in on their business unprompted, and remember details from conversations months earlier.&lt;/p&gt;

&lt;p&gt;He came to me wanting to "scale" his follow-ups. We built a 4-touchpoint automated sequence: personalised messages triggered by pipeline stage, scheduled over 14 days. It was technically beautiful.&lt;/p&gt;

&lt;p&gt;His conversion rate dropped 40% in the first month.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Bhai, mere automation ne tera business slow kar diya." That's what I had to tell him. My automation slowed down his business.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem wasn't the technology. The problem was the assumption. His prospects weren't buying his service — they were buying &lt;em&gt;him&lt;/em&gt;. The personal touch wasn't a nice-to-have; it was the entire value proposition.&lt;/p&gt;

&lt;p&gt;We ripped it out. Went back to manual follow-ups. Conversions recovered within two weeks.&lt;/p&gt;

&lt;p&gt;That experience taught me something I now share with every new client: &lt;strong&gt;before you automate any customer-facing process, ask one question — "Does my customer want speed, or do they want ME?"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Processes You Should Never Automate
&lt;/h2&gt;

&lt;p&gt;After making this mistake and watching dozens of other businesses make similar ones, I've identified four categories of work where automation consistently backfires.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Relationship-Driven Interactions
&lt;/h3&gt;

&lt;p&gt;If your customer is paying a premium because they trust &lt;em&gt;you&lt;/em&gt; personally, automating your communication tells them they aren't worth your time. This applies to consulting, wealth management, legal advisory, and any high-ticket service where the relationship IS the product.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Processes That Change Every Quarter
&lt;/h3&gt;

&lt;p&gt;Automation works best on stable, repeatable workflows. If your process shifts every few months — because of regulatory changes, seasonal cycles, or evolving business models — you'll spend more time maintaining the automation than doing it manually.&lt;/p&gt;

&lt;p&gt;I had a client in the import-export space whose customs documentation process changed with every new trade circular. We built an automation. It broke within six weeks. We rebuilt it. It broke again. Eventually, the honest answer was: this process isn't stable enough to automate profitably.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. High-Exception Workflows
&lt;/h3&gt;

&lt;p&gt;Some workflows look simple on a whiteboard but have fifty edge cases in practice. ITR filing, for instance, has a core process that's highly automatable — but the exceptions require human judgment. The trick is automating the 80% that's mechanical and leaving the 20% for human expertise.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. When Maintenance Costs Exceed Manual Costs
&lt;/h3&gt;

&lt;p&gt;Every automation system has a maintenance burden. I use a simple calculation: if the annual maintenance cost is more than 60% of the manual effort it replaces, I advise against building it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The STAR Framework
&lt;/h2&gt;

&lt;p&gt;Before greenlighting any automation project, I run it through the STAR test:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stable:&lt;/strong&gt; Has the process been the same for at least 6 months? If not, wait.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transferable:&lt;/strong&gt; Can you explain the process to a new hire in under 30 minutes with zero ambiguity? If not, it has hidden complexity that will haunt the automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arithmetic:&lt;/strong&gt; Does the math work? Calculate: (hours saved × hourly rate) minus (build cost amortized over 12 months + monthly maintenance). If negative, don't build it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replaceable:&lt;/strong&gt; Is the human element genuinely replaceable, or is it the reason the customer pays? If a bot can do it without the customer noticing — automate away. If they'd notice and care — stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Skill Is Knowing Where to Draw the Line
&lt;/h2&gt;

&lt;p&gt;The automation industry has a bias problem. Every tool vendor, every course, every consultant has an incentive to say "yes, automate it." The revenue model rewards building, not advising against building.&lt;/p&gt;

&lt;p&gt;But the consultants who build lasting client relationships are the ones who occasionally say: "Don't automate this. Here's why. Here's what to do instead."&lt;/p&gt;

&lt;p&gt;The best automation isn't about replacing everything. It's about knowing which 80% to automate so you can be 100% present for the 20% that actually matters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Jo har cheez automate karta hai, wo kisi cheez mein mahir nahi hota." — The one who automates everything masters nothing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next time you're tempted to automate a process, run it through the STAR test first. You might save yourself ₹1.2 lakh and a very awkward phone call to your client.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>strategy</category>
      <category>consulting</category>
      <category>python</category>
    </item>
    <item>
      <title>Build a GST Invoice Parser in 70 Lines of Python</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 20 Jun 2026 03:41:45 +0000</pubDate>
      <link>https://dev.to/automate-archit/build-a-gst-invoice-parser-in-70-lines-of-python-h50</link>
      <guid>https://dev.to/automate-archit/build-a-gst-invoice-parser-in-70-lines-of-python-h50</guid>
      <description>&lt;p&gt;If you run a small business in India, you know the monthly ritual: a folder full of vendor invoice PDFs, and a spreadsheet that needs GSTIN, invoice number, date, taxable value, and GST amounts pulled out of every single one. Doing it by hand takes hours. Let's automate it in about 70 lines of Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we're building
&lt;/h2&gt;

&lt;p&gt;A script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scans a folder of invoice PDFs&lt;/li&gt;
&lt;li&gt;Extracts GSTIN, invoice number, date, taxable value, CGST/SGST/IGST, and total&lt;/li&gt;
&lt;li&gt;Validates the GSTIN format (including the checksum-style structure)&lt;/li&gt;
&lt;li&gt;Writes everything to a clean CSV you can import into Tally or Excel&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pdfplumber
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the only dependency. &lt;code&gt;pdfplumber&lt;/code&gt; handles text extraction from digitally generated PDFs (which most GST invoices are).&lt;/p&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pdfplumber&lt;/span&gt;

&lt;span class="c1"&gt;# GSTIN: 2-digit state code + 10-char PAN + entity code + 'Z' + check char
&lt;/span&gt;&lt;span class="n"&gt;GSTIN_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b\d{2}[A-Z]{5}\d{4}[A-Z]\d[A-Z]\d\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;INV_NO_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?:Invoice\s*(?:No|Number|#)\.?\s*[:\-]?\s*)([A-Z0-9\/\-]+)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;DATE_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4})\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;AMOUNT_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?:\u20b9|Rs\.?|INR)\s*([\d,]+\.?\d*)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;LABELS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taxable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taxable\s*(?:value|amount)\s*[:\-]?\s*(?:\u20b9|Rs\.?|INR)?\s*([\d,]+\.?\d*)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cgst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CGST[^\d]*([\d,]+\.\d{2})&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sgst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SGST[^\d]*([\d,]+\.\d{2})&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;igst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IGST[^\d]*([\d,]+\.\d{2})&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?:grand\s*total|total\s*amount|amount\s*payable)\s*[:\-]?\s*(?:\u20b9|Rs\.?|INR)?\s*([\d,]+\.?\d*)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;STATE_CODES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid_gstin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gstin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GSTIN_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fullmatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gstin&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;gstin&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;STATE_CODES&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pdfplumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;gstins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;GSTIN_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;valid_gstin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;inv_no&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;INV_NO_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DATE_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vendor_gstin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gstins&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;gstins&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NOT FOUND&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoice_no&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inv_no&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;inv_no&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NOT FOUND&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NOT FOUND&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LABELS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

    &lt;span class="c1"&gt;# Sanity check: taxable + taxes should roughly equal total
&lt;/span&gt;    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;taxable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cgst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sgst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;igst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mismatch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YES&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pdfs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;pdfs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No PDFs found in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;parse_invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pdfs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoices_extracted.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fieldnames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Parsed &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; invoices -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flagged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mismatch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;flagged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Warning: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flagged&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; invoice(s) have tax totals that don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t add up — check manually.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python gst_parser.py ~/Downloads/vendor-invoices/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parsed 23 invoices -&amp;gt; invoices_extracted.csv
Warning: 2 invoice(s) have tax totals that don't add up — check manually.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That mismatch flag is my favourite part. It catches data-entry errors on the vendor's side &lt;em&gt;and&lt;/em&gt; extraction failures on ours — anything where taxable value + CGST + SGST + IGST doesn't land within ₹1 of the stated total gets flagged for a human look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why regex and not AI?
&lt;/h2&gt;

&lt;p&gt;For digitally generated invoices, regex is faster, free, and deterministic. A month of invoices parses in under two seconds with zero API costs. Where this approach breaks down is scanned/photographed invoices — for those, add an OCR step with &lt;code&gt;pytesseract&lt;/code&gt; before the regex pass, or hand the text to an LLM for extraction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three upgrades worth making
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vendor name capture.&lt;/strong&gt; Most invoices put the vendor name within a couple of lines of the GSTIN. Grab the surrounding lines and you can auto-fill the vendor column too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GSTIN verification.&lt;/strong&gt; The format check above catches typos, but the government's GST portal can confirm a GSTIN is actually registered. Useful before claiming input tax credit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HSN code extraction.&lt;/strong&gt; If you need item-level detail for GSTR filings, &lt;code&gt;pdfplumber&lt;/code&gt;'s &lt;code&gt;extract_tables()&lt;/code&gt; handles the line-item tables most invoice formats use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Seventy lines, one dependency, and the monthly invoice grind becomes a two-second script run. The same pattern — extract text, regex the fields you care about, validate, write CSV — works for bank statements, salary slips, and purchase orders too.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me on Twitter @automate_archit for daily AI automation tips.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Build a GST Invoice Generator in 87 Lines of Python</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 20 Jun 2026 03:40:49 +0000</pubDate>
      <link>https://dev.to/automate-archit/build-a-gst-invoice-generator-in-87-lines-of-python-106m</link>
      <guid>https://dev.to/automate-archit/build-a-gst-invoice-generator-in-87-lines-of-python-106m</guid>
      <description>&lt;p&gt;If you freelance or run a small business in India, you have probably paid for invoicing software that does one thing: multiply numbers and put them in a PDF. Today we will build that ourselves — a GST-compliant tax invoice generator that reads line items from a CSV and produces a clean PDF, in 87 lines of Python.&lt;/p&gt;

&lt;p&gt;It handles the part everyone gets wrong: the CGST/SGST vs IGST split. Intra-state sales split the tax into equal CGST and SGST halves; inter-state sales charge a single IGST. Our script decides automatically by comparing the first two digits of the buyer's and seller's GSTINs (those digits are the state code).&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll need
&lt;/h2&gt;

&lt;p&gt;One dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fpdf2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fpdf2&lt;/code&gt; is a maintained, pure-Python PDF library — no system packages, works the same on Windows, Mac, and Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  The input format
&lt;/h2&gt;

&lt;p&gt;Keep your line items in a plain CSV. Anyone on your team can edit this in Excel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;description,hsn,qty,rate,gst_pct
Website development,998314,1,45000,18
Annual hosting,998315,1,12000,18
SSL certificate,998316,2,1500,18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The full code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;GST invoice generator — reads line items from CSV, outputs a PDF invoice.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fpdf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FPDF&lt;/span&gt;

&lt;span class="n"&gt;SELLER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Acme Tech Services Pvt Ltd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;221 MG Road, Bengaluru, KA 560001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gstin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;29ABCDE1234F1Z5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;29&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hsn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hsn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gst_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gst_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_totals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interstate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;taxable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;tax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;taxable&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gst_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
        &lt;span class="n"&gt;subtotal&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;taxable&lt;/span&gt;
        &lt;span class="n"&gt;tax_total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;taxable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interstate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FPDF&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Helvetica&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TAX INVOICE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;align&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Helvetica&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SELLER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | GSTIN: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SELLER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gstin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SELLER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invoice date: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-%&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;-%&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  |  Bill to: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
             &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (GSTIN: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gstin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Helvetica&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;widths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HSN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Qty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rate (Rs)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GST %&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Amount (Rs)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Helvetica&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;taxable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hsn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gst_pct&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;taxable&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Helvetica&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Taxable value: Rs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;interstate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IGST: Rs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tax_total&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CGST: Rs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tax_total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;   SGST: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                 &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tax_total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Grand total: Rs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;new_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LMARGIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NEXT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;csv_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;items.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;buyer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Globex Retail LLP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gstin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;27PQRSX5678G1Z3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;interstate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gstin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;SELLER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_totals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;load_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv_path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;interstate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;build_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buyer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interstate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoice.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoice.pdf written - grand total Rs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tax_total&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python gst_invoice.py items.csv
&lt;span class="c"&gt;# invoice.pdf written - grand total Rs 70,800.00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Loading (&lt;code&gt;load_items&lt;/code&gt;).&lt;/strong&gt; &lt;code&gt;csv.DictReader&lt;/code&gt; turns each CSV row into a dict keyed by the header row, so the code reads like the spreadsheet. We cast &lt;code&gt;qty&lt;/code&gt;, &lt;code&gt;rate&lt;/code&gt;, and &lt;code&gt;gst_pct&lt;/code&gt; to floats up front so the math functions never deal with strings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tax math (&lt;code&gt;compute_totals&lt;/code&gt;).&lt;/strong&gt; Each line's taxable value is &lt;code&gt;qty x rate&lt;/code&gt;, and tax is a simple percentage of that. We accumulate a subtotal and a tax total and keep the per-row figures for the PDF table. The interstate decision happens once, in the entrypoint: &lt;code&gt;buyer GSTIN state code != seller state code&lt;/code&gt; means IGST applies. In our example the buyer's GSTIN starts with &lt;code&gt;27&lt;/code&gt; (Maharashtra) and the seller's with &lt;code&gt;29&lt;/code&gt; (Karnataka), so the invoice shows a single IGST line. Change the buyer's GSTIN to start with &lt;code&gt;29&lt;/code&gt; and you will see it split into equal CGST and SGST halves instead — no other change needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The PDF (&lt;code&gt;build_pdf&lt;/code&gt;).&lt;/strong&gt; &lt;code&gt;fpdf2&lt;/code&gt;'s &lt;code&gt;cell()&lt;/code&gt; API is old-school but predictable: each cell has a fixed width, &lt;code&gt;border=1&lt;/code&gt; draws the table lines, and &lt;code&gt;new_y="NEXT"&lt;/code&gt; moves the cursor down a row. The &lt;code&gt;widths&lt;/code&gt; tuple is the entire layout — adjust six numbers and the whole table reflows. Total layout code: about 40 lines, and you own every pixel of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending it
&lt;/h2&gt;

&lt;p&gt;A few upgrades that each take only a handful of lines: pull &lt;code&gt;SELLER&lt;/code&gt; and the buyer from a JSON config instead of hardcoding; add an invoice number that auto-increments from a counter file; loop over a folder of CSVs to batch-generate a month of invoices; or add &lt;code&gt;pdf.image("logo.png", x=10, y=8, w=30)&lt;/code&gt; for letterhead branding.&lt;/p&gt;

&lt;p&gt;One honest caveat: this covers the common single-rate service invoice. If you deal with cess, reverse charge, or e-invoicing (IRN/QR codes), those are regimes of their own — treat this as the foundation, not a compliance department.&lt;/p&gt;

&lt;p&gt;That's a working invoice pipeline in 87 lines — CSV in, compliant PDF out, and the tax split handled correctly without a subscription.&lt;/p&gt;

&lt;p&gt;Follow me on Twitter @automate_archit for daily AI automation tips.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Claude Code vs Cursor vs Copilot: An Honest Review After 40 Production Automations</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 20 Jun 2026 03:39:36 +0000</pubDate>
      <link>https://dev.to/automate-archit/claude-code-vs-cursor-vs-copilot-an-honest-review-after-40-production-automations-516m</link>
      <guid>https://dev.to/automate-archit/claude-code-vs-cursor-vs-copilot-an-honest-review-after-40-production-automations-516m</guid>
      <description>&lt;p&gt;₹40,000 to ₹70,000 — that's the extra monthly capacity my consulting practice has picked up since switching my primary dev loop to Claude Code six months ago. Forty production automations shipped in that window: bank reconciliation pipelines, stock screeners, ITR-prep bots, expense categorizers, GST filing helpers, a couple of trading systems I still babysit.&lt;/p&gt;

&lt;p&gt;This post is the scorecard. What Claude Code gets right, where it still breaks, and how I decide when to reach for it versus Cursor versus plain GitHub Copilot. No sponsored angle, no affiliate link. I pay for all three out of pocket. What follows is what I'd tell a friend over chai.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context — Who This Review Is For
&lt;/h2&gt;

&lt;p&gt;I'm not a web app engineer. I build finance and trading automations in Python, glue them to broker APIs and Google Sheets, and ship scripts that run on cron jobs or Railway containers. If you build similar back-end, script-first work, this review will transfer cleanly. If you're writing React all day, your mileage will differ.&lt;/p&gt;

&lt;p&gt;The bar I measure against is brutal. A client automation has to work on day one against real production data, handle every edge case a CA firm can dream up, and be debuggable by me at 11 PM when a trade doesn't fire. No tolerance for "it worked on my machine."&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude Code Gets Right — The Four Wins That Actually Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Multi-file reasoning at a level nothing else touches
&lt;/h3&gt;

&lt;p&gt;Most AI coding assistants play well inside a single file. Claude Code holds an entire repo in its head. I asked it to refactor a bank-reconciliation project that spans eleven modules and 2,300 lines — it traced every call site, flagged one circular import I'd never noticed, and proposed a clean split in a single turn. Cursor starts to struggle past six or seven files. Copilot gives up around two.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. It asks the right questions before writing code
&lt;/h3&gt;

&lt;p&gt;This surprised me. When I told Claude Code to "add retry logic to the Zerodha order function," it didn't just write it. It asked whether the retry should respect the broker's rate limits, what to do on partial fills, and whether idempotency keys were available. Those are the questions a senior engineer would ask. The answers shape whether the automation is safe for real money or a ticking time bomb.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Long-running tasks stay coherent
&lt;/h3&gt;

&lt;p&gt;I regularly hand Claude Code a task that takes 20-40 minutes — "refactor the GST prep pipeline, add test coverage, run the suite, fix any regressions." It plans, executes, self-corrects, and comes back with a diff that's ready to review. The agentic loop is tight. No hallucinated file paths. No code that assumes packages that don't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. It respects the code that's already there
&lt;/h3&gt;

&lt;p&gt;Copilot rewrites style aggressively. Claude Code reads the file, matches existing conventions, and produces diffs that don't feel foreign two weeks later. For a consulting practice where I hand off code to clients' in-house teams, that matters more than it sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Claude Code Still Breaks
&lt;/h2&gt;

&lt;p&gt;Honest time. Three real failure modes I've hit.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Indian fintech APIs are still weak ground
&lt;/h3&gt;

&lt;p&gt;Ask Claude Code about the Zerodha Kite Connect SDK and it gets 80% right. The last 20% — ticker formats for F&amp;amp;O, post-2024 margin changes, specific error codes — is where it hallucinates plausibly. I always double-check anything broker-specific against the official docs. For one client I caught it confidently using a parameter name that was deprecated nine months ago. The test suite caught it before production did. Barely.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Long debug sessions can loop
&lt;/h3&gt;

&lt;p&gt;If the first three fixes don't resolve an issue, it sometimes cycles — tries approach A, moves to B, comes back to A wrapped in a helper. I've learned to stop the loop manually, paste the stack trace into a fresh context, and state the constraint explicitly ("do not change the signature of X"). The second attempt almost always lands.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cost at scale needs discipline
&lt;/h3&gt;

&lt;p&gt;Unconstrained, a single long agentic task can burn through tokens fast. For a big refactor I'll sometimes spend the equivalent of a cheap dinner in one session. That's still trivial against the time saved, but only if you're measuring. The techniques in &lt;a href="https://architmittal.com/blog/ai-api-cost-optimization-85k-to-12k" rel="noopener noreferrer"&gt;how I cut a client's AI API bill from ₹85K to ₹12K/month&lt;/a&gt; apply here too — set bounded budgets, use smaller models for simple sub-tasks, and don't let agentic loops run without a ceiling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code vs Cursor vs Copilot — When I Use Each
&lt;/h2&gt;

&lt;p&gt;Simple rule of thumb, from six months of real use:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task Type&lt;/th&gt;
&lt;th&gt;My Pick&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New automation from scratch&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Plans across files, asks clarifying questions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single-file editing at speed&lt;/td&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;Faster inline completions, tight editor loop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boilerplate-heavy typing&lt;/td&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;Cheapest, good at the obvious stuff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large refactor across 10+ files&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Nothing else holds this much context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Working in a legacy repo I don't know&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Reads and understands before writing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pair-programming over screen-share&lt;/td&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;Inline suggestions are less disruptive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All three stay installed. Picking the right one is like picking the right screwdriver — the mistake is treating one tool as the answer to every problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rupee Impact — What 40 Automations Looks Like in Numbers
&lt;/h2&gt;

&lt;p&gt;A summary from my consulting log since switching:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Build time:&lt;/strong&gt; 38% lower than my pre-Claude baseline on average.&lt;br&gt;
&lt;strong&gt;Client revisions:&lt;/strong&gt; Down by roughly half — better first drafts mean fewer "can you also..." cycles.&lt;br&gt;
&lt;strong&gt;Debugging time:&lt;/strong&gt; Up slightly, because I now take on projects I wouldn't have before.&lt;br&gt;
&lt;strong&gt;Capacity:&lt;/strong&gt; ₹40,000-₹70,000 of extra billable capacity per month. Over six months, a real second income line without hiring anyone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The same tooling shift that helped me ship a &lt;a href="https://architmittal.com/blog/weekend-python-script-ca-firm-209-hours-itr" rel="noopener noreferrer"&gt;weekend Python script that saved a CA firm 209 hours during ITR season&lt;/a&gt; is now the default for every new project — from the &lt;a href="https://architmittal.com/blog/stock-screener-automation-trader-replaced-47k-advisory-python" rel="noopener noreferrer"&gt;stock screener that replaced a ₹47K/month advisory&lt;/a&gt; to the full &lt;a href="https://architmittal.com/blog/cfos-ai-playbook-finance-automation-india-2026" rel="noopener noreferrer"&gt;CFO playbook of five finance automations&lt;/a&gt; I rolled out to two SMBs this quarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Non-Obvious Tip Most Teams Miss
&lt;/h2&gt;

&lt;p&gt;The setting that changed my workflow most: &lt;strong&gt;a CLAUDE.md file at the root of every project.&lt;/strong&gt; Claude Code reads it automatically. I put project context, naming conventions, the specific broker API version we're using, and our testing rules. It's the difference between getting a generic Python suggestion and getting a suggestion that knows we use Pandas 2.2, pytest, and a specific way of mocking Kite Connect.&lt;/p&gt;

&lt;p&gt;If you skip this step, you're using maybe 60% of the tool. I've seen teams adopt Claude Code, get indifferent results, and blame the model. Nine times out of ten, the CLAUDE.md was missing or empty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Switch?
&lt;/h2&gt;

&lt;p&gt;If you're already on Cursor and happy, don't rip it out. Layer Claude Code on top for planning and large refactors and see how the split feels for a month. If you're still on Copilot-only and doing anything more complex than boilerplate, the jump to Claude Code is the single highest-ROI tooling change I've made as an automation consultant this year.&lt;/p&gt;

&lt;p&gt;"Jo tool sahi kaam karta hai, wohi chuno." (Pick the tool that does the actual job.)&lt;/p&gt;

&lt;p&gt;Not everything should be automated, and &lt;a href="https://architmittal.com/blog/over-automation-trap-when-not-to-automate" rel="noopener noreferrer"&gt;not every process should be shipped with an AI pair programmer either&lt;/a&gt;. For production automations where quality and context matter more than keystroke speed, Claude Code is the best tool I've used. The ceiling is high. The floor is higher than any other assistant I've tried.&lt;/p&gt;

&lt;p&gt;Which AI coding tool are you reaching for most right now — and for what kind of work?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Archit Mittal helps businesses automate chaos. Follow on LinkedIn: &lt;a href="https://linkedin.com/in/automate-archit" rel="noopener noreferrer"&gt;@automate-archit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get automation insights every Saturday — join The Automation Dispatch at &lt;a href="https://architmittal.com/newsletter" rel="noopener noreferrer"&gt;architmittal.com/newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>productivity</category>
      <category>python</category>
    </item>
    <item>
      <title>How a Weekend Python Script Saved a CA Firm 209 Hours During ITR Season</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 20 Jun 2026 03:38:01 +0000</pubDate>
      <link>https://dev.to/automate-archit/how-a-weekend-python-script-saved-a-ca-firm-209-hours-during-itr-season-3lng</link>
      <guid>https://dev.to/automate-archit/how-a-weekend-python-script-saved-a-ca-firm-209-hours-during-itr-season-3lng</guid>
      <description>&lt;h1&gt;
  
  
  How a Weekend Python Script Saved a CA Firm 209 Hours During ITR Season
&lt;/h1&gt;

&lt;p&gt;₹3,12,000. That's what Rajesh Sharma's CA firm in Jaipur spent every ITR season hiring three temporary data entry operators for two months. They'd sit in a back room extracting numbers from Form 16 PDFs, cross-checking PAN details against the income tax portal, and pre-filling ITR forms — one cell at a time, one return at a time, 340 returns total.&lt;/p&gt;

&lt;p&gt;Last July, a single Python script replaced that entire process. Built in one weekend. Running cost: ₹0. Time saved across the season: 209 hours.&lt;/p&gt;

&lt;p&gt;This is not a theoretical tutorial. This is what actually happened, with real numbers, real friction, and the parts that almost went wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: ITR Season Is a Two-Month Data Entry Marathon
&lt;/h2&gt;

&lt;p&gt;If you've never worked inside a CA firm during July–September, here's what it looks like. Clients send Form 16 PDFs over WhatsApp — sometimes as photos, sometimes as scanned copies with coffee stains. The firm's staff manually opens each PDF, types salary figures into a master Excel sheet, cross-references PAN numbers on the income tax portal, and fills in the ITR form fields one by one.&lt;/p&gt;

&lt;p&gt;Rajesh's firm handled 340 individual ITRs last year. Each return took an average of 38 minutes of pure data processing before a CA even looked at it for deductions and exemptions. That's 215 hours of someone staring at PDFs and typing numbers into boxes.&lt;/p&gt;

&lt;p&gt;The three temporary hires cost ₹1,04,000 each for the season — ₹3,12,000 total. And they still made errors. Rajesh's senior CA spent another 40+ hours catching and fixing data entry mistakes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Har saal yahi hota tha. Teen log hire karo, train karo, phir unki galtiyan dhundo. It felt like we were paying people to create problems we'd solve ourselves."&lt;br&gt;
(Every year the same thing. Hire three people, train them, then find their mistakes.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Script: What It Actually Does
&lt;/h2&gt;

&lt;p&gt;I didn't build Rajesh an AI platform. I didn't sell him a subscription. I built a Python script that does three things — and does them well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 1: PDF Text Extraction
&lt;/h3&gt;

&lt;p&gt;The script uses an open-source PDF library to read every Form 16 PDF in a folder. It extracts employer name, PAN, salary breakdowns (basic, HRA, special allowance), TDS deducted, and Section 80C/80D declarations. For scanned or photo PDFs — which made up about 30% of the documents — it falls back to OCR using Tesseract, another free tool.&lt;/p&gt;

&lt;p&gt;This stage alone eliminated about 70% of the manual typing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: Validation and Cross-Check
&lt;/h3&gt;

&lt;p&gt;Every extracted PAN is validated against a checksum algorithm (PAN numbers follow a specific format — the script catches typos instantly). Salary totals are cross-checked: does basic + HRA + special allowance + other components equal gross salary? If not, the return gets flagged for manual review instead of silently carrying an error forward.&lt;/p&gt;

&lt;p&gt;This is where the script outperformed humans consistently. The temporary hires caught about 60% of calculation mismatches. The script catches 100% — because it doesn't get tired at 4 PM on a Thursday.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: Pre-Filled Output
&lt;/h3&gt;

&lt;p&gt;The script generates a structured spreadsheet with every field mapped to the ITR form layout. Rajesh's CAs open the sheet, review the numbers, apply their professional judgment on deductions and exemptions, and file. The 38-minute-per-return data processing step dropped to about 6 minutes of review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Numbers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before: 38 min/return x 340 returns = 215 hours of data processing&lt;/li&gt;
&lt;li&gt;After: 6 min/return x 340 returns = 34 hours of CA review&lt;/li&gt;
&lt;li&gt;Net saving: ~209 hours (after accounting for the 28 returns flagged for manual processing)&lt;/li&gt;
&lt;li&gt;Cost saving: ₹3,12,000 in seasonal hiring — replaced by a script with ₹0 running cost&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Almost Went Wrong
&lt;/h2&gt;

&lt;p&gt;I'd be lying if I said the script worked perfectly from day one. Two things nearly derailed it.&lt;/p&gt;

&lt;p&gt;The first problem was PDF variety. Indian employers don't follow a standard Form 16 template. Some PDFs had salary components in tables, others in plain text paragraphs, and a few used formats I'd never seen — with Devanagari headers mixed into English content. The first version of the script handled about 75% of PDFs correctly. I spent the second day of that weekend writing fallback extraction logic for edge cases. By the end, it handled 92% automatically — the remaining 8% (28 returns) got flagged for manual processing.&lt;/p&gt;

&lt;p&gt;The second problem was trust. Rajesh didn't trust the script's output initially — and he shouldn't have. We ran a parallel test: his staff processed the first 50 returns manually while the script processed the same 50. We compared outputs line by line. The script matched human output on 47 returns and was actually &lt;em&gt;more accurate&lt;/em&gt; on the other 3 (the staff had made small transcription errors).&lt;/p&gt;

&lt;p&gt;That parallel test took an extra day but bought something no amount of demos could: Rajesh's confidence that the numbers were right.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Jab tak maine apni aankhon se comparison nahi dekha, mujhe yakeen nahi aaya. But the numbers don't lie."&lt;br&gt;
(Until I saw the comparison with my own eyes, I didn't believe it. But the numbers don't lie.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why This Matters Beyond One CA Firm
&lt;/h2&gt;

&lt;p&gt;India has over 3.5 lakh practising Chartered Accountants. The vast majority of small and mid-size firms still process ITRs the way Rajesh used to — manually, with seasonal hires, under deadline pressure that leads to errors and late nights.&lt;/p&gt;

&lt;p&gt;The automation here isn't complicated. It's not an AI model that needs training data or a cloud platform that costs ₹50,000/month. It's a Python script using free libraries, running on the same laptop the CA already owns. The total infrastructure cost is zero.&lt;/p&gt;

&lt;p&gt;What it requires is someone who understands both the accounting workflow and the code — or a CA willing to work with someone who does. That intersection is where the real value lives. Not in the technology itself, but in knowing which 80% of the process is pure data movement and which 20% genuinely needs a Chartered Accountant's brain.&lt;/p&gt;

&lt;p&gt;If you're a CA firm owner reading this: you don't need to learn Python. You need to find someone who can spend a weekend understanding your Form 16 processing workflow and write a script tailored to it. The ROI pays for itself before August.&lt;/p&gt;

&lt;p&gt;And if you're a developer looking for freelance projects: ITR season starts in July. CA firms start panicking in June. That's your window. The ones who've done it manually for 20 years are the ones most ready to try something different — they just need someone to show them it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can a Python script really automate ITR filing for a CA firm?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. A Python script can automate the repetitive data extraction, validation, and pre-filling stages of ITR preparation. The CA still reviews and signs off on every return — the script handles the 80% of work that is pure data movement, not professional judgment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much time can automation save during ITR season?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this case, a single script saved 209 hours across one ITR season by automating PDF extraction, data validation, and form pre-filling. The exact savings depend on your firm's volume and how manual your current process is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it legal for CA firms to use automation scripts for ITR filing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Absolutely. The automation handles data processing — extracting numbers from Form 16s, validating PAN details, and pre-filling fields. The Chartered Accountant still reviews every return, applies professional judgment, and digitally signs the final filing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does it cost to build an ITR automation script?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The script in this case study was built in a single weekend using free, open-source Python libraries. Total running cost: ₹0. No SaaS subscriptions, no API fees, no licensing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Archit Mittal helps businesses automate chaos. Follow on LinkedIn: &lt;a href="https://linkedin.com/in/automate-archit" rel="noopener noreferrer"&gt;@automate-archit&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get automation insights every Saturday — join &lt;a href="https://architmittal.com/newsletter" rel="noopener noreferrer"&gt;The Automation Dispatch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>fintech</category>
      <category>india</category>
    </item>
    <item>
      <title>How I Cut a Client's AI API Bill from ₹85K to ₹12K/Month — Without Losing Quality</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 20 Jun 2026 03:36:49 +0000</pubDate>
      <link>https://dev.to/automate-archit/how-i-cut-a-clients-ai-api-bill-from-85k-to-12kmonth-without-losing-quality-24hm</link>
      <guid>https://dev.to/automate-archit/how-i-cut-a-clients-ai-api-bill-from-85k-to-12kmonth-without-losing-quality-24hm</guid>
      <description>&lt;p&gt;₹85,000 per month. That was the AI API bill sitting in my client's inbox when they called me in a mild panic last quarter. They run a mid-sized e-commerce operation in Pune — about 4,000 orders a day — and had integrated AI into customer support, product descriptions, and internal reporting. The AI was working beautifully. The invoice was not.&lt;/p&gt;

&lt;p&gt;"Archit bhai, AI toh kaam kar raha hai, lekin cost control se bahar ja raha hai." (The AI is working, but the costs are spiralling out of control.)&lt;/p&gt;

&lt;p&gt;Three weeks later, their monthly bill was ₹12,400. Same tasks. Same quality. No corners cut. Here's exactly what changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem: Every Task Was Using the Most Expensive Model
&lt;/h2&gt;

&lt;p&gt;When I audited their setup, the issue was obvious within five minutes. Every single API call — whether it was classifying a customer complaint into one of 8 categories or generating a 2,000-word product description — was hitting the same premium model. It's the most common mistake I see with businesses adopting AI: they pick one model during the proof-of-concept phase and never revisit that decision as they scale.&lt;/p&gt;

&lt;p&gt;Think of it this way. You wouldn't hire a senior chartered accountant to do data entry. But that's essentially what was happening — a top-tier reasoning model was being used to answer "Is this complaint about shipping or billing?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix #1: Model Routing — The Single Biggest Cost Lever
&lt;/h2&gt;

&lt;p&gt;Model routing is the practice of sending each task to the cheapest model that can handle it at acceptable quality. I categorized their ~47 distinct API call types into three tiers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Task Types&lt;/th&gt;
&lt;th&gt;Model Class&lt;/th&gt;
&lt;th&gt;Cost Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Simple&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Classification, extraction, yes/no decisions, formatting&lt;/td&gt;
&lt;td&gt;Lightweight (Haiku-class)&lt;/td&gt;
&lt;td&gt;~90% cheaper per call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Medium&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Summarization, short-form content, template-based responses&lt;/td&gt;
&lt;td&gt;Mid-tier (Sonnet-class)&lt;/td&gt;
&lt;td&gt;~50% cheaper per call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Complex&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Long product descriptions, nuanced customer responses, analytics reports&lt;/td&gt;
&lt;td&gt;Premium (Opus-class)&lt;/td&gt;
&lt;td&gt;Full price — but only 12% of calls&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The result? 68% of their API calls moved to the lightweight tier, 20% to mid-tier, and only 12% stayed on premium. That single change dropped the bill from ₹85K to roughly ₹38K. No quality degradation — we ran A/B tests on customer satisfaction scores for two weeks before fully switching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix #2: Prompt Caching — Stop Paying for the Same Context Twice
&lt;/h2&gt;

&lt;p&gt;Their customer support bot sent the same 1,200-token system prompt with every single API call. That's company policies, tone guidelines, product catalog context — all identical across thousands of daily calls. Every call was paying full input token pricing for information the model had already processed moments ago.&lt;/p&gt;

&lt;p&gt;Prompt caching solves this. The first call processes the full system prompt, and subsequent calls within the cache window reference it at a fraction of the cost. For their volume — around 6,000 support interactions per day — this alone saved ₹8,000-10,000 monthly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick math:&lt;/strong&gt; 6,000 calls/day x 1,200 tokens x 30 days = 216 million input tokens/month just on repeated system prompts. At standard pricing, that's a significant chunk of the bill that prompt caching nearly eliminates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Fix #3: Batching Non-Urgent Requests
&lt;/h2&gt;

&lt;p&gt;Not everything needs a real-time response. Their internal reporting pipeline — daily sales summaries, inventory alerts, marketing performance digests — was making individual API calls as each data point came in. Sixty to eighty calls that could easily be batched into three or four.&lt;/p&gt;

&lt;p&gt;We restructured their reporting to collect data throughout the day and process it in batch windows — once at 6 AM, once at 2 PM, once at 10 PM. Batch API pricing is typically 50% cheaper than real-time, and for internal reports, a few hours of delay is completely acceptable.&lt;/p&gt;

&lt;p&gt;"Pehle har choti cheez ke liye alag call jaati thi. Ab ek baar mein sab ho jaata hai." (Earlier, every small thing triggered a separate call. Now everything processes at once.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix #4: Output Token Discipline
&lt;/h2&gt;

&lt;p&gt;This one is subtle but adds up fast. Their product description prompts asked the model to "write a detailed, comprehensive product description." The model happily obliged — averaging 800-1,000 tokens per response when the actual requirement was 200-300 tokens for their product cards.&lt;/p&gt;

&lt;p&gt;We rewrote prompts with explicit length constraints and structured output formats. Instead of open-ended generation, the model received exact specifications: "Write a product description in exactly 3 sentences. First sentence: what it is. Second: key benefit. Third: who it's for."&lt;/p&gt;

&lt;p&gt;Output tokens are more expensive than input tokens on most providers. Cutting average output length by 60% across thousands of daily calls compounded into real savings.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Final Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Optimization&lt;/th&gt;
&lt;th&gt;Monthly Savings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model routing&lt;/td&gt;
&lt;td&gt;₹47,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt caching&lt;/td&gt;
&lt;td&gt;₹9,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request batching&lt;/td&gt;
&lt;td&gt;₹8,200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output token discipline&lt;/td&gt;
&lt;td&gt;₹7,900&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total monthly bill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;₹12,400 (down from ₹85,000)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's an 85% reduction. The AI does exactly the same work. The customer satisfaction score actually went &lt;em&gt;up&lt;/em&gt; by 3% — likely because the lighter models respond faster, and customers prefer quicker replies over marginally more eloquent ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Most People Get Wrong About AI Costs
&lt;/h2&gt;

&lt;p&gt;The instinct is to shop for a cheaper provider. "Should I switch from OpenAI to Claude? From Claude to an open-source model?" Sometimes that helps, but the real leverage is architectural. I've seen businesses switch providers three times and still overpay because the fundamental pattern — one model for everything, no caching, verbose outputs — never changes.&lt;/p&gt;

&lt;p&gt;If your AI API bill is higher than you'd like, start with these questions: How many of your API calls actually need a premium model? Are you sending the same context repeatedly? Can any of your calls be batched? Are your prompts asking for more output than you use?&lt;/p&gt;

&lt;p&gt;The answers usually reveal that 60-80% of your bill is waste hiding in plain sight. You don't need to spend less on AI. You need to spend smarter.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How much do AI API calls typically cost for a small business in India?&lt;/strong&gt;&lt;br&gt;
Most small businesses using AI APIs spend between ₹15,000 and ₹1,00,000 per month depending on volume and model choice. The biggest cost driver is using premium models for tasks that cheaper models handle equally well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is model routing and how does it reduce AI costs?&lt;/strong&gt;&lt;br&gt;
Model routing means sending each task to the cheapest AI model that can handle it well. Simple classification tasks go to lightweight models, while complex reasoning goes to premium models. This alone can cut costs by 40-60%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can prompt caching really save money on AI API bills?&lt;/strong&gt;&lt;br&gt;
Yes. If your application sends similar system prompts or context repeatedly, prompt caching avoids reprocessing those tokens. Depending on your use case, this can reduce input token costs by 50-90% on repeated calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it worth switching AI providers just to save costs?&lt;/strong&gt;&lt;br&gt;
Not always. The real savings come from architectural changes — model routing, caching, batching, and output token optimization — not from switching providers. That said, comparing pricing across providers for your specific use case is always smart.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Archit Mittal helps businesses automate chaos. Follow on LinkedIn: &lt;a href="https://linkedin.com/in/automate-archit" rel="noopener noreferrer"&gt;@automate-archit&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related reads:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://architmittal.com/blog/weekend-python-script-ca-firm-209-hours-itr" rel="noopener noreferrer"&gt;How a Weekend Python Script Saved a CA Firm 209 Hours During ITR Season&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://architmittal.com/blog/zero-rupee-automation-stack-enterprise-workflows" rel="noopener noreferrer"&gt;The ₹0 Automation Stack: Enterprise-Grade Workflows Without Paying for SaaS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://architmittal.com/blog/over-automation-trap-when-not-to-automate" rel="noopener noreferrer"&gt;Why I Tell Clients NOT to Automate Everything — The Over-Automation Trap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>costoptimization</category>
      <category>india</category>
    </item>
    <item>
      <title>The CFO's AI Playbook: 5 Finance Automations Every Indian Business Should Run in 2026</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 20 Jun 2026 03:35:43 +0000</pubDate>
      <link>https://dev.to/automate-archit/the-cfos-ai-playbook-5-finance-automations-every-indian-business-should-run-in-2026-4ai8</link>
      <guid>https://dev.to/automate-archit/the-cfos-ai-playbook-5-finance-automations-every-indian-business-should-run-in-2026-4ai8</guid>
      <description>&lt;p&gt;Over 60% of APAC finance leaders say AI-led automation is their top priority for 2026. For Indian businesses, that stat hides a quieter truth: most SMBs have no idea &lt;em&gt;which&lt;/em&gt; automation to start with. They hear "AI for finance" and picture an enterprise suite with a six-figure licence fee. Wrong picture.&lt;/p&gt;

&lt;p&gt;I've built finance automations for CA firms, D2C brands, trading desks, family-run manufacturers, and a few fintech startups. The pattern is always the same. Five finance processes eat the most hours, hide the most errors, and respond best to a simple Python layer on top of whatever ledger you already use.&lt;/p&gt;

&lt;p&gt;This is the playbook. No enterprise suite. No subscriptions you don't need. Each automation is something I've shipped for real clients using Python, free APIs, and a ledger that's usually Tally or Zoho Books.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Bank Reconciliation — The Single Biggest Time Sink in Indian Finance
&lt;/h2&gt;

&lt;p&gt;Every finance team I meet has the same nightmare. Statements from three or four banks. Tally or Zoho on the other side. An Excel sheet in the middle. Eight hours a month — sometimes more — matching rows.&lt;/p&gt;

&lt;p&gt;A CA friend was losing two sleepless nights before every GST deadline on exactly this. We replaced it with a Python script that pulls statements from email attachments, categorizes transactions using keyword rules, cross-references entries with Tally, and flags only the mismatches in a clean Excel file. Eight hours dropped to fifteen minutes of review.&lt;/p&gt;

&lt;p&gt;"Tu 2 saal pehle kyu nahi mila?" (Why didn't I meet you two years ago?)&lt;/p&gt;

&lt;p&gt;If your team is still opening each bank statement manually, start here. It's the highest-ROI automation in Indian finance. I've written the full workflow in &lt;a href="https://architmittal.com/blog/weekend-python-script-ca-firm-209-hours-itr" rel="noopener noreferrer"&gt;how a weekend Python script saved a CA firm 209 hours during ITR season&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Cash Application — Matching Payments to Invoices at Indian Speeds
&lt;/h2&gt;

&lt;p&gt;Globally, AI-driven cash application handles up to 90% of invoice matching without human touch. In India, it's harder — money arrives in more shapes than most tools expect: UPI, NEFT, RTGS, IMPS, cheques, partial payments, grouped settlements where one transfer covers four invoices. Manual matching is why so many Indian SMBs run receivables that are perpetually a week out of date.&lt;/p&gt;

&lt;p&gt;I build a three-layer pipeline. Layer one parses payment references — UTR numbers, invoice IDs, sometimes just a customer name in the remarks. Layer two tries deterministic matches: exact amount, reference, customer. Layer three hands the ambiguous ones to a lightweight AI model that reasons about partial amounts, nicknames, and grouped payments, then suggests matches with a confidence score.&lt;/p&gt;

&lt;p&gt;Above 95% confidence gets auto-applied. Below that goes to human review. A D2C brand I rolled this out for went from a seven-day receivables gap to same-day application. Their working capital position shifted by roughly ₹14 lakhs without a single new customer.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Real-Time P&amp;amp;L Reporting — Know Your Numbers Before the CA Calls You
&lt;/h2&gt;

&lt;p&gt;Most Indian SMB founders see their P&amp;amp;L twenty days after the month ends, when their accountant sends a formatted Excel. By then, the decisions that would have mattered — cut this spend, double that campaign, pause that hire — are a month old.&lt;/p&gt;

&lt;p&gt;Real-time P&amp;amp;L automation closes that gap. A scheduled Python script pulls trial balance data overnight, categorizes new entries into your chart of accounts, and renders a dashboard with revenue, gross margin, operating expenses and EBITDA as of yesterday. Usually in Google Sheets or a lightweight HTML dashboard.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What this actually changes:&lt;/strong&gt; You stop making capital decisions on twenty-day-old data. For a business doing ₹30L/month, a single well-timed cut or push based on real-time numbers can move EBITDA by 2-3 percentage points over a quarter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This pairs beautifully with the &lt;a href="https://architmittal.com/blog/zero-rupee-automation-stack-enterprise-workflows" rel="noopener noreferrer"&gt;₹0 automation stack&lt;/a&gt; I've written about — cron, Python, Google Sheets, and free accounting exports give you an enterprise-grade finance dashboard without a rupee of subscription spend.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. GST Filing Prep — Eliminate the Three Nights Before Every Return
&lt;/h2&gt;

&lt;p&gt;GSTR-1, GSTR-3B, and the quarterly reconciliations are the other reason finance teams lose sleep. The filing itself is data entry. The real work is pulling sales data, reconciling with purchase registers, checking vendor filing mismatches, and formatting it all for the GSTN portal.&lt;/p&gt;

&lt;p&gt;Every one of those steps is automatable. I build GST prep bots that run on the 28th of every month. They pull sales and purchase data, compute GSTR-1 and GSTR-3B figures, pull vendor GSTR-2A data via the GSTN API, flag reconciliation mismatches, and produce a filing-ready summary.&lt;/p&gt;

&lt;p&gt;A small manufacturing client went from three anxious days a month to a two-hour review window. Their CA still does the actual submission — that's judgment work, stays human. The 80% that's data plumbing? Gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Expense Categorization — Stop Miscategorizing Half Your Costs
&lt;/h2&gt;

&lt;p&gt;This one sounds boring. It isn't. Miscategorized expenses are a silent killer in Indian SMB P&amp;amp;Ls. A ₹2L advertising spend mis-booked as "professional fees" wrecks every board metric that flows from it.&lt;/p&gt;

&lt;p&gt;Expense categorization automation uses an AI model trained on your own chart of accounts and historical entries. Each new entry gets a suggested category with confidence. High-confidence ones auto-categorize. The ambiguous 10-15% goes to a review queue. Your reviews feed back in and the model sharpens.&lt;/p&gt;

&lt;p&gt;For a client with ~800 expense entries a month, this shifted their finance lead's time from 6 hours of categorization to 45 minutes of review. Accuracy went from ~82% to 97%. Their board deck finally told the truth about where money was going.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Five Automations at a Glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Automation&lt;/th&gt;
&lt;th&gt;Time Saved / Month&lt;/th&gt;
&lt;th&gt;Typical Rollout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bank reconciliation&lt;/td&gt;
&lt;td&gt;6-10 hours&lt;/td&gt;
&lt;td&gt;2-4 weekends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cash application&lt;/td&gt;
&lt;td&gt;15-25 hours&lt;/td&gt;
&lt;td&gt;3-6 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time P&amp;amp;L&lt;/td&gt;
&lt;td&gt;8-12 hours + faster decisions&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GST filing prep&lt;/td&gt;
&lt;td&gt;12-20 hours&lt;/td&gt;
&lt;td&gt;3-5 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expense categorization&lt;/td&gt;
&lt;td&gt;4-8 hours&lt;/td&gt;
&lt;td&gt;1-2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Stack all five and you're recovering 45-75 hours of skilled finance time every month. For an SMB with a single accountant, that's effectively a second person at zero incremental cost. For a firm with a CFO, it's the difference between reactive month-end rituals and proactive capital decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Start (And Where Not To)
&lt;/h2&gt;

&lt;p&gt;Do not try to build all five at once. That's how automation projects become automation graveyards. Start with bank reconciliation — bounded, high-ROI, and an immediate win. Once it's running reliably for two months, pick the next one where your team still feels stuck.&lt;/p&gt;

&lt;p&gt;Also, don't automate what doesn't need to be automated. I've written a whole piece on &lt;a href="https://architmittal.com/blog/over-automation-trap-when-not-to-automate" rel="noopener noreferrer"&gt;when not to automate&lt;/a&gt; — it applies especially hard in finance, where reviewing edge cases is often the most valuable part of the job. The goal isn't a human-free finance function. It's one where humans spend hours on judgment, not typing.&lt;/p&gt;

&lt;p&gt;"Jo kaam AI se ho sakta hai, AI kare. Jo judgment se hota hai, woh humans ke paas rahe." (Let AI do what AI can do. Let judgment stay with humans.)&lt;/p&gt;

&lt;p&gt;That's the whole playbook. Five automations. Zero enterprise suites. A real finance function that tells you the truth, faster, with less pain.&lt;/p&gt;

&lt;p&gt;Which of these five is eating the most hours in your finance team right now?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Archit Mittal helps businesses automate chaos. Follow on LinkedIn: &lt;a href="https://linkedin.com/in/automate-archit" rel="noopener noreferrer"&gt;@automate-archit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get automation insights every Saturday — join The Automation Dispatch at &lt;a href="https://architmittal.com/newsletter" rel="noopener noreferrer"&gt;architmittal.com/newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>finance</category>
      <category>india</category>
    </item>
  </channel>
</rss>
