Proration and Premium Allocation
The Proration plugin controls how premiums, commissions, taxes, and fees are prorated when coverage periods are reduced by either endorsement or cancellation.
In an endorsement, existing peril characteristics are split and premium is prorated to determine the amount to be allocated to the segment before the split timestamp (this is called the “pre-split amount.”) For non-premium bearing endorsements, this also determines the post-split amount (equal to the original amount minus the pre-split amount).
For example, if a characteristics object that covers January 1 2021 to January 1 2022 and has $1000 of allocated premium is endorsed on July 1, approximately half of the premium should be allocated to the January 1 to July 1 segment. You may want to have more nuance:
Prorate by months: The premium will be 6 / 12 * 1000, or $500.00
Prorate by days: The premium will be 181 / 365 * 1000, $495.89
Prorate by milliseconds: The premium (in a daylight savings timezone in the northern hemisphere) will be 15634800000 / 31536000000 * 1000, or $495.78
The proration plugin can handle these and similar scenarios.
Cancellations work similarly but post-split characteristics will not be generated because the coverage is terminated.
Note
The plugin also handles “holdbacks” for retaining extra amounts beyond the proration calculation. This is useful for scenarios like cancellation short rates. See the Proration Holdbacks topic for details.
Plugin Details
Enabling the plugin
To enable the plugin, follow the steps in the plugins topic.
The plugin script
The proration plugin requires a plugin script called prorater.js
that exports a function called getProrationResult
.
The data object
The data
object passed to the plugin looks like this:
requiredsegmentSplitTimestamp timestampitems [ProrationPluginItem]operation string creation | endorsement | renewal | cancellation | reinstatement | withdrawal | actionpaymentScheduleName stringpolicy PluginPolicyInfotenantTimeZone stringoptionalcancellationCategory stringcancellationComments stringcancellationType stringoldPaymentScheduleName string
requiredlocator stringpolicyholderLocator stringproductName stringoriginalContractStartTimestamp timestampcurrency stringoptionalquoteLocator string
Each proration item looks like this:
requiredid stringsegmentEndTimestamp timestampsegmentStartTimestamp timestampamount numberfollowingAmount numbertype string premium | tax | commission | fee | technicalPremium | premiumHoldback | taxHoldback | feeHoldback | commissionHoldback | premiumHoldbackReversal | taxHoldbackReversal | feeHoldbackReversal | commissionHoldbackReversaloptionalperilName stringperilCharacteristicsLocator stringfieldValues map<string,[string]>commissionLocator stringcommissionRecipient stringfeeLocator stringfeeName stringtaxLocator stringtaxName string
Note
The id
property of the proration item is a transient value used to key the plugin input to the response. It is not saved in the database nor is it consistent across calls.
Note
Numeric values sent to the plugin are passed as strings to ensure no loss of precision.
The Plugin Response Object
The plugin requires that the response from the plugin looks like this:
requireditems [ProrationResponseItem]
Where each ProrationResponseItem
looks like this:
requiredid stringholdbackAmount numberproratedAmount numberoptionalholdbackMetadata string
Validation
The response from the plugin must conform to the following criteria:
The
id
for each ProrationResponseItem must match that in the corresponding ProrationPluginItem in the input.An output item’s
proratedAmount
must not exceed theamount
of the input item.The
holdbackAmount
is required. Set its value to0
if you do not want to create a holdback.You may include
holdbackMetadata
only if you are also including a positiveholdbackAmount
in theProrationResponseItem
.
Sample Script (Simple)
This script implements the proration plugin using linear (millisecond-based) proration.
function getProrationResult(data)
{
return { items: data.items.map(item => prorateItem(data, item)) };
}
function prorateItem(data, item)
{
return {
id: item.id,
proratedAmount: round2(parseFloat(item.amount) * getLinearFraction(data, item)),
holdbackAmount: 0
};
}
function getLinearFraction(data, item)
{
return (parseInt(data.segmentSplitTimestamp) - parseInt(item.segmentStartTimestamp))
/ (parseInt(item.segmentEndTimestamp) - parseInt(item.segmentStartTimestamp));
}
function round2(num)
{
return Math.round(num * 100) / 100.0;
}
exports.getProrationResult = getProrationResult;
Sample Script (Advanced)
This script implements the proration plugin using linear proration for upfront
, every_week
, and every_two_weeks
payment schedules, and monthly proration for other schedules.
Note
This Zip file
contains the required library and associated support files for this example.
const { DateCalc } = require('../lib/DateCalc.js');
function getProrationResult(data)
{
destringifyData(data);
let dateCalc = new DateCalc(data.tenantTimeZone);
let fractionFn;
switch (data.paymentScheduleName)
{
case "full-pay":
fractionFn = getLinearFraction;
break;
case "every_week":
case "every_two_weeks":
fractionFn = getDayFraction;
break;
default:
fractionFn = getMonthlyFraction;
break;
}
return { items: data.items.map(item => ({ id: item.id,
proratedAmount: round2(fractionFn(data, item, dateCalc) * item.amount),
holdbackAmount: 0 })) };
}
function getDayFraction(data, item, dateCalc)
{
return dateCalc.dayCountRatio(item.segmentStartTimestamp,
data.segmentSplitTimestamp,
item.segmentEndTimestamp,
true);
}
function getMonthlyFraction(data, item, dateCalc)
{
return dateCalc.socotraMonthCountRatio(item.segmentStartTimestamp,
data.segmentSplitTimestamp,
item.segmentEndTimestamp,
true);
}
function getLinearFraction(data, item, dateCalc)
{
return dateCalc.linearRatio(item.segmentStartTimestamp,
data.segmentSplitTimestamp,
item.segmentEndTimestamp,
true);
}
function destringifyData(data)
{
data.segmentSplitTimestamp = parseInt(data.segmentSplitTimestamp);
for (const item of data.items)
{
item.amount = parseFloat(item.amount);
item.followingAmount = parseFloat(item.followingAmount);
item.segmentStartTimestamp = parseInt(item.segmentStartTimestamp);
item.segmentEndTimestamp = parseInt(item.segmentEndTimestamp);
}
}
function round2(num) { return Math.round(num * 100) / 100.0; }
exports.getProrationResult = getProrationResult;
Legacy Proration
If the proration plugin is not implemented, the system will behave as follows:
During endorsements and cancellations, Socotra allocates premium to each coverage period using a single method, so all calculations are consistent.
If periods start and end at 00:00:00 (midnight), actual-millisecond proration is the same as actual-day
When allocating premium to billing periods, Socotra assigns the same amount to each whole billing period and then uses actual-millisecond proration for partial billing periods.
For up-front, weekly, and every other week payment schedules, Socotra will use milliseconds-based proration. For other schedules, Socotra will use monthly-based proration based on the number of months (see below).
Month Counting
Consider the following scenario where a cancellation is processed before the end of the policy term:
The policy period is from June 13th for a one year term
The total premium for the year is $1200
The policyholder requests a cancellation effective September 19th
Resulting calculations:
The remaining coverage period is from June 13th until September 19th, which is 3 months and 6 days.
Since September 13th to October 13th is 30 days, the coverage period is 3 + 6/30 = 3.2 months long.
3.2 months will be used for monthly proration.