From 830dc6a4485fd301ec0d4c03c0b2123315d53898 Mon Sep 17 00:00:00 2001 From: alexmcdermid Date: Wed, 14 Aug 2024 10:34:34 -0700 Subject: [PATCH 1/5] ind downloadable report by dis --- .../api/constants/v1/ReportTypeCode.java | 2 + .../v1/ReportGenerationController.java | 3 +- .../IndigenousHeadcountReportService.java | 42 +++++++++++++------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/constants/v1/ReportTypeCode.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/constants/v1/ReportTypeCode.java index 3f3135e84..edabce3d7 100644 --- a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/constants/v1/ReportTypeCode.java +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/constants/v1/ReportTypeCode.java @@ -19,6 +19,8 @@ public enum ReportTypeCode { DIS_SPECIAL_EDUCATION_HEADCOUNT("DIS_SPECIAL_EDUCATION_HEADCOUNT"), DIS_SPECIAL_EDUCATION_HEADCOUNT_PER_SCHOOL("DIS_SPECIAL_EDUCATION_HEADCOUNT_PER_SCHOOL"), INDIGENOUS_HEADCOUNT("INDIGENOUS_HEADCOUNT"), + DIS_INDIGENOUS_HEADCOUNT("DIS_INDIGENOUS_HEADCOUNT"), + DIS_INDIGENOUS_HEADCOUNT_PER_SCHOOL("DIS_INDIGENOUS_HEADCOUNT_PER_SCHOOL"), BAND_RESIDENCE_HEADCOUNT("BAND_RESIDENCE_HEADCOUNT"), CAREER_HEADCOUNT("CAREER_HEADCOUNT"), FRENCH_HEADCOUNT("FRENCH_HEADCOUNT"), diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java index 8a0241e03..687308681 100644 --- a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java @@ -67,7 +67,8 @@ public DownloadableReportResponse generateSDCReport(UUID collectionID, String re case FRENCH_HEADCOUNT -> frenchProgramHeadcountReportService.generateFrenchProgramHeadcountReport(collectionID, false); case DIS_FRENCH_HEADCOUNT -> frenchProgramHeadcountReportService.generateFrenchProgramHeadcountReport(collectionID, true); case DIS_FRENCH_HEADCOUNT_PER_SCHOOL -> frenchPerSchoolHeadcountReportService.generatePerSchoolReport(collectionID); - case INDIGENOUS_HEADCOUNT -> indigenousHeadcountReportService.generateIndigenousHeadcountReport(collectionID); + case INDIGENOUS_HEADCOUNT -> indigenousHeadcountReportService.generateIndigenousHeadcountReport(collectionID, false); + case DIS_INDIGENOUS_HEADCOUNT -> indigenousHeadcountReportService.generateIndigenousHeadcountReport(collectionID, true); case BAND_RESIDENCE_HEADCOUNT -> bandOfResidenceHeadcountReportService.generateBandOfResdienceReport(collectionID); case DIS_REFUGEE_HEADCOUNT_PER_SCHOOL -> refugeeHeadcountPerSchoolReportService.generateRefugeePerSchoolReport(collectionID); case ELL_HEADCOUNT -> ellHeadcountReportService.generateEllHeadcountReport(collectionID); diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousHeadcountReportService.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousHeadcountReportService.java index c67289c28..2989021f3 100644 --- a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousHeadcountReportService.java +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousHeadcountReportService.java @@ -4,8 +4,10 @@ import ca.bc.gov.educ.studentdatacollection.api.constants.v1.SchoolGradeCodes; import ca.bc.gov.educ.studentdatacollection.api.exception.EntityNotFoundException; import ca.bc.gov.educ.studentdatacollection.api.exception.StudentDataCollectionAPIRuntimeException; +import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcDistrictCollectionEntity; import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcSchoolCollectionEntity; import ca.bc.gov.educ.studentdatacollection.api.properties.ApplicationProperties; +import ca.bc.gov.educ.studentdatacollection.api.repository.v1.SdcDistrictCollectionRepository; import ca.bc.gov.educ.studentdatacollection.api.repository.v1.SdcSchoolCollectionRepository; import ca.bc.gov.educ.studentdatacollection.api.repository.v1.SdcSchoolCollectionStudentRepository; import ca.bc.gov.educ.studentdatacollection.api.rest.RestUtils; @@ -31,12 +33,14 @@ public class IndigenousHeadcountReportService extends BaseReportGenerationServic private final SdcSchoolCollectionRepository sdcSchoolCollectionRepository; private final SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository; + private final SdcDistrictCollectionRepository sdcDistrictCollectionRepository; private JasperReport indigenousHeadcountReport; - public IndigenousHeadcountReportService(SdcSchoolCollectionRepository sdcSchoolCollectionRepository, SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository, RestUtils restUtils) { + public IndigenousHeadcountReportService(SdcSchoolCollectionRepository sdcSchoolCollectionRepository, SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository, RestUtils restUtils, SdcDistrictCollectionRepository sdcDistrictCollectionRepository) { super(restUtils, sdcSchoolCollectionRepository); this.sdcSchoolCollectionRepository = sdcSchoolCollectionRepository; this.sdcSchoolCollectionStudentRepository = sdcSchoolCollectionStudentRepository; + this.sdcDistrictCollectionRepository = sdcDistrictCollectionRepository; } @PostConstruct @@ -57,17 +61,31 @@ private void compileJasperReports(){ } } - public DownloadableReportResponse generateIndigenousHeadcountReport(UUID collectionID){ - try { - Optional sdcSchoolCollectionEntityOptional = sdcSchoolCollectionRepository.findById(collectionID); - SdcSchoolCollectionEntity sdcSchoolCollectionEntity = sdcSchoolCollectionEntityOptional.orElseThrow(() -> - new EntityNotFoundException(SdcSchoolCollectionEntity.class, "Collection by Id", collectionID.toString())); - - var headcountsList = sdcSchoolCollectionStudentRepository.getIndigenousHeadcountsBySdcSchoolCollectionId(sdcSchoolCollectionEntity.getSdcSchoolCollectionID()); - return generateJasperReport(convertToReportJSONString(headcountsList, sdcSchoolCollectionEntity), indigenousHeadcountReport, ReportTypeCode.INDIGENOUS_HEADCOUNT); - } catch (JsonProcessingException e) { - log.error("Exception occurred while writing PDF report for indigenous programs :: " + e.getMessage()); - throw new StudentDataCollectionAPIRuntimeException("Exception occurred while writing PDF report for indigenous programs :: " + e.getMessage()); + public DownloadableReportResponse generateIndigenousHeadcountReport(UUID collectionID, Boolean isDistrict){ + if (Boolean.TRUE.equals(isDistrict)) { + try { + Optional sdcDistrictCollectionEntityOptional = sdcDistrictCollectionRepository.findById(collectionID); + SdcDistrictCollectionEntity sdcDistrictCollectionEntity = sdcDistrictCollectionEntityOptional.orElseThrow(() -> + new EntityNotFoundException(SdcDistrictCollectionEntity.class, "Collection ID: " + collectionID)); + + var programList = sdcSchoolCollectionStudentRepository.getIndigenousHeadcountsBySdcDistrictCollectionId(sdcDistrictCollectionEntity.getSdcDistrictCollectionID()); + return generateJasperReport(convertToReportJSONStringDistrict(programList, sdcDistrictCollectionEntity), indigenousHeadcountReport, ReportTypeCode.DIS_INDIGENOUS_HEADCOUNT); + } catch (JsonProcessingException e) { + log.error("Exception occurred while writing PDF report for district indigenous programs :: " + e.getMessage()); + throw new StudentDataCollectionAPIRuntimeException("Exception occurred while writing PDF report for district indigenous programs :: " + e.getMessage()); + } + } else { + try { + Optional sdcSchoolCollectionEntityOptional = sdcSchoolCollectionRepository.findById(collectionID); + SdcSchoolCollectionEntity sdcSchoolCollectionEntity = sdcSchoolCollectionEntityOptional.orElseThrow(() -> + new EntityNotFoundException(SdcSchoolCollectionEntity.class, "Collection by Id", collectionID.toString())); + + var headcountsList = sdcSchoolCollectionStudentRepository.getIndigenousHeadcountsBySdcSchoolCollectionId(sdcSchoolCollectionEntity.getSdcSchoolCollectionID()); + return generateJasperReport(convertToReportJSONString(headcountsList, sdcSchoolCollectionEntity), indigenousHeadcountReport, ReportTypeCode.INDIGENOUS_HEADCOUNT); + } catch (JsonProcessingException e) { + log.error("Exception occurred while writing PDF report for indigenous programs :: " + e.getMessage()); + throw new StudentDataCollectionAPIRuntimeException("Exception occurred while writing PDF report for indigenous programs :: " + e.getMessage()); + } } } From 335fbc6b9bc0a4616b70d33dac69ad4726838326 Mon Sep 17 00:00:00 2001 From: alexmcdermid Date: Wed, 14 Aug 2024 11:14:58 -0700 Subject: [PATCH 2/5] ind downloadable report by dis per school --- .../v1/ReportGenerationController.java | 2 + ...genousPerSchoolHeadcountReportService.java | 145 +++ .../reports/indigenousHeadcounts.jrxml | 2 +- .../indigenousHeadcountsPerSchool.jrxml | 934 ++++++++++++++++++ 4 files changed, 1082 insertions(+), 1 deletion(-) create mode 100644 api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java create mode 100644 api/src/main/resources/reports/indigenousHeadcountsPerSchool.jrxml diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java index 687308681..662d9db76 100644 --- a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationController.java @@ -36,6 +36,7 @@ public class ReportGenerationController implements ReportGenerationEndpoint { private final FrenchProgramHeadcountReportService frenchProgramHeadcountReportService; private final FrenchPerSchoolHeadcountReportService frenchPerSchoolHeadcountReportService; private final IndigenousHeadcountReportService indigenousHeadcountReportService; + private final IndigenousPerSchoolHeadcountReportService indigenousPerSchoolHeadcountReportService; private final EllHeadcountReportService ellHeadcountReportService; private final SpecialEdHeadcountReportService specialEdHeadcountReportService; private final SpecialEdHeadcountPerSchoolReportService specialEdHeadcountPerSchoolReportService; @@ -69,6 +70,7 @@ public DownloadableReportResponse generateSDCReport(UUID collectionID, String re case DIS_FRENCH_HEADCOUNT_PER_SCHOOL -> frenchPerSchoolHeadcountReportService.generatePerSchoolReport(collectionID); case INDIGENOUS_HEADCOUNT -> indigenousHeadcountReportService.generateIndigenousHeadcountReport(collectionID, false); case DIS_INDIGENOUS_HEADCOUNT -> indigenousHeadcountReportService.generateIndigenousHeadcountReport(collectionID, true); + case DIS_INDIGENOUS_HEADCOUNT_PER_SCHOOL -> indigenousPerSchoolHeadcountReportService.generateIndigenousHeadcountPerSchoolReport(collectionID); case BAND_RESIDENCE_HEADCOUNT -> bandOfResidenceHeadcountReportService.generateBandOfResdienceReport(collectionID); case DIS_REFUGEE_HEADCOUNT_PER_SCHOOL -> refugeeHeadcountPerSchoolReportService.generateRefugeePerSchoolReport(collectionID); case ELL_HEADCOUNT -> ellHeadcountReportService.generateEllHeadcountReport(collectionID); diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java new file mode 100644 index 000000000..30a1292d1 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java @@ -0,0 +1,145 @@ +package ca.bc.gov.educ.studentdatacollection.api.reports; + +import ca.bc.gov.educ.studentdatacollection.api.constants.v1.ReportTypeCode; +import ca.bc.gov.educ.studentdatacollection.api.constants.v1.SchoolGradeCodes; +import ca.bc.gov.educ.studentdatacollection.api.exception.EntityNotFoundException; +import ca.bc.gov.educ.studentdatacollection.api.exception.StudentDataCollectionAPIRuntimeException; +import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcDistrictCollectionEntity; +import ca.bc.gov.educ.studentdatacollection.api.properties.ApplicationProperties; +import ca.bc.gov.educ.studentdatacollection.api.repository.v1.SdcDistrictCollectionRepository; +import ca.bc.gov.educ.studentdatacollection.api.repository.v1.SdcSchoolCollectionRepository; +import ca.bc.gov.educ.studentdatacollection.api.repository.v1.SdcSchoolCollectionStudentRepository; +import ca.bc.gov.educ.studentdatacollection.api.rest.RestUtils; +import ca.bc.gov.educ.studentdatacollection.api.struct.external.institute.v1.SchoolTombstone; +import ca.bc.gov.educ.studentdatacollection.api.struct.v1.headcounts.IndigenousHeadcountResult; +import ca.bc.gov.educ.studentdatacollection.api.struct.v1.reports.DownloadableReportResponse; +import ca.bc.gov.educ.studentdatacollection.api.struct.v1.reports.HeadcountChildNode; +import com.fasterxml.jackson.core.JsonProcessingException; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperReport; +import org.springframework.stereotype.Service; + +import java.io.InputStream; +import java.util.*; + +@Service +@Slf4j +public class IndigenousPerSchoolHeadcountReportService extends BaseReportGenerationService { + + private final SdcDistrictCollectionRepository sdcDistrictCollectionRepository; + private final SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository; + private JasperReport indHeadcountPerSchoolReport; + private final RestUtils restUtils; + private List indHeadcounts = new ArrayList<>(); + private List allSchoolsTombstones; + + public IndigenousPerSchoolHeadcountReportService(SdcDistrictCollectionRepository sdcDistrictCollectionRepository, SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository, RestUtils restUtils, SdcSchoolCollectionRepository sdcSchoolCollectionRepository, RestUtils restUtils1) { + super(restUtils, sdcSchoolCollectionRepository); + + this.sdcDistrictCollectionRepository = sdcDistrictCollectionRepository; + this.sdcSchoolCollectionStudentRepository = sdcSchoolCollectionStudentRepository; + this.restUtils = restUtils1; + } + + @PostConstruct + public void init() { + ApplicationProperties.bgTask.execute(this::initialize); + } + + private void initialize() { + this.compileJasperReports(); + } + + private void compileJasperReports() { + try { + InputStream inputSpecialEdHeadcount = getClass().getResourceAsStream("/reports/indigenousHeadcountsPerSchool.jrxml"); + indHeadcountPerSchoolReport = JasperCompileManager.compileReport(inputSpecialEdHeadcount); + } catch (JRException e) { + throw new StudentDataCollectionAPIRuntimeException("Compiling Jasper reports has failed :: " + e.getMessage()); + } + } + + public DownloadableReportResponse generateIndigenousHeadcountPerSchoolReport(UUID collectionID) { + try { + Optional sdcDistrictCollectionEntityOptional = sdcDistrictCollectionRepository.findById(collectionID); + SdcDistrictCollectionEntity sdcDistrictCollectionEntity = sdcDistrictCollectionEntityOptional.orElseThrow(() -> + new EntityNotFoundException(SdcDistrictCollectionEntity.class, "CollectionId", collectionID.toString())); + + indHeadcounts = sdcSchoolCollectionStudentRepository.getIndigenousHeadcountsBySdcDistrictCollectionIdGroupBySchoolId(sdcDistrictCollectionEntity.getSdcDistrictCollectionID()); + this.allSchoolsTombstones = getAllSchoolTombstones(collectionID); + return generateJasperReport(convertToReportJSONStringDistrict(indHeadcounts, sdcDistrictCollectionEntity), indHeadcountPerSchoolReport, ReportTypeCode.DIS_INDIGENOUS_HEADCOUNT_PER_SCHOOL); + } catch (JsonProcessingException e) { + log.error("Exception occurred while writing PDF report for inclusive education dis per school :: " + e.getMessage()); + throw new StudentDataCollectionAPIRuntimeException("Exception occurred while writing PDF report for inclusive education dis per school :: " + e.getMessage()); + } + } + + public HashMap generateNodeMap(boolean includeKH) { + HashMap nodeMap = new HashMap<>(); + Set includedSchoolIDs = new HashSet<>(); + + int sequencePrefix = 10; + if (!indHeadcounts.isEmpty()) { + for (IndigenousHeadcountResult result : indHeadcounts) { + String schoolID = result.getSchoolID(); + Optional schoolOptional = restUtils.getSchoolBySchoolID(schoolID); + int finalSequencePrefix = sequencePrefix; + schoolOptional.ifPresent(school -> { + includedSchoolIDs.add(school.getSchoolId()); + String schoolTitle = school.getMincode() + " - " + school.getDisplayName(); + addValuesForSectionToMap(nodeMap, schoolID, schoolTitle, String.valueOf(finalSequencePrefix)); + }); + sequencePrefix += 10; + } + } + + for (SchoolTombstone school : allSchoolsTombstones) { + if (!includedSchoolIDs.contains(school.getSchoolId())) { + String schoolTitle = school.getMincode() + " - " + school.getDisplayName(); + addValuesForSectionToMap(nodeMap, school.getSchoolId(), schoolTitle, String.valueOf(sequencePrefix)); + sequencePrefix += 10; + } + } + + return nodeMap; + } + + private void addValuesForSectionToMap(HashMap nodeMap, String sectionPrefix, String sectionTitle, String sequencePrefix){ + nodeMap.put(sectionPrefix + "Heading", new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false)); + nodeMap.put(sectionPrefix + "indLang", new HeadcountChildNode("Indigenous Language and Culture", FALSE, sequencePrefix + "1", false)); + nodeMap.put(sectionPrefix + "indSupport", new HeadcountChildNode("Indigenous Support Services", FALSE, sequencePrefix + "2", false)); + nodeMap.put(sectionPrefix + "indProg", new HeadcountChildNode("Other Approved Indigenous Programs", FALSE, sequencePrefix + "3", false)); + nodeMap.put(sectionPrefix + "all", new HeadcountChildNode("All Indigenous Support Programs", FALSE, sequencePrefix + "4", false)); + } + + public void setValueForGrade(HashMap nodeMap, IndigenousHeadcountResult gradeResult) { + Optional optionalCode = SchoolGradeCodes.findByValue(gradeResult.getEnrolledGradeCode()); + var code = optionalCode.orElseThrow(() -> + new EntityNotFoundException(SchoolGradeCodes.class, "Grade Value", gradeResult.getEnrolledGradeCode())); + String schoolID = gradeResult.getSchoolID(); + + if (nodeMap.containsKey(schoolID + "indLang")) { + nodeMap.get(schoolID + "indLang").setValueForGrade(code, gradeResult.getIndigenousLanguageTotal()); + } + + if (nodeMap.containsKey(schoolID + "indSupport")) { + nodeMap.get(schoolID + "indSupport").setValueForGrade(code, gradeResult.getIndigenousSupportTotal()); + } + + if (nodeMap.containsKey(schoolID + "indProg")) { + nodeMap.get(schoolID + "indProg").setValueForGrade(code, gradeResult.getOtherProgramTotal()); + } + + if (nodeMap.containsKey(schoolID + "all")) { + nodeMap.get(schoolID + "all").setValueForGrade(code, gradeResult.getAllSupportProgramTotal()); + } + + if (nodeMap.containsKey(schoolID + "Heading")) { + nodeMap.get(schoolID + "Heading").setAllValuesToNull(); + } + } + +} diff --git a/api/src/main/resources/reports/indigenousHeadcounts.jrxml b/api/src/main/resources/reports/indigenousHeadcounts.jrxml index 8d1b88fc3..cf55c7e5a 100644 --- a/api/src/main/resources/reports/indigenousHeadcounts.jrxml +++ b/api/src/main/resources/reports/indigenousHeadcounts.jrxml @@ -296,7 +296,7 @@ - + diff --git a/api/src/main/resources/reports/indigenousHeadcountsPerSchool.jrxml b/api/src/main/resources/reports/indigenousHeadcountsPerSchool.jrxml new file mode 100644 index 000000000..4381cf334 --- /dev/null +++ b/api/src/main/resources/reports/indigenousHeadcountsPerSchool.jrxml @@ -0,0 +1,934 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9cb578a68bd3e7721691a8952ccc9860031e6753 Mon Sep 17 00:00:00 2001 From: alexmcdermid Date: Wed, 14 Aug 2024 11:33:21 -0700 Subject: [PATCH 3/5] adds per schools total row to ind and sped --- ...genousPerSchoolHeadcountReportService.java | 25 ++++++++++++---- ...cialEdHeadcountPerSchoolReportService.java | 29 ++++++++++++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java index 30a1292d1..406b51399 100644 --- a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/IndigenousPerSchoolHeadcountReportService.java @@ -29,6 +29,7 @@ @Slf4j public class IndigenousPerSchoolHeadcountReportService extends BaseReportGenerationService { + protected static final String ALLIND = "allInd"; private final SdcDistrictCollectionRepository sdcDistrictCollectionRepository; private final SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository; private JasperReport indHeadcountPerSchoolReport; @@ -80,6 +81,7 @@ public DownloadableReportResponse generateIndigenousHeadcountPerSchoolReport(UUI public HashMap generateNodeMap(boolean includeKH) { HashMap nodeMap = new HashMap<>(); Set includedSchoolIDs = new HashSet<>(); + addValuesForSectionToMap(nodeMap, ALLIND, "All Indigenous Support Program Headcount for All Schools", "00"); int sequencePrefix = 10; if (!indHeadcounts.isEmpty()) { @@ -108,11 +110,15 @@ public HashMap generateNodeMap(boolean includeKH) { } private void addValuesForSectionToMap(HashMap nodeMap, String sectionPrefix, String sectionTitle, String sequencePrefix){ - nodeMap.put(sectionPrefix + "Heading", new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false)); - nodeMap.put(sectionPrefix + "indLang", new HeadcountChildNode("Indigenous Language and Culture", FALSE, sequencePrefix + "1", false)); - nodeMap.put(sectionPrefix + "indSupport", new HeadcountChildNode("Indigenous Support Services", FALSE, sequencePrefix + "2", false)); - nodeMap.put(sectionPrefix + "indProg", new HeadcountChildNode("Other Approved Indigenous Programs", FALSE, sequencePrefix + "3", false)); - nodeMap.put(sectionPrefix + "all", new HeadcountChildNode("All Indigenous Support Programs", FALSE, sequencePrefix + "4", false)); + if (Objects.equals(sectionPrefix, ALLIND)) { + nodeMap.put(sectionPrefix, new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false, false, false, false)); + } else { + nodeMap.put(sectionPrefix + "Heading", new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false)); + nodeMap.put(sectionPrefix + "indLang", new HeadcountChildNode("Indigenous Language and Culture", FALSE, sequencePrefix + "1", false)); + nodeMap.put(sectionPrefix + "indSupport", new HeadcountChildNode("Indigenous Support Services", FALSE, sequencePrefix + "2", false)); + nodeMap.put(sectionPrefix + "indProg", new HeadcountChildNode("Other Approved Indigenous Programs", FALSE, sequencePrefix + "3", false)); + nodeMap.put(sectionPrefix + "all", new HeadcountChildNode("All Indigenous Support Programs", FALSE, sequencePrefix + "4", false)); + } } public void setValueForGrade(HashMap nodeMap, IndigenousHeadcountResult gradeResult) { @@ -121,6 +127,11 @@ public void setValueForGrade(HashMap nodeMap, Indige new EntityNotFoundException(SchoolGradeCodes.class, "Grade Value", gradeResult.getEnrolledGradeCode())); String schoolID = gradeResult.getSchoolID(); + HeadcountChildNode allIndNode = nodeMap.get(ALLIND); + if (allIndNode.getValueForGrade(code) == null) { + allIndNode.setValueForGrade(code, "0"); + } + if (nodeMap.containsKey(schoolID + "indLang")) { nodeMap.get(schoolID + "indLang").setValueForGrade(code, gradeResult.getIndigenousLanguageTotal()); } @@ -140,6 +151,10 @@ public void setValueForGrade(HashMap nodeMap, Indige if (nodeMap.containsKey(schoolID + "Heading")) { nodeMap.get(schoolID + "Heading").setAllValuesToNull(); } + + int currentTotal = Integer.parseInt(gradeResult.getAllSupportProgramTotal()); + int accumulatedTotal = Integer.parseInt(allIndNode.getValueForGrade(code)); + allIndNode.setValueForGrade(code, String.valueOf(accumulatedTotal + currentTotal)); } } diff --git a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/SpecialEdHeadcountPerSchoolReportService.java b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/SpecialEdHeadcountPerSchoolReportService.java index 106667e97..8c3ac3ee2 100644 --- a/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/SpecialEdHeadcountPerSchoolReportService.java +++ b/api/src/main/java/ca/bc/gov/educ/studentdatacollection/api/reports/SpecialEdHeadcountPerSchoolReportService.java @@ -29,6 +29,7 @@ @Slf4j public class SpecialEdHeadcountPerSchoolReportService extends BaseReportGenerationService { + protected static final String ALLSPED = "allSped"; private final SdcDistrictCollectionRepository sdcDistrictCollectionRepository; private final SdcSchoolCollectionStudentRepository sdcSchoolCollectionStudentRepository; private JasperReport specialEdHeadcountPerSchoolReport; @@ -80,6 +81,7 @@ public DownloadableReportResponse generateSpecialEdHeadcountPerSchoolReport(UUID public HashMap generateNodeMap(boolean includeKH) { HashMap nodeMap = new HashMap<>(); Set includedSchoolIDs = new HashSet<>(); + addValuesForSectionToMap(nodeMap, ALLSPED, "All Inclusive Education Headcount for All Schools", "00"); int sequencePrefix = 10; if (!spedHeadcounts.isEmpty()) { @@ -107,13 +109,17 @@ public HashMap generateNodeMap(boolean includeKH) { return nodeMap; } - private void addValuesForSectionToMap(HashMap nodeMap, String sectionPrefix, String sectionTitle, String sequencePrefix){ - nodeMap.put(sectionPrefix + "Heading", new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false)); - nodeMap.put(sectionPrefix + "level1", new HeadcountChildNode("Level 1", FALSE, sequencePrefix + "1", false)); - nodeMap.put(sectionPrefix + "level2", new HeadcountChildNode("Level 2", FALSE, sequencePrefix + "2", false)); - nodeMap.put(sectionPrefix + "level3", new HeadcountChildNode("Level 3", FALSE, sequencePrefix + "3", false)); - nodeMap.put(sectionPrefix + "other", new HeadcountChildNode("Other", FALSE, sequencePrefix + "4", false)); - nodeMap.put(sectionPrefix + "all", new HeadcountChildNode("All Levels & Categories", FALSE, sequencePrefix + "5", false)); + private void addValuesForSectionToMap(HashMap nodeMap, String sectionPrefix, String sectionTitle, String sequencePrefix) { + if (Objects.equals(sectionPrefix, ALLSPED)) { + nodeMap.put(sectionPrefix, new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false, false, false, false)); + } else { + nodeMap.put(sectionPrefix + "Heading", new HeadcountChildNode(sectionTitle, "true", sequencePrefix + "0", false)); + nodeMap.put(sectionPrefix + "level1", new HeadcountChildNode("Level 1", FALSE, sequencePrefix + "1", false)); + nodeMap.put(sectionPrefix + "level2", new HeadcountChildNode("Level 2", FALSE, sequencePrefix + "2", false)); + nodeMap.put(sectionPrefix + "level3", new HeadcountChildNode("Level 3", FALSE, sequencePrefix + "3", false)); + nodeMap.put(sectionPrefix + "other", new HeadcountChildNode("Other", FALSE, sequencePrefix + "4", false)); + nodeMap.put(sectionPrefix + "all", new HeadcountChildNode("All Levels & Categories", FALSE, sequencePrefix + "5", false)); + } } public void setValueForGrade(HashMap nodeMap, SpecialEdHeadcountResult gradeResult) { @@ -122,6 +128,11 @@ public void setValueForGrade(HashMap nodeMap, Specia new EntityNotFoundException(SchoolGradeCodes.class, "Grade Value", gradeResult.getEnrolledGradeCode())); String schoolID = gradeResult.getSchoolID(); + HeadcountChildNode allSpedNode = nodeMap.get(ALLSPED); + if (allSpedNode.getValueForGrade(code) == null) { + allSpedNode.setValueForGrade(code, "0"); + } + if (nodeMap.containsKey(schoolID + "level1")) { nodeMap.get(schoolID + "level1").setValueForGrade(code, gradeResult.getLevelOnes()); } @@ -145,5 +156,9 @@ public void setValueForGrade(HashMap nodeMap, Specia if (nodeMap.containsKey(schoolID + "Heading")) { nodeMap.get(schoolID + "Heading").setAllValuesToNull(); } + + int currentTotal = Integer.parseInt(gradeResult.getAllLevels()); + int accumulatedTotal = Integer.parseInt(allSpedNode.getValueForGrade(code)); + allSpedNode.setValueForGrade(code, String.valueOf(accumulatedTotal + currentTotal)); } } From 09c2322229653cb077dd1bbd2f4311c5277bc3f0 Mon Sep 17 00:00:00 2001 From: alexmcdermid Date: Wed, 14 Aug 2024 11:43:18 -0700 Subject: [PATCH 4/5] tests --- .../v1/ReportGenerationControllerTest.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationControllerTest.java b/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationControllerTest.java index 2f52f9a66..bb2ef2772 100644 --- a/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationControllerTest.java +++ b/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/controller/v1/ReportGenerationControllerTest.java @@ -878,6 +878,140 @@ void testEligibleSpedHeadcountDistrictPerSchool_emptyDistrict_ShouldReturnOk() t .andDo(print()).andExpect(status().isOk()); } + @Test + void testIndHeadcountDistrictReport_ShouldReturnOk() throws Exception { + final GrantedAuthority grantedAuthority = () -> "SCOPE_READ_SDC_COLLECTION"; + final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); + + var districtMock = this.createMockDistrict(); + when(this.restUtils.getDistrictByDistrictID(anyString())).thenReturn(Optional.of(districtMock)); + var schoolMock = this.createMockSchool(); + when(this.restUtils.getSchoolBySchoolID(anyString())).thenReturn(Optional.of(schoolMock)); + var csfSchoolMock = this.createMockSchool(); + csfSchoolMock.setSchoolReportingRequirementCode(SchoolReportingRequirementCodes.CSF.getCode()); + when(this.restUtils.getSchoolBySchoolID(anyString())).thenReturn(Optional.of(csfSchoolMock)); + + CollectionEntity collection = createMockCollectionEntity(); + collection.setCloseDate(LocalDateTime.now().plusDays(2)); + collectionRepository.save(collection); + + SdcDistrictCollectionEntity sdcMockDistrict = createMockSdcDistrictCollectionEntity(collection, UUID.fromString(districtMock.getDistrictId())); + sdcMockDistrict = sdcDistricCollectionRepository.save(sdcMockDistrict); + + SdcSchoolCollectionEntity sdcMockSchool = createMockSdcSchoolCollectionEntity(collection, UUID.fromString(schoolMock.getSchoolId())); + sdcMockSchool.setUploadDate(null); + sdcMockSchool.setUploadFileName(null); + sdcMockSchool.setSdcDistrictCollectionID(sdcMockDistrict.getSdcDistrictCollectionID()); + sdcMockSchool = sdcSchoolCollectionRepository.save(sdcMockSchool); + + SdcSchoolCollectionEntity sdcCsfMockSchool = createMockSdcSchoolCollectionEntity(collection, UUID.fromString(csfSchoolMock.getSchoolId())); + sdcCsfMockSchool.setUploadDate(null); + sdcCsfMockSchool.setUploadFileName(null); + sdcCsfMockSchool.setSdcDistrictCollectionID(sdcMockDistrict.getSdcDistrictCollectionID()); + sdcCsfMockSchool = sdcSchoolCollectionRepository.save(sdcCsfMockSchool); + + SdcSchoolCollectionStudentEntity student1 = createMockSchoolStudentEntity(sdcMockSchool); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE09.getCode()); + sdcSchoolCollectionStudentRepository.save(student1); + + SdcSchoolCollectionStudentEntity student2 = createMockSchoolStudentEntity(sdcMockSchool); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE10.getCode()); + sdcSchoolCollectionStudentRepository.save(student2); + + SdcSchoolCollectionStudentEntity student3 = createMockSchoolStudentEntity(sdcMockSchool); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE11.getCode()); + sdcSchoolCollectionStudentRepository.save(student3); + + SdcSchoolCollectionStudentEntity student4 = createMockSchoolStudentEntity(sdcCsfMockSchool); + sdcSchoolCollectionStudentRepository.save(student4); + + student1.setNativeAncestryInd("Y"); + student2.setNativeAncestryInd("Y"); + student3.setNativeAncestryInd("Y"); + student4.setNativeAncestryInd("Y"); + + this.mockMvc.perform( + get(URL.BASE_URL_REPORT_GENERATION + "/" + sdcMockDistrict.getSdcDistrictCollectionID() + "/" + "DIS_INDIGENOUS_HEADCOUNT").with(mockAuthority)) + .andDo(print()).andExpect(status().isOk()); + } + + @Test + void testEligibleIndHeadcountDistrictPerSchool_ShouldReturnOk() throws Exception { + final GrantedAuthority grantedAuthority = () -> "SCOPE_READ_SDC_COLLECTION"; + final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); + + var districtMock = this.createMockDistrict(); + when(this.restUtils.getDistrictByDistrictID(anyString())).thenReturn(Optional.of(districtMock)); + var schoolMock = this.createMockSchool(); + when(this.restUtils.getSchoolBySchoolID(anyString())).thenReturn(Optional.of(schoolMock)); + var schoolMock2 = this.createMockSchool(); + when(this.restUtils.getSchoolBySchoolID(anyString())).thenReturn(Optional.of(schoolMock2)); + + CollectionEntity collection = createMockCollectionEntity(); + collection.setCloseDate(LocalDateTime.now().plusDays(2)); + collectionRepository.save(collection); + + SdcDistrictCollectionEntity sdcMockDistrict = createMockSdcDistrictCollectionEntity(collection, UUID.fromString(districtMock.getDistrictId())); + sdcMockDistrict = sdcDistricCollectionRepository.save(sdcMockDistrict); + + SdcSchoolCollectionEntity sdcMockSchool = createMockSdcSchoolCollectionEntity(collection, UUID.fromString(schoolMock.getSchoolId())); + sdcMockSchool.setUploadDate(null); + sdcMockSchool.setUploadFileName(null); + sdcMockSchool.setSdcDistrictCollectionID(sdcMockDistrict.getSdcDistrictCollectionID()); + sdcMockSchool = sdcSchoolCollectionRepository.save(sdcMockSchool); + + SdcSchoolCollectionEntity sdcMockSchool2 = createMockSdcSchoolCollectionEntity(collection, UUID.fromString(schoolMock2.getSchoolId())); + sdcMockSchool2.setUploadDate(null); + sdcMockSchool2.setUploadFileName(null); + sdcMockSchool2.setSdcDistrictCollectionID(sdcMockDistrict.getSdcDistrictCollectionID()); + sdcMockSchool2 = sdcSchoolCollectionRepository.save(sdcMockSchool2); + + SdcSchoolCollectionStudentEntity student1 = createMockSchoolStudentEntity(sdcMockSchool); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE09.getCode()); + sdcSchoolCollectionStudentRepository.save(student1); + + SdcSchoolCollectionStudentEntity student2 = createMockSchoolStudentEntity(sdcMockSchool); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE11.getCode()); + sdcSchoolCollectionStudentRepository.save(student2); + + SdcSchoolCollectionStudentEntity student3 = createMockSchoolStudentEntity(sdcMockSchool); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE10.getCode()); + sdcSchoolCollectionStudentRepository.save(student3); + + SdcSchoolCollectionStudentEntity student4 = createMockSchoolStudentEntity(sdcMockSchool2); + student1.setEnrolledGradeCode(SchoolGradeCodes.GRADE08.getCode()); + sdcSchoolCollectionStudentRepository.save(student4); + + student1.setNativeAncestryInd("Y"); + student2.setNativeAncestryInd("Y"); + student3.setNativeAncestryInd("Y"); + student4.setNativeAncestryInd("Y"); + + this.mockMvc.perform( + get(URL.BASE_URL_REPORT_GENERATION + "/" + sdcMockDistrict.getSdcDistrictCollectionID() + "/" + "DIS_INDIGENOUS_HEADCOUNT_PER_SCHOOL").with(mockAuthority)) + .andDo(print()).andExpect(status().isOk()); + } + + @Test + void testEligibleIndHeadcountDistrictPerSchool_emptyDistrict_ShouldReturnOk() throws Exception { + final GrantedAuthority grantedAuthority = () -> "SCOPE_READ_SDC_COLLECTION"; + final SecurityMockMvcRequestPostProcessors.OidcLoginRequestPostProcessor mockAuthority = oidcLogin().authorities(grantedAuthority); + + var districtMock = this.createMockDistrict(); + when(this.restUtils.getDistrictByDistrictID(anyString())).thenReturn(Optional.of(districtMock)); + + CollectionEntity collection = createMockCollectionEntity(); + collection.setCloseDate(LocalDateTime.now().plusDays(2)); + collectionRepository.save(collection); + + SdcDistrictCollectionEntity sdcMockDistrict = createMockSdcDistrictCollectionEntity(collection, UUID.fromString(districtMock.getDistrictId())); + sdcMockDistrict = sdcDistricCollectionRepository.save(sdcMockDistrict); + + this.mockMvc.perform( + get(URL.BASE_URL_REPORT_GENERATION + "/" + sdcMockDistrict.getSdcDistrictCollectionID() + "/" + "DIS_INDIGENOUS_HEADCOUNT_PER_SCHOOL").with(mockAuthority)) + .andDo(print()).andExpect(status().isOk()); + } + @Test void testRefugeePerSchool_ShouldReturnOk() throws Exception { final GrantedAuthority grantedAuthority = () -> "SCOPE_READ_SDC_COLLECTION"; From 0c9cd5608072713dd57efba1323f75adac72c1f0 Mon Sep 17 00:00:00 2001 From: alexmcdermid Date: Thu, 15 Aug 2024 09:35:48 -0700 Subject: [PATCH 5/5] fix ut --- .../studentdatacollection/api/rules/RulesProcessorTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/rules/RulesProcessorTest.java b/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/rules/RulesProcessorTest.java index ee70ea396..8053f14fd 100644 --- a/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/rules/RulesProcessorTest.java +++ b/api/src/test/java/ca/bc/gov/educ/studentdatacollection/api/rules/RulesProcessorTest.java @@ -897,8 +897,10 @@ void testNoOfCoursesRules() { @Test void testSchoolFundingGroupRule() { + val school = createMockSchool(); + school.setSchoolCategoryCode(SchoolCategoryCodes.INDEPEND.getCode()); var collection = collectionRepository.save(createMockCollectionEntity()); - var sdcSchoolCollectionEntity = sdcSchoolCollectionRepository.save(createMockSdcSchoolCollectionEntity(collection, null)); + var sdcSchoolCollectionEntity = sdcSchoolCollectionRepository.save(createMockSdcSchoolCollectionEntity(collection, UUID.fromString(school.getSchoolId()))); val entity = this.createMockSchoolStudentEntity(sdcSchoolCollectionEntity); entity.setNumberOfCourses("20"); @@ -906,7 +908,7 @@ void testSchoolFundingGroupRule() { PenMatchResult penMatchResult = getPenMatchResult(); when(this.restUtils.getPenMatchResult(any(),any(), anyString())).thenReturn(penMatchResult); - val validationErrorMax = rulesProcessor.processRules(createMockStudentRuleData(entity, createMockSchool())); + val validationErrorMax = rulesProcessor.processRules(createMockStudentRuleData(entity, school)); assertThat(validationErrorMax.size()).isNotZero(); val errorContEd = validationErrorMax.stream().anyMatch(val -> val.getValidationIssueCode().equals("INVALIDGRADESCHOOLFUNDINGGROUP")); assertThat(errorContEd).isTrue();