Skip to content

Repository files navigation

AI-Based Collections Strategy Optimizer

An Angular 19 front-end application that recommends optimal collections outreach strategies for delinquent borrowers using deterministic business rules, recovery probability scoring, and AI-generated customer communications.


1. Problem Statement

Collections teams manage hundreds of delinquent accounts with varying risk profiles, engagement levels, and hardship situations. Manual prioritization is slow, inconsistent, and difficult to audit. This application provides:

  • Automated borrower segmentation based on delinquency attributes
  • Next-best-action recommendations (channel, timing, outreach type)
  • Recovery probability estimation to prioritize high-yield accounts
  • AI-generated, customer-safe messaging for outreach
  • Explainability so agents understand why a recommendation was made
  • Role-based access and audit logging for compliance

2. Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        Presentation Layer                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐  │
│  │  Dashboard   │  │   Details    │  │     Audit Log        │  │
│  │    Page      │  │    Page      │  │   (Supervisor)       │  │
│  └──────┬───────┘  └──────┬───────┘  └──────────┬───────────┘  │
│         │                 │                      │              │
│  ┌──────┴─────────────────┴──────────────────────┴───────────┐  │
│  │              Shared Components & Guards                   │  │
│  │  Header | Explainability Panel | Badges | SupervisorGuard  │  │
│  └──────────────────────────┬────────────────────────────────┘  │
└─────────────────────────────┼───────────────────────────────────┘
                              │
┌─────────────────────────────┼───────────────────────────────────┐
│                     Service Layer (Business Logic)               │
│  ┌────────────────┐  ┌───────────────────┐  ┌───────────────┐  │
│  │ BorrowerService│  │SegmentationService│  │RecoveryProb.  │  │
│  └───────┬────────┘  └─────────┬─────────┘  └───────┬───────┘  │
│          │                     │                     │          │
│  ┌───────┴─────────────────────┴─────────────────────┴───────┐  │
│  │              RecommendationService (Orchestrator)           │  │
│  └──────────────────────────┬────────────────────────────────┘  │
│  ┌───────────────────────────┼────────────────────────────────┐  │
│  │ AiService          AuditService         AuthService        │  │
│  └──────────────────────────┴────────────────────────────────┘  │
└─────────────────────────────┼───────────────────────────────────┘
                              │
┌─────────────────────────────┼───────────────────────────────────┐
│                        Data Layer                                │
│  mock-borrowers.json (assets)  |  In-memory signals (state)     │
│  External LLM API (optional)   |  environment.aiToken           │
└─────────────────────────────────────────────────────────────────┘

Folder Structure

src/app/
├── components/          # Reusable UI (header, explainability panel)
├── pages/               # Route-level views (dashboard, details, audit)
├── services/            # All business logic
├── models/              # TypeScript interfaces & types
├── shared/              # Guards, badges, utilities
└── data/                # (reserved for static constants)

src/assets/
└── mock-borrowers.json  # 12 realistic borrower records

src/environments/
├── environment.ts       # Dev config (aiToken here)
└── environment.prod.ts  # Production config

Design Principles

Principle Implementation
Separation of concerns UI components are thin; all logic in services
Deterministic rules Segmentation & scoring are rule-based, testable
AI as augmentation LLM used for message generation & natural-language explainability
Signals for reactivity Auth role, audit logs, recommendations use Angular signals
No backend Mock JSON + in-memory state; suitable for demo/interview

3. Features

Feature Description
Borrower Dashboard Table with Name, DPD, Amount, Segment, Action, Recovery %
Borrower Details Full profile, recommendation, channel/time, AI message
Explainability Panel Rule-by-rule breakdown of segmentation decision
AI Message Generation Customer-safe outreach via LLM API (with fallback templates)
Recovery Probability Scoring model (0–100) based on borrower attributes
Role-Based Access Agent vs Supervisor (audit log restricted)
Audit Logging Tracks analyze, recommend, message-generate, and explanation events
Security Token from environment, route guards, no PII in prompts beyond name

3.1 Assignment Criteria Alignment

This project is intentionally scoped for a clear demo and interview discussion. Each assessment criterion is addressed as follows:

Criterion How it is covered
Clear end-to-end flow Single Angular SPA: Dashboard → Borrower Details → Analyze → Why? → Generate Message → Supervisor Audit Log. No backend, no NgRx — logic lives in services.
Small, realistic mock data 12 synthetic borrowers in mock-borrowers.json, each designed to trigger a distinct segmentation path (see §3.2).
Grounded, concise, auditable AI LLM prompts are fed only deterministic outputs (segment, action, channel, DPD, amount). Explain prompts are capped at 3–5 sentences. All AI actions are audit-logged.
Documented assumptions & trade-offs §9 Assumptions, §10 Limitations, §10.1 Trade-offs, §10.2 Edge Cases, §10.3 Failure Modes.
Demo-ready explanations §3.3 Demo Script, §6 AI prompts, ARCHITECTURE.md for deeper design Q&A.

3.2 Mock Data → Decision Logic

Borrower Key attributes Expected segment Why it matters
BRW-001, BRW-006, BRW-010 High response, DPD < 30 Willing but Delayed Early delinquency, gentle SMS/email reminder
BRW-002, BRW-008, BRW-011 Default catch-all pattern Habitual Late Payer BRW-011: high response but DPD 55 → not "Willing" (needs DPD < 30)
BRW-003, BRW-007 hardshipIndicator: true Hardship Case BRW-007: hardship wins over high DPD + low response (priority rule)
BRW-005 Low response, DPD 38 Unresponsive Agent call vs escalation threshold at DPD 60
BRW-004, BRW-009, BRW-012 DPD > 90 and amount > ₹50k High-Risk Escalation Escalation vs manual review by response history

3.3 End-to-End Demo Script (5 minutes)

  1. Dashboard — App auto-analyzes on first load. Show segment, action, and recovery % columns.
  2. BRW-001 (Priya Sharma) — Open details. Point out deterministic explainability factors (rule breakdown panel).
  3. Analyze — Re-run if needed; show toast and updated recommendation.
  4. Why? — AI explanation is grounded in the deterministic context string (segment, factors, recovery %). Not a black box.
  5. Generate Message — Customer-safe outreach copy; falls back to template if API unavailable.
  6. Switch to Supervisor — Header role toggle.
  7. Audit Log — Show borrower_analyzed, recommendation_generated, message_generated, and explanation_generated entries with user, role, and timestamp.

Talking points: Segmentation/scoring = local rules (no API). AI = message + explanation only. Audit trail = compliance.


4. Segmentation Logic

Rules are evaluated in priority order (first match wins):

Priority Segment Condition
1 Hardship Case hardshipIndicator === true
2 High-Risk Escalation daysPastDue > 90 AND overdueAmount > 50000
3 Unresponsive responseHistory === 'low' AND daysPastDue > 30
4 Willing but Delayed responseHistory === 'high' AND daysPastDue < 30
5 Habitual Late Payer Default (poor/moderate payment behavior pattern)

Action Mapping (by segment)

Segment Typical Action
Willing but Delayed SMS Reminder / Email Reminder
Habitual Late Payer Agent Call / Payment Plan Offer
Hardship Case Hardship Support / Payment Plan Offer
Unresponsive Agent Call / Escalation
High-Risk Escalation Escalation / Manual Review

5. Recovery Probability Logic

Base score: 50 (neutral starting point)

Factor Adjustment
Good payment history +15
Fair payment history +5
Poor payment history −10
High response rate +15
Medium response rate +5
Low response rate −15
DPD > 90 −20
DPD 61–90 −15
DPD 31–60 −10
DPD < 15 +5
Hardship indicator −10
3+ broken promises −10
1–2 broken promises −5
Amount > ₹50,000 −10

Final score is clamped to [0, 100].


6. AI Integration

Endpoint: POST https://llm-wrapper-741152993481.asia-south1.run.app/llm/query

Configuration: Token is read from environment.aiToken — never hardcoded.

// src/environments/environment.ts
export const environment = {
  production: false,
  aiToken: '',  // Set your token here
  aiApiUrl: 'https://llm-wrapper-741152993481.asia-south1.run.app/llm/query',
};

Uses:

  1. Message generation — empathetic, customer-safe outreach copy
  2. Natural-language explainability — "Why?" button on borrower details

Grounding: AI never decides the segment or action. It only rephrases outputs from SegmentationService, RecoveryProbabilityService, and RecommendationService. The explainability context passed to the LLM is a structured text block built from rule factors.

Conciseness: The explanation prompt explicitly limits responses to 3–5 sentences and forbids exposing internal scoring formulas.

Auditability: Every AI touchpoint writes to AuditService:

  • message_generated — when outreach copy is created
  • explanation_generated — when "Why?" is answered

Prompt templates (see AiService)

Message generation prompt:

Write a customer-safe, empathetic collections outreach message for the following scenario.
Do not use threatening language. Be professional, concise, and action-oriented.

Borrower Name: {name}
Days Past Due: {dpd}
Overdue Amount: ₹{amount}
Segment: {segment}          ← from deterministic rules
Recommended Action: {action} ← from deterministic rules
Channel: {channel}

Write only the message body suitable for {channel}. No subject lines unless email.

Explanation prompt:

You are a collections strategy assistant. Answer the following question clearly and
professionally for a collections agent. Keep the response concise (3-5 sentences).
Do not include sensitive internal scoring details.

Context:
{deterministic explainability context — factors, segment, action, recovery %, channel, time}

Question: Why is this borrower assigned to {segment} with recommended action {action}?

Fallback: If no token is configured or the API fails, deterministic template messages are used. The UI remains functional and auditable.


7. Data Schema

All types live under src/app/models/. Mock borrower records are in src/assets/mock-borrowers.json.

Borrower (borrower.model.ts)

Field Type Description
id string Unique borrower ID (e.g. BRW-001)
name string Borrower display name
email string Contact email
phone string Contact phone (E.164-style)
daysPastDue number Days past due (DPD)
overdueAmount number Outstanding overdue balance (INR)
priorPaymentBehavior 'good' | 'fair' | 'poor' Historical repayment track record
responseHistory 'high' | 'medium' | 'low' Past outreach engagement level
preferredChannel 'sms' | 'email' | 'phone' | 'mail' Borrower channel preference
repaymentPromises number Count of broken repayment promises
hardshipIndicator boolean Financial hardship flag

Recommendation (recommendation.model.ts)

Produced by RecommendationService.analyze() and stored in memory per borrower.

Field Type Description
borrowerId string FK to borrower
segment BorrowerSegment One of 5 segments (see §4)
recommendedAction RecommendedAction Next-best action (7 types)
bestChannel CommunicationChannel SMS, Email, Phone, or Mail
bestTime string Suggested outreach time window
recoveryProbability number Estimated recovery likelihood (0–100)
explainability ExplainabilityFactor[] Rule factors shown in UI panel
reasoningSummary string Human-readable summary
generatedMessage string? AI/template outreach copy (after generate)
analyzedAt string ISO timestamp of analysis

ExplainabilityFactor: { attribute, value, impact } — one row per rule input.

Audit log (audit-log.model.ts)

Field Type Description
id string Unique audit entry ID
timestamp string ISO timestamp
action AuditActionType borrower_analyzed, recommendation_generated, message_generated, explanation_generated
borrowerId string Affected borrower
borrowerName string Borrower name at time of action
performedBy string Agent/supervisor display name
role string agent or supervisor
details string Free-text action summary

User / role (user-role.model.ts)

Field Type Description
id string Mock user ID
name string Display name
role 'agent' | 'supervisor' RBAC role

8. Security Considerations

Area Measure
API token Stored in environment.ts, excluded from source control in production via CI secrets
Role-based access AuthService + supervisorGuard restrict audit log route
Audit trail All analyze, recommend, message, and explanation actions logged with user, role, timestamp
AI prompts Customer-safe instructions; no internal scoring formulas exposed to borrowers
Input validation Borrower data loaded from trusted mock JSON (no user-supplied attributes)
HTTPS LLM API called over HTTPS with Bearer auth
PII handling Demo uses synthetic data; production would require data masking in prompts

Production implementation (beyond this prototype)

Even though auth is mocked client-side, a real lending deployment would add:

Concern Production approach
Authentication OAuth2 / OIDC or enterprise SSO; short-lived JWT access tokens
Authorization Server-enforced RBAC — agents see assigned portfolios only; supervisors see team/org scope
Borrower data isolation Row-level security in the API/DB (agent_id / team_id on every query); no client-side-only guards
Sensitive data in AI Mask or tokenize PII in LLM prompts; log prompt hashes, not full borrower records
Audit persistence Append-only audit store (PostgreSQL / immutable log stream); retention per compliance policy
Secrets LLM API keys in vault/CI secrets — never in frontend bundles
Transport TLS everywhere; optional field-level encryption for contact details at rest

9. Assumptions

  1. Borrower attributes are pre-validated and normalized (enums for behavior/response levels).
  2. Segmentation rules are mutually exclusive via priority ordering.
  3. INR (₹) is the currency for overdue amounts; threshold of ₹50,000 for high-risk.
  4. "Habitual Late Payer" is the catch-all for accounts not matching higher-priority rules.
  5. Role switching is simulated client-side (no real authentication backend).
  6. AI token is provided by the interviewer/assessor at runtime.
  7. Communication time windows are heuristic-based, not ML-optimized.

10. Limitations

  • No persistent storage — recommendations and audit logs reset on page refresh
  • No real authentication — role switching is a UI toggle for demo purposes
  • Mock data only — no integration with loan servicing systems
  • Single-tenant — no multi-org or team-level permissions
  • AI dependency — message quality depends on external LLM availability
  • No A/B testing — recovery probability is estimated, not validated against outcomes

10.1 Trade-offs

Decision Benefit Cost
No backend Fast to build and demo; zero infra No persistence, no real auth
Priority-ordered rules Auditable, testable, explainable May miss nuanced cases that ML could catch
Hybrid AI (rules + LLM) Compliance-friendly decisions + natural language Two systems to maintain; LLM can still hallucinate on edge phrasing
In-memory audit log Simple signal-based reactivity Lost on refresh
Client-side RBAC Easy role demo Not secure for production
Fallback AI templates Works offline / without token Less personalized than live LLM
12 mock borrowers Covers all segments without noise Not representative of production portfolio scale

10.2 Edge Cases

Scenario Behavior
Hardship + high DPD + low response (BRW-007) Hardship rule wins (priority 1) → Hardship Case, not High-Risk or Unresponsive
High response but DPD ≥ 30 (BRW-011) Does not qualify as Willing but Delayed → falls through to Habitual Late Payer
High-Risk with medium response (BRW-009) Segment = High-Risk Escalation, action = Manual Review (not Escalation)
Generate message before analyze RecommendationService auto-analyzes first, then calls AI
Missing borrower ID in URL Details page shows empty state; no API calls
Unknown borrower ID Borrower set to null after mock lookup
No AI token configured Fallback templates used; no HTTP call to LLM
LLM returns empty string Falls back to deterministic template
Agent opens /audit Guard redirects; audit page shows access-restricted message

10.3 Failure Modes

Failure User impact System response
LLM API down / 5xx Message or explanation may be generic AiService catches error → fallback template; toast on message failure
LLM returns empty body User still sees usable text map() falls back to template
Mock JSON load fails Dashboard empty HttpClient error surfaces in console; no borrowers shown
Page refresh All in-memory state lost User re-analyzes; audit log clears
Invalid environment.aiToken API 401/403 Same as API failure — fallback templates
Concurrent analyze on same borrower Last write wins Recommendation map overwritten (acceptable for demo)

11. Future Improvements

  • Backend API with persistent audit store and real RBAC (OAuth/JWT)
  • ML-based recovery probability trained on historical collection outcomes
  • A/B testing framework for outreach strategies
  • Batch analyze all borrowers with progress indicator
  • Export audit logs to CSV/PDF for compliance
  • Integration with SMS/email gateways for direct outreach
  • Real-time borrower data sync from core banking system
  • Unit test coverage for segmentation, scoring, and services (100% coverage)
  • E2E tests (Playwright/Cypress) for full user flows

12. Run Instructions

Prerequisites

  • Node.js 18+ (tested with v22)
  • npm 9+

Install

cd collections-optimizer
npm install

Configure AI Token (optional)

Edit src/environments/environment.ts:

export const environment = {
  production: false,
  aiToken: 'your-bearer-token-here',
  aiApiUrl: 'https://llm-wrapper-741152993481.asia-south1.run.app/llm/query',
};

Without a token, the app uses fallback message templates.

Development Server

npm start

Open http://localhost:4200

Production Build

npm run build

Output: dist/collections-optimizer/

Usage Walkthrough

  1. Dashboard — View all borrowers; click Analyze to generate recommendations
  2. Borrower Details — Click a name for full profile and recommendation
  3. Why? — Get AI-powered explanation of the recommendation
  4. Generate Message — Create customer-safe outreach copy
  5. Role Switch — Toggle Agent/Supervisor in header
  6. Audit Log — (Supervisor only) View all system actions

Unit Tests

npm test

Headless CI run with coverage:

npm test -- --no-watch --browsers=ChromeHeadless --code-coverage

Coverage: 100% statements, branches, functions, and lines (105 tests).

Test coverage includes:

Spec File What it tests
auth.service.spec.ts Role switching, RBAC permissions, escalation
borrower.service.spec.ts Mock JSON loading via HttpClient
segmentation.service.spec.ts All 5 segmentation rules + priority
recovery-probability.service.spec.ts Scoring model, clamping 0–100
recommendation.service.spec.ts Analyze orchestration, audit, AI message, explanation audit
ai.service.spec.ts LLM API calls, no-token path, fallback on error/empty
audit.service.spec.ts Audit log creation and filtering
toast.service.spec.ts Toast show/dismiss/auto-dismiss
supervisor.guard.spec.ts Route guard for audit page
borrower-dashboard.component.spec.ts Dashboard load, analyze all, toasts
borrower-details.component.spec.ts Details flow, analyze, explain, generate message
borrower.fixtures.spec.ts Test data factory
Component specs Header, explainability panel, badges, toast, audit log, app root

Tech Stack

  • Angular 19 (Standalone Components, Signals)
  • TypeScript 5.7
  • Tailwind CSS 4
  • Angular HttpClient
  • RxJS 7

License

Assessment project — not for production use without further hardening.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages