1
votes

I am new to Drools and am trying to design some rules for a dental insurance application. The system will basically let users known when a procedure they are about to perform may not be covered by insurance based on the history of previously performed services. It will have other rules as well, which may be age based, but I can handle those.

My facts are:

  • Patient - Listing of patient information.
  • Services - Previously performed services. (ie: serviceCode=D1234, datePerformed=Date)
  • Alerts - (alertName = "Xrays 2/12 Month Period")

I need a rule which says WHEN a patient has had D1234 performed 2 or more times in the last 12 month period THEN add a warning saying that D1234 may not be covered by insurance until 12 months after date of last D1234 service.

Further complicating the situation is the fact that there could be groups of codes which are limited in the same way. So, the codes listed in the rule may be an array of codes and not just a single one, but the rule would still need to fire.

I could write a service to fetch all the services performed and just do it like that, but I would think it is nicer to just throw all the facts (previous services, etc) into Drools and let it work it all out. This way I could have a rule process run for each patient with their alerts and previous services as facts and the result with be a list of warnings.

Can someone help me understand how to write a rule like I need above?

1

1 Answers

4
votes

I will show you some examples of the different things you need to do, and leave it to you to combine them into a rule which works within your application.

Warning - I have not executed the following examples, so there may be bugs/typos.

First, the following piece of code will collect up all services performed on each patient in the working memory.

rule "Count patient services"
when
    $patient : Patient()
    $serviceList : ArrayList() from collect (
        Service(patientId == $patient.id)
    )
then
    System.out.println("Patient " + $patient.id 
        + " has received " + $serviceList.size() + " services.");
end

The following matches when a patient has received more than 2 services with a particular code:

$serviceList : ArrayList( size > 2 ) from collect (
    Service(
        patientId == $patient.id, 
        serviceCode == "D1234"
    )
)

The following matches when a patient has received more than 2 services matching a list of codes.

$serviceList : ArrayList( size > 2 ) from collect (
    Service(
        patientId == $patient.id, 
        serviceCode in ("D1234", "E5678")
    )
)

The following finds the most recent matching service date:

accumulate (
    Service(
        patientId == $patient.id, 
        serviceCode in ("D1234", "E5678"),
        $datePerformed: datePerformed
    );
    $mostRecentDate: max($datePerformed)
)

Likewise, you can add constraints on dates or other attributes.

An effective mechanism for maintaining code groups would be to insert group membership facts. A spreadsheet or web decision table can do this easily, or you could query a database and insert them via the API. i.e.

insert( new ServiceGroup( "HighCostService", "D1234" ) );
insert( new ServiceGroup( "HighCostService", "D5678" ) );

Then you can do the matching with constraints like this:

$highCostServices : ArrayList() from accumulate (
        ServiceGroup( group == "HighCostService", $serviceCode ),
        init( ArrayList list = new ArrayList(); ),
        action( list.add($serviceCode); ),
        reverse( list.remove($serviceCode); ),
        result(list)
)
$serviceList : ArrayList( size > 2 ) from collect (
    Service(
        patientId == $patient.id, 
        serviceCode in $highCostServices
    )
)

n.b. - Accumulators are rather easy to get wrong, so I usually put a few unit tests around them. The above code was written freehand in here without running it anywhere, so you may well be lucky if it works without corrections.

For more details, see the manual:

http://docs.jboss.org/drools/release/5.5.0.Final/drools-expert-docs/html_single/

Matching items which are in a list:

4.8.3.3.10.10. The operators in and not in (compound value restriction)

Collecting lists of matched facts:

4.8.3.7.3. Conditional Element collect

Accumulators for calculating max, min, sum, etc values for collections:

4.8.3.7.4.1. Accumulate CE (preferred syntax)