Installments

Description

The Installment entity represents a scheduled payment within a loan’s repayment plan. Each loan has multiple installments based on its repayment cadence (e.g., biweekly). Installments track their due dates, amounts, and payment applications.

Storage

Environment Table Name Region

test

test-loc-service

us-west-2

prod

prod-loc-service

us-east-2

Fields

Field Type Description

loc_user_id

String

User ID who owns the installment

loc_loan_id

String

Loan this installment belongs to

loc_installment_id

String

Unique installment identifier (UUID)

loc_total_amount

Integer

Total installment amount in cents

loc_outstanding_balance

Integer

Remaining balance in cents

loc_status

String

Installment status (see Status Values below)

loc_due_date

String

Due date in YYYY-MM-DD format

loc_process

String

Process that last updated this installment

loc_applications

Array

List of payments applied to this installment

loc_update_reason

String

Reason for last update (for audit logging)

loc_created_date

String

Creation timestamp (RFC3339)

loc_last_updated

String

Last update timestamp (RFC3339)

Status Values

Status Description

SCHEDULED

Installment is scheduled, payment not yet due or pending

COMPLETED

Installment has been fully paid

OVERDUE

Installment is past due and not fully paid

DEFAULTED

Installment has been marked as defaulted

Process Values

Process Description

CREATION

Initial installment creation

AUTOPAY

Updated by autopay collection

MANUAL

Updated by manual user payment

UNAPPLY

Payment was unapplied (e.g., ACH return)

Keys and Indexes

Primary Key

Key Pattern

PK

USER#<user_id>

SK

LOAN#<loan_id>#INSTALLMENT#<installment_id>

GSI1 - Installments by Status and Due Date

Used by collection jobs to query installments across all users by status and due date.

Key Pattern

GSI1PK

INSTALLMENT#STATUS#<status>

GSI1SK

DUEDATE#<due_date>#INSTALLMENT#<installment_id>

GSI2 - Installments by User and Loan

Used to list all installments for a specific loan ordered by due date.

Key Pattern

GSI2PK

USER#<user_id>

GSI2SK

LOAN#<loan_id>#DUEDATE#<due_date>#INSTALLMENT#<installment_id>

Query Patterns

Query Index Key Condition Sort Key Condition

Get installment by ID

Primary

PK = USER#<user_id>

SK = LOAN#<loan_id>#INSTALLMENT#<installment_id>

List installments for loan

Primary

PK = USER#<user_id>

SK begins_with LOAN#<loan_id>#INSTALLMENT

List scheduled installments due today

GSI1

GSI1PK = INSTALLMENT#STATUS#SCHEDULED

GSI1SK begins_with DUEDATE#<today>

List overdue scheduled installments

GSI1

GSI1PK = INSTALLMENT#STATUS#SCHEDULED

GSI1SK < DUEDATE#<today>

List installments for user’s loan by date

GSI2

GSI2PK = USER#<user_id>

GSI2SK begins_with LOAN#<loan_id>#DUEDATE#

Status Transitions

                    ┌──────────────────────┐
                    │      SCHEDULED       │
                    │   (Payment pending)  │
                    └──────────┬───────────┘
                               │
         ┌─────────────────────┼─────────────────────┐
         │                     │                     │
         ▼                     ▼                     ▼
┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐
│    COMPLETED    │   │     OVERDUE     │   │   DEFAULTED     │
│   (Fully paid)  │   │   (Past due)    │   │   (Default)     │
└─────────────────┘   └────────┬────────┘   └─────────────────┘
                               │
                    ┌──────────▼───────────┐
                    │      COMPLETED       │
                    │   (Paid after due)   │
                    └──────────────────────┘

Payment Applications

When a payment is applied to an installment, an entry is added to loc_applications:

{
  "loc_applications": [
    {
      "payment_id": "pay-123",
      "installment_id": "inst-456",
      "amount": 2500,
      "payment_date": "2024-01-15T12:00:00Z"
    },
    {
      "payment_id": "pay-789",
      "installment_id": "inst-456",
      "amount": 2500,
      "payment_date": "2024-01-16T12:00:00Z"
    }
  ]
}

An installment is marked COMPLETED when loc_outstanding_balance reaches zero.

Outstanding Balance Calculation

The outstanding balance is calculated as:

outstanding_balance = total_amount - sum(applications.amount)

This calculation is performed when saving the installment and verified against the stored loc_outstanding_balance field.