From 276697605041bdff82a2e008470727a2de9c2182 Mon Sep 17 00:00:00 2001 From: Ken Long Date: Fri, 3 Apr 2020 16:56:23 -0700 Subject: [PATCH 1/2] HTML-722 : Setting a new patient program workflow state while editing an encounter should not overwrite previous states not related to the encounter --- .../htmlformentry/WorkflowStateTagTest.java | 88 +++++++++++++++++++ .../WorkflowStateSubmissionElement.java | 18 +++- 2 files changed, 103 insertions(+), 3 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..4995316cc 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 @@ -1623,6 +1623,94 @@ public void testBlankFormHtml(String html) { }.run(); } + @Test + public void shouldNotOverwritePreviousStateOnEdit() throws Exception { + //Given: Patient has a workflow state of X starting in Jan 2012 + transitionToState(START_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); + } + + @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:"), MIDDLE_STATE); + } + + @Override + public void testEditedResults(SubmissionResults results) { + results.assertNoErrors(); + + ProgramWorkflowState firstState = Context.getProgramWorkflowService().getStateByUuid(START_STATE); + ProgramWorkflowState secondState = Context.getProgramWorkflowService().getStateByUuid(MIDDLE_STATE); + + //verify existing behavior does match expectations for the second state + PatientProgram patientProgram = getPatientProgramByState(results.getPatient(), secondState, DATE); + PatientState currentPatientState = getPatientState(patientProgram, secondState, DATE); + Assert.assertNotNull(patientProgram); + Assert.assertEquals(dateAsString(PAST_DATE), dateAsString(patientProgram.getDateEnrolled())); + Assert.assertEquals(dateAsString(DATE), dateAsString(currentPatientState.getStartDate())); + Assert.assertNull(patientProgram.getDateCompleted()); + Assert.assertNull(currentPatientState.getEndDate()); + + //illustrate that this second state has overwritten the existing state + Assert.assertEquals(2, patientProgram.getStates().size()); + + //after the fix for this is in place, the following should also pass + PatientState previousPatientState = getPatientState(patientProgram, firstState, PAST_DATE); + + Assert.assertEquals(dateAsString(PAST_DATE), dateAsString(previousPatientState.getStartDate())); + Assert.assertEquals(dateAsString(DATE), dateAsString(previousPatientState.getEndDate())); + + List patientPrograms = Context.getProgramWorkflowService().getPatientPrograms(patient, + patientProgram.getProgram(), null, null, null, null, false); + + //only one program enrollment should exist + Assert.assertEquals(1, patientPrograms.size()); + } + }.run(); + + } + @Test public void checkboxShouldNotAppearCheckedIfNotCurrentlyInSpecifiedState() throws Exception { 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..0cf987ca3 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 @@ -215,9 +215,21 @@ 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); + PatientState oldPatientState = getActivePatientState(session.getContext().getExistingPatient(), prevDate, workflow); + + //since there is no direct connection between encounters and states + //the best that can be done, for now, is to check + //if the encounterDatetime matches the startDate + if (oldPatientState != null && !oldPatientState.getStartDate().equals(prevDate)) { + oldPatientState = null; + } // if no old state, simply transition to this new state if (oldPatientState == null) { @@ -226,7 +238,7 @@ public void handleSubmission(FormEntrySession session, HttpServletRequest submis // it is picked up by the FormSubmissionAction.transitionToState method and a new program is not created) PatientProgram patientProgram = HtmlFormEntryUtil.getPatientProgramByProgramOnDate(session.getPatient(), newState.getProgramWorkflow().getProgram(), session.getEncounter().getEncounterDatetime()); - + if (patientProgram != null) { session.getSubmissionActions().getPatientProgramsToUpdate().add(patientProgram); } From 75dc90275c32c2827f119daa1dc29efe30bdeed2 Mon Sep 17 00:00:00 2001 From: Ken Long Date: Mon, 6 Apr 2020 18:01:18 -0700 Subject: [PATCH 2/2] adding additional comments regarding logic around determining the link between a state and an encounter based on the datetime --- .../htmlformentry/element/WorkflowStateSubmissionElement.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 0cf987ca3..4625e7257 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 @@ -226,7 +226,9 @@ public void handleSubmission(FormEntrySession session, HttpServletRequest submis //since there is no direct connection between encounters and states //the best that can be done, for now, is to check - //if the encounterDatetime matches the startDate + //if the encounterDatetime exactly matches the startDate. + //If so, we presume the state was originally set via this form + //and therefore we need to modify it if (oldPatientState != null && !oldPatientState.getStartDate().equals(prevDate)) { oldPatientState = null; }