Example Scenario

Claims Eligibility Check is a REST based API exposed by Claims, servicing other applications that require an eligibility check. The incoming request inquires about a person and provider, including the date on which the eligibility is requested. This chapter describes a number of scenarios to highlight some capabilities.

Scenario 1: Eligibility Check Approved

This scenario covers an eligibility check where the provider sends in a request where the person is identified by his social security number and where the following validations on the person and provider are evaluated:

  1. Is the person enrolled for product DENTAL?

  2. Is the provider in network?

  3. Is the person a resident of the United States or Canada?

This scenario requires the following setup in Claims:

  1. The social security number of the person is stored in a dynamic fields on the Person (in this example with usage name SSN)

  2. A dynamic record in configured on the Eligibility Check with the structure of the Enrollment Callout Response (in this example with usage name enrollmentProduct)

  3. An Eligibility Response Definition is defined with the required process steps (see below)

Eligibility Response Definition

Definition

Code Description Response Mapping

DENTALNA

Dental Coverage North America

DENTAL_NA

The response mapping is a dynamic logic function with signature 'Eligibility Response Definition'. See the Functions section in the Dynamic Logic chapter of the Developer Guide for a specification of this dynamic logic signature.

Process Steps

Sequence Display Name Rule Steps Sequence Rule Steps Description Rule Steps Callout or Validation

1

Enrollment Callout

1

Policies callout

Callout Rule

2

Enrollment check

Validation Rule

2

Enrollment Validation

1

Dental Enrollment check

Validation Rule

2

Provider in network

Validation Rule

3

Country of residence

Validation Rule

Eligibility Check Request

Send in the Eligibility Check

The external system sends in an eligibility check request with eligibility response definition "DENTALNA".

The request that is sent to the eligibility check service: ;

{"person":{"SSN":"8236-73538-11"},
 "provider":{"flexCodeSystem":"OHI","code":"PROV723630"},
 "requestDate":"2017-11-11",
 "product":"DENTAL",
 "countryOfResidence":"Canada"
}

The request is stored in Claims and the person and provider are looked up in the Claims reference data. The person is retrieved based on the dynamic field SSN, the provider is checked on it’s flexcode definition code and code. If no technical errors occur, the system will respond to the external system with a HTTP 201 (Created) response along with a Location header to an eligibility check status resource. The process continues with the execution of the process steps in an a-synchronous way. The status of the eligibility check is In Process.

Process Step 1 - Rule Step 1 - Enrollment Callout

This callout rule initiates communication by sending out a request for enrollment information. The enrollment system sends a response back to Claims. The enrollment system can be Policies, or any other third party system.

The request message includes the unique identifier for the serviced person, as well as the time-span for which enrollment information is required. An example of a callout rule function dynamic logic might look something like this:

import groovy.util.slurpersupport.Attributes;

import java.text.SimpleDateFormat

// Use this date format in this particular dynamic logic
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd")

// Small helper method to parse a text representation of a date as contained by a {@link XmlSlurper}'s {@link Attributes},
// and morph the result into a java.sql.Date instance. This value can then subsequently be used to be fed into a dynamic record.
java.sql.Date parseToDate(SimpleDateFormat simpleDateFormat, Attributes attributes) {
    return new java.sql.Date(simpleDateFormat.parse(attributes.text()).getTime())
}

// First use the request date as was stored on the eligibility check
// and translate that to a well known date format.
requestDate = formatter.format(eligibilityCheck.requestDate)

// Subsequently call the `enrollment` callout specifying
// The responseDefinitionCode specified here, identifies the response logic for the called system
// person - the code of the person as was stored on the eligibility check
// requestDate - the `transformed` request date as was stored on the eligibility check
String response = initCallOut(WebTarget.class)
        .path("enrollment")
        .queryParam("person", eligibilityCheck.person.code)
        .queryParam("requestDate", requestDate)
        .request("application/xml;responseDefinitionCode=type1")
        .buildGet()
        .invoke()
        .readEntity(String.class)

// As the response is XML can `slurp it`
xml = new XmlSlurper().parseText(response)

// To subsequently add the contained product information as dynamic records
xml.products.product.each { product ->
    eligibilityCheck.addDynamicRecord("enrollmentProduct",
            [productCode: product.@"code".text(),
             startDate  : parseToDate(formatter, product.@"startDate"),
             endDate    : parseToDate(formatter, product.@"endDate")
            ]
    )
}

The response message includes the following information:

  • The person and period in the request message

  • Products

The identifiers, e.g., for the person and products, in the response message have to match the identifiers as they are known in Claims. Note that these are not proprietary identifiers; these identifiers are typically specified through the corresponding integration points by the system of record into Claims.

The block below contains the response message in pseudo code. Three consecutive decimal points indicate the possibility of multiple iterations.

<enrollment
  startDate=""
  endDate="">

 <products>
   <product
      code=""
      startDate=""
      endDate=""
      contractDate="">
    </product>
   ...
 ;</products>
</enrollment>

The contents of the response message is stored in dynamic records defined on the eligibility check.

The response message has a number of time valid elements. The time validity is expected to be bound by the start and end date in the corresponding request message.

In the event that there are no <product> elements available for the person for the requested time period, Claims expects 404- Not Found and the response body as 'NO ENROLLMENT FOUND' in the response. Claims does not distinguish situation (1) where the serviced person’s record does not exist in the enrollment system from situation (2) where its record does exist, but no products are found that are active in the requested time-span.

In this example scenario the enrollment callout returns 2 enrollment products for this person so 2 dynamic records are attached to the eligibility check:

Product Start Date End Date

BASIC

01-JAN-2017

31-DEC-2017

DENTAL

01-JAN-2017

31-DEC-2017

Process Step 1 - Rule Step 2 - Enrollment Check

This validation rule checks if there are any enrollments found for this person. When no enrollment dynamic record is attached to the eligibility check the message on the validation rule is attached to the eligibility check and the system does not proceed with the second process step. In that case the status of the eligibility check is set to Denied. An example of a validation condition dynamic logic might look something like this:

// When there is no `enrollmentProduct` information recorded - that means that the
// enrollment callout did not return any applicable enrollments. In that case this validation should yield true
// and the message attached to that validation rule should be attached to the eligibility check
eligibilityCheck.enrollmentProduct == null

Process Step 2 - Rule Step 1 - Dental Enrollment Check

Intheexample scenario, process step 1 did not raise any fatal messages so the eligibility check continues with process step 2.

The first rule step checks if there is a dynamic record with product code 'DENTAL' attached to the eligibility check with a time validity on the service date in the request.

The block below contains the validation rule condition dynamic logic which could look something like this:

// When the enrollment information gathered from the external callout did not
// yield a result containing the `DENTAL` product, let the validation record a message accordingly
!eligibilityCheck.enrollmentProduct["productCode"].contains("DENTAL")
Note that the condition dynamic logic function of the validation rule should return false when the person is enrolled for the product on the requested service date.

Process Step 2 - Rule Step 2 - Provider in Network

The second rule step checks if the provider for which the request was initiated is in or out of network for product DENTAL. For this eligibility check it is sufficient to know whether the provider is in or out of network for the product. It is not relevant which network so no additional information needs to be stored on the eligibility check.

The block below contains the validation rule condition dynamic logic which could look something like this:

// Find a single provider group affiliation that
// 1 is valid from the perspective of time validity (start date of the affiliation before the request date)
// 2 refers to a product provider that
// 2.1 refers to the dental product and
// 2.2 which is valid from the perspective of time validity
// Finding a match for this situation does need require raising the validation message
!eligibilityCheck.provider.providerGroupAffiliationList.asOf(eligibilityCheck.requestDate).any { it ->
    new SearchBuilder(ProductProviderGroup.class)
            .join("product").by("code").eq("DENTAL").and()
            .by("providerGroup").eq(it.providerGroup).and()
            .by("startDate").lte(eligibilityCheck.requestDate).and()
            .group()
            .by("endDate").gte(eligibilityCheck.requestDate).or()
            .by("endDate").eq(null)
            .end()
            .execute()
            .size() > 0
}
Note that the condition dynamic logic function of the validation rule should return false when the provider is in the network.

Process Step 2 - Rule Step 3 - Country of Residence

The third and final rule step checks if the person’s country of residence is the United States or Canada. The country of residence in the request is Canada so no error message results from this validation.

The block below contains the validation rule dynamic logic, which could look something like this:

// When the EligibilityCheck country of residence registered is not part of
// 'Canada' or the 'United States' validation must add a message accordingly
!["Canada", "United States"].contains(eligibilityCheck.countryOfResidence)
Note that the condition dynamic logic function of the validation rule should return false when the country of residence is United States or Canada.

Complete the Eligibility Check

After the last rule step of the last process step has been completed, the status of the eligibility check is set to Approved because no fatal messages are attached to the eligibility check.

Get Eligibility Response

After the external system receives HTTP 201 (Created) with Location header response, the external system can use that Location header information to start checking the progress of the eligibility check process. Eventually this eligibility status resource will indicate that the process has been completed. Subsequently the external system can invoke the eligibility check service to get the created response. The response is constructed via a piece of dynamic logic and typically leverages information stored on the eligibility check.

The block below provides an example on what the response dynamic logic could look like, that creates the response:

import groovy.xml.StreamingMarkupBuilder

markupBuilder = new StreamingMarkupBuilder()

// Constructs a piece of XML that serves as the `EligibilityCheck` response maker.
xml = markupBuilder.bind { builder ->

    eligibilityCheckAttributes = eligibilityHeader(eligibilityCheck)
    eligibility(eligibilityCheckAttributes) {
        if (eligibilityCheck.eligibilityCheckMessageList.size() > 0) {
            buildMessages builder, eligibilityCheck.eligibilityCheckMessageList
        }
    }

}

return xml.toString()

// This method will construct the EligibilityCheck `header` with attributes. As some of
// these attributes are optional (e.g. validFrom, validTo) to have extra control
// of not outputting empty attributes.
def eligibilityHeader(eligibilityCheck) {
    atts = ["code": eligibilityCheck.code, "status": eligibilityCheck.checkStatus]
    if (eligibilityCheck.requestDate != null)
        atts.put("requestDate", eligibilityCheck.requestDate)
    if (eligibilityCheck.validFrom != null)
        atts.put("startDate", eligibilityCheck.validFrom)
    if (eligibilityCheck.validTo != null)
        atts.put("endDate", eligibilityCheck.validTo)

    return atts;
}

// This method is responsible for creating the `messages` child element. It should be called
// whenever the number of `messages` contained by the EligibilityCheck is larger than 0.
def buildMessages(builder, messages) {
    builder.messages {
        messages.collect { EligibilityCheckMessage m ->
            message(code: m.messageCode, text: m.messageText)
        }
    }
}

The block below contains an example response message in XML.

<eligibility
  code="00000000000001"
  status="Approved"
  requestDate="2017-11-11"
 ; startDate="2017-01-01"
  endDate="2017-12-31"
/>

Scenario 2: Eligibility Check Denied

This example covers a scenario where the person and provider could be matched in Claims, the person is enrolled in the Policy Admin system but fails some additional requirements.

This scenario has the same eligibility request sent in.

The configuration differs in two places:

  1. The enrollment callout in process step 1 returns only the BASIC product, not DENTAL

  2. The country of residence validation rule requires the person to be resident of the United States only.

The eligibility check request is handled in the same way as in the previous scenario. The eligibility check is stored in Claims, the eligibility check code is send back to the external system and the process steps are executed.

Process Step 1

Process step 1 returns an enrollment product for this person so it is completed successfully. Because process step 1 did not result in any fatal messages, process step 2 is also executed.

Process Step 2

All rule steps in the process step are evaluated with the following result:

Rule Step Result Action

1

Error

Message defined on validation rule "Dental Enrollment check" is attached to eligibility check

2

Success

-

3

Error

Message defined on validation rule "Country of residence" is attached to eligibility check

Two fatal messages are attached to the eligibility check and the status is set to Denied.

Eligibility Response

The block below contains an example response message in XML.

<eligibility
  code="00000000000001"
  status="Denied">
  <messages>
    <message
      code="ELIG-002-DENTAL"
      text="Person is not enrolled for product DENTAL"/>
    <message
      code="ELIG-004-COR"
      text="Person is not a resident of the United States"/>
  </messages>
</eligibility>
The messages are user configured messages defined on the validation rules.

Scenario 3: Eligibility Check Denied (Unknown Person)

This example covers the scenario where the person that is sent in in the eligibility check request could not be found in Claims. Again, the same request is sent in.

The fixed logic of the eligibility check service tries to find the person based n the provided social security number. In this example the person could not be identified so a fatal message is attached to the eligibility check and the status is set to Denied.

Because there is already a fatal message is attached to the eligibility check, the process steps are not executed.

Eligibility Response

The block below contains an example response message in pseudo code.

<eligibility
  code="00000000000001"
  status="Denied">
  <messages>
    <message
      code="CLA-IP-ELCH-001"
      text="Person not found for the criteria provided."/>
  </messages>
</eligibility>