Payment Processing

Record loan payments with component-based allocation, automatic general ledger entries, and duplicate protection through idempotency keys.

How Payments Work

Every loan payment in CEF Core is component-based, meaning each payment is broken down into its constituent parts rather than recorded as a single lump sum. This ensures precise tracking of how funds are applied and accurate GL accounting.

Principal

Reduces the outstanding loan balance. Recorded via principal_amount.

Interest

Covers accrued interest since the last payment. Recorded via interest_amount.

Fees

Late fees, origination fees, or other charges. Recorded via fee_amount.

The total payment amount equals the sum of all three components. You may specify zero for any component that does not apply (e.g., a principal-only paydown would set interest_amount: 0 and fee_amount: 0).

Recording a Payment

Follow these steps to record a payment against an active loan.

  1. Open the loan: Navigate to Loans in the sidebar. Click on the loan row to open the loan detail view.
  2. Click "Record Payment": This opens the payment form within the loan detail panel.
  3. Enter payment components:
    • principal_amount -- Amount applied to principal
    • interest_amount -- Amount applied to interest
    • fee_amount -- Amount applied to fees (optional, defaults to 0)
    • payment_date -- Date the payment was received
    • payment_method -- ACH, CHECK, WIRE, or CASH
    • reference_number -- Check number, wire reference, or ACH trace ID
  4. Submit: Click Save Payment. The system calls POST /api/v1/loans/:id/payment with an idempotency key.
  5. Verify: The loan balance updates immediately. Check the payment history tab on the loan detail view to confirm the entry.

Payment Methods

CEF Core supports four payment methods. The method selected affects how the reference number is validated and which cash account receives the funds.

MethodReference NumberNotes
ACHACH trace numberElectronic transfer via Automated Clearing House. Typically 1-2 business day settlement.
CHECKCheck numberPhysical or electronic check. Record the check number for reconciliation.
WIREWire reference IDBank wire transfer. Same-day settlement for domestic wires.
CASHReceipt numberPhysical cash deposit. Requires in-person receipt documentation.

Automatic GL Journal Entries

When a payment is recorded, CEF Core automatically generates double-entry journal entries in the General Ledger. No manual GL posting is required.

Standard Payment Journal Entry

AccountDebitCredit
Cash (bank account)Total payment--
Loans Receivable--Principal portion
Interest Income--Interest portion
Fee Income--Fee portion

These entries are posted to the GL via the event outbox pattern, ensuring they are never lost even if the GL service is temporarily unavailable.

Idempotency: Preventing Duplicate Payments

Loan payments are money operations, and CEF Core requires an idempotency key for all money operations. This prevents accidental duplicate payments caused by network retries, double-clicks, or system errors.

How It Works

  1. The frontend generates a unique x-idempotency-key header (typically a UUID) for each payment submission.
  2. The backend checks the ops.idempotency_keys table for a matching key.
  3. If the key already exists, the original response is returned without processing the payment again.
  4. If the key is new, the payment is processed and the key is stored with its response.

Important: Never reuse an idempotency key for different payment amounts or different loans. Each unique payment intent must have its own key. Keys expire after 24 hours.

API Reference

MethodEndpointDescription
POST/api/v1/loans/:id/paymentRecord a payment (requires x-idempotency-key header)
GET/api/v1/loans/:idView loan detail with payment history
GET/api/v1/loans/:id/scheduleView scheduled vs. actual payments

Pro Tip: The payment endpoint returns the updated loan balance in the response body. Use this to update the UI immediately without making a second GET request.

Best Practices

  • Record Payments Same Day: Enter payments on the date received to keep accrual calculations accurate and avoid interest discrepancies.
  • Always Include Reference Numbers: Check numbers, wire references, and ACH trace IDs are critical for bank reconciliation.
  • Verify Component Amounts: Ensure the principal + interest + fee breakdown matches the amortization schedule before submitting.
  • Check the GL Tie-Out: After recording payments, the daily tie-out job (2:10 AM UTC) verifies that the loans subledger balances with the GL. Review any discrepancies promptly.

Understanding Payment Schedules

Learn how amortization schedules determine the expected principal and interest split for each payment period.

Amortization Schedules Guide