Skip to content

Commit

Permalink
Merge pull request #1511 from bcgov/feature/programChangs
Browse files Browse the repository at this point in the history
Added program eligibility changes and fte calc
  • Loading branch information
SodhiA1 authored Jan 15, 2025
2 parents 7918ace + e189b91 commit 26930f3
Show file tree
Hide file tree
Showing 14 changed files with 109 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.NUM_COURSES;

@Component
@Slf4j
@Order(100)
Expand All @@ -32,7 +34,11 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
BigDecimal numCourses = StringUtils.isBlank(sdcSchoolStudent.getNumberOfCourses()) ? BigDecimal.ZERO : BigDecimal.valueOf(TransformUtil.parseNumberOfCourses(sdcSchoolStudent.getNumberOfCourses(), sdcSchoolStudent.getSdcSchoolCollectionStudentID()));
FteCalculationResult fteCalculationResult = new FteCalculationResult();
fteCalculationResult.setFte(numCourses.multiply(fteMultiplier).setScale(4, RoundingMode.HALF_UP).stripTrailingZeros());
fteCalculationResult.setFteZeroReason(null);
if (fteCalculationResult.getFte() != null && fteCalculationResult.getFte().compareTo(BigDecimal.ZERO) > 0) {
fteCalculationResult.setFteZeroReason(null);
}else{
fteCalculationResult.setFteZeroReason(NUM_COURSES.getCode());
}
log.debug("AdultStudentCalculator: Fte result {} calculated for student :: {}", fteCalculationResult.getFte(), studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return fteCalculationResult;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
return fteCalculationResult;
}

return fteCalculationResult;
log.debug("CollectionAndFacilityTypeCalculator: No FTE result, moving to next calculation for student :: " + studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return this.nextCalculator.calculateFte(studentData);
} else {
log.debug("CollectionAndFacilityTypeCalculator: No FTE result, moving to next calculation for student :: " + studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return this.nextCalculator.calculateFte(studentData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.NUM_COURSES;

@Component
@Slf4j
@Order(110)
Expand Down Expand Up @@ -45,7 +47,11 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
log.error(errorMessage);
throw new StudentDataCollectionAPIRuntimeException(errorMessage);
}
fteCalculationResult.setFteZeroReason(null);
if (fteCalculationResult.getFte() != null && fteCalculationResult.getFte().compareTo(BigDecimal.ZERO) > 0) {
fteCalculationResult.setFteZeroReason(null);
}else{
fteCalculationResult.setFteZeroReason(NUM_COURSES.getCode());
}
log.debug("CollectionAndGradeCalculator: Fte result {} calculated for student :: {}", fteCalculationResult.getFte(), studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return fteCalculationResult;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.DISTRICT_DUPLICATE_FUNDING;
import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.IND_AUTH_DUPLICATE_FUNDING;
import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.*;

@Component
@Slf4j
Expand Down Expand Up @@ -60,7 +59,11 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
log.debug("NewOnlineStudentCalculator: calculating for all other grades with student :: " + studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
fteCalculationResult.setFte(new BigDecimal("0.9529"));
}
fteCalculationResult.setFteZeroReason(null);
if (fteCalculationResult.getFte() != null && fteCalculationResult.getFte().compareTo(BigDecimal.ZERO) > 0) {
fteCalculationResult.setFteZeroReason(null);
}else{
fteCalculationResult.setFteZeroReason(NUM_COURSES.getCode());
}
log.debug("NewOnlineStudentCalculator: Fte result {} calculated for student :: {}", fteCalculationResult.getFte(), studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return fteCalculationResult;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.NUM_COURSES;

@Component
@Slf4j
@Order(140)
Expand Down Expand Up @@ -52,7 +54,11 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
log.error(errorMessage);
throw new StudentDataCollectionAPIRuntimeException(errorMessage);
}
fteCalculationResult.setFteZeroReason(null);
if (fteCalculationResult.getFte() != null && fteCalculationResult.getFte().compareTo(BigDecimal.ZERO) > 0) {
fteCalculationResult.setFteZeroReason(null);
}else{
fteCalculationResult.setFteZeroReason(NUM_COURSES.getCode());
}
log.debug("StudentGradeCalculator: Fte result {} calculated for student :: {}", fteCalculationResult.getFte(), studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return fteCalculationResult;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.NUM_COURSES;

@Component
@Slf4j
@Order(160)
Expand Down Expand Up @@ -41,7 +43,11 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
BigDecimal fte = (numCourses.add(numSupportBlocks).multiply(fteMultiplier)).setScale(4, RoundingMode.HALF_UP).stripTrailingZeros();
fteCalculationResult.setFte(fte.compareTo(BigDecimal.ONE) > 0 ? BigDecimal.ONE : fte);
}
fteCalculationResult.setFteZeroReason(null);
if (fteCalculationResult.getFte() != null && fteCalculationResult.getFte().compareTo(BigDecimal.ZERO) > 0) {
fteCalculationResult.setFteZeroReason(null);
}else{
fteCalculationResult.setFteZeroReason(NUM_COURSES.getCode());
}
log.debug("StudentGraduatedCalculator: Fte result {} calculated for student :: {}", fteCalculationResult.getFte(), studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return fteCalculationResult;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes.NUM_COURSES;

@Component
@Slf4j
@Order(150)
Expand All @@ -35,7 +37,11 @@ public FteCalculationResult calculateFte(StudentRuleData studentData) {
if(SchoolCategoryCodes.INDEPENDENTS.contains(studentData.getSchool().getSchoolCategoryCode())) {
fteCalculationResult.setFte(fteCalculationResult.getFte().compareTo(BigDecimal.ONE) > 0 ? BigDecimal.ONE : fteCalculationResult.getFte());
}
fteCalculationResult.setFteZeroReason(null);
if (fteCalculationResult.getFte() != null && fteCalculationResult.getFte().compareTo(BigDecimal.ZERO) > 0) {
fteCalculationResult.setFteZeroReason(null);
}else{
fteCalculationResult.setFteZeroReason(NUM_COURSES.getCode());
}
log.debug("SupportBlocksCalculator: Fte result {} calculated for student :: {}", fteCalculationResult.getFte(), studentData.getSdcSchoolCollectionStudentEntity().getSdcSchoolCollectionStudentID());
return fteCalculationResult;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,38 @@
import lombok.Getter;

public enum ProgramEligibilityIssueCode {
HOMESCHOOL("HOMESCHOOL", "Homeschool students are not eligible for program funding."),
OFFSHORE("OFFSHORE", "Offshore students are not eligible program funding."),
TOO_YOUNG("TOO_YOUNG", "Students that are \"too young\" are not eligible for program funding."),
OUT_OF_PROVINCE("OUTOFPROV", "Out of Province/International students are not eligible for program funding."),
INACTIVE_ADULT("INACTADULT", "Students who have not been reported as \"active\" in a new course in the last two years are not eligible for program funding."),
INACTIVE_SCHOOL_AGE("INACTMINOR", "Students who have not been reported as \"active\" in a new course in the last two years are not eligible for program funding."),
NOT_ENROLLED_FRENCH("NTENRFRENC", "The student is not enrolled in french programs."),
NOT_ENROLLED_CAREER("NTENRCAREE", "The student is not enrolled in career programs."),
ENROLLED_CAREER_INDY_SCHOOL("ENRCARINDY", "Students reported by Independent Schools are not eligible for Career Program funding."),
NOT_ENROLLED_INDIGENOUS("NTENRINDIG", "The student is not enrolled in indigenous programs."),
NOT_ENROLLED_SPECIAL_ED("NTENRSPED", "The student was not reported in any inclusive education programs."),
NON_ELIG_SPECIAL_EDUCATION("NELISPED", "Student must be school-aged or a non-graduated adult reported in a grade other than GA."),
FEB_ONLINE_WITH_HISTORICAL_FUNDING("FEBSPEDERR", "Student has already been funded in September collection."),
INDP_FIRST_NATION_SPED("FUND20SPED", "Students reported by Independent School with Funding code 20 are not eligible for Inclusive Education funding."),
INDIGENOUS_ADULT("ISADULTAGE", "Student must be school-aged and self-identify as having Indigenous Ancestry to be eligible for funding for Indigenous Support Programs."),
YEARS_IN_ELL("ELL5ORLESS", "Student must be school-aged and have been reported in ELL for 5 years or less."),
NOT_ENROLLED_ELL("NTENRELL", "The student is not enrolled in the ELL program."),
NO_INDIGENOUS_ANCESTRY("NOANCESTRY", "Student must be school-aged and self-identify as having Indigenous Ancestry to be eligible for funding for Indigenous Support Programs."),
ELL_INDY_SCHOOL("ELLINDYERR", "Students reported by Independent Schools are not eligible for English Language Learning funding."),
INDIGENOUS_INDY_SCHOOL("INDYERR", "Students reported by Independent Schools are not eligible for Indigenous Support Program funding.");
HOMESCHOOL("HOMESCHOOL", "Homeschool students are not eligible for program funding.", ProgramEligibilityTypeCode.BASE),
OFFSHORE("OFFSHORE", "Offshore students are not eligible program funding.", ProgramEligibilityTypeCode.BASE),
TOO_YOUNG("TOO_YOUNG", "Students that are \"too young\" are not eligible for program funding.", ProgramEligibilityTypeCode.BASE),
OUT_OF_PROVINCE("OUTOFPROV", "Out of Province/International students are not eligible for program funding.", ProgramEligibilityTypeCode.BASE),
INACTIVE_ADULT("INACTADULT", "Students who have not been reported as \"active\" in a new course in the last two years are not eligible for program funding.", ProgramEligibilityTypeCode.BASE),
INACTIVE_SCHOOL_AGE("INACTMINOR", "Students who have not been reported as \"active\" in a new course in the last two years are not eligible for program funding.", ProgramEligibilityTypeCode.BASE),
NOT_ENROLLED_FRENCH("NTENRFRENC", "The student is not enrolled in french programs.", ProgramEligibilityTypeCode.FRENCH),
NOT_ENROLLED_CAREER("NTENRCAREE", "The student is not enrolled in career programs.", ProgramEligibilityTypeCode.CAREER_PROGRAMS),
ENROLLED_CAREER_INDY_SCHOOL("ENRCARINDY", "Students reported by Independent Schools are not eligible for Career Program funding.", ProgramEligibilityTypeCode.CAREER_PROGRAMS),
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),
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),
NOT_ENROLLED_ELL("NTENRELL", "The student is not enrolled in the ELL program.", ProgramEligibilityTypeCode.ELL),
NO_INDIGENOUS_ANCESTRY("NOANCESTRY", "Student must be school-aged and self-identify as having Indigenous Ancestry to be eligible for funding for Indigenous Support Programs.", ProgramEligibilityTypeCode.IND_SUPPORT),
ELL_INDY_SCHOOL("ELLINDYERR", "Students reported by Independent Schools are not eligible for English Language Learning funding.", ProgramEligibilityTypeCode.ELL),
INDIGENOUS_INDY_SCHOOL("INDYERR", "Students reported by Independent Schools are not eligible for Indigenous Support Program funding.", ProgramEligibilityTypeCode.IND_SUPPORT);

@Getter
private final String code;

@Getter
private final String message;

ProgramEligibilityIssueCode(String code, String message) {
@Getter final ProgramEligibilityTypeCode programEligibilityTypeCode;

ProgramEligibilityIssueCode(String code, String message, ProgramEligibilityTypeCode programEligibilityTypeCode) {
this.code = code;
this.message = message;
this.programEligibilityTypeCode = programEligibilityTypeCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ca.bc.gov.educ.studentdatacollection.api.constants.v1;

import lombok.Getter;

public enum ProgramEligibilityTypeCode {
BASE("BASE"),
SPED("SPED"),
FRENCH("FRENCH"),
ELL("ELL"),
IND_SUPPORT("IND_SUPPORT"),
CAREER_PROGRAMS("CAREER_PROGRAMS");


@Getter
private final String code;

ProgramEligibilityTypeCode(String code) {
this.code = code;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public enum ZeroFteReasonCodes {
PRP_OR_YOUTH_SCHOOL("PRPYOUTH", "Student is funded outside of the funding allocation system."),
OUT_OF_PROVINCE("OUTOFPROV", "Out-of-Province/International Students are not eligible for funding."),
OFFSHORE("OFFSHORE", "Offshore students do not receive funding."),
NUM_COURSES("NUMCOURSE", "Student does not have any courses reported."),
INACTIVE("INACTIVE", "The student has not been reported as \"active\" in a new course in the last two years."),
NOMINAL_ROLL_ELIGIBLE("NOMROLL", "The student is Nominal Roll eligible and is federally funded."),
IND_AUTH_DUPLICATE_FUNDING("AUTHDUP", "The authority has already received funding for the student this year."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ca.bc.gov.educ.studentdatacollection.api.constants.TopicsEnum;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.CollectionTypeCodes;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.ProgramEligibilityIssueCode;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.ProgramEligibilityTypeCode;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.SdcSchoolStudentStatus;
import ca.bc.gov.educ.studentdatacollection.api.exception.EntityNotFoundException;
import ca.bc.gov.educ.studentdatacollection.api.helpers.SdcHelper;
Expand Down Expand Up @@ -44,9 +45,11 @@

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

import static ca.bc.gov.educ.studentdatacollection.api.constants.v1.ProgramEligibilityIssueCode.*;
import static ca.bc.gov.educ.studentdatacollection.api.util.TransformUtil.isCollectionInProvDupes;

@Service
Expand Down Expand Up @@ -349,30 +352,21 @@ public void updateProgramEligibilityColumns(List<ProgramEligibilityIssueCode> er
student.setCareerProgramNonEligReasonCode(reasonCode);
student.setSpecialEducationNonEligReasonCode(reasonCode);
} else {
student.setFrenchProgramNonEligReasonCode(getReasonCode(errors, Arrays.asList(NOT_ENROLLED_FRENCH)));
student.setEllNonEligReasonCode(getReasonCode(errors, Arrays.asList(NOT_ENROLLED_ELL, YEARS_IN_ELL, ELL_INDY_SCHOOL)));
student.setIndigenousSupportProgramNonEligReasonCode(getReasonCode(errors, Arrays.asList(NOT_ENROLLED_INDIGENOUS, INDIGENOUS_ADULT, NO_INDIGENOUS_ANCESTRY, INDIGENOUS_INDY_SCHOOL)));
student.setCareerProgramNonEligReasonCode(getReasonCode(errors, Arrays.asList(NOT_ENROLLED_CAREER, ENROLLED_CAREER_INDY_SCHOOL)));
student.setSpecialEducationNonEligReasonCode(getReasonCode(errors, Arrays.asList(NOT_ENROLLED_SPECIAL_ED, NON_ELIG_SPECIAL_EDUCATION)));
student.setFrenchProgramNonEligReasonCode(getReasonCode(errors, ProgramEligibilityTypeCode.FRENCH));
student.setEllNonEligReasonCode(getReasonCode(errors, ProgramEligibilityTypeCode.ELL));
student.setIndigenousSupportProgramNonEligReasonCode(getReasonCode(errors, ProgramEligibilityTypeCode.IND_SUPPORT));
student.setCareerProgramNonEligReasonCode(getReasonCode(errors, ProgramEligibilityTypeCode.CAREER_PROGRAMS));
student.setSpecialEducationNonEligReasonCode(getReasonCode(errors, ProgramEligibilityTypeCode.SPED));
}
}

private String getReasonCode(List<ProgramEligibilityIssueCode> errors, List<ProgramEligibilityIssueCode> codes){
var first = errors.stream().filter(codes::contains).findFirst();
private String getReasonCode(List<ProgramEligibilityIssueCode> errors, ProgramEligibilityTypeCode typeCode){
var first = errors.stream().filter(programEligibilityIssueCode -> programEligibilityIssueCode.getProgramEligibilityTypeCode().getCode().equalsIgnoreCase(typeCode.getCode())).findFirst();
return first.isPresent() ? first.get().getCode() : null;
}

public static final Optional<ProgramEligibilityIssueCode> getBaseProgramEligibilityFailure(List<ProgramEligibilityIssueCode> errors) {
List<ProgramEligibilityIssueCode> ineligibleCodes = Arrays.asList(
HOMESCHOOL,
OFFSHORE,
OUT_OF_PROVINCE,
INACTIVE_ADULT,
INACTIVE_SCHOOL_AGE,
TOO_YOUNG
);

return errors.stream().filter(ineligibleCodes::contains).findFirst();
public static Optional<ProgramEligibilityIssueCode> getBaseProgramEligibilityFailure(List<ProgramEligibilityIssueCode> errors) {
return errors.stream().filter(programEligibilityIssueCode -> programEligibilityIssueCode.getProgramEligibilityTypeCode().getCode().equalsIgnoreCase(ProgramEligibilityTypeCode.BASE.getCode())).findFirst();
}

public void updateFteColumns(FteCalculationResult fteCalculationResult, SdcSchoolCollectionStudentEntity studentEntity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ca.bc.gov.educ.studentdatacollection.api.calculator.FteCalculator;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.SchoolGradeCodes;
import ca.bc.gov.educ.studentdatacollection.api.constants.v1.ZeroFteReasonCodes;
import ca.bc.gov.educ.studentdatacollection.api.model.v1.SdcSchoolCollectionStudentEntity;
import ca.bc.gov.educ.studentdatacollection.api.struct.StudentRuleData;
import ca.bc.gov.educ.studentdatacollection.api.struct.v1.FteCalculationResult;
Expand Down Expand Up @@ -126,7 +127,7 @@ void testCalculateFte_NullNumCourses() {

// Then
assertEquals(BigDecimal.ZERO, result.getFte());
assertNull(result.getFteZeroReason());
assertEquals(ZeroFteReasonCodes.NUM_COURSES.getCode(), result.getFteZeroReason());
verify(nextCalculator, never()).calculateFte(any());
}
}
Expand Down
Loading

0 comments on commit 26930f3

Please sign in to comment.