Skip to content

Commit

Permalink
Add Jefferson CSV with download endpoint (#710)
Browse files Browse the repository at this point in the history
* Add Jefferson CSV with download endpoint
  • Loading branch information
spokenbird committed Apr 26, 2024
1 parent c3266dd commit 13fea77
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 5 deletions.
16 changes: 16 additions & 0 deletions src/main/java/org/ladocuploader/app/FileExportController.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@ ResponseEntity<?> downloadWicCsv(

return handleCsvGeneration(encodedFlow, encodedSubmissionId, httpSession, locale, CsvType.WIC_APPLICATION);
}

@GetMapping("{flow}/jefferson-ece/{submissionId}")
ResponseEntity<?> downloadJeffersonEceCsv(
@PathVariable String flow,
@PathVariable String submissionId,
HttpSession httpSession,
Locale locale
) throws IOException, CsvRequiredFieldEmptyException, CsvDataTypeMismatchException {

String encodedFlow = UriComponentsBuilder.fromPath(flow).build().toUriString();
String encodedSubmissionId = UriComponentsBuilder.fromPath(submissionId).build().toUriString();

log.info("GET downloadCSV Jefferson ECE");

return handleCsvGeneration(encodedFlow, encodedSubmissionId, httpSession, locale, CsvType.JEFFERSON_ECE);
}


protected static void throwNotFoundError(String flow, String message) {
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/ladocuploader/app/csv/CsvGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.ladocuploader.app.csv.enums.CsvType;
import org.ladocuploader.app.csv.model.BaseCsvModel;
import org.ladocuploader.app.csv.model.ECEApplicationCsvModel;
import org.ladocuploader.app.csv.model.JeffersonCsvModel;
import org.ladocuploader.app.csv.model.ParentGuardianCsvModel;
import org.ladocuploader.app.csv.model.StudentCsvModel;
import org.ladocuploader.app.csv.model.RelationshipCsvModel;
Expand Down Expand Up @@ -119,6 +120,20 @@ public CsvDocument generateWICApplicationCsvData(List<Submission> submissionList
}
return generateCsv(CsvType.WIC_APPLICATION, WICApplicationCsvModel.class, applicationList);
}

public CsvDocument generateJeffersionApplicationCsvData(List<Submission> submissionList)
throws CsvRequiredFieldEmptyException, CsvDataTypeMismatchException, IOException {

List<BaseCsvModel> applicationList = new ArrayList<>();

for (Submission submission : submissionList) {
if(isEceEligibleAndInterested(submission)) {
BaseCsvModel application = JeffersonCsvModel.generateModel(submission);
applicationList.add(application);
}
}
return generateCsv(CsvType.JEFFERSON_ECE, JeffersonCsvModel.class, applicationList);
}

private CsvDocument generateCsv(CsvType csvType, Class classType, List<BaseCsvModel> objects) throws CsvRequiredFieldEmptyException, CsvDataTypeMismatchException, IOException {
CsvDocument csv = new CsvDocument(csvType);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/ladocuploader/app/csv/CsvService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.ladocuploader.app.csv;


import static org.ladocuploader.app.csv.enums.CsvType.JEFFERSON_ECE;
import static org.ladocuploader.app.csv.enums.CsvType.PARENT_GUARDIAN;
import static org.ladocuploader.app.csv.enums.CsvType.RELATIONSHIP;
import static org.ladocuploader.app.csv.enums.CsvType.STUDENT;
Expand Down Expand Up @@ -49,6 +50,7 @@ public CsvDocument generateCsvFormattedData(List<Submission> submissionList, Csv
case PARENT_GUARDIAN -> csvGenerator.generateParentGuardianCsvData(submissionList);
case ECE_APPLICATION -> csvGenerator.generateECEApplicationCsvData(submissionList);
case WIC_APPLICATION -> csvGenerator.generateWICApplicationCsvData(submissionList);
case JEFFERSON_ECE -> csvGenerator.generateJeffersionApplicationCsvData(submissionList);
default -> {
log.warn("Unknown CSV Type requested: {}", csvType.name());
yield null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ protected Object convert(String value) {
@Override
protected String convertToWrite(Object value) {
Map<String, Integer> dateMap = (Map) value;
if (dateMap.get("year") == null || dateMap.get("month") == null || dateMap.get("day") == null) {
return "";
}
return String.format("%04d-%02d-%02d",
dateMap.get("year"),
dateMap.get("month"),
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/ladocuploader/app/csv/enums/CsvType.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum CsvType {
STUDENT("Student", "student.csv"),
RELATIONSHIP("Relationship", "relationship.csv"),
ECE_APPLICATION("ECE Application", "application.csv"),
JEFFERSON_ECE("Jefferson ECE", "jefferson_ece.csv"),
WIC_APPLICATION("WIC Application", "application.csv");

private final String name;
Expand Down
178 changes: 178 additions & 0 deletions src/main/java/org/ladocuploader/app/csv/model/JeffersonCsvModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package org.ladocuploader.app.csv.model;

import static org.ladocuploader.app.utils.SubmissionUtilities.formatMoney;

import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.opencsv.bean.CsvBindByName;
import com.opencsv.bean.CsvCustomBindByName;
import formflow.library.data.Submission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.ladocuploader.app.csv.CsvBindByNameOrder;
import org.ladocuploader.app.csv.converters.AddressStreetConverter;
import org.ladocuploader.app.csv.converters.HouseholdBirthDateConverter;
import org.ladocuploader.app.csv.converters.PhoneNumberConverter;
import org.ladocuploader.app.utils.HouseholdUtilities;
import org.ladocuploader.app.utils.IncomeCalculator;
import org.ladocuploader.app.utils.SubmissionUtilities;

@Getter
@Setter
@JsonTypeName("jefferson")
@Slf4j
@CsvBindByNameOrder({"cfa_reference","Are you currently pregnant and planning to apply for your unborn child? *","First Name","Last Name","Gender","Birthdate","Race","Street Address","Street Address 2","City","State","Zip Code","Applicant First Name","Applicant Last Name","Cell Phone", "Main Phone","Work Phone","Email","Total Household Number","Applicant Gross Income","Do any of the child's legal guardians (who live in your household) have a disability?","How many of the child's legal guardians (who live in your household) are either working, in school, in a training program, or seeking work?"})
public class JeffersonCsvModel extends BaseCsvModel {

@CsvBindByName(column="cfa_reference")
private String id;

@CsvBindByName(column="Are you currently pregnant and planning to apply for your unborn child? *")
private String pregnant;

@CsvBindByName(column="First Name")
private String childFirstName;

@CsvBindByName(column="Last Name")
private String childLastName;

@CsvBindByName(column="Gender")
private String childGender;

@CsvCustomBindByName(column="Birthdate", converter= HouseholdBirthDateConverter.class)
private Map<String, Integer> childBirthDate = new HashMap<>();

@CsvBindByName(column="Race")
private String childRace;

@CsvBindByName(column="Street Address")
private String homeAddressStreet;

@CsvBindByName(column="Street Address 2")
private String homeAddressStreet2;

@CsvBindByName(column="City")
private String homeAddressCity;

@CsvBindByName(column="State")
private String homeAddressState;

@CsvBindByName(column="Zip Code")
private String homeAddressZipCode;

@CsvBindByName(column="Applicant First Name")
private String firstName;

@CsvBindByName(column="Applicant Last Name")
private String lastName;

@CsvCustomBindByName(column="Cell Phone", converter = PhoneNumberConverter.class)
private String cellPhoneNumber;

@CsvCustomBindByName(column="Main Phone", converter = PhoneNumberConverter.class)
private String phoneNumber;

@CsvCustomBindByName(column="Work Phone", converter = PhoneNumberConverter.class)
private String workPhoneNumber;

@CsvBindByName(column="Email")
private String emailAddress;

@CsvBindByName(column="Total Household Number")
private String totalHouseholdNumber;

@CsvBindByName(column="Applicant Gross Income")
private String applicantGrossIncome;

@CsvBindByName(column="Do any of the child's legal guardians (who live in your household) have a disability?")
private String disability;

@CsvBindByName(column="How many of the child's legal guardians (who live in your household) are either working, in school, in a training program, or seeking work?")
private String guardiansWorking;


@JsonSetter(value="memberBirthDay")
private void setMemberBirthDay(final String day) {
try {
if (day != null) {
childBirthDate.put("day", Integer.valueOf(day));
}
} catch (NumberFormatException e) {
log.error("JSON Mapping: Unable to set member birth day, as value '{}' is bad.", day);
}
}

@JsonSetter(value="memberBirthMonth")
private void setMemberBirthMonth(final String month) {
try {
if (month != null) {
childBirthDate.put("month", Integer.valueOf(month));
}
} catch (NumberFormatException e) {
log.error("JSON Mapping: Unable to set member birth month, as value '{}' is bad.", month);
}
}

@JsonSetter(value="memberBirthYear")
private void setMemberBirthYear(final String year) {
try {
if (year != null) {
childBirthDate.put("year", Integer.valueOf(year));
}
} catch (NumberFormatException e) {
log.error("JSON Mapping: Unable to set member birth year, as value '{}' is bad.", year);
}
}

public static BaseCsvModel generateModel(Submission submission){
Map<String, Object> inputData = submission.getInputData();
Map<String, Object> jeffersonDataMap = new HashMap<>();

jeffersonDataMap.put("id", submission.getId());
boolean hasPregnancy = "true".equals(inputData.getOrDefault("pregnancyInd", "false"));
jeffersonDataMap.put("pregnant", hasPregnancy ? "Yes" : "No");

List<Map<String, Object>> householdList = (List) inputData.getOrDefault("household", List.of());
householdList.stream().filter(HouseholdUtilities::isMemberCutoffEligible).findFirst().ifPresent(member -> {
jeffersonDataMap.put("childFirstName", member.get("householdMemberFirstName"));
jeffersonDataMap.put("childLastName", member.get("householdMemberLastName"));
jeffersonDataMap.put("childGender", member.get("householdMemberSex"));
jeffersonDataMap.put("memberBirthDay", member.get("householdMemberBirthDay"));
jeffersonDataMap.put("memberBirthMonth", member.get("householdMemberBirthMonth"));
jeffersonDataMap.put("memberBirthYear", member.get("householdMemberBirthYear"));
if (submission.getInputData().containsKey("householdMemberRace_wildcard_" + member.get("uuid") + "[]")) {
jeffersonDataMap.put("childRace", String.join(", ", (List) submission.getInputData().get("householdMemberRace_wildcard_" + member.get("uuid") + "[]")));
}
});

jeffersonDataMap.put("homeAddressStreet", inputData.get("homeAddressStreetAddress1"));
jeffersonDataMap.put("homeAddressStreet2", inputData.getOrDefault("homeAddressStreetAddress2", ""));
jeffersonDataMap.put("homeAddressCity", inputData.get("homeAddressCity"));
jeffersonDataMap.put("homeAddressState", inputData.get("homeAddressState"));
jeffersonDataMap.put("homeAddressZipCode", inputData.get("homeAddressZipCode"));
jeffersonDataMap.put("firstName", inputData.get("firstName"));
jeffersonDataMap.put("lastName", inputData.get("lastName"));
jeffersonDataMap.put("cellPhoneNumber", inputData.getOrDefault("cellPhoneNumber", ""));
jeffersonDataMap.put("phoneNumber", inputData.getOrDefault("phoneNumber", ""));
jeffersonDataMap.put("workPhoneNumber", inputData.getOrDefault("workPhoneNumber", ""));
jeffersonDataMap.put("emailAddress", inputData.getOrDefault("emailAddress", ""));
jeffersonDataMap.put("totalHouseholdNumber", householdList.size() + 1); // +1 for the applicant

IncomeCalculator incomeCalculator = new IncomeCalculator(submission);

jeffersonDataMap.put("applicantGrossIncome", formatMoney(incomeCalculator.applicantTotalFutureEarnedIncome()));
if (inputData.containsKey("guardiansHaveDisabilityInd")) {
boolean guardianHasDisability = "true".equals(inputData.get("guardiansHaveDisabilityInd"));
jeffersonDataMap.put("disability", guardianHasDisability ? "Yes" : "No");
}
jeffersonDataMap.put("guardiansWorking", inputData.getOrDefault("adultsWorking", ""));
JeffersonCsvModel jeffersonModel = mapper.convertValue(jeffersonDataMap, JeffersonCsvModel.class);
jeffersonModel.setSubmissionId(submission.getId());
return jeffersonModel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,19 @@ public static boolean isMemberEceEligible(Map<String, Object> member, Map<String
return true;
}

return isMemberCutoffEligible(member);
}

public static boolean isMemberCutoffEligible(Map<String, Object> member) {
try {

int birthDay = Integer.parseInt((String) member.get("householdMemberBirthDay"));
int birthMonth = Integer.parseInt((String) member.get("householdMemberBirthMonth"));
int birthYear = Integer.parseInt((String) member.get("householdMemberBirthYear"));

if (birthDay <= 0 || birthMonth <= 0 || birthYear <= 0 ) {
log.warn("Did not find birthdate. Marking household member as ineligible");
return false;
log.warn("Did not find birthdate. Marking household member as ineligible");
return false;
}

// these are converted to milliseconds since Epoch and then compared.
Expand All @@ -82,8 +86,6 @@ public static boolean isMemberEceEligible(Map<String, Object> member, Map<String
log.warn("Could not parse birthdate. Marking household member as ineligible");
return false;
}


}

public static List<Map<String, Object>> formattedHouseholdData(Submission submission, String key) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/ladocuploader/app/utils/IncomeCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ public Double totalFutureEarnedIncome() {

return total;
}

public Double applicantTotalFutureEarnedIncome() {
var jobs = (List<Map<String, Object>>) submission.getInputData().getOrDefault("income", new ArrayList<>());
var total = jobs.stream()
.filter(job -> (boolean) job.getOrDefault("iterationIsComplete", false))
.filter(job -> "you".equals(job.get("householdMemberJobAdd")))
.map(IncomeCalculator::futureIncomeForJob)
.reduce(0.0d, Double::sum);

return total;
}

public static double futureIncomeForJob(Map<String, Object> job) throws NumberFormatException {
if (job.getOrDefault("jobPaidByHour", "false").toString().equals("true")) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/templates/fragments/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<a class="link--subtle" target="_blank" rel="noopener noreferrer" th:if="${submission != null}" th:href="'/download-csv/laDigitalAssister/student/' + ${submission.getId()}">Student Summary CSV</a> |
<a class="link--subtle" target="_blank" rel="noopener noreferrer" th:if="${submission != null}" th:href="'/download-csv/laDigitalAssister/ece/' + ${submission.getId()}">ECE Summary CSV</a> |
<a class="link--subtle" target="_blank" rel="noopener noreferrer" th:if="${submission != null}" th:href="'/download-csv/laDigitalAssister/wic/' + ${submission.getId()}">WIC Summary CSV</a> |
<a class="link--subtle" target="_blank" rel="noopener noreferrer" th:if="${submission != null}" th:href="'/download-csv/laDigitalAssister/jefferson-ece/' + ${submission.getId()}">Jefferson Summary CSV</a> |
<a class="link--subtle" target="_blank" rel="noopener noreferrer" th:if="${submission != null}" th:href="'/download/laDigitalAssister/' + ${submission.getId()}">Applicant PDF</a>
</th:block>
<th:block th:if="${#arrays.contains(@environment.getActiveProfiles(), 'staging')}">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ <h2 th:text="#{race-selection.header(${inputData.firstName})}"></h2>
<hr/>

<th:block th:if="${fieldData.containsKey('household')}">
<p th:value="${fieldData.household}"></p>
<div th:each="householdMember, iter: ${fieldData.household}"
class="spacing-below-15">
<th:block
Expand Down

0 comments on commit 13fea77

Please sign in to comment.