This page contains high level information about the product logic of overdraft along with explanation of its implementation in Thought machine and description of postings usage. The overview of implemented business logic is as following:

  1. Open an overdraft for given customer’s main account

    • performed as funds transfer from internal overdraft account to customer’s main account

  2. Customer has 30 days (grace period) to spend the overdraft

    • customer can use overdraft only on selected transaction types

  3. At the end of grace period we automatically try to repay the overdraft

    • if customer had enough money, the overdraft (or the spent part of overdraft) is repaid and closed

    • if customer did not use overdraft at all, the overdraft is returned and closed

    • if customer did not have enough money to return the overdraft, proceed with next steps

  4. If customer failed to repay the overdraft after 30 days, they are being charged an overdraft fee and the grace period is extended to 60 days

    • if customer is not immediately able to pay the fee, a debt is recorded for the overdraft fee

    • if customer still had some unused overdraft left, it can be used to (partially) repay the debt for the overdraft fee

  5. At the end of after grace period (after 60 days), if overdraft fee was not paid off and overdraft was not repaid, try again to repay the overdraft

    • if customer has no enough money for that, create a debt for the overdraft

  6. After 60 days, overdraft penalties for late overdraft are being issued regularly (by Loxon for example). If customer doesn’t have any money and is not able to pay for the penalties, create a debt for each unpaid penalty.

  7. Once customer has finally enough funds, when new funds arrive to the account, immediately “lock them” and use them to repay the overdraft with its debts according to their priority (done by debt manager):

    1. Overdraft penalties

    2. Overdraft fee

    3. Overdraft (principal)


Illustration of the state process:

Following documentation contains details about implementation of the solution.

TM overdraft product implementation

Overdraft is on smart contract level implemented as a feature of main account product (source code in SaFi repository). Since overdraft is a part of main account, overdraft is just an extension of its functionality mapped to a separate OVERDRAFT address on the main account, not a separate account, and its logic is a part of source code of main account smart contract (see more implementation details here).

The overdraft service logic (microservice and workflows) is a part of loan-manager service.

Overdrafts debts are managed as a part of main account by debt manager supervisor.

Overdraft funds

When an overdraft is open, customer receives additional funds to their main account which can be used for specific allowed payment types. The source of funds is an internal account dedicating for borrowing / paying off overdrafts. Each request to open an overdraft is first validated against allowed overdraft amounts for given customer and their risk params.

Available overdraft funds are stored on separate address on main account: OVERDRAFT, which represents current amount of borrowed overdraft that has not been spent yet by customer.

This address is initiated at the time of overdraft opening, with the amount equal to total amount of opened overdraft by custom posting from an internal account to the address.

Pre posting validation

When there is an outgoing payment from customer’s main account, following steps are being performed in order to decide if the outgoing posting should be accepted or not (see pre_posting_code() function of main account smart contract to see the actual implementation ):

  1. available overdraft amount (from the OVERDRAFT address) is first fetched (if any)

  2. postings of the outgoing payment are validated against their allowance for overdraft.

  3. the next step is to calculate the minimum balance allowed for main account after processing the outgoing payment. This is either 0 by default (since we do not allow main account to fall into negative balance) or - (minus) amount of available overdraft, if the payment was validated as allowed for overdraft in the previous step.

  4. lastly, outgoing payment is validated against minimum allowed balance. If it does not cause the main account to fall under allowed minimum balance (which is either 0 or the negative amount of available overdraft), it is accepted.

Post posting validation

Overdraft usage - rebalancing

After an outgoing payment was accepted and took an effect on the main account balance, post_posting_code() hook is run to perform additional actions. For overdraft, this mostly applies to identifying, if an overdraft was used to perform the payment, and rebalancing the negative amount on main account from overdraft:

  1. we first identify if the outgoing payment caused main account to fall into negative balance. If not, no action is required

  2. if yes, we compute the amount from overdraft needed to rebalance the negative balance - which is usually equal to abs(main_account_balance)

  3. to rebalance the negative amount on main account, an internal posting in then created to send the rebalancing amount (abs(original_main_account_balance - outgoing_funds)) from OVERDRAFT address to DEFAULT address of main account

Overdraft repayment

Post posting code also contains posting handling logic for overdraft repayment. If there is an outgoing posting with inquiry to repay the borrowed overdraft, overdraft amount which was not originally spent by customer is also additionally returned to main account’s DEFAULT address so that customer only pays for the amount of overdraft they they really spent.

Overdraft debt management

We are able to record three types of overdraft related debts (ordered by repayment priority):

  • overdraft penalties, which are penalties issued by Loxon after 60 days of unreturned overdraft (after “after grace period”)

  • overdraft fee, which is a one time fee applied at the end of grace period (after 30 days) after customer failed to return the overdraft on 30th day

  • overdraft principal - which is not returned yet overdraft

The overdraft debts have each a separate debt address on main account:

Overdraft debt type

Debt type label

Main account debt address

Overdraft penalties

overdraft_penalty

overdraft_penalties_debt

Overdraft fee

overdraft_fee

overdraft_fees_debt

Overdraft principal

overdraft

overdraft_debt

and their abs(balance) is at any time equal to the current debt of customer.

Important thing to note is that the unspent overdraft itself can be used to (partially) repay the overdraft related debts. Therefore:

  • if customer fails to return the overdraft amount after 30 days, overdraft fee is charged. If the customer is not able to pay for the overdraft fee, overdraft fee debt is returned. However, at this point, if customer still had some partial amount of unused overdraft, this amount is used to (partially) repay the debt for overdraft fee.

  • if customer still fails to return the overdraft even after 60 days, debt for overdraft principal is recorded. However, if at this point the customer still had some small amount of overdraft left (and unused), all the remaining overdraft here is used to partially pay of the overdraft principal debt.

  • Technically it is impossible to use unspent overdraft for overdraft penalty debt payment, because that would mean that we had enough overdraft money to repay first both overdraft fee / principal debt (which is not possible, because otherwise we would not be in a debt). Moreover, in such case it would be impossible to issue the overdraft penalty, because overdraft and overdraft fee would be paid off and overdraft closed.

To see more details about how overdraft debt are recorded and repaid, see documentation of Debt manager. Overdraft is automatically integrated with debt manager as long as its main account is assigned under a plan supervised by debt manager.

Detailed break down of overdraft debt payment scenario along with all the required postings is explained here:

Overdraft penalties

At the end of after grace period overdraft workflow tries to return the overdraft and evaluates, if everything is paid off. If not, then we enter the “after 60 days period”, where overdraft penalties for overdue overdrafts are issued by Loxon. From the implementation point of view, there are two endpoints in loan manager - /loan/overdraft/{accountId}/penalty/rebalance and /loan/overdraft/{accountId}/penalty/repay which allow to record / directly repay (decrease) overdraft penalties and are callable from external services. Therefore, the overdraft penalties are not issued automatically by loan manager, but we expect the penalties to be issues by creating requests to given endpoints.

Transaction types and postings

Each overdraft related posting is labeled by its transaction type, which defines its function. All the postings have following format:

account_from: ...
address_from (custom postings only): ...
account_to: ...
address_to (custom postings): ...
amount: ...
instruction_details: {
  transaction_type: TRANSACTION_TYPE,
  account_id / overdraft_id: uuid, (unique identifier of overdraft)
  additional details, custom to given transaction type
}

1. Internal overdraft postings

Following table contains overview of all transaction types used for overdraft with a brief description:

Transaction type

Instruction type

Source

Description

OVERDRAFT_IMBURSEMENT

custom

overdraft workflow

Posting that moves funds from internal overdraft account to OVERDRAFT address of main account and represents opening of an overdraft / top up.

OVERDRAFT_REPAYMENT

transfer

overdraft workflow

Posting moving funds from DEFAULT address of main account to overdraft internal account and represents the repayment (returning) of an overdraft.

“OVERDRAFT_RETURN” (not currently filled in instruction details, can be added (postings library))

custom

main account smart contract

The previous posting is being followed by an additional internal custom posting instruction generated by main account smart contract, which also returns unused overdraft from OVERDRAFT address of main account to DEFAULT address of main account, so customer only returns the part of overdraft they actually spent

“OVERDRAFT_REBALANCE” (also currently not being filled in instruction details, but should have been added by posting library)

custom

main account smart contract

Posting from OVERDRAFT address to DEFAULT address of main account that rebalances the amount of used overdraft

OVERDRAFT_FEE

transfer

overdraft workflow

Posting from DEFAULT address of main account to internal overdraft fees account, which serves the function of issuing an overdraft fee to a customer

CLAIM_PAYMENT
- with additional details of “claim_type” set to either “overdraft”, “overdraft_fee” or “overdraft_penalty”, and “account_id” set to current account for mapping

transfer

overdraft workflow

Posting from DEFAULT address of main account to internal unpaid overdraft / fees accounts, which serves the role of claiming a debt for given overdraft entity. We are trying to at least partially pay for given overdraft / fee / penalty by this posting, and if not enough money is available, debt is recorded. Serves as an input for debt manager.

CUSTOMER_DEBT_REBALANCE
- with additional details of “debt_type” set to either “overdraft”, “overdraft_fee” or “overdraft_penalty”, and “account_id” set to current account for mapping

custom

debt manager (main account supervised by debt mgr)

Internal posting produced by debt manager from <debt_type>_address to DEFAULT address of main account, which serves the function of recording a debt for given overdraft / fee / penalty. By listening to this posting, overdraft workflow gets an information about a new debt being recorded / increased and can react accordingly.

CUSTOMER_DEBT_REPAY
- with additional details of “debt_type” set to either “overdraft”, “overdraft_fee” or “overdraft_penalty”, and “account_id” set to current account for mapping

custom

debt manager (main account supervised by debt mgr)

Internal posting produced by debt manager from DEFAULT to <debt_type>_address address of main account, which serves the function of repayment of a debt for given overdraft / fee / penalty. By listening to this posting, overdraft workflow gets an information about an existing debt being repaid / lowered and can react accordingly.

DIRECT_DEBT_REPAY with additional details of “override_debt_payment“ set to “overdraft_penalty”

transfer

overdraft workflow

This incoming funds posting from any source to DEFAULT address of main account is a tool how to directly repay or increase existing debt for OVERDRAFT_PENALTY (even if customer currently has other debt with higher repayment priority).

2. Payments allowed for overdraft

Validating if a transaction is allowed for overdraft

Usage of overdraft is allowed only for a limited number of transaction types. There is a fixed list of payments transaction types defined as product level (“template-level”) parameter for main account smart contract (parameter name is overdraft_allowed_transaction_types` ), used for validation, if an outgoing transaction can be (partially) covered by overdraft. Current default value of the parameter is set to ["INTERNAL_TRANSACTION", "BILL_PAYMENT", "CARD_PAYMENT", "OVERDRAFT_FEE", "CARD_INQUIRY"], meaning that the listed transaction types are allowed to be (partially) paid off by overdraft:

- INTERNAL_TRANSACTION
- BILL_PAYMENT
- CARD_PAYMENT
- OVERDRAFT_FEE
- CARD_INQUIRY

If a given outgoing posting is allowed for overdraft (if its transaction type contains one of the listed types) is then verified by extracting transaction type from postings instruction details and testing if it appears in the list:

"instruction_details": {
  "transaction_type": "BILL_PAYMENT",
  ...
}

Modifying the list of overdraft allowed transactions

If you need to add a new transaction type to be allowed for an overdraft (or remove an existing allowed transaction type, so it is not allowed for overdraft anymore), you need to perform multiple steps:

  • if you are creating a new transaction type, which was not used in SaFi before, add the transaction type first to /common/tm-client/src/main/kotlin/ph/safibank/tm/util/TmConstants.kt as a new item in TrasactionType enum

  • if you don’t need to create and deploy a new version of main account product, then use CoreAPI to update the template parameter overdraft_allowed_transaction_types`, by making a PUT request to /v1/product-versions/{product_version_id}:updateParams endpoint, as described in TM docs.

  • if you would also like to update the main account product to a new version and create a new default value for the overdraft_allowed_transaction_types parameter, then update the default values of the parameter in /tm-contracts/smart-contracts/main/features/overdraft.py and also in /tm-contracts/deploy/resource_templates/main_account_smart_contract_version.resource.template.yaml and deploy the product. Note that you might still need to perform the previous step to upgrade the param value for previously created accounts.

Attachments:

Overdraft and debt manager postings (2).xlsx (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
image-20221128-223513.png (image/png)