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:

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 the originalAmount. This charge will have its isNew property equal to false.

  • A negative charge that reverses the original positive charge. Its amount is usually the negative of the positive charge’s originalAmount.

  • 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:

PaymentSchedulePluginData
required
productName string
coverageStartTimestamp timestamp
coverageEndTimestamp timestamp
defaultPaymentTerms PaymentTermsResponse
operation string newBusiness | endorsement | renewal | reinstatement | cancellation | manual | feeAssessment
paymentScheduleName string
tenantTimeZone string
plannedInvoices [FutureInvoiceResponse] (deprecated)
transactionType string newBusiness | endorsement | renewal | reinstatement | cancellation | manual | feeAssessment (deprecated)

optional
oldPaymentScheduleName string

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.

PaymentSchedulePluginCharge
required
coverageStartTimestamp timestamp
coverageEndTimestamp timestamp
amount number
originalAmount number
previouslyInvoicedAmount number
amountCurrency string
chargeId string
isNew boolean
policyModificationLocator string
type string premium | tax | commission | fee | technicalPremium | premiumHoldback | taxHoldback | feeHoldback | commissionHoldback | premiumHoldbackReversal | taxHoldbackReversal | feeHoldbackReversal | commissionHoldbackReversal

optional
perilName string
perilCharacteristicsLocator string
category string new | previously_invoiced | carried_forward
commissionLocator string
commissionRecipient string
feeLocator string
feeName string
perilLocator string
taxLocator string
taxName string
  • The isNew property is set to false for charges that have been scheduled before. These charges will also have originalAmount and previouslyInvoicedAmount properties. The amount for these charges is net of amounts on other invoices that remain in force.

  • The coverageStartTimestamp and coverageEndTimestamp 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:

PaymentSchedulePluginResponse
PaymentSchedulePluginInstallmentResponse
required
issueTimestamp timestamp
dueTimestamp timestamp
startTimestamp timestamp
endTimestamp timestamp
installmentFees [InstallmentFee]
writeOff boolean
PaymentSchedulePluginInvoiceItemResponse
required
amount number
chargeId string
InstallmentFee
required
amount number
description string
feeName 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.