Skip to content

feat(loans): Due EMI column + unclip account dropdown - #38

Merged
parameshjava merged 2 commits into
mainfrom
feat/loans-due-emi-column
Aug 6, 2026
Merged

feat(loans): Due EMI column + unclip account dropdown#38
parameshjava merged 2 commits into
mainfrom
feat/loans-due-emi-column

Conversation

@parameshjava

Copy link
Copy Markdown
Owner

Due EMI column

Adds a Due EMI column beside Pending EMI on /admin/loans and /dashboard/loans.

Pending EMI is a count; Due EMI is the money. It sums, over exactly the installments Pending EMI counts (unpaid rows due on or before this month's end):

(principal_due − principal_paid) + (interest_due − interest_paid)

That is precisely what payEmi charges. Late fees are excluded — they're a separate penalty receivable, collected (or waived) alongside the EMI rather than being part of it.

  • src/lib/emi-due.ts (new) — installmentOutstanding() + tallyPendingEmi() returning { count, due } per loan. Both pages now derive the count and the amount from the same query result, so the two columns can't disagree about which installments are payable. Each leg is clamped at ≥0 so an over-applied principal payment can't cancel out interest still owed.
  • Column is sortable, right-aligned, rendered via formatRupees, amber when more than one installment is stacked up (matching Pending EMI), for accrual-model loans, with a footer total. Also added to CSV/PDF export with its own total.

TopBar dropdown fix

The sticky TopBar wrapper had overflow-hidden, which clipped the account dropdown — it renders below the bar's box. Removed; the banner image keeps its own clipping wrapper, so the cover-crop behaviour is unchanged. Dropdown also gets z-30 to clear page content under the z-20 bar.

Verification

  • npm test — 256 passed (7 new in src/lib/emi-due.test.ts: partials, Postgres numeric-as-string, over-application, grouping)
  • npm run lint — clean (one pre-existing warning in pending-interest-panel.tsx)
  • npm run build — passes

🤖 Generated with Claude Code

Due EMI shows the rupees owed on exactly the installments Pending EMI
counts (unpaid, due on or before this month's end): unpaid principal +
unpaid interest, which is what payEmi charges. Late fees are excluded —
they're a separate penalty receivable, collected or waived alongside.

Both counts now come from one tally helper (src/lib/emi-due.ts) so the
two columns can't disagree about which installments are payable. Column
is sortable, totalled in the footer, and included in export.

Also drops overflow-hidden from the sticky TopBar wrapper, which was
clipping the account dropdown; the banner image keeps its own clipping
wrapper.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aits-fcf-tracker Ready Ready Preview Aug 6, 2026 3:36pm

Plain-text version of the paid/total progress ring: "48 / 60" with
"20% pending" underneath. Spans the whole schedule, unlike Pending EMI
(payable this month). Sorts on % pending; loans with no schedule sort
last via a -1 sentinel. Waived installments count as settled — they owe
nothing, so leaving them out would report them as forever pending.

Both loan pages now fetch the full schedule once and tallyEmiSchedule()
derives all three EMI columns in one pass, replacing the pending-only
query. UNPAID_EMI_STATUSES is now consumed there rather than duplicated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@parameshjava
parameshjava merged commit 2e6eb83 into main Aug 6, 2026
3 of 4 checks passed
@parameshjava
parameshjava deleted the feat/loans-due-emi-column branch August 6, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant