From de5457a9aa03d08d383d4af21872bc87ed5f6cfa Mon Sep 17 00:00:00 2001
From: Sahil Malhotra <smalhotra@mitre.org>
Date: Wed, 24 Aug 2022 08:08:16 -0400
Subject: [PATCH 1/2] rems endpoint updates

---
 .../davinci/endpoint/rems/DatabaseInit.java   |  41 ++-
 .../rems/controller/RemsController.java       | 335 +++++++++++++++---
 .../endpoint/rems/database/drugs/Drug.java    |  21 ++
 .../endpoint/rems/database/rems/Rems.java     |  22 +-
 .../database/requirement/MetRequirement.java  |  29 +-
 .../database/requirement/Requirement.java     |  27 +-
 6 files changed, 407 insertions(+), 68 deletions(-)

diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/DatabaseInit.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/DatabaseInit.java
index cc747bddc..d8b4e5a34 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/DatabaseInit.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/DatabaseInit.java
@@ -69,12 +69,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TuralioPatientEnrollmentResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TuralioPatientQuestionnaireResource = JacksonUtil.toJsonNode(TuralioPatientQuestionnaire);
             TuralioPatientEnrollmentResource.setResource(TuralioPatientQuestionnaireResource);
-            TuralioPatientEnrollmentResource.setId("turalio-patient-enrollment");
+            TuralioPatientEnrollmentResource.setId("TuralioRemsPatientEnrollment");
             remsFhirRepository.save(TuralioPatientEnrollmentResource);
             TuralioPatientEnrollmentRequirement.setName("Patient Enrollment");
+            TuralioPatientEnrollmentRequirement.setCreateNewCase(true);
             TuralioPatientEnrollmentRequirement.setResource(TuralioPatientEnrollmentResource);
             TuralioPatientEnrollmentRequirement.setDescription("Submit Patient Enrollment form to the REMS Administrator");
             TuralioPatientEnrollmentRequirement.setDrug(turalio);
+            TuralioPatientEnrollmentRequirement.setStakeholder("patient");
             requirementRepository.save(TuralioPatientEnrollmentRequirement);
 
              // prescriber enrollment form requirement
@@ -84,12 +86,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
              TuralioPrescriberEnrollmentResource.setResourceType(ResourceType.Questionnaire.toString());
              JsonNode TuralioPrescriberQuestionnaireResource = JacksonUtil.toJsonNode(TuralioPrescriberQuestionnaire);
              TuralioPrescriberEnrollmentResource.setResource(TuralioPrescriberQuestionnaireResource);
-             TuralioPrescriberEnrollmentResource.setId("turalio-prescriber-enrollment");
+             TuralioPrescriberEnrollmentResource.setId("TuralioPrescriberEnrollmentForm");
              remsFhirRepository.save(TuralioPrescriberEnrollmentResource);
              TuralioPrescriberEnrollmentRequirement.setName("Prescriber Enrollment");
+             TuralioPrescriberEnrollmentRequirement.setCreateNewCase(false);
              TuralioPrescriberEnrollmentRequirement.setResource(TuralioPrescriberEnrollmentResource);
              TuralioPrescriberEnrollmentRequirement.setDescription("Submit Prescriber Enrollment form and training certification to the REMS Administrator");
              TuralioPrescriberEnrollmentRequirement.setDrug(turalio);
+             TuralioPrescriberEnrollmentRequirement.setStakeholder("prescriber");
              requirementRepository.save(TuralioPrescriberEnrollmentRequirement);
 
             // prescriber knowledge assessment / certification sub-requirement
@@ -99,12 +103,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TuralioPrescriberKnowledgeResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TuralioPrescriberKnowledgeQuestionnaireResource = JacksonUtil.toJsonNode(TuralioPrescriberKnowledgeQuestionnaire);
             TuralioPrescriberKnowledgeResource.setResource(TuralioPrescriberKnowledgeQuestionnaireResource);
-            TuralioPrescriberKnowledgeResource.setId("turalio-prescriber-knowledge-check");
+            TuralioPrescriberKnowledgeResource.setId("TuralioPrescriberKnowledgeAssessment");
             remsFhirRepository.save(TuralioPrescriberKnowledgeResource);
             TuralioPrescriberCertificationRequirement.setName("Prescriber Knowledge Assessment");
+            TuralioPrescriberCertificationRequirement.setCreateNewCase(false);
             TuralioPrescriberCertificationRequirement.setResource(TuralioPrescriberKnowledgeResource);
             TuralioPrescriberCertificationRequirement.setDescription("Submit Prescriber Knowledge Assessment Form to REMS Administrator to receive certification");
             TuralioPrescriberCertificationRequirement.setParentRequirement(TuralioPrescriberEnrollmentRequirement);
+            TuralioPrescriberCertificationRequirement.setStakeholder("prescriber");
             // prescriberCertificationRequirement.setDrug(turalio); 
             requirementRepository.save(TuralioPrescriberCertificationRequirement);
 
@@ -116,12 +122,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
              TuralioPharmacistEnrollmentResource.setResourceType(ResourceType.Questionnaire.toString());
              JsonNode TuralioPharmacistQuestionnaireResource = JacksonUtil.toJsonNode(TuralioPharmacistQuestionnaire);
              TuralioPharmacistEnrollmentResource.setResource(TuralioPharmacistQuestionnaireResource);
-             TuralioPharmacistEnrollmentResource.setId("turalio-pharmacist-enrollment");
+             TuralioPharmacistEnrollmentResource.setId("TuralioPharmacistEnrollment");
              remsFhirRepository.save(TuralioPharmacistEnrollmentResource);
              TuralioPharmacistEnrollmentRequirement.setName("Pharmacist Enrollment");
+             TuralioPharmacistEnrollmentRequirement.setCreateNewCase(false);
              TuralioPharmacistEnrollmentRequirement.setResource(TuralioPharmacistEnrollmentResource);
              TuralioPharmacistEnrollmentRequirement.setDescription("Submit Pharmacist Enrollment form and training certification to the REMS Administrator");
              TuralioPharmacistEnrollmentRequirement.setDrug(turalio);
+             TuralioPharmacistEnrollmentRequirement.setStakeholder("pharmacist");
              requirementRepository.save(TuralioPharmacistEnrollmentRequirement);
 
 
@@ -135,12 +143,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TIRFPatientEnrollmentResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TIRFPatientQuestionnaireResource = JacksonUtil.toJsonNode(TIRFPatientQuestionnaire);
             TIRFPatientEnrollmentResource.setResource(TIRFPatientQuestionnaireResource);
-            TIRFPatientEnrollmentResource.setId("TIRF-patient-enrollment");
+            TIRFPatientEnrollmentResource.setId("TIRFRemsPatientEnrollment");
             remsFhirRepository.save(TIRFPatientEnrollmentResource);
             TIRFPatientEnrollmentRequirement.setName("Patient Enrollment");
+            TIRFPatientEnrollmentRequirement.setCreateNewCase(true);
             TIRFPatientEnrollmentRequirement.setResource(TIRFPatientEnrollmentResource);
             TIRFPatientEnrollmentRequirement.setDescription("Submit Patient Enrollment form to the REMS Administrator");
             TIRFPatientEnrollmentRequirement.setDrug(tirf);
+            TIRFPatientEnrollmentRequirement.setStakeholder("patient");
             requirementRepository.save(TIRFPatientEnrollmentRequirement);
 
             // prescriber enrollment form requirement
@@ -150,12 +160,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TIRFPrescriberEnrollmentResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TIRFPrescriberQuestionnaireResource = JacksonUtil.toJsonNode(TIRFPrescriberQuestionnaire);
             TIRFPrescriberEnrollmentResource.setResource(TIRFPrescriberQuestionnaireResource);
-            TIRFPrescriberEnrollmentResource.setId("TIRF-prescriber-enrollment");
+            TIRFPrescriberEnrollmentResource.setId("TIRFPrescriberEnrollmentForm");
             remsFhirRepository.save(TIRFPrescriberEnrollmentResource);
             TIRFPrescriberEnrollmentRequirement.setName("Prescriber Enrollment");
+            TIRFPrescriberEnrollmentRequirement.setCreateNewCase(false);
             TIRFPrescriberEnrollmentRequirement.setResource(TIRFPrescriberEnrollmentResource);
             TIRFPrescriberEnrollmentRequirement.setDescription("Submit Prescriber Enrollment form to the REMS Administrator");
             TIRFPrescriberEnrollmentRequirement.setDrug(tirf);
+            TIRFPrescriberEnrollmentRequirement.setStakeholder("prescriber");
             requirementRepository.save(TIRFPrescriberEnrollmentRequirement);
 
             // prescriber knowledge assessment / certification sub-requirement
@@ -165,12 +177,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TIRFPrescriberKnowledgeResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TIRFPrescriberKnowledgeQuestionnaireResource = JacksonUtil.toJsonNode(TIRFPrescriberKnowledgeQuestionnaire);
             TIRFPrescriberKnowledgeResource.setResource(TIRFPrescriberKnowledgeQuestionnaireResource);
-            TIRFPrescriberKnowledgeResource.setId("TIRF-prescriber-knowledge-check");
+            TIRFPrescriberKnowledgeResource.setId("TIRFPrescriberKnowledgeAssessment");
             remsFhirRepository.save(TIRFPrescriberKnowledgeResource);
             TIRFPrescriberCertificationRequirement.setName("Prescriber Knowledge Assessment");
+            TIRFPrescriberCertificationRequirement.setCreateNewCase(false);
             TIRFPrescriberCertificationRequirement.setResource(TIRFPrescriberKnowledgeResource);
             TIRFPrescriberCertificationRequirement.setDescription("Submit Prescriber Knowledge Assessment form to the REMS Administrator to receive certification");
             TIRFPrescriberCertificationRequirement.setParentRequirement(TIRFPrescriberEnrollmentRequirement);
+            TIRFPrescriberCertificationRequirement.setStakeholder("prescriber");
             //TIRFPrescriberCertificationRequirement.setDrug(tirf);
             requirementRepository.save(TIRFPrescriberCertificationRequirement);
 
@@ -182,12 +196,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TIRFPharmacistEnrollmentResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TIRFPharmacistQuestionnaireResource = JacksonUtil.toJsonNode(TIRFPharmacistQuestionnaire);
             TIRFPharmacistEnrollmentResource.setResource(TIRFPharmacistQuestionnaireResource);
-            TIRFPharmacistEnrollmentResource.setId("TIRF-pharmacist-enrollment");
+            TIRFPharmacistEnrollmentResource.setId("TIRFPharmacistEnrollmentForm");
             remsFhirRepository.save(TIRFPharmacistEnrollmentResource);
             TIRFPharmacistEnrollmentRequirement.setName("Pharmacist Enrollment");
+            TIRFPharmacistEnrollmentRequirement.setCreateNewCase(false);
             TIRFPharmacistEnrollmentRequirement.setResource(TIRFPharmacistEnrollmentResource);
             TIRFPharmacistEnrollmentRequirement.setDescription("Submit Pharmacist Enrollment form to the REMS Administrator");
             TIRFPharmacistEnrollmentRequirement.setDrug(tirf);
+            TIRFPharmacistEnrollmentRequirement.setStakeholder("pharmacist");
             requirementRepository.save(TIRFPharmacistEnrollmentRequirement);
 
             // pharmacist knowledge assessment / certification sub-requirement
@@ -198,12 +214,14 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TIRFPharmacistKnowledgeResource.setResourceType(ResourceType.Questionnaire.toString());
             JsonNode TIRFPharmacistKnowledgeQuestionnaireResource = JacksonUtil.toJsonNode(TIRFPharmacistKnowledgeQuestionnaire);
             TIRFPharmacistKnowledgeResource.setResource(TIRFPharmacistKnowledgeQuestionnaireResource);
-            TIRFPharmacistKnowledgeResource.setId("TIRF-pharmacist-knowledge-check");
+            TIRFPharmacistKnowledgeResource.setId("TIRFPharmacistKnowledgeAssessment");
             remsFhirRepository.save(TIRFPharmacistKnowledgeResource);
             TIRFPharmacistCertificationRequirement.setName("Pharmacist Knowledge Assessment");
+            TIRFPharmacistCertificationRequirement.setCreateNewCase(false);
             TIRFPharmacistCertificationRequirement.setResource(TIRFPharmacistKnowledgeResource);
             TIRFPharmacistCertificationRequirement.setDescription("Submit Pharmacist Knowledge Assessment form to the REMS Administrator to receive certification");
             TIRFPharmacistCertificationRequirement.setParentRequirement(TIRFPharmacistEnrollmentRequirement);
+            TIRFPharmacistCertificationRequirement.setStakeholder("pharmacist");
             //TIRFPharmacistCertificationRequirement.setDrug(tirf);
             requirementRepository.save(TIRFPharmacistCertificationRequirement);
 
@@ -226,6 +244,8 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TuralioPharmacistCredentialsResource.setId("Turalio-pharmacist-organization");
             remsFhirRepository.save(TuralioPharmacistCredentialsResource);
             TuralioPharmacistEnrollmentMetRequirement.setCompleted(true);
+            String turalioFunctionalId = TuralioPharmacistOrganizationResource.get("resourceType").textValue() + "/" + TuralioPharmacistOrganizationResource.get("id").textValue();
+            TuralioPharmacistEnrollmentMetRequirement.setFunctionalId(turalioFunctionalId);
             TuralioPharmacistEnrollmentMetRequirement.setRequirement(TuralioPharmacistEnrollmentRequirement);
             TuralioPharmacistEnrollmentMetRequirement.setCompletedRequirement(TuralioPharmacistCredentialsResource);
             metRequirementRepository.save(TuralioPharmacistEnrollmentMetRequirement);
@@ -244,6 +264,8 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             TIRFPharmacistCredentialsResource.setId("TIRF-pharmacist-organization");
             remsFhirRepository.save(TIRFPharmacistCredentialsResource);
             TIRFPharmacistEnrollmentMetRequirement.setCompleted(true);
+            String TIRFFunctionalId = TIRFPharmacistOrganizationResource.get("resourceType").textValue() + "/" + TIRFPharmacistOrganizationResource.get("id").textValue();
+            TIRFPharmacistEnrollmentMetRequirement.setFunctionalId(TIRFFunctionalId);
             TIRFPharmacistEnrollmentMetRequirement.setRequirement(TIRFPharmacistEnrollmentRequirement);
             TIRFPharmacistEnrollmentMetRequirement.setCompletedRequirement(TIRFPharmacistCredentialsResource);
             metRequirementRepository.save(TIRFPharmacistEnrollmentMetRequirement);
@@ -251,6 +273,7 @@ CommandLineRunner initDatabase(DrugsRepository repository, RemsFhirRepository re
             // pharmacist knowledge form requirement
             MetRequirement TIRFPharmacistCertificationMetRequirement = new MetRequirement();
             TIRFPharmacistCertificationMetRequirement.setCompleted(true);
+            TIRFPharmacistCertificationMetRequirement.setFunctionalId(TIRFFunctionalId);
             TIRFPharmacistCertificationMetRequirement.setRequirement(TIRFPharmacistCertificationRequirement);
             TIRFPharmacistCertificationMetRequirement.setParentMetRequirement(TIRFPharmacistEnrollmentMetRequirement);
             metRequirementRepository.save(TIRFPharmacistCertificationMetRequirement);
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java
index 8e866ca9e..c856bf578 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java
@@ -35,11 +35,13 @@
 import org.springframework.web.server.ResponseStatusException;
 import org.springframework.http.HttpStatus;
 import java.util.Arrays;
+import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.util.logging.Logger;
 
+
 /**
  * Provides the REST interface that can be interacted with at [base]/api/fhir and [base]/fhir.
  */
@@ -72,83 +74,305 @@ private ResponseEntity<Drug> processRequirements(Drug drug) {
                 .contentType(MediaType.parseMediaType(MediaType.APPLICATION_JSON_VALUE))
                 .body(drug);
     }
-
-    public void updateRemsRequestStatus(String uid) {
-        try {
-          TimeUnit.SECONDS.sleep(30);
-        }
-        catch(Exception e)
-        {
-            System.out.println(e);
-          }
-        Rems rems = remsRepository.findById(uid).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, uid + " not found"));
-        rems.setStatus("Approved");
-        remsRepository.save(rems);
-      }
-    
-      public void updateRemsRequestStatusInBackground (final String uid) {
-        Thread t = new Thread(() -> updateRemsRequestStatus(uid));
-        t.start();
-      }
     
       @PostMapping(value = "/rems")
       @CrossOrigin
       public ResponseEntity<Object> postRems(@RequestBody String jsonData) {
+        Rems remsRequest = new Rems();
+        MetRequirement returnMetReq = new MetRequirement();
+        Boolean returnRemsRequest = false;
+
         JsonNode remsObject = JacksonUtil.toJsonNode(jsonData);
+
         String id = UUID.randomUUID().toString().replace("-", "");
 
+        // extract params and questionnaire response identifier
         JsonNode params = getResource(remsObject, remsObject.get("entry").get(0).get("resource").get("focus").get("parameters").get("reference").textValue());
-        
+        JsonNode questionnaireResponse = getQuestionnaireResponse(remsObject);
+        String[] questionnaireStringArray = questionnaireResponse.get("questionnaire").textValue().split("/");
+        String requirementId = questionnaireStringArray[questionnaireStringArray.length - 1];
+
+        // stakeholder and medication references
         String prescriptionReference = "";
+        String practitionerReference = "";
+        String pharmacistReference = "";
+        String patientReference = "";
         for (JsonNode param : params.get("parameter")) {
             if (param.get("name").textValue().equals("prescription")) {
-                prescriptionReference = param.get("reference").textValue();
+              prescriptionReference = param.get("reference").textValue();
+            }
+            else if (param.get("name").textValue().equals("prescriber")) {
+              practitionerReference = param.get("reference").textValue();
+            }
+            else if (param.get("name").textValue().equals("pharmacy")) {
+              pharmacistReference = param.get("reference").textValue();
+            }      else if (param.get("name").textValue().equals("source-patient")) {
+              patientReference = param.get("reference").textValue();
             }
         }
 
+        // obtain drug information from database
         JsonNode presciption = getResource(remsObject, prescriptionReference);
         String prescriptionSystem = presciption.get("medicationCodeableConcept").get("coding").get(0).get("system").textValue();
         String prescriptionCode = presciption.get("medicationCodeableConcept").get("coding").get(0).get("code").textValue();
         Drug drug = drugsRepository.findDrugByCode(prescriptionSystem, prescriptionCode).get(0);
 
+        // iterate through each requirement of the drug
+        for (Requirement requirement : drug.getRequirements()) {
 
+            // if the requirement is the one submitted continue
+            if (requirement.getResource().getId().equals(requirementId)) {
 
-        Rems remsRequest = new Rems();
-        remsRequest.setCase_number(id);
-        remsRequest.setStatus("Pending");
-        remsRequest.setResource(remsObject);
-        remsRepository.save(remsRequest);
-        
-        for (Requirement requirement : drug.getRequirements()) {
-            MetRequirement metReq = new MetRequirement();
-            metReq.setRequirement(requirement);
-            metReq.setRemsRequest(remsRequest);
-            remsRequest.addMetRequirement(metReq);
-
-            //logic to set requirement as met or not, for now hard code only patient enrollment form
-            if (requirement.getName().equals("Patient Enrollment")) {
-              metReq.setCompleted(true);
-            }
+              // if the req submitted is a patient enrollment form and requires creating a new case
+              if (requirement.getCreateNewCase()) {
+                returnRemsRequest = true;
+                // create new rems request and add the created metReq to it
+                remsRequest.setCase_number(id);
+                remsRequest.setStatus("Pending");
+                remsRequest.setResource(remsObject);
+                remsRepository.save(remsRequest);
 
-            metRequirementsRepository.save(metReq);
+                // figure out which stakeholder the req corresponds to 
+                String reqStakeholder = requirement.getStakeholder();
+                String reqStakeholderReference = reqStakeholder.equals("prescriber") ? practitionerReference : (reqStakeholder.equals("pharmacist") ? pharmacistReference : patientReference);
+
+                // create the metReq that was submitted
+                MetRequirement metReq = new MetRequirement();
+                metReq.setRequirement(requirement);
+                metReq.setFunctionalId(reqStakeholderReference);
+                metReq.setCompleted(true);
+                metReq.addRemsRequest(remsRequest);
+                remsRequest.addMetRequirement(metReq);
+                metRequirementsRepository.save(metReq);
+
+                // create child metReqs for this req
+                for (Requirement subRequirement : requirement.getChildRequirements()) {
+                  Boolean foundSubMatch = false;
+                  // check if sub req has already been submitted 
+                  for (MetRequirement possibleMetSubRequirement : subRequirement.getMetRequirements()) {
+                    if ((possibleMetSubRequirement.getFunctionalId().equals(pharmacistReference) && subRequirement.getStakeholder().equals("pharmacist"))
+                            || (possibleMetSubRequirement.getFunctionalId().equals(practitionerReference) && subRequirement.getStakeholder().equals("prescriber"))
+                            || (possibleMetSubRequirement.getFunctionalId().equals(patientReference) && subRequirement.getStakeholder().equals("patient"))) {
+                      
+                      foundSubMatch = true;
+                      possibleMetSubRequirement.setParentMetRequirement(metReq);
+                      metReq.addChildMetRequirements(possibleMetSubRequirement);
+                      metRequirementsRepository.save(possibleMetSubRequirement);
+                      break;
+
+                    }
+                  }
+
+                  // create a new sub met req if one is not found, set completed status to false 
+                  if (!foundSubMatch) {
+                    // figure out which stakeholder the req corresponds to 
+                    String reqStakeholder2 = subRequirement.getStakeholder();
+                    String reqStakeholderReference2 = reqStakeholder2.equals("prescriber") ? practitionerReference : (reqStakeholder2.equals("pharmacist") ? pharmacistReference : patientReference);
+
+                    MetRequirement falseSubMetReq = new MetRequirement();
+                    falseSubMetReq.setRequirement(subRequirement);
+                    falseSubMetReq.setFunctionalId(reqStakeholderReference2);
+                    falseSubMetReq.setCompleted(false);
+                    falseSubMetReq.setParentMetRequirement(metReq);
+                    metReq.addChildMetRequirements(falseSubMetReq);
+                    metRequirementsRepository.save(falseSubMetReq);
+                  }
+                }
+
+                metRequirementsRepository.save(metReq);
+
+                // iterate through all other reqs again to create corresponding false metReqs / assign to existing 
+                for (Requirement requirement2 : drug.getRequirements()) {
+                  // skip if the req found is the same as in the outer loop and has already been processed
+                  if (!requirement2.getResource().getId().equals(requirementId)) {
+                    Boolean foundMatch = false;
+                    MetRequirement newMetReq = new MetRequirement();
+                    // check if an existing metReq has already been submitted 
+                    for (MetRequirement possibleMetRequirement : requirement2.getMetRequirements()) {
+                      if ((possibleMetRequirement.getFunctionalId().equals(pharmacistReference) && requirement2.getStakeholder().equals("pharmacist"))
+                      || (possibleMetRequirement.getFunctionalId().equals(practitionerReference) && requirement2.getStakeholder().equals("prescriber"))
+                      || (possibleMetRequirement.getFunctionalId().equals(patientReference) && requirement2.getStakeholder().equals("patient"))) {
+                        foundMatch = true;
+                        newMetReq = possibleMetRequirement;
+                        newMetReq.addRemsRequest(remsRequest);
+                        remsRequest.addMetRequirement(newMetReq);
+                        metRequirementsRepository.save(newMetReq);
+                        break;
+
+                      }
+                    }
+                    // create a new metReq if one was not found, set completed status to false 
+                    if (!foundMatch) {
+                      // figure out which stakeholder the req corresponds to 
+                      String reqStakeholder3 = requirement2.getStakeholder();
+                      String reqStakeholderReference3 = reqStakeholder3.equals("prescriber") ? practitionerReference : (reqStakeholder3.equals("pharmacist") ? pharmacistReference : patientReference);
+
+                      newMetReq.setRequirement(requirement2);
+                      newMetReq.setCompleted(false);
+                      newMetReq.setFunctionalId(reqStakeholderReference3);
+                      newMetReq.addRemsRequest(remsRequest);
+                      remsRequest.addMetRequirement(newMetReq);
+                      metRequirementsRepository.save(newMetReq);
+
+                    }
+                    // iterate through all other child reqs to create corresponding false metReqs / assign to existing 
+                    for (Requirement subRequirement2 : requirement2.getChildRequirements()) {
+                      Boolean foundSubMatch2 = false;
+                      // check if sub req has already been submitted 
+                      for (MetRequirement possibleMetSubRequirement2 : subRequirement2.getMetRequirements()) {
+                        if ((possibleMetSubRequirement2.getFunctionalId().equals(pharmacistReference) && subRequirement2.getStakeholder().equals("pharmacist"))
+                        || (possibleMetSubRequirement2.getFunctionalId().equals(practitionerReference) && subRequirement2.getStakeholder().equals("prescriber"))
+                        || (possibleMetSubRequirement2.getFunctionalId().equals(patientReference) && subRequirement2.getStakeholder().equals("patient"))) {
+                          
+                          foundSubMatch2 = true;
+                          possibleMetSubRequirement2.setParentMetRequirement(newMetReq);
+                          if (!foundMatch) {
+                            newMetReq.addChildMetRequirements(possibleMetSubRequirement2);
+                          }
+                          metRequirementsRepository.save(possibleMetSubRequirement2);
+                          break;
+                        }
+                      }
+
+                      // create a new met req if one is not found, set completed status to false 
+                      if (!foundSubMatch2) {
+                        // figure out which stakeholder the req corresponds to 
+                        String reqStakeholder4 = subRequirement2.getStakeholder();
+                        String reqStakeholderReference4 = reqStakeholder4.equals("prescriber") ? practitionerReference : (reqStakeholder4.equals("pharmacist") ? pharmacistReference : patientReference);
+
+                        MetRequirement falseSubMetReq2 = new MetRequirement();
+                        falseSubMetReq2.setRequirement(subRequirement2);
+                        falseSubMetReq2.setFunctionalId(reqStakeholderReference4);
+                        falseSubMetReq2.setCompleted(false);
+                        falseSubMetReq2.setParentMetRequirement(newMetReq);
+                        newMetReq.addChildMetRequirements(falseSubMetReq2);
+                        metRequirementsRepository.save(falseSubMetReq2);
+                      }
+                    }
+                    metRequirementsRepository.save(newMetReq);
+                  }
+                }
+                remsRepository.save(remsRequest);
+
+
+              } else {
+                // look through open met Reqs for matching cases and set status to true 
+                Boolean foundMetReq3 = false;
+                for (MetRequirement possibleMetRequirement3 : requirement.getMetRequirements()) {
+                  if ((possibleMetRequirement3.getFunctionalId().equals(pharmacistReference) && requirement.getStakeholder().equals("pharmacist"))
+                  || (possibleMetRequirement3.getFunctionalId().equals(practitionerReference) && requirement.getStakeholder().equals("prescriber"))
+                  || (possibleMetRequirement3.getFunctionalId().equals(patientReference) && requirement.getStakeholder().equals("patient"))) {
+                    
+                    foundMetReq3 = true;
+                    possibleMetRequirement3.setCompleted(true);
+                    // possibleMetRequirement3.setCompletedRequirement(remsObject);
+                    metRequirementsRepository.save(possibleMetRequirement3);
+                    returnMetReq = possibleMetRequirement3;
+                  }
+                }
+
+                if (!foundMetReq3) {
+                  // figure out which stakeholder the req corresponds to 
+                  String reqStakeholder5 = requirement.getStakeholder();
+                  String reqStakeholderReference5 = reqStakeholder5.equals("prescriber") ? practitionerReference : (reqStakeholder5.equals("pharmacist") ? pharmacistReference : patientReference);
+
+                  MetRequirement submittedMetReq = new MetRequirement();
+                  submittedMetReq.setRequirement(requirement);
+                  submittedMetReq.setCompleted(true);
+                  // submittedMetReq.setCompletedRequirement(remsObject);
+                  submittedMetReq.setFunctionalId(reqStakeholderReference5);
+                  metRequirementsRepository.save(submittedMetReq);
+                  returnMetReq = submittedMetReq;
+                }
+
+
+              }
+
+              break;
 
-            // only handle one level of sub requirements for now
-            for (Requirement subRequirement : requirement.getChildRequirements()) {
-              MetRequirement subMetReq = new MetRequirement();
-              subMetReq.setRequirement(subRequirement);
-              // subMetReq.setRemsRequest(remsRequest);
-              subMetReq.setParentMetRequirement(metReq);
-              // remsRequest.addMetRequirement(subMetReq);
-              metReq.addChildMetRequirements(subMetReq);
-              metRequirementsRepository.save(subMetReq);
             }
 
+            // check sub requirements - note sub reqs can not initiate a new rems request, only a parent level requirement can start a new rems case
+            // only handle one level of sub requirements
+            for (Requirement subRequirement : requirement.getChildRequirements()) {
+              Boolean foundMetReq4 = false;
+              for (MetRequirement possibleMetRequirement4 : subRequirement.getMetRequirements()) {
+                if ((possibleMetRequirement4.getFunctionalId().equals(pharmacistReference) && requirement.getStakeholder().equals("pharmacist"))
+                || (possibleMetRequirement4.getFunctionalId().equals(practitionerReference) && requirement.getStakeholder().equals("prescriber"))
+                || (possibleMetRequirement4.getFunctionalId().equals(patientReference) && requirement.getStakeholder().equals("patient"))) {
+                  
+                  foundMetReq4 = true;
+                  possibleMetRequirement4.setCompleted(true);
+                  // possibleMetRequirement4.setCompletedRequirement(remsObject);
+                  metRequirementsRepository.save(possibleMetRequirement4);
+                  returnMetReq = possibleMetRequirement4;
+                }
+              }
+
+              if (!foundMetReq4) {
+                // figure out which stakeholder the req corresponds to 
+                String reqStakeholder6 = subRequirement.getStakeholder();
+                String reqStakeholderReference6 = reqStakeholder6.equals("prescriber") ? practitionerReference : (reqStakeholder6.equals("pharmacist") ? pharmacistReference : patientReference);
 
+                MetRequirement submittedMetReq4 = new MetRequirement();
+                submittedMetReq4.setRequirement(subRequirement);
+                submittedMetReq4.setCompleted(true);
+                // submittedMetReq4.setCompletedRequirement(remsObject);
+                submittedMetReq4.setFunctionalId(reqStakeholderReference6);
+                metRequirementsRepository.save(submittedMetReq4);
+                returnMetReq = submittedMetReq4;
+              }
+                // MetRequirement subMetReq = new MetRequirement();
+                // subMetReq.setRequirement(subRequirement);
+                // // subMetReq.setRemsRequest(remsRequest);
+                // subMetReq.setParentMetRequirement(metReq);
+                // // remsRequest.addMetRequirement(subMetReq);
+                // metReq.addChildMetRequirements(subMetReq);
+                // metRequirementsRepository.save(subMetReq);
+            }
+        }
+
+            // check status of each rems request once requirements are parsed through
+            // could not set rems - drug relationship without java bean issue, for now iterate through all rems requests 
+            // ToDo : Assign relationship and only iterate through the rems requests associated with the current drug instead of all rems requests for all drug
+            // Optimization: filter on only Pending rems requests (custom SQL query would need to be created in the repository most likely)
+            List<Rems> rems = remsRepository.findRems();
+            for (Rems rem : rems) {
+              if (rem.getStatus().equals("Pending")) {
+                Boolean foundFalse = false;
+                for (MetRequirement finalMetReq : rem.getMetRequirements()) {
+                  if (!finalMetReq.getCompleted()) {
+                    foundFalse = true; 
+                    break;
+                  }
+  
+                  for (MetRequirement finalSubMetReq : finalMetReq.getChildMetRequirements()) {
+                    if (!finalSubMetReq.getCompleted()) {
+                      foundFalse = true; 
+                      break;
+                    }
+                  }
+                  if (foundFalse) {
+                    break;
+                  }
+                }
+                
+                if (!foundFalse) {
+                  rem.setStatus("Approved");
+                  remsRepository.save(rem);
+                  if (rem.getCase_number().equals(remsRequest.getCase_number())) {
+                    remsRequest.setStatus("Approved");
+                  }
+                }
+              }
+            }
+        
+        // return MetReq unless a new case is created in which case return the Rems request
+        if (returnRemsRequest) {
+          return ResponseEntity.ok().body(remsRequest);
+        } else  {
+          return ResponseEntity.ok().body(returnMetReq);
         }
-        remsRepository.save(remsRequest);
-        updateRemsRequestStatusInBackground(id);
-        return ResponseEntity.ok().body(remsRequest);
-    
       }
     
       @CrossOrigin
@@ -171,5 +395,16 @@ public JsonNode getResource(JsonNode bundle, String resourceReference) {
         }
         return null;
       }
+
+      public JsonNode getQuestionnaireResponse(JsonNode bundle) {
+        String _resourceType = "QuestionnaireResponse";
+      
+        for (int i = 0; i < bundle.get("entry").size(); i++) {
+          if ((bundle.get("entry").get(i).get("resource").get("resourceType").textValue().equals(_resourceType))) {
+            return bundle.get("entry").get(i).get("resource");
+          }
+        }
+        return null;
+      }
     
 }
\ No newline at end of file
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/drugs/Drug.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/drugs/Drug.java
index 5938e1be2..d3c6f0480 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/drugs/Drug.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/drugs/Drug.java
@@ -1,6 +1,9 @@
 package org.hl7.davinci.endpoint.rems.database.drugs;
 
 import org.hl7.davinci.endpoint.rems.database.requirement.Requirement;
+import org.hl7.davinci.endpoint.rems.database.rems.Rems;
+import com.fasterxml.jackson.annotation.JsonManagedReference;
+
 
 import javax.persistence.*;
 import java.time.ZonedDateTime;
@@ -27,6 +30,10 @@ public class Drug {
     @OneToMany(mappedBy="drug", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
     private List<Requirement> requirements = new ArrayList<>();
 
+    // ToDo: Revist this relationship mapping between drug and rems, currently broken
+    // @OneToMany(mappedBy="drug", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
+    // private List<Rems> rems = new ArrayList<>();
+
     public Drug() {
         this.createdAt = ZonedDateTime.now().format(DateTimeFormatter.ofPattern( "uuuu.MM.dd.HH.mm.ss" ));
 
@@ -51,6 +58,20 @@ public void setRequirements(List<Requirement> requirements) {
     public void addRequirement(Requirement requirement)  {
         this.requirements.add(requirement);
     }
+
+    // ToDo: Revist this relationship mapping between drug and rems, currently broken
+    // public List<Rems> getRems() {
+    //     return this.rems;
+    // }
+
+    // public void setRems(List<Rems> rems) {
+    //     this.rems = rems;
+    // }
+
+    // public void addRems(Rems rem)  {
+    //     this.rems.add(rem);
+    // }
+
     public String getCreatedAt() {
         return this.createdAt;
     }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/rems/Rems.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/rems/Rems.java
index 9a053437d..47b5575f9 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/rems/Rems.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/rems/Rems.java
@@ -1,6 +1,12 @@
 package  org.hl7.davinci.endpoint.rems.database.rems;
 import org.hl7.davinci.endpoint.rems.database.requirement.MetRequirement;
+import org.hl7.davinci.endpoint.rems.database.drugs.Drug;
+
 import com.fasterxml.jackson.annotation.JsonManagedReference;
+import com.fasterxml.jackson.annotation.JsonBackReference;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+
 import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.*;
@@ -28,11 +34,17 @@ public class Rems {
   @Column(name = "status", nullable = false, length = 100)
   private String status;
 
+  // @ManyToOne
+  // @JoinColumn(name="drug", nullable = true)
+  // // @JsonBackReference
+  // @JsonIgnore
+  // private Drug drug;
+
   @Type(type = "json")
   @Column(columnDefinition = "json", name = "resource", nullable = false, length = 10000000)
   private JsonNode resource;
 
-  @OneToMany(mappedBy="remsRequest", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
+  @ManyToMany
   @JsonManagedReference
   private List<MetRequirement> metRequirements = new ArrayList<>();
 
@@ -66,6 +78,14 @@ public void addMetRequirement(MetRequirement metRequirement)  {
     this.metRequirements.add(metRequirement);
 }
 
+// public Drug getDrug() {
+//   return this.drug;
+// }
+
+// public void setDrug(Drug drug) {
+//   this.drug = drug;
+// }
+
 public JsonNode getResource() {
   return this.resource;
 }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/MetRequirement.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/MetRequirement.java
index b6c383abc..18b17aefd 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/MetRequirement.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/MetRequirement.java
@@ -23,6 +23,9 @@ public class MetRequirement {
     @Column(name = "createdAt", nullable = false)
     private String createdAt;
 
+    @Column(name = "functionalId", nullable = false)
+    private String functionalId;
+
     @Column(name = "completed", nullable = false)
     private Boolean completed ;
 
@@ -35,11 +38,11 @@ public class MetRequirement {
     @JoinColumn(name="REQUIREMENT_ID")
     private Requirement requirement;
 
-    @ManyToOne
-    @JoinColumn(name="REMS_REQUEST")
+    @ManyToMany
+    // @JoinColumn(name="REMS_REQUEST")
     @JsonBackReference
-    private Rems remsRequest;
-
+    private List<Rems> remsRequest = new ArrayList<>();
+    
     @OneToMany(mappedBy="parentMetRequirement", fetch = FetchType.EAGER)
     @JsonManagedReference
     private List<MetRequirement> childMetRequirements = new ArrayList<>();
@@ -61,12 +64,16 @@ public void setId(Integer id) {
         this.id = id;
     }
 
-    public Rems getRemsRequest() {
+    public List<Rems> getRemsRequest() {
         return this.remsRequest;
     }
 
-    public void setRemsRequest(Rems request) {
-        this.remsRequest = request;
+    public void setRemsRequest(List<Rems> requests) {
+        this.remsRequest = requests;
+    }
+
+    public void addRemsRequest(Rems request)  {
+        this.remsRequest.add(request);
     }
 
     public RemsFhir getCompletedRequirement() {
@@ -85,6 +92,14 @@ public void setCreatedAt(String createdAt) {
         this.createdAt = createdAt;
     }
 
+    public String getFunctionalId() {
+        return this.functionalId;
+    }
+
+    public void setFunctionalId(String id) {
+        this.functionalId = id;
+    }
+
     public Boolean getCompleted() {
         return this.completed;
     }
diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/Requirement.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/Requirement.java
index 3b37ab9a0..3359133b0 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/Requirement.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/database/requirement/Requirement.java
@@ -28,6 +28,12 @@ public class Requirement {
     @Column(name = "name", nullable = true)
     private String name;
 
+    @Column(name = "stakeholder", nullable = false)
+    private String stakeholder;
+
+    @Column(name = "createNewCase")
+    private Boolean createNewCase ;
+
     // FHIR resource which defines the requirement (task, questionnaire, etc)
     @JoinColumn(name = "resource", nullable = true)
     @OneToOne
@@ -71,6 +77,8 @@ public void setResource(RemsFhir resource) {
         this.resource = resource;
     }
 
+    
+
     public String getCreatedAt() {
         return this.createdAt;
     }
@@ -79,6 +87,15 @@ public void setCreatedAt(String createdAt) {
         this.createdAt = createdAt;
     }
 
+
+    public Boolean getCreateNewCase() {
+        return this.createNewCase;
+    }
+
+    public void setCreateNewCase(Boolean createNewCase) {
+        this.createNewCase = createNewCase;
+    }
+
     public String getDescription() {
         return this.description;
     }
@@ -95,8 +112,16 @@ public void setName(String name) {
         this.name = name;
     }
 
+    public String getStakeholder() {
+        return this.stakeholder;
+    }
+
+    public void setStakeholder(String stakeholder) {
+        this.stakeholder = stakeholder;
+    }
+
     public Drug getDrug() {
-        return drug;
+        return this.drug;
     }
 
     public void setDrug(Drug drug) {

From 8dd763c874829761ad23823c7200166634746e11 Mon Sep 17 00:00:00 2001
From: Sahil Malhotra <smalhotra@mitre.org>
Date: Thu, 25 Aug 2022 11:41:09 -0400
Subject: [PATCH 2/2] bug fix on met sub reqs parent relation

---
 .../rems/controller/RemsController.java       | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java b/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java
index c856bf578..0fbe57a3d 100644
--- a/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java
+++ b/server/src/main/java/org/hl7/davinci/endpoint/rems/controller/RemsController.java
@@ -282,6 +282,35 @@ else if (param.get("name").textValue().equals("pharmacy")) {
                   // submittedMetReq.setCompletedRequirement(remsObject);
                   submittedMetReq.setFunctionalId(reqStakeholderReference5);
                   metRequirementsRepository.save(submittedMetReq);
+
+                  for (Requirement childRequirement2 : requirement.getChildRequirements()) {
+                    Boolean foundMetReq6 = false;
+                    for (MetRequirement possibleMetRequirement6 : childRequirement2.getMetRequirements()) {
+                      if ((possibleMetRequirement6.getFunctionalId().equals(pharmacistReference) && childRequirement2.getStakeholder().equals("pharmacist"))
+                      || (possibleMetRequirement6.getFunctionalId().equals(practitionerReference) && childRequirement2.getStakeholder().equals("prescriber"))
+                      || (possibleMetRequirement6.getFunctionalId().equals(patientReference) && childRequirement2.getStakeholder().equals("patient"))) {
+                        
+                        foundMetReq6 = true;
+                        possibleMetRequirement6.setParentMetRequirement(submittedMetReq);
+                        submittedMetReq.addChildMetRequirements(possibleMetRequirement6);
+                        metRequirementsRepository.save(possibleMetRequirement6);
+                      }
+                    }
+    
+                    if (!foundMetReq6) {
+                      String reqStakeholder6 = childRequirement2.getStakeholder();
+                      String reqStakeholderReference6 = reqStakeholder6.equals("prescriber") ? practitionerReference : (reqStakeholder6.equals("pharmacist") ? pharmacistReference : patientReference);
+    
+                      MetRequirement submittedMetReqChild = new MetRequirement();
+                      submittedMetReqChild.setRequirement(childRequirement2);
+                      submittedMetReqChild.setCompleted(false);
+                      submittedMetReqChild.setFunctionalId(reqStakeholderReference6);
+                      submittedMetReqChild.setParentMetRequirement(submittedMetReq);
+                      submittedMetReq.addChildMetRequirements(submittedMetReqChild);
+                      metRequirementsRepository.save(submittedMetReqChild);
+                    }
+                  }
+                  metRequirementsRepository.save(submittedMetReq);
                   returnMetReq = submittedMetReq;
                 }
 
