491 lines
16 KiB
Plaintext
491 lines
16 KiB
Plaintext
= Capitalized Income
|
|
|
|
== Overview
|
|
|
|
Capitalized Income (formerly referred to as Origination Fee) in Apache Fineract is a fee-based or interest-based income item that is added to the principal of a loan and amortized over time. It is designed to be applied at disbursement and is treated as part of the loan's principal for repayment and interest calculations.
|
|
|
|
== Purpose
|
|
|
|
This functionality enables financial institutions to:
|
|
|
|
* Recognize deferred income (fees or interest) systematically over the loan term
|
|
* Align accounting practices with regulatory requirements
|
|
* Improve income recognition accuracy
|
|
|
|
== Supported Loan Type
|
|
|
|
[IMPORTANT]
|
|
====
|
|
Capitalized Income is only supported for:
|
|
|
|
* Progressive Loan Schedules
|
|
* Advanced Payment Allocation Strategy
|
|
|
|
Other loan schedule types and transaction processing strategies are not supported.
|
|
====
|
|
|
|
== Configuration at Loan Product Level
|
|
|
|
Capitalized income must be configured on the loan product.
|
|
|
|
The configuration options include:
|
|
|
|
* *Enable Capitalized Income*: Boolean toggle (default: disabled)
|
|
* *Calculation Mode*: Only "Flat" is currently supported
|
|
** Later "Percentage based" can be introduced
|
|
* *Amortization Strategy*: Only "EQUAL_AMORTIZATION" is supported
|
|
*** Daily equal portions are recognized over the life of the loan
|
|
*** Later other strategies can be introduced
|
|
* *Income Type*: Specifies allocation rule. Defines which "balance category" to be used.
|
|
|
|
[NOTE]
|
|
====
|
|
In Fineract, balance of a transaction is either: Principal, Fee, Penalty, Interest or overpayment
|
|
====
|
|
|
|
Options:
|
|
* FEE (default)
|
|
* INTEREST
|
|
|
|
=== GL Mapping
|
|
|
|
Required GL Account mappings when Capitalized Income is enabled:
|
|
|
|
* *Deferred Income (Liability)*: `deferredIncomeLiabilityAccountId` - mandatory when enabled
|
|
* *Income from Capitalization (Income)*: `incomeFromCapitalizationAccountId` - mandatory when enabled
|
|
|
|
[IMPORTANT]
|
|
====
|
|
Both GL accounts become mandatory when `enableIncomeCapitalization` is set to `true`.
|
|
====
|
|
|
|
=== Configuration Dependencies
|
|
|
|
When `enableIncomeCapitalization` is set to `true`, all following parameters become mandatory:
|
|
|
|
* `capitalizedIncomeCalculationType` - must be "FLAT"
|
|
* `capitalizedIncomeStrategy` - must be "EQUAL_AMORTIZATION"
|
|
* `capitalizedIncomeType` - must be "FEE" or "INTEREST"
|
|
* `deferredIncomeLiabilityAccountId` - must reference a valid GL account
|
|
* `incomeFromCapitalizationAccountId` - must reference a valid GL account
|
|
|
|
== Behavior and Calculations
|
|
|
|
* Capitalized income is added via API on or after the first disbursement date
|
|
* It is treated as a principal portion, recalculating the repayment schedule accordingly
|
|
* Interest and amortization schedules are updated to include the capitalized income amount
|
|
* Validated using formula: `(Total Disbursed + Current Capitalized Income + New Transaction Amount) ≤ Max Amount`, where Max Amount depends on loan product configuration: if `allowApprovedDisbursedAmountsOverApplied = true` uses `getOverAppliedMax(loan)`, otherwise uses `getApprovedPrincipal()`
|
|
|
|
=== Daily Amortization
|
|
|
|
* Recognized daily using the configured strategy
|
|
* Recognized portions move from Deferred Income to Income from Capitalization
|
|
|
|
==== Special Handling
|
|
|
|
* *Preclosure*: Remaining balance recognized in full on the preclosure date
|
|
* *Charge-off*: Amortization stops and remaining balance is charged off
|
|
|
|
== Transaction Types Introduced
|
|
|
|
* Capitalized Income
|
|
* Capitalized Income Amortization
|
|
* Capitalized Income Adjustment
|
|
* Capitalized Income Amortization Adjustment
|
|
|
|
=== Capitalized Income Transaction
|
|
|
|
The Capitalized Income transaction in Apache Fineract performs the following actions:
|
|
|
|
* Adds a specified amount to the loan principal
|
|
** Considered a deferred income item (such as a fee or interest)
|
|
** Booked as part of the loan's principal
|
|
** Added post-disbursement and only if the loan type supports it (currently: Progressive Loans)
|
|
* Creates a distinct loan transaction
|
|
** Separately tracked with its own transaction type ("Capitalized Income")
|
|
** Not merged with disbursements or repayments
|
|
* Updates the loan schedule
|
|
** Recalculates amortization and interest schedule to include the added amount in the outstanding principal
|
|
* Triggers accounting entries
|
|
** Debits "Loan Portfolio" (Asset)
|
|
** Credits "Deferred Income" (Liability)
|
|
** Does not recognize income upfront
|
|
* Initiates daily amortization
|
|
** Source for daily income recognition through "Capitalized Income Amortization" transactions
|
|
** Progressively converts the deferred amount to recognized income
|
|
|
|
==== Accounting Entries
|
|
|
|
[cols="2*"]
|
|
|===
|
|
|Scenario |Debit |Credit
|
|
|
|
|Capitalized Income
|
|
|Loan Portfolio (Asset)
|
|
|Deferred Income (Liability)
|
|
|===
|
|
|
|
=== Capitalized Income Amortization
|
|
|
|
A Capitalized Income Amortization transaction in Apache Fineract does the following:
|
|
|
|
* *Recognizes Deferred Income Over Time*: Transfers a portion of the capitalized income (originally posted as a liability) into recognized income (posted as interest or fee income), based on a configured daily amortization strategy.
|
|
|
|
* *Daily Posting*: The system automatically creates this transaction each day from the date of capitalized income until the loan maturity or until the full amount is amortized. This is handled by a background job during the COB (Close of Business) process.
|
|
|
|
* *Uses Equal Amortization*: The default and only supported strategy is Equal Amortization, which divides the total capitalized income evenly over the remaining number of days until the loan matures.
|
|
|
|
==== Accounting Entries
|
|
|
|
[cols="2*"]
|
|
|===
|
|
|Scenario |Debit |Credit
|
|
|
|
|Daily amortization
|
|
|Deferred Income (Liability)
|
|
|Income from Capitalization (Income)
|
|
|===
|
|
|
|
==== Stops on Events
|
|
|
|
* *Preclosure*: Triggers final amortization for remaining unrecognized income
|
|
* *Charge-off*: Halts further amortization; the remaining deferred income is charged off
|
|
|
|
[NOTE]
|
|
====
|
|
Reversal Handling: If the original Capitalized Income transaction is reversed, all associated amortization transactions are also reversed via "Capitalized Income Amortization Adjustment" transactions.
|
|
====
|
|
|
|
=== Capitalized Income Adjustment
|
|
|
|
A Capitalized Income Adjustment transaction in Apache Fineract serves to reduce the balance of an existing capitalized income transaction.
|
|
|
|
==== Purpose
|
|
|
|
* Correct overcharged or misposted capitalized income amounts
|
|
* Reflect fee waivers or negotiated reductions
|
|
* Support backdated corrections if needed
|
|
|
|
==== Transaction Behavior
|
|
|
|
* It is a credit-type transaction, reducing the capitalized income balance
|
|
* Treated similarly to other credit transactions and follows a defined allocation strategy
|
|
* Can be backdated, but not dated before the original capitalized income transaction
|
|
|
|
==== Validation Rules
|
|
|
|
* The adjustment amount must not exceed the remaining amount (original capitalized income amount minus total previous adjustments)
|
|
* Adjustment is linked to a specific Capitalized Income transaction (by ID)
|
|
* Multiple adjustments can be made against the same original transaction
|
|
* Adjustments can be reversed if needed
|
|
|
|
==== Accounting Entries
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Scenario |Debit |Credit
|
|
|
|
|Adjustment ≤ unrecognized balance
|
|
|Deferred Income (Liability)
|
|
|Loan Portfolio (Asset)
|
|
|
|
|Adjustment > unrecognized balance
|
|
|Deferred Income (Liability)
|
|
|Loan Portfolio (Asset)
|
|
|===
|
|
|
|
==== Business Event Triggers
|
|
|
|
* Triggers "Capitalized Income Adjustment" event
|
|
* Updates loan balance and possibly loan status depending on impact
|
|
|
|
==== Impact
|
|
|
|
* Reduces amortization basis
|
|
* May modify future amortization amounts
|
|
* Repayment schedule is not affected directly unless recalculated manually
|
|
|
|
=== Capitalized Income Amortization Adjustment
|
|
|
|
A Capitalized Income Amortization Adjustment in Apache Fineract is a special transaction type used to reverse previously recognized income from capitalized income amortization.
|
|
|
|
==== Purpose
|
|
|
|
* Automatically generated when a Capitalized Income transaction is reversed or when backdated Capitalized Income Adjustment affects amortization balances
|
|
* Reverses all already recognized portions (amortized income) linked to the original Capitalized Income transaction
|
|
|
|
==== When It Occurs
|
|
|
|
* Created by daily amortization (COB) or final amortization (triggered on loan closure, charge-off, or by any backdated transaction that affects capitalized income balances)
|
|
* Reverses previously recognized income when amortization needs to be adjusted
|
|
* Restores Deferred Income balances and reverses income recognition
|
|
|
|
==== Accounting Entries
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Transaction Type |Debit |Credit
|
|
|
|
|Capitalized Income Amortization Adjustment
|
|
|Income from Capitalization (Income)
|
|
|Deferred Income (Liability)
|
|
|===
|
|
|
|
==== Key Characteristics
|
|
|
|
* *System-Generated Only*: Cannot be created manually by API or UI
|
|
* *Ensures Accounting Integrity*: Keeps amortized and unrecognized balances aligned after reversals
|
|
* *Non-monetary transaction - does not trigger balance changed or status update events*
|
|
|
|
==== Business Events
|
|
|
|
* Triggers a new business event: Capitalized Income Amortization Adjustment
|
|
|
|
== API Endpoints
|
|
|
|
=== Configure Capitalized Income on Loan Product
|
|
|
|
* *Endpoint*: `/loanproducts`
|
|
* *Method*: `POST`
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
...
|
|
"enableIncomeCapitalization": true, // Mandatory
|
|
"capitalizedIncomeCalculationType": "FLAT", // Mandatory when enabled
|
|
"capitalizedIncomeStrategy": "EQUAL_AMORTIZATION", // Mandatory when enabled
|
|
"capitalizedIncomeType": "FEE", // Mandatory when enabled
|
|
"deferredIncomeLiabilityAccountId": 123, // Mandatory when enabled
|
|
"incomeFromCapitalizationAccountId": 456 // Mandatory when enabled
|
|
}
|
|
----
|
|
|
|
=== Add Capitalized Income
|
|
|
|
* *Endpoint*: `/loans/{loanId}/transactions?command=capitalizedIncome`
|
|
* *Alternative Endpoint*: `/loans/external-id/{loanExternalId}/transactions?command=capitalizedIncome`
|
|
* *Method*: `POST`
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"transactionDate": "2025-05-01", // Mandatory
|
|
"dateFormat": "yyyy-MM-dd", // Mandatory
|
|
"locale": "en", // Mandatory
|
|
"transactionAmount": 100.0, // Mandatory
|
|
"paymentTypeId": 1, // Optional
|
|
"note": "Capitalized income fee", // Optional
|
|
"externalId": "CINCOME-001" // Optional
|
|
}
|
|
----
|
|
|
|
=== Get Capitalized Income Amortization Info
|
|
|
|
* *Endpoint*: `/loans/{loanId}/deferredincome`
|
|
* *Alternative Endpoint*: `/loans/external-id/{loanExternalId}/deferredincome`
|
|
* *Method*: `GET`
|
|
|
|
==== Response Body
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"capitalizedIncomeData": [
|
|
{
|
|
"amount": 50.0, // Total capitalized income amount
|
|
"amortizedAmount": 1.1, // Amount already amortized
|
|
"unrecognizedAmount": 48.9, // Amount not yet amortized
|
|
"amountAdjustment": 0.0, // Any adjustments made
|
|
"chargedOffAmount": 0.0 // Amount charged off (if applicable)
|
|
}
|
|
]
|
|
}
|
|
----
|
|
|
|
=== Add Capitalized Income Adjustment
|
|
|
|
* *Endpoint*: `/loans/{loanId}/transactions/{capitalizedIncomeTransactionId}?command=capitalizedIncomeAdjustment`
|
|
* *Alternative Endpoint*: `/loans/external-id/{loanExternalId}/transactions/{capitalizedIncomeTransactionId}?command=capitalizedIncomeAdjustment`
|
|
* *Method*: `POST`
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"transactionDate": "2025-05-01", // Mandatory
|
|
"dateFormat": "yyyy-MM-dd", // Mandatory
|
|
"locale": "en", // Mandatory
|
|
"transactionAmount": 50.0, // Mandatory
|
|
"paymentTypeId": 1, // Optional
|
|
"note": "Capitalized income fee", // Optional
|
|
"externalId": "CINCOMEADJ-001" // Optional
|
|
}
|
|
----
|
|
|
|
==== Response Body
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"resourceId": 1,
|
|
"resourceExternalId": "CINCOMEADJ-001"
|
|
}
|
|
----
|
|
|
|
=== Capitalized Income Template API (to retrieve limits)
|
|
|
|
* *Endpoint*: `/loans/{loanId}/transactions/template?command=capitalizedIncome`
|
|
* *Alternative Endpoint*: `/loans/external-id/{loanExternalId}/transactions/template?command=capitalizedIncome`
|
|
* *Method*: `GET`
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"paymentTypeOptions": [], // List of available payment types
|
|
"currency": {...}, // Currency configuration
|
|
"date": [2025, 5, 29], // Return the current date
|
|
"amount": 0 // Return the maximum amount that can be capitalized (approved amount - disbursed amount - capitalized income)
|
|
}
|
|
----
|
|
|
|
=== Capitalized Income Adjustment Template API (to retrieve limits)
|
|
|
|
* *Endpoint*: `/loans/{loanId}/transactions/template?command=capitalizedIncomeAdjustment&transactionId={capitalizedIncomeTransactionId}`
|
|
* *Alternative Endpoint*: `/loans/external-id/{loanExternalId}/transactions/template?command=capitalizedIncomeAdjustment&transactionId={capitalizedIncomeTransactionId}`
|
|
* *Method*: `GET`
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"paymentTypeOptions": [], // List of available payment types
|
|
"currency": {...}, // Currency configuration
|
|
"date": [2025, 5, 29], // Return the current date
|
|
"amount": 0 // Return the maximum amount that can be adjusted (capitalized income - adjustment)
|
|
}
|
|
----
|
|
|
|
== Accounting Entries
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Transaction Type |Debit |Credit
|
|
|
|
|Capitalized Income
|
|
|Loan Portfolio (Asset)
|
|
|Deferred Income (Liability)
|
|
|
|
|Capitalized Income Amortization
|
|
|Deferred Income (Liability)
|
|
|Income from Capitalization (Income)
|
|
|
|
|Capitalized Income Adjustment
|
|
|Deferred Income (Liability)
|
|
|Loan Portfolio (Asset)
|
|
|
|
|Capitalized Income Amortization Adjustment
|
|
|Income from Capitalization (Income)
|
|
|Deferred Income (Liability)
|
|
|===
|
|
|
|
== Business Events
|
|
|
|
=== Triggered for Capitalized Income
|
|
|
|
* `LoanCapitalizedIncomeTransactionCreatedBusinessEvent`
|
|
* `LoanBalanceChangedBusinessEvent`
|
|
|
|
=== Daily Amortization
|
|
|
|
* `LoanCapitalizedIncomeAmortizationTransactionCreatedBusinessEvent`
|
|
* `LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent`
|
|
|
|
=== Capitalized Income Adjustment
|
|
|
|
* `LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent`
|
|
* `LoanBalanceChangedBusinessEvent`
|
|
|
|
=== Reversal
|
|
|
|
* `LoanAdjustTransactionBusinessEvent`
|
|
|
|
== Database Structure
|
|
|
|
=== Configuration
|
|
|
|
==== Stored on Loan Product (`m_product_loan`)
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Field |Data Type |Description
|
|
|
|
|`enable_income_capitalization` |`BOOLEAN` |Enable capitalized income feature (default: `false`)
|
|
|`capitalized_income_calculation_type` |`VARCHAR` |Calculation method (ENUM: `FLAT`)
|
|
|`capitalized_income_strategy` |`VARCHAR` |Amortization strategy (ENUM: `EQUAL_AMORTIZATION`)
|
|
|`capitalized_income_type` |`VARCHAR` |Income type (ENUM: `FEE`, `INTEREST`)
|
|
|===
|
|
|
|
==== Stored on Loan (`m_loan`)
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Field |Data Type |Description
|
|
|
|
|`enable_income_capitalization` |`BOOLEAN` |Enable capitalized income feature (default: `false`)
|
|
|`capitalized_income_calculation_type` |`VARCHAR` |Calculation method (ENUM: `FLAT`)
|
|
|`capitalized_income_strategy` |`VARCHAR` |Amortization strategy (ENUM: `EQUAL_AMORTIZATION`)
|
|
|`capitalized_income_type` |`VARCHAR` |Income type (ENUM: `FEE`, `INTEREST`)
|
|
|===
|
|
|
|
=== Balances
|
|
|
|
==== On Loan
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Field |Data Type |Description
|
|
|
|
|`capitalized_income_derived` |`DECIMAL(19,6)` |Total capitalized income amount (nullable)
|
|
|`capitalized_income_adjustment_derived` |`DECIMAL(19,6)` |Total adjustment amount (nullable)
|
|
|===
|
|
|
|
==== Capitalized Income Balance (`m_loan_capitalized_income_balance`)
|
|
|
|
Each capitalized income has its own balance (1 row for each transaction)
|
|
|
|
[cols="3*"]
|
|
|===
|
|
|Field |Data Type |Description
|
|
|
|
|`id` |`BIGINT` |Unique identifier (Primary Key)
|
|
|`version` |`BIGINT` |Version for optimistic locking
|
|
|`loan_id` |`BIGINT` |Associated loan ID (Foreign Key, NOT NULL)
|
|
|`loan_transaction_id` |`BIGINT` |Associated loan transaction ID (Foreign Key, NOT NULL)
|
|
|`amount` |`DECIMAL(19,6)` |Capitalized income transaction amount (NOT NULL)
|
|
|`date` |`DATE` |Capitalized income transaction date (NOT NULL)
|
|
|`unrecognized_amount` |`DECIMAL(19,6)` |Amortization - not yet recognized amount (NOT NULL)
|
|
|`charged_off_amount` |`DECIMAL(19,6)` |Charged-off balance (nullable)
|
|
|`amount_adjustment` |`DECIMAL(19,6)` |Total adjustment amount (nullable)
|
|
|`created_by` |`BIGINT` |Audit field - user who created the record
|
|
|`created_on_utc` |`DATETIME` |Creation timestamp (UTC)
|
|
|`last_modified_by` |`BIGINT` |Last modifier user ID
|
|
|`last_modified_on_utc` |`DATETIME` |Last modification timestamp (UTC)
|
|
|===
|
|
|
|
=== Constraints
|
|
|
|
* **Foreign Key Constraints:**
|
|
- `loan_id` references `m_loan(id)`
|
|
- `loan_transaction_id` references `m_loan_transaction(id)`
|
|
- `created_by` references `m_appuser(id)`
|
|
- `last_modified_by` references `m_appuser(id)`
|
|
|
|
== Notes
|
|
|
|
[IMPORTANT]
|
|
====
|
|
* Capitalized income transactions support backdating
|
|
* Adjustment transactions must not predate the original capitalized income
|
|
* No automatic reversal is supported; must be handled manually via dedicated transactions
|
|
* Proper GL accounts must be set for Deferred Income and Income from Capitalization to enable this functionality
|
|
====
|