How LedgerMap finds contra entries
A contra entry is a transfer between two of the party's own bank accounts. The money leaves one bank and arrives at the other. Miracle must book it once. This page explains every way the app finds one, what the user sees, and where it can go wrong.
Same UTR / RRN
Both statements print the same bank reference. The server pairs them.
Same amount, no reference
One bank prints no reference. Same amount, ≤ 1 day apart.
Found in Miracle books
The other bank's statement is not imported, but its posting is in Miracle.
Paired by hand
Alt+C or "Pair as contra" on any entry. Any dates.
Where can a user turn a transaction into a contra entry?
Accept or reject a possible contra entry
This is the first review step. It lists transfers the app is not sure about: same-amount pairs between two statements (Way B), and matches with Miracle books (Way C).
- Actions
- Accept (or Enter on the row) saves it. Not contra (or Delete) sets it aside. Accept all N shows when there are 2 or more.
- "Why" column
- Way B: "Same date" or "1 day apart", plus "Same amount on both statements". Way C: Already in Miracle or Booked against Suspense. If other postings also match, it adds "N other postings or entries match too: check it first."
- Effect
- Accept on Way B pairs both entries with each other's bank ledger. Not contra on Way B is permanent (saved on the server). Not contra on Way C is kept only for this tab.
Transfers between the party’s own bank accounts. Each one is exported once, so Miracle does not book it twice.
| Date | From | To | Amount | Why | Actions |
|---|---|---|---|---|---|
| 04/04/2026 | HDFC Current Row 18 · NEFT DR ICIC0000123… | ICICI OD Row 7 · BY TRANSFER | 50,000.00 | 1 day apart Same amount on both statements | ✓ Accept ✕ Not contra |
| 09/04/2026 | HDFC Current Row 31 · IMPS-…-SELF | SBI CC MIRACLE Receipt voucher · 09/04/2026 | 1,20,000.00 | Booked against Suspense A/c Accepting exports it as a transfer; then correct that voucher in Miracle. | ✓ Accept ✕ Not contra |
See saved pairs and break them
The second table on the same step. It lists every saved pair once, with how it was found.
- "Found by" column
- Same reference with the UTR/RRN (Way A). Confirmed (Way B or D, no reference). From Miracle books (Way C misbooked), with "Miracle books it against … : correct that voucher."
- Actions
- Unpair (Delete) for a pair. Undo for a books transfer: it clears the ledger, so the entry goes back to "To confirm".
- Effect of Unpair
- Both sides lose their automatic ledger. The two entries are rejected for good: they are never paired or suggested again.
| Date | From | To | Amount | Found by | Action |
|---|---|---|---|---|---|
| 01/04/2026 | HDFC Current Row 3 | ICICI OD Row 1 | 2,00,000.00 | Same reference HDFCN52026040100509415 | ⛓ Unpair |
| 12/04/2026 | ICICI OD Row 22 | HDFC Current Row 40 | 75,000.00 | Confirmed | ⛓ Unpair |
| 09/04/2026 | HDFC Current Row 31 | SBI CC MIRACLE Receipt voucher · 09/04/2026 | 1,20,000.00 | From Miracle books Miracle books it against Suspense A/c: correct that voucher. | ↶ Undo |
Missing a transfer? Press Alt+C on an entry in any other step to pair it with its other side.
A small button under the narration
Shown in Suggestions, Suspense, Review and All entries. It shows only on an entry with no ledger that has at least one possible partner.
- Partner rule
- Opposite side (debit ↔ credit), on another bank of this import, same amount or the debit higher by a fee (≤ ₹100 and ≤ 1%). No date limit.
- Keyboard
- Not a Tab stop. Alt+C does the same thing.
| Sr. | Date | Narration | Debit | Credit | Ledger |
|---|---|---|---|---|---|
| 40 | 12/04/2026 | TRANSFER FROM 0123XXXX ⇄ Pair as contra | 75,000.00 | Search ledgers… | |
| 41 | 13/04/2026 | UPI/RAMESH TRADERS/… | 4,250.00 | Search ledgers… |
Pick the other side by hand
Alt+C works on the row, in its Ledger box, or anywhere on the page outside another text box. The pop-up lists every partner, nearest date first, with a search box.
- Enter
- Pairs the two. Saved on the server as a pair with no reference (
manual: true). An earlier "Not contra" for the same two is forgotten. - When it cannot pair
- The page says why: "already a contra entry", "a possible contra entry waiting", "Clear its ledger first", or "No credit on another bank … has the same amount".
Pair as a contra entry
A transfer by ledger only (no pair)
The Ledger box offers every ledger except the statement's own bank. So the user can type "ICICI OD" for an HDFC entry. That exports a transfer voucher, but it does not create a pair.
- What then happens
- The server may pair it later if the other side shares a UTR/RRN, or suggest it if the amount is the same and dates are ≤ 1 day apart. If not, the other bank's entry is exported too. See finding F4.
| Narration | Debit | Ledger |
|---|---|---|
| CHQ 000418 SELF | 30,000.00 | icici▌
ICICI OD · Bank Accounts ICICI Lombard Ins. · Expenses |
Reverse actions
Export step: "N entries are already in Miracle and left out" with Show. Each row has Export it (or Delete). It clears the ledger and sets the posting aside, so the entry goes to Suggestions or Suspense and is exported.
Bank ledgers step: changing a PDF's bank ledger warns "Changing the bank ledger unpairs this statement’s contra entries", then dissolves its pairs and matches again.
- 6 contra deposits are left out. The withdrawal from the other bank books each transfer.
1 is no longer found in Miracle: check it.Show ▾
| Date | Entry | Amount | In Miracle | Action |
|---|---|---|---|---|
| 05/04/2026 | HDFC Current row 22 NEFT DR AXIS… | 25,000.00 | Axis Current Contra voucher · 05/04/2026 | ⤴ Export it |
Also: how a contra entry looks in the other steps
Paired entry (Way A, B, D)
Read-only. No Ledger box. Cannot be selected. Below the ledger:
Contra with ICICI OD row 1 · Ref HDFCN52026… · change it in Contra entries
Already in Miracle (Way C)
Has a ledger box (editable). Below it:
Already in Miracle · left out of the export
Misbooked, accepted (Way C)
Has a ledger box (editable). Below it:
Contra entry from Miracle books
What happens if one side is already in Miracle?
1 · Read the books
The page readsRKACCT01.DBF of every financial year in the entries' period ± 3 days, for all the party's bank ledgers. Desktop: Go backend/miracle_books.go. Browser: lib/miracle-books.ts. Needs the company folder on this PC and at least two bank ledgers. Without a folder the step says: "Connect the company folder on this PC to check its books…"2 · Which entries are checked?
Entries with no ledger, no pair, no possible contra from another statement (Way B wins), and not set aside. Entries already accepted from the books are rechecked to keep their posting.3 · Does a posting match?
Posting is on another bank ledger · opposite side (a debit here = that bank's deposit) · same amount, or the withdrawal higher by a fee (≤ ₹100 and ≤ 1%) · at most 3 days apart. Each posting goes to one entry only: exact amount first, then nearest date. The match counts how many other postings or entries also fit.Already in Miracle
Only at the exact amount. Any amount (no ₹500 floor).
Nothing else matches → saved by itself as the other bank's ledger, source books, in_books = true. Not shown in To confirm.
Others match → waits in To confirm with "Already in Miracle" and "check it first".
Export: left out. Listed under "already in Miracle" with Show / Export it.
Probably misbooked
Needs ≥ ₹500 and a narration that is not cash, ATM or card (csh, cash, atm, nwd-, atw-, pos). Fee difference allowed.
Always waits in To confirm: "Booked against Suspense A/c".
Accept → saved with the other bank's ledger and exported. The user must correct the Miracle voucher, or the transfer is booked twice.
When Miracle is later corrected, the entry becomes "In Miracle" by itself.
Ignored
The posting is a real transfer with some other bank or cash. It never matches.
The entry goes on to Suggestions or Suspense as normal.
Safety rules that protect the export
loadContraBook removes them). That would export the other row and book the transfer twice.in_books flag. Company files and postings stay on the PC.What do we show as contra suggestions?
| A · Same reference auto | B · Possible contra To confirm | C · Miracle books in books misbooked | D · Alt+C partners by hand | |
|---|---|---|---|---|
| Runs where | Server, after every bank link and entry write | Server, on statement load and recommendations | Browser / desktop app, on this PC | Browser / desktop app |
| Reference | Must share a UTR or 12-digit RRN; one side's refs all on the other | No shared ref needed. Blocked if both print refs and none is shared | Not used (books keep no UTR) | Not used |
| Amount | Equal, or debit higher by fee (≤ ₹100, ≤ 1%) | Exactly equal, ≥ ₹500 | In books: exact, any amount. Misbooked: fee allowed, ≥ ₹500 | Equal, or debit higher by fee |
| Dates | ≤ 3 days apart | ≤ 1 day apart | ≤ 3 days apart | Any; nearest first |
| Must be unique | Yes, each other's only candidate | Yes, each other's only candidate | One posting per entry; rivals counted and shown | No, lists all |
| Cash / ATM / card excluded | Not needed (no shared UTR) | No | Misbooked only | No |
| Saved by itself | Yes | No | In books with no rival: yes. Else no | No |
| Rejected how | Unpair → never again (server) | Not contra → never again (server) | Not contra → this tab only | Esc |
| Other rules | Same-statement debit + credit with same ref and amount = reversal, never paired. Copies from overlapping statements join the pair. | A row with a ledger counts only if it is the other bank; at least one side must be open. | Postings against a bank or cash are ignored. | Both sides need no ledger, or the other's bank; at most one has one. |
Order of priority
An entry with a Way B suggestion is skipped by Way C. An entry with any non-bank ledger is skipped by A, B and C. Alt+C (D) is always available as a manual fallback.
What the user reads on each suggestion
"Same amount on both statements" (Way B)
"Accepting leaves it out of the export." + rivals note (Way C, in books, with a rival)
"Accepting exports it as a transfer; then correct that voucher in Miracle." (Way C, misbooked)
What do we show at each stage?
Step 3 · Contra entries, in detail
- Tab count: "N left" = entries of open Way B pairs (both sides) + Way C entries to confirm.
- Opens first when it has work left.
- Empty state: "No transfers between the party’s banks" + Continue to suggestions.
- To confirm: sorted by date. Enter accepts, Delete rejects.
- Contra entries: Delete unpairs or undoes.
- Footer: "Checking the company’s Miracle books…", "Checked the company’s Miracle books…" or the read error, with Read books again.
Steps 4–6 · Suggestions, Suspense, Review
- Entries with an undecided contra entry stay out: "2 possible contra entries are still undecided and stay in Contra entries."
- Paired entries: no Ledger box, no checkbox, note "Contra with … · change it in Contra entries".
- A Review ledger with only paired entries is locked.
- All entries: Status column shows Contra or In Miracle.
Step 7 · Export rules for contra
Pair, both in import
Exported once from the bank the money left. The deposit is left out: "N contra deposits are left out."
Pair, withdrawal outside import
The deposit is kept: "…kept, since its withdrawal is in a statement outside this import. Leave it out in Miracle if that withdrawal was already exported."
In Miracle
Left out. Counted in the tile and listed under Show. Recorded as exported on the server.
Entry states
Findings
Checked against the code on main. The contra unit tests pass (frontend: 4 files, 14 tests; Go: pure-logic tests). The Go PostgreSQL tests were skipped, because TEST_DATABASE_URL was not set.
F1 · A transfer with a fee that is already in Miracle is exported again in full
When the books hold the transfer against this bank but the amount differs by a fee, the match is thrown away. The entry gets no hint and goes to Suggestions or Suspense. The export then writes the whole row, so Miracle gets the transfer amount a second time.
Fix idea: keep the match. Show it in To confirm as "Already in Miracle, except a ₹10 fee", and export only the fee (or ask).
if (inBooks && other !== amount) continue;F2 · Cash withdrawals and deposits can be suggested as contra
The docs say "Cash deposits and withdrawals are not treated as contra". But the server's amount-only suggestion (Way B) and Alt+C have no cash filter. Only the books path (Way C) has one.
Fix idea: apply the same notTransfer narration test to suggestable on the server.
F3 · "Pair as contra" shows on many entries that are not transfers
The chip shows on any open entry that has an opposite entry of the same amount on another bank, at any date. Round amounts (₹10,000, ₹25,000) repeat often. So the chip can show on many rows, and it loses meaning.
Fix idea: show the chip only when a partner is within a few days. Keep Alt+C for any date.
F4 · Choosing another bank in the Ledger box makes a one-sided transfer
The user can pick "ICICI OD" for an HDFC entry. The export treats it as a normal row. If ICICI's statement is in the import and its side is not paired, the ICICI entry is exported too, and the transfer is booked twice. No warning is shown.
Fix idea: when a bank ledger is chosen and a partner exists, offer "Pair as contra" at once; or warn in Export.
F5 · The step count and the "To confirm" count differ
The tab counts entries (2 per pair). The table header counts transfers (1 per pair). Two open pairs show "4 left" on the tab and "To confirm 2" on the page.
F6 · All entries does not show contra suggestions or misbooked transfers as contra
An entry with a possible contra waiting shows "No ledger". An accepted misbooked transfer from the books shows "Chosen", not "Contra".
F7 · Way B misses some real transfers
- Account numbers count as references. If both sides print a different 12-digit number, the pair is blocked.
- Way B needs an exact amount. A transfer with a fee and no UTR is never suggested.
- An entry that already got a non-bank ledger by an exact match is never suggested.
Alt+C covers all three, but only if the user notices.
F8 · "Not contra" on a books match is kept only in this tab
It is saved by entry key with the tab state, not on the server. Another PC or a new window shows the same match again. This is by design, but it is not the same as Way B, which remembers for good.
What works well
The crux
- Where: the Contra entries step (Accept / Not contra / Unpair), Alt+C or the "Pair as contra" chip in every other step, and Export → Show → Export it.
- Already in Miracle: read on this PC; same amount against this bank → saved by itself and left out of the export; against another ledger → user confirms and must correct Miracle.
- Suggestions: same UTR/RRN = automatic; same amount ≤ 1 day = confirm; Miracle books = confirm unless it is clearly already there.
- Stages: all decisions happen in step 3; later steps show contra read-only; export writes each transfer once.
- Fix first: F1 (fee transfer already in Miracle gets double-booked), then F2 (cash suggested as contra).