Part 2: Using Tables and Formulas

Implementing Premium Computation

In this chapter we will implement the premium computation for our home contents products.

We will extend our model to include the attributes and methods shown in the following figure.

model computation
Figure 1. The Premium Computation is Captured in the Model

Each coverage is subject to an annual base premium. An annual base premium is the net premium payable per annum, insurance tax and surcharges not included. The contract’s annual base premium is the total value of all coverages' annual base premiums.

The contract’s netPremiumPm is the net premium due per payment. It is the result of the annual base premium plus an installment surcharge (if the premium is not paid annually), divided by the number of payments, e.g., 12 in the case of monthly payment.

The grossPremiumPm is the gross premium due per payment, i.e. including insurance tax. It amounts to the netPremiumPm times 1+insurance tax rate. For the sake of simplicity, we will assume in this tutorial that the installment surcharge is always 3% and the insurance tax is always 19%.

Your next task will be to create the new attributes in the classes HomeContract and HomeBaseCoverage. We will leave the HomeExtraCoverages for the next chapter. All attributes are derived (cached) and of the type Money. Because they are cached, derived attributes, Faktor-IPS generates one member variable and one getter method for each attribute.

All premium attributes are computed by the computePremium() method of the HomeContract class. This method is able to compute all premium attributes of the contract, as well as the annual base premium of the coverages. To do this, of course, it uses the computeAnnualBasePremium() method of the coverages.

You can now create these methods on the second editor page for the HomeContract and HomeBaseCoverage classes. The dialog box for editing a method signature is shown in the next figure.

dialog methodsignature
Figure 2. Edit Dialog for Method Signatures

Generating code offers more advantages for relationships and attributes than for methods. Hence, methods can, of course, also be defined directly in the source code.

The following code snippet shows the premium computation implementation in the HomeContract class. For the sake of clarity, we will implement the computation of the annual base premium and the netPremiumPm in two separate, private methods that will be written directly in the source code, but not added to the model.

/**
 * @generated NOT
 */
@IpsGenerated
public void computePremium() {
    computeAnnualBasePremium();
    computeNetPremiumPm();
    Decimal taxMultiplier = Decimal.valueOf(119, 2); // 1 + 19% tax rate
    grossPremiumPm = netPremiumPm.multiply(taxMultiplier, RoundingMode.HALF_UP);
}

private void computeAnnualBasePremium() {
    annualBasePremium = Money.euro(0, 0);
    HomeBaseCoverage baseCoverage = getHomeBaseCoverage();
    baseCoverage.computeAnnualBasePremium();
    annualBasePremium = annualBasePremium.add(baseCoverage.getAnnualBasePremium());
    /*
     * TODO: When extra coverages are added to the model, their premium of course
     * has to be added here as well.
     */
}

private void computeNetPremiumPm() {
    if (paymentMode == null) {
        netPremiumPm = Money.NULL;
        return;
    }
    if (paymentMode.intValue() == 1) {
        netPremiumPm = annualBasePremium;
    } else {
        Decimal factor = Decimal.valueOf(103, 2); // 1 + 0.03 surcharge for non-annual payment
        netPremiumPm = annualBasePremium.multiply(factor, RoundingMode.HALF_UP);
    }
    netPremiumPm = netPremiumPm.divide(paymentMode.intValue(), RoundingMode.HALF_UP);
}

Premium Computation for Coverages

For our home contents insurance, the annual base premium computation has to be implemented at the coverages level.

Technically, the annual base rate for the base coverage is computed like this:

  • From the rates table, determine the rate per 1000 Euro sum insured.

  • Divide the sum insured by 1000 Euro and multiply with the premium rate.

As this formula is not subject to change, we will implement it directly in the HomeBaseCoverage Java class. For extra coverages, we will allow the business users to define the annual base premium using computation formulas.

We already defined the method computeAnnualBasePremium() in the HomeBaseCoverage class at the beginning of this chapter. Open the Java class HomeBaseCoverage in the editor and implement the method as follows:

/**
 * @generated NOT
 */
@IpsGenerated
public void computeAnnualBasePremium() {
    RateTableHome table = getRateTable();
    RateTableHomeRow row = null;
    if(table!=null) {
        row=table.findRow(getHomeContract().getRatingDistrict());
    }
    if(row==null) {
        annualBasePremium=Money.NULL;
        return;
    }
    Money si = getHomeContract().getSumInsured();
    Decimal premiumRate = row.getPremiumRate();
    annualBasePremium = si.divide(1000, RoundingMode.HALF_UP).multiply(premiumRate, RoundingMode.HALF_UP);
}

We will test the premium computation by extending our JUnit test once more.

@Test
public void testComputePremium() {
    // Create a new HomeContract with the products factory method
    HomeContract contract = compactProduct.createHomeContract();
    // Set contract attributes
    contract.setZipcode("45525");
    contract.setSumInsured(Money.euro(60_000));
    contract.setPaymentMode(2);
    // Get the base coverage type that is assigned to the product
    HomeBaseCoverageType coverageType = compactProduct.getHomeBaseCoverageType();
    // Create the base coverage and add it to the contract
    HomeBaseCoverage coverage = contract.newHomeBaseCoverage(coverageType);
    // Compute the premium and check the results
    contract.computePremium();
    // rating district III => premiumRate = 1,21 annualBasePremium = sumInsured /
    // 1000 * premiumRate = 60000 / 1000 * 1,21 = 72,60
    assertEquals(Money.euro(72, 60), coverage.getAnnualBasePremium());
    // contract.annualBasePremium = baseCoverage.annualBasePremium
    assertEquals(Money.euro(72, 60), contract.getAnnualBasePremium());
    // netPremiumPm = 72,60 / 2 * 1,03 (semi-annual, 3% surcharge) = 37,389 => 37,39
    assertEquals(Money.euro(37, 39), contract.getNetPremiumPm());
    // grossPremiumPm = 37,39 * taxMultiplier = 37,39 * 1,19 = 44,49
    assertEquals(Money.euro(44, 49), contract.getGrossPremiumPm());
}