opensrp / fhircore

FHIR Core / OpenSRP 2 is a Kotlin application for delivering offline-capable, mobile-first healthcare project implementations from local community to national and international scale using FHIR and WHO Smart Guidelines on Android.
https://smartregister.org
Apache License 2.0
50 stars 39 forks source link

Add related person fields to registration questionnaire #184

Closed f-odhiambo closed 2 years ago

f-odhiambo commented 3 years ago

Based on the FHIR spec we would like to have related person's details appended to the patient registration process. FHIR spec for a related person link here

Related person details to be capture

  1. Family name
  2. First name
  3. Relationship to patient
  4. Contact a. telecom (phone number) b. telecom (alternative phone number)

For this

  1. The registration details can be bundled i.e. Patient resource and Related person resource
  2. The resources can be extracted and saved as separate resources upon save/submit

Subtasks

cc. @syedowaisali90 Also liaise with @shoaibmushtaq25 on issue #183 as he also incorporates some of the styling based on shared designs on #fhirdevs channel

Attached mock

Screen Shot 2021-05-31 at 12 12 31 PM
f-odhiambo commented 3 years ago

We need to unblock this feature implementation. At the moment we do not have a way in which we can be able to extract multiple resources from a single questionnaire

pld commented 3 years ago

Is the related person to add a parent or guardian? We should say that then, the term "related person" does not sound appropriate for a user

f-odhiambo commented 3 years ago

Update

  1. Structure map based extraction
  2. Definition support to be used in place once UUID work is complete
  3. Create a subtask for this issue
ekigamba commented 2 years ago

StructureMap used to perform extraction

map "http://hl7.org/fhir/StructureMap/PatientRegistration" = 'PatientRegistration'

uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireReponse" as source
uses "http://hl7.org/fhir/StructureDefinition/Bundle" as target
uses "http://hl7.org/fhir/StructureDefinition/Patient" as target
uses "http://hl7.org/fhir/StructureDefinition/Patient" as source

group PatientRegistration(source src : QuestionnaireResponse, target bundle: Bundle) {
    src -> bundle.id = uuid() "rule_c";
    src -> bundle.type = 'collection' "rule_b";
    src -> bundle.entry as entry, entry.resource = create('Patient') as patient then
        ExtractPatient(src, patient), ExtractRelatedPerson(src, bundle, patient) "rule_i";
}

group ExtractPatient(source src : QuestionnaireResponse, target patient : Patient) {
    src -> patient.id = uuid() "rule_j";

    src.item as item where(linkId = 'PR') then {
       item.item as inner_item where (linkId = 'patient-0-birth-date') then {
           inner_item.answer first as ans then { 
               ans.value as val -> patient.birthDate = val "rule_a";
           };
       };

       item.item as nameItem where(linkId = 'PR-name') -> patient.name = create('HumanName') as patientName then {  
          src -> patientName.family = evaluate(nameItem, $this.item.where(linkId = 'PR-name-family').answer.value) "rule_d";
          src -> patientName.given = evaluate(nameItem, $this.item.where(linkId = 'PR-name-given').answer.value) "rule_e";
       };

       src -> patient.gender = evaluate(item, $this.item.where(linkId = 'patient-0-gender').answer.value.code) "rule_f";
       item.item as telecomBlock where (linkId = 'PR-telecom') -> patient.telecom = create('ContactPoint') as patientContact then {
          src -> patientContact.value = evaluate(telecomBlock, $this.item.where(linkId = 'PR-telecom-value').answer.value) "rule_f1";
          src -> patientContact.system = "phone" "rule_f2";
          src -> patientContact.rank = create('positiveInt') as posInt then {
            src -> posInt.value = "1" "rule_f5";
          } "rule_f3";
       } "rule_f4";
       src -> patient.active = evaluate(item, $this.item.where(linkId = 'PR-active').answer.value) "rule_h";
       item.item as addressBlock where (linkId = 'PR-address') -> patient.address = create('Address') as patientAddress then {
          src -> patientAddress.city = evaluate(addressBlock, $this.item.where(linkId = 'PR-address-city').answer.value) "rule_g1";
          src -> patientAddress.country = evaluate(addressBlock, $this.item.where(linkId = 'PR-address-country').answer.value) "rule_g2";
          src -> patientAddress.use = "home" "rule_g3";
          src -> patientAddress.type = "physical" "rule_g4";
       } "rule_g";
    };
}

group ExtractRelatedPerson(source src : QuestionnaireResponse, target bundle : Bundle, source patientId : Patient) {
    src -> bundle.entry as entry, entry.resource = create('RelatedPerson') as relatedPerson then {
        src.item as item where(linkId = 'RP') then {
            src -> relatedPerson.name = create('HumanName') as relatedPersonName then {
                src -> relatedPersonName.family = evaluate(item, $this.item.where(linkId = 'RP-family-name').answer.value) "rule_erp_2";
                src -> relatedPersonName.given = evaluate(item, $this.item.where(linkId = 'RP-first-name').answer.value) "rule_erp_3";
            } "rule_erp_1";
            src -> evaluate(item, $this.item.where(linkId = 'RP-relationship').answer.value) as relationshipString then {
                src -> relatedPerson.relationship = cc("http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype", relationshipString) "rule_erp_4a";
            } "rule_erp_4";
            src -> relatedPerson.telecom = create('ContactPoint') as relatedPersonContact then {
                src -> relatedPersonContact.system = "phone" "rule_erp_5";
                src -> relatedPersonContact.value = evaluate(item, $this.item.where(linkId = 'RP-contact-1').answer.value) "rule_erp_6";
                src -> relatedPersonContact.rank = create('positiveInt') as posInt then {
                    src -> posInt.value = "1" "rule_erp_7a";
                } "rule_erp_7";
            } "rule_erp_7b";

            src -> relatedPerson.telecom = create('ContactPoint') as relatedPersonContact then {
                src -> relatedPersonContact.system = "phone" "rule_erp_8";
                src -> relatedPersonContact.value = evaluate(item, $this.item.where(linkId = 'RP-contact-alternate').answer.value) "rule_erp_9";
                src -> relatedPersonContact.rank = create('positiveInt') as posInt then {
                  src -> posInt.value = "2" "rule_erp_10b";
                } "rule_erp_10";
            } "rule_erp_10a";

            src -> relatedPerson.id = uuid() "rule_erp_11";
            patientId -> relatedPerson.patient = create('Reference') as patientReference then {
                patientId.id as thePatientId  -> patientReference.reference = thePatientId "rule_erp_12";
                src -> patientReference.type = "Patient" "rule_erp_13";
            } "rule_erp_13a";
        };
    } "rule_erp_14";
}
ekigamba commented 2 years ago

Update