Functions

A dynamic logic function is the most generic type of dynamic logic: it can have one or more input arguments and return different types of output. A dynamic logic function is used to extend default behavior in certain areas. Each usage of dynamic logic functions is described in a separate paragraph below.

Adjustment Rule

An adjustment rule specifies which combination of procedures, modifiers and/or diagnoses leads to an adjustment of the allowed amount. A formula can be applied to adjust the normal calculation. Typically, the claim line will provide the number of units and the provider pricing clause will provide the percentage (through the quantifier). The following signature applies (the signature’s as-of date defaults to the price input date):

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed.

In

providerPricingClause

ProviderPricingClause

The provider pricing clause that is being evaluated. Can be used to parametrize the dynamic logic.

In

adjustmentRule

AdjustmentRule

The adjustment rule that is being evaluated. Can be used to parametrize the dynamic logic.

In

allowedAmount

Money

The old allowed amount and currency up till the moment of adjustment through the formula.

In

unadjustedAllowedAmount

Money

The old allowed amount and currency as calculated with a reimbursement method (before any adjustment rule was applied)

In

userDefinedParameters

userDefinedParameters

The variable userDefinedParameters[8] and userDefinedParameters[9] can be populated through the function dynamic logic to be used as substitution parameters 8 and 9.

Out

n/a

Money

The new allowed amount and currency as outcome of the calculation.

Example:

// Rendered units are the number of treatments that were physically rendered by the Provider
// Calculation logic: first rendered unit at 100%, reduce subsequent rendered units to a reduced %

RenderedUnits = 2 * claimLine.priceInputNumberOfUnits
AdjustmentPercentage = 100 + providerPricingClause.percentage * (RenderedUnits -1)
newAllowedAmount = (allowedAmount / claimLine.priceInputNumberOfUnits) * (AdjustmentPercentage / 100)
AdjustmentAmount = allowedAmount - newAllowedAmount

// The userDefinedParamters are used as placeholder values in adjustment rule messages
userDefinedParameters[8] = AdjustmentAmount
userDefinedParameters[9] = AdjustmentPercentage

Advice Response Definition

This function specifies the response that is sent via claims advice service. (The signature’s as-of date defaults to the AdviceRequest: serviceDate)

In / Out Name Type Description

In

providerPricingClauseMap

Map<String,List<ProviderPricingClauseData>>

All matching ppc’s keyed on either a matching FeeSchedule, ChargedAmount or SimpleAdjustmentRule.

In

productBenefitSpecificationMap

Map<String,ProductBenefitSpecification>

All matching benefit specifications keyed on the type (Authorization, Coverage or WaitingPeriod)

In

adviceResponseDefinition

AdviceResponseDefinition

The configuration record that applies the function to allow for parametrization.

In

adviceRequest

AdviceRequest

Entity that captures the request, including the name/value pairs that may have been passed along

Out

n/a

Alphanumeric

The response message - claims advice response - which will be sent to the external component.

ProviderPricingClauseData: This structure will contain the following

attributes:

  • providerPricingClause

  • pricingRule: This will point to SimpleAdjustmentRule, if the selected ProviderPricingClause is pointing to SimpleAdjustmentRule, else it will be null.

  • reimbursementMethod: This will point to ChargedAmount or FeeSchedule, if the selected ProviderPricingClause is pointing to ChangedAmount or FeeSchedule, else it will be null.

  • feeScheduleLineList: This will contain the selected fee schedule lines based on the above selection logic, if the selected ProviderPricingClause is pointing to FeeSchedule, else it will be an empty list.

Aggregation Level

This function is called when a limit is selected for which an aggregation level is required that is not product related. The aggregation level that is the result of this dynamic logic function is stamped on the limit counter periods and consumptions so limits can be counted based on user defined dimensions.

Examples of user defined dimensions for which this function can be used are:

  • Count per main diagnosis code (the first 3 characters of the diagnosis code)

  • Count per enrollment product. The enrollment product code can be set as a dynamic field on the policy product

In / Out Name Type Description

In

limit

Limit

The limit being selected

In

policyProduct

PolicyProduct

The policy product in context

In

claimLine

ClaimLine

The claim line in context

In

claimLineLimit

ClaimLineLimit

The claim line limit in context (when applicable)

Out

n/a

Alphanumeric

The aggregation level for the limit counter period / consumption

Note that the return value will be truncated to 30 characters.

Below is a simple example function, using a dynamic field on the enrollment response as the aggregation level:

// return policyProduct dyn field 'enrollmentProductCode'. return 'UNKNOWN' if not specified

claimLine.policyEnrollment.getProducts()[0]?.enrollmentProductCode ?: 'UNKNOWN'

Another example, using the first 3 characters of the primary diagnosis as the aggregration level:

claimLine.getPrimaryDiagnosis().code.substring(0,3)

Authorization Matching

Every authorization regime specifies a dynamic logic function for authorization matching. In the event a claim line requires an authorization that function is used to find eligible authorizations. The function returns a list of eligible authorizations. Whether or not these authorizations are actually used is determined by hard coded logic in OHI Claims Adjudication, i.e., is there enough space left on the authorization? The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

In

authorizationList

List of authorizations

All authorizations for the claim line serviced person or object

In

authorizationRegime

AuthorizationRegime

The authorization regime being evaluated. Can be used to parametrize the dynamic logic.

In

benefitSpecification

BenefitSpecification

The benefit specification related to the authorization regime being evaluated. Can be used to parametrize the dynamic logic.

In

product

Product

The product related to the authorization regime being evaluated. Can be used to parametrize the dynamic logic.

Out

n/a

List of Authorizations

The list of authorizations that meet the conditions of the function.

Consider the following function for clarification. The function searches for authorizations that meet the following conditions:

  • the first three characters of the code of the primary diagnosis match the first three characters of one of the diagnoses for the authorization;

  • the location provider of the claim line matches the location provider on the authorization;

  • one of the specialties of the servicing provider of the claim line matches the specialty of the authorization;

  • one of the procedures of the claim line matches one of the procedures for the authorization;

  • the service date of the claim is in the validity period of the authorization with a five day margin.

This signature’s as-of date defaults to the claim line start date. Note that the authorizationList is pre-filtered to contain only authorizations for the claim line serviced person or object.

def primaryDiagnosis = claimLine.getPrimaryDiagnosis()

if (!primaryDiagnosis) {
  // no primary diagnosis found, cannot find matching authorizations
  return []
}

// find all matching authorizations and return them
return authorizationsList.findAll { authorization ->
  authCodeMatch(authorization.authorizationDiagnosisList, primaryDiagnosis) &&
  specialtyMatch(authorization, claimLine) &&
  procedureMatch(authorization.authorizationLineList, claimLine) &&
  dateMatch(claimLine.startDate, authorization) &&
  authorization.locationProvider == claimLine.locationProvider
}

// Do the first three characters of the primary diagnosis code of the claim line match with the first three
// characters of one of the authorization diagnoses?
def authCodeMatch(authorizationDiagnosisList, primaryDiagnosis) {
  return authorizationDiagnosisList.diagnosis.code.any { it[0..2] == primaryDiagnosis.code[0..2] }
}

def specialtyMatch(authorization, claimLine) {
  return claimLine.serviceProvider.hasSpecialty(authorization.specialty.code)
}

// Does one of the procedures of the claim line match with the procedure of one
// of the authorization lines?
def procedureMatch(authorizationLineList, claimLine) {
  return authorizationLineList.procedure.intersect([claimLine.procedure, claimLine.procedure2, claimLine.procedure3])
}

def dateMatch(serviceDate, authorization) {
  return serviceDate >= authorization.startDate - 5 && serviceDate <= authorization.endDate + 5;
}

Authorization Detail Matching

Every authorization regime can specify a dynamic logic function for authorization detail matching. In the event a claim line requires an authorization, that function is used to find eligible authorization lines and/or authorization basket details on the eligible authorizations. The function returns a list/map of eligible authorization lines and/or authorization basket details. Whether or not these authorization lines and authorization basket details are actually used is determined by hard coded logic in OHI Claims Adjudication, i.e., is there enough space left on the authorization line or authorization basket detail? The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed.

In

authorization

Authorization

The authorization being processed.

In

authorizationDetails

AuthorizationDetails

Predefined object with the following attributes:

  • authorizationLineList: a list of all authorization lines for the selected authorization.

  • authorizationBasketDetailList: a list of all authorization basket details for the selected authorization. An authorization basket detail is another predefined object, representing the combination of an authorization basket and a basket detail, which in turn has the following attributes:

    • authorizationBasket

    • basketDetail

In

authorizationRegime

AuthorizationRegime

The authorization regime being evaluated. Can be used to parametrize the dynamic logic.

In

benefitSpecification

BenefitSpecification

The benefit specification related to the authorization regime being evaluated. Can be used to parametrize the dynamic logic.

In

product

Product

The product related to the authorization regime being evaluated. Can be used to parametrize the dynamic logic.

Out

n/a

AuthorizationDetails

Same structure as the input object, but with the output being a filtered authorizationLineList and authorizationBasketDetailMap.

This signature’s as-of date defaults to the claim line start date.

If this function is not configured, the authorization lines and authorization basket details of the authorization will not be evaluated so there won’t be any consumption on them. It is still possible to evaluate them in the Authorization Matching dynamic logic function to determine if the authorization is eligible.

If the result of the function is an empty list of authorization lines and authorization basket details, the authorization is still eligible and will be consumed on the authorization level (if there is enough space left).

Example 1

Consider the following example for clarification. The function searches for authorization lines on the authorization that meet the condition that one of the procedures of the claim line matches the procedure on the authorization line.

matchedAuthorizationDetails = new AuthorizationDetails()
matchedAuthorizationDetails.authorizationLineList = authorizationDetails.authorizationLineList.findAll { authorizationLine ->
    authorizationLine.procedure in [claimLine.procedure, claimLine.procedure2, claimLine.procedure3]
}
return matchedAuthorizationDetails

Example 2

Consider the following example for clarification. The function searches for authorization lines and/or authorization basket details on the authorization that meet the following conditions:

Authorization Lines

  • The claim line start date falls within the time period of the authorization line

  • If a procedure group is specified on the authorization line, the claim line procedure needs to be in that group on the claim line start date

  • If a procedure is specified on the authorization line, the claim line procedure needs to match that procedure

  • If specialties (dynamic field) are specified on the authorization line, the claim line service specialty needs to match one of those specialties

Authorization Basket Details

  • The claim line start date falls within the time period of the authorization basket and the basket detail

  • The claim line procedure matches the basket detail procedure or has the same ATC Code (dynamic field) as the basket detail procedure

Overrides

  • If a matched authorization basket detail has the same procedure as a matched authorization line, the authorization basket detail is discarded from the list

def isTimeValid(entity) {

    return entity.startDate <= claimLine.startDate && (entity.endDate == null || entity.endDate >= claimLine.startDate)
}

def authorizationLineMatches(authorizationLine) {

    return isTimeValid(authorizationLine)
        && (!authorizationLine.procedureGroup || claimLine.procedure.inProcedureGroup(authorizationLine.procedureGroup.code))
        && (!authorizationLine.procedure || authorizationLine.procedure.equals(claimLine.procedure))
        && (!authorizationLine.specialties || authorizationLine.specialties.Code.contains(claimLine.serviceSpecialty?.code))
}

def authorizationBasketDetailMatches(authorizationBasketDetail, matchedAuthorizationLines) {

    authorizationBasket = authorizationBasketDetail.authorizationBasket
    basketDetail = authorizationBasketDetail.basketDetail

    return isTimeValid(basketDetail)
        && isTimeValid(authorizationBasket)
        && (basketDetail.procedure == claimLine.procedure || basketDetail.procedure.ATCCode == claimLine.procedure.ATCCode)
        && (!basketDetail.procedure || !matchedAuthorizationLines.procedure.contains(basketDetail.procedure)
}

def matchedAuthorizationLines = []
def matchedAuthorizationBasketDetails = []
def matchedAuthorizationDetails = new AuthorizationDetails()

authorizationDetails.authorizationLineList.each { authorizationLine ->
    if (authorizationLineMatches(authorizationLine)) {
        matchedAuthorizationLines << authorizationLine
    }
}

authorizationDetails.authorizationBasketDetailList.each { authorizationBasketDetail ->
    if (authorizationBasketDetailMatches(authorizationBasketDetail, matchedAuthorizationLines)) {
        matchedAuthorizationBasketDetails.add(authorizationBasketDetail)
    }
}

matchedAuthorizationDetails.authorizationLineList = matchedAuthorizationLines
matchedAuthorizationDetails.authorizationBasketDetailList = matchedAuthorizationBasketDetails
return matchedAuthorizationDetails

Benefits Rounding

This function takes the result of a cover withhold rule and allows for customized rounding, such as rounding up and down of cents or rounding to the nearest multiple of 10. It can also be used to build in thresholds, such as a minimum and maximum amount for a percentage based cover withhold rule. The following signature applies (the signature’s as-of date defaults to the claim line start date):

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed.

In

coverWithholdRule

CoverWithholdRule

The cover withhold rule that is being evaluated. Can be used to parametrize the dynamic logic.

In

inputAmount

Money

The unrounded amount as calculated by the cover withhold rule for the coverage label that matches the action of the cover withhold rule.

In

inputNumberOfUnits

BigDecimal

The number of units for which the coverage is calculated by the cover withhold rule.

Out

n/a

Money

The adjusted amount as outcome of the calculation for the coverage label that matches the action of the cover withhold rule. Note that the system might still need to round this amount to a precision of two digits behind the decimal point; standard rounding as specified in the Benefits implementation guide is then applied.

Example:

// Round to the nearest multiple of 10

return inputAmount.round(-1)

Example:

// Round to the nearest multiple of 10
// Use a minimum and a maximum amount if specified (dynamic fields on the cover withhold rule)

roundedAmount = inputAmount.round(-1)

if (coverWithholdRule.minimumAmount == null) {
    minimumAmount = roundedAmount
} else {
    minimumAmount = Money.create(coverWithholdRule.minimumAmount * inputNumberOfUnits, inputAmount.currencyCode).round(-1)
}

if (coverWithholdRule.maximumAmount == null) {
    maximumAmount = roundedAmount
} else {
    maximumAmount = Money.create(coverWithholdRule.maximumAmount * inputNumberOfUnits, inputAmount.currencyCode).round(-1)
}

if (roundedAmount > minimumAmount && roundedAmount < maximumAmount) {
    return roundedAmount
} else if (roundedAmount < minimumAmount) {
    return minimumAmount
} else {
    return maximumAmount
}

Callout Definition

A Callout Definition specifies dynamic functions to create the request message body and (optionally) to handle the response message.

The following signature applies to dynamic logic for creating request messages:

In / Out Name Type Description

In

claim

Claim

The claim that triggered the callout rule and associated callout definition.

In

claimCalloutRule

ClaimCalloutRule

The claim callout rule that is being evaluated, and which refers to the callout definition. Can be used to parametrize the dynamic logic.

This object allows access to the callout definition that is being executed (claimCalloutRule.calloutDefinition).

In/Out

requestHeaders

Map

The request headers to be set for REST based call out

Out

n/a

Alphanumeric

The message body which will be sent to the external component.

Note for SOAP protocol based callout, this will be encapsulated by soap body

This signature’s as-of date defaults to the claim start date.

The following example shows dynamic logic that creates a callout message with information on a claim’s providers:

def writer = new StringWriter()

def xml = new groovy.xml.MarkupBuilder(writer)
xml.claim(code:claim.code)
    {
    attendingProvider(claim.attendingProvider.code)
    locationProvider(claim.locationProvider.code)
    operatingProvider(claim.operatingProvider.code)
    referralProvider(claim.referralProvider.code)
    }

requestHeaders.put("correlationId" ,claim.code) // e.g. setting a request header parameter that is expected by an external system
return writer.toString()

The resulting callout message may then be as depicted below. For a rest based call, the request header will contain correlationID header parameter. This will be set to the code of the claim.

Note that the encapsulating element <asynchronousCalloutRequest> is added automatically by OHI Claims for SOAP calouts (refer to the description of the Claim Callout IP (SOAP) in the implementation guide for process rules):

<asynchronousCalloutRequest>
    <claim code='CLAIM123'>
      <attendingProvider>123456</attendingProvider>
      <locationProvider>345678</locationProvider>
      <operatingProvider>098765</operatingProvider>
      <referralProvider>567895</referralProvider>
    </claim>
</asynchronousCalloutRequest>

The following signature applies to dynamic logic for handling response messages:

In / Out Name Type Description

In

claim

Claim

The claim that triggered the callout rule and associated callout definition.

In

claimCalloutRule

ClaimCalloutRule

The claim callout rule that is being evaluated, and which refers to the callout definition. Can be used to parametrize the dynamic logic.

This object allows access to the callout definition that is being executed (claimCalloutRule.calloutDefinition).

In

response

Alphanumeric

The message body returned by the external endpoint.

Note- for SOAP based call outs, this is soap body

This signature’s as-of date defaults to the claim start date. This signature does not have an Out object, because the intent of dynamic logic with this signature is to do one or both of the following:

  • Set values of dynamic fields.

  • Add messages to the claim using a pre-defined method (refer to the text on Predefined Methods).

The following example shows dynamic logic that parses the response message and sets the value of a dynamic field on the claim header.

The response:

<asynchronousCalloutResponse>
    <customMessage dynamicFieldABCD="Value12345"/>
</asynchronousCalloutResponse>

The dynamic logic:

def result = new XmlSlurper().parseText(response)

claim.dynamicFieldABCD = result.customMessage.@dynamicFieldABCD.text()

Notes:

  • Refer to the text "Call Out to External Service" in the implementation guide for dynamic logic for more elaborate examples. Note however that the callouts described there are synchronous callouts that may be executed from any dynamic logic. Those callouts are not tracked in the claim status history; callouts as a consequence of claim callout rules are.

  • Parsing XML in dynamic logic can be done with the XmlSlurper library.

Case Definition

A case definition can specify up to two dynamic logic functions. The first (mandatory) function determines the start date of a new case, in the event that a claim line meets the conditions to open a new case. The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

In

caseDefinition

CaseDefinition

The case definition being evaluated. Can be used to parametrize the dynamic logic.

Out

n/a

Date

The start date of the new case

This signature’s as-of date defaults to the claim line start date. This dynamic logic function is executed during the creation of a new case. This is a step during the calculation of benefits. The second (optional) function sets a case end date. The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

In

caseDefinition

CaseDefinition

The case definition being evaluated. Can be used to parametrize the dynamic logic.

In

adjudicationCase

AdjudicationCase

The adjudication case being evaluated

Out

n/a

Date

The end date of the case

This signature’s as-of date defaults to the claim line start date. This dynamic logic function is executed both when a new case is created and when a claim line is appended as an ancillary line. Note that the adjudicationCase input variable is empty when the dynamic logic is executed when a new case is created.

Claim Event Rule

The fields that are additionally sent out on the event message are produced by a dynamic function. This dynamic function produces a list of name value pairs. This list of name value pairs is shown in the Claim event messages in the <fields> element. These fields can be at the claim or at the claim line level. The following signature applies for the claim level (with the as-of date defaulting to the claim start date):

In / Out Name Type Description

In

claim

Claim

The claim being processed

In/Out

requestHeaders

Map

The request headers to be set for REST event. Refer callout rule definition example for details.

Out

n/a

Map

The field names and their values

The following signature applies at the claim line level (with the as-of date defaulting to the claim line start date):

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

claimLine

ClaimLine

The claim line being processed

Out

n/a

Map

The field names and their values

Claim Code Generation

A claim code can be produced by a dynamic function. If the dynamic logic is not present, then the code defaults to the primary key of the entity. The following signature applies:

In / Out Name Type Description

In

claim

Claim

The claim being processed

Out

n/a

Alphanumerical

The claim code

Example:

// Uses the id of the claim and prefixes it with CLA
return "CLA" + claim.id.toString()

Claim Line Code Generation

A claim line code with a different format than the default generated format "1, 2, 3" can be produced by a dynamic function. If the dynamic logic is not present, then the code defaults to the primary key of the entity. The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

Out

n/a

Alphanumerical

The claim line code

Example:

// Uses the id of the claim line and prefixes it with CLL
return "CLL" + claimLine.id.toString()

Claim Transaction Event Rule (Claim Fields)

The fields that are additionally sent out on the transaction event message are produced by a dynamic function. This dynamic function produces a list of name value pairs. This list of name value pairs is shown in the Claim transaction event messages in the <fields> element. These fields can only be at the claim level; the following signature applies:

In / Out Name Type Description

In

ctrClaim

CtrClaim

The claim transaction being processed

In/Out

requestHeaders

Map

The request headers to be set for REST based ctr events. Refer callout rule definition example for details.

Out

n/a

Map

The field names and their values

Claim Transaction Event Rule (Request Message)

In free format style, the payload can be composed through dynamic logic. The following signature applies:

In / Out Name Type Description

In

ctrClaimLine

CtrClaimLine

The claim line transaction being processed

In

claimLine

ClaimLine

The claim line corresponding to the claim line transaction being processed

In

limitConsumption

LimitConsumption

The limit consumption of the claim line that triggered the claim transaction event rule. Optional, so could be null.

In

claimTransactionEventRule

ClaimTransactionEventRule

The rule being evaluated. Can be used to parametrize the dynamic logic

Out

n/a

String

The message payload to be sent

More details, including an example, can be found in the chapter "Claim Transaction Event Integration Point (REST)".

Combination Adjustment Rule

A combination adjustment rule specifies which combination of procedures, modifiers and/or diagnoses leads to an adjustment of the allowed amount. A combination adjustment rule takes all claim lines of a claim into account, recognizing some as primary, some as secondary. Three formulas can be applied; one to calculate the allowed amount of primary claim lines, one to calculate the allowed amount of secondary claim lines and one to calculate the allowed amount of tertiary claim lines. Typically, the claim line being evaluated will provide the number of units and the provider pricing clause will provide the percentage (through the quantifier). The following signature applies (the signature’s as-of date defaults to the price input date):

In / Out Name Type Description

In

triggeringClaimLine

ClaimLine

The claim line being processed.

In

primaryClaimLineList

List of ClaimLines

All claim lines to which the combination adjustment rule applies and which are recognized as primary.

In

secondaryClaimLineList

List of ClaimLines

All claim lines to which the combination adjustment rule applies and which are recognized as secondary.

In

tertiaryClaimLineList

List of ClaimLines

All claim lines to which the combination adjustment rule applies and which are recognized as tertiary.

In

providerPricingClause

ProviderPricingClause

The provider pricing clause that is being evaluated. Can be used to parametrize the dynamic logic.

In

combinationAdjustmentRule

CombinationAdjustmentRule

The combination adjustment rule that is being evaluated. Can be used to parametrize the dynamic logic.

In

allowedAmount

Money

The old allowed amount and currency up till the moment of adjustment through the formula.

In

unadjustedAllowedAmount

Money

The old allowed amount and currency as calculated with the reimbursement method (before any adjustment rule was applied)

In

userDefinedParameters

userDefinedParameters

Variable userDefinedParameters[9] can be populated through the function dynamic logic to be used as substitution parameter 9.

Out

n/a

Money

The new allowed amount and currency as outcome of the calculation.

For an example see the Adjustment Rule function signature.

Combination Check

A combination rule compares the current claim line to other claim lines. These lines can be either in the same, or another claim. For example, a combination check would be used for duplicate claim line detection. The following signature applies:

In / Out Name Type Description

In

triggeringClaimLine

ClaimLine

The claim line being processed

In

claimLineList

List of ClaimLines

All claim lines for the claim line person or object

In

combinationCheck

combinationCheck

The combination check being evaluated. Can be used to parametrize the dynamic logic.

Out

n/a

ClaimLine

The claim line that meets the conditions in the function.

This signature’s as-of date defaults to the claim line start date. The logic is executed when combination checks are evaluated, during the pre-benefits step.

The second input parameter is the list of claim lines that are to be compared to the triggering claim line. This list consists of all claims lines that meet the following set of conditions:

  • They have the same serviced person or object

  • They are not the triggering claim line

  • They are not replaced as a result of (un)bundling

  • Their start date lies within the start and end date specified on the combination check

The example below shows a simple function for a combination check that is configured for duplicate detection. In addition to conditions on which the lines are pre-filtered, i.e., the bullet list above, the function considers a claim line to match the triggering claim line when the first three characters of the procedure code are equal:

prefix = triggeringClaimLine.procedure?.code.substring(0,3)
def dupeLine = null

claimLineList.each { claimLine ->
  if ( claimLine.procedure.code.startsWith(prefix) ) {
    dupeLine = claimLine
  }
}
return dupeLine

Country Format

This function is attached to a country and defines the format of addresses within that country. The following signature applies:

In / Out Name Type Description

In

address

Address

The address that is to be displayed

Out

n/a

List<String>

The character strings that represents the formatted address. Every address line is a new entry in the list.

This function is executed whenever an address is displayed.

Example:

addressLine1=''
addressLine2=''
if (address.houseNumber) addressLine1 += address.houseNumber+ ' '
if (address.street) addressLine1 += address.street + ' '
if (address.city) addressLine2 += address.city + ' '
if (address.postalCode) addressLine2 += address.postalCode + ' '
return [addressLine1,addressLine2]

There is no default as-of date. If no country format function is attached to the related country, the following default format is used: {house number} {number addition} {street} line-break {city} {country region code} {postal code}. So for example:

14 Walnut Street

Boston MA 02108

Coverage Label

This function is attached to a coverage label and defines the input value for the calculation of a cover withhold rule. The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

Out

n/a

Money

The amount and currency that are used as input

This function is executed during benefits calculation whenever a cover withhold rule refers to a coverage label of action 'INPUT' for the percentage of.

Currency Conversion (Benefit)

Before the evaluation of benefits, a conversion may be needed from the pricing currency into the benefit currency. This is done by the function of this signature of which 0 or 1 occurrence may be present (guaranteed by a business rule):

  • If no function is specified, then no conversion is needed (this will typically occur in a single currency environment).

  • If a function is specified, then the function will automatically be applied to the outcome of the process field derivation rule for benefits input amount. If no process field derivation rule for benefits input amount is applied to the claim line being processed, then also no conversion will take place. This would happen when the benefits input amount is specified directly, e.g. by sending it in; in that case the benefits input amount specified includes the desired currency.

The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line that is being processed.

Out

n/a

ExchangeRate

The exchange rate object that is the outcome of the conversion. The object consists of the currency from, the currency to, the reference date, the context and the rate.

Example:

if(claimLine.product == null) {
  return getExchangeRate(claimLine.allowedAmount.currencyCode, claimLine.policyEnrollment.getProducts()[0]?.product.currency.currencyCode, null,null)
} else {
  return getExchangeRate(claimLine.allowedAmount.currencyCode, claimLine.product.currency.currencyCode,null,null)
}

Note that in this example, the steering currency is used of the product that is:

  • the overriding product of the claim line if specified OR (if not specified)

  • the policy enrollment product with the highest priority

That way, it resembles best the logic of selecting applicable products in benefits processing.

The dynamic logic calling the predefined method getExchangeRate can of course be implemented at the customer’s discretion, taking into account that:

  • an unspecified currency from or currency to will result in no conversion at all

  • if currency from and currency to are same, this will also result in no conversion at all

  • an unspecified reference date will lead to the usage of the claim line start date as the reference date to find the exchange rate

  • in case no exchange rate is found with the passed in arguments, GEN-CURR-002 (fatal) is thrown back:

Currency Conversion (Authorization)

The evaluation of an authorization regime may lead to the need for one or more authorizations. Each of these authorizations needs to be evaluated until ample room is provided. The benefits processing (including the configuration of authorization period regime tranches) is done in the benefit currency. An authorization, however, will often be specified in the provider’s currency. Therefore, before the evaluation of an authorization, a conversion may be needed from the benefit currency into the authorization currency. This is done by the function of this signature of which 0 or 1 occurrence may be present (guaranteed by a business rule):

  • If no function is specified, then usually no conversion is needed (this will typically occur in a single currency environment).

    • If conversion is needed and no function is specified, a fatal message will be attached to the claim line during the benefits evaluation (see the Claims Flow implementation guide for more information)

  • If a function is specified, then the function will automatically be applied when evaluating the first authorization in the list that is approved and that has an authorized amount specified on the authorization and/or authorization procedure level.

The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line that is being processed.

In

authorization

Authorization

The authorization that is being evaluated.

Out

n/a

ExchangeRate

The exchange rate object that is the outcome of the conversion. The object consists of the currency from, the currency to, the reference date, the context and the rate.

Example:

if (authorization.authorizedAmount != null) {
    return getExchangeRate(authorization.authorizedAmount.currencyCode, claimLine.benefitsInputAmount.currencyCode, null, null)
} else {
    for (authorizationLine in authorization.authorizationLineList) {
        if (authorizationLine.authorizedAmount?.currencyCode != null
             && claimLine.benefitsInputAmount?.currencyCode != null
             && authorizationLine.authorizedAmount?.currencyCode != claimLine.benefitsInputAmount?.currencyCode) {
          return getExchangeRate(authorizationLine.authorizedAmount.currencyCode, claimLine.benefitsInputAmount.currencyCode, null, null)
        }
    }
}

The dynamic logic calling the predefined method getExchangeRate can of course be implemented at the customer’s discretion, taking into account that:

  • an unspecified currency from or currency to will result in no conversion at all

  • if currency from and currency to are same, this will also result in no conversion at all

  • an unspecified reference date will lead to the usage of the claim line start date as the reference date to find the exchange rate

  • in case no exchange rate is found with the passed in arguments, GEN-CURR-002 (fatal) is thrown back:

Currency Conversion (Payment)

In the finalization step, financial transactions and financial transaction details are created. The creation of financial transaction details is driven by the function dynamic logic with signature Transaction Scenario (Financial Transaction Detail). Before the creation of these details (on which the amount is stored to be paid out), a conversion may be needed from the benefit currency into the payment currency. This is done by the function of this signature of which 0 or 1 occurrence may be present (guaranteed by a business rule):

  • If no function is specified, then no conversion is needed (this will typically occur in a single currency environment).

  • If a function is specified, then the function will automatically be applied after execution of the function dynamic logic with signature Transaction Scenario (Financial Transaction Detail).

The following signature applies:

In / Out Name Type Description

In

ctrClaimLine

ClaimLine

The claim line that is being processed.

In

benefitCurrency

Char

The benefits currency

Out

n/a

ExchangeRate

The exchange rate object that is the outcome of the conversion. The object consists of the currency from, the currency to, the reference date, the context and the rate.

Example:

return getExchangeRate(ctrClaimLine.benefitsInputAmountCurrency, ctrClaimLine.allowedAmountCurrency, null, null)

The dynamic logic calling the predefined method getExchangeRate can of course be implemented at the customer’s discretion, taking into account that:

  • an unspecified currency from or currency to will result in no conversion at all

  • if currency from and currency to are same, this will also result in no conversion at all

  • an unspecified reference date will lead to the usage of the start date of the claim line transaction as the reference date to find the exchange rate

  • in case no exchange rate is found with the passed in arguments, GEN-CURR-002 (fatal) is thrown back:

    • No exchange rate found for {currency from code}, {currency to code}, {reference date} and {context}

Derivation Rule

Derivation rules are used to set the values of one or more dynamic and/or fixed fields. Which input parameters are passed along depends on the "level" field of the derivation rule. There are three signatures for derivation rules functions:

The following signature applies to derivation rules with the level "Claim". This signature’s as-of date defaults to the claim start date:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

derivationRule

DerivationRule

The derivation rule being evaluated. Can be used to parametrize the dynamic logic.

The following fixed claim elements cannot be changed through dynamic logic:

  • code

  • status

  • process fields:

    • ind external pricing

    • ind external benefits

    • due date

  • derived fields:

    • total claimed amount (including currency)

    • total allowed amount (including currency)

    • total covered amount (including currency)

  • ind preprocessing done

  • ind pricing done

  • ind changed in UI

  • ind manual

  • ind send out for preprocessing

  • ind send out for pricing

  • brand

  • payer code

  • claim form

  • all detail tables except Claim Diagnosis

The following signature applies to derivation rules with the level "Claim Line". This signature’s as-of date defaults to the claim line start date or pricing input date, based on the context of the rule:

  • Pre Reversal, Pre Pricing and End Pricing: price input date

  • Pre Benefits and End Benefits: claim line start date

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

claimLine

ClaimLine

The claim line being processed

In

derivationRule

DerivationRule

The derivation rule being evaluated. Can be used to parametrize the dynamic logic.

The following fixed claim line elements cannot be changed through dynamic logic:

  • code

  • sequence

  • status

  • process fields:

    • price individual provider

    • price organization provider

    • price input date

    • price input number of units

    • price principal procedure

    • benefits provider

    • benefits input amount (including currency)

    • benefits age input date

    • benefits input date

  • claimed amount (including currency)

  • allowed amount (including currency)

  • covered amount (including currency)

  • encounter

  • keep pricing

  • keep benefits

  • keep price principal procs

  • locked

  • manual benefits

  • manual pricing

  • replaced

  • is original for claim line

  • is replacement of claim line

  • all detail tables except Claim Diagnosis, Claim Line Modifier and Claim Line Contract Reference

The following signature applies to derivation rules with the level "Bill". This signature’s as-of date defaults to the bill date:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

bill

Bill

The bill being processed

In

derivationRule

DerivationRule

The derivation rule being evaluated. Can be used to parametrize the dynamic logic.

The following fixed bill elements cannot be changed through dynamic logic:

  • all detail tables except Bill Diagnosis

The functions are called when the derivation rules are executed. Note that none of the signatures have a return value. Instead, values can be assigned to dynamic and/or fixed fields using an assignment statement within the script itself:

<object>.<field> = <value>

The following example assumes that "prof" is a dynamic field defined for claims. This field gets the value 'Y' when the claim form is either 'CMS1500' or '837P'.

if ["CMS1500", "837P"].contains(claim.claimForm.code) {
  claim.prof ='Y'
}
else {
  claim.prof ='N'
}

Note that it is also possible to assign values to more than one field within the same script:

if ["CMS1500", "837P"].contains(claim.claimForm.code) {
  claim.prof ='Y'
  claim.inst ='N'
}
else {
  claim.prof ='N'

  if ["UB04", "837I"].contains(claim.claimForm.code) {
    claim.inst ='Y'
  }
  else {
    claim.inst ='N'
  }
}

After the function has finished its execution, the values that were assigned are stored. At this point, OHI Claims checks that the function only wrote values to dynamic fields and/or allowed fixed fields. If this is not the case, a fatal message is generated.

Consider another example. The US seed data specifies a claim line dynamic field called "placeOfService". This field is defined as a flex field. Its domain value is restricted to the flex codes under the flex code definition "PLACES OF SERVICE". The key field flex codes under this definition is the "Code" field. The following flex codes are available:

Code Description Start date End date

01

Pharmacy

2009-01-01

03

School

2009-01-01

04

Homeless Shelter

2009-01-01

05

Indian Health Service Free-standing Facility

2009-01-01

06

Indian Health Service Provider-based Facility

2009-01-01

A value can be assigned to this field as follows:

claimLine.placeOfService='04'

If the field is defined as flex code set lets say medicalCondition, which is of type Diagnosis, it is required to specify both the code and flex field definition code to set the value. In such a scenario, use the custom function setField, with parameters, fieldName, code and flexFieldDefinitionCode.

Note that there is also a pre-defined method "setField" that can accomplish the same:

claimLine.setField('placeOfService', '04', 'PLACES OF SERVICE')

This method is particularly useful if the key value "04" is not enough to disambiguate the intended flex code. This could occur when a dynamic field is restricted to the values of a set of flex code definitions, because there is potentially an overlap of key values between the definitions in the set.

= Eligibility Callout Rule

An Eligibility Callout Rule specifies dynamic function to create a request message body, make the callout and to handle the response message.

The following signature applies to the dynamic logic:

In / Out Name Type Description

In

eligibilityCheck

EligibilityCheck

The eligibility check that is being evaluated

In

eligibilityCalloutRule

EligibilityCalloutRule

The callout rule that is being evaluated (can be used to parametrize the dynamic logic)

This signature’s as-of date defaults to the eligibility check request date. Using this function dynamic logic the eligibility check (except for the Status, Code, Eligibility Response Definition, Request Date, Person and Provider fields) and eligibility check messages can be modified.

The following example shows dynamic logic that creates a callout message with information about the person for whom the eligibility check is requested and the product to which the eligibility response message belongs to.

def writer = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(writer)

xml.eligibilityCheck(code:eligibilityCheck.code) {
    personCode(eligibilityCheck.person.code)
}
 String response = initCallOut(WebTarget.class)
                     .path("post")
                     .request("application/xml")
                     .buildPost(Entity.xml(writer.toString()))
                     .invoke()
                     .readEntity(String.class)

def result = new XmlSlurper().parseText(response)

eligibilityCheck.dynamicFieldABCD = result.customMessage.@dynamicFieldABCD.text()
  • Parsing XML in dynamic logic can be done with the Groovy XmlSlurper library.

By default the callout invocation to the external service endpoint is done in an unsecured way. Property "ohi.service.{0}.client.authentication" (for example: "ohi.service.DYLO_CODE.client.authentication" where DYLO_CODE is the uniquely identifying code of the Dynamic Logic script) must be set to value BasicAuthentication to send the request using HTTP Basic Authentication. In that case the credentials must be specified using the "credentials" resource. The default value for "ohi.service.{0}.client.authentication" is None.

Alternatively, a callout request can also be specified with a callerId to identify the client, e.g.:

//Make the callout request
String response = initCallOut(WebTarget.class, "MY_CALLER_ID")
                   .path("post")
                   .request()
                   .buildPost(Entity.xml(writer.toString()))
                   .invoke()
                   .readEntity(String.class)

In that case the authentication feature can be controlled with property "ohi.service.MY_CALLER_ID.client.authentication". This feature also allows use of multiple clients in one dynamic logic function and precise specification of features on a per client basis.

Eligibility Response Definition

This function specifies the response that is sent via the eligibility check service. (The signature’s as-of date defaults to the EligibilityRequest: requestDate)

In / Out Name Type Description

In

eligibilityResponseDefinition

EligibilityResponseDefinition

The configuration record that applies the function to allow for parametrization.

In

eligibilityCheck

EligibilityCheck

Entity that captures the request.

Out

n/a

Alphanumeric

The response message - eligibility response - which will be sent to the external component.

Using this function dynamic logic the eligibility check (except for the Status, Code, Eligibility Response Definition, Request Date, Person and Provider fields) can be modified.

Eligibility Validation Rule

An eligibility validation rule is evaluated during the processing of an eligibility check.

In / Out Name Type Description

In

eligibilityCheck

EligibilityCheck

The eligibility check that is being evaluated

In

eligibilityValidationRule

EligibilityValidationRule

The validation rule being evaluated (can be used to parametrize the dynamic logic)

This signature’s as-of date defaults to the eligibility check request date. Using this function dynamic logic the eligibility check (except for the Status, Code, Eligibility Response Definition, Request Date, Person and Provider), and eligibility check messages can be modified.

Episode

An episode definition can specify three dynamic logic functions which are evaluated during the episode of care detection at the start of pricing.

The first (mandatory) function determines the start date of a new episode. The following signature applies:

In / Out Name Type Description

In

triggeringClaimLine

TriggeringClaimLine

The triggering claim line being processed

In

episodeDefinition

EpisodeDefinition

The episode definition being evaluated. Can be used to parametrize the dynamic logic.

In

episode

Episode

The episode. This will be null if the episode was not present before processing.

Out

n/a

Date

The start date of the episode

This signature’s as-of date defaults to the claim line start date. This dynamic logic function is executed when a claim line is identified as the triggering claim line; in other words, it will only be set once through the dynamic logic during claims processing..

The second (optional) function sets an episode’s end date. The following signature applies:

In / Out Name Type Description

In

triggeringClaimLine

TriggeringClaimLine

The triggering claim line being processed

In

episodeDefinition

EpisodeDefinition

The episode definition being evaluated. Can be used to parametrize the dynamic logic.

In

episode

Episode

The episode. This will be null if the episode was not present before processing.

Out

n/a

Date

The end date of the episode

This signature’s as-of date defaults to the claim line start date. This dynamic logic function is executed when a claim line is identified as the triggering claim line; in other words, it will only be set once through the dynamic logic during claims processing..

The third function dynamic logic can be attached to an episode definition to create a new line. It is mandatory when the result of the episode definition is 'New Line' and ignored when the result is 'Existing Line'. The following signature applies:

In / Out Name Type Description

In

triggeringClaimLine

TriggeringClaimLine

The triggering claim line being processed

In

newClaimLine

NewClaimLine

The new claim line that is created. This claim line is seeded with some default values which may be overridden.

In

episodeDefinition

EpisodeDefinition

The episode definition being evaluated. Can be used to parametrize the dynamic logic.

This signature’s as-of date defaults to the claim line start date. This dynamic logic function is executed when a claim line is identified as the triggering claim line; in other words, it will only be set once through the dynamic logic during claims processing..

The following fields of the newClaimLine cannot be set. Trying to do so will result in a processing error:

  • claim

  • claimLineBenefitSpecificationList

  • claimLineCoverageList

  • claimLinePendReasonList

  • claimLineProviderPricingClauseList

  • claimLineRuleCoverageList

  • coveredAmount (including currency)

  • coveredNumberOfUnits

  • keepBenefits

  • keepPricing

  • locked

  • manualBenefits

  • manualPricing

  • adjudicationCaseDetailList

  • originalClaimLine

  • replaced

  • replacementClaimLine

  • sequence

  • status

Fee Schedule Line Duplicity

Within a fee schedule, lines that are functionally the same may not overlap in time validity. Fee schedule lines are functionally the same if they have the same:

  • Certain Fixed Fields (these are described in the Fee Schedule Model in the Implementation Guide for Pricing Components)

  • Certain Dynamic Fields

    • Which dynamic fields are part of the time validity check is specified in a dynamic logic of this signature which returns a list of dynamic field usage names.

The following signature applies:

In / Out Name Type Description

Out

n/a

List of DynamicFieldUsageNames

The list with dynamic field usage names.

Example:

return ['zipCode']

Note that it is not recommended to update this dynamic logic (for example adding a new dynamic field) if fee schedule lines exist, because this could potentially result in duplicate fee schedule lines.

Fee Schedule Line Priority

Dynamic logic with this signature is executed in the case that multiple fee schedule lines are applicable to price a claim line. The intent of this dynamic logic is to select, i.e. 'choose', the fee schedule line with the highest priority.

The following signature applies:

In / Out Name Type Description

In

feeScheduleLineList

List of FeeScheduleLines

The list of applicable fee schedule lines

In

claimLine

ClaimLine

The claim line that needs to be priced

In

providerPricingClause

ProviderPricingClause

The selected provider pricing clause

Out

n/a

List of FeeScheduleLines

The filtered list with fee schedule lines. Ideally filtered to include only one line.

This dynamic logic signature has as output object a list of fee schedule lines. This allows for the following possibilities:

  • If this list contains only one fee schedule line, then this is the line that will be used to price the claim line.

  • If this list contains more than one fee schedule line, then this denotes that the dynamic logic was not able to choose between these fee schedule lines. This will lead to a pricing fatal message.

Returning an empty list of fee schedule lines is not allowed and will result in a processing error. The output list of fee schedule lines may include only fee schedule lines from the input list.

The following example demonstrates a very simple implementation where the input fee schedule line list is filtered in three steps:

  1. In step 1 the fee schedule line list is filtered to include only fee schedule lines that are most specific with regard to procedure match. This uses a pre-defined method specifically intended for this task.

  2. In step 2 the fee schedule line list is filtered to include only fee schedule lines that are most specific with regard to modifier match. This uses a pre-defined method specifically intended for this task.

  3. In step 3 the fee schedule line list is filtered further; the (unrealistic) choice is made to just go forward with the first fee schedule line in the input list.

// Step 1: Filter based on procedure specificty
feeScheduleLineList = claimLine.filterFeeScheduleLineProcedureSpecificity(feeScheduleLineList)
// Step 2: Filter based on modifier specificity
feeScheduleLineList = claimLine.filterFeeScheduleLineModifierSpecificity(feeScheduleLineList)
// Step 3: Just return the first line in the feeScheduleLineList
return [feeScheduleLineList[0]]

Refer to the text on fee schedule line priority (in the implementation guide for the Claims Flow) for a more elaborate and realistic example of dynamic logic with this signature.

This signature’s as-of date defaults to the claim line’s price input date.

A HTTP link references a dynamic logic function to build up the URL needed to access - in a different browser tab - the report. The context from which the link is clicked serves as input object for the dynamic logic.

In / Out Name Type Description

In

Depends on the page

Depends on the page

The object that the page provides as input.

In

httpLink

HTTP Link

The HTTP link that is being evaluated

Out

n/a

Alphanumerical

The composed URL

Example:

// Navigate to external overview page
return "http://"+getSystemProperty('reports.server.name')+".benefitsoverview?p_claim_code="+claim.code

where the server location for the report is stored in a property so that different environments can navigate to different servers for that.

MDS (Function)

OHI has a component that can execute dynamic logic and return the result. This result can for example be used to show additional information on a page using an MDS customization. Consider the following example where a field 'Amount After Copay' on the claim line shows the summed amount of the claim line coverages for coverage label Amount After Copay:

float total=0

for (ClaimLineRuleCoverage coverage: claimLine.claimLineCoverageList) {
  if ("AMOUNT AFTER COPAY"== coverage.coverageLabel.code) {
    total+=coverage.amount.amount
  }
}

total

The input object is the object on which MDS is being applied. In the previous example the input object is claimLine.

Name Format

Name formats are defined by a dynamic logic function. The dynamic logic function constructs a formatted name for a person or individual provider, using the available person or provider fields such as the first name, prefix and titles. The following signature for persons applies:

In / Out Name Type Description

In

person

Person

The person of which the name is to be displayed

Out

n/a

Alphanumerical

The string that contains the formatted name of the person

The following signature for individual providers applies:

In / Out Name Type Description

In

individualProvider

IndividualProvider

The individual provider of which the name is to be displayed

Out

n/a

Alphanumerical

The string that contains the formatted name of the individual provider

This function is called whenever a formatted name is displayed. Consider the following example for persons, where the formatted name consists of the person’s initials, prefix, (last) name and suffix respectively:

nf = ''
if (person.initials) nf += person.initials + ' '
if (person.prefix) nf += person.prefix.displayCode + ' '
if (person.name) nf += person.name
if (person.suffix) nf += ' ' + person.suffix
return nf

Consider the following example for individual providers, where the formatted name consists of the provider’s titles, first name, middle name, (last) name and suffix respectively:

nf = ''
if (individualProvider.getTitles('B')) nf += individualProvider.getTitles('B') + ' '
if (individualProvider.firstName) nf += individualProvider.firstName + ' '
if (individualProvider.middleName) nf += individualProvider.middleName + ' '
if (individualProvider.name) nf += individualProvider.name + ' '
if (individualProvider.suffix) nf += individualProvider.suffix
return nf

Payment Function

A payment function is a reimbursement method that calculates the claim line allowed amount.

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

claimLine

ClaimLine

The claim line being processed

In

providerPricingClause

ProviderPricingClause

The provider pricing clause

Out

n/a

Money

The claim line allowed amount and currency

This function uses the price input date is the as-of date.

Pend Reason

The fields that are additionally sent out on the workflow message are produced by a dynamic function. This dynamic function produces a list of name value pairs. This list of name value pairs is shown in the workflow messages in the <fields> element. These fields can be at the claim, bill or at the claim line level. This signature’s as-of date defaults to the claim start date, bill date or claim line start date.

The following signature applies for the claim level:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In/Out

requestHeaders

Map

The request headers to be set for REST based workflow events. Refer callout rule definition example for details.

Out

n/a

Map

The field names and their values

The following signature applies at the bill level:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

bill

Bill

The bill being processed

Out

n/a

Map

The field names and their values

The following signature applies at the claim line level:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

claimLine

ClaimLine

The claim line being processed

Out

n/a

Map

The field names and their values

Post Benefits Regime

Every post benefits regime specifies a dynamic logic function. The outcome of the function is used as the covered or the withheld amount, depending on the action of the post cover withhold rule. The following signature applies (this signature’s as-of date defaults to the claim line start date):

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

Out

n/a

Money

The amount and currency that is to be covered or withheld.

As an example a simple function for a form of Up to Allowed coordination of benefits, where the difference between benefits input amount and the preceding payer paid amount is used as covered amount.

return claimLine.benefitsInputAmount - claimLine.precedingPayerPaidAmount

Pricing Dynamic Field Rule

Dynamic field rules are used to set the values of one or more dynamic fields during Pricing. Which input parameters are passed along depends on the "level" field of the dynamic field rule. There are three signatures for pricing dynamic field rule functions:

The following signature applies to dynamic field rules with the level "Claim". This signature’s as-of date defaults to the claim start date:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

dynamicFieldRule

DynamicFieldRule

The dynamic field rule being evaluated. Can be used to parametrize the dynamic logic.

In

providerPricingClause

ProviderPricingClause

The provider pricing clause that is being evaluated. Can be used to parametrize the dynamic logic.

The following signature applies to dynamic field rules with the level "Claim Line". This signature’s as-of date defaults to the price input date:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

claimLine

ClaimLine

The claim line being processed

In

dynamicFieldRule

DynamicFieldRule

The dynamic field rule being evaluated. Can be used to parametrize the dynamic logic.

In

providerPricingClause

ProviderPricingClause

The provider pricing clause that is being evaluated. Can be used to parametrize the dynamic logic.

The following signature applies to dynamic field rules with the level "Bill". This signature’s as-of date defaults to the bill date:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

bill

Bill

The bill being processed

In

dynamicFieldRule

DynamicFieldRule

The dynamic field rule being evaluated. Can be used to parametrize the dynamic logic.

In

providerPricingClause

ProviderPricingClause

The provider pricing clause that is being evaluated. Can be used to parametrize the dynamic logic.

The functions are called when the dynamic field rules are executed. Note that none of the signatures have a return value. Instead, values can be assigned to dynamic fields using an assignment statement within the script itself:

<object>.<field> = <value>

After the function has finished its execution, the values that were assigned are stored. At this point, OHI Claims checks that the function only wrote values to dynamic fields (and not fixed fields). If this is not the case, a fatal message is generated.

Process Field Derivation Rule

Process Field Derivation rules set the value of a single field on the claim or the claim line (refer to the text on derivation rules in the implementation guide on process rules). Rather than returning a value, the function allows the process field to be set in the script itself. OHI Claims checks whether the field that was set in the code is the same as the process field specified on the process field derivation rule.

The following signature applies to derivation rules that concern a process field on claim line level:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

In

processFieldDerivationRule

ProcessFieldDerivationRule

The derivation rule being evaluated. Can be used to parametrize the dynamic logic.

This function is called when the process field derivation rule is executed. This signature’s as-of date defaults to the claim line start date or pricing input date (based on the context of the rule). The following example calculates the value for the benefits input amount depending on the cobCalculationIndicator field. The fields "cobCalculationIndicator" and "medicareAllowedAmount" are dynamic fields.

if (claimLine.cobCalculationIndicator == '1') {
  claimLine.benefitsInputAmount = claimLine.allowedAmount
}
else {
  claimLine.benefitsInputAmount = Money.create(claimLine.medicareAllowedAmount)
}

The following signature (as-of date defaults to the claim start date) applies to derivation rules that concern a process field on claim level:

In / Out Name Type Description

In

claim

Claim

The claim being processed

In

processFieldDerivationRule

ProcessFieldDerivationRule

The derivation rule being evaluated. Can be used to parametrize the dynamic logic.

Prorate

This function is called when a limit is selected that is subject to prorating. Typical use of this function is that the value in the policy product parameter is multiplied by the factor defined on the policy product. Rounding of the result is part of the dynamic logic function.

In / Out Name Type Description

In

limit

Limit

The limit being selected

In

policyProduct

PolicyProduct

The policy product from which the factor is used in prorating

In

limitMaxValue

Money /

BigDecimal

The limit max value that is determined in the adjudication process before prorating

Out

n/a

Money /

BigDecimal

The prorated limit max value

The limitMaxValue input parameter can either be a bigdecimal or a money object. This depends on the type of the limit.

Below is a simple example function where the limit parameter value is multiplied by the factor of the policy product.

return limitMaxValue * policyProduct.factor

Provider Code Generation

A provider code can be produced by a dynamic function. This function can use the generated sequence number for generating a provider code. If the dynamic logic is not present, then the code defaults to the primary key of the entity. The following signature applies:

In / Out Name Type Description

In

provider

Provider

The provider being created

Out

n/a

Alphanumerical

The provider code

// Uses the id of the provider and prefixes it with 'PROV-'
return "PROV-" + provider.id.toString()
A field validation rule on the Provider Flex Code Definition may enforce a specific format and or value of the provider code. If such a validation rule exists the provider code generation dynamic logic must meet that validation.

Provider Matching

Similar to relation matching strategies, a provider matching is a dynamic logic function that takes provider demographics and foreign identifiers and tries to find the corresponding provider in OHI Claims. The following signature applies:

In / Out Name Type Description

In

matchingContext

Map

The claim line being processed

Out

n/a

Provider

The matching provider

The matchingContext object contains the following attributes:

Attribute Note

matchingDate

An as-of date that is to be used when matching against time valid information, such as a service address

name

initials

Individual providers only

namePrefix

Individual providers only

serviceAddress.street

Not for Provider, only for Individual Provider and Organization Provider

serviceAddress.houseNumber

Not for Provider, only for Individual Provider and Organization Provider

serviceAddress.houseNumberAddition

Not for Provider, only for Individual Provider and Organization Provider

serviceAddress.zipCode

Not for Provider, only for Individual Provider and Organization Provider

serviceAddress.city

Not for Provider, only for Individual Provider and Organization Provider

serviceAddress.country

Not for Provider, only for Individual Provider and Organization Provider

dynamicFieldName

dynamicFieldValue

flexCodeDefinitionCode

The provider code flex code definition

providerCode

The provider code

This signature’s as-of date defaults to the matching date. The provider matching function is executed when a claim is imported through the claims in integration point and it is specified on the incoming claim.

An example on how to search on provider code and flexCodeDefinitionCode:

def SearchBuilder sb =  new SearchBuilder(IndividualProvider.class).by("code").eq(matchingContext.providerCode)
sb = sb.and().join("flexCodeSystem").by("code").eq(matchingContext.flexCodeDefinitionCode)
def matches = sb.execute()
if (matches.size() == 1) {
  return matches[0]
} else {
  return null
}

An example on how to search on a provider dynamic field, in conjunction with the provider code:

def matches = new SearchBuilder(Provider.class).by("code").eq(matchingContext.providerCode).and().by(matchingContext.dynamicFieldName).eq(matchingContext.dynamicFieldValue).execute()
if (matches.size() == 1) {
  return matches[0]
} else {
  return null
}

Following examples are valid for specific types of providers, Individual Provider or Organization Provider.

An example that searches on Individual Provider based on the code and the provider address, please note that search in serviceAddressList is only possible for Individual Provider or Organization Provider and not for the generic type i.e. Provider:

def SearchBuilder sb =  new SearchBuilder(IndividualProvider.class).by("code").eq(matchingContext.providerCode)
sb = sb.and().by("name").eq(matchingContext.name)
sb = sb.and().join("serviceAddressList").by("street").eq(matchingContext.serviceAddress.street)
sb = sb.and().join("serviceAddressList").by("houseNumber").eq(matchingContext.serviceAddress.houseNumber)

def matches = sb.execute()
if (matches.size() == 1) {
  return matches[0]
} else {
  return null
}

An example that searches on Organization Provider based on the code and provider address, please note that search in serviceAddressList is only possible for Individual Provider or Organization Provider and not for the generic type i.e. Provider:

def SearchBuilder sb =  new SearchBuilder(OrganizationProvider.class).by("code").eq(matchingContext.providerCode)
sb = sb.and().by("name").eq(matchingContext.name)
sb = sb.and().join("serviceAddressList").by("street").eq(matchingContext.serviceAddress.street)
sb = sb.and().join("serviceAddressList").by("houseNumber").eq(matchingContext.serviceAddress.houseNumber)

def matches = sb.execute()
if (matches.size() == 1) {
  return matches[0]
} else {
  return null
}

Relation Matching

On various occasions a relation from the outside world has to be matched against the relations that are present in OHI Claims. Ideally, the outside world will be able to communicate by means of the code of the relation, making the match trivial. The more common scenario is that the source of incoming claims is unaware of the identifying codes in OHI Claims, and sends in a set of demographic information and foreign identifiers instead.

A "matching strategy" is a dynamic logic function that takes these demographics and foreign identifiers and tries to find the corresponding relation in OHI Claims. The following signature applies:

In / Out Name Type Description

In

matchingContext

Map

The claim line being processed

Out

n/a

Relation

The matching relation

The matchingContext object contains the following attributes:

Attribute Note

matchingDate

An as-of date that is to be used when matching against time valid information, such as an address.

code

relation code

name

relation name

initials

Relation of type Person only.

namePrefix

Relation of type Person only.

namePartnerPrefix

Relation of type Person only.

namePartner

Relation of type Person only.

dateOfBirth

Relation of type Person only.

address.street

The street part of the address.

address.houseNumber

The house number of the address.

address.houseNumberAddition

The house number addition.

address.city

The city of the address.

address.zipCode

The zip code of the address.

address.country

The country of the address.

dynamicFieldName

The name of the dynamic field used for matching.

dynamicFieldValue

The value of the dynamic field used for matching.

This signature’s as-of date defaults to the matching date. The relation matching function is executed when a claim is imported through the claims in integration point and it is specified on the incoming claim. The following example returns a relation if the name and date of birth are an exact match. In the case that no relation or more than one relations are found, the matching strategy fails.

def SearchBuilder sb = new SearchBuilder(Person.class).by("name").eq(matchingContext.name)
sb= sb.and().by("dateOfBirth").eq(matchingContext.dateOfBirth)

def matches = sb.execute()
if (matches.size() == 1) {
  return matches[0]
} else {
  return null
}

The example below shows a search using the postalCode for the site address on a particular date:

def SearchBuilder sb = new SearchBuilder(Person.class).by("name").eq(matchingContext.name)
sb = sb.and().by("dateOfBirth").eq(matchingContext.dateOfBirth)
sb = sb.and().join("addressList").by("postalCode").eq(matchingContext.address.zipCode)
sb = sb.and().join("addressList").by("type").eq(AddressType.SiteAddress)
def matches = sb.execute()

The example below shows a search using the dynamic field value and name, provided in the matchingContext object:

def SearchBuilder sb = new SearchBuilder(Relation.class).by("name").eq(matchingContext.name)
sb = sb.and().by(matchingContext.dynamicFieldName).eq(matchingContext.dynamicFieldValue)
def matches = sb.exceute()

Replacement Rule

Upon executing a replacement defined by a replacement rule, a new claim line is created that replaces one or more existing claim lines. Using function dynamic logic, field values of this new claim line may be set (or changed where they were seeded).

The following signature applies to dynamic logic for setting fields on the new claim line:

In / Out Name Type Description

In

claim

Claim

The claim being processed,

In

replacedClaimLineList

List of ClaimLines

The claim lines that triggered the replacement rule and that will be replaced by the new claim line.

In

replacementClaimLine

ClaimLine

The new claim line that is created to replace the existing claim lines that triggered the rule. This claim line is seeded with default values which may be overridden.

In

providerPricingClause

ProviderPricingClause

The provider pricing clause that is being evaluated. Can be used to parametrize the dynamic logic.

This object allows access to the replacement rule that is being executed (providerPricingClause.pricingRule).

This signature’s as-of date defaults to the price input date of the triggering claim line with the lowest sequence number.

The following fields of the replacementClaimLine cannot be set. Trying to do so will result in a processing error:

  • claim

  • claimLineBenefitSpecificationList

  • claimLineCoverageList

  • claimLinePendReasonList

  • claimLineProviderPricingClauseList

  • claimLineRuleCoverageList

  • coveredAmount (including currency)

  • coveredNumberOfUnits

  • keepBenefits

  • keepPricing

  • locked

  • manualBenefits

  • manualPricing

  • adjudicationCaseDetailList

  • originalClaimLine

  • replaced

  • replacementClaimLine

  • sequence

  • status

The following example demonstrates overriding the seeded values with a custom claim line code and with a DRG-code and price specified on the claim header. Setting the DRG-code is parametrized using a dynamic field ('copyDRGCode') on the replacement rule. Setting the DRG price is parametrized using a dynamic field ('copyDRGPrice') on the provider pricing clause:

// Set claim line code using a custom scheme
replacementClaimLine.code = (replacementClaimLine.sequence * 100).toString().padLeft(4,'0')

// Copy DRG Code from a dynamic field on the claim header
//  if so configured in the replacement rule.
if  (providerPricingClause.pricingRule.copyDRGCode == 'Y')
    {
    // Copy the DRG into the first procedure field
    replacementClaimLine.setField('procedure',claim.DRGCode,'DIAGNOSIS_RELATED_GROUPS')
    // Clear out other existing procedures and modifiers
    //  that were copied from the first replaced claim line.
    // This obviously assumes that both pricing and benefits
    //  use the DRG only.
    replacementClaimLine.procedure2 = null
    replacementClaimLine.procedure3 = null
    replacementClaimLine.claimLineModifierList = null
    // Set the price input number of units to 1
    replacementClaimLine.priceInputNumberOfUnits = 1

    // Copy DRG Price from a dynamic field on the claim header
    //  if so configured in the provider pricing clause.
    if  (providerPricingClause.copyDRGPrice == 'Y')
        {
        // Copy the DRG price to the claim line allowed amount
        replacementClaimLine.allowedAmount = Money.create(claim.DRGPrice)
        replacementClaimLine.allowedNumberOfUnits = 1
        // Add a message to the replacement claim line
        replacementClaimLine.addMessage('DRG_PRICED_METHODOLOGY',providerPricingClause.percentage.toString())
        }
    }

Reservation Line Matching

Every reservation regime specifies a dynamic logic function for reservation line matching. In the event a claim line requires a reservation line during processing, that function is used. The function returns one reservation line or none at all. The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

In

reservationLineList

List of ClaimLines

All non-replaced reservation lines for the claim line serviced person

In

reservationRegime

ReservationRegime

The reservation regime being evaluated. Can be used to parametrize the dynamic logic.

In

reservationSpecification

BenefitSpecification

The reservation specification being evaluated. Can be used to parametrize the dynamic logic.

In

product

Product

The product related to the product reservation specification evaluated. Can be used to parametrize the dynamic logic.

Out

n/a

ClaimLine

The reservation line that meet the conditions of the function.

Consider the following function for clarification. The function searches for reservation lines that meet the following conditions:

  • the location provider of the claim line matches the location provider on the reservation line;

  • the procedure of the claim line matches the procedure for the reservation line;

  • the service date of the claim line is within days of the service date of the reservation line

This signature’s as-of date defaults to the claim line start date. Note that the reservationLineList is pre-filtered to contain only reservation lines for the claim line serviced person.

// find all matching reservation lines and return the first
return reservationLineList.find {reservationLine ->
  reservationLine.procedure == claimLine.procedure &&
  reservationLine.locationProvider == claimLine.locationProvider &&
  reservationLine.startDate >= claimLine.startDate - 5 &&
  reservationLine.startDate <= claimLine.startDate + 5
}

Reusable Code

This is a common signature, available in all the applications. This signature has no bindings. It allows for writing standalone methods/reusable classes code that can be shared across other scripts.

Extension

This is a common signature, available in all the applications. This signature has no bindings. It allows for writing extensions to the dynamic logic scripts that are delivered by the product.

URL Composition

A flex code field usage of a dynamic record definition can reference a dynamic logic function to build up the URL needed to access an external application. In this way it is possible to change e.g. a server location in a central way.

In / Out Name Type Description

In

dynamicRecord

DynamicRecord

The dynamic record

Out

n/a

Alphanumerical

The composed URL

Example:

return "http://financialsystem.oracle.com?p_check_number="+dynamicRecord.checkNumber

This signature’s as-of date defaults to the claim.

Waiting Period Start Date

This is a function that can be optionally used on a waiting period regime. This function returns the start date as of which the waiting period is measured: the time in between the returned value and the service date for the claim line represents the wait time already served. If it exceeds the specified period then the waiting period requirement is satisfied.

The function signature includes additional incoming bind variables that represent typical return values for this function.The following signature applies:

In / Out Name Type Description

In

claimLine

ClaimLine

The claim line being processed

In

waitingPeriodRegime

WaitingPeriodRegime

The waiting period regime being evaluated. Can be used to parameterize the dynamic logic.

In

waitingPeriodRegimeSpecification

BenefitSpecification

The benefit specification related to the waiting period regime being evaluated. Can be used to parameterize the dynamic logic.

In

policyProduct

PolicyProduct

The enrollment information for the product that is under evaluation for the waiting period

In

earliestCoverageDate

date

date as of which the member is covered by the same, similar or better benefit based their product benefit history within the system. If the member had no products prior to the current product, the earliest coverage date is retrieved from the enrollment response

Out

n/a

date

The earliest coverage date.

Note: The earliest coverage date is the earliest start date for a coverage product benefit specification that belongs the same service option/service as the wait specification that is under evaluation, barring the coverage specifications that belong to products that have a lower level of coverage. In the event that the member had no products prior to the current product, the earliest coverage date is retrieved from the enrollment response

The earliest coverage date is the earliest start date for a coverage product benefit specification that

  1. has the same service option service code as the waiting period specification being evaluated

  2. barring the coverage specifications that belong to products that have a lower level of coverage

In the event that the member had no products prior to the current product, the earliest coverage date is retrieved from the enrollment response

The derivation of the date requires information from the enrollment response. If the enrollment response does not include the information that is needed, or does not exist at all then the value of these dates is defaulted to the claim line start date.