Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Note

This module was created by the https://openimis.atlassian.net/wiki/spaces/OP/pages/2161147938/Project+D1+Formal+Sector+Support?pageId=2161147938 the concept and business logic where develop for that scope but the rules are used in other context such as the Project: 2021.T3 Payment Layer

version

version

date

comment

changes

1

06-2021

Project: D1 Formal Sector Support

2

08-2021

Project: 2021.T3 Payment Layer

remove acceptance criteria form FS

cleaning FS specifics

move calculation rules in a specific table

add filter based on type and sub-type

Concepts

The rules for the Formal Sector the the calculation of the policy value or payment to HF can be complex and evolving. Therefore, the "Formal Sector" solution should bring flexibility, to avoid complete redesign and databases change when a parameter to define the contribution value is changed.
To bring that flexibility, the solution described here uses a Calculation Rule (the Calculation Rules are defined in additional openIMIS modules extending the Calculation Module). This module is defining a framework to design calculations and to manage their activation and versioning in openIMIS. This solution will deliver a Calculation Module that takes the income (on the level of the Contract’s insuree) and a rate (on the level of the Contribution Plan) as parameters, make the calculation and updates the payment value of the Contract’s insuree.


The value of the parameters will be saved as a JSON string in the json_ext field.

Later, this module could be used as a framework to create event-based actions

Business process: example of the formal sector

This module will use a "generic contribution" to get the required parameters and the json_ext database field will be used to save the parameters (generic backend feature). Finally, a signal will trigger the calculation action. 

...

Code Block
my_signal= dispatch.Signal(providing_args=["instance","user"])

Use cases (specific to formal sector)

UC14-1: add a new Calculation rule (needs to change the openimis.json).
UC14-2: use the contribution_fe to select a calculation rule.
UC14-3: use the contribution_fe to display the parameters required by multiple calculation for an object.
UC14-4: replace a calculation rule.
UC14-5: remove a calculation rule.

Authorities

This module won't have ad-hoc authorities.

Entities

class CalculationRules

  • CalculationClassName: str

  • Status: int

  • Description: str

  • Priority : int

  • dateValidFrom : date

  • dateValidTo : date

class CalculationRulesDetails (HistoryModel)

  • CalculationRulesUUID: uuid

  • Status: int

  • ClassName: str

  • Main: bool

  • Params: Dict

  • ClassParams: List[CalculationParam]

class CalculationParam

...

Type: str

...

rights: Dict

...

Relevance: str

...

conditions: str

...

Detailed design

Calculations Backend Module

...

relevance and condition are Nice to have.

Abstract Methods defined in rules

active_for_object

ready

check_calculation

calculate

get_linked_class

convert

Methods

...

getRuleName(classname)

NEED TO BE DEFINED ON ABSTRACT CLASS LEVEL

return an object “CalculationRules”

getRuleDetails(classname)

...

defined in abstract class

get_uuid

return UUID

get_version

return version

get_calculation_rule_name

return calculation rule name

get_rule_name(cls, sender, class_name, **kwargs):

return rule object is classname is part of impacted class

get_description

return description

get_impacted_class_parameter

return impacted_class_parameter

get_rule_details(classname)

For object in listObject

if object.class == classname

return object

...

get_paramteres(ClassName, instance)

...

#className is the class name of the object where the calculation param need to be added

...

return a list only with rule details that matches step 1 and 2

...

run_calculation_rules(instance, context)

...

this function will be register to the module signal via the ready function if the rule is active

...

2 if activeForObject(instance)

calculate(instance)
ready()

NEED TO BE DEFINED ON RULE LEVEL

This method makes sure the calculation is registered in the calculation table (if not the line should be added with "inactive status") and register the signals only if it is active

all rules, if active will have to register to the signal sent by “getRuleDetails”

activeForObject(object, context)

NEED TO BE DEFINED ON RULE LEVEL

this method will contains the checks if the calculation need to be executed for the object on that context. the default context will be:

  • create

  • update

  • delete

  • submit

  • amend

  • replace

  • check

  • validate

This function is required because the same class can have different calculation based on the object members values (like product ….)

(TDC)calculateEvent(sender, instance, user, **kwargs)

NEED TO BE DEFINED ON RULE LEVEL

  • This method runs the calculation based on the object sending the signal, this means that the relationship with the other item required for the calculation could be found from the object sending the signal. (e.g., link to the product can be found in the policy as foreign key.)

  • This function should call first the activeForObject method, the context will depend on the calling event, if the fuction return true the calcuation needs to be run, in other case the even handling will stop

  • the calculate(*args) function

  • Signal need to be set up on the ready function to call it

checkCalculation(instance)

NEED TO BE DEFINED ON RULE LEVEL

this function will get the calculation relative the instance

1- get instance class

2- if class known then return check that the linked calculation is the current one

calculate(instance, *args)

NEED TO BE DEFINED ON RULE LEVEL

Function that will do the calculation based on the parameters

getLinkedClass(List[classname])

NEED TO BE DEFINED ON RULE LEVEL

...

run_convert(instance, from, to, **argv)

execute the conversion for the instance with the first rule that provide the conversion (see get_convert_from_to)

get_convert_from_to()

get the possible conversion, return [calc UUID, from, to]

Module function/Service

NEED TO BE DEFINED ON MODULE LEVEL

...

get_rule_details(classname)

this function will send a signal and the rules will reply if they have object matching the classname in their list of object

...

merge listruledetails and result_signal

return listruledetails

...

calculate(instance, context)

for all calculation rules (send signal):

runCalculationRules(instance, context)

no return

...

get_parameters(ClassName, instance)

#className is the class name of the object where the calculation param need to be added

...

return the ruleDetails that are valid to classname and related to instance

...

get_linked_class(List[ClassName] = None)

#List[ClassName] is send from FE, by checking the class used in page where the user ave access if None (in case too difficult to do on the FE) all liked class will be retrieve

...

return all the returnListClass

Authorities

Calculation (prefix 153)

  • search → 153 001

  • update → 153 003 (to activate or not)

...