Overview

Of late, community has been building features like 'Workflow using datatables', 'Triggered SMS', 'Notifications' etc, also we have many more features in roadmap like 'Flagging of Accounts', 'Data Driven Authorisation', 'Tasks Framework' etc. In all of these features, there is one commonality, which is to listen on a business event on an entity and perform either additional validation or processing. Drawback being that on each such business event each of these additional processing/validation results in a Database query to check if any additional processing or validation is required. The more such features we continue to add, the more we are slowing down the system by way of adding more and more DB calls whether required or not. Also we are adding more and more new APIs and related processing code which in my view is mundane as well as time consuming. This design proposes to generalize all such features under one single framework and API modelling, thus reducing the calls to DB and also improving the turn-around time for feature addition.

Design Approach

Platform

Business Event Notifier is an existing feature that notifies interested listeners to be able to act on any business event on any entity. A Business Event internally represented by Entity/Action/PreOrPostEvent information. Approach is to provide a framework around which any processors/validators can be added to be able to act on any Business Event.

Consider the below Class and ER diagram:

A generic framework implementation provides template/create/read/delete capabilities thru an unified or generalised API endpoint '/bep/{processor}', where {processor} represent different features like 'sms', 'workflow', 'datadrivenautorisation' etc.

Against a unique triplet of "Business Event/Product Id/Processor", metadata required for processing by individual processor would be managed by the framework in generic JSON string format. A null ProductId as part of triplet would mean the default processing.

AbstractBusinessEventProcessor is abstraction for different processors possible. Any concrete implementor of this Abstract class potentially add a new processing/validation capability.

Any concrete implementor of AbstractBusinessEventProcessor has to do the following:

  1. Identify themselves against a processor name by overriding 'processorName' property. PS: A concrete implementation in AbstractBusinessEventProcessor makes sure the instance is registered with BusinessEventProcessorRegistry against the 'processorName'.
  2. Provide implementation of getTemplate, validateData methods for the metadata it expects for its processing. BusinessEventProcessorWritePlatformService will take help of these methods to be able to take the matadata and save in JSON format.
  3. Provide implementation of processBusinessEvent method which will be invoked by BEPEventListener for any relevant Business Event. This is where actual processing or validation as needed by the feature will be performed.

BusinessEventProcessorAPIResource and BusinessEventWritePlatformService would utilise the implementations in point 1 and 2 above to manage the metadata required by individual processors in generic way.

A single BEPEventListener would listen for all the Business Events Notification, retrieve all the business event processor information, invoke all relevant feature processors for that business event using the processBusinessEvent method implementation. Since there would be single Business Event Listener who gets all the relevant processors in one shot from the Database, multiple DB calls by each feature would be avoided.

Following Sequence Diagrams explain how the framework works for Create and Process Business Event use cases:

UI

A single UI screen can handle the definition for all the features

OR

There can be individual screen (reusing same implementation with just a different {processor} name end point) for processor definition of individual feature.

Advantages

  • Single Business Event Listener and Single Database call to retrieve all the processor info in one shot
  • No clutter of new APIs
  • No or reduced Database design and new tables for each feature
  • Since the metadata is stored as JSON, data for each different scenario within a processor is limited only to its validation logic/capability

Example Design for Flagging of Accounts feature on top of this framework

In the simplest of terms, flagging of accounts feature allows to tag a Savings or Loan account with a flag. The flags are custom definable by the MFI. Also MFI can define what actions are not allowed when based on flags.

Implemenation Notes

  1. Define a Code-Value Mapping attribute and allow MFI to define their own Flags for Savings and Loans seperately
  2. Add new command API on savings and Loan APIs to tag accounts with Flags
  3. Implement AbstractBusinessEventProcessor as AccountFlaggingValidator
    1. Template method takes the options for Flags from Code-Value and also identifies entity and business events that can be processed
    2. Validate method validates that the code-values are from the definition in note.1
    3. Process method throws InvalidActionForFlaggedAccountException if it finds the business event is not allowed for the account flag.
    4. JSON data would be as follows

{

    entity : "loan",

    event : "waive interest",

    isPreEvent : true,

    processor : "accountFlaggingValidator",

    data : {

        blockedForFlags : ["XYZ", "ABC"]

    }

}

Example Design for Data Driven Authorisation

In the simplest of terms, Data Driven Authorisation enforces the user to have specific role before being able to perform an action. For eg, Loan Approval of amount more than 10000 should be done by user with role "Manager"

Implementation Notes

  1. We might not need any additional modifications to existing APIs
  2. Implement AbstractBusinessEventProcessor as DataDrivenAuthorisationValidator
    1. Template method shall return available roles as options and provide entities and actions for which this is supported
    2. Validation will make sure the range of amount is complete and non-overlapping and also role/entity/action are valid
    3. Process method throws InvalidAuthorisationForGivenDataException when the validation fails
    4. JSON data structure would be as follows:

{

    entity : "loan",

    event : "approval",

    isPreEvent : true,

    processor : "dataDrivenAuthorisationValidator",

    data : {

        [

            {

             "fromAmount": 10000,

             "toAmount":1000000,

             "roleId": 10

            },

            {

             "fromAmount": 1000001,

             "toAmount": 1000000000,

             "roleId": 20

            }

        ]

    }

}

 

 

 

  • No labels