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 or 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 or 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 or 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 Claims, that is, is there enough space left on the authorization? The following signature applies:
In or 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 Claims, that is, is there enough space left on the authorization line or authorization basket detail? The following signature applies:
In or 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:
|
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 or 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 }
Call-out Definition
A Callout Definition specifies dynamic functions to create the request message body and (optionally) to handle the response message.
Request
The following signature applies to dynamic logic for creating request messages:
In or 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. |
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.
Response
The following signature applies to dynamic logic for handling response messages:
In or 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. |
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).
-
This signature also allows the use of the following object methods:
-
claimLine.removeClaimLineModifier
-
claimLine.addClaimLineModifier
-
claimLine.removeClaimLineDiagnosis
-
claimLine.addClaimLineDiagnosis
-
claimLine.setKeepBenefits
-
claim.removeClaimDiagnosis
-
claim.addClaimDiagnosis
-
claim.recalculate using a predefined method (refer to the text on Predefined Methods)
-
ClaimLineRuleCoverage.setAmountManually using a predefined method (refer to the text on Predefined Methods)
-
ClaimMessage.setOverturn
-
ClaimLineMessage.setOverturn
-
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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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
-
Overturned indicator on Claim Message
-
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 or 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
-
Claim Line Contract Reference
-
Dynamic fields on Claim Line Limit
-
Overturned indicator on Claim Line Message
-
The following signature applies to derivation rules with the level "Bill". This signature’s as-of date defaults to the bill date:
In or 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, 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 Call-out 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 or 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 or 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 or 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 four 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 or Out | Name | Type | Description |
---|---|---|---|
In |
triggeringLine |
ClaimLine |
The triggering claim line being processed |
In |
episodeDefinition |
String |
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 or Out | Name | Type | Description |
---|---|---|---|
In |
claimLine |
ClaimLine |
The triggering/Include 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 or Out | Name | Type | Description |
---|---|---|---|
In |
triggeringClaimLine |
ClaimLine |
The triggering claim line being processed |
In |
newClaimLine |
ClaimLine |
The new claim line that is created. This claim line is seeded with some default values which may be overridden. |
In |
episodeDefinition |
String |
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 or inclusion 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
Episode Identifier
This function returns the episode identifier. This identifier is stored on the episode.
The system matches this identifier to the identifier on the claim line to include a claim line (as include line or triggering line) within an existing episode.
The following signature applies:
In or Out | Name | Type | Description |
---|---|---|---|
In |
claimLine |
claimLine |
The claim line with identifier being processed |
In |
episodeDefinition |
EpisodeDefinition |
The episode definition being evaluated. |
out |
episodeIdentifier |
episodeIdentifier |
The episode identifier to be stored on the episode. |
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 or 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 or 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:
-
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.
-
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.
-
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.
HTTP Link
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 or 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)
Oracle Health Insurance 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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 or 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, 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. 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 or 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 or 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 or 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 or 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 Claims. The following signature applies:
In or 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 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 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 Claims. The following signature applies:
In or 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 or 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 or 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 or 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 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 following signature applies:
In or 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 |
Out |
n/a |
date |
The waiting period start date. |