Skill: abhi152003/tally-prime-skill (version 1.0.1)

--- emoji: 🧾 name: tally-prime-entry version: 1.0.1 author: Maxxit description: >- Post purchase, sales, and bank entries in TallyPrime with GST voucher classes. Generate sales invoice PDFs via tallyca. disableModelInvocation: false requires: env: - TALLY_URL metadata: openclaw: requiredEnv: - TALLY_URL bins: - curl - tallyca - scribe primaryCredential: TALLY_URL --- # TallyPrime Entry Skill Connect to a **locally running** TallyPrime instance via **XML-over-HTTP**. All requests are HTTP POST to `$TALLY_URL` (commonly `http://localhost:9000`). ## Scope This skill handles only: | Category | Modes / Types | |---|---| | **Purchase Voucher** | Item Invoice · Accounting Invoice · As Voucher | | **Purchase Voucher Classes** | Purchase @ 5 % · Purchase @ 18 % · Purchase @ 28 % | | **Sales Voucher** | Item Invoice · As Voucher | | **Sales Voucher Classes** | Sales @ 5 % · Sales @ 18 % · Sales @ 28 % | | **Bank Statement** | Payment · Receipt · Contra | | **Sales Invoice PDF** | `tallyca` CLI | For anything outside this scope, tell the user this skill does not cover that task. ## Critical rules (must follow) 1. **Never assume company** — if not explicit, ask which company before posting. 2. **Never guess ledgers** — verify ledger exists before posting; ask user if unsure. 3. **Dates are `YYYYMMDD`** (no separators). 4. **Unique GUID per voucher** — prevents duplicates on retries. 5. **Voucher totals must balance** — sum of all `AMOUNT` values = 0. 6. **Escape XML** — `&` → `&amp;` in narration and party names. 7. **Confirm before posting** — every Create is a write; confirm company and intent first. 8. **Bill-wise allocations on party ledgers** — include `BILLALLOCATIONS.LIST` to keep outstandings correct. 9. **`LEDGERENTRIES.LIST` in Invoice Voucher View** — never use `ALLLEDGERENTRIES.LIST` when `OBJVIEW="Invoice Voucher View"` is set; Tally silently ignores it. 10. **Post-entry review is mandatory** — after every voucher post, fetch it back and verify before telling the user it is done. 11. **Voucher class — confirm before posting** — run the class decision rules at the top of the relevant purchase/sales reference file before posting. 12. **Check import response** — after every POST, read `CREATED`/`ERRORS` from Tally's response (see `reference/reports.md`). Never confirm success if `ERRORS > 0` or `CREATED = 0`. ## Step 0: Server check ```bash curl -s --max-time 5 "$TALLY_URL" ``` Expected response: ```xml <RESPONSE>TallyPrime Server is Running</RESPONSE> ``` If no response, ask the user to open TallyPrime and enable integrations on the correct port. ## Step 1: Company Ask for the company name if not provided. Use the **exact** spelling in `SVCURRENTCOMPANY`. ## Step 2: Invoice / image extraction (mandatory OCR) When the user sends a **PDF, JPEG, JPG, or PNG** invoice or bill, use the `scribe` CLI. Do not extract data with the LLM directly. ### PDF extraction ```bash mkdir -p "scribe-extractions" scribe type "<input.pdf>" scribe extract -f txt "<input.pdf>" "scribe-extractions/<id>.txt" ``` Read the `.txt` file and parse the invoice fields. If quality is poor (image-native PDF), run OCR first: ```bash scribe recognize -h -o "scribe-extractions/<id>-ocr" "<input.pdf>" scribe extract -f txt "scribe-extractions/<id>-ocr/<stem>.pdf" "scribe-extractions/<id>-recognized.txt" ``` ### Image extraction (JPEG / PNG) 1. Try direct extraction: ```bash scribe extract -f txt "<input.jpeg>" "scribe-extractions/<id>.txt" ``` 2. If output is empty, run OCR: ```bash scribe recognize -h -o "scribe-extractions/<id>-ocr" "<input.jpeg>" scribe extract -f txt "scribe-extractions/<id>-ocr/<stem>.pdf" "scribe-extractions/<id>-recognized.txt" ``` ### After extraction Present a clean summary to the user: supplier/customer, GSTINs, invoice number, date, line items, taxable value, CGST/SGST/IGST, round-off, total. Ask for confirmation before posting. If extraction fails, say "I could not read this bill clearly. Please resend a clearer photo or PDF." — do not mention CLI, OCR, errors, or paths. ## Step 2b: Verify / create masters Before posting any voucher, verify that all required ledgers and (for Item Invoice) stock items exist. Use `reference/ledgers.md` and `reference/inventory.md`. **Ledger check** (`reference/ledgers.md`): - Fetch `List of Accounts` and confirm party ledger, purchase/sales ledger, and GST ledgers exist. - If any are missing, create them using the templates in `reference/ledgers.md` before posting. **Inventory check — Item Invoice only** (`reference/inventory.md`): - Confirm each stock item referenced in the invoice exists in Tally (fetch Stock Summary). - If missing, create in order: Stock Group → UOM → Stock Item. - Confirm godown: default is `Main Location` / `Primary Batch` unless the company has custom godowns. **Bank statement pre-flight** (`reference/reports.md`): - Before posting bank entries, fetch all ledger names (Ledger Names query in `reference/reports.md`). - Present the mapping to the user: "These are the ledgers I will use: [bank], [parties]. Confirm to proceed." - Do not post until confirmed. ## Step 3: Post vouchers Load only the file that matches the task — this keeps context lean: | Task | Reference file | |---|---| | Purchase — stock items | `reference/purchase.md` → Item Invoice | | Purchase — services/expenses (invoice layout) | `reference/purchase.md` → Accounting Invoice | | Purchase — classic By/To view | `reference/purchase.md` → As Voucher | | Sales — stock items | `reference/sales.md` → Item Invoice | | Sales — no items (ledger-only) | `reference/sales.md` → As Voucher | | Money received from customer | `reference/bank.md` → Receipt | | Money paid to vendor/expense | `reference/bank.md` → Payment | | Bank/cash transfer | `reference/bank.md` → Contra | | Ledger check / create | `reference/ledgers.md` | | Stock item check / create | `reference/inventory.md` | **Voucher class decision** — the class decision rules and GST ledger name table are at the top of each purchase/sales reference file. Run them before posting. **Preflight checklist before any Create:** | # | Check | Reference | Block if… | |---|---|---|---| | 1 | Company confirmed | — | Not given — ask | | 2 | Server reachable | — | No response | | 3 | Party ledger exists | `reference/ledgers.md` | Missing — create first | | 4 | Purchase/Sales/GST ledgers exist | `reference/ledgers.md` | Missing — create first | | 5 | Stock items exist (Item Invoice only) | `reference/inventory.md` | Missing — create first | | 6 | Voucher class confirmed (Purchase/Sales) | purchase/sales reference file | Unknown — ask, never guess | | 7 | GST header fields available (class mode) | — | Any missing — ask | | 8 | Totals balance | — | Mismatch — fix before posting | ## Step 4: Post-entry review (mandatory) After every voucher Create: 1. **Read the import response** — check `CREATED` and `ERRORS` fields (`reference/reports.md`). Stop if `ERRORS > 0`. 2. **Fetch the voucher back** — use Voucher Register (preferred) or Day Book as fallback (`reference/reports.md`). 3. **Match against the intended entry** — company, voucher type, number, date, party, all ledgers, amounts, GST split, bill-wise allocations. 4. If everything matches, summarize to the user in accountant language (no XML, no HTTP terms). 5. If anything is off, do not confirm completion — explain the mismatch and ask how to proceed. Never say "Entry posted" without completing this review. ## PDF Generation — Sales Invoice Use the `tallyca` CLI. Do **not** build PDFs manually. ### Preflight ```bash tallyca --version # must be >= 1.1.0 ``` If missing or older: `npm install -g tallyca@latest` ### Minimum user input Ask the user for only these 4 fields. Everything else is auto-filled from Tally: | Field | Source | |---|---| | `party-name` | User | | `item` | User — stock item name | | `qty` | User | | `rate` | User — per unit | ### Auto-fill sequence (run before calling tallyca) Execute in this order. Each step reduces what the user needs to provide: | Field | How to auto-fill | Reference | |---|---|---| | `date` | Default to today (`D/M/YYYY`) | — | | `invoice-no` | Fetch last Sales voucher number → +1 | `reference/reports.md` | | `unit` | Fetch stock item master → `BASEUNITS` | `reference/inventory.md` | | `hsn-code` | Fetch stock item master → `HSNDETAILS.LIST > HSNCODE` | `reference/inventory.md` | | `gst-rate` | Fetch stock item master → IGST rate from `GSTDETAILS.LIST`; or parse `@ XX %` from item name | `reference/inventory.md` | | `customer-gstin` | Fetch party ledger → `$PARTYGSTIN` | `reference/ledgers.md` | | `place-of-supply` | Fetch party ledger → `$PriorStateName`; if same state as company → intra-state (CGST+SGST), else IGST | `reference/ledgers.md` | | `billing-address` | Fetch party ledger → `$Address` (line 1); remaining lines from `ADDRESS.LIST` in any recent voucher to that party | `reference/ledgers.md` | | `company-gstin` | Parse `<CMPGSTIN>` from any recent Day Book sales voucher export | `reference/reports.md` | | `company-address` | Fetch company → `$Address`, `$PinCode`, `$StateName` via Company TDL collection | `reference/ledgers.md` | **Fallback:** if any auto-fill fails, use `--json-errors`. The CLI returns a `missing` array — ask the user only for those specific fields, then retry. ### From structured fields (preferred) Always use `--no-interactive` and `--json-errors` when running non-interactively: ```bash tallyca generate:invoice \ --company "ABC Company" \ --company-gstin "GSTIN_HERE" \ --company-address "Full company address, State PIN" \ --party-name "XYZ Party" \ --customer-gstin "PARTY_GSTIN" \ --billing-address "Party address, State" \ --invoice-no 186 \ --date "2/1/2026" \ --place-of-supply "Uttar Pradesh" \ --item "PQR Item" \ --qty 140 \ --unit Bag \ --rate 279.66 \ --hsn-code 25322210 \ --gst-rate 18 \ --b2b \ --output invoice_186.pdf \ --no-interactive \ --json-errors ``` **On exit code 2 (validation failure):** parse JSON from stderr, read the `missing` array, ask the user only for those fields, then retry. Never hand-build a PDF. ```json {"error":"validation","message":"Missing required invoice fields","missing":["place-of-supply","unit"],"warnings":[]} ``` ### From raw WhatsApp / Telegram text ```bash tallyca from-text \ --company "ABC Company" \ --text "Party Name: XYZ Party Invoice No.: 186 Date: 2/1/2026 Place of Supply: Uttar Pradesh Item: PQR Item 2523 @ 18 % Qty: 140 Bag Rate: 279.66/Bag HSN Code: 25322210 Amount: 39152.40 Make sure to use voucher class Sales @ 18 %" \ --output invoice_186.pdf \ --no-interactive \ --json-errors ``` ### On Linux / AWS without Chromium ```bash export TALLYCA_PDF_BACKEND=pdfmake ``` Then run the same command. Do not substitute a hand-built PDF. ## GUID pattern ``` {companyShort}-{voucherType}-{invoiceNo}-{date} ``` Examples: `abc-purchase-inv001-20260115` · `abc-sales-186-20260201` ## Accountant-friendly responses After posting, do **not** mention XML, HTTP, payloads, status codes, or integration internals. Say: - "Entry posted" (not "XML import succeeded") - "Tally is connected" (not "server responded 200") - Summarize: company, voucher type, date, party/ledger names, amounts, tax split, narration.

path: reference/purchase.md
content: # Purchase Vouchers — TallyPrime XML Templates

Covers: Item Invoice · Accounting Invoice · As Voucher (with and without voucher class).

## Conventions

- Always set `SVCURRENTCOMPANY` and `GUID`.
- Dates as `YYYYMMDD`. Escape `&` → `&amp;`.
- Include `BILLALLOCATIONS.LIST` on the vendor entry. Voucher totals must sum to zero.
- `Invoice Voucher View` → use `LEDGERENTRIES.LIST`
- `Accounting Voucher View` → use `ALLLEDGERENTRIES.LIST`

## Voucher class — decision rules

Run this **every time** before posting.

```
Does the company's Purchase voucher type have a class configured?
│
├─ YES → Exact class name confirmed?
│         ├─ Yes → Use "with class" template. Set CLASSNAME + all 4 GST header fields.
│         └─ No  → STOP. Ask: "What is the exact class name in Tally?"
│
├─ NO  → Use "no class" template.
│
└─ UNKNOWN → STOP. Ask: "Does this company use voucher classes (e.g. Purchase @ 18 %)?"
```

### GST ledger names per class rate

| Class | CGST % | SGST % | Input CGST ledger | Input SGST ledger |
|---|---|---|---|---|
| Purchase @ 5 % | 2.5 | 2.5 | `Input Cgst @ 2.5 %` | `Input Sgst @ 2.5 %` |
| Purchase @ 18 % | 9 | 9 | `Input Cgst @ 9 %` | `Input Sgst @ 9 %` |
| Purchase @ 28 % | 14 | 14 | `Input Cgst @ 14 %` | `Input Sgst @ 14 %` |

Ledger names must match **exactly** as configured in Tally.

### Class mode — required header fields

```xml
<CLASSNAME>Purchase @ 18 %</CLASSNAME>
<CMPGSTIN>COMPANY_GSTIN</CMPGSTIN>
<PARTYGSTIN>VENDOR_GSTIN</PARTYGSTIN>
<GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
<PLACEOFSUPPLY>STATE_NAME</PLACEOFSUPPLY>
```

## Mode selection

| Mode | `OBJVIEW` | `ISINVOICE` | Use when |
|---|---|---|---|
| Item Invoice | `Invoice Voucher View` | Yes | Stock items with Qty/Rate/Amount |
| Accounting Invoice | `Invoice Voucher View` | Yes | Invoice layout, ledger-only (services/expenses) |
| As Voucher | `Accounting Voucher View` | No | Classic By/To accounting view |

---

## Item Invoice — no class

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Purchase" ACTION="Create" OBJVIEW="Invoice Voucher View">
            <GUID>GUID_VALUE</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Purchase</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <PARTYLEDGERNAME>VENDOR_LEDGER</PARTYLEDGERNAME>
            <ISINVOICE>Yes</ISINVOICE>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>VENDOR_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </ALLLEDGERENTRIES.LIST>

            <!-- Repeat for each stock item -->
            <ALLINVENTORYENTRIES.LIST>
              <STOCKITEM>STOCK_ITEM_NAME</STOCKITEM>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <RATE>RATE_PER_UNIT</RATE>
              <AMOUNT>LINE_AMOUNT</AMOUNT>
              <ACTUALQTY>QUANTITY</ACTUALQTY>
              <BILLEDQTY>QUANTITY</BILLEDQTY>
              <BATCHALLOCATIONS.LIST>
                <GODOWNNAME>Main Location</GODOWNNAME>
                <BATCHNAME>Primary Batch</BATCHNAME>
                <QUANTITY>QUANTITY</QUANTITY>
              </BATCHALLOCATIONS.LIST>
            </ALLINVENTORYENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>PURCHASE_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-TAXABLE_VALUE</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Input Cgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-CGST_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Input Sgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-SGST_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## Item Invoice — with class (5 / 18 / 28 %)

Replace `Purchase @ 18 %` and GST ledger names per the rate table above.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Purchase" ACTION="Create" OBJVIEW="Invoice Voucher View">
            <GUID>GUID_VALUE</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Purchase</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <PARTYLEDGERNAME>VENDOR_LEDGER</PARTYLEDGERNAME>
            <ISINVOICE>Yes</ISINVOICE>

            <CLASSNAME>Purchase @ 18 %</CLASSNAME>
            <CMPGSTIN>COMPANY_GSTIN</CMPGSTIN>
            <PARTYGSTIN>VENDOR_GSTIN</PARTYGSTIN>
            <GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
            <PLACEOFSUPPLY>STATE_NAME</PLACEOFSUPPLY>

            <!-- LEDGERENTRIES.LIST required in Invoice Voucher View -->
            <LEDGERENTRIES.LIST>
              <LEDGERNAME>VENDOR_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </LEDGERENTRIES.LIST>

            <!-- Repeat for each stock item -->
            <ALLINVENTORYENTRIES.LIST>
              <STOCKITEMNAME>ITEM_NAME</STOCKITEMNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <RATE>RATE_PER_UNIT</RATE>
              <AMOUNT>TAXABLE_VALUE</AMOUNT>
              <ACTUALQTY>QUANTITY</ACTUALQTY>
              <BILLEDQTY>QUANTITY</BILLEDQTY>
              <BATCHALLOCATIONS.LIST>
                <GODOWNNAME>Main Location</GODOWNNAME>
                <BATCHNAME>Primary Batch</BATCHNAME>
                <AMOUNT>TAXABLE_VALUE</AMOUNT>
                <ACTUALQTY>QUANTITY</ACTUALQTY>
                <BILLEDQTY>QUANTITY</BILLEDQTY>
              </BATCHALLOCATIONS.LIST>
              <ACCOUNTINGALLOCATIONS.LIST>
                <LEDGERNAME>PURCHASE_LEDGER</LEDGERNAME>
                <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
                <AMOUNT>TAXABLE_VALUE</AMOUNT>
              </ACCOUNTINGALLOCATIONS.LIST>
            </ALLINVENTORYENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Input Cgst @ 9 %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-CGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Input Sgst @ 9 %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-SGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## Accounting Invoice — no class

Invoice layout, no stock items. `LEDGERENTRIES.LIST` required (Invoice Voucher View).
`VCHENTRYMODE` must be set to `Accounting Invoice` — without it Tally defaults to Item Invoice.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Purchase" ACTION="Create" OBJVIEW="Invoice Voucher View">
            <GUID>GUID_VALUE</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Purchase</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <PARTYLEDGERNAME>VENDOR_LEDGER</PARTYLEDGERNAME>
            <ISINVOICE>Yes</ISINVOICE>
            <VCHENTRYMODE>Accounting Invoice</VCHENTRYMODE>
            <NARRATION>NARRATION_TEXT</NARRATION>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>VENDOR_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>PURCHASE_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-TAXABLE_VALUE</AMOUNT>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Input Cgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-CGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Input Sgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-SGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>

            <!-- Optional -->
            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Round Off</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-ROUND_OFF</AMOUNT>
            </LEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## Accounting Invoice — with class (5 / 18 / 28 %)

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Purchase" ACTION="Create" OBJVIEW="Invoice Voucher View">
            <GUID>GUID_VALUE</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Purchase</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <PARTYLEDGERNAME>VENDOR_LEDGER</PARTYLEDGERNAME>
            <ISINVOICE>Yes</ISINVOICE>
            <VCHENTRYMODE>Accounting Invoice</VCHENTRYMODE>
            <NARRATION>NARRATION_TEXT</NARRATION>

            <CLASSNAME>Purchase @ 18 %</CLASSNAME>
            <CMPGSTIN>COMPANY_GSTIN</CMPGSTIN>
            <PARTYGSTIN>VENDOR_GSTIN</PARTYGSTIN>
            <GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
            <PLACEOFSUPPLY>STATE_NAME</PLACEOFSUPPLY>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>VENDOR_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>PURCHASE_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-TAXABLE_VALUE</AMOUNT>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Input Cgst @ 9 %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-CGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Input Sgst @ 9 %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-SGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## As Voucher (classic By/To view)

`OBJVIEW="Accounting Voucher View"` + `ISINVOICE=No`. Vendor entry **must come first** so the Day Book Particulars column shows the vendor name.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Purchase" ACTION="Create" OBJVIEW="Accounting Voucher View">
            <GUID>GUID_VALUE</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Purchase</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <PARTYLEDGERNAME>VENDOR_LEDGER</PARTYLEDGERNAME>
            <ISINVOICE>No</ISINVOICE>
            <NARRATION>NARRATION_TEXT</NARRATION>

            <!-- Vendor FIRST — drives Day Book Particulars -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>VENDOR_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>PURCHASE_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-TAXABLE_VALUE</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Input Cgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-CGST_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Input Sgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-SGST_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <!-- Optional -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Round Off</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-ROUND_OFF</AMOUNT>
            </ALLLEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```


path: reference/bank.md
content: # Bank Statement Vouchers — TallyPrime XML Templates

Covers: Payment · Receipt · Contra

## Conventions

- Always set `SVCURRENTCOMPANY` and `GUID`.
- Dates as `YYYYMMDD`. Escape `&` → `&amp;`.
- All three voucher types use `OBJVIEW="Accounting Voucher View"` and `ALLLEDGERENTRIES.LIST`.
- Voucher totals must sum to zero.

## Bank statement → Tally mapping

Bank statements are from the **bank's perspective**. Post from the **business's books**:

| Bank statement | Business books | Voucher type |
|---|---|---|
| Credit (money in) | Bank account debited | **Receipt** |
| Debit (money out) | Bank account credited | **Payment** |
| Internal transfer | Fund moves between accounts | **Contra** |

| Transaction | Voucher | Debit | Credit |
|---|---|---|---|
| NEFT/RTGS/UPI credit from customer | Receipt | Bank | Customer ledger |
| NEFT/RTGS/UPI debit to supplier | Payment | Supplier/Expense | Bank |
| Cash deposit to bank | Contra | Bank | Cash |
| ATM / cash withdrawal | Contra | Cash | Bank |
| Bank A → Bank B transfer | Contra | Destination Bank | Source Bank |
| Interest credit | Receipt | Bank | Interest Income |
| Bank charges | Payment | Bank Charges | Bank |

---

## Receipt (money received)

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Receipt" ACTION="Create" OBJVIEW="Accounting Voucher View">
            <GUID>UNIQUE_GUID</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Receipt</VOUCHERTYPENAME>
            <NARRATION>NARRATION_TEXT</NARRATION>
            <ISINVOICE>No</ISINVOICE>
            <PARTYLEDGERNAME>CUSTOMER_LEDGER</PARTYLEDGERNAME>

            <!-- Bank / Cash — debit (money in) -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>BANK_OR_CASH_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <!-- Customer — credit -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>CUSTOMER_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## Payment (money paid)

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Payment" ACTION="Create" OBJVIEW="Accounting Voucher View">
            <GUID>UNIQUE_GUID</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Payment</VOUCHERTYPENAME>
            <NARRATION>NARRATION_TEXT</NARRATION>
            <ISINVOICE>No</ISINVOICE>
            <PARTYLEDGERNAME>VENDOR_OR_EXPENSE_LEDGER</PARTYLEDGERNAME>

            <!-- Payee (vendor / expense) — debit -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>VENDOR_OR_EXPENSE_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <!-- Bank / Cash — credit (money out) -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>BANK_OR_CASH_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## Contra (bank / cash transfers)

Debit the account that **receives** funds; credit the account that **gives** funds.

| Scenario | Debit (`TO_LEDGER`) | Credit (`FROM_LEDGER`) |
|---|---|---|
| Cash deposit to bank | Bank ledger | Cash ledger |
| ATM / cash withdrawal | Cash ledger | Bank ledger |
| Bank A → Bank B | Bank B ledger | Bank A ledger |

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Contra" ACTION="Create" OBJVIEW="Accounting Voucher View">
            <GUID>UNIQUE_GUID</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Contra</VOUCHERTYPENAME>
            <NARRATION>NARRATION_TEXT</NARRATION>
            <ISINVOICE>No</ISINVOICE>

            <!-- Account receiving funds — debit -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>TO_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <!-- Account giving funds — credit -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>FROM_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```


path: reference/reports.md
content: # Reports — Post-Entry Review & Ledger Fetch

Focused on: post-entry voucher review (mandatory after every post) and ledger name fetch (bank statement pre-flight).

## Import response — how to read it

After every `Import Data` POST, Tally returns a statistics block. Always parse it before telling the user the entry is complete.

Key fields to check:

| Field | Meaning |
|---|---|
| `CREATED` | Objects successfully created |
| `ALTERED` | Objects successfully altered |
| `ERRORS` | Import errors — treat any non-zero value as failure |
| `EXCEPTIONS` | Partial/unexpected failures |

**Rule:** if `ERRORS > 0` or `CREATED = 0` (for a Create action), the voucher was **not** posted. Do not tell the user it was posted. Read the error detail, diagnose, and fix before retrying.

---

## Fetch last Sales invoice number (for auto-increment)

Use before PDF generation to determine the next invoice number without asking the user.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Export Data</TALLYREQUEST></HEADER>
  <BODY>
    <EXPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Voucher Register</REPORTNAME>
        <STATICVARIABLES>
          <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
          <SVVOUCHERTYPENAME>Sales</SVVOUCHERTYPENAME>
          <SVFROMDATE>FYSTART_YYYYMMDD</SVFROMDATE>
          <SVTODATE>TODAY_YYYYMMDD</SVTODATE>
        </STATICVARIABLES>
      </REQUESTDESC>
    </EXPORTDATA>
  </BODY>
</ENVELOPE>
```

- `SVFROMDATE`: start of the current financial year (Indian FY starts April 1 — e.g., `20250401`).
- `SVTODATE`: today's date.
- From the response, collect all `<VOUCHERNUMBER>` values, extract the numeric part from the last/highest one, and add 1.
- If no Sales vouchers exist yet this FY, start from `1`.

---

## Post-entry review (mandatory after every Create)

After every voucher post, fetch it back from Tally and verify before telling the user it is done.

### Step 1 — Fetch via Voucher Register (preferred)

Filter by voucher type and the exact voucher date:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Export Data</TALLYREQUEST></HEADER>
  <BODY>
    <EXPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Voucher Register</REPORTNAME>
        <STATICVARIABLES>
          <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
          <SVVOUCHERTYPENAME>VOUCHER_TYPE</SVVOUCHERTYPENAME>
          <SVFROMDATE>VOUCHER_YYYYMMDD</SVFROMDATE>
          <SVTODATE>VOUCHER_YYYYMMDD</SVTODATE>
        </STATICVARIABLES>
      </REQUESTDESC>
    </EXPORTDATA>
  </BODY>
</ENVELOPE>
```

`SVVOUCHERTYPENAME` values: `Purchase` · `Sales` · `Payment` · `Receipt` · `Contra`

### Step 2 — Fallback: Day Book

Use when Voucher Register does not return enough detail:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Export Data</TALLYREQUEST></HEADER>
  <BODY>
    <EXPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Day Book</REPORTNAME>
        <STATICVARIABLES>
          <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
          <SVFROMDATE>VOUCHER_YYYYMMDD</SVFROMDATE>
          <SVTODATE>VOUCHER_YYYYMMDD</SVTODATE>
        </STATICVARIABLES>
      </REQUESTDESC>
    </EXPORTDATA>
  </BODY>
</ENVELOPE>
```

### Step 3 — Fallback: Ledger Vouchers

Use when you need to confirm a specific party or bank ledger entry:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Export Data</TALLYREQUEST></HEADER>
  <BODY>
    <EXPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Ledger Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
          <SVLEDGERNAME>LEDGER_NAME</SVLEDGERNAME>
          <SVFROMDATE>FROM_YYYYMMDD</SVFROMDATE>
          <SVTODATE>TO_YYYYMMDD</SVTODATE>
        </STATICVARIABLES>
      </REQUESTDESC>
    </EXPORTDATA>
  </BODY>
</ENVELOPE>
```

### Review checklist

Locate the voucher by GUID first; if GUID is not in the export, match by voucher type + number + date + party + amount.

- Company and voucher type
- Voucher number/reference and date
- Party ledger and all debit/credit ledger names
- Debit/credit direction and total amount
- GST ledgers, taxable value, tax split, round-off
- Bill-wise allocations and narration

If anything does not match, do **not** confirm to the user. Explain the mismatch in business terms and ask how to proceed.

---

## Ledger Names — fetch all (bank statement pre-flight)

Before posting bank statement transactions, fetch all ledger names and confirm the mapping with the user once before posting.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER>
    <VERSION>1</VERSION>
    <TALLYREQUEST>Export</TALLYREQUEST>
    <TYPE>Data</TYPE>
    <ID>LedgerListReport</ID>
  </HEADER>
  <BODY>
    <DESC>
      <STATICVARIABLES>
        <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
        <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
      </STATICVARIABLES>
      <TDL>
        <TDLMESSAGE>
          <REPORT NAME="LedgerListReport">
            <FORMS>LedgerListForm</FORMS>
          </REPORT>
          <FORM NAME="LedgerListForm">
            <PARTS>LedgerListPart</PARTS>
          </FORM>
          <PART NAME="LedgerListPart">
            <LINES>LedgerListLine</LINES>
            <REPEAT>LedgerListLine : LedgerCollection</REPEAT>
            <SCROLL>Vertical</SCROLL>
          </PART>
          <LINE NAME="LedgerListLine">
            <FIELDS>LedgerNameField</FIELDS>
          </LINE>
          <FIELD NAME="LedgerNameField">
            <SET>$Name</SET>
          </FIELD>
          <COLLECTION NAME="LedgerCollection">
            <TYPE>Ledger</TYPE>
          </COLLECTION>
        </TDLMESSAGE>
      </TDL>
    </DESC>
  </BODY>
</ENVELOPE>
```

Present the relevant ledgers to the user as: "These are the ledgers I will use for the bank entries: [bank ledger], [party ledgers]. Confirm to proceed." Do not post until confirmed.


path: reference/inventory.md
content: # Inventory Masters — Check & Create

Required when posting Item Invoice vouchers (Purchase or Sales). If a stock item, UOM, or godown referenced in a voucher does not exist in Tally, the import will fail with "Stock Item does not exist."

## Fetch stock item details (unit + HSN + GST rate)

Use this before PDF generation to auto-fill `unit`, `hsn-code`, and `gst-rate` without asking the user.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER>
    <VERSION>1</VERSION>
    <TALLYREQUEST>Export</TALLYREQUEST>
    <TYPE>Data</TYPE>
    <ID>StockItemDetailReport</ID>
  </HEADER>
  <BODY>
    <DESC>
      <STATICVARIABLES>
        <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
        <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
      </STATICVARIABLES>
      <TDL>
        <TDLMESSAGE>
          <REPORT NAME="StockItemDetailReport">
            <FORMS>StkDetailForm</FORMS>
          </REPORT>
          <FORM NAME="StkDetailForm">
            <PARTS>StkDetailPart</PARTS>
          </FORM>
          <PART NAME="StkDetailPart">
            <LINES>StkDetailLine</LINES>
            <REPEAT>StkDetailLine : StkItemColl</REPEAT>
            <SCROLL>Vertical</SCROLL>
          </PART>
          <LINE NAME="StkDetailLine">
            <FIELDS>FldName, FldBaseUnits, FldGSTRate</FIELDS>
          </LINE>
          <FIELD NAME="FldName">
            <SET>$Name</SET>
          </FIELD>
          <FIELD NAME="FldBaseUnits">
            <SET>$BaseUnits</SET>
          </FIELD>
          <FIELD NAME="FldGSTRate">
            <SET>$$FilteredValue:GSTRateDetails:GSTRate:GSTRateDutyHead:IGST</SET>
          </FIELD>
          <COLLECTION NAME="StkItemColl">
            <TYPE>Stock Item</TYPE>
            <FILTER>ByItemName</FILTER>
          </COLLECTION>
          <SYSTEM TYPE="Formulae" NAME="ByItemName">
            $Name = "ITEM_NAME"
          </SYSTEM>
        </TDLMESSAGE>
      </TDL>
    </DESC>
  </BODY>
</ENVELOPE>
```

**Parse the response:**

| Field needed | XML path | Example |
|---|---|---|
| `unit` | `FldBaseUnits` | `Bag` |
| `gst-rate` | `FldGSTRate` (IGST rate = total GST %) | `28` |

**HSN code — parse from item name:** Items commonly follow the naming convention `{Name} {HSN} @ {Rate} %` (e.g., `PPC Cement 2523 @ 28 %`). Extract:
- HSN → digits immediately before ` @ ` in the item name
- GST rate → digits after `@ ` and before ` %` (use this if `FldGSTRate` is empty)
- Unit → last token of `DSPCLQTY` in Stock Summary (e.g., `-56943 Bag` → `Bag`)

If any field is still missing after the name parse, ask the user only for that specific field.

---

## Check if a stock item exists

Fetch `List of Accounts` (same query as in `reference/ledgers.md`) and search for `<NAME>ITEM_NAME</NAME>`. Alternatively, fetch the Stock Summary:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Export Data</TALLYREQUEST></HEADER>
  <BODY>
    <EXPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Stock Summary</REPORTNAME>
        <STATICVARIABLES>
          <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
    </EXPORTDATA>
  </BODY>
</ENVELOPE>
```

If the item is absent, create in order: Stock Group → UOM → Stock Item.

## Create Stock Group

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <STOCKGROUP NAME="GROUP_NAME" ACTION="Create">
            <NAME>GROUP_NAME</NAME>
          </STOCKGROUP>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

## Create Unit of Measure (UOM)

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <UNIT NAME="UOM_SYMBOL" ACTION="Create">
            <NAME>UOM_SYMBOL</NAME>
            <ISSIMPLEUNIT>Yes</ISSIMPLEUNIT>
            <ORIGINALNAME>UOM_FULL_NAME</ORIGINALNAME>
            <DECIMALPLACES>0</DECIMALPLACES>
          </UNIT>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

Common symbols: `Pcs`, `Kg`, `Ltr`, `Box`, `Bag`, `Mtr`, `Nos`.

## Create Stock Item

UOM and Stock Group must exist first.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <STOCKITEM NAME="ITEM_NAME" ACTION="Create">
            <NAME>ITEM_NAME</NAME>
            <PARENT>STOCK_GROUP_NAME</PARENT>
            <BASEUNITS>UOM_SYMBOL</BASEUNITS>
          </STOCKITEM>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

## Godown / batch defaults

If godowns/batches are **not** explicitly enabled in the company, use:

- `GODOWNNAME` → `Main Location`
- `BATCHNAME` → `Primary Batch`

If a custom godown is needed, create it first:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <GODOWN NAME="GODOWN_NAME" ACTION="Create">
            <NAME>GODOWN_NAME</NAME>
          </GODOWN>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```


path: reference/sales.md
content: # Sales Vouchers — TallyPrime XML Templates

Covers: Item Invoice · As Voucher (with and without voucher class).

## Conventions

- Always set `SVCURRENTCOMPANY` and `GUID`.
- Dates as `YYYYMMDD`. Escape `&` → `&amp;`.
- Include `BILLALLOCATIONS.LIST` on the customer entry. Voucher totals must sum to zero.
- `Invoice Voucher View` → use `LEDGERENTRIES.LIST`
- `Accounting Voucher View` → use `ALLLEDGERENTRIES.LIST`

## Voucher class — decision rules

Run this **every time** before posting.

```
Does the company's Sales voucher type have a class configured?
│
├─ YES → Exact class name confirmed?
│         ├─ Yes → Use "with class" template. Set CLASSNAME + all 4 GST header fields.
│         └─ No  → STOP. Ask: "What is the exact class name in Tally?"
│
├─ NO  → Use "no class" template (As Voucher only for Sales).
│
└─ UNKNOWN → STOP. Ask: "Does this company use voucher classes (e.g. Sales @ 18 %)?"
```

### GST ledger names per class rate

| Class | CGST % | SGST % | Output CGST ledger | Output SGST ledger |
|---|---|---|---|---|
| Sales @ 5 % | 2.5 | 2.5 | `Output Cgst @ 2.5 %` | `Output Sgst @ 2.5 %` |
| Sales @ 18 % | 9 | 9 | `Output Cgst @ 9 %` | `Output Sgst @ 9 %` |
| Sales @ 28 % | 14 | 14 | `Output Cgst @ 14 %` | `Output Sgst @ 14 %` |

Ledger names must match **exactly** as configured in Tally.

### Class mode — required header fields

```xml
<CLASSNAME>Sales @ 18 %</CLASSNAME>
<CMPGSTIN>COMPANY_GSTIN</CMPGSTIN>
<PARTYGSTIN>CUSTOMER_GSTIN</PARTYGSTIN>
<GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
<PLACEOFSUPPLY>STATE_NAME</PLACEOFSUPPLY>
```

## Mode selection

| Mode | `OBJVIEW` | `ISINVOICE` | Use when |
|---|---|---|---|
| Item Invoice | `Invoice Voucher View` | Yes | Stock items with Qty/Rate/Amount |
| As Voucher | `Accounting Voucher View` | No | Ledger-only, classic view |

---

## Item Invoice — with class (5 / 18 / 28 %)

Replace `Sales @ 18 %` and GST ledger names per the rate table above.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Sales" ACTION="Create" OBJVIEW="Invoice Voucher View">
            <GUID>GUID_VALUE</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Sales</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <REFERENCE>INVOICE_NO</REFERENCE>
            <REFERENCEDATE>YYYYMMDD</REFERENCEDATE>
            <PARTYLEDGERNAME>CUSTOMER_LEDGER</PARTYLEDGERNAME>
            <ISINVOICE>Yes</ISINVOICE>
            <PERSISTEDVIEW>Invoice Voucher View</PERSISTEDVIEW>
            <VCHENTRYMODE>Item Invoice</VCHENTRYMODE>

            <CLASSNAME>Sales @ 18 %</CLASSNAME>
            <CMPGSTIN>COMPANY_GSTIN</CMPGSTIN>
            <PARTYGSTIN>CUSTOMER_GSTIN</PARTYGSTIN>
            <GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
            <PLACEOFSUPPLY>STATE_NAME</PLACEOFSUPPLY>

            <!-- Repeat for each stock item -->
            <ALLINVENTORYENTRIES.LIST>
              <STOCKITEMNAME>ITEM_NAME</STOCKITEMNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <RATE>RATE_PER_UNIT</RATE>
              <AMOUNT>TAXABLE_VALUE</AMOUNT>
              <ACTUALQTY>QUANTITY</ACTUALQTY>
              <BILLEDQTY>QUANTITY</BILLEDQTY>
              <BATCHALLOCATIONS.LIST>
                <GODOWNNAME>Main Location</GODOWNNAME>
                <BATCHNAME>Primary Batch</BATCHNAME>
                <AMOUNT>TAXABLE_VALUE</AMOUNT>
                <ACTUALQTY>QUANTITY</ACTUALQTY>
                <BILLEDQTY>QUANTITY</BILLEDQTY>
              </BATCHALLOCATIONS.LIST>
              <ACCOUNTINGALLOCATIONS.LIST>
                <LEDGERNAME>SALES_LEDGER</LEDGERNAME>
                <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
                <AMOUNT>TAXABLE_VALUE</AMOUNT>
              </ACCOUNTINGALLOCATIONS.LIST>
            </ALLINVENTORYENTRIES.LIST>

            <!-- LEDGERENTRIES.LIST required in Invoice Voucher View -->
            <LEDGERENTRIES.LIST>
              <LEDGERNAME>CUSTOMER_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>-TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Output Cgst @ 9 %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>CGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>

            <LEDGERENTRIES.LIST>
              <LEDGERNAME>Output Sgst @ 9 %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>SGST_AMOUNT</AMOUNT>
            </LEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

---

## As Voucher — no class (ledger-only)

`OBJVIEW="Accounting Voucher View"` + `ISINVOICE=No`. Customer entry **must come first**.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>Vouchers</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <VOUCHER VCHTYPE="Sales" ACTION="Create" OBJVIEW="Accounting Voucher View">
            <GUID>UNIQUE_GUID</GUID>
            <DATE>YYYYMMDD</DATE>
            <VOUCHERTYPENAME>Sales</VOUCHERTYPENAME>
            <VOUCHERNUMBER>INVOICE_NO</VOUCHERNUMBER>
            <NARRATION>NARRATION_TEXT</NARRATION>
            <ISINVOICE>No</ISINVOICE>
            <PARTYLEDGERNAME>CUSTOMER_LEDGER</PARTYLEDGERNAME>

            <!-- Customer FIRST — drives Day Book Particulars -->
            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>CUSTOMER_LEDGER</LEDGERNAME>
              <ISPARTYLEDGER>Yes</ISPARTYLEDGER>
              <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
              <AMOUNT>-TOTAL_AMOUNT</AMOUNT>
              <BILLALLOCATIONS.LIST>
                <NAME>INVOICE_NO</NAME>
                <BILLTYPE>New Ref</BILLTYPE>
                <AMOUNT>-TOTAL_AMOUNT</AMOUNT>
                <BILLDATE>YYYYMMDD</BILLDATE>
              </BILLALLOCATIONS.LIST>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>SALES_LEDGER</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>BASE_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Output Cgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>CGST_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>

            <ALLLEDGERENTRIES.LIST>
              <LEDGERNAME>Output Sgst @ RATE %</LEDGERNAME>
              <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
              <AMOUNT>SGST_AMOUNT</AMOUNT>
            </ALLLEDGERENTRIES.LIST>
          </VOUCHER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```


path: reference/ledgers.md
content: # Ledgers — Check & Create

Covers: ledger existence check · party ledger creation (customer/vendor) · minimal ledger creation.

## Fetch party GSTIN, place of supply, and address

Use this before PDF generation to auto-fill `customer-gstin`, `place-of-supply`, and address from the party ledger already in Tally.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER>
    <VERSION>1</VERSION>
    <TALLYREQUEST>Export</TALLYREQUEST>
    <TYPE>Data</TYPE>
    <ID>PartyDetailReport</ID>
  </HEADER>
  <BODY>
    <DESC>
      <STATICVARIABLES>
        <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
        <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
      </STATICVARIABLES>
      <TDL>
        <TDLMESSAGE>
          <REPORT NAME="PartyDetailReport">
            <FORMS>PartyDetailForm</FORMS>
          </REPORT>
          <FORM NAME="PartyDetailForm">
            <PARTS>PartyDetailPart</PARTS>
          </FORM>
          <PART NAME="PartyDetailPart">
            <LINES>PartyDetailLine</LINES>
            <REPEAT>PartyDetailLine : PartyLedgerColl</REPEAT>
            <SCROLL>Vertical</SCROLL>
          </PART>
          <LINE NAME="PartyDetailLine">
            <FIELDS>FldName, FldGSTIN, FldPlaceOfSupply, FldRegType, FldAddr1</FIELDS>
          </LINE>
          <FIELD NAME="FldName">
            <SET>$Name</SET>
          </FIELD>
          <FIELD NAME="FldGSTIN">
            <SET>$PARTYGSTIN</SET>
          </FIELD>
          <FIELD NAME="FldPlaceOfSupply">
            <SET>$PriorStateName</SET>
          </FIELD>
          <FIELD NAME="FldRegType">
            <SET>$GSTRegistrationType</SET>
          </FIELD>
          <FIELD NAME="FldAddr1">
            <SET>$Address</SET>
          </FIELD>
          <COLLECTION NAME="PartyLedgerColl">
            <TYPE>Ledger</TYPE>
            <FILTER>ByLedgerName</FILTER>
          </COLLECTION>
          <SYSTEM TYPE="Formulae" NAME="ByLedgerName">
            $Name = "PARTY_LEDGER_NAME"
          </SYSTEM>
        </TDLMESSAGE>
      </TDL>
    </DESC>
  </BODY>
</ENVELOPE>
```

**Parse the response:**

| Field needed | XML path | Example |
|---|---|---|
| `customer-gstin` | `FldGSTIN` → maps to `$PARTYGSTIN` | `24AFTPD8403N1Z3` |
| `place-of-supply` | `FldPlaceOfSupply` → maps to `$PriorStateName` | `Gujarat` |
| Registration type | `FldRegType` → maps to `$GSTRegistrationType` | `Regular` / `Unregistered` |
| Address line 1 | `FldAddr1` → maps to `$Address` | `C/1, Amarnath Tenament` |

**Full address** — the Day Book / Voucher Register export for any voucher involving this party includes the complete `ADDRESS.LIST` with all lines. Parse it from there when you need more than line 1.

**Place of supply decision:**
- If `FldPlaceOfSupply` == company's state → intra-state → CGST + SGST apply
- If different → inter-state → IGST applies
- If `FldPlaceOfSupply` is empty (unregistered party) → default to company's state

**If `FldGSTIN` is empty:** party is unregistered — omit `--customer-gstin` flag; do not use `--b2b`.

---

## Fetch company address (for PDF `--company-address`)

Use this to auto-fill the seller address on the invoice.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER>
    <VERSION>1</VERSION>
    <TALLYREQUEST>Export</TALLYREQUEST>
    <TYPE>Data</TYPE>
    <ID>CompanyAddrReport</ID>
  </HEADER>
  <BODY>
    <DESC>
      <STATICVARIABLES>
        <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
        <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
      </STATICVARIABLES>
      <TDL>
        <TDLMESSAGE>
          <REPORT NAME="CompanyAddrReport">
            <FORMS>CmpAddrForm</FORMS>
          </REPORT>
          <FORM NAME="CmpAddrForm">
            <PARTS>CmpAddrPart</PARTS>
          </FORM>
          <PART NAME="CmpAddrPart">
            <LINES>CmpAddrLine</LINES>
            <REPEAT>CmpAddrLine : CmpColl</REPEAT>
            <SCROLL>Vertical</SCROLL>
          </PART>
          <LINE NAME="CmpAddrLine">
            <FIELDS>FldAddr, FldPin, FldState</FIELDS>
          </LINE>
          <FIELD NAME="FldAddr">
            <SET>$Address</SET>
          </FIELD>
          <FIELD NAME="FldPin">
            <SET>$PinCode</SET>
          </FIELD>
          <FIELD NAME="FldState">
            <SET>$StateName</SET>
          </FIELD>
          <COLLECTION NAME="CmpColl">
            <TYPE>Company</TYPE>
          </COLLECTION>
        </TDLMESSAGE>
      </TDL>
    </DESC>
  </BODY>
</ENVELOPE>
```

**Parse the response** and build the `--company-address` string:

| Field | XML tag | Example |
|---|---|---|
| Address line 1 | `FldAddr` | `Shop No 6, Rajendra Shopping Center` |
| Pincode | `FldPin` | `380008` |
| State | `FldState` | `Gujarat` |

Combine as: `"<FldAddr>, <FldState> <FldPin>"`. For the remaining address lines (stored in Tally but not returned by `$Address`), append them from known company data or ask the user once to confirm.

**Company GSTIN** — not available via Company TDL fields. Read `<CMPGSTIN>` from any recent Day Book sales voucher export.

---

## Check if a ledger exists

Fetch the List of Accounts and search the response for the ledger name before posting any voucher.

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Export Data</TALLYREQUEST></HEADER>
  <BODY>
    <EXPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>List of Accounts</REPORTNAME>
        <STATICVARIABLES>
          <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
    </EXPORTDATA>
  </BODY>
</ENVELOPE>
```

Search the response XML for `<NAME>LEDGER_NAME</NAME>`. If absent, create the ledger before posting.

## Create party ledger (customer or vendor)

Collect all fields below from the user before creating. Do **not** guess GSTIN, state, or opening balance.

| Field | Description |
|---|---|
| `LEDGER_NAME` | Full legal name |
| `PARENT` | `Sundry Debtors` (customer) or `Sundry Creditors` (vendor) |
| `PARTYGSTIN` | 15-digit GSTIN (omit if unregistered) |
| `GSTREGISTRATIONTYPE` | `Regular` / `Unregistered` / `Consumer` / `Composition` |
| `STATE_NAME` | State of registered address |
| `APPLICABLEFROM` | GST effective date `YYYYMMDD` |
| `ADDRESS_LINE_1/2` | Street address lines |
| `OPENINGBALANCE` | 0 if none; positive = credit, negative = debit |

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <LEDGER NAME="LEDGER_NAME" ACTION="Create">
            <NAME>LEDGER_NAME</NAME>
            <PARENT>Sundry Creditors</PARENT>
            <TAXTYPE>Others</TAXTYPE>
            <GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
            <PARTYGSTIN>PARTY_GSTIN</PARTYGSTIN>
            <COUNTRYOFRESIDENCE>India</COUNTRYOFRESIDENCE>
            <ISBILLWISEON>No</ISBILLWISEON>
            <OPENINGBALANCE>0</OPENINGBALANCE>

            <LANGUAGENAME.LIST>
              <NAME.LIST TYPE="String">
                <NAME>LEDGER_NAME</NAME>
                <NAME>2</NAME>
              </NAME.LIST>
              <LANGUAGEID>1033</LANGUAGEID>
            </LANGUAGENAME.LIST>

            <LEDGSTREGDETAILS.LIST>
              <APPLICABLEFROM>YYYYMMDD</APPLICABLEFROM>
              <GSTREGISTRATIONTYPE>Regular</GSTREGISTRATIONTYPE>
              <STATE>STATE_NAME</STATE>
              <PLACEOFSUPPLY>STATE_NAME</PLACEOFSUPPLY>
              <GSTIN>PARTY_GSTIN</GSTIN>
              <ISOTHTERRITORYASSESSEE>No</ISOTHTERRITORYASSESSEE>
              <CONSIDERPURCHASEFOREXPORT>No</CONSIDERPURCHASEFOREXPORT>
              <ISTRANSPORTER>No</ISTRANSPORTER>
              <ISCOMMONPARTY>No</ISCOMMONPARTY>
            </LEDGSTREGDETAILS.LIST>

            <LEDMAILINGDETAILS.LIST>
              <ADDRESS.LIST TYPE="String">
                <ADDRESS>ADDRESS_LINE_1</ADDRESS>
                <ADDRESS>ADDRESS_LINE_2</ADDRESS>
              </ADDRESS.LIST>
              <APPLICABLEFROM>YYYYMMDD</APPLICABLEFROM>
              <MAILINGNAME>LEDGER_NAME</MAILINGNAME>
              <STATE>STATE_NAME</STATE>
              <COUNTRY>India</COUNTRY>
            </LEDMAILINGDETAILS.LIST>
          </LEDGER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

For **unregistered** parties: omit `<PARTYGSTIN>` and set `<GSTREGISTRATIONTYPE>Unregistered</GSTREGISTRATIONTYPE>` in both the header and `LEDGSTREGDETAILS.LIST`.

## Create minimal ledger (GST / bank / expense ledgers)

Use for non-party ledgers (GST duty heads, bank accounts, expense accounts).

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <LEDGER NAME="LEDGER_NAME" ACTION="Create">
            <NAME>LEDGER_NAME</NAME>
            <PARENT>PARENT_GROUP</PARENT>
          </LEDGER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

## Ledger group reference

| Ledger type | Parent group |
|---|---|
| Customer (debtor) | `Sundry Debtors` |
| Vendor (creditor) | `Sundry Creditors` |
| Sales income | `Sales Accounts` |
| Purchases | `Purchase Accounts` |
| Direct costs | `Direct Expenses` |
| Indirect expenses | `Indirect Expenses` |
| Bank account | `Bank Accounts` |
| Cash | `Cash-in-Hand` |
| GST ledgers | `Duties &amp; Taxes` |

## GST duty ledger creation (Input / Output CGST / SGST)

Use when a GST ledger is missing. Repeat for each rate slab (substitute rate and duty head).

```xml
<?xml version="1.0" encoding="utf-8"?>
<ENVELOPE>
  <HEADER><TALLYREQUEST>Import Data</TALLYREQUEST></HEADER>
  <BODY>
    <IMPORTDATA>
      <REQUESTDESC>
        <REPORTNAME>All Masters</REPORTNAME>
        <STATICVARIABLES>
          <SVCURRENTCOMPANY>COMPANY_NAME</SVCURRENTCOMPANY>
        </STATICVARIABLES>
      </REQUESTDESC>
      <REQUESTDATA>
        <TALLYMESSAGE xmlns:UDF="TallyUDF">
          <LEDGER NAME="Input Cgst @ 9 %" ACTION="Create">
            <NAME>Input Cgst @ 9 %</NAME>
            <PARENT>Duties &amp; Taxes</PARENT>
            <TAXTYPE>GST</TAXTYPE>
            <GSTDUTYHEAD>CGST</GSTDUTYHEAD>
            <RATEOFTAXCALCULATION>9</RATEOFTAXCALCULATION>
            <ISGSTDUTYLEDGER>Yes</ISGSTDUTYLEDGER>
          </LEDGER>
        </TALLYMESSAGE>
      </REQUESTDATA>
    </IMPORTDATA>
  </BODY>
</ENVELOPE>
```

| `GSTDUTYHEAD` value | Use for |
|---|---|
| `CGST` | Input/Output CGST ledgers |
| `SGST/UTGST` | Input/Output SGST ledgers |
| `IGST` | Input/Output IGST ledgers |


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal:  | SkillSpector: clean (LOW)