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:
- 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.
- 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 | |
---|---|
OrganizationId | Name |
ACME | ACME Org. |
Facilities | ||||||
---|---|---|---|---|---|---|
FacilityId | OrganizationId | Name | Timezone | NFCEnabled | NFCSelfModificationEnabled | BarCodeEnabled |
ACME-PH | ACME | Pearl Harbor | US/Hawaii | true | false | false |
Note: the facility has support for NFC tag identification for Users and Patients.
Workspaces | |||
---|---|---|---|
WorkspaceId | FacilityId | Name | Description |
PH-Nursery | ACME-PH | Nursery | Nursery Workspace of Pearl Harbor |
PH-Nicu | ACME-PH | NICU | NICU Workspace of Pearl Harbor |
Rooms | ||
---|---|---|
RoomId | WorkspaceId | Name |
PH-N-poda | PH-Nursery | Pod A |
PH-N-podb | PH-Nursery | Pod B |
PH-A-poda | PH-Nicu | Pod A |
PH-A-podb | PH-Nicu | Pod B |
2. Organization's metadata
OrganizationMetadata | |||
---|---|---|---|
OrganizationMetadataId | OrganizationId | Abbreviation | PatientSeq |
1 | ACME | ACM | 8 |
A sample of a Chart Id for patients of this Organization is: ACM0914-001
3. Organization's Roles and Permissions
Roles | |||
---|---|---|---|
Id | Name | Description | OrganizationId |
1 | Admin | This represents an Admin for ACME Org. | ACME |
2 | Nurse | This 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 | |||
---|---|---|---|
Id | RoleId | PermissionName | OrganizationId |
1 | 1 | list_organizations | |
2 | 1 | read_organization | ACME |
3 | 1 | list_facilities | ACME |
4 | 1 | read_facility | ACME |
5 | 1 | list_workspaces | ACME |
6 | 1 | read_workspace | ACME |
7 | 1 | list_rooms | ACME |
8 | 1 | read_room | ACME |
9 | 1 | list_roles | ACME |
10 | 1 | read_role | ACME |
11 | 1 | list_users | ACME |
12 | 1 | read_user | ACME |
13 | 1 | delete_user | ACME |
14 | 1 | modify_user | ACME |
15 | 1 | modify_own_user | |
16 | 1 | modify_user_nfc_tag | ACME |
17 | 1 | list_patients_from_current_organization | |
18 | 1 | list_discharged_patients | ACME |
19 | 1 | read_alerts_from_entire_organization | |
20 | 1 | send_messages | |
21 | 2 | list_rooms | ACME |
22 | 2 | read_room | ACME |
23 | 2 | read_user | ACME |
24 | 2 | modify_own_user | |
25 | 2 | list_patients_from_current_facility | |
26 | 2 | list_discharged_patients | ACME |
27 | 2 | discharge_patients | ACME |
28 | 2 | final_discharge_patients | ACME |
29 | 2 | read_alerts_only_from_associated_patients |
4. Organization's Users and Patients
Users | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
UserId | Username | Pin | TagId | Password | UpdateDate | RoleId | FistName | LastName | FacilityId | Status | |
ACME-U1 | admin | 1c3b637c7bbf0b2fae454d8fc563b3103522896f | 000000003ec47563013ed8b51 | admin@acme.org | 58e6b3a414a1e090dfc6029add0f3555ccba127f | 2014-09-02 13:35:20 | 1 | John | Jovi | ACME-PH | ACTIVE |
ACME-U2 | nurse1 | 23bad90c7bbf0b2fae454d8fc563b31046daac9f | 000000003ecae23092bbc8b98 | nurse1@acme.org | 23bad90c7bbf0b2fae454d8fc563b31046daac9f | 2014-09-02 13:35:20 | 2 | Mary | Stewart | ACME-PH | ACTIVE |
ACME-U3 | nurse2 | 329884cnad78df9a9bcc0a6512abd43019fbb32 | 000000003ec47563013edaaa3 | nurse2@acme.org | 329884cnad78df9a9bcc0a6512abd43019fbb32 | 2014-09-02 13:35:20 | 2 | Rachel | Gandolfini | ACME-PH | ACTIVE |
Note: Pin and Password columns are SHA1ed.
Patients | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Guid | ChartId | TagId | GestationalAge | Weight | DischargeDate | CreateDate | Creator | RoomId | Length | HeadCircumference | AdmissionDate | DeliveryType | FinalDischargeDate | UpdateDate | UpdateBy | CalculatedDOB | Survive | ExcludeFromStudy |
1 | ACM0914-001 | 000000003ec47563013ed0001 | 25 | 900 | 2014-09-02 13:35:20 | ACME-U2 | PH-N-poda | 60 | 20 | 2014-09-02 13:35:20 | Inborn | 2014-08-30 07:00:00 | ||||||
2 | ACM0914-002 | 000000003ec47563013ed0002 | 25 | 875 | 2014-09-02 13:35:20 | ACME-U2 | PH-N-poda | 75 | 26 | 2014-09-02 13:35:20 | Outborn | 2014-08-30 07:00:00 | ||||||
3 | ACM0914-003 | 000000003ec47563013ed0003 | 23 | 925 | 2014-09-02 13:35:20 | ACME-U2 | PH-N-podb | 75 | 24 | 2014-09-02 13:35:20 | Inborn | 2014-09-02 13:35:20 | ||||||
4 | ACM0914-004 | 000000003ec47563013ed0004 | 20 | 780 | 2014-09-02 13:35:20 | ACME-U2 | PH-N-podb | 69 | 26 | 2014-09-02 13:35:20 | Inborn | 2014-09-02 13:35:20 | ||||||
5 | ACM0914-005 | 000000003ec47563013ed0005 | 27 | 1100 | 2014-09-02 13:35:20 | ACME-U3 | PH-A-poda | 80 | 27 | 2014-09-02 13:35:20 | Inborn | 2014-09-02 13:35:20 | ||||||
6 | ACM0914-006 | 000000003ec47563013ed0006 | 24 | 700 | 2014-09-02 13:35:20 | ACME-U3 | PH-A-poda | 68 | 25 | 2014-09-02 13:35:20 | Inborn | 2014-09-02 13:35:20 | ||||||
7 | ACM0914-007 | 000000003ec47563013ed0007 | 26 | 1000 | 2014-09-02 13:35:20 | ACME-U3 | PH-A-podb | 90 | 30 | 2014-09-02 13:35:20 | Outborn | 2014-09-02 13:35:20 | ||||||
8 | ACM0914-007 | 000000003ec47563013ed0008 | 24 | 768 | 2014-09-02 13:35:20 | ACME-U3 | PH-A-podb | 88 | 28 | 2014-09-02 13:35:20 | Inborn | 2014-09-02 13:35:20 |
5. Organization's Devices
Device | |||||||
---|---|---|---|---|---|---|---|
Id | StockNumber | Model | MacAddress | SerialNumber | Status | Name | Description |
1 | 1 | Nexus 5 | 50:5d:46:1e:f6:3f | 015d2a504c0c0a0e | ACTIVE | Nexus 5 | This is a Nexus 5 device |
2 | 2 | Nexus 7 | cc:fa:ab:00:1e:dc | 04a4edd425730a16 | ACTIVE | Nexus 7 | This is a Nexus 7 device |
DeviceAssignment | |
---|---|
DeviceId | RoomId |
1 | PH-N-poda |
2 | PH-A-poda |
6. Organiation's Survey Templates
FacilitySurveyTemplate | ||
---|---|---|
FacilitySurveyTemplateId | SurveyId | FacilityId |
1 | 5 | ACME-PH |
2 | 6 | ACME-PH |
3 | 9 | ACME-PH |
4 | 10 | ACME-PH |
5 | 4 | ACME-PH |
Note: The values of SurveyId column comes from SurveyTemplates table. The currently supported templates are:
SurveyTemplates | |
---|---|
SurveyId | Name |
1 | New Line Report |
2 | Line Maintenance |
3 | Infection Report |
4 | Breast Milk Report |
5 | Patient Demographics |
6 | Patient Discharge |
7 | Patient Open Lines |
8 | Form Open Lines |
9 | Admission Questions |
10 | Patient Final Discharge |
11 | AUDIT |
12 | MDQ |
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 | |||||
---|---|---|---|---|---|
Id | Name | Description | AlertKey | WorkspaceId | SendNotification |
1 | New Patient Admission | PH-Nursery | True | ||
2 | Milk Importance Not Discussed | PH-Nursery | True | ||
3 | New Patient Admission | PH-Nicu | True | ||
4 | Milk Importance Not Discussed | PH-Nicu | True |
AlertConfigurationUserRecipient | ||
---|---|---|
Id | AlertConfigurationId | UserId |
1 | 1 | ACME-U1 |
2 | 3 | ACME-U1 |
AlertConfigurationRoleRecipient | ||
---|---|---|
Id | AlertConfigurationId | RoleId |
1 | 2 | 2 |
2 | 4 | 2 |