Skip to content

Commit

Permalink
Merge pull request #1515 from bcgov/feature/v99
Browse files Browse the repository at this point in the history
Changes to support V99.
  • Loading branch information
SodhiA1 authored Jan 15, 2025
2 parents 26930f3 + 3d963db commit de83bc5
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package ca.bc.gov.educ.studentdatacollection.api.calculator;

import ca.bc.gov.educ.studentdatacollection.api.constants.v1.CollectionTypeCodes;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.FacilityTypeCodes;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.ProgramEligibilityIssueCode;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.ValidationRulesService;
import ca.bc.gov.educ.studentdatacollection.api.struct.StudentRuleData;
import ca.bc.gov.educ.studentdatacollection.api.struct.v1.FteCalculationResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

@Component
Expand All @@ -23,12 +28,23 @@ public FteCalculatorChainProcessor(final List<FteCalculator> fteCalculators, Val
public FteCalculationResult processFteCalculator(StudentRuleData studentRuleData) {
log.debug("Starting FTE calculation for student :: {} with data :: {}", studentRuleData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID(), studentRuleData);
validationRulesService.setupPENMatchAndEllAndGraduateValues(studentRuleData);
var student = studentRuleData.getSdcSchoolCollectionStudentEntity();
String collectionType = student.getSdcSchoolCollection().getCollectionEntity().getCollectionTypeCode();
String facilityType = studentRuleData.getSchool().getFacilityTypeCode();
var onlineFacilityCodes = Arrays.asList(FacilityTypeCodes.DISTONLINE.getCode(), FacilityTypeCodes.DIST_LEARN.getCode());
var historicalStudents = validationRulesService.getStudentInHistoricalCollectionWithInSameDistrict(studentRuleData, "1");

for (int i = 0; i < fteCalculators.size() - 1; i++) {
FteCalculator currentCalculator = fteCalculators.get(i);
FteCalculator nextCalculator = fteCalculators.get(i + 1);
currentCalculator.setNext(nextCalculator);
}
return fteCalculators.get(0).calculateFte(studentRuleData);
var fteResult = fteCalculators.get(0).calculateFte(studentRuleData);
if(student.getFte() != null && collectionType.equalsIgnoreCase(CollectionTypeCodes.FEBRUARY.getTypeCode()) && onlineFacilityCodes.contains(facilityType) &&
(historicalStudents.isEmpty() || historicalStudents.stream().anyMatch(stu -> stu.getFte().compareTo(BigDecimal.ZERO) == 0)) && student.getFte().compareTo(BigDecimal.ZERO) == 0) {
log.debug("ProgramEligibilityBaseRule - SpecialEducationProgramsRule: CollectionTypeCodes - {}, facilityType - {}, for sdcSchoolCollectionStudentID :: {}", collectionType, facilityType, studentRuleData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
studentRuleData.getSdcSchoolCollectionStudentEntity().setSpecialEducationNonEligReasonCode(ProgramEligibilityIssueCode.FEB_ONLINE_WITH_HISTORICAL_FUNDING.getCode());
}
return fteResult;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public enum StudentValidationIssueTypeCode {
REFUGEE_IN_PREV_COL("REFUGEEINPREVCOL", "School-aged students reported in the previous collection are not eligible for newcomer refugee funding.", FUNDING_WARNING),
REFUGEE_IS_ADULT("REFUGEEISADULT", "Adults are not eligible for February newcomer refugee funding.", FUNDING_WARNING),
SUMMER_PUBLIC_SCHOOL_GRADE_ERROR("SUMMERPUBLICSCHOOLGRADEERROR","8/9 cross enrolment students must be in grades 8 or 9", ERROR),
SUMMER_STUDENT_REPORTED_IN_DISTRICT_ERROR("SUMMERSTUDENTREPORTEDINDISTRICTERROR","The student has already been reported by the district during the current school year.", ERROR),
SUMMER_STUDENT_ALREADY_REPORTED_ERROR("SUMMERSTUDENTREPORTEDINDISTRICTERROR","The student has already been reported during the current school year.", ERROR),
SUMMER_STUDENT_REPORTED_NOT_IN_DISTRICT_ERROR("SUMMERSTUDENTREPORTEDNOTINDISTRICTERROR","Student was not reported in Grade 8 or 9 this school year and cannot be reported in 8/9 cross enrolment in this collection.", FUNDING_WARNING),
SUMMER_ADULT_STUDENT_ERROR("SUMMERADULTSTUDENTERROR","Adult students cannot be reported in 8/9 cross enrolment", ERROR),
SUMMER_FUNDING_CODE_ERROR("SUMMERFUNDINGCODEERROR","Out of Province/International students cannot be reported in Summer collection", ERROR),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum ProgramEligibilityIssueCode {
NOT_ENROLLED_INDIGENOUS("NTENRINDIG", "The student is not enrolled in indigenous programs.", ProgramEligibilityTypeCode.IND_SUPPORT),
NOT_ENROLLED_SPECIAL_ED("NTENRSPED", "The student was not reported in any inclusive education programs.", ProgramEligibilityTypeCode.SPED),
NON_ELIG_SPECIAL_EDUCATION("NELISPED", "Student must be school-aged or a non-graduated adult reported in a grade other than GA.", ProgramEligibilityTypeCode.SPED),
FEB_ONLINE_WITH_HISTORICAL_FUNDING("FEBSPEDERR", "Student has already been funded in September collection.", ProgramEligibilityTypeCode.SPED),
FEB_ONLINE_WITH_HISTORICAL_FUNDING("FEBSPEDERR", "Student has no new courses and is not continuing their educational program for this school year.", ProgramEligibilityTypeCode.SPED),
INDP_FIRST_NATION_SPED("FUND20SPED", "Students reported by Independent School with Funding code 20 are not eligible for Inclusive Education funding.", ProgramEligibilityTypeCode.SPED),
INDIGENOUS_ADULT("ISADULTAGE", "Student must be school-aged and self-identify as having Indigenous Ancestry to be eligible for funding for Indigenous Support Programs.", ProgramEligibilityTypeCode.IND_SUPPORT),
YEARS_IN_ELL("ELL5ORLESS", "Student must be school-aged and have been reported in ELL for 5 years or less.", ProgramEligibilityTypeCode.ELL),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -1126,6 +1127,23 @@ NOT IN (SELECT saga.sdcSchoolCollectionStudentID FROM SdcSagaEntity saga WHERE s
""")
List<SdcSchoolCollectionStudentEntity> findStudentInCurrentFiscalWithInSameDistrict(UUID districtID, List<UUID> assignedStudentIDs, String noOfCollections);

@Query(value="""
SELECT SSCS FROM SdcSchoolCollectionEntity SSC, CollectionEntity C, SdcSchoolCollectionStudentEntity SSCS, SdcDistrictCollectionEntity SDC
WHERE SDC.districtID = :districtID
AND C.collectionID = SDC.collectionEntity.collectionID
AND C.collectionID = SSC.collectionEntity.collectionID
AND SDC.sdcDistrictCollectionID = SSC.sdcDistrictCollectionID
AND SSC.sdcSchoolCollectionID = SSCS.sdcSchoolCollection.sdcSchoolCollectionID
AND SSCS.assignedStudentId in :assignedStudentIDs
AND C.collectionID != :collectionID
AND SSCS.fte > 0
AND SSCS.sdcSchoolCollectionStudentStatusCode != 'DELETED'
AND C.collectionID IN
(SELECT CE.collectionID FROM CollectionEntity CE WHERE CE.collectionStatusCode = 'COMPLETED' AND CE.snapshotDate < :snapshotDate ORDER BY CE.snapshotDate DESC LIMIT :noOfCollections)
""")
List<SdcSchoolCollectionStudentEntity> findStudentInCurrentFiscalWithInSameDistrict(UUID districtID, List<UUID> assignedStudentIDs, String noOfCollections, UUID collectionID, LocalDate snapshotDate);


@Query(value="""
SELECT SSCS FROM SdcSchoolCollectionEntity SSC, CollectionEntity C, SdcSchoolCollectionStudentEntity SSCS
WHERE C.collectionID = SSC.collectionEntity.collectionID
Expand Down Expand Up @@ -1163,6 +1181,17 @@ AND SSCS.enrolledGradeCode NOT IN ('08', '09')
""")
List<SdcSchoolCollectionStudentEntity> findStudentInCurrentFiscalInOtherDistrictsNotInGrade8Or9WithNonZeroFte(UUID districtID, List<UUID> assignedStudentIDs, String noOfCollections);

@Query(value="""
SELECT SSCS FROM SdcSchoolCollectionEntity SSC, CollectionEntity C, SdcSchoolCollectionStudentEntity SSCS
WHERE C.collectionID = SSC.collectionEntity.collectionID
AND SSC.sdcSchoolCollectionID = SSCS.sdcSchoolCollection.sdcSchoolCollectionID
AND SSCS.assignedStudentId in :assignedStudentIDs
AND SSCS.enrolledGradeCode IN ('08', '09')
AND C.collectionID IN
(SELECT CE.collectionID FROM CollectionEntity CE WHERE CE.collectionStatusCode = 'COMPLETED' ORDER BY CE.snapshotDate DESC LIMIT :noOfCollections)
""")
List<SdcSchoolCollectionStudentEntity> findStudentInCurrentFiscalInGrade8Or9(List<UUID> assignedStudentIDs, String noOfCollections);

List<SdcSchoolCollectionStudentEntity> findAllBySdcSchoolCollection_CollectionEntity_CollectionIDAndEnrolledGradeCodeIn(UUID collectionID, List<String> enrolledGradeCode);

@Query("SELECT " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ public List<ProgramEligibilityIssueCode> executeValidation(StudentRuleData stude
&& SchoolFundingCodes.STATUS_FIRST_NATION.getCode().equals(student.getSchoolFundingCode())) {
log.debug("ProgramEligibilityBaseRule - SpecialEducationProgramsRule: SchoolCategoryCode - {}, SchoolFundingCode - {}, for sdcSchoolCollectionStudentID :: {}", studentRuleData.getSchool().getSchoolCategoryCode(), student.getSchoolFundingCode(), studentRuleData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
errors.add(ProgramEligibilityIssueCode.INDP_FIRST_NATION_SPED);
} else if(collectionType.equalsIgnoreCase(CollectionTypeCodes.FEBRUARY.getTypeCode()) && onlineFacilityCodes.contains(facilityType) &&
historicalStudents.stream().anyMatch(stu -> stu.getFte().compareTo(BigDecimal.ZERO) > 0 && stu.getSpecialEducationNonEligReasonCode() == null)) {
} else if(student.getFte() != null && collectionType.equalsIgnoreCase(CollectionTypeCodes.FEBRUARY.getTypeCode()) && onlineFacilityCodes.contains(facilityType) &&
(historicalStudents.isEmpty() || historicalStudents.stream().anyMatch(stu -> stu.getFte().compareTo(BigDecimal.ZERO) == 0)) && student.getFte().compareTo(BigDecimal.ZERO) == 0) {
log.debug("ProgramEligibilityBaseRule - SpecialEducationProgramsRule: CollectionTypeCodes - {}, facilityType - {}, for sdcSchoolCollectionStudentID :: {}", collectionType, facilityType, studentRuleData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
errors.add(ProgramEligibilityIssueCode.FEB_ONLINE_WITH_HISTORICAL_FUNDING);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public List<SdcSchoolCollectionStudentValidationIssue> executeValidation(Student
if (school.isPresent() && FacilityTypeCodes.getOnlineFacilityTypeCodes().contains(school.get().getFacilityTypeCode())) {
BigDecimal fte = studentEntity.getFte();

if (fte != null && fte.compareTo(BigDecimal.ZERO) >= 0) {
if (fte != null && fte.compareTo(BigDecimal.ZERO) > 0) {
isOnlineRegistered = true;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public List<SdcSchoolCollectionStudentValidationIssue> executeValidation(Student
if (school.isPresent()) {
boolean isOnlineSchool = FacilityTypeCodes.getOnlineFacilityTypeCodes().contains(school.get().getFacilityTypeCode());
if (!isOnlineSchool || SchoolGradeCodes.getKToNineGrades().contains(studentEntity.getEnrolledGradeCode())) {
errors.add(createValidationIssue(StudentValidationIssueSeverityCode.FUNDING_WARNING, StudentValidationFieldCode.ENROLLED_GRADE_CODE, StudentValidationIssueTypeCode.SUMMER_STUDENT_REPORTED_IN_DISTRICT_ERROR));
errors.add(createValidationIssue(StudentValidationIssueSeverityCode.FUNDING_WARNING, StudentValidationFieldCode.ENROLLED_GRADE_CODE, StudentValidationIssueTypeCode.SUMMER_STUDENT_ALREADY_REPORTED_ERROR));
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public List<SdcSchoolCollectionStudentValidationIssue> executeValidation(Student

validationRulesService.setupPENMatchAndEllAndGraduateValues(studentRuleData);
if(studentRuleData.getSdcSchoolCollectionStudentEntity().getAssignedStudentId() != null) {
var isStudentReportedInCurrentFiscal = validationRulesService.findStudentInCurrentFiscalInOtherDistrictsNotInGrade8Or9WithNonZeroFte(studentRuleData);
var isStudentReportedInCurrentFiscal = validationRulesService.studentExistsInCurrentFiscalInGrade8Or9(studentRuleData);

if (isStudentReportedInCurrentFiscal) {
if (!isStudentReportedInCurrentFiscal) {
errors.add(createValidationIssue(StudentValidationIssueSeverityCode.FUNDING_WARNING, StudentValidationFieldCode.ENROLLED_GRADE_CODE, StudentValidationIssueTypeCode.SUMMER_STUDENT_REPORTED_NOT_IN_DISTRICT_ERROR));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,10 @@ public void setGraduationStatus(SdcSchoolCollectionStudentEntity student){
}
}

public List<SdcSchoolCollectionStudentEntity> getStudentInHistoricalCollectionWithInSameDistrict(StudentRuleData studentRuleData,String noOfCollectionsForLookup) {
public List<SdcSchoolCollectionStudentEntity> getStudentInHistoricalCollectionWithInSameDistrict(StudentRuleData studentRuleData, String noOfCollectionsForLookup) {
setupMergedStudentIdValues(studentRuleData);
return sdcSchoolStudentRepository.findStudentInCurrentFiscalWithInSameDistrict(UUID.fromString(studentRuleData.getSchool().getDistrictId()), studentRuleData.getHistoricStudentIds(), noOfCollectionsForLookup);
var collection = studentRuleData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollection().getCollectionEntity();
return sdcSchoolStudentRepository.findStudentInCurrentFiscalWithInSameDistrict(UUID.fromString(studentRuleData.getSchool().getDistrictId()), studentRuleData.getHistoricStudentIds(), noOfCollectionsForLookup, collection.getCollectionID(), collection.getSnapshotDate());
}

public List<SdcSchoolCollectionStudentEntity> getStudentInHistoricalCollectionInAllDistrict(StudentRuleData studentRuleData) {
Expand All @@ -192,10 +193,10 @@ public List<SdcSchoolCollectionStudentEntity> getStudentInHistoricalCollectionIn
return sdcSchoolStudentRepository.findStudentInCurrentFiscalInAllDistrict(studentRuleData.getHistoricStudentIds(), noOfCollectionsForLookup);
}

public boolean findStudentInCurrentFiscalInOtherDistrictsNotInGrade8Or9WithNonZeroFte(StudentRuleData studentRuleData) {
public boolean studentExistsInCurrentFiscalInGrade8Or9(StudentRuleData studentRuleData) {
setupMergedStudentIdValues(studentRuleData);
String noOfCollectionsForLookup = "3";
List<SdcSchoolCollectionStudentEntity> entity = sdcSchoolStudentRepository.findStudentInCurrentFiscalInOtherDistrictsNotInGrade8Or9WithNonZeroFte(UUID.fromString(studentRuleData.getSchool().getDistrictId()), studentRuleData.getHistoricStudentIds(), noOfCollectionsForLookup);
List<SdcSchoolCollectionStudentEntity> entity = sdcSchoolStudentRepository.findStudentInCurrentFiscalInGrade8Or9(studentRuleData.getHistoricStudentIds(), noOfCollectionsForLookup);
return !entity.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ public void setUp() throws IOException {
Objects.requireNonNull(getClass().getClassLoader().getResource("sdc-student-saga-data.json")).getFile()
);
studentData = new ObjectMapper().readValue(file, StudentRuleData.class);
CollectionEntity collection = new CollectionEntity();
collection.setCollectionID(UUID.randomUUID());
collection.setCollectionTypeCode(CollectionTypeCodes.SEPTEMBER.getTypeCode());
collection.setSnapshotDate(LocalDate.now());
SdcSchoolCollectionEntity sdcSchoolCollection = new SdcSchoolCollectionEntity();
sdcSchoolCollection.setCollectionEntity(collection);
studentData.getSdcSchoolCollectionStudentEntity().setSdcSchoolCollection(sdcSchoolCollection);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ca.bc.gov.educ.studentdatacollection.api.calculator;

import ca.bc.gov.educ.studentdatacollection.api.model.v1.CollectionEntity;
import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcSchoolCollectionEntity;
import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcSchoolCollectionStudentEntity;
import ca.bc.gov.educ.studentdatacollection.api.service.v1.ValidationRulesService;
import ca.bc.gov.educ.studentdatacollection.api.struct.StudentRuleData;
Expand All @@ -10,8 +12,10 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static org.mockito.Mockito.*;

Expand All @@ -33,7 +37,13 @@ void setUp() {
@Test
void testProcessFteCalculator_WhenIsGraduatedIsNull_ThenGradStatusCalculated() {
// Given
CollectionEntity collection = new CollectionEntity();
collection.setCollectionID(UUID.randomUUID());
collection.setSnapshotDate(LocalDate.now());
SdcSchoolCollectionEntity sdcSchoolCollection = new SdcSchoolCollectionEntity();
sdcSchoolCollection.setCollectionEntity(collection);
SdcSchoolCollectionStudentEntity studentEntity = new SdcSchoolCollectionStudentEntity();
studentEntity.setSdcSchoolCollection(sdcSchoolCollection);
studentEntity.setIsGraduated(null);
StudentRuleData studentRuleData = new StudentRuleData();
studentRuleData.setSdcSchoolCollectionStudentEntity(studentEntity);
Expand Down
Loading

0 comments on commit de83bc5

Please sign in to comment.