Skip to main content

Overview

The Loan Management system handles the complete lifecycle of microfinance loans, from initial application through approval, disbursement, repayment tracking, and final closure.
Loans are always associated with both a union member (borrower) and a union. The loan inherits the credit officer from the union.

Loan Data Model

From the Prisma schema:
model Loan {
  id            String      @id @default(cuid())
  loanNumber    String      @unique  // Auto-generated unique identifier
  
  // Borrower and Union
  unionMemberId String
  unionMember   UnionMember
  unionId       String
  union         Union
  
  // Loan Details
  loanTypeId        String?
  loanType          LoanType?
  principalAmount   Decimal   @db.Decimal(14, 2)
  currencyCode      String    @default("NGN")
  
  // Terms
  termCount         Int       // Duration count
  termUnit          TermUnit  // DAY, WEEK, or MONTH
  startDate         DateTime
  endDate           DateTime?
  
  // Fees
  processingFeeAmount    Decimal  @db.Decimal(14, 2)
  processingFeeCollected Boolean  @default(false)
  penaltyFeePerDayAmount Decimal  @db.Decimal(14, 2)
  
  // Status
  status            LoanStatus @default(DRAFT)
  
  // Assignment
  createdByUserId   String
  createdByUser     User
  assignedOfficerId String?
  assignedOfficer   User?
  
  // Dates
  disbursedAt DateTime?
  closedAt    DateTime?
  notes       String?
  
  // Relations
  scheduleItems RepaymentScheduleItem[]
  repayments    Repayment[]
  documents     LoanDocument[]
  
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deletedAt DateTime?
}

Loan Status Lifecycle

Loans move through several statuses:
enum LoanStatus {
  DRAFT              // Just created, not submitted
  PENDING_APPROVAL   // Submitted, awaiting supervisor
  APPROVED           // Approved, ready for disbursement
  ACTIVE             // Disbursed and being repaid
  COMPLETED          // Fully repaid and closed
  DEFAULTED          // Borrower failed to repay
  WRITTEN_OFF        // Bad debt, removed from books
  CANCELED           // Canceled before disbursement
}

Status Flow Diagram

1

DRAFT

Loan application created but not yet submitted
2

PENDING_APPROVAL

Submitted to supervisor for review
3

APPROVED

Supervisor approved, ready to disburse funds
4

ACTIVE

Money disbursed, repayments in progress
5

COMPLETED

All payments received, loan closed successfully

Alternative Outcomes

DEFAULTED

Borrower stopped paying and is significantly overdue

WRITTEN_OFF

Bad debt that will not be recovered

CANCELED

Application withdrawn before disbursement

Creating a New Loan Application

Prerequisites

Before creating a loan:
  • Union member must exist and be verified
  • Member must belong to a union
  • Loan type (optional) should be configured

Creation Process

1

Start Application

Navigate to Business ManagementLoans and click + Add New Loan
2

Select Borrower

  1. Choose Union from dropdown
  2. Select Union Member (only verified members appear)
  3. System auto-fills member details
3

Loan Details

Required Fields:
  • Loan Type - Select from configured types
  • Principal Amount - How much to lend (in Naira)
  • Interest Rate - Annual percentage (may auto-fill from loan type)
  • Loan Term - Duration count
  • Term Unit - Days, Weeks, or Months
  • Repayment Frequency - How often payments are due
  • Purpose - Why the loan is needed
  • Start Date - When the loan begins
4

Review Schedule

The system automatically generates:
  • Complete repayment schedule
  • Payment due dates
  • Principal and interest breakdown
  • Total amount to be repaid
5

Submit or Save

Two options:
  • Save as Draft - Saves but doesn’t submit (status: DRAFT)
  • Submit for Approval - Sends to supervisor (status: PENDING_APPROVAL)

Term Units Explained

enum TermUnit {
  DAY    // Daily repayments (e.g., 30 days)
  WEEK   // Weekly repayments (e.g., 12 weeks)
  MONTH  // Monthly repayments (e.g., 6 months)
}
  • Term Count: 6
  • Term Unit: MONTH
  • Result: 6 monthly payments over 6 months

API Endpoint

// POST /api/loans
const createLoan = async (data: {
  unionMemberId: string;
  unionId: string;
  loanTypeId?: string;
  principalAmount: number;
  termCount: number;
  termUnit: 'DAY' | 'WEEK' | 'MONTH';
  startDate: string;
  processingFeeAmount: number;
  penaltyFeePerDayAmount: number;
  notes?: string;
}) => {
  // Creates loan in DRAFT status
  // Generates repayment schedule
}

Viewing All Loans

The Loans page provides comprehensive filtering and viewing:

Summary Cards

  • Total loans count
  • Active loans
  • Pending approvals
  • Overdue loans
  • Total disbursed amount

Search & Filter

  • Search by loan number or borrower
  • Filter by status
  • Filter by union
  • Filter by date range
  • Filter by amount range
  • Filter by credit officer

Data Table

  • Loan number
  • Borrower name
  • Principal amount
  • Status badge
  • Due date
  • Payment progress
  • Actions (view, edit, delete)

Export Options

  • Export to Excel
  • Export to PDF
  • Copy to clipboard
  • Filter before export

Configurable Columns

Click the Settings icon to show/hide columns based on your needs
Available columns:
  • Loan Number
  • Union Member
  • Loan Type
  • Principal Amount
  • Due Today
  • Status
  • Credit Officer
  • Union
  • Overdue Amount
  • Payment Status
  • Actions

Loan Approval Workflow

Only Supervisors and Administrators can approve or reject loan applications

For Supervisors: Reviewing Pending Loans

1

Access Pending Loans

Go to Loans page and filter by “Pending Approval” status
2

Review Application

Click on a loan to view:
  • Borrower information and history
  • Loan amount and terms
  • Repayment schedule
  • Purpose of loan
  • Credit officer notes
3

Make Decision

To Approve:
  1. Click Approve button
  2. Add approval notes (optional)
  3. Confirm approval
  4. Status changes to APPROVED
To Reject:
  1. Click Reject button
  2. Enter rejection reason (required)
  3. Confirm rejection
  4. Status changes to REJECTED

API Endpoints

// Update loan status
POST /api/loans/:id/status
Body: {
  status: 'APPROVED' | 'REJECTED' | 'CANCELED',
  notes?: string
}

Disbursing Loans

Once approved, loans can be disbursed:
1

Open Approved Loan

Find the loan with APPROVED status
2

Click Disburse

Click the Disburse button
3

Enter Details

Provide disbursement information:
  • Disbursement Date (defaults to today)
  • Payment Method (Cash, Bank Transfer, Mobile Money, etc.)
  • Reference Number (transaction ID, check number, etc.)
  • Notes (optional)
4

Confirm Disbursement

Click Confirm DisbursementLoan status changes to ACTIVE and repayment tracking begins
Once disbursed, you cannot undo the action. Ensure all details are correct before confirming.

API Endpoint

// POST /api/loans/:id/disburse
const disburseLoan = async (loanId: string, data: {
  disbursedAt?: Date;
}) => {
  // Updates status to ACTIVE
  // Records disbursement date
  // Activates repayment schedule
}

Viewing Loan Details

Click any loan to see comprehensive information:
  • Loan number and status
  • Borrower details with profile
  • Principal, interest, and total amounts
  • Start and end dates
  • Loan type and terms
  • Processing and penalty fees
  • Created by and assigned officer

Repayment Schedule

The system automatically generates a repayment schedule based on:
  • Principal amount
  • Interest rate
  • Loan term and frequency
  • Start date

Schedule Model

model RepaymentScheduleItem {
  id     String @id
  loanId String
  loan   Loan
  
  sequence     Int       // Payment number (1, 2, 3...)
  dueDate      DateTime  // When payment is due
  
  principalDue Decimal   @db.Decimal(14, 2)
  interestDue  Decimal   @default(0) @db.Decimal(14, 2)
  feeDue       Decimal   @default(0) @db.Decimal(14, 2)
  
  totalDue     Decimal   @db.Decimal(14, 2)
  paidAmount   Decimal   @default(0) @db.Decimal(14, 2)
  
  status   ScheduleStatus @default(PENDING)
  closedAt DateTime?
  
  allocations RepaymentAllocation[]
}

enum ScheduleStatus {
  PENDING  // Not yet paid
  PARTIAL  // Partially paid
  PAID     // Fully paid
  OVERDUE  // Past due date and unpaid
}

Schedule Calculation Example

Loan Details:
  • Principal: ₦50,000
  • Term: 5 months
  • Annual Interest: 10%
  • Monthly Interest: 10% / 12 = 0.833%
Monthly Payment Calculation:
  • Total with interest: ₦50,000 + (₦50,000 × 0.10 × 5/12) = ₦52,083
  • Monthly payment: ₦52,083 / 5 = ₦10,417
Schedule:
SeqDue DatePrincipalInterestTotal
1Feb 1₦10,000₦417₦10,417
2Mar 1₦10,000₦417₦10,417
3Apr 1₦10,000₦417₦10,417
4May 1₦10,000₦417₦10,417
5Jun 1₦10,000₦417₦10,417

Regenerating Schedules

Only Administrators can regenerate loan schedules. This action should only be used to fix calculation errors.
// POST /api/loans/:loanId/regenerate-schedule
// Admin only - regenerates payment schedule

Loan Assignment

Loans can be reassigned to different credit officers:
1

Open Loan Details

Navigate to the loan
2

Click Assign

Click Assign Loan button
3

Select Officer

Choose the new assigned officer
4

Provide Reason

Enter the reason for reassignment
5

Confirm

Confirm the assignment change
Reassignment changes the assignedOfficerId but doesn’t change the union or borrower.

Editing Loans

Loans can only be edited while in DRAFT or PENDING_APPROVAL status. Once disbursed, loans cannot be modified.
Editable fields:
  • Loan amount (if not yet approved)
  • Terms and duration
  • Interest rate
  • Processing fees
  • Notes
Non-editable after approval:
  • Borrower
  • Union
  • Disbursement date
  • Repayment history

Deleting Loans

Loans can only be deleted if:
  • Status is DRAFT or CANCELED
  • No payments have been recorded
  • No documents are attached
1

Locate Loan

Find the loan in the list
2

Delete Action

Click the Delete icon (trash can)
3

Confirm

Review the warning and confirm deletion
Loans are soft deleted (marked with deletedAt) to maintain audit trail and reporting accuracy.

Loan Summary and Analytics

Each loan provides summary metrics:

Financial Summary

  • Principal amount
  • Total interest
  • Processing fees
  • Penalty fees
  • Total amount due
  • Total paid to date
  • Outstanding balance

Payment Performance

  • Payments on time
  • Late payments
  • Missed payments
  • Completion percentage
  • Days overdue (if any)

Schedule Progress

  • Total installments
  • Paid installments
  • Pending installments
  • Overdue installments
  • Next payment due date

Timeline

  • Application date
  • Approval date
  • Disbursement date
  • First payment date
  • Expected completion date
  • Actual completion date

API Endpoint

// GET /api/loans/:id/summary
const getLoanSummary = async (loanId: string) => {
  // Returns comprehensive loan metrics
}

Best Practices

Application Process

  • Verify member identity before creating loan
  • Use consistent loan types
  • Document loan purpose clearly
  • Review schedule before submission

Approval

  • Review borrower’s history
  • Check existing loan performance
  • Verify ability to repay
  • Document approval decision

Disbursement

  • Confirm borrower receipt
  • Record accurate payment method
  • Keep transaction references
  • Disburse only approved loans

Monitoring

  • Track payment schedules daily
  • Follow up on overdue payments early
  • Update loan notes regularly
  • Communicate with borrowers

Troubleshooting

Check:
  • Member is verified
  • Member belongs to a union
  • All required fields are filled
  • Amount is within allowed range
  • You have permission to create loans
Verify:
  • Loan is in DRAFT status
  • All required information is complete
  • Schedule was generated successfully
  • No validation errors
Reasons:
  • Loan is not in APPROVED status
  • You lack disbursement permissions
  • Member is no longer verified
  • Technical error - contact support
Possible causes:
  • Invalid term count (must be > 0)
  • Invalid date range
  • Missing interest rate
  • System calculation error
Solution: Contact administrator to regenerate
Reason: Loan status doesn’t allow editingStatus Rules:
  • DRAFT - Fully editable
  • PENDING_APPROVAL - Limited editing
  • APPROVED/ACTIVE - Cannot edit
  • COMPLETED - View only

API Reference

// Get all loans
GET /api/loans?page=1&limit=20&status=ACTIVE&unionId=xxx&unionMemberId=xxx

// Get loan by ID
GET /api/loans/:id

// Create loan
POST /api/loans
Body: { unionMemberId, unionId, principalAmount, termCount, termUnit, ... }

// Update loan
PUT /api/loans/:id
Body: { principalAmount?, termCount?, notes?, ... }

// Update status
POST /api/loans/:id/status
Body: { status: 'APPROVED' | 'REJECTED' | 'CANCELED', notes? }

// Disburse loan
POST /api/loans/:id/disburse
Body: { disbursedAt? }

// Assign loan
POST /api/loans/:id/assign
Body: { assignedOfficerId, reason? }

// Delete loan
DELETE /api/loans/:id

// Get loan schedule
GET /api/loans/:id/schedule

// Get loan summary
GET /api/loans/:id/summary

// Regenerate schedule (Admin)
POST /api/loans/:loanId/regenerate-schedule

// Generate missing schedules (Admin)
POST /api/loans/generate-missing-schedules

Summary

Loan Management provides:
  • ✅ Complete application workflow
  • ✅ Supervisor approval process
  • ✅ Automated schedule generation
  • ✅ Disbursement tracking
  • ✅ 8 distinct status types
  • ✅ Role-based permissions
  • ✅ Comprehensive reporting
  • ✅ Document management
  • ✅ Assignment history

Next Steps

Build docs developers (and LLMs) love