Skip to content

feat: close nine daily branch-operations gaps, and unblock the spec sync #416 breaks - #418

Merged
Aman-Mittal merged 11 commits into
apache:mainfrom
Aman-Mittal:feat/servicing-and-navigation-gaps
Aug 22, 2026
Merged

feat: close nine daily branch-operations gaps, and unblock the spec sync #416 breaks#418
Aman-Mittal merged 11 commits into
apache:mainfrom
Aman-Mittal:feat/servicing-and-navigation-gaps

Conversation

@Aman-Mittal

@Aman-Mittal Aman-Mittal commented Aug 22, 2026

Copy link
Copy Markdown
Member

Closes #419.
Supersedes #416.

Eleven commits, each taking a screen that already existed and making it do the one thing the role using it actually needs. Reviewable commit by commit.

Supersedes #416

#416 syncs the same image (apache/fineract@sha256:6c331bbe…) and its build fails: upstream added issuanceDate/expiryDate between existing parameters on the document upload endpoint, shifting every overload of postEntityTypeEntityIdDocuments by two positions, so the sole caller no longer type-checks.

client-document-form.component.ts:207 TS2769: No overload matches this call
client-document-form.component.ts:220 TS2769: No overload matches this call

The first commit here carries the identical sync and fixes both call sites, passing the new parameters as undefined — behaviour unchanged. verify-api-client against apache/fineract:latest confirms the digest is still 6c331bbe… and the regenerated client is byte-identical, so this is current with upstream main.

What changed

Commit
chore(api) Spec sync, plus the two call sites #416 breaks.
feat(layout) Breadcrumb trail and Alt+letter navigation.
feat(clients) Create-client becomes a three-step wizard.
feat(organization) Loan portfolio summary by office and product.
feat(accounting) Journal entries filter by office, GL account and entry type.
feat(products) Savings undo-approval; deposit charges and interest rate chart.
feat(working-capital) Charges, rate changes, amortization schedule, delinquency range tags.
feat(system) Bulk import widened; chart-of-accounts template bug fixed; scheduler bulk run.
feat(tasks) Work queues grouped by office; reschedule requests can be rejected.
feat(security) Audit log CSV export.
test Vitest timeout raised above Angular's cold TestBed compile.

Notes for review

  • Breadcrumbs reuse route title rather than parallel route data, so they cannot drift from the tab title — but they inherit 285 routes in 21 feature files still inherit their tab title from the section above them #355, and those crumbs read wrong until it lands.
  • The wizard is creation-only. Editing keeps the flat form: correcting one field is better served by seeing all of them.
  • The outstanding-amount filters are opt-in. The search endpoint treats them as present-or-absent, not nullable, so the keys are omitted entirely unless toggled on.
  • undoapproval omits dateFormat/locale — like the loan equivalent, it answers 400 for parameters it does not expect.
  • Deposit charges and the rate chart use HttpClient directly: both need ?associations=all, which no generated method can send. ChartSlab is local because the generated model omits fields the real response carries.
  • The reschedule queue stays flat while the others group by office — its list response carries no office at all.
  • The audit export covers the loaded page, not a silent re-query; the endpoint is paginated and unbounded.
  • The Vitest timeout is a CI fix, not a preference. The first createComponent() in a file compiles the component and its imports, exceeding the 5s default on a cold cache — so specs pass locally on a warm re-run and fail in CI, which is always cold. Reproduce with rm -rf node_modules/.vite && npm run test:unit.
  • api-surface.json is recorded incrementally, so api:surface passes at every commit, not just the tip. It also drops a stale deleteMakercheckersAuditId entry, whose last call site went with the maker-checker rejection fix.

Not in this branch

GLIM and GSIM screens are held back on feat/glim-gsim-accounts: per #376 the platform refuses both on PostgreSQL, and the specs are mocked-only with no backend companion, so they are unverified against a real Fineract.

Scoped out and left on their own issues: #197 (savings parity — undo-approval is taken here because it loses data when missing), #295 (term-deposit lifecycle), #355 (route titles).

Checks

All 14 CI checks pass locally, plus verify-api-client and build. 432 Vitest and 898 Karma tests pass, Vitest verified from a cold cache. All commits GPG-signed. The e2e suites need the Fineract stack and were left to CI.

The nightly spec sync picked up a newer apache/fineract image, which adds
`issuanceDate` and `expiryDate` to the document upload endpoint.

Both land between existing parameters rather than after them, so every
generated overload of `postEntityTypeEntityIdDocuments` shifts by two
positions. The KYC document form is the only caller; it passes the new
parameters as `undefined` so behaviour is unchanged, and the arguments are
commented with the field each one carries so the next shift is easier to spot.
@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

E2E — mocked backend

🎭 E2E Tests

✅ All green — 311 passed · 0 failed · 0 skipped, across 25 spec files in 6m 27s.

By spec file

Spec ⏭️ Time
accessibility.spec.ts 3 0 0 11.3s
all-functions-read-shortcut.spec.ts 5 0 0 8.5s
breadcrumb.spec.ts 2 0 0 4.7s
client-servicing-gaps.spec.ts 14 0 0 45.3s
client.spec.ts 1 0 0 3.9s
e2e-journey.spec.ts 81 0 0 2m 37s
feature-coverage.spec.ts 44 0 0 1m 29s
functional-coverage.spec.ts 42 0 0 1m 53s
global-search-nav-shortcuts.spec.ts 4 0 0 9.6s
global-search-navigation.spec.ts 8 0 0 19.4s
group-detail.spec.ts 6 0 0 25.3s
guidance-tour-dashboard.spec.ts 1 0 0 2.6s
keyboard-shortcuts.spec.ts 5 0 0 9.8s
list-pagination.spec.ts 8 0 0 30.0s
loan-portfolio-summary.spec.ts 4 0 0 14.3s
loan-product-down-payment.spec.ts 13 0 0 1m 8s
loan-schedule-type-gating.spec.ts 5 0 0 17.5s
loan-servicing-gaps.spec.ts 13 0 0 50.8s
rbac-feature-flag.spec.ts 10 0 0 17.9s
rbac-route-protection.spec.ts 18 0 0 1m 41s
report-enhancements.spec.ts 2 0 0 7.1s
reporting.spec.ts 2 0 0 3.9s
scheduler-jobs.spec.ts 3 0 0 11.7s
two-factor-authentication.spec.ts 10 0 0 19.0s
working-capital-loan-actions.spec.ts 7 0 0 33.7s
All 311 tests — click to expand

accessibility.spec.ts

  • ✅ Runtime accessibility › client list has no blocking violations — 3.9s
  • ✅ Runtime accessibility › client form has no blocking violations — 3.7s
  • ✅ Runtime accessibility › create office dialog has no blocking violations — 3.7s

all-functions-read-shortcut.spec.ts

  • ✅ ALL_FUNCTIONS_READ shortcut › grants read access to the Clients list without any explicit READ_CLIENT permission — 1.6s
  • ✅ ALL_FUNCTIONS_READ shortcut › does not grant the Create Client action — 2.0s
  • ✅ ALL_FUNCTIONS_READ shortcut › does not grant Create Client even combined with an explicit READ_CLIENT permission — 1.7s
  • ✅ ALL_FUNCTIONS_READ shortcut › a user with the real CREATE_CLIENT permission still sees the button — 1.6s
  • ✅ ALL_FUNCTIONS_READ shortcut › ALL_FUNCTIONS (full superuser) still sees the Create Client button — 1.7s

breadcrumb.spec.ts

  • ✅ a single-crumb page shows no breadcrumb trail — 1.6s
  • ✅ a nested page shows a trail, and the ancestor crumb navigates back — 3.1s

client-servicing-gaps.spec.ts

  • ✅ Client transfers › proposing a transfer sends the destination, the date and the format that parses it — 3.3s
  • ✅ Client transfers › a one-step transfer omits the date the platform refuses — 3.3s
  • ✅ Client transfers › the client’s own office is not offered as a destination — 3.9s
  • ✅ Client transfers › accepting a transfer sends a note and nothing else — 3.2s
  • ✅ Client transfers › accepting with no note sends an empty body — 3.1s
  • ✅ Client transfers › rejecting a transfer is offered while one is pending — 4.1s
  • ✅ Client transfers › withdrawing is offered from on hold, which is the only way back — 3.0s
  • ✅ Client transfers › answers to a transfer are not offered when none is pending — 2.6s
  • ✅ Client staff and default savings account › assigning a member of staff sends the staff id — 3.4s
  • ✅ Client staff and default savings account › unassigning echoes the current holder back, which the platform requires — 3.1s
  • ✅ Client staff and default savings account › unassigning is not offered when nobody is assigned — 2.6s
  • ✅ Client staff and default savings account › the assigned officer is shown on the header — 3.0s
  • ✅ Client staff and default savings account › setting the default savings account sends the account id — 3.2s
  • ✅ Undoing a rejection › posts the command name the platform recognises, not the menu identifier — 3.5s

client.spec.ts

  • ✅ Client Management › should create a new client — 3.9s

e2e-journey.spec.ts

  • ✅ E2E: Login Flow › should display login page with all required fields — 1.0s
  • ✅ E2E: Login Flow › should have Sign In button disabled when fields are empty — 1.2s
  • ✅ E2E: Login Flow › should enable Sign In when credentials are entered — 1.2s
  • ✅ E2E: Login Flow › should redirect to dashboard after successful login — 1.5s
  • ✅ E2E: Login Flow › should display language selector on login page — 1.5s
  • ✅ E2E: Login Flow › should display API endpoint selector with value — 1.2s
  • ✅ E2E: Dashboard › should display dashboard summary cards — 1.6s
  • ✅ E2E: Dashboard › should display system health as Online — 1.5s
  • ✅ E2E: Dashboard › should display pending approvals section — 1.5s
  • ✅ E2E: Dashboard › should display loan and savings status distribution charts — 1.5s
  • ✅ E2E: Dashboard › should display system operational status — 1.5s
  • ✅ E2E: Dashboard › should have header with business date, render time, and logout — 1.9s
  • ✅ E2E: Dashboard › should have sidebar toggle button — 1.5s
  • ✅ E2E: Dashboard › should have global search bar in header — 1.4s
  • ✅ E2E: Dashboard › should have Guide button in header — 1.5s
  • ✅ E2E: Dashboard › should have dark mode toggle button — 1.4s
  • ✅ E2E: Sidebar Navigation › should have all main navigation links — 1.8s
  • ✅ E2E: Sidebar Navigation › should have Products section with sub-links — 1.5s
  • ✅ E2E: Sidebar Navigation › should have Transfers section with sub-links — 1.5s
  • ✅ E2E: Sidebar Navigation › should have Accounting section with sub-links — 1.6s
  • ✅ E2E: Sidebar Navigation › should have Security section — 1.5s
  • ✅ E2E: Sidebar Navigation › should have Settings section — 1.9s
  • ✅ E2E: Sidebar Navigation › should have Organization section — 1.5s
  • ✅ E2E: Sidebar Navigation › should have System section — 1.5s
  • ✅ E2E: Sidebar Navigation › should navigate to all major pages via sidebar — 3.1s
  • ✅ E2E: Offices › should display offices list with table — 1.7s
  • ✅ E2E: Offices › should have Create Office button — 2.1s
  • ✅ E2E: Offices › should navigate to office create form — 1.8s
  • ✅ E2E: Offices › should validate office create form - save disabled when empty — 1.9s
  • ✅ E2E: Offices › should fill office create form and enable save — 2.4s
  • ✅ E2E: Offices › should cancel office creation and return to list — 1.9s
  • ✅ E2E: Offices › should have search input on offices page — 2.0s
  • ✅ E2E: Offices › should show edit button for each office — 1.7s
  • ✅ E2E: Offices › should have pagination controls — 1.7s
  • ✅ E2E: Clients › should display clients list page — 1.7s
  • ✅ E2E: Clients › should display client data in table — 1.8s
  • ✅ E2E: Clients › should show ACTIVE status badge — 1.7s
  • ✅ E2E: Clients › should have Create Client button — 2.3s
  • ✅ E2E: Clients › should show empty state when no clients exist — 1.7s
  • ✅ E2E: Clients › should have search input and status filter — 1.7s
  • ✅ E2E: Clients › should have pagination controls — 1.7s
  • ✅ E2E: Client Creation › should navigate to client create form — 1.9s
  • ✅ E2E: Client Creation › should display all required client form fields, across the wizard steps — 3.0s
  • ✅ E2E: Client Creation › should display optional client form fields, across the wizard steps — 2.6s
  • ✅ E2E: Client Creation › should have Next disabled until the current step is valid — 2.4s
  • ✅ E2E: Client Creation › should populate office dropdown from API — 2.1s
  • ✅ E2E: Client Creation › should fill client form and enable save on the last step — 3.1s
  • ✅ E2E: Client Creation › should submit client and redirect to clients list — 3.5s
  • ✅ E2E: Client Creation › should cancel client creation and return to clients list — 2.0s
  • ✅ E2E: Client Creation › should have add office quick-action button — 2.0s
  • ✅ E2E: Client Creation › should have help icons for form fields — 1.7s
  • ✅ E2E: Client Creation › should have calendar buttons for date fields — 2.4s
  • ✅ E2E: Client Creation › should have pre-filled dates in Submitted On and Activation Date — 3.0s
  • ✅ E2E: Client Creation › should have Active checkbox checked by default — 2.4s
  • ✅ E2E: Client Creation › should handle Entity legal form showing fullname field — 4.7s
  • ✅ E2E: Loan Products Page › should display loan products list page — 2.3s
  • ✅ E2E: Loan Products Page › should have Create Loan Product button — 2.0s
  • ✅ E2E: Loan Products Page › should display table with correct headers — 1.9s
  • ✅ E2E: Loan Products Page › should show empty state when no products exist — 1.9s
  • ✅ E2E: Loan Products Page › should have search input — 2.6s
  • ✅ E2E: Loan Products Page › should navigate to loan product create form — 2.2s
  • ✅ E2E: Savings Products Page › should display savings products list page — 2.0s
  • ✅ E2E: Other Products Pages › Fixed Deposit Products page loads — 1.9s
  • ✅ E2E: Other Products Pages › Recurring Deposit Products page loads — 2.0s
  • ✅ E2E: Other Products Pages › Share Products page loads — 2.6s
  • ✅ E2E: Other Products Pages › Tax Components page loads — 1.9s
  • ✅ E2E: Other Products Pages › Tax Groups page loads — 2.0s
  • ✅ E2E: Other Products Pages › Floating Rates page loads — 1.9s
  • ✅ E2E: Loans Portfolio › should display loans portfolio page — 1.9s
  • ✅ E2E: Loans Portfolio › should have Create Loan Account button — 2.5s
  • ✅ E2E: Loans Portfolio › should display table with correct headers — 1.9s
  • ✅ E2E: Loans Portfolio › should show empty state when no loans exist — 2.1s
  • ✅ E2E: Loans Portfolio › should have search input — 1.9s
  • ✅ E2E: Loans Portfolio › should have pagination controls — 2.0s
  • ✅ E2E: Header & Global Elements › should display Fineract logo and title in header — 2.3s
  • ✅ E2E: Header & Global Elements › should display logged-in username — 1.6s
  • ✅ E2E: Header & Global Elements › should display office name for user — 1.8s
  • ✅ E2E: Header & Global Elements › should have Logout button — 1.6s
  • ✅ E2E: Header & Global Elements › should have language selector in header — 1.6s
  • ✅ E2E: Header & Global Elements › should display render time — 2.2s
  • ✅ E2E: Header & Global Elements › should display business date — 1.7s

feature-coverage.spec.ts

  • ✅ Navigation & Sidebar › all main navigation links are visible in sidebar — 2.1s
  • ✅ Navigation & Sidebar › sidebar navigation routes to correct pages — 3.0s
  • ✅ Navigation & Sidebar › header shows logged-in user info — 1.6s
  • ✅ Navigation & Sidebar › help tour button is visible and interactive — 2.2s
  • ✅ Navigation & Sidebar › logout button is visible — 1.7s
  • ✅ Navigation & Sidebar › language selector is present — 1.6s
  • ✅ Dashboard › dashboard shows key metrics cards — 1.6s
  • ✅ Dashboard › dashboard shows pending approvals section — 1.7s
  • ✅ Dashboard › dashboard shows loan and savings status distribution — 2.2s
  • ✅ Dashboard › dashboard shows system operational status — 1.6s
  • ✅ Groups › groups page renders with title — 1.8s
  • ✅ Groups › groups page has create button — 1.9s
  • ✅ Centers › centers page renders with title — 2.0s
  • ✅ Centers › centers page has create button — 2.5s
  • ✅ Organization › offices page loads with list — 2.0s
  • ✅ Organization › staff page loads — 2.0s
  • ✅ Organization › funds page loads — 1.8s
  • ✅ Organization › payment types page loads — 1.9s
  • ✅ Accounting › chart of accounts loads — 2.0s
  • ✅ Accounting › journal entries page loads — 2.0s
  • ✅ Accounting › accounting closures loads — 3.0s
  • ✅ Accounting › accounting rules loads — 1.9s
  • ✅ Accounting › financial activity mappings loads — 2.0s
  • ✅ Accounting › charges page loads — 1.9s
  • ✅ Security › users page loads — 1.8s
  • ✅ Security › roles page loads — 2.8s
  • ✅ Security › audit logs page loads — 2.0s
  • ✅ Products - Loan & Savings › loan products page loads — 2.0s
  • ✅ Products - Loan & Savings › savings products page loads — 1.9s
  • ✅ Products - Loan & Savings › tax components page loads — 1.9s
  • ✅ Products - Loan & Savings › tax groups page loads — 2.0s
  • ✅ Products - Loan & Savings › floating rates page loads — 2.4s
  • ✅ Products - Loan & Savings › savings accounts page loads — 1.9s
  • ✅ Settings › global configurations page loads — 1.9s
  • ✅ Settings › holidays page loads — 2.0s
  • ✅ Settings › working days page loads — 1.8s
  • ✅ System › data tables page loads — 2.5s
  • ✅ System › bulk import page loads — 1.9s
  • ✅ System › delinquency page loads — 2.0s
  • ✅ Tellers › tellers page loads with create button — 1.9s
  • ✅ Transfers › account transfer page loads — 1.9s
  • ✅ Transfers › standing instructions page loads — 2.4s
  • ✅ Transfers › SI history page loads — 1.9s
  • ✅ Embedded Fintech › asset owners page loads — 1.8s

functional-coverage.spec.ts

  • ✅ Client CRUD Workflow › should complete full client creation flow — Person — 3.7s
  • ✅ Client CRUD Workflow › should complete full client creation flow — Entity — 3.4s
  • ✅ Client CRUD Workflow › should cancel client creation and return to list — 2.2s
  • ✅ Client CRUD Workflow › should disable office and legal form in edit mode — 4.1s
  • ✅ Client View & Status Transitions › should display client view with correct details — 3.1s
  • ✅ Client View & Status Transitions › should show actions menu for pending client (status 100) — 3.6s
  • ✅ Client View & Status Transitions › should show actions menu for active client (status 300) — 3.9s
  • ✅ Client View & Status Transitions › should show actions menu for closed client (status 600) — 3.5s
  • ✅ Client View & Status Transitions › should show New Account menu for active client — 3.8s
  • ✅ Client View & Status Transitions › should navigate from client view to client list via breadcrumb — 4.1s
  • ✅ Client View & Status Transitions › should navigate back from client view — 3.6s
  • ✅ Client View Tabs › should display all expected tabs on client view — 3.4s
  • ✅ Client View Tabs › should switch between client view tabs — 3.7s
  • ✅ Search & Filter Interactions › should have search input on clients page and accept input — 1.9s
  • ✅ Search & Filter Interactions › should have office filter on groups page — 2.0s
  • ✅ Search & Filter Interactions › should have office filter on loans page — 1.9s
  • ✅ Search & Filter Interactions › should have search input on charges page — 1.9s
  • ✅ Navigation Flow Verification › should navigate full client lifecycle: list → create → back → list — 3.2s
  • ✅ Navigation Flow Verification › should navigate from dashboard to all top-level pages via sidebar — 4.1s
  • ✅ Navigation Flow Verification › should go from loan products → create → back — 2.3s
  • ✅ Office CRUD › should validate office create form — save disabled when empty — 2.2s
  • ✅ Office CRUD › should validate office create form — save enabled when filled — 2.4s
  • ✅ Office CRUD › should cancel office creation — 2.8s
  • ✅ Organization Create Flows › staff create form loads — 2.3s
  • ✅ Organization Create Flows › funds create form loads — 1.9s
  • ✅ Organization Create Flows › payment types create form loads — 2.1s
  • ✅ Accounting CRUD › accounting closure create form loads — 2.2s
  • ✅ Accounting CRUD › accounting rule create form loads — 2.0s
  • ✅ Accounting CRUD › financial activity mapping create form loads — 1.9s
  • ✅ Accounting CRUD › charge create form loads — 3.0s
  • ✅ Accounting CRUD › chart of accounts create form loads — 1.9s
  • ✅ Settings CRUD › global configurations page has editable toggle — 2.0s
  • ✅ Settings CRUD › holiday create form loads — 2.1s
  • ✅ Settings CRUD › working days page has save button — 1.9s
  • ✅ System CRUD › data table create form loads — 2.7s
  • ✅ System CRUD › delinquency page has create buttons for ranges and buckets — 1.8s
  • ✅ Security CRUD › role create form loads — 2.1s
  • ✅ Security CRUD › audit logs search form has date range — 2.2s
  • ✅ Security CRUD › audit logs list exports the loaded page as CSV — 2.1s
  • ✅ Reporting — Run Report Flow › should navigate to report and verify report parameters — 3.3s
  • ✅ Teller CRUD › teller create form loads — 2.2s
  • ✅ Create Office Dialog from Client Form › should open create office dialog from client create form — 2.4s

global-search-nav-shortcuts.spec.ts

  • ✅ Global search navigation shortcuts › offers a settings page the entity search cannot return — 1.9s
  • ✅ Global search navigation shortcuts › navigates to the page behind a shortcut — 2.2s
  • ✅ Global search navigation shortcuts › keeps the results open across the mousedown that starts a click, so a slow render cannot race the dropdown closed — 2.7s
  • ✅ Global search navigation shortcuts › withholds a shortcut the user has no permission to reach — 2.7s

global-search-navigation.spec.ts

  • ✅ Global search navigation › does not query the backend for a single character — 2.5s
  • ✅ Global search navigation › sends one request for a phrase typed straight through — 2.9s
  • ✅ Global search navigation › opens the client behind a client result — 2.3s
  • ✅ Global search navigation › opens the loan behind a loan result — 2.9s
  • ✅ Global search navigation › opens the savings account behind a savings result — 2.2s
  • ✅ Global search navigation › clears the query and closes the dropdown after a selection — 2.0s
  • ✅ Global search navigation › closes the dropdown when focus leaves without a selection — 2.1s
  • ✅ Global search navigation › shows nothing rather than an empty dropdown when there are no matches — 2.5s

group-detail.spec.ts

  • ✅ Group detail › asks for the associations, and shows every member rather than only the active ones — 4.4s
  • ✅ Group detail › closes a group with the reason id and a Fineract-formatted date — 5.2s
  • ✅ Group detail › does not offer a client who is already a member, and associates the one it does — 4.0s
  • ✅ Group detail › unassigns a committee role by the assignment id, not the role id — 4.3s
  • ✅ Group detail › offers a retry when the group cannot be loaded — 3.3s
  • ✅ Group detail › says so when no closure reason has been defined — 4.0s

guidance-tour-dashboard.spec.ts

  • ✅ highlights the System Status card, not the sidebar, on the dashboard tour — 2.6s

keyboard-shortcuts.spec.ts

  • ✅ Alt+C jumps straight to Create Client from anywhere — 2.0s
  • ✅ Alt+G jumps to Create Group — 1.8s
  • ✅ Alt+E jumps to Create Center — 1.8s
  • ✅ Alt+H opens the guidance tour for the current page — 1.6s
  • ✅ typing in the global search box does not trigger the Create Client shortcut — 2.6s

list-pagination.spec.ts

  • ✅ List pagination › advances through pages and back again — 3.6s
  • ✅ List pagination › jumps to the last page — 3.4s
  • ✅ List pagination › returns to the first page when a filter changes — 4.2s
  • ✅ List pagination › returns to the first page when searching — 4.2s
  • ✅ Profile › renders the signed-in user rather than hanging on a spinner — 3.4s
  • ✅ Profile › shows an error when the profile cannot be loaded — 3.5s
  • ✅ List load failure › reports the failure and reloads when the user retries — 4.4s
  • ✅ List load failure › calendars: reports the failure and reloads when the user retries — 3.4s

loan-portfolio-summary.spec.ts

  • ✅ Loan Portfolio Summary › searching sends entities: loans and shows the grouped results — 3.1s
  • ✅ Loan Portfolio Summary › Edit Parameters returns from the results view to the filter form — 4.0s
  • ✅ Loan Portfolio Summary › checking the outstanding-amount filter sends the between min/max values — 3.3s
  • ✅ Loan Portfolio Summary › switching to a single-value comparison condition sends one value — 3.9s

loan-product-down-payment.spec.ts

  • ✅ Loan product down payment and tranches › down payment is offered only for a progressive product — 4.7s
  • ✅ Loan product down payment and tranches › the percentage and auto-repayment appear only once down payment is on — 4.1s
  • ✅ Loan product down payment and tranches › multi-tranche disbursement reveals its tranche count, on either engine — 3.2s
  • ✅ Loan product down payment and tranches › submits the down payment and tranche settings it was given — 5.1s
  • ✅ Loan product down payment and tranches › does not send a down payment on a cumulative product — 5.3s
  • ✅ Loan product down payment and tranches › income recognition is offered only for a progressive product — 4.0s
  • ✅ Loan product down payment and tranches › the capitalisation details appear only once it is on — 5.0s
  • ✅ Loan product down payment and tranches › submits the income recognition settings it was given — 5.1s
  • ✅ Loan product down payment and tranches › does not send income recognition on a cumulative product — 5.3s
  • ✅ Loan product down payment and tranches › interest recalculation reveals its mandatory settings only once it is on — 3.7s
  • ✅ Loan product down payment and tranches › the rest interval appears only when the frequency is not the repayment period — 14.5s
  • ✅ Loan product down payment and tranches › submits the interest recalculation settings it was given — 3.4s
  • ✅ Loan product down payment and tranches › does not send recalculation settings once it is switched back off — 4.3s

loan-schedule-type-gating.spec.ts

  • ✅ Loan schedule type gating › a cumulative loan offers neither progressive-only tab, and fetches neither — 3.4s
  • ✅ Loan schedule type gating › a progressive loan shows only the capabilities it actually has — 3.4s
  • ✅ Loan schedule type gating › a progressive loan with both capabilities shows both — 3.8s
  • ✅ Loan schedule type gating › a charged-off loan says so and offers the reversal instead — 3.4s
  • ✅ Loan schedule type gating › a healthy loan offers charge-off and no marker — 3.5s

loan-servicing-gaps.spec.ts

  • ✅ Loan servicing gaps › undo approval sends an empty body, without the locale the platform refuses — 4.4s
  • ✅ Loan servicing gaps › undo approval carries the reason when one was given — 4.2s
  • ✅ Loan servicing gaps › undo approval is offered only while the loan is approved — 3.4s
  • ✅ Loan servicing gaps › the delinquency tab shows the summary the loan carries and the tags it fetches — 4.2s
  • ✅ Loan servicing gaps › the data-only tabs stay hidden when the loan carries nothing for them — 3.4s
  • ✅ Loan servicing gaps › each data-only tab appears and renders once the loan carries its data — 3.2s
  • ✅ Loan servicing gaps › disburse to savings sends the date and amount, with the platform date format — 4.4s
  • ✅ Loan servicing gaps › disburse to savings is offered only on an approved loan — 3.4s
  • ✅ Loan servicing gaps › unassign loan officer sends the date, and appears only when one is assigned — 4.4s
  • ✅ Loan servicing gaps › unassign loan officer is hidden on a loan with no officer — 4.2s
  • ✅ Loan servicing gaps › undo last disbursal appears only on a multi-disbursal loan, and sends an empty body — 4.4s
  • ✅ Loan servicing gaps › undo last disbursal is hidden on a single-disbursal loan — 3.2s
  • ✅ Loan servicing gaps › close as rescheduled is offered on an active loan — 4.0s

rbac-feature-flag.spec.ts

  • ✅ RBAC permission gating (rbacEnabled = true) › a limited user does not see permission-gated nav groups — 1.6s
  • ✅ RBAC permission gating (rbacEnabled = true) › a user with READ_USER sees only the Security entries that permission covers — 1.5s
  • ✅ RBAC permission gating (rbacEnabled = true) › the Security group fills in as the user is granted each of its permissions — 1.5s
  • ✅ RBAC permission gating (rbacEnabled = true) › a superuser (ALL_FUNCTIONS) sees all permission-gated groups — 1.8s
  • ✅ RBAC institution-feature gating (rbacEnabled = true) › universal institution shows Groups, Centers and Collection Sheet — 2.2s
  • ✅ RBAC institution-feature gating (rbacEnabled = true) › commercial bank (cb) hides all group-lending features — 1.8s
  • ✅ RBAC institution-feature gating (rbacEnabled = true) › credit union (cu) shows Groups but hides Centers and Collection Sheet — 1.7s
  • ✅ rbacEnabled = false › restores the pre-RBAC behaviour of showing everything — 1.7s
  • ✅ deployment navigation overrides › removes the entries config.json names, leaving the rest alone — 1.6s
  • ✅ deployment navigation overrides › removes them even where RBAC is off — 2.6s

rbac-route-protection.spec.ts

  • ✅ route authorization › a superuser reaches every sampled route and sees the full navigation — 13.5s
  • ✅ route authorization › a single-module user is confined to that module — 9.3s
  • ✅ route authorization › a read-only user gets the lists and not the forms — 11.4s
  • ✅ route authorization › a user with an empty permission list is refused everywhere and the app still works — 9.1s
  • ✅ route authorization › a session carrying no permissions field is treated as carrying none — 5.0s
  • ✅ route authorization › an unrecognised permission code grants nothing — 5.8s
  • ✅ route authorization › an unauthenticated visitor is asked to sign in, not told they are forbidden — 6.2s
  • ✅ route authorization › a deployment with RBAC turned off behaves as it did before the guard — 7.1s
  • ✅ the Access Denied page › says what happened, under a single heading — 4.0s
  • ✅ the Access Denied page › moves focus to the heading, since the user did not ask to come here — 3.2s
  • ✅ the Access Denied page › announces itself politely — 3.2s
  • ✅ the Access Denied page › names the permissions the screen wanted, so the user can ask for them — 4.0s
  • ✅ the Access Denied page › offers a way back that the user is allowed to take — 3.4s
  • ✅ the Access Denied page › is reachable by keyboard alone — 3.3s
  • ✅ permission feedback › a visible nav entry says what the user can do in that module — 1.6s
  • ✅ permission feedback › a nav entry carries no hint when there is nothing specific to say — 2.4s
  • ✅ navigation and routes agree › a hidden menu entry is also refused by URL, and a shown one is not — 5.1s
  • ✅ navigation and routes agree › the create button is withheld from a user whose create route would refuse them — 3.4s

report-enhancements.spec.ts

  • ✅ Report Enhancements, Pagination, and Help Tour › should run report, show paginated data, and download CSV — 4.8s
  • ✅ Report Enhancements, Pagination, and Help Tour › should trigger guidance help tour and navigate steps — 2.3s

reporting.spec.ts

  • ✅ Reporting › should display list of reports — 1.8s
  • ✅ Reporting › should navigate to run report page — 2.1s

scheduler-jobs.spec.ts

  • ✅ Scheduler Jobs bulk run › Run Selected is disabled until a job is checked — 3.4s
  • ✅ Scheduler Jobs bulk run › Select All checks every job, and running confirms then triggers each one — 4.8s
  • ✅ Scheduler Jobs bulk run › declining the confirmation runs nothing — 3.5s

two-factor-authentication.spec.ts

  • ✅ two-step verification › asks for a code and lets the user in once it is accepted — 1.8s
  • ✅ two-step verification › sends the token on every later request — 1.7s
  • ✅ two-step verification › keeps the user on the step when the code is wrong, and says why — 2.4s
  • ✅ two-step verification › accepts a correct code after a wrong one — 1.7s
  • ✅ two-step verification › offers the choice when there is more than one channel — 1.4s
  • ✅ two-step verification › says so when the account has no channel configured — 1.4s
  • ✅ two-step verification › returns to the choice when the code could not be sent — 1.4s
  • ✅ two-step verification › does not let a half-finished session reach the application — 4.1s
  • ✅ two-step verification › backing out returns to the password form — 1.5s
  • ✅ two-step verification › a deployment without a second factor signs in exactly as before — 1.6s

working-capital-loan-actions.spec.ts

  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › shows delinquency action history and submits a new one — 4.6s
  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › shows breach action history and submits a new one — 5.9s
  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › shows near-breach action history and submits a new one — 4.6s
  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › attaches and detaches a loan originator — 4.2s
  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › adds a new charge and waives an existing one — 5.1s
  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › shows rate-change history, amortization schedule, and delinquency range tags — 3.6s
  • ✅ Working Capital loan delinquency, breach and near-breach actions, and originators › marks the loan as fraud, applies a discount, and changes the payment rate — 5.7s
Slowest 10 — what the shard counts should be tuned against
Test Spec Time
Loan product down payment and tranches › the rest interval appears only when the frequency is not the repayment period loan-product-down-payment.spec.ts 14.5s
route authorization › a superuser reaches every sampled route and sees the full navigation rbac-route-protection.spec.ts 13.5s
route authorization › a read-only user gets the lists and not the forms rbac-route-protection.spec.ts 11.4s
route authorization › a single-module user is confined to that module rbac-route-protection.spec.ts 9.3s
route authorization › a user with an empty permission list is refused everywhere and the app still works rbac-route-protection.spec.ts 9.1s
route authorization › a deployment with RBAC turned off behaves as it did before the guard rbac-route-protection.spec.ts 7.1s
route authorization › an unauthenticated visitor is asked to sign in, not told they are forbidden rbac-route-protection.spec.ts 6.2s
Working Capital loan delinquency, breach and near-breach actions, and originators › shows breach action history and submits a new one working-capital-loan-actions.spec.ts 5.9s
route authorization › an unrecognised permission code grants nothing rbac-route-protection.spec.ts 5.8s
Working Capital loan delinquency, breach and near-breach actions, and originators › marks the loan as fraud, applies a discount, and changes the payment rate working-capital-loan-actions.spec.ts 5.7s

📼 Download the HTML report, videos and traces — see the playwright-report-mocked artifact.

Generated by run 32584680931 from 21273f9. The run executed a fork branch, so treat its contents as unverified.

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

E2E — real Fineract

🎭 E2E Tests

✅ All green — 72 passed · 0 failed · 0 skipped, across 22 spec files in 6m 47s.

By spec file

Spec ⏭️ Time
backend.setup.ts 3 0 0 6.0s
center-servicing.spec.ts 2 0 0 19.5s
client-transfer.spec.ts 4 0 0 46.6s
deposit-account-servicing.spec.ts 3 0 0 27.2s
deposit-product-configuration.spec.ts 3 0 0 15.6s
group-membership.spec.ts 3 0 0 48.7s
loan-account-actions.spec.ts 3 0 0 24.3s
loan-charge-off.spec.ts 2 0 0 21.4s
loan-product-accounting.spec.ts 1 0 0 31.6s
loan-servicing.spec.ts 2 0 0 19.9s
login.spec.ts 4 0 0 6.0s
parity-screens.spec.ts 8 0 0 47.6s
rbac-backend-restricted-user.spec.ts 7 0 0 35.7s
rbac-multi-permission.spec.ts 9 0 0 58.7s
full-demo.spec.ts 1 0 0 1m 2s
loan-lifecycle.spec.ts 4 0 0 2m 1s
loan-schedule-type.spec.ts 3 0 0 34.9s
report-parameter-backend.spec.ts 4 0 0 23.4s
savings-transaction-correction.spec.ts 1 0 0 7.7s
share-account-servicing.spec.ts 2 0 0 19.0s
share-product-accounting.spec.ts 1 0 0 24.7s
teller-cash-management.spec.ts 2 0 0 36.6s
All 72 tests — click to expand

backend.setup.ts

  • ✅ seed backend reference data — 2.3s
  • ✅ seed backend reference data — 1.9s
  • ✅ seed backend reference data — 1.9s

center-servicing.spec.ts

  • ✅ Center servicing › a center is activated, staffed and given a group — 14.0s
  • ✅ Center servicing › notes are recorded against the center — 5.6s

client-transfer.spec.ts

  • ✅ Client transfer between offices › a proposed transfer is held until the destination accepts, and then the client moves — 12.0s
  • ✅ Client transfer between offices › a rejected transfer leaves the client on hold, and withdrawing is the way back — 12.5s
  • ✅ Client transfer between offices › a client can be transferred in one step when the user may act for both offices — 11.1s
  • ✅ Client staff assignment › an officer can be assigned and then removed — 11.0s

deposit-account-servicing.spec.ts

  • ✅ Term deposit account servicing › an account is approved, activated and closed before maturity — 12.1s
  • ✅ Term deposit account servicing › a deposit is recorded, listed, and reversed without leaving the list — 8.8s
  • ✅ Term deposit account servicing › an application can be rejected instead of approved — 6.3s

deposit-product-configuration.spec.ts

  • ✅ Deposit product configuration › a fixed deposit product survives being edited — 5.1s
  • ✅ Deposit product configuration › a recurring deposit product can be created at all — 5.3s
  • ✅ Deposit product configuration › a savings product carries its accounting configuration — 5.2s

group-membership.spec.ts

  • ✅ Group membership and lifecycle › a group is activated, staffed, given members and a committee, then emptied — 20.7s
  • ✅ Group membership and lifecycle › notes are recorded against the group and can be removed again — 8.8s
  • ✅ Group membership and lifecycle › an empty group is closed with a reason, and a group with members is refused — 19.2s

loan-account-actions.spec.ts

  • ✅ Loan account lifecycle actions › new action menu items appear only for active loans — 7.0s
  • ✅ Loan account lifecycle actions › undo disbursal shows a confirm dialog and reverts the loan to Approved — 9.7s
  • ✅ Loan account lifecycle actions › write off requires confirmation and moves the loan out of Active status — 7.6s

loan-charge-off.spec.ts

  • ✅ Loan servicing commands › charges a loan off through the UI and reverses it — 11.4s
  • ✅ Loan servicing commands › records a goodwill credit through the shared transaction form — 10.0s

loan-product-accounting.spec.ts

  • ✅ Loan product accounting › a cash-accounting product is configured, round-trips on edit, and posts to the ledger — 31.6s

loan-servicing.spec.ts

  • ✅ Loan servicing: notes and transaction adjustment › notes can be added and removed, with a confirm dialog on delete — 9.2s
  • ✅ Loan servicing: notes and transaction adjustment › a repayment transaction can be viewed and adjusted with a corrected amount — 10.8s

login.spec.ts

  • ✅ Login › login page displays correctly — 1.3s
  • ✅ Login › login form has required fields — 2.0s
  • ✅ Login › submit button is disabled when form is empty — 1.3s
  • ✅ Login › submit button is enabled when form is filled — 1.3s

parity-screens.spec.ts

  • ✅ Screens added for platform parity › a manual journal entry can be read whole and reversed — 6.9s
  • ✅ Screens added for platform parity › an entry that is already reversed is not offered again — 5.1s
  • ✅ Screens added for platform parity › a report definition can be created, edited and deleted; a core one cannot — 6.9s
  • ✅ Screens added for platform parity › a core report opens read-only with only its in-use setting — 4.5s
  • ✅ Screens added for platform parity › a pending loan is approved from the queue, in a batch — 7.3s
  • ✅ Screens added for platform parity › a fixed deposit is listed as a deposit, not as a savings account — 5.0s
  • ✅ Screens added for platform parity › an office has a screen, and it carries its custom fields — 5.7s
  • ✅ Screens added for platform parity › a savings account carries notes, and the note survives a reload — 6.3s

rbac-backend-restricted-user.spec.ts

  • ✅ a genuinely restricted Fineract user › holds exactly the permissions their role was granted — 286ms
  • ✅ a genuinely restricted Fineract user › reaches the screen their permission covers — 5.3s
  • ✅ a genuinely restricted Fineract user › is refused a screen their permission does not cover, by URL and by the backend — 5.0s
  • ✅ a genuinely restricted Fineract user › is refused a write screen they can read the list for, and the write itself — 7.0s
  • ✅ a genuinely restricted Fineract user › is not offered the actions it would be refused for — 3.8s
  • ✅ a genuinely restricted Fineract user › is shown an action it cannot take, disabled and saying what it needs — 6.1s
  • ✅ a genuinely restricted Fineract user › the superuser the rest of the suite uses is unaffected — 8.1s

rbac-multi-permission.spec.ts

  • ✅ a route declaring more than one permission code (OR semantics) › is admitted by either declared code alone — 5.4s
  • ✅ a route declaring more than one permission code (OR semantics) › is admitted by the other declared code alone — 4.6s
  • ✅ a route declaring more than one permission code (OR semantics) › is refused when holding neither declared code, by the router and by the backend — 5.5s
  • ✅ ALL_FUNCTIONS_READ, against the real Fineract permission catalogue › reaches read screens across modules it holds no specific code for — 9.4s
  • ✅ ALL_FUNCTIONS_READ, against the real Fineract permission catalogue › is refused every write screen, and the writes themselves — 7.0s
  • ✅ a restricted session across a real page reload › keeps the same permission boundary after reloading, not just after a fresh login — 10.3s
  • ✅ a second real action-level gate, distinct from loan repayment › is shown the Approve action disabled and naming what it needs, refused by the backend too — 6.0s
  • ✅ Security module writes (users, roles), against the real backend › reaches the list screens but is refused the write screens — 10.3s
  • ✅ Security module writes (users, roles), against the real backend › is refused creating a user and modifying a role, by the backend itself — 318ms

full-demo.spec.ts

  • ✅ Full feature demo recording › walk through loan schedule type, lifecycle, custom fields, collateral, and disbursement — 1m 2s

loan-lifecycle.spec.ts

  • ✅ Loan lifecycle: creation, approval, disbursement › create, approve, and disburse a Cumulative loan — 30.9s
  • ✅ Loan lifecycle: creation, approval, disbursement › create, approve, and disburse a Progressive loan — 32.8s
  • ✅ Loan lifecycle: creation, approval, disbursement › an approved loan can be returned to pending approval — 29.0s
  • ✅ Loan lifecycle: creation, approval, disbursement › the delinquency tab reads a real loan, and the empty data tabs stay hidden — 28.5s

loan-schedule-type.spec.ts

  • ✅ Loan Schedule Type (Cumulative vs Progressive) › loan products list shows a schedule type chip per product — 8.9s
  • ✅ Loan Schedule Type (Cumulative vs Progressive) › create a Progressive loan product end-to-end and verify it round-trips — 15.6s
  • ✅ Loan Schedule Type (Cumulative vs Progressive) › loan creation shows the schedule type badge for a Progressive product — 10.5s

report-parameter-backend.spec.ts

  • ✅ Dynamic report parameters against Fineract › keeps the parameter form available when a report has cascading lookups — 4.5s
  • ✅ Dynamic report parameters against Fineract › changing Office changes the Client Listing row set — 7.5s
  • ✅ Cascading report parameters against Fineract › sends the parent value to the child lookup and clears the child when it changes — 7.0s
  • ✅ Chart reports against Fineract › renders a chart report as a chart rather than a table — 4.5s

savings-transaction-correction.spec.ts

  • ✅ Savings transaction correction › a deposit is reversed and a hold is released — 7.7s

share-account-servicing.spec.ts

  • ✅ Share account servicing › an account is approved, activated, traded and closed — 12.9s
  • ✅ Share account servicing › an application can be rejected — 6.1s

share-product-accounting.spec.ts

  • ✅ Share product accounting › a share product is mapped to equity and round-trips on edit — 24.7s

teller-cash-management.spec.ts

  • ✅ Teller cash management › a cashier is listed, receives an allocation, and settles cash back — 24.9s
  • ✅ Teller cash management › settling more than the cashier holds is refused and the form stays usable — 11.7s
Slowest 10 — what the shard counts should be tuned against
Test Spec Time
Full feature demo recording › walk through loan schedule type, lifecycle, custom fields, collateral, and disbursement full-demo.spec.ts 1m 2s
Loan lifecycle: creation, approval, disbursement › create, approve, and disburse a Progressive loan loan-lifecycle.spec.ts 32.8s
Loan product accounting › a cash-accounting product is configured, round-trips on edit, and posts to the ledger loan-product-accounting.spec.ts 31.6s
Loan lifecycle: creation, approval, disbursement › create, approve, and disburse a Cumulative loan loan-lifecycle.spec.ts 30.9s
Loan lifecycle: creation, approval, disbursement › an approved loan can be returned to pending approval loan-lifecycle.spec.ts 29.0s
Loan lifecycle: creation, approval, disbursement › the delinquency tab reads a real loan, and the empty data tabs stay hidden loan-lifecycle.spec.ts 28.5s
Teller cash management › a cashier is listed, receives an allocation, and settles cash back teller-cash-management.spec.ts 24.9s
Share product accounting › a share product is mapped to equity and round-trips on edit share-product-accounting.spec.ts 24.7s
Group membership and lifecycle › a group is activated, staffed, given members and a committee, then emptied group-membership.spec.ts 20.7s
Group membership and lifecycle › an empty group is closed with a reason, and a group with members is refused group-membership.spec.ts 19.2s

📼 Download the HTML report, videos and traces — see the playwright-report-backend artifact.

Generated by run 32584680931 from 21273f9. The run executed a fork branch, so treat its contents as unverified.

@Aman-Mittal
Aman-Mittal force-pushed the feat/servicing-and-navigation-gaps branch from 61f2f91 to b4dc7ff Compare August 22, 2026 15:32
@Aman-Mittal Aman-Mittal changed the title Enhance API, UI, and reporting features across multiple modules feat: close nine daily branch-operations gaps, and unblock the spec sync #416 breaks Aug 22, 2026
…rtcuts

Two navigation gaps on every screen. The back office is several levels deep
in places — a group's GLIM account, a loan's charge form — with nothing on
the page saying where that is or how to get back up, and reaching a common
section always meant a trip through the sidebar.

The trail is derived from each activated route's `title`, the translation key
`TranslatedTitleStrategy` already sets for the browser tab, rather than a
second set of route data that could drift out of step with it. Route configs
here commonly pair an outer titled segment with an identically titled
empty-path child that lazy-loads the feature, so adjacent duplicate crumbs
collapse into one.

Shortcuts are Alt+letter, which leaves the browser's own Ctrl/Cmd bindings
alone, and are ignored while focus is in a text field so they cannot eat what
someone is typing.
The create-client form presented every field at once — legal form, office,
staff, names, dates, address and contact details on one page — with no
indication of which handful were actually required. Front-office staff
opening an account are the least experienced users of this application and
the ones under the most time pressure, so the long form is where they stall.

Splitting it into Client Type, Personal Details and Contact Details lets each
step gate its own required fields: `Next` stays disabled until the step is
valid, so the user is told what is missing where it is missing rather than by
a rejected submit at the end.

The wizard applies to creation only. Editing reuses the same template flat,
because someone correcting one field on an existing client is better served
seeing all of them at once than being paced through steps again.

The shared stepper is a new component rather than a form-local one — the loan
and savings application forms have the same shape of problem.
Branch and portfolio managers had no way to answer "how much is outstanding,
where, and how much of it is at risk" without exporting to a spreadsheet. The
platform already answers this through the advanced search endpoint; nothing
in the back office called it.

The screen drives that endpoint: filter by status, product, office and a date
range, optionally bounding outstanding amount or outstanding percentage, and
get counts and totals grouped by office and product.

The two outstanding filters are opt-in because the endpoint treats them as
present-or-absent rather than as nullable — sending the field at all changes
the query, so the payload omits the amount and percentage keys entirely
unless their toggle is on, and sends min/max only for the `between`
condition and a single value otherwise.
…try type

The journal entries list was filterable by date alone. On a multi-branch
tenant that is the one dimension that does not narrow anything useful — an
accountant reconciling a single branch's cash account had to page through
every entry the institution posted that day.

Office and GL account come from their own endpoints rather than from the
entries themselves, so the lists stay complete when the current filter
returns nothing. The manual-entries toggle maps to the endpoint's
`manualEntriesOnly` flag, which is how the platform distinguishes an
accountant's correcting entry from one the portfolio posted.

Filter changes are debounced through a subject: office, account, type and
both dates are commonly changed in sequence, and each one otherwise fired
its own request.
… rate chart

Three gaps on the deposit side of the product screens.

An approved savings account could not be returned to pending. Approval is
routinely done in error — wrong product, wrong client — and without an undo
the only remedy was to reject the account and re-key it, which loses the
application date and the account number. `undoapproval` is sent without the
usual `dateFormat`/`locale` pair: like the loan equivalent, it answers 400 for
parameters it does not expect, and accepts an empty body or one carrying only
a note.

Deposit accounts showed neither their charges nor the interest rate chart the
product was opened under. The rate chart is what a customer actually asks
about — which rate applies at which term — and it was visible only on the
product, not on the account, so an account opened before a product rate change
could not be checked against the terms it was actually sold on. Both live
under `?associations=all`, which neither generated method can send, so they go
through the same `HttpClient` escape hatch as the transaction list.

`ChartSlab` is declared locally rather than reusing the generated model: the
generated type omits the amount range, description and incentive fields the
real response carries, and this reads what is actually on the wire.
…uency tags

The working-capital loan view showed the loan and its actions but none of the
detail a reviewer needs to justify one. Four tabs, all backed by endpoints the
API already exposed:

- Charges, with the form to add and waive one. A working-capital facility is
  priced largely through its charges, so not being able to add one meant
  dropping to the generic loan screens or to the API.
- Rate changes, showing the effective date and the rate before and after,
  including reversed ones — the audit trail for a repriced facility.
- The projected amortization schedule, which is what the borrower is shown.
- Delinquency range tags, so the reason a facility was flagged is visible
  next to the facility rather than only in the delinquency report.

`mark as fraud` and `apply discount` join the action form for the same reason:
both are decisions taken while looking at this screen.
…run jobs in bulk

Bulk import offered a fraction of the entity types the platform supports. The
transactional ones were the notable absence — loan repayments, savings,
fixed and recurring deposit transactions — which are exactly the files an
institution loads daily from a branch or an agent network. Guarantors and
share accounts are added alongside them.

The chart-of-accounts entry downloaded the wrong file: `glaccounts` called the
journal-entries template. Every other entry names its own resource, so this
was a copy-paste of the wrong service rather than a deliberate alias, and it
gave anyone importing a chart of accounts a template that could not be
imported. Journal entries are now their own entry, wired to the endpoint
`glaccounts` had been borrowing.

Guarantors are scoped to one loan rather than to the tenant, so that template
needs a loan id before it can be downloaded; the field appears only for the
entity types that require it.

Scheduler jobs gain multi-select and a `Run Selected` action. Recovering from
a failed nightly batch means re-running a specific set of jobs, and doing that
one job at a time is both slow and easy to get wrong.
Two things made the bulk work queues awkward for the branch staff who use
them. Everything arrived as one flat list across the whole institution, so a
branch approver had to pick their own office's rows out of every other
branch's; and the reschedule queue could only approve, even though a
reschedule request is at least as often declined.

Rows now group under the office heading the loan or client belongs to. The
loan list answers `clientOfficeId` and no name, so office names are fetched
once and cached — they are shared master data that does not change mid-session.

The reschedule queue stays flat: its list response carries no office at all,
so grouping it would mean a per-row lookup for a queue that is normally short.

Reject reuses the same batch path as approve, differing only in the command
and in the date field the platform expects (`rejectedOnDate` rather than
`approvedOnDate`), and is gated on `REJECT_RESCHEDULELOAN`.
An audit log that can only be read on screen is of limited use to the people
who need it — an internal auditor or a regulator asking what changed and who
approved it wants the records out of the application, not a set of
screenshots.

The export covers the page currently loaded, matching what the table shows
rather than silently re-querying the full result set: the audit endpoint is
paginated and unbounded, and an export that quietly differed from the filtered
view on screen would be worse than none.

CSV escaping is its own utility with its own tests rather than an inline
join. Audit records carry free text — usernames, entity names and the command
JSON — so quotes, commas and newlines in the data are the normal case here,
not an edge case.
Vitest's 5s default is measured against the test body, but the first
`createComponent()` in a file also compiles the component and everything it
imports. For the larger screens that runs past 5s on a cold Vite cache even
though the test itself is synchronous, so a spec passes locally on a warm
re-run and fails in CI, which is always cold.

The compile is paid once per file rather than per test, so a higher ceiling
costs nothing on the passing path.
@Aman-Mittal
Aman-Mittal force-pushed the feat/servicing-and-navigation-gaps branch from b4dc7ff to 21273f9 Compare August 22, 2026 16:25
@Aman-Mittal
Aman-Mittal merged commit 715f1c1 into apache:main Aug 22, 2026
29 checks passed
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.

Daily branch operations: nine gaps that push routine back-office work into spreadsheets and the API

1 participant