Example

Table of Contents

New Organization Requirements

The new organization (called 'ACME') is composed by 1 facility and 2 workspaces. Each workspace has 2 rooms containing 2 patients each.

The organization has 3 users: one of role Admin and two of role Nurse. The organization only has 2 devices.

The only available surveys for this organization are Admission/Demographics/Discharge and Human Breast Milk report.

The ACME organization is only interested in 2 alerts:

  1. When a patient is admitted, send an alert to the user with 'Admin' role. The alert is specific to the user and not to the role.
  2. When a Human Breast Milk report is submitted, inform any user with role 'Nurse' (that is currently assigned to the patient that generated the submission) if the answer for question "Did you discuss the importance of providing milk or reviewed the pumping log?" is "No".

1. Organization Structure

Organizations
OrganizationIdName
ACMEACME Org.
Facilities
FacilityIdOrganizationIdNameTimezoneNFCEnabledNFCSelfModificationEnabledBarCodeEnabled
ACME-PHACME

 Pearl Harbor

US/Hawaii

truefalsefalse

Note: the facility has support for NFC tag identification for Users and Patients.

 

Workspaces
WorkspaceIdFacilityIdNameDescription
PH-NurseryACME-PHNurseryNursery Workspace of Pearl Harbor
PH-NicuACME-PHNICUNICU Workspace of Pearl Harbor
Rooms
RoomIdWorkspaceIdName
PH-N-podaPH-NurseryPod A
PH-N-podbPH-NurseryPod B
PH-A-podaPH-NicuPod A
PH-A-podbPH-NicuPod B

2. Organization's metadata

OrganizationMetadata
OrganizationMetadataIdOrganizationIdAbbreviationPatientSeq
1ACMEACM8

A sample of a Chart Id for patients of this Organization is: ACM0914-001 

3. Organization's Roles and Permissions

Roles
IdNameDescriptionOrganizationId
1AdminThis represents an Admin for ACME Org.ACME
2NurseThis represents an Nurse for ACME Org.ACME

The RolePermission entries bellow are just an example. Different organizations could allow or restrict certain operations to different roles in different ways.

RolePermissions
IdRoleIdPermissionNameOrganizationId
11list_organizations 
21read_organizationACME
31list_facilitiesACME
41read_facilityACME
51list_workspacesACME
61read_workspaceACME
71list_roomsACME
81read_roomACME
91list_rolesACME
101read_roleACME
111list_usersACME
121read_userACME
131delete_userACME
141modify_userACME
151modify_own_user 
161modify_user_nfc_tagACME
171list_patients_from_current_organization 
181list_discharged_patientsACME
191read_alerts_from_entire_organization 
201send_messages 
212list_roomsACME
222read_roomACME
232read_userACME
242modify_own_user 
252list_patients_from_current_facility 
262list_discharged_patientsACME
272discharge_patientsACME
282final_discharge_patientsACME
292read_alerts_only_from_associated_patients 

4. Organization's Users and Patients

Users
UserIdUsernamePinTagIdEmailPasswordUpdateDateRoleIdFistNameLastNameFacilityIdStatus
ACME-U1admin1c3b637c7bbf0b2fae454d8fc563b3103522896f000000003ec47563013ed8b51admin@acme.org58e6b3a414a1e090dfc6029add0f3555ccba127f2014-09-02 13:35:201JohnJoviACME-PHACTIVE
ACME-U2nurse123bad90c7bbf0b2fae454d8fc563b31046daac9f000000003ecae23092bbc8b98nurse1@acme.org23bad90c7bbf0b2fae454d8fc563b31046daac9f2014-09-02 13:35:202MaryStewartACME-PHACTIVE
ACME-U3nurse2329884cnad78df9a9bcc0a6512abd43019fbb32000000003ec47563013edaaa3nurse2@acme.org329884cnad78df9a9bcc0a6512abd43019fbb322014-09-02 13:35:202RachelGandolfiniACME-PHACTIVE

Note: Pin and Password columns are SHA1ed.

 

Patients
GuidChartIdTagIdGestationalAgeWeightDischargeDateCreateDateCreatorRoomIdLengthHeadCircumferenceAdmissionDateDeliveryTypeFinalDischargeDateUpdateDateUpdateByCalculatedDOBSurviveExcludeFromStudy
1ACM0914-001000000003ec47563013ed000125900 2014-09-02 13:35:20ACME-U2PH-N-poda60202014-09-02 13:35:20Inborn   2014-08-30 07:00:00  
2ACM0914-002000000003ec47563013ed000225875 2014-09-02 13:35:20ACME-U2PH-N-poda75262014-09-02 13:35:20Outborn   2014-08-30 07:00:00  
3ACM0914-003000000003ec47563013ed000323925 2014-09-02 13:35:20ACME-U2PH-N-podb75242014-09-02 13:35:20Inborn   2014-09-02 13:35:20  
4ACM0914-004000000003ec47563013ed000420780 2014-09-02 13:35:20ACME-U2PH-N-podb69262014-09-02 13:35:20Inborn   2014-09-02 13:35:20  
5ACM0914-005000000003ec47563013ed0005271100 2014-09-02 13:35:20ACME-U3PH-A-poda80272014-09-02 13:35:20Inborn   2014-09-02 13:35:20  
6ACM0914-006000000003ec47563013ed000624700 2014-09-02 13:35:20ACME-U3PH-A-poda68252014-09-02 13:35:20Inborn   2014-09-02 13:35:20  
7ACM0914-007000000003ec47563013ed0007261000 2014-09-02 13:35:20ACME-U3PH-A-podb90302014-09-02 13:35:20Outborn   2014-09-02 13:35:20  
8ACM0914-007000000003ec47563013ed000824768 2014-09-02 13:35:20ACME-U3PH-A-podb88282014-09-02 13:35:20Inborn   2014-09-02 13:35:20  

5. Organization's Devices

Device
IdStockNumberModelMacAddressSerialNumberStatusNameDescription
11Nexus 550:5d:46:1e:f6:3f015d2a504c0c0a0eACTIVENexus 5This is a Nexus 5 device
22Nexus 7cc:fa:ab:00:1e:dc04a4edd425730a16ACTIVENexus 7This is a Nexus 7 device
DeviceAssignment
DeviceIdRoomId
1PH-N-poda
2PH-A-poda

6. Organiation's Survey Templates

FacilitySurveyTemplate
FacilitySurveyTemplateIdSurveyIdFacilityId
15ACME-PH
26ACME-PH
39ACME-PH
410ACME-PH
54ACME-PH

Note: The values of SurveyId column comes from SurveyTemplates table. The currently supported templates are:

SurveyTemplates
SurveyIdName
1New Line Report
2Line Maintenance
3Infection Report
4Breast Milk Report
5Patient Demographics
6Patient Discharge
7Patient Open Lines
8Form Open Lines
9Admission Questions
10Patient Final Discharge
11AUDIT
12MDQ

7. Organization's Alerts

7.1 SurveyAgent

Remember that Alerts are generated by the SurveyAgent. For this scenario we are going to have 2 rules generating alerts: 'New Patient Admission" and "Milk Importance Not Discussed".

For this scenario, we are going to place both rules in a single .drl file. The name of the file will be ACME-alerts.drl

 

package org.socraticgrid.survey.agent;
import org.drools.mas.body.content.*;
import org.drools.mas.action.message.*;
import org.drools.mas.action.message.types.*;
import org.drools.mas.action.message.invokers.*;
import org.socraticgrid.survey.agent.api.model.SurveySubmissionFact;
import org.socraticgrid.survey.agent.api.model.SurveySubmissionAnswerFact;
import org.socraticgrid.survey.agent.api.model.PreValidationResult;
import org.socraticgrid.survey.agent.log.RulesLoggerHelper;
import org.socraticgrid.surveys.model.*;
import org.socraticgrid.surveys.service.SurveyService;
import org.socraticgrid.alertmanager.service.AlertService;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;
import org.drools.mas.action.helpers.*;
/* Global Services */
global SurveyService surveyService;
global AlertService alertService;
global Logger logger;
 
rule "New Patient Admission"
when
    //There is a Submission of a #5 Survey
    //And there alert was not previously sent.
    $s: SurveySubmissionFact(
            surveyId == 5,
            $chartId: q["q008"],
            alertService.parameterizedAlertExists($s.getPatientId(), "New Patient Admission") == false
    )
then
    RulesLoggerHelper.debug(logger, drools, "New Admission detected: {}", $s);

    templateVariables.put("common_patient_chartId", $chartId);
    insert( new ResolvableActionAgentNotificationCandidateFact(
        drools.getRule().getName(),     //sourceRule
        "ADMISSION",                    //sourceProgram
        (SurveySubmissionFact)$s,       //sourceFact
        $s.getPatientId(),              //sourcePatient
        "HIGH",                         //priority
        "ACME-NewAdmission",            //template
        "10s",                          //timeout
        templateVariables               //template variables
));
end

rule "Milk Importance Not Discussed"
when
    //There is a Submission of a #4 Survey
    $s: SurveySubmissionFact(
            surveyId == 4,
            q["q007"] == "No"
    )
then
    RulesLoggerHelper.debug(logger, drools, "Milk Importance Not Discussed: {}", $s);
    insert( new ResolvableActionAgentNotificationCandidateFact(
        drools.getRule().getName(),     //sourceRule
        "NCCC",                         //sourceProgram
        (SurveySubmissionFact)$s,       //sourceFact
        $s.getPatientId(),              //sourcePatient
        "HIGH",                         //priority
        "ACME-NotDiscussed",            //template
        "10s",                          //timeout
        null                            //template variables
));
end

Some important notes about ACME-alerts.drl are:

  • Lines #25 and #50 define the 2 rules
  • In "New Patient Admission" rule (the other rule is similar):
    • Line #35 logs information
    • Line #37 inserts a new ResolvableActionNotificationCandidateFact that will end up notifying the ActionAgent about a new Alert.
    • Line #44 specifies the Template id that we want to use. Templates and their Ids are defined in the ActionAgent.

The next step is to create a change-set that includes all the necessary .drl files. Let's call this file ACME-change-set.xml.

 

<?xml version="1.0" encoding="UTF-8"?>
<change-set xmlns='http://drools.org/drools-5.0/change-set' xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd'>
    <add>
        <resource type="DRL" source="classpath:org/drools/mas/acl_common.drl" />
        <resource type="DRL" source="classpath:knowledge/subsession/subsession-config.drl" />
        <resource type="DRL" source="classpath:knowledge/subsession/survey-common.drl" />
        <resource type="DRL" source="classpath:knowledge/subsession/survey-prevalidation-common.drl" />
        <resource type="DRL" source="classpath:knowledge/subsession/survey-alert-common.drl" />
        <resource type="DRL" source="classpath:knowledge/subsession/ACME-alerts.drl" />
    </add>
</change-set>

Some important notes about the change-set:

  • From line #5 to line #9 we have some common .drl that should be included in any session.
  • Line #10 includes the .drl we have specifically created for ACME organization.

 

Once we have the rules and the change-set we need to define a new sub-session for ACME in applicationContext.xml file:

<bean id="ACME" class="org.drools.mas.core.DroolsAgentConfiguration$SubSessionDescriptor">
    <constructor-arg value="subsession-acme"/>
    <constructor-arg value="ACME-change-set.xml"/>
    <constructor-arg value="${agent.node}"/>
    <constructor-arg>
        <map>
            <entry key="organizationId" value="ACME"/>
        </map>
    </constructor-arg>
</bean>
...
<bean id="${agent.name}-configuration" class="org.drools.mas.core.DroolsAgentConfiguration">
    <property name="agentId" value="${agent.name}"/>
    <property name="changeset" value="agent_changeset.xml" />
    <!-- by default the mindNodeLocation is local --> 
    <property name="mindNodeLocation" value="${agent.node}"/>
    <property name="subSessions">
        <list>
            ...
            <ref local="${agent.name}-unc"/>
        </list>
    </property>
</bean>

Important notes about the contextApplication.xml file:

  • Line #1 defines the new sub-session for ACME organization.
  • Line #20 includes this new sub-session as part of the main session of the agent.

The last step is to add the routing statement in agent_cbr.drl:

rule "Mapping"
when
then
    ...
    insert( new SessionMapping("ACME","subsession-acme") );
    RulesLoggerHelper.debug(logger, drools, "Subsession mapping created for 'ACME');
    ... 
end

7.2 Alerts Configuration

AlertConfiguration
IdNameDescriptionAlertKeyWorkspaceIdSendNotification
1  New Patient AdmissionPH-NurseryTrue
2  Milk Importance Not DiscussedPH-NurseryTrue
3  New Patient AdmissionPH-NicuTrue
4  Milk Importance Not DiscussedPH-NicuTrue
AlertConfigurationUserRecipient
IdAlertConfigurationIdUserId
1 1 ACME-U1
2 3 ACME-U1
AlertConfigurationRoleRecipient
IdAlertConfigurationIdRoleId
1 2 2
2 4 2