Skip to content

Commit

Permalink
Fix bug with going back in subflows (#196)
Browse files Browse the repository at this point in the history
* Fix bug with going back in subflows

Co-authored-by: Ana Medrano <amedrano@codeforamerica.org>
  • Loading branch information
spokenbird and analoo committed Apr 3, 2024
1 parent 2b7fb08 commit a3c11fd
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 6 deletions.
@@ -0,0 +1,35 @@
package org.mdbenefits.app.submission.actions;


import formflow.library.config.submission.Action;
import formflow.library.data.Submission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class ClearIncompleteIncomeIterations implements Action {

/**
* This action will clear out the incomplete iterations from the income subflow. These can be created when the user goes back
* to the beginning of the subflow before completing an iteration.
*
* @param submission submission object the action is associated with, not null
* @param id the id of the current iteration being submitted when this action is run, not null
*/
@Override
public void run(Submission submission, String id) {
ArrayList<HashMap<String, Object>> incomeSubflow = (ArrayList<HashMap<String, Object>>) submission.getInputData().get("income");
if (incomeSubflow != null) {
List<HashMap<String, Object>> filteredIncomeSubflow = incomeSubflow.stream()
.filter(iteration -> id.equals(iteration.get("uuid")) ||
Boolean.TRUE.equals(iteration.get(Submission.ITERATION_IS_COMPLETE_KEY)))
.collect(Collectors.toList());
submission.getInputData().put("income", filteredIncomeSubflow);
}
}
}
@@ -0,0 +1,42 @@
package org.mdbenefits.app.submission.actions;

import formflow.library.config.submission.Action;
import formflow.library.data.Submission;
import formflow.library.data.SubmissionRepository;
import formflow.library.data.SubmissionRepositoryService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class ClearIncompleteIterationsFromHousehold implements Action {

SubmissionRepositoryService submissionRepositoryService;

public ClearIncompleteIterationsFromHousehold(SubmissionRepositoryService submissionRepositoryService) {
this.submissionRepositoryService = submissionRepositoryService;
}

/**
* This action will clear out the incomplete iterations from the household subflow. These can be created when the user goes back
* to the beginning of the subflow before completing an iteration.
*
* @param submission submission object the action is associated with, not null
*/
@Override
public void run(Submission submission) {
ArrayList<HashMap<String, Object>> household = (ArrayList<HashMap<String, Object>>) submission.getInputData().get("household");
if (household != null) {
List<HashMap<String, Object>> filteredHouseholdSubflow = household.stream()
.filter(iteration -> Boolean.TRUE.equals(iteration.get(Submission.ITERATION_IS_COMPLETE_KEY)))
.collect(Collectors.toList());
submission.getInputData().put("household", filteredHouseholdSubflow);
submissionRepositoryService.save(submission);
}
}
}
6 changes: 3 additions & 3 deletions src/main/java/org/mdbenefits/app/utils/IncomeCalculator.java
Expand Up @@ -21,11 +21,11 @@ public Double totalFutureEarnedIncome() {
// if submission.getInputData().
var jobs = (List<Map<String, Object>>) submission.getInputData()
.getOrDefault("income", new ArrayList<Map<String, Object>>());
var total = jobs.stream()
var completedJobs = jobs.stream().filter(job -> job.get(Submission.ITERATION_IS_COMPLETE_KEY).equals(true)).toList();

return completedJobs.stream()
.map(IncomeCalculator::futureIncomeForJob)
.reduce(0.0d, Double::sum);

return total;
}

public static double futureIncomeForJob(Map<String, Object> job) throws NumberFormatException {
Expand Down
Expand Up @@ -7,6 +7,7 @@
import java.time.OffsetDateTime;
import java.util.*;

import static formflow.library.data.Submission.ITERATION_IS_COMPLETE_KEY;
import static formflow.library.inputs.FieldNameMarkers.DYNAMIC_FIELD_MARKER;
import static java.util.Collections.emptyList;

Expand Down Expand Up @@ -183,9 +184,11 @@ public static ArrayList<HashMap<String, Object>> getHouseholdIncomeReviewItems(S
.getOrDefault("lastName", "");
var notYetShownNames = getHouseholdMemberNames(submission);
ArrayList<HashMap<String, Object>> items = new ArrayList<>();
List<HashMap<String, Object>> incomeSubflowIterations = (List<HashMap<String, Object>>) submission.getInputData()
.getOrDefault("income", new ArrayList<HashMap<String, Object>>());

for (var job : (List<HashMap<String, Object>>) submission.getInputData()
.getOrDefault("income", new ArrayList<HashMap<String, Object>>())) {
for (var job : incomeSubflowIterations.stream().filter(job ->
job.get(ITERATION_IS_COMPLETE_KEY).equals(true)).toList()) {
var item = new HashMap<String, Object>();
var name = job.get("householdMemberJobAdd").equals("you") ? applicantFullName : job.get("householdMemberJobAdd");
item.put("name", name);
Expand Down Expand Up @@ -266,7 +269,7 @@ public static boolean isNoneOfAboveSelection(@Nullable Object value) {
* Uses the "birthDay", "birthMonth", and "birthYear" fields from the input data to create an "MM/DD/YYYY" formatted string.
*
* @param inputData input data map to pull the dates from.
* @return
* @return formatted birthdate string in format of "MM/DD/YYYY"
*/
public static String getFormattedBirthdate(Map<String, Object> inputData) {
Integer month = Integer.valueOf((String) inputData.getOrDefault("birthMonth", "0"));
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/flows-config.yaml
Expand Up @@ -127,6 +127,7 @@ flow:
## END applicant information

householdList:
beforeDisplayAction: ClearIncompleteIterationsFromHousehold
nextScreens:
- name: householdSeasonalFarmWorker
householdInfo:
Expand Down Expand Up @@ -175,6 +176,7 @@ flow:
nextScreens:
- name: householdIncomeWho
householdIncomeWho:
beforeSaveAction: ClearIncompleteIncomeIterations
subflow: income
nextScreens:
- name: householdEmployerName
Expand Down
@@ -0,0 +1,46 @@
package org.mdbenefits.app.submission.actions;

import static org.assertj.core.api.Assertions.assertThat;

import formflow.library.data.Submission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;

class ClearIncompleteIncomeIterationsTest {

@Test
void shouldClearIncompleteIterationsFromIncomeSubflow() {
ClearIncompleteIncomeIterations clearIncompleteIncomeIterations = new ClearIncompleteIncomeIterations();
Submission submission = new Submission();
var income = new ArrayList<Map<String, Object>>();
var job1 = new HashMap<String, Object>();
job1.put(Submission.ITERATION_IS_COMPLETE_KEY, true);
job1.put("uuid", "complete iteration");
job1.put("employerName", "ACME Inc");
job1.put("payPeriod", "It varies");
job1.put("payPeriodAmount", 400.0);
var job2 = new HashMap<String, Object>();
job2.put(Submission.ITERATION_IS_COMPLETE_KEY, false);
job2.put("uuid", "Current Iteration");
job2.put("employerName", "Monsters Inc");
job2.put("payPeriodAmount", 200.0);
var job3 = new HashMap<String, Object>();
job3.put(Submission.ITERATION_IS_COMPLETE_KEY, false);
job3.put("uuid", "Incomplete Iteration");
job3.put("employerName", "Disney Inc");
income.add(job1);
income.add(job2);
income.add(job3);
HashMap<String, Object> inputData = new HashMap<>();
inputData.put("income", income);
submission.setInputData(inputData);
clearIncompleteIncomeIterations.run(submission, "Current Iteration");
ArrayList<HashMap<String, Object>> incomeSubflow = (ArrayList<HashMap<String, Object>>) submission.getInputData().get("income");
assertThat(incomeSubflow).size().isEqualTo(2);
assertThat(incomeSubflow).doesNotContain(job3);
assertThat(incomeSubflow).isEqualTo(List.of(job1, job2));
}
}
@@ -0,0 +1,53 @@
package org.mdbenefits.app.submission.actions;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import formflow.library.data.Submission;
import formflow.library.data.SubmissionRepositoryService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.ActiveProfiles;

@ActiveProfiles("test")
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ClearIncompleteIterationsFromHouseholdTest {

@Autowired
SubmissionRepositoryService submissionRepositoryService;

@Test
void shouldClearIncompleteIterationsFromHouseholdSubflow() {
ClearIncompleteIterationsFromHousehold clearIncompleteIterationsFromHousehold = new ClearIncompleteIterationsFromHousehold(submissionRepositoryService);
Submission submission = new Submission().builder()
.id(UUID.randomUUID())
.flow("flow")
.build();
var household = new ArrayList<Map<String, Object>>();
var householdMember1 = new HashMap<String, Object>();
householdMember1.put(Submission.ITERATION_IS_COMPLETE_KEY, true);
var householdMember2 = new HashMap<String, Object>();
householdMember2.put(Submission.ITERATION_IS_COMPLETE_KEY, true);
var householdMember3 = new HashMap<String, Object>();
householdMember3.put(Submission.ITERATION_IS_COMPLETE_KEY, false);
household.add(householdMember1);
household.add(householdMember2);
household.add(householdMember3);
HashMap<String, Object> inputData = new HashMap<>();
inputData.put("household", household);
submission.setInputData(inputData);
clearIncompleteIterationsFromHousehold.run(submission);
ArrayList<HashMap<String, Object>> incomeSubflow = (ArrayList<HashMap<String, Object>>) submission.getInputData().get("household");
assertThat(incomeSubflow).size().isEqualTo(2);
assertThat(incomeSubflow).doesNotContain(householdMember3);
assertThat(incomeSubflow).isEqualTo(List.of(householdMember1, householdMember2));
}
}
37 changes: 37 additions & 0 deletions src/test/java/org/mdbenefits/app/utils/IncomeCalculatorTest.java
@@ -0,0 +1,37 @@
package org.mdbenefits.app.utils;

import static org.junit.jupiter.api.Assertions.*;

import formflow.library.data.Submission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;

class IncomeCalculatorTest {

@Test
void totalFutureEarnedIncomeShouldFilterIncompleteSubflowIterations() {
// given
var submission = new Submission();
var income = new ArrayList<Map<String, Object>>();
var job1 = new HashMap<String, Object>();
job1.put(Submission.ITERATION_IS_COMPLETE_KEY, true);
job1.put("employerName", "ACME Inc");
job1.put("payPeriod", "It varies");
job1.put("payPeriodAmount", 400.0);
var job2 = new HashMap<String, Object>();
job2.put(Submission.ITERATION_IS_COMPLETE_KEY, false);
job2.put("employerName", "Monsters Inc");
job2.put("payPeriodAmount", 200.0);
income.add(job1);
income.add(job2);
submission.setInputData(Map.of("income", income));
var calculator = new IncomeCalculator(submission);

var total = calculator.totalFutureEarnedIncome();

// Amount will exclude amount from incomplete iteration
assertEquals(400.0, total);
}
}
31 changes: 31 additions & 0 deletions src/test/java/org/mdbenefits/app/utils/SubmissionUtilityTest.java
Expand Up @@ -2,7 +2,11 @@

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

import formflow.library.data.Submission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

Expand All @@ -22,4 +26,31 @@ public void shouldBeCorrectlyFormatted(String month, String day, String year, St
assertThat(SubmissionUtilities.getFormattedBirthdate(inputData)).isEqualTo(fullDate);
}

@Test
public void getHouseholdIncomeReviewItemsShouldIgnoreIncompleteSubflowIterations() {
Submission submission = new Submission();
HashMap<String, Object> job1 = new HashMap<>();
job1.put(Submission.ITERATION_IS_COMPLETE_KEY, true);
job1.put("householdMemberJobAdd", "you");
job1.put("employerName", "ACME Inc");
job1.put("payPeriod", "It varies");
job1.put("payPeriodAmount", 400.0);

HashMap<String, Object> job2 = new HashMap<>();
job2.put(Submission.ITERATION_IS_COMPLETE_KEY, false);
job2.put("employerName", "Monsters Inc");
job2.put("payPeriodAmount", 200.0);

ArrayList<Map<String, Object>> income = new ArrayList<>();
income.add(job1);
income.add(job2);

HashMap<String, Object> inputData = new HashMap<>();
inputData.put("income", income);
submission.setInputData(inputData);

ArrayList<HashMap<String, Object>> householdIncomeReviewItems = SubmissionUtilities.getHouseholdIncomeReviewItems(submission);
assertThat(householdIncomeReviewItems.stream().noneMatch(item -> item.getOrDefault("jobName", "").equals("Monsters Inc"))).isTrue();
assertThat(householdIncomeReviewItems.stream().noneMatch(item -> item.getOrDefault("income", "").equals("$200"))).isTrue();
}
}

0 comments on commit a3c11fd

Please sign in to comment.