Pinnex Bridge v0.3.3 - Setup

PREREQUISITES
  - Tally Prime is installed and running
  - In Tally Prime: F12 Configure -> Advanced -> ODBC Server is ENABLED (port 9000)
  - You can run PowerShell as Administrator

UPGRADE FROM v0.3.0 / v0.3.1 / v0.3.2 (3 STEPS)
  1. Extract this ZIP.
  2. Right-click install.ps1 -> "Run with PowerShell" (as Administrator).
  3. Done. Your existing .env is preserved.

  The installer detects the existing PinnexBridge service, stops it,
  swaps in the new pinnex-bridge.exe, and restarts. TALLY_COMPANY,
  LICENSE_KEY and all other settings stay exactly as you had them.

FRESH INSTALL (3 STEPS)
  1. Extract this ZIP.
  2. Right-click install.ps1 -> "Run with PowerShell" (as Administrator).
  3. When prompted, paste:
       - the license key Ravya sent you,
       - the firm code (e.g. NSQ),
       - your DEFAULT Tally company name EXACTLY as it appears in Tally Prime,
         INCLUDING any "(From Apr 25)" or similar suffix shown in
         "Select Company" view.

  v0.3.3 note: the .env TALLY_COMPANY is now just the DEFAULT. Callers can
  override it per request via the `tally_company` parameter — see
  CHANGES IN v0.3.3 below.

A Windows service called "PinnexBridge" is installed and starts
automatically with the PC.

VERIFY
  Open PowerShell and run:
     Get-Service PinnexBridge
     Invoke-WebRequest http://127.0.0.1:9888/health -UseBasicParsing | % Content

  v0.3.3 health response includes:
     "version":          "0.3.3"
     "company_loaded":   true / false
     "matched_company":  "<canonical name from Tally>"
     "loaded_companies": ["Co A", "Co B", ...]
     "capabilities": {
        "per_call_tally_company_override": true,
        "raw_xml_forwarding": true
     }
     "license": { "valid": true, "source": "cached" | "online" | "failopen" }

  If company_loaded is false, the response also includes
     "error_detail": "configured company 'X' not found in loaded list: [Y, Z]"
  so you can fix .env without log spelunking.

DEBUG LOGGING
  Edit C:\Program Files\Pinnex Bridge\.env and add:
     LOG_LEVEL=debug
  Then: Restart-Service PinnexBridge
  Now every Tally request / response is logged in full (truncated at 10 KB).

LOGS
  C:\ProgramData\Pinnex Bridge\log\
     bridge-YYYY-MM-DD.log   <- application log (one file per day)
     nssm-stdout.log         <- service stdout (rotated at 10 MB)
     nssm-stderr.log         <- service stderr (rotated at 10 MB)

UNINSTALL
  Right-click uninstall.ps1 -> Run with PowerShell (as Administrator).

TROUBLESHOOTING

  "Cannot run script" / execution policy:
     PowerShell> Set-ExecutionPolicy -Scope Process Bypass
     then re-run install.ps1.

  Service won't start:
     Open the latest C:\ProgramData\Pinnex Bridge\log\bridge-*.log
     Also check nssm-stderr.log for service-level startup errors.

  Health check shows tally_reachable = false:
     - Make sure Tally Prime is open.
     - Tally menu: F12 Configure -> Advanced -> Tally.ERP 9 is acting as
       -> Both, ODBC Server enabled, port 9000.
     - From PowerShell: Test-NetConnection localhost -Port 9000 should be True.

  Health check shows company_loaded = false:
     v0.3.2's "loaded_companies" field tells you exactly what Tally has open.
     Compare it to your TALLY_COMPANY in .env - copy/paste the EXACT name
     (including any "(From Apr 25)" suffix that Tally shows in Select Company).
     Edit C:\Program Files\Pinnex Bridge\.env, fix TALLY_COMPANY, restart:
        Restart-Service PinnexBridge

  License check warnings in the log:
     v0.3.2 fails open when api.pinnex.in is unreachable - that's expected
     when the PC is offline or behind a strict firewall. No action needed
     as long as the bearer-token check on /sync/push keeps working.

  Port 9888 already in use (EADDRINUSE):
     Pick any free port - edit BRIDGE_PORT in C:\Program Files\Pinnex Bridge\.env
     and Restart-Service PinnexBridge.

CHANGES IN v0.3.3
  - tally_post_voucher and tally_post_voucher_xml now accept a per-call
    `tally_company` parameter that overrides the .env TALLY_COMPANY for
    that single call only. One Bridge can post to ANY currently-open
    Tally company without editing .env or restarting the service.

    Example - POST /sync/push:
       {
         "tally_company": "Testing Company",
         "vouchers": [...]
       }

    The response includes:
       "tally_company":        "Testing Company",
       "tally_company_source": "per_call_override"

    so you can confirm where the entries landed.

  - /sync/xml is now a RAW XML pass-through:
       POST /sync/xml?tally_company=<optional>
       Content-Type: text/xml
       Authorization: Bearer <LICENSE_KEY>
       <body: raw Tally Import-XML envelope>
    The Bridge forwards the body to Tally verbatim (rewriting
    SVCURRENTCOMPANY if tally_company is supplied) and returns the same
    counters wrapper as /sync/push:
       { posted, failed, created, altered, ignored, errors, tally_response }
    Malformed bodies return HTTP 400 xml_malformed.
    The old "JSON vouchers -> downloaded XML file" behaviour is gone -
    use /sync/push with dry_run:true to get the generated envelope back.

  - /health now publishes a `capabilities` block so callers can detect
    these features at runtime.

  - Fully backward compatible: existing callers that don't send
    `tally_company` continue to use the .env default. /sync/xml still
    accepts a JSON body of shape {"xml": "<ENVELOPE>..."} for old MCP
    callers.

PREVIOUS CHANGES (v0.3.2)
  - Fixed company-detection request: now uses the documented Collection /
    "List of Companies" XML. v0.3.0/0.3.1's "Export Data" variant returned
    an empty 103-byte CompanyObject on TallyPrime Silver, leaving
    company_loaded permanently false.
  - /health now lists loaded_companies + matched_company so mismatches
    are obvious immediately.
  - Debug body logging via LOG_LEVEL=debug.
  - License verify fails open when api.pinnex.in is unreachable; cached
    timestamp persisted under C:\ProgramData\Pinnex Bridge.
  - install.ps1 preserves an existing .env on upgrade.

PREVIOUS CHANGES (v0.3.1)
  - Default port 9876 -> 9888 (9876 conflicted with Windows IP Helper Service)
  - install.ps1 is pure ASCII; ZIP packager writes UTF-8 BOM defensively
  - API accepts dr_cr: "Dr"/"Cr"/"debit"/"credit" as an alias for
    isDeemedPositive
  - NSSM service writes rotated stdout/stderr logs
