Skip to content

Finance audit — 17 September 2026

Five independent audits of the finance module and its connections, run on integration/ops-upgrade (code as on disk, read-only). Lenses: (1) posting rules and double entry, (2) finance ↔ operations, (3) reports and reconciliation, (4) controls and tax compliance, (5) screens, workflow and intelligence. Line references are to src/lib/api.ts unless stated and will drift as Wave 1 merges; search by handler name.

Not legal or tax advice. Items marked [CA] need the company's Chartered Accountant.

Verdict

The finance module has broad features but its numbers cannot be relied on and its controls can be bypassed:

  • Books: revenue is booked when a booking is created (not at tour completion, FIN-001); cancellations reverse entries more than once; foreign-currency purchases are posted without conversion; air seat cost never reaches the P&L; realised FX is always zero; posted entries are edited and hard-deleted.
  • Money vs operations: operational screens use a stored Booking.balanceAmount that is wrong for rate-sheet groups (always 0 → tickets auto-cleared), after refunds (refund shows as due) and after "mark paid" (cash that never reaches the books).
  • Reports: silently truncated at 1,000 ledger lines; dated by entry time, not voucher date; opening balances counted twice; GST summary ignores cancellations; locked periods can still change.
  • Controls: maker-checker is enforced by the database in one place only; receipts can be saved as already verified; anyone signed in can approve B2B cancellations; HR holds every finance permission; TCS is not implemented; tax invoices lack mandatory fields.
  • Screens: one 14,000-line page for every role; the confirmation dialog is not used; "Approve all" and "Clear all ledger data" are one click; the intelligence panel reports "no FX exposure" for a business paying SAR; the AI copilot sends customer names and balances to outside providers from browser-supplied data.

Findings by severity

P0 — stop now (money can be lost, misstated or approved without authority)

# Finding Rules Audit
1 B2B cancellation approve/reject has no permission check; table policy USING(true) — any signed-in user, including customers, can approve ACC-020, FIN-032 4
2 Receipts saved as verified from 5 staff screens; API accepts client status and verifiedBy; cashier can self-verify FIN-032 4, 5
3 Journal approval maker-checker is browser-only; DB allows finance.edit to approve; reversals auto-approve regardless of original FIN-032, FIN-031 1, 4
4 ADMIN_HR (and IT_ADMIN) hold every finance permission and can grant access ACC-012 4
5 Posted entries are mutable: payer/agent change rewrites posted lines; hard deletes on block/FIT/supplier/opening balance/account delete; ledger reset; rebuild-all reposts revenue (gated by inventory.create) FIN-031, AUD-002 1, 2, 4
6 Mark-paid creates verified payments with no journal, excludes GST and clears tickets FIN-033 1, 2
7 Rate-sheet group bookings have totalAmount = 0 → balance 0 → tickets cleared, readiness green, group P&L revenue 0 FIN-033 2 (fixed for ticket clearance in 1D)
8 Payment refund: no cap, any status, wrong account; verified→rejected keeps the receipt journal PRC-030 1, 2
9 Periods and years: any staff user (incl. AGENT) can reopen periods; lock covers only journal inserts; year close is a label FIN-031 3, 4
10 Reports truncated at 1,000 rows (BS, P&L, cash flow, statements, GST, AP aging, bank match) FIN-033 3

P1 — books are wrong

# Finding Rules Audit
11 No Advances account; revenue at booking create / group-invoice post; nothing at completion FIN-001, LC-041 1
12 Cancellation reversals stack (passenger → booking → delete); refund override ignored; retained charge never booked as income; GST reversed on a different basis than charged CXL-*, PRC-020 1, 2
13 Booking edit + group invoice double revenue; group invoice posting skipped for the whole group if one legacy booking exists FIN-030 1, 2
14 Foreign currency: block, FIT, ground, food purchase, group invoice and booking amounts posted without INR conversion; realised FX always 0; revaluation never auto-reversed FIN-034 1, 2
15 Air seat cost never expensed for package passengers; periodic closing-stock entry double-counts perpetual stock FIN-030 1
16 Non-TDS supplier payments post to the 2100 control account while purchases credit supplier sub-ledgers → suppliers never show paid FIN-030 1
17 Reports use createdAt, period locks use entryDate; opening balances double-counted; BS from filter drops history FIN-033 3
18 Transfer moves only the base rate, auto-approved, no GST, no group-invoice credit note LC-030 1, 2
19 Partner-portal bookings, agent invoices, visa fees, ticket void/refund, incidents post nothing FIN-030 1, 2
20 Hotel edit reposts to expense instead of stock; B2B cancellation hardcodes 18% GST; airline filing credits stock with entered amounts, not seat cost FIN-030 1
21 Journal header and lines inserted non-atomically (browser and Razorpay webhook); posting failures swallowed CXL-001 1, 2
22 Customer/agent/portal ledgers built from operational tables, each on a different basis FIN-033 2, 3
23 Group and inventory P&L double-count and mix currencies; group P&L ignores invoices and credit notes FIN-033 2, 3

P1 — statutory

# Finding Rules Audit
24 TCS (Income-tax Act 2025 s.394(1)) not implemented anywhere [CA] FIN-020 4
25 No GST on advances; no receipt voucher (r.50) or refund voucher (r.51) FIN-011 4
26 Group invoice print has no GSTIN/SAC/place of supply; booking invoice lacks GSTINs and tax split FIN-010 4
27 Cancelling an issued invoice removes it from GSTR-1 instead of raising a credit note FIN-012 4
28 GSTR-3B splits all GST as CGST/SGST (IGST never); GSTR-1 repeats taxable value across instalment invoices; B2CL threshold likely stale [CA] FIN-010 3, 4
29 5% scheme with input tax credit still claimed on supplier GST [CA] FIN-010 4
30 TDS: only 194C/J/Q (no 194H commission, 195, no-PAN rate); YTD threshold from browser; no deposit journal; 26Q not in RPU format FIN-021 4
31 Invoice/receipt numbers: GINV/AINV non-atomic, counters editable, number functions callable anonymously, no FY series FIN-010 4

P2 — workflow, screens, intelligence

# Finding Rules Audit
32 useConfirm unused in finance; ~40 state-changing actions without Yes/No; four window.confirm; "Approve all" and "Clear all ledger data" one click UX-001 5
33 Only 13 permission gates across the finance page; ~40 finance permissions unused in the UI; every role lands on Accounts ACC-012, UX-010 5
34 Eight ways to record a receipt with different behaviour; record-payment drops date and notes; voucher receipt loops non-atomic posts FIN-032 5
35 Landing KPIs wrong (liquid funds = lifetime receipts; payables 0 until Reports opened) INT-002 5
36 FX intelligence reads wrong field names → always "no exposure"; supplier checks fed an empty list; forecast assumptions invented; GST calendar wrong INT-002 5
37 Copilot context built in the browser (injectable), PII to four external AI providers without masking or logging, only finance.view checked, data truncated while claimed complete INT-006, AUD-020 5
38 Bank reconciliation: no reference matching or confidence, pending payments matchable, duplicate matches across imports, manual match unvalidated, no statement-vs-ledger proof FIN-033 3, 5
39 47 swallowed errors (outage looks like "no data"); tabs cached for the session; deep links broken PLT 5
40 Print uses the wrong brand red; no amount in words; negatives shown as ₹-1,234 UX 5

Target design

  1. One posting function per business event, in the database. The operational change and its journal are written in one transaction; the actor comes from the session; approver ≠ maker; reversals link to the original, follow its status, and can never exceed what remains. Posted entries are never updated or deleted — corrections are reversals, credit notes or debit notes. (FIN-030/031/032, CXL-001)
  2. Posting rulebook (FIN-030). Advances on receipt (2150 Advances from Customers, with GST on advance and TCS); revenue at tour completion (principal 4000 / agent 4100, FIN-003); refunds via 2160 Refund Payable; retained cancellation charges to 4200 Cancellation Income; purchases to Stock-in-Hand at INR on the transaction date and supplier sub-ledgers only; consumption Dr 5100–5400 / Cr 1310; Razorpay via a clearing account with gateway fees. Full table in audit 1 §E — to be copied into 07-finance-accounting-tax.md as FIN-030 detail once the CA answers FIN-002/003/010.
  3. Balances come from the ledger (FIN-033). Booking paid/outstanding, invoice balances, party statements, portal balances, ticket clearance and readiness all read one ledger-derived view per booking/invoice/party. Stored totals become caches maintained by the database, never written by the browser.
  4. Dimensions on journal lines. Real foreign keys for booking, passenger, group, invoice, payment, block/FIT, supplier and partner, so group and inventory P&L are sums of ledger lines.
  5. Reports as database functions over approved lines dated by entryDate (IST), paged, with standard filters, comparatives and drill-down report → account → voucher → source document → audit trail.
  6. Periods and years. Lock trigger on every ledger-affecting table; unlock needs a second approver and a reason; year close posts closing entries and carries balances forward.
  7. Controls. Role bundles re-seeded (cashier records, accountant prepares and verifies others', finance manager approves, HR and IT hold no finance rights, auditor read-only); approval limits by amount (ACC-030); MFA required for finance functions.
  8. Tax. TCS module; GST on advances with receipt/refund vouchers; CGST/SGST/IGST by place of supply; statutory invoice fields; credit notes instead of cancelling issued invoices; per-FY atomic numbering; TDS rate table with 194H/195/no-PAN rate, database YTD, challan with deposit journal, RPU export.
  9. Nightly drift check (AUD-010). Unbalanced vouchers; entryDate vs createdAt; opening balances; control vs sub-ledger vs operational balances; verified payments without approved journals; GST and TDS ledgers vs reports; supplier ledger; bank vs ledger; changes inside locked periods; group P&L vs tagged lines; stored counters. Results go to a drift register; repairs only with management approval.
  10. Finance workspace (UX-010/011). Role dashboards (cashier, accountant, finance manager, CEO, auditor); left rail Books · Receivables · Payables · Tax · Treasury · Close · Reports; one receipt composer; one approvals inbox; live Dr/Cr preview; 360 money panels on customer, partner, supplier and group; useConfirm everywhere; URL-driven state.
  11. Smart finance (INT-150..154). Receipt auto-allocation, bank matching with confidence, anomaly feed, commitment-based cash forecast, FX exposure, dunning by risk, tax and close assistant — all computed in the database; AI only narrates, with PII masked and every figure linked to vouchers.

Remediation plan

Workstream Scope (finding #) When
1B Money integrity ✅ merged Done: 1, 2, 6, 10 (TB/P&L/BS/cash flow/day book), refund caps and approval (8), immutability and removal of reset/force-delete/mark-paid (5), period/year writes (9), rebuild gate, entryDate in reports (17), realised FX (14), FinanceConfig read policy. Still open → F1–F4: direct insert of approved journals (3); reversal of pending originals auto-approved (3, 12); 1,000-row cap in statements/ledgers/GST/AP aging/settlement/bank match (10); opening balances double-counted (17); GST summary excludes reversals (28); permission checks on aging, receivables-payables, pending settlements, /finance/ledger, customer ledger, pl-summary, inventory P&L; receipt voucher loop and dropped date (34); Razorpay (21); block overpay guard; supplier payments to 2100 (16); SupplierTransaction/TDS delete policies; GINV/AINV numbering (31); automatic credit/debit notes (27); archive instead of delete for blocks/FIT Wave 1 ✅
1D Tickets/visa/comms (done) 7 for ticket clearance (money-based check incl. group invoices) Wave 1 ✅
F1 Controls hardening ✅ merged Done: direct insert of approved journals and reversal status/cap (3); role bundle re-seed with SUPER_ADMIN / CHARTERED_ACCOUNTANT (4); period and year write permissions, supplier-transaction and TDS immutability (9); GINV/AINV numbering and counter editing (31); supplier payments to the sub-ledger (16); opening balances double-counted (17); GST summary excluding reversals (28); the 1,000-row cap on statements, ledgers, GST, AP aging, settlement and bank match (10); permission checks on aging, receivables-payables, pending settlements, /finance/ledger, customer ledger, pl-summary, inventory P&L; receipt date and the receipt-voucher loop (34); block overpay guard; approval limits for refunds and manual journals (ACC-030). Still open → F2–F4: automatic credit/debit notes (27), Razorpay webhook (21), archive instead of delete for blocks/FIT, MFA for finance functions, approval limits for discount / supplier payment / fare / seat release / write-off, second approver above ₹2,00,000 Wave 1 follow-up ✅
F2 Posting engine 11–16, 18–21 — posting functions per event, rulebook, dimensions, FX, completion revenue Wave 5 tax/closeout, starts after CA answers; defects 12–16, 20–21 fixed earlier where they don't depend on FIN-002/003/010
F3 Ledger-derived balances 7 (remaining), 22, 23 — views, portal/staff/ticket/readiness on one basis With F2
F4 Reports and close 10, 17, 38 — report functions, year close, bank rec rebuild, drift register Wave 4 (finance workspace)
F5 Tax 24–30 Wave 5, after CA review
F6 Finance workspace 32–35, 39, 40 — split page, role dashboards, composer, approvals inbox, confirmations Wave 2 (confirm + dashboards), Wave 4 (split)
F7 Finance intelligence 36–37, INT-150..154 — server-side copilot context with masking and permission checks; fix FX/supplier/forecast/GST calendar Wave 2 (copilot safety P0), Wave 4

Questions for the Chartered Accountant

  1. FIN-002: Ind AS or AS for Alhuda Travels; FIN-003: principal or agent per product (packages, air-only, visa-only, hotel-only, B2B seat sales).
  2. FIN-010: GST scheme for Hajj/Umrah packages (5% without ITC vs 18% with ITC) and whether current ITC claims must be reversed.
  3. FIN-020: TCS under s.394(1) — rate, threshold, collection timing (gross-up vs within package price), treatment of B2B sales to agents, refunds, return and certificate forms under the 2025 Act.
  4. TDS sections and rates under the 2025 Act numbering; commission (194H equivalent) and payments to Saudi suppliers (195 equivalent).
  5. GSTR-1 B2C large threshold and required tables (at/atadj/doc_issue); e-invoicing applicability by turnover.
  6. Time limits for credit notes and treatment of cancellations after invoicing.