SaFi Bank Space : account-manager technical documentation

Object model

Service

Description

AccountAuthorizationService

Responsible of authorization of controller endpoints with accountId as input.

DevelopmentController

Contains endpoints that should not be used by both FE and other micro-services. It should be mainly for testing purposes and/or resolving of issues. All endpoints here should be authorized for “other microservice only” although it should not be used in such way.

Contains endpoints to reschedule events in TM that manages interest accrual and application. Note: if no time is provided, it schedules the event in 2 seconds. Do not call this endpoint again until the event finished its processing, otherwise it will not be processed again. That means, do not call this endpoint more than every 10 seconds.

Currently contains endpoint for manual transaction. This was just fast solution for EPFS build and it will not be possible to build it in future because of correct accounting and postings validation. It should be changed for 2 customer reconciliation transactions (one to give customer money, one to get it from him) and all other reconciliations with 3rd party providers should have separate transactions.

AccountController

Contains endpoints that works for both main and saving accounts. That currently includes:

  • Getting account by accountId or customerId

  • Management of blocking of the accounts for given customer (both bank and customer variants)

MainAccountController

Contains endpoints for operations specific only to main account. That currently includes:

  • Getters - single main account by customerId and account number

  • Create new main account

  • Edit main account

  • End-of-day balance of given main account (Used by statement-manager)

MainAccountService

Service responsible for for all operations specific to main account. In addition to main account specific processing of Entity, balances and parameters change it provides methods for:

  • Creation of new main account - each customer can have only 1 main account. Also including creation of plan for it and part of its association. So for given customer we first create both main account and plan at the same time in pending state. Because we are not sure in which order they will be created, we listen on creation events of both of them and when second arrives, we associate newly created main account with newly created plan. When event regarding successful association is listened, we set state of both of them to active. Uses AccountNumberService for generation of account number.

  • Edit operation - including validations and other checks. Does not include TM because at the moment, you can change only name which is stored in the database. If you will need to add parameter for which TM is source of truth, see SavingAccountService how it should be done.

This service also manages when snapshots and audit logs are created.

AccountNumberService

Service responsible for generation of account numbers. This service just randomly provides the number, it does not checks for uniqueness.

SavingAccountController

Contains endpoints for operations specific only to saving account. That currently includes:

  • Get all saving accounts by customerId

  • 2x Creation of new saving account (locked and unlocked have separate endpoints)

  • 2x Edit of saving account (locked and unlocked have separate endpoints)

  • Locking and unlocking of saving account

  • Maximum number of saving accounts given customer can have

  • Closing of the saving account

  • End-of-day balance of given saving account (Used by statement-manager)

  • Uploading of image for given saving account

  • Endpoint for setting up of bonus interests (Used by engagement-manager)

SavingAccountService

Service responsible for for all operations specific to saving account. In addition to saving account specific processing of Entity (including specific processing of locked and unlocked, balances and parameters change it provides methods for:

  • Creation of both locked and unlocked versions - attachment to plan is done in AccountService

  • Edit operations for both locked and unlocked versions - including validations

  • Locking and unlocking of saving account. Also manages unlocking of locked pocket at the end of tenure if auto-renewal is not set. This is done based on event sent from TM upon reaching end of tenure because smart-contracts can not change their parameters.

  • Notification - End of tenure of locked account (two variants based on if the auto-renewal is enabled), target amount reached for unlocked pocket, target date reached for unlocked pocket. The latest one is implemented as outbox pattern - airflow job triggers our endpoint which finds all saving account with reached target date for which message was not sent. The list is sent one by one in multiple messages through Kafka and our service is also the consumer. Upon consumption, the message is sent and this is also flagged in the database.

  • Account image management - using AccountImageService

  • Calculation of expected profit of locked account - profit up to this date + expected future profit based on principal, interest rate and number of remaining days. Note: please double-check if the calculation is correct because of changes in addresses

This service also manages when snapshots and audit logs are created.

AccountImageService

Service used for uploading of saving accounts image to GCS and its signed retrieving. Used by SavingAccountService.

AccountSearchService

Service for filtering criteria for accounts. Usually used in Controllers. It should search AccountRepository and pass found AccountEntity into AccountService.

AccountService

Service responsible for account processing, when you do not know what is the given account type. Namely for:

  • Processing AccountEntity into Account model (most often requested by AccountSearchService). Does shared extraction from AccountEntity and then calls processing method on MainAccountService or SavingAccountService based on account type.

  • Processing change in balances, parameters or status. In those use-cases, this class performs shared processing such as caching and then use MainAccountService or SavingAccountService for further processing based on affected account type.

  • Association of a plan to newly created accounts (called by PlanListener)

StateService

Service responsible for management of account blocking (both customer and bank ones) and management of account states (this might be not used anymore)

OutputService

Responsible for preparing and sending notifications via output-manager.

ParametersService

Service responsible for management of instance parameters of all accounts. We consider the source of truth for financial parameters the TM thus this service serves for caching of them (to reduce workload of TM, it fetches them only when necessary). Names and types of all parameters are managed by user of this class, this class only works with string keys and values.

When setting a parameter, the request is forwarded into TM using TMClient. When the change is applied in TM, a Kafka event is emitted and processed by AccountService which calls method on ParameterService to cache it (in AccountEntity.parametersCache).

When reading a parameter, user must provide a accountId and may provide parameterCache. If the cache is not provided, it is red from the database based on accountId. If the cache in database is empty, it is fetched from TM and cached.

GlobalInterestRateService

Service responsible for getting and setting of all interest related global and template parameters. Namely:

  • Main account interest rate

  • Unlocked saving account interest rate

  • Locked saving account interest rates in form of pairs tenure + interest rate

  • Global reduced rates (limit + interest rate)

  • Withholding tax rate

This service uses ParameterService to achieve that - that means this service is owner of names of those parameters

GlobalInterestRateController

Contains endpoints for getting and setting of all interest related global and template parameters mentioned in GlobalInterestRateService.

ProductVersionIdCacheService

Service responsible for caching of current versionId for each account type.

Each account type have associated smart-contract of which multiple versions might be present in TM at same time (i.e. during upgrades). All version have separate template parameters thus we need to keep track what is the most recent one to properly get and set parameters.

TemplateParameterService

Service responsible for caching of template and global parameters. Works in same way as ParametersService. It caches parameters under version ids and requires this parameter upon reading and writing. Global parameters are stored under version 0. (Don’t ask me, it is nasty TM stuff)

MessagingService

Service responsible for sending snapshots of all entities in this micro-service. Each entity have service to prepare the data (although it might be nice to somehow move all functionality in them and remove this service). Namely:

  • GlobalInterestRateSnapshotService

  • GlobalParametersSnapshotService

  • MainAccountSnapshotService

  • SavingAccountSnapshotService

BalanceService

Service responsible for caching and processing of balances. Works very similar to ParameterService - when balances of our accounts changes, this change is stored in AccountEntity. Upon reading, first they are taken from the database. If they are not present, they are requested via REST call from TM (and cached). Balances from TM are not the ones we are presenting to the customer - TM provides us with balances on different addresses / phases. Similar to ParameterService, the user of this service defines their balance structure - each balance is aggregation of some combination of addresses and phases.

Also this service takes care of end of day balances of each account - for each day it stores the last balance with no entries for days when no change happened. That means, to retrieve balance for specific day we need to find last recored before that date (including given date)

PostingApiListener +

PostingHandler

We had a lot of implementation attached to listening of postings thus we created shared handler which calls processing of different postings in different contexts.

Note: should be changed for Postings library one.

InterestHistoryService

Service for statistics related to interest and withholding tax transaction. Stores all interest and withholding tax postings and provides different types of aggregations.

InterestHistoryController

Controller containing endpoints related to interest history, mainly exposes different types of aggregations implemented in InterestHistoryService

AccrueInterestPostingHandler

Handler for daily interest accrual transactions. Inserts data in InterestHistoryService

ApplyAccruedInterestPostingHandler

Handler for interest application and emit event with enriched data. Used in transaction-history-manager.

Note: Currently works only for main accounts, saving accounts have missing specification because of unclear settlement

InterestTaxDeductionPostingHandler

Handler for withholding tax application. Emit event with enriched data. Used in transaction-history-manager.

Note: Currently specified only for main accounts, saving accounts have missing specification because of unclear settlement. For some reason this filter is not there.

ClosePocketPostingHandler

Handler for transaction that moves money from saving account to main account upon is closure. Emit event with enriched data. Used in transaction-history-manager.

PostingService

Service performing manual transaction - This was just fast solution for EPFS build and it will not be possible to build it in future because of correct accounting and postings validation. It should be changed for 2 customer reconciliation transactions (one to give customer money, one to get it from him) and all other reconciliations with 3rd party providers should have separate transactions.

ManualTransactionPostingHandler

Handler for manual transaction. Emit event with enriched data. Used in transaction-history-manager.

Attachments:

~drawio~617861f4a9897100705af77c~Untitled Diagram.drawio.tmp (application/vnd.jgraph.mxfile)
~drawio~617861f4a9897100705af77c~Untitled Diagram.drawio.tmp (application/vnd.jgraph.mxfile)
Untitled Diagram.drawio (application/vnd.jgraph.mxfile)
Untitled Diagram.drawio.png (image/png)
~Untitled Diagram.drawio.tmp (application/vnd.jgraph.mxfile)
Untitled Diagram.drawio (application/vnd.jgraph.mxfile)
Untitled Diagram.drawio.png (image/png)