Payment Schedule Plugin
Overview
The payment schedule plugin provides a way for configurers to write custom rules for generating payment schedules. This gives fine control for situations like:
Non-standard payment schedule, such as “monthly for the first 9 months out of a year-long policy term”
Consolidating small value invoices into one
Scheduling invoices on certain dates or days of the week
Special logic for endorsement or reinstatement invoicing
It also has a facility for changing the payment schedule for an existing policy.
Important
Use of this plugin can cause unexpected proration calculations on endorsements and cancellations. If this feature is enabled, you should also implement the Proration Plugin.
Note
This feature is not compatible with legacy cancellations and reinstatements, and requires enabling feature flags (see below). Unpredictable behavior may result otherwise. To enable the latest cancellations and reinstatements feature, be sure to include a cancellations.json
file in the configuration for that product.
See the Plugins topic for information about enabling the plugin and setting the script path.
Enabling the plugin
To enable the plugin, follow the steps in the plugins topic. Also, turn on the Payment Schedule Plugin feature flag in config.json
:
{
"timezone": "America/Los_Angeles",
"currency": "USD",
"features": {
"property.installments.plugin.enabled": true,
"property.proration.plugin.enabled": true,
"property.quotes.for.endorsements.and.renewals.enabled": true
}
}
To prevent proration problems, also enable the proration plugin and its corresponding feature flag.
The property.installments.plugin.enabled
and property.proration.plugin.enabled
feature flags will not be needed after an upcoming release.
Script
The script is defined in a file called installments.js
with exported function createInstallments
. This file should be under the scripts branch you wish to use, for example /scripts/master/installments.js
.
A simple sample script is below, and another more detailed example is here.
Both of these samples will work with all the policy transaction types that are subject to installments:
New Business
Endorsement
Renewal
Reinstatement
Manual Changes (See Manual Payment Plan Changes)
Charges
The data.charges
array contains the information needed to ensure all receivables are properly invoiced. Each charge reflects a receivable amount for an individual peril’s premium or commission, or a tax or fee.
Typically on new business or renewals each peril will be represented by one charge. For endorsement, there are usually four charges per peril:
A positive charge representing the original overall amount of premium for the affected policy segment. This could be net of previously invoices amounts, such that the
amount
+previouslyInvoicedAmount
equals theoriginalAmount
. This charge will have itsisNew
property equal tofalse
.A negative charge that reverses the original positive charge. Its
amount
is usually the negative of the positive charge’soriginalAmount
.A positive charge representing the prorated premium for the segment before the endorsement.
A positive charge representing the calculated premium for the segment after the endorsement.
The last three charges in this sequence will have isNew
equal to true, previouslyInvoicedAmount
equal to zero, and its amount
equal to its originalAmount
.
For example, in a year-long policy with one peril we might have the following charge passed to the plugin for the new business event:
Start |
End |
Amount |
Original Amount |
Prev Inv Amount |
---|---|---|---|---|
Jan 1 2022 |
Jan 1 2023 |
$1200 |
$0 |
$0 |
And after endorsement on March 1 with $200 on previously generated invoices and a $400 premium increase, the charges passed to the plugin might look like this:
Start |
End |
Amount |
Original Amount |
Prev Inv Amount |
---|---|---|---|---|
Mar 1 2022 |
Jan 1 2023 |
$1000 |
$1200 |
$200 |
Jan 1 2022 |
Jan 1 2023 |
($1200) |
$0 |
$0 |
Jan 1 2022 |
Mar 1 2022 |
$300 |
$0 |
$0 |
Mar 1 2022 |
Jan 1 2023 |
$1300 |
$0 |
$0 |
Note
When amounts have been previously invoiced, the coverageStartTimestamp
for the charge is adjusted to show the coverage start for the uninvoiced portion. To get the full time range for the charge, use the charge’s policyModificationLocator
to lookup the associated policy modification, and use that modification’s effectiveTimestamp
.
Taxes, fees, and commissions are handled similarly to the peril premium case described above.
Write offs
To write off certain charges or portions of charges, put them on a separate set of installments and set the writeOff
flag for those installments to true
. This can be useful, for example, in putting extra cents onto a separate written-off invoice so that the totals for other invoices remain constant.
Written off invoices will have settlementStatus
of settled
and settlementType
of writtenOff
.
The Plugin data Object
The data
object passed to the plugin looks like this:
requiredproductName stringcoverageStartTimestamp timestampcoverageEndTimestamp timestampcharges [PaymentSchedulePluginCharge]defaultPaymentTerms PaymentTermsResponseoperation string newBusiness | endorsement | renewal | reinstatement | cancellation | manual | feeAssessmentpaymentScheduleName stringpolicy PolicyResponsetenantTimeZone stringtransactionType string newBusiness | endorsement | renewal | reinstatement | cancellation | manual | feeAssessment (deprecated)optionaloldPaymentScheduleName string
The plannedInvoices
property describes what the invoice schedule was planned before the transaction being processed. Those planned invoices will be replaced with the installments returned from the plugin. Your plugin logic may examine the original planned invoice for hints on how to schedule the new installments.
The coverageStartTimestamp
and coverageEndTimestamp
properties describe the period covered by the transaction:
For new business, it is the period from the policy effective date to the expiration date.
For an endorsement, it is the period from the endorsement effective date to the policy end.
For a renewal, it is the period from the renewal start to the new policy end.
For a reinstatement, it is the entire policy from start to the end after reinstatement.
requiredcoverageStartTimestamp timestampcoverageEndTimestamp timestampamount numberoriginalAmount numberpreviouslyInvoicedAmount numberamountCurrency stringchargeId stringisNew booleanpolicyModificationLocator stringtype string premium | tax | commission | fee | technicalPremium | premiumHoldback | taxHoldback | feeHoldback | commissionHoldback | premiumHoldbackReversal | taxHoldbackReversal | feeHoldbackReversal | commissionHoldbackReversaloptionalperilName stringperilCharacteristicsLocator stringcommissionLocator stringcommissionRecipient stringfeeLocator stringfeeName stringperilLocator stringtaxLocator stringtaxName string
The
isNew
property is set tofalse
for charges that have been scheduled before. These charges will also haveoriginalAmount
andpreviouslyInvoicedAmount
properties. Theamount
for these charges is net of amounts on other invoices that remain in force.The
coverageStartTimestamp
andcoverageEndTimestamp
properties for the individual charge describe the period covered by the charge. This can be different from the overall transaction coverage period.
The plugin is required to return a response in this form:
requiredinstallments [PaymentSchedulePluginInstallmentResponse]
requiredissueTimestamp timestampdueTimestamp timestampstartTimestamp timestampendTimestamp timestampinstallmentFees [InstallmentFee]invoiceItems [PaymentSchedulePluginInvoiceItemResponse]writeOff boolean
requiredamount numberchargeId string
requiredamount numberdescription stringfeeName string
Validation
The response from the plugin must conform to the following criteria:
For each charge in the
data.charges
array, the sum of the invoice item amounts across all installments must exactly equal the charge’s amount.Installments must cover the coverage period with no gaps or overlaps. This means that the first installment’s start must be at the beginning of the coverage period, and each installment’s end timestamp must match the start timestamp of the next installment, except for the last installment, where the end timestamp should equal the coverage end.
The end timestamp of each installment must be greater than or equal to its start timestamp.
Important
On cancellation invoicing, each of the new installment(s) must have their startTimestamp
and endTimestamp
each align with a the start and end of a previously created installment. This is a known issue which will be fixed in an upcoming release.
Simple Example
This is the simplest possible implementation, which is a full-pay plan. It puts all the charges for each transaction on a single invoice:
function createInstallments(data)
{
let invoiceItems = data.charges.map(ch => ({
amount: parseFloat(ch.amount),
chargeId: ch.chargeId
}));
return { installments: [{
dueTimestamp: data.coverageStartTimestamp,
issueTimestamp: data.coverageStartTimestamp,
startTimestamp: data.coverageStartTimestamp,
endTimestamp: data.coverageEndTimestamp,
invoiceItems: invoiceItems,
writeOff: false
}]};
}
exports.createInstallments = createInstallments;
Note
A more detailed example for new business with multiple supported plans is here.
Note
This plugin only affects future invoices. Changing already-generated invoices is not yet supported, but we are planning an upcoming feature to refactor existing invoices.