# Inheritance and Versioning

BriteLines has two important functionalities: Inheritance and Versioning. A Line can be straightforward, with just a collection of Risk Types with single Version. Or a Line can be complex, with Risk Types inherited across multiple Products (Inheritance) and changes that exist in multiple Versions with different effective dates (Versioning).

# Inheritance

Inheritance allows models to share common definition ancestors. This allows common data elements to be defined in an upstream template Line of Business (LOB) product, then utilized repeatedly through inheritance into specific LOBs products that extend the base product. For example, there might be Homeowners product that defines 80% of all HO business, but then inherit HO-Common into HO-2, HO-3, and HO-5, each of which introduces new item, rates, and rules.

# Example

  • HO-Common
    • HO-2
      • HO-2-MO
      • HO-2-KS
      • HO-2-OK
    • HO-3
      • HO-3-MO
      • HO-3-KS
      • HO-3-OK
    • HO-5
      • HO-5-MO
      • HO-5-KS
      • HO-5-OK

Each Line can have multiple Products, in above example LOB is Homeowners with root Product HO-Common and other Products HO-2, HO-3 and HO-5 inherited from HO-Common Product. This is handled via lines.Product model.

# Versioning

Line, Risk Type and all entities of Risk Type are bound to a Version. A Version is composed of a name and an effective date, the effective date tells when a certain Line of Business, Risk Type, or Entity is going live/effective from.

Once a Line of Business or Risk Type is live, users should not be able make changes to it. Instead, users will create a new Version with a new effective date and make changes there.

Consider following Line effective from 1/1/2018:

Auto Line of Business:
    Vehicle Risk Type:
        VIN - Field
1
2
3

Later the user decides to change the label of a Data Field from VIN to something more verbose like Vehicle Identification Number. In this case, a new Version with a new effective_date should be created and we should duplicate the VIN Field with updated label.

So going from one Version to another Version requires duplication of data. In BriteCore Classic we duplicate the whole Line of Business instead of just duplicating the Data Field.

The goal here is to avoid as much duplication as possible and make changes as fast as possible.

To support this we have split some of our entity's models into two: a version model and an instance model.

# Version Model

Version model mostly only contains pointers so that when going from one version to another version all we have to do is to duplicate bunch of pointers. A version model holds pointers for:

  • RiskType (ForeignKey)
  • RiskTypeVersion (ForeignKey)
  • Version (ForeignKey)
  • Instance Model (ForeignKey)
  • Other Many-to-Many relations for entity

RiskFieldVersion, RateTableVersion, RateTableSourceVersion, CalculationVersion and RiskItemVersion are version models

# Instance Model

Instance models contain data points like name or label. These models will only be duplicated when a change happens to instance-level data.

RiskField, RateTable, RateTableSource, Calculation and RiskItem are instance models.

# DB Schema

DB Schema

# Examples

  • Consider we have an enum data Field with 5 options and the user would like to add a new option. This will require us to duplicate the RiskFieldVersion model, add new option in options (many-to-many), and that's it. It still uses the previous instance model (RiskField) as there was no change in data points like name, label, etc. and we have avoided duplicating them unnecessarily.

# Gotchas!

  • Only duplicate Version and Instance model when we are explicitly making a change which affects them. Going from one Version to another can still use previous instances as long as there is no change happening.
  • Avoid ForeignKey relationships at the Instance model level. Duplicating Instances means that all direct relations also need to be duplicated unnecessarily.
  • From API perspective, end users do not need to know how we are handling versioning on the backend. A single API call contains all data to create/update a risk field and Version and Instance model will be created/updated respectively (if needed).