EC to Case Model Breakdown
As shown in the EC Data Model diagram, the client app runs on two SQLite databases. One is used by Cloudant sync API to save EC data in form of JSON documents whereas the other is used to store registers view data in relational tables for easier display,searching and sorting. Whenever a user saves a form submission or syncs data from the server, the data (EC) is stored in the cloudant db and after either of the two operations is complete the process of converting EC data to the case model is started immediately by invoking ClientProcessor.getInstance(mContext).processClient() method. To be able to break down events and clients JSON documents to different cases (register tables), two JSON config mapping files are required in each site module as the reference point to ClientProcessor Java logic to determine which fields to pull from the EC documents and which table to populate in the registers database. To listen on when sync process is completed, in CloudantSyncHandler.reloadReplicationSettings(), CloudantSyncHandler class is registered as a listener to both pull and push replicator instances. Further, a method (complete()) is created in CloudantSyncHandler class with the annotation @Subscribe and cloudant ReplicationCompleted param type and it's the method Cloudant API will invoke on completing the replication process.
ec_client_classification.json
{ "case_classification_rules": [ { "comment": "ANC: This rule checks whether a given case belongs to ANC register", "rule": { "type": "event", "fields": [ { "field":"obs.fieldCode", "concept": "162942AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "value": ["1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"], "closes_case":["ec_elco","ec_pnc"], "creates_case":["ec_mcaremother"] }, { "field":"obs.fieldCode", "concept": "161641AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "value": ["125872AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"], "closes_case":["ec_mcaremother"], "creates_case":["ec_elco"] }, { "field":"eventType", "field_value": "ANC Reminder Visit 1", "closes_case":["ec_elco"], "creates_case":["ec_mcaremother"] }, { "field":"eventType", "field_value": "ANC Reminder Visit 2", "closes_case":["ec_elco","ec_pnc"], "creates_case":["ec_mcaremother"] }, { "field":"eventType", "field_value": "ANC Reminder Visit 3", "closes_case":["ec_elco","ec_pnc"], "creates_case":["ec_mcaremother"] }, { "field":"eventType", "field_value": "ANC Reminder Visit 4", "closes_case":["ec_elco","ec_pnc"], "creates_case":["ec_mcaremother"] } ] } } ] }
The following is a brief description of the JSON keys under fields JSON array
JSON KEY | Notes |
---|---|
field | This is the name of an existing field in the event document mostly either of obs.fieldCode, eventType |
field_value | This is the value to the json key (field name) specified by the 'field' above. Most of the times will either be a concept question or an encounter type |
value | This is the answer to a question but in form of a concept |
concept | Values in the obs section of an event are mostly concepts, this key specifies the encounter question in concept form |
closes_case | These are the cases to close e.g When a woman is recorded as pregnant in the PSRF form anc(ec_mcaremother) case is opened and the woman is removed from the elco register(ec_elco) |
creates_case | These are cases which are opened by various events. If an existing event in the db has any field that satisfies the set conditions a new record is created or updated in the table(s) specified here |
This json mapping config file is used to determine which cases to create or close. After pulling events from the cloudant database, every event is checked against each of the classification rules specified in this file to see if the event opens or closes any case. e.g In the example above, the client processor logic in ClientProcessor.processClient() method iterates through each of the items in an event's obs section to check if any has obs.fieldCode==162942AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA and obs.value==1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA and if so adds a woman to anc register and removes the woman from either the elco or pnc register. In the mappings that have the field as 'eventType', the processor checks if an event is of the specified type and creates/closes cases accordingly.
ec_client_fields.json
This json_mapping file specifies table column names and the source of the values to be populated into the columns. This file is loaded in the ClientProcessor.processCaseModel() method to act as a guide in retrieving column values from the event being processed for each of the tables specified in a classification rule's creates_case json array. e.g If an event satisfies any of the creates_case conditions specified in the ec_client_classification.json file, ClientProcessor.processCaseModel() method iterates through the creates_case tables, loads the column mappings, iterates again through each of the columns definition to retrieve the json_mapping values to compare against the event being processed to see if the a column should be populated with the value from the event. For each record created in the tables, client base_entity_id acts as the primary key in such a way that continuous processing of events that affect a single client in a given case/table leads to only a single row being created with every other subsequent processing updating this row.
{ "bindobjects": [ { "name": "ec_mcaremother", "columns": [ { "column_name": "base_entity_id", "type": "Client", "json_mapping": { "field": "baseEntityId" } }, { "column_name": "FWPSRLMP", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "concept": "1427AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWVG", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "concept": "163090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWHRP", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "concept": "163092AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWHR_PSR", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "concept": "163091AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWANC1DATE", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "event_type": "ANC Reminder Visit 1", "concept": "160753AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWANC2DATE", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "event_type": "ANC Reminder Visit 2", "concept": "160753AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWANC3DATE", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "event_type": "ANC Reminder Visit 3", "concept": "160753AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } }, { "column_name": "FWANC4DATE", "type": "Event", "json_mapping": { "field": "obs.fieldCode", "event_type": "ANC Reminder Visit 4", "concept": "160753AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" } } ] }] }
JSON KEY | Notes |
---|---|
column_name | SQLite table column name |
type | Where to fetch the value specified in the json_mapping from, either from the Event or Client document |
field | The json key to retrieve the column value from |
event_type | As of now some events can only be differentiated from each other through the event type e.g pnc,anc events |
concept | The concept value of the EC document key specified by the 'field' key above |
NB: For all the other fields that are not added to the case registers/tables, they're saved in the ec_details table.
ec_details has four columns:
- base_entity_id column stores the client entity id,
- key has the field name as it appears in the form submissions
- value is the field value
- timestamp is the current time
This table stores a unique entity_id, key, value row meaning that, for each field the latest value is the only one that's stored here
This site is no longer maintained. Please visit docs.opensrp.io for current documentation.