From affd16a79264a1cc59a9b0ac34eeb817002bec54 Mon Sep 17 00:00:00 2001 From: Ken Long Date: Wed, 1 Apr 2020 13:54:50 -0700 Subject: [PATCH] HTML-720 : adding new method to get patient program enrollment by workflow on a given date and making it the default behavior of the tag --- .../htmlformentry/WorkflowStateTagTest.java | 214 ++++++++++++++++++ .../htmlformentry/FormSubmissionActions.java | 16 +- .../WorkflowStateSubmissionElement.java | 28 ++- 3 files changed, 254 insertions(+), 4 deletions(-) diff --git a/api-tests/src/test/java/org/openmrs/module/htmlformentry/WorkflowStateTagTest.java b/api-tests/src/test/java/org/openmrs/module/htmlformentry/WorkflowStateTagTest.java index 65e4da7c2..d8f091722 100644 --- a/api-tests/src/test/java/org/openmrs/module/htmlformentry/WorkflowStateTagTest.java +++ b/api-tests/src/test/java/org/openmrs/module/htmlformentry/WorkflowStateTagTest.java @@ -396,6 +396,12 @@ public void shouldTransitionToStateBeforeAnotherState() throws Exception { //Given: Patient has a workflow state of X starting in Jan 2012 transitionToState(END_STATE, DATE); + ProgramWorkflowState state = Context.getProgramWorkflowService().getStateByUuid(START_STATE); + + List patientPrograms = Context.getProgramWorkflowService().getPatientPrograms(patient, + state.getProgramWorkflow().getProgram(), null, null, null, null, false); + patientPrograms.size(); + new RegressionTestHelper() { @Override @@ -868,6 +874,214 @@ public void testEditFormHtml(String html) { }.run(); } + @Test + public void shouldAllowNewProgramAfterCompletedProgram() throws Exception { + //Given: Patient has a workflow state of X starting in Jan 2012 + transitionToState(START_STATE, FURTHER_PAST_DATE); + transitionToState(END_STATE, PAST_DATE); + + new RegressionTestHelper() { + + @Override + public String getFormName() { + return XML_FORM_NAME; + } + + @Override + public String[] widgetLabels() { + return new String[] { "Date:", "Location:", "Provider:", "State:" }; + } + + @Override + public void setupRequest(MockHttpServletRequest request, Map widgets) { + request.addParameter(widgets.get("Location:"), "2"); + request.addParameter(widgets.get("Provider:"), "502"); + + //When: Html form is being back entered with an encounter date of June 2011, in which the workflow state selected is Y + request.addParameter(widgets.get("Date:"), dateAsString(DATE)); + request.addParameter(widgets.get("State:"), START_STATE); + } + + @Override + public void testResults(SubmissionResults results) { + results.assertNoErrors(); + results.assertEncounterCreated(); + results.assertProvider(502); + results.assertLocation(2); + + //Then: Workflow state Y is created with a start date of June 2011 and a stop date of Jan 2012. Workflow state X stays as is. + ProgramWorkflowState state = Context.getProgramWorkflowService().getStateByUuid(START_STATE); + PatientProgram patientProgram = getPatientProgramByState(results.getPatient(), state, DATE); + PatientState patientState = getPatientState(patientProgram, state, DATE); + + List patientPrograms = Context.getProgramWorkflowService().getPatientPrograms(patient, + state.getProgramWorkflow().getProgram(), null, null, null, null, false); + + Assert.assertEquals(2, patientPrograms.size()); + + Assert.assertNotNull(patientProgram); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientProgram.getDateEnrolled())); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientState.getStartDate())); + Assert.assertNull(patientState.getEndDate()); + + state = Context.getProgramWorkflowService().getStateByUuid(START_STATE); + patientState = getPatientState(patientProgram, state, DATE); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientState.getStartDate())); + Assert.assertNull(patientState.getEndDate()); + } + }.run(); + + } + + @Test + public void shouldAllowNewProgramAfterCompletedProgramViaEdit() throws Exception { + //Given: Patient has a workflow state of X starting in Jan 2012 + transitionToState(START_STATE, FURTHER_PAST_DATE); + transitionToState(END_STATE, PAST_DATE); + + new RegressionTestHelper() { + + @Override + public String getFormName() { + return XML_FORM_NAME; + } + + @Override + public String[] widgetLabels() { + return new String[] { "Date:", "Location:", "Provider:", "State:" }; + } + + @Override + public void setupRequest(MockHttpServletRequest request, Map widgets) { + request.addParameter(widgets.get("Location:"), "2"); + request.addParameter(widgets.get("Provider:"), "502"); + + //When: Html form is being back entered with an encounter date of June 2011, in which the workflow state selected is Y + request.addParameter(widgets.get("Date:"), dateAsString(DATE)); + } + + @Override + public void testResults(SubmissionResults results) { + results.assertNoErrors(); + results.assertEncounterCreated(); + results.assertProvider(502); + results.assertLocation(2); + } + + @Override + public boolean doEditEncounter() { + return true; + } + + @Override + public String[] widgetLabelsForEdit() { + return new String[] { "Date:", "Location:", "Provider:", "State:" }; + } + + @Override + public void setupEditRequest(MockHttpServletRequest request, Map widgets) { + request.setParameter(widgets.get("Location:"), "2"); + request.setParameter(widgets.get("Provider:"), "502"); + request.setParameter(widgets.get("Date:"), dateAsString(DATE)); + request.setParameter(widgets.get("State:"), START_STATE); + } + + @Override + public void testEditedResults(SubmissionResults results) { + results.assertNoErrors(); + + ProgramWorkflowState state = Context.getProgramWorkflowService().getStateByUuid(START_STATE); + PatientProgram patientProgram = getPatientProgramByState(results.getPatient(), state, DATE); + PatientState patientState = getPatientState(patientProgram, state, DATE); + Assert.assertNotNull(patientProgram); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientProgram.getDateEnrolled())); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientState.getStartDate())); + Assert.assertNull(patientProgram.getDateCompleted()); + Assert.assertNull(patientState.getEndDate()); + + List patientPrograms = Context.getProgramWorkflowService().getPatientPrograms(patient, + patientProgram.getProgram(), null, null, null, null, false); + + Assert.assertEquals(2, patientPrograms.size()); + } + }.run(); + + } + + @Test + public void shouldAllowNewProgramAfterCompletedProgramViaEditToEarlierDate() throws Exception { + //Given: Patient has a workflow state of X starting in Jan 2012 + transitionToState(END_STATE, FURTHER_PAST_DATE); + + new RegressionTestHelper() { + + @Override + public String getFormName() { + return XML_FORM_NAME; + } + + @Override + public String[] widgetLabels() { + return new String[] { "Date:", "Location:", "Provider:", "State:" }; + } + + @Override + public void setupRequest(MockHttpServletRequest request, Map widgets) { + request.addParameter(widgets.get("Location:"), "2"); + request.addParameter(widgets.get("Provider:"), "502"); + + //When: Html form is being back entered with an encounter date of June 2011, in which the workflow state selected is Y + request.addParameter(widgets.get("Date:"), dateAsString(PAST_DATE)); + } + + @Override + public void testResults(SubmissionResults results) { + results.assertNoErrors(); + results.assertEncounterCreated(); + results.assertProvider(502); + results.assertLocation(2); + } + + @Override + public boolean doEditEncounter() { + return true; + } + + @Override + public String[] widgetLabelsForEdit() { + return new String[] { "Date:", "Location:", "Provider:", "State:" }; + } + + @Override + public void setupEditRequest(MockHttpServletRequest request, Map widgets) { + request.setParameter(widgets.get("Location:"), "2"); + request.setParameter(widgets.get("Provider:"), "502"); + request.setParameter(widgets.get("Date:"), dateAsString(DATE)); + request.setParameter(widgets.get("State:"), START_STATE); + } + + @Override + public void testEditedResults(SubmissionResults results) { + results.assertNoErrors(); + + ProgramWorkflowState state = Context.getProgramWorkflowService().getStateByUuid(START_STATE); + PatientProgram patientProgram = getPatientProgramByState(results.getPatient(), state, DATE); + PatientState patientState = getPatientState(patientProgram, state, DATE); + Assert.assertNotNull(patientProgram); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientProgram.getDateEnrolled())); + Assert.assertEquals(dateAsString(DATE), dateAsString(patientState.getStartDate())); + Assert.assertNull(patientProgram.getDateCompleted()); + Assert.assertNull(patientState.getEndDate()); + + List patientPrograms = Context.getProgramWorkflowService().getPatientPrograms(patient, + patientProgram.getProgram(), null, null, null, null, false); + + Assert.assertEquals(2, patientPrograms.size()); + } + }.run(); + + } + @Test public void shouldAllowToEditStateWithSameDate() throws Exception { new RegressionTestHelper() { diff --git a/api/src/main/java/org/openmrs/module/htmlformentry/FormSubmissionActions.java b/api/src/main/java/org/openmrs/module/htmlformentry/FormSubmissionActions.java index 843c51d88..617bebfb9 100644 --- a/api/src/main/java/org/openmrs/module/htmlformentry/FormSubmissionActions.java +++ b/api/src/main/java/org/openmrs/module/htmlformentry/FormSubmissionActions.java @@ -486,7 +486,21 @@ public void transitionToState(ProgramWorkflowState state) { throw new IllegalArgumentException("Cannot change state without an Encounter"); // fetch any existing patient program with a state from this workflow - PatientProgram patientProgram = HtmlFormEntryUtil.getPatientProgramByWorkflow(patient, state.getProgramWorkflow()); + PatientProgram patientProgram = HtmlFormEntryUtil.getPatientProgramByProgramOnDate(patient, + state.getProgramWorkflow().getProgram(), encounter.getEncounterDatetime()); + + //if there was none + if (patientProgram == null) { + //fall back to old behavior for lookup + patientProgram = HtmlFormEntryUtil.getPatientProgramByWorkflow(patient, state.getProgramWorkflow()); + + //but if this program was already completed, act like there was none + //so a new program enrollment will be created + if (patientProgram != null && patientProgram.getDateCompleted() != null + && !patientProgram.getDateCompleted().after(encounter.getEncounterDatetime())) { + patientProgram = null; + } + } // if no existing patient program, see if a patient program for this program is already set to be created at part of this submission (HTML-416) if (patientProgram == null) { diff --git a/api/src/main/java/org/openmrs/module/htmlformentry/element/WorkflowStateSubmissionElement.java b/api/src/main/java/org/openmrs/module/htmlformentry/element/WorkflowStateSubmissionElement.java index 5c07e2639..340d530dd 100644 --- a/api/src/main/java/org/openmrs/module/htmlformentry/element/WorkflowStateSubmissionElement.java +++ b/api/src/main/java/org/openmrs/module/htmlformentry/element/WorkflowStateSubmissionElement.java @@ -184,7 +184,23 @@ else if (!(widget instanceof HiddenFieldWidget)){ * @return */ private PatientState getActivePatientState(Patient patient, Date encounterDatetime, ProgramWorkflow workflow) { - PatientProgram patientProgram = HtmlFormEntryUtil.getPatientProgramByWorkflow(patient, workflow); + //try getting the state based on the encounter datetime + PatientProgram patientProgram = HtmlFormEntryUtil.getPatientProgramByProgramOnDate(patient, workflow.getProgram(), + encounterDatetime); + + //if there was none + if (patientProgram == null) { + //fall back to old behavior for lookup + patientProgram = HtmlFormEntryUtil.getPatientProgramByWorkflow(patient, workflow); + + //but if this program was already completed, and this is not a retroactive entry, + //act like there was no program, so a new program enrollment will be created + if (patientProgram != null && patientProgram.getDateCompleted() != null + && !patientProgram.getDateCompleted().after(encounterDatetime)) { + patientProgram = null; + } + } + if (patientProgram != null) { for (PatientState patientState : patientProgram.statesInWorkflow(workflow,false)) { if (patientState.getActive(encounterDatetime)) { @@ -215,9 +231,15 @@ public void handleSubmission(FormEntrySession session, HttpServletRequest submis if (!StringUtils.isBlank(stateUuid)) { if (Mode.EDIT.equals(session.getContext().getMode())) { + Date prevDate = session.getContext().getPreviousEncounterDate(); + if (prevDate == null) { + prevDate = session.getEncounter().getEncounterDatetime(); + } + ProgramWorkflowState newState = Context.getProgramWorkflowService().getStateByUuid(stateUuid); - PatientState oldPatientState = getActivePatientState(session.getContext().getExistingPatient(), session - .getContext().getPreviousEncounterDate(), workflow); + //find which state is "currently" active given the "current" encounter time + PatientState oldPatientState = getActivePatientState(session.getContext().getExistingPatient(), + prevDate, workflow); // if no old state, simply transition to this new state if (oldPatientState == null) {