Skip to main content

FAQ — technical

Q: How do I add a new posting rule?

A: Add a function to services/posting.py — takes a PostingInput, returns a list of PostingLines. Register it in the dispatch dict at the bottom. Balance invariant is enforced at insert; write a unit test that shapes an input and asserts ΣDR = ΣCR.

Q: How do I add a new source (upstream broker)?

A: Four pieces:

  1. brokers/<name>.py — HTTP client (auth, pagination, error retries).
  2. services/<name>_importer.py — map raw row → TransactionPayload.
  3. services/classify.py — add a classify_<name> function.
  4. services/<name>_sync.py — loop customers, call the broker, call import_<name>_batch, optionally recost.

Also: widen the source CHECK in a migration if the source name is new.

Q: How do I add a new endpoint?

A: Add a route to api/jobs.py (jobs) or a new module (reports). Match the existing conventions: Depends(require_ledger_token) for reads, Depends(require_admin_token) for writes, response_model=<Pydantic> always.

Q: Why is the ledger cost-only? Why not mark to market on the GL?

A: Correctness — MTM revenue hasn't crystallized, and posting it would breach the trial balance if credited to an income account. Simplicity — the ledger's job is to prove where the money is, not to speculate on unrealized value. MTM lives on /v1/india/nav (reporting only).

Q: Why 1300 GlomoPay FX Receivable, not immediate revenue?

A: The FX-spread is earned when the order is paid but SETTLED when GlomoPay pays out the merchant batch. 1300 holds the earned-but-unpaid margin; the fx_spread_settle posting clears it to 1010.

Q: What's on the CoA that isn't posting?

A: 2110 Sec Liab - Bonds is dormant (no bonds ingested yet). 4020 Custody Fee Revenue is seeded but not yet firing.

Q: What if GlomoPay is unreachable?

A: Every India endpoint degrades gracefully:

  • Treasury returns configured=false with a warning.
  • Exceptions returns an empty snapshot with a warning.
  • FX-margin returns realized=None for the priced remittances (still shows the assumed accrual).
  • Sync jobs skip the customer and report customers_failed in the response.

Q: What if ViewTrade is unreachable?

A: NAV shows status=error per-customer with the error message. Ledger-recon and Holdings-recon do the same. The scheduled recon check surfaces a warn on the next cycle.

Q: How do I know the trial balance balances?

A: GET /v1/firm/trial_balance sums debit and credit per account; the Category-A trial_balance_zero check runs on every recon cycle and turns fail if it doesn't.

Q: How do I run a one-off sync for a single customer?

A: Pass customer_ids: ["cust-x"] in any sync job's request body.

Q: How do I reverse a transaction?

A:

curl -X POST -H "X-Ledger-Admin-Token: <TOKEN>" \
http://localhost:8078/v1/transactions/{txn_id}/reverse

Idempotent — a second call returns the existing reversal.

Q: What if I need to re-cost historical transactions?

A: recosted_at IS NULL is the filter. Set the column back to NULL manually for the affected txns, then run POST /v1/jobs/recost.