FX handling
Anything not denominated in INR — SAR hotel invoices, USD flight blocks, AED visa fees — needs an exchange rate to enter the books. This runbook tells you where rates come from, how the app captures them at posting time, and what to do at month-end for open foreign-currency balances.
Base currency for the Al Huda books is INR. Every voucher ultimately
posts INR values on JournalLine.debit and JournalLine.credit; the
source-currency amount and the rate used are pinned alongside.
1. When FX matters
Any time you post a voucher whose source amount is not INR:
- SAR hotel invoices (Makkah / Madinah suppliers bill in SAR).
- USD / AED airline or ticketing DMC invoices.
- SAR / USD ground-transport contracts.
- Foreign agent commissions or settlements.
If the customer-facing invoice is in INR but one of your cost lines came from a foreign supplier, you still need an FX rate — but only for the cost-side posting.
2. How the rate is captured at posting
Two migrations added the audit trail for FX postings:
supabase/migrations/20260418060325_journal_fx_rate.sql— addsJournalEntry.fxRateUsed(the header-level rate).supabase/migrations/20260418150000_journal_line_original_amounts.sql— addsJournalLine.originalDebit,originalCredit,originalCurrency,fxRate(per-line source values).
What this means in practice:
- When you post a SAR hotel bill, the voucher stores
originalDebit: 4500 SAR,fxRate: 22.10,originalCurrency: 'SAR'anddebit: ₹99,450all on the same line. - The rate at the moment you clicked Post is frozen. If someone later edits the supplier contract's exchange rate, the historical voucher does not change — it still reports the rate that was used when it was posted.
- For pure INR postings, all four columns are
NULL— no conversion happened.
FX rate cannot be edited after posting
Once a voucher is approved, the FX rate pinned on it is immutable in the UI. The only way to change a posted rate is to reverse the voucher and re-post with the correct rate. See the reversing-and-correcting runbook.
3. Where the rate comes from
The app asks you for the rate at posting time. It does not currently fetch from a live feed.
Policy (recommended — confirm with your Finance Manager)
- For supplier invoices linked to an inventory record (airline block, hotel contract, ground-transfer contract), the contract's stored exchange rate is the default — the one agreed at the time the contract was booked. Use it unless the supplier bills against a different rate in the invoice itself.
- For standalone supplier invoices (a one-off SAR bill with no inventory contract), use the RBI reference rate for the invoice date. Source: https://www.rbi.org.in/scripts/ReferenceRateArchive.aspx
- For customer receipts in foreign currency (rare), use the rate at which the bank actually credited your INR account — that's the honest number.
Record the rate source in the memo
Always write the rate source in the voucher memo, e.g. Rate:
RBI ref 2026-04-14 — 1 SAR = 22.10 INR. This saves the auditor a
round-trip. It is also free evidence if the rate is ever questioned.
4. Posting a foreign-currency voucher — worked example
Scenario: Hotel Al Haram, Makkah, bills SAR 45,000 for April block. You agreed rate at contract was SAR 1 = INR 22.10.
Steps
- Finance → Vouchers → Journal (or the supplier-linked voucher form, if the invoice ties back to a hotel inventory record).
- Currency: set to
SAR. - Original Amount:
45,000.00. - FX Rate:
22.10. The form auto-computes the INR column (9,94,500.00). - Fill the rest of the voucher exactly like an INR bill — expense line
debits
5101 Hotel Purchases, credit line credits the supplier's creditor account. Amounts in the INR columns flow from your rate. - In the Memo, note the rate source:
SAR 45,000 @ 22.10 (contract rate) = INR 9,94,500 — Hotel Al Haram April invoice INV-2326. - Verify Total Dr = Total Cr in INR terms.
- Click Post.
What the journal stores
| Column | Debit line (expense) | Credit line (supplier) |
|---|---|---|
debit |
994500.00 | — |
credit |
— | 994500.00 |
originalDebit |
45000.00 | — |
originalCredit |
— | 45000.00 |
originalCurrency |
SAR | SAR |
fxRate |
22.10 | 22.10 |
Header fxRateUsed is also 22.10.
5. Period-end FX revaluation
Open foreign-currency balances (unpaid SAR invoices, USD advances still sitting with suppliers) carry a rate risk: the rupee moves, so the INR value of those balances at period-end is different from the INR value captured when they were posted.
Current capability
Revaluation is not currently automated
The app does not run an automated period-end FX revaluation job. There is no "Revalue open FX balances" button. If your Finance Manager has decided revaluation is material this month, you run a manual adjustment journal per the procedure below.
Manual revaluation procedure
- Get the period-end closing rate from the RBI reference page for every foreign currency you have open balances in.
- For each supplier / customer with an open foreign-currency balance: a. Pull their ledger. Note the open balance in source currency. b. Compute period-end INR value = (source-currency balance) × (period-end rate). c. Compute the difference vs the INR value currently on the books. This is your unrealised gain or loss.
- Post one adjustment journal per currency with a row per
supplier / customer affected:
- If rupee has weakened (foreign currency worth more INR):
- Debit
5501 FX Loss (Unrealised)or Credit4501 FX Gain (Unrealised)depending on net direction. - Opposite side hits the supplier creditor / customer debtor per-party.
- Debit
- Memo:
Period-end FX revaluation, April 2026 close, RBI rate 1 SAR = 22.45 (prev contract 22.10).
- If rupee has weakened (foreign currency worth more INR):
- Approve the revaluation journal via the normal maker-checker flow.
- At the start of the next period, post a reversing entry for the whole revaluation (see reversing-and-correcting.md §1). Without the reversal, next month the revaluation sits on top of the actual realised FX gain/loss when the invoice finally settles.
Why reverse at period start
Standard Indian accounting practice: unrealised FX adjustments at period-end are reversed on Day 1 of the next period so that when the invoice is actually paid, the realised gain/loss hits the books as a single number, not mixed with the prior-period estimate.
6. Verifying an FX voucher posted correctly
- [ ] Trial Balance: run in INR (default). The voucher contributes the correct INR debit and INR credit; overall balance is zero.
- [ ] Drill into the journal (Journal tab → click the voucher row): the Voucher Detail dialog should show both the INR amounts and the original-currency amounts side by side, with the rate.
- [ ] Supplier ledger: the invoice is visible. If you drill into the line, the source-currency amount is carried through.
- [ ] Audit log: the
finance.voucher.createentry records the voucher id; headerfxRateUsedis populated.
Reports are INR-only
Trial Balance, Balance Sheet, P&L, Aging — every report prints in
INR. The source-currency information is only visible on the
individual voucher / ledger line. If the auditor asks for a
foreign-currency report, you export the relevant account
statement and filter the originalCurrency column.
7. Common mistakes
- Typing the wrong rate direction —
1 SAR = 22.10 INRis correct.1 INR = 22.10 SARis wrong. The form accepts either number, but the INR amount will be off by a factor of 500+ if you invert it. Sanity check: if your INR amount has one more digit than it should, you probably inverted the rate. - Using today's rate for an old invoice — the rate should match the invoice date, not today. RBI reference page has historical rates.
- Forgetting to note the rate source in the memo — auditors will always ask. Put it in once, save everyone the email chain.
- Revaluing then forgetting to reverse on day 1 of next period — you end up double-counting FX gain / loss next month when the invoice actually settles.