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 KEYNotes
field
This is the name of an existing field in the event document mostly either of obs.fieldCode, eventType
field_valueThis 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
valueThis is the answer to a question but in form of a concept
conceptValues in the obs section of an event are mostly concepts, this key specifies the encounter question in concept form
closes_caseThese 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_caseThese 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 KEYNotes
column_nameSQLite table column name
typeWhere to fetch the value specified in the json_mapping from, either from the Event or Client document
fieldThe json key to retrieve the column value from
event_typeAs of now some events can only be differentiated from each other through the event type e.g pnc,anc events
conceptThe 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