Cosmic Module

O

Qubits of DPK

March 20, 2026

Core Open Source

The Analogy

A savings account in Fineract is like a piggy bank that the bank manages for you. You can put money in (deposit), take money out (withdrawal), and the bank adds interest periodically. If you don't touch it for too long, it goes dormant. If you close it, you get all your money back.

Savings Account Types

All three share the same core SavingsAccount entity with different configurations.

Savings Account Status State Machine

javascript
QUBITS OF DPK
1SUBMITTED (100)
2     |
3   approve
4     |
56 APPROVED (200)
7     |
8  activate
9     |
1011  ACTIVE (300) ──────── dormancy detected ───▶ DORMANT (400)
12     |                                                    |
13   close                                            re-activated
14     |                                                    |
15     ▼                                                    ▼
16  CLOSED (600)                                     ACTIVE (300)

Step 1 — Opening a Savings Account

API Call

javascript
QUBITS OF DPK
1POST /fineract-provider/api/v1/savingsaccounts
2Body: {
3  "clientId": 1,
4  "productId": 2,
5  "nominalAnnualInterestRate": 4.5,
6  "submittedOnDate": "01 March 2025"
7}

Code Flow

javascript
QUBITS OF DPK
1SavingsAccountsApiResource.submitApplication()
2SavingsApplicationApprovalCommandHandler
3SavingsAccountWritePlatformServiceImpl.submitSavingsAccountApplication()
4Loads client + savings product
5Creates SavingsAccount entity (status=SUBMITTED)
6Copies interest rate, min balance from product
7Saves to m_savings_account

Approval + Activation

javascript
QUBITS OF DPK
1POST /savingsaccounts/1?command=approve   → status = APPROVED
2POST /savingsaccounts/1?command=activate  → status = ACTIVE (account is now usable)

Step 2 — Deposit

API Call

javascript
QUBITS OF DPK
1POST /fineract-provider/api/v1/savingsaccounts/1/transactions?command=deposit
2Body: {
3  "transactionDate": "05 March 2025",
4  "transactionAmount": 10000
5}

Code Flow

javascript
QUBITS OF DPK
1SavingsAccountTransactionsApiResource.transaction()
2SavingsAccountDepositCommandHandler
3SavingsAccountWritePlatformServiceImpl.deposit()
4Validates account is ACTIVE
5Validates amount > 0
6Creates SavingsAccountTransaction (type=DEPOSIT)
7Updates m_savings_account.account_balance_derived
8Publishes DepositSavingsAccountTransactionBusinessEvent
9AccountingListener:
10                 DEBIT  Bank Account (Cash)    +10000
11                 CREDIT Savings Deposits (Liability) +10000

Step 3 — Withdrawal

javascript
QUBITS OF DPK
1POST /savingsaccounts/1/transactions?command=withdrawal
2Body: { "transactionAmount": 5000 }

Validations checked:

  • Account must be ACTIVE (not dormant, not closed)
  • Amount must not exceed available balance (unless overdraft configured)
  • If minimum balance configured: balance after withdrawal >= minimum balance
  • If daily withdrawal limit configured: total today <= limit

Step 4 — Interest Calculation

Layman

The bank calculates interest daily (or monthly) and credits it to your account. Think of it like getting a tiny salary from the bank every day for keeping money with them.

How It Works in Fineract

Fineract uses daily balance method for interest calculation:
javascript
QUBITS OF DPK
1Daily Interest = Balance × (Annual Rate / 365)
Interest is accrued daily (calculated but not yet credited) and posted periodically (actually added to balance).
Accrual vs Posting:
  • Accrual: "We've EARNED this interest"—accounting entry to record earned income
  • Posting: "We're PAYING this to the customer"—actual balance increase

The COB Job Does This

java
QUBITS OF DPK
1// SavingsSchedularInterestPostingJobExecutor (runs nightly)
2public void execute() {
3    // 1. Get all active savings accounts
4    // 2. For each account: calculate interest for the day
5    // 3. Accrue interest (accounting entry)
6    // 4. If posting date reached: post to balance
7}

Interest Compounding Options

Step 5 — Dormancy

What It Is

If a customer doesn't do any transaction for X days (configured per product), the account becomes dormant.

Rules:

  • Dormant accounts: restricted withdrawals, some banks charge inactivity fee
  • If dormant for even longer: becomes escheatment (money transferred to government)

Detection (COB Job):

java
QUBITS OF DPK
1// SavingsDormancyTrackingJobExecutor
2public void execute() {
3    // Find all savings accounts where:
4    // last_transaction_date < (today - dormancy_period_days)
5    // Update status to DORMANT (400)
6    // Publish SavingsDormancyUpdateBusinessEvent
7}

Step 6 — Account Closure

javascript
QUBITS OF DPK
1POST /savingsaccounts/1?command=close
2Body: {
3  "closedOnDate": "01 June 2025",
4  "withdrawBalance": true,  // withdraw remaining balance on close
5  "paymentTypeId": 1        // how to pay the remaining balance
6}
Flow:
  1. #
    Validate account can be closed (no pending transactions)
  2. #
    Calculate and post any pending interest
  3. #
    Withdraw remaining balance (if withdrawBalance=true)
  4. #
    Set status = CLOSED (600)
  5. #
    Set closedOnDate

Key Domain Classes

Mentor Cheat Sheet