Overview
Parameters
Name | Type | Default | Description |
---|---|---|---|
blocked_by_bank | Instance | false | Blocked by bank parameter. Rejects all transactions (both incoming and outgoing) if true. (Options: false, true) |
blocked_by_client | Instance | false | Blocked by client parameter. Rejects all outgoing transaction if true. (Options: false, true) |
deposit_interest_wht_account | Template | DEPOSIT_INTEREST_WHT_ACCOUNT | Internal account for paid interest tax. Note: Should be removed when Postings library will be implemented. |
main_account | Instance | - | Money could be transferred only from and to defined main account. When saving account is closed all remaining money is moved to this account. |
auto_renewal | Instance | - | Auto-renewal of locked pocket after tenure is at the end. (Options: false, true) |
tenure | Instance | - | Tenure of locked pocket. |
locked_interest_application_second | Template | 0 | The second of the minute at which profit for locked account is applied. |
locked_interest_application_minute | Template | 10 | The minute of the hour at which profit for locked account is applied. |
locked_interest_application_hour | Template | 1 | The hour of the day at which profit for locked account is applied. |
rounding_difference_account | Template | ROUNDING_DIFFERENCE_ACCOUNT | Internal account for rounding difference when closing pockets. Note: Should be removed when Postings library will be implemented. |
interest_application_second | Tempalte | 0 | The second of the minute at which profit is applied. |
interest_application_minute | Tempalte | 5 | The minute of the hour at which profit is applied. |
interest_application_hour | Template | 1 | The hour of the day at which profit is applied. |
interest_accrual_second | Template | 0 | The second of the minute at which profit is accrued. |
interest_accrual_minute | Template | 0 | The minute of the hour at which profit is accrued. |
interest_accrual_hour | Template | 1 | The hour of the day at which profit is accrued. |
bonus_interest_rate | Instance | 0 | The annual rate of the pocket to be applied after the interest rate based on pocket's interest rates. Used as a reward from completion of a challenge. |
template_locked_interest_rate_per_tenure | Template | {"3": "0.01", "6": "0.02", "9": "0.05", "12": "0.10",} | Annual interest rate for locked pocket with tenure. Format is json map with tenure length as key and interest rate as value. |
template_locked_interest_rate | Template | 0.06 | Annual interest rate for locked pocket |
template_unlocked_interest_rate | Template | 0.04 | Annual interest rate for unlocked pocket |
debug | Instance | - | Debug parameter used for rescheduling of the events. |
denomination | Template | PHP | Default denomination. |
reduced_interest_rate | Global | 0.0001 | Reduced interest rate applied for pockets. |
interest_limit | Global | 0.01 | Interest limit applied for pockets. |
interest_tax_rate | Global | 0.2 | Tax rate applied for accrued interests. |
pocket_type | Instance | unlocked | Pocket type defining if pocket is unlocked or locked |
Addresses
Name | Rounding digits number | Description |
---|---|---|
DEFAULT | 2 | |
INTEREST | 5 | |
WHT | 5 | |
MONTHLY_INTERESTS | 2 | |
LOCKED_BONUS | 5 | |
LOCKED_BONUS_TAX | 5 | |
LOCKED_BONUS_TAX_CONTRA | 5 |
Transactions
Bank transaction code | Event | Name | Debit account | Credit account | Product | Note |
---|---|---|---|---|---|---|
Daily interest accrual (unlocked) | Interest accrual | Deposit interest cost account | Saving account/ INTEREST | Saving account interest | Shown in interest history as gained interest | |
Withholding tax accrual | Saving Account/ WHT | Deposit interest WHT | Saving account interest | Shown in interest history as paid tax | ||
Monthly interest application (unlocked) | Interest application | Saving account/ INTEREST | Saving account/ DEFAULT | Saving account interest | Shown in transaction history | |
Tax deduction | Saving account/ DEFAULT | Saving account/ WHT | Saving account interest | Shown in transaction history | ||
Daily interest accrual (locked) | Interest accrual | Deposit interest cost account | Saving account/ INTEREST | Saving account interest | Shown in interest history as gained interest | |
Locked bonus separation | Saving account/ INTEREST | Saving account/ LOCKED BONUS | Saving account interest | Shown in interest history as gained interest bonus | ||
Withholding tax accrual | Saving Account/ WHT | Deposit interest WHT | Saving account interest | Shown in interest history as paid tax | ||
Tracking of accrued tax from locked bonus | Saving Account/ LOCKED_BONUS_TAX_CONTRA | Saving Account/ LOCKED_BONUS_TAX | Saving account interest | |||
Monthly interest application (locked) | Interest application | Saving account/ INTEREST | Saving account/ MONTHLY_INTERESTS | Saving account interest | Probably shown in settlement? | |
Tax deduction | Saving account/ MONTHLY_INTERESTS | Saving account/ WHT | Saving account interest | Probably shown in settlement? | ||
End of tenure (locked) | Bonus payment | Saving account/ LOCKED BONUS | Saving account/ INTEREST | Saving account interest | ||
Compound interest payment | Saving account/ MONTHLY_INTERESTS | Saving account/ INTEREST | Saving account interest | |||
Interest payment | Saving account/ INTEREST | Saving account/ DEFAULT | Saving account interest | Shown in transaction history | ||
Tax payment | Saving account/ DEFAULT | Saving account/ WHT | Saving account interest | Shown in transaction history | ||
Tax payment in case more tax from bonus payment is returned | Saving account/ WHT | Saving account/ DEFAULT | ||||
Reset of accrued tax from locked bonus | Saving Account/ LOCKED_BONUS_TAX | Saving Account/ LOCKED_BONUS_TAX_CONTRA | Saving account interest | |||
Unlocking | Bonus lost | Saving account/ LOCKED BONUS | Deposit interest cost account | Saving account interest | Shown in interest history as lost interest bonus | |
Compound interest payment | Saving account/ MONTHLY_INTERESTS | Saving account/ INTEREST | Saving account interest | |||
Interest payment | Saving account/ INTEREST | Saving account/ DEFAULT | Saving account interest | Shown in transaction history | ||
Tax payment | Saving account/ DEFAULT | Saving account/ WHT | Saving account interest | Shown in transaction history | ||
Tax payment if returned bonus tax is greater than remaining tax | Saving account/ WHT | Saving account/ DEFAULT | Saving account interest | Shown in transaction history | ||
Returned tax from lost bonus | Saving account/ WHT | Deposit interest WHT | Saving account interest | |||
Reset of accrued tax from locked bonus | Saving Account/ LOCKED_BONUS_TAX | Saving Account/ LOCKED_BONUS_TAX_CONTRA | Saving account interest | |||
Closing | Same as Unlocking | |||||
Move money back to main account | Saving account/ DEFAULT | Main account/ DEFAULT | Shown in transaction history | |||
Move remainders to rounding difference internal account | ||||||
Withdrawal from unlocked pocekt | Money payment | Saving account/ DEFAULT | Main account/ DEFAULT | Shown in transaction history | ||
Rebalance form interest | Saving account/ INTEREST | Saving account/ DEFAULT | Saving account interest | Shown in transaction history | ||
Partial taxes paid | Saving account/ DEFAULT | Saving account/ WHT | Saving account interest | Shown in transaction history |
Events
Name | Scheduled at | Description |
---|---|---|
ACCRUE_INTEREST | Daily at 01:00:00 |
|
APPLY_ACCRUED_INTEREST | First day of month at 01:05:00 |
Blocking
There are two types of blockings - initiated by the bank and initiated by the customer. Both are enabled by setting associated instance parameter to true. If blocked_by_bank is enabled, all transactions (both outgoing and incoming) are rejected. If blocked_by_client is enabled, all outgoing transactions are rejected.
There are transactions that should not be rejected even when blocked (both types) - ones related to interests (Interest accrual, Withholding tax accrual, Interest application, Tax deduction) and payment of subscription fee (TODO: fill name here).
Withdrawal of interests
We allow customer to withdraw their interests at any time. We still need to have special address for that because they should be used as principal during interest accrual.
When customer withdraws money via Money payment transaction we allow him/her to put DEFAULT address into negative balance up to INTEREST + WHT. In post posting hook move interest money to DEFAULT address (via Rebalance form interest) and pay tax (via Partial taxes paid). If transferred money is less than available interest, only proportional part of INTEREST and WHT addresses are taken.
available_balance = balance on INTEREST address + balance on WHT address used_balance = min(available_balance, withdrawn_balance) proportion = used_balance / available_balance moved_interest = proportion * balance on INTEREST address moved_tax = proportion * balance on WHT address
Allow only self transfer
Only transfer from and to associated main account should be allowed in pre posting hook. Although standard postings does not show other side of the transaction, we should provide this in additional information via postings library.
Paying debt from saving account
It is possible to pay debt from the saving account. If the account is unlocked, then it is considered a standard withdrawal, if the account is locked first it is unlocked and then processed like unlocked one. Debt manager is preferring taking money from unlocked ones.
Interests and withholding tax
In Unlocked saving account
Should work exactly like in main account.
Accrual
Interest and withholding tax are accrued on daily basis via transactions Interest accrual and Withholding tax accrual on INTEREST and WHT addresses during ACCRUE_INTEREST event. The amount is computed as:
daily_interest_rate = template_interest_rate / number of days in given year daily_reduced_interest_rate = reduced_interest_rate / number of days in given year principal = balance on DEFAULT address full_interest = min(interest_limit, principal) * daily_interest_rate reduced_interest = max(principal - interest_limit,0) * daily_reduced_interest_rate total_interest = full_interest + reduced_interest total_wht = total_interest * interest_tax_rate # Results accrued_interest = round_down(total_interest, 5) accrued_wht = round_down(total_wht, 5)
Application
On first day of the month, the interests are given to the customer (Interest application transaction) and customer virtually pays the tax (Tax deduction transaction, from financial perspective, we pay it for him/her and he did not receive it). Both of these transactions are necessary because of statements and transaction history. Both of the transaction have amount rounded to two decimal places, because on DEFAULT address we should not have number with higher precision.
applied_interest = round_down(balance on INTEREST address, 2) deduced_wht = round_down(balance on WHT address, 2)
In Locked saving account
Because of requirement to “reduce interests to amount as if the account was unlocked whole time” in case of premature unlocking we had to implement complex logic in locked saving accounts.
Accrued interest is split into multiple parts - interest of simulated unlocked account, compound interests of simulated unlocked accounts (each month interest are added to principal in unlocked accounts but not in locked ones) and bonus for locking interests. The interest accrued daily is constant whole time (if customer did not add funds) but the split into previously mentioned addresses changes in time.
Taxes are dealt in similar way as in unlocked pocket. The only difference is that we track how much was paid for locked bonus because in case of premature unlocking we need to return it to the customer. This is implemented via two technical addresses LOCKED_BONUS_TAX_CONTRA and LOCKED_BONUS_TAX
Accrual
limited_interest(principal, interest) = min(interest_limit, principal) * interest + max(principal - interest_limit,0) * reduced_interest_rate // same as in unlocked one) total_interest = limited_interest(balance on DEFAULT, locked_interest_rate(tenure)) unlocked_interest = limited_interest(balance on DEFAULT + balance on MONTHLY_INTEREST, unlocked_interest_rate) locked_interest_bonus = total_interest - unlocked_interest unlocked_tax = unlocked_interest * tax_rate locked_bonus_tax = locked_interest_bonus * tax_rate # Results accrued_interest = round_down(total_interest, 5) accrued_bonus = round_down(locked_interest_bonus - locked_bonus_tax, 5) accrued_wht = round_down(unlocked_tax + locked_bonus_tax, 5) accrued_tracking_Tax = round_down(locked_bonus_tax, 5)
Monthly application due to simulation of unlocked account
applied_interest = round_down(balance on INTEREST address, 2) deduced_wht = round_down(balance on WHT address, 2)
End of tenure
locked_bonus = balance on LOCKED_BONUS compund_interest = balance on MONTHLY_INTERESTS total_interest = balance on INTEREST bonus_payment = locked_bonus compound_interest_payment = compund_interest interest_payment = round_down(locked_bonus + compund_interest + total_interest, 2) tax_payment = round_down(balance on WHT address, 2) reset_tax_from_bonus = balance on LOCKED_BONUS_TAX
Locking and unlocking
During locking no money movement is done. Unlocking is different because locked bonus is lost, that means we have to return payed tax as well.
locked_bonus = balance on LOCKED_BONUS compund_interest = balance on MONTHLY_INTERESTS total_interest = balance on INTEREST bonus_tax = balance on LOCKED_BONUS_TAX tax = balance on WHT bonus_payment = locked_bonus compound_interest_payment = compund_interest interest_payment = round_down(locked_bonus + compund_interest + total_interest, 2) tax_payment = round_down(balance on WHT address, 2) reset_tax_from_bonus = bonus_tax bonus_lost = locked_bonus compound_interest_payment = compund_interest interest_payment = round_down(compund_interest + total_interest, 2) tax_payment = round_down(tax - bonus_tax, 2) // Based on sign of result one of the tax transactions is used returned_tax_from_lost_bonus = bonus_tax reset_of_accrued_tax_from_locked_bonus = bonus_tax
Closing
Closing is basically unlocking and sending money to associated main account. Before closing all addresses with precision up to 5 digits must be made exactly 0. This is done via money transfer to rounding difference internal account.