Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2303 - Total eligible amount in NOA screen #2365

Merged
merged 17 commits into from
Oct 5, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
AssessmentStatus,
Institution,
InstitutionLocation,
OfferingIntensity,
} from "@sims/sims-db";
import { getDateOnlyFormat } from "@sims/utilities";
import { MASKED_MSFAA_NUMBER } from "../../../../../src/services";
Expand Down Expand Up @@ -65,21 +66,158 @@ describe("AssessmentInstitutionsController(e2e)-getAssessmentNOA", () => {
},
);
await db.msfaaNumber.save(currentMSFAA);
const application = await saveFakeApplicationDisbursements(db.dataSource, {
institution: collegeF,
institutionLocation: collegeFLocation,
student,
msfaaNumber: currentMSFAA,
});
const application = await saveFakeApplicationDisbursements(
db.dataSource,
{
institution: collegeF,
institutionLocation: collegeFLocation,
student,
msfaaNumber: currentMSFAA,
},
{
offeringIntensity: OfferingIntensity.fullTime,
createSecondDisbursement: true,
},
);
const assessment = application.currentAssessment;
const [firstDisbursementSchedule] =
application.currentAssessment.disbursementSchedules;
const [firstDisbursementSchedule, secondDisbursementSchedule] =
assessment.disbursementSchedules;

const awards = {};
firstDisbursementSchedule.disbursementValues.forEach((disbursement) => {
awards[`disbursement1${disbursement.valueCode.toLowerCase()}`] =
disbursement.valueAmount;
});
const firstDisbursementScheduleAwards = {};
firstDisbursementSchedule.disbursementValues.forEach(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor. can use a common method to create disbursement schedule awards.

(firstDisbursement) => {
firstDisbursementScheduleAwards[
`disbursement1${firstDisbursement.valueCode.toLowerCase()}`
] = firstDisbursement.valueAmount;
},
);
const secondDisbursementScheduleAwards = {};
secondDisbursementSchedule.disbursementValues.forEach(
(secondDisbursement) => {
secondDisbursementScheduleAwards[
`disbursement2${secondDisbursement.valueCode.toLowerCase()}`
] = secondDisbursement.valueAmount;
},
);

const endpoint = `/institutions/assessment/student/${student.id}/application/${application.id}/assessment/${assessment.id}/noa`;
const institutionUserToken = await getInstitutionToken(
InstitutionTokenTypes.CollegeFUser,
);

// Act/Assert
await request(app.getHttpServer())
.get(endpoint)
.auth(institutionUserToken, BEARER_AUTH_TYPE)
.expect(HttpStatus.OK)
.expect({
applicationId: application.id,
applicationNumber: application.applicationNumber,
applicationStatus: application.applicationStatus,
assessment: assessment.assessmentData,
disbursement: {
disbursement1COEStatus: firstDisbursementSchedule.coeStatus,
disbursement1Date: getDateOnlyFormat(
firstDisbursementSchedule.disbursementDate,
),
disbursement1Id: firstDisbursementSchedule.id,
disbursement1MSFAACancelledDate:
firstDisbursementSchedule.msfaaNumber?.cancelledDate,
disbursement1MSFAADateSigned:
firstDisbursementSchedule.msfaaNumber?.dateSigned,
disbursement1MSFAAId: firstDisbursementSchedule.msfaaNumber?.id,
disbursement1MSFAANumber: MASKED_MSFAA_NUMBER,
disbursement1Status:
firstDisbursementSchedule.disbursementScheduleStatus,
disbursement1TuitionRemittance:
firstDisbursementSchedule.tuitionRemittanceRequestedAmount,
...firstDisbursementScheduleAwards,
disbursement2COEStatus: secondDisbursementSchedule.coeStatus,
disbursement2Date: getDateOnlyFormat(
secondDisbursementSchedule.disbursementDate,
),
disbursement2Id: secondDisbursementSchedule.id,
disbursement2MSFAACancelledDate:
secondDisbursementSchedule.msfaaNumber?.cancelledDate,
disbursement2MSFAADateSigned:
secondDisbursementSchedule.msfaaNumber?.dateSigned,
disbursement2MSFAAId: secondDisbursementSchedule.msfaaNumber?.id,
disbursement2MSFAANumber: MASKED_MSFAA_NUMBER,
disbursement2Status:
secondDisbursementSchedule.disbursementScheduleStatus,
disbursement2TuitionRemittance:
secondDisbursementSchedule.tuitionRemittanceRequestedAmount,
...secondDisbursementScheduleAwards,
},
eligibleAmount: assessment.disbursementSchedules.reduce(
(totalValueAmount, schedule) => {
return (
totalValueAmount +
(schedule.disbursementValues || []).reduce(
(sum, disbursementValue) => sum + disbursementValue.valueAmount,
0,
)
);
},
0,
),
fullName: getUserFullName(application.student.user),
locationName: assessment.offering.institutionLocation.name,
noaApprovalStatus: assessment.noaApprovalStatus,
offeringIntensity: assessment.offering.offeringIntensity,
offeringStudyEndDate: getDateOnlyFormat(
assessment.offering.studyEndDate,
),
offeringStudyStartDate: getDateOnlyFormat(
assessment.offering.studyStartDate,
),
programName: assessment.offering.educationProgram.name,
});
});

it("Should get the student noa details for an eligible partime application when an eligible public institution user tries to access it.", async () => {
// Arrange

// Student has an application to the institution eligible for NOA.
const student = await saveFakeStudent(db.dataSource);

const currentMSFAA = createFakeMSFAANumber(
{ student },
{
msfaaState: MSFAAStates.Signed,
},
);
await db.msfaaNumber.save(currentMSFAA);
const application = await saveFakeApplicationDisbursements(
db.dataSource,
{
institution: collegeF,
institutionLocation: collegeFLocation,
student,
msfaaNumber: currentMSFAA,
},
{ createSecondDisbursement: true },
);
const assessment = application.currentAssessment;
const [firstDisbursementSchedule, secondDisbursementSchedule] =
assessment.disbursementSchedules;

const firstDisbursementScheduleAwards = {};
firstDisbursementSchedule.disbursementValues.forEach(
(firstDisbursement) => {
firstDisbursementScheduleAwards[
`disbursement1${firstDisbursement.valueCode.toLowerCase()}`
] = firstDisbursement.valueAmount;
},
);
const secondDisbursementScheduleAwards = {};
secondDisbursementSchedule.disbursementValues.forEach(
(secondDisbursement) => {
secondDisbursementScheduleAwards[
`disbursement2${secondDisbursement.valueCode.toLowerCase()}`
] = secondDisbursement.valueAmount;
},
);

const endpoint = `/institutions/assessment/student/${student.id}/application/${application.id}/assessment/${assessment.id}/noa`;
const institutionUserToken = await getInstitutionToken(
Expand Down Expand Up @@ -112,8 +250,36 @@ describe("AssessmentInstitutionsController(e2e)-getAssessmentNOA", () => {
firstDisbursementSchedule.disbursementScheduleStatus,
disbursement1TuitionRemittance:
firstDisbursementSchedule.tuitionRemittanceRequestedAmount,
...awards,
...firstDisbursementScheduleAwards,
disbursement2COEStatus: secondDisbursementSchedule.coeStatus,
disbursement2Date: getDateOnlyFormat(
secondDisbursementSchedule.disbursementDate,
),
disbursement2Id: secondDisbursementSchedule.id,
disbursement2MSFAACancelledDate:
secondDisbursementSchedule.msfaaNumber?.cancelledDate,
disbursement2MSFAADateSigned:
secondDisbursementSchedule.msfaaNumber?.dateSigned,
disbursement2MSFAAId: secondDisbursementSchedule.msfaaNumber?.id,
disbursement2MSFAANumber: MASKED_MSFAA_NUMBER,
disbursement2Status:
secondDisbursementSchedule.disbursementScheduleStatus,
disbursement2TuitionRemittance:
secondDisbursementSchedule.tuitionRemittanceRequestedAmount,
...secondDisbursementScheduleAwards,
},
eligibleAmount: assessment.disbursementSchedules.reduce(
(totalValueAmount, schedule) => {
return (
totalValueAmount +
(schedule.disbursementValues || []).reduce(
(sum, disbursementValue) => sum + disbursementValue.valueAmount,
0,
Copy link
Collaborator

@sh16011993 sh16011993 Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it

)
);
},
0,
),
fullName: getUserFullName(application.student.user),
locationName: assessment.offering.institutionLocation.name,
noaApprovalStatus: assessment.noaApprovalStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ export class AssessmentControllerService {
assessment.offering.studyStartDate,
),
offeringStudyEndDate: getDateOnlyFormat(assessment.offering.studyEndDate),
eligibleAmount: this.sumDisbursementValueAmounts(
assessment.disbursementSchedules,
),
disbursement: this.populateDisbursementAwardValues(
assessment.disbursementSchedules,
{ maskMSFAA: options?.maskMSFAA },
Expand Down Expand Up @@ -152,6 +155,25 @@ export class AssessmentControllerService {
return disbursementDetails;
}

/**
* Calculate the sum of value amount for each disbursement value within the disbursement schedules.
* @param disbursementSchedules disbursement schedule details.
* @returns The total sum of value amount across all disbursement schedules.
*/
private sumDisbursementValueAmounts(
disbursementSchedules: DisbursementSchedule[],
): number {
return disbursementSchedules.reduce((totalValueAmount, schedule) => {
return (
totalValueAmount +
(schedule.disbursementValues || []).reduce(
(sum, disbursementValue) => sum + disbursementValue.valueAmount,
0,
)
);
}, 0);
}

/**
* Get estimated and actual(if present) award details of an assessment.
* @param assessmentId assessment to which awards details belong to.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class AssessmentNOAAPIOutDTO {
offeringIntensity: OfferingIntensity;
offeringStudyStartDate: string;
offeringStudyEndDate: string;
eligibleAmount: number;
disbursement: Record<string, string | number>;
noaApprovalStatus: AssessmentStatus;
applicationStatus: ApplicationStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export interface AssessmentNOAAPIOutDTO {
offeringStudyEndDate: string;
msfaaNumber: string;
disbursement: unknown;
eligibleAmount: number;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that following fields are used in NOA form.io but not saved by the workflow.

Are these fields not relevant to the part time application?

image

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes if you are talking about the form.io not saving the assessmentData by the PartTime application, yes there are fields that are used only for FullTime application.

Copy link
Collaborator

@dheepak-aot dheepak-aot Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question is, does part time noa require Living Allowance, Other allowable cost and Total Assessed Cost ? or they are disregarded part time NOA.

I am doubtful that they may be needed for PT noa as well. But I may be wrong.

But if they are needed, the value is never going to come for PT application unless I am missing something.

@JasonCTang @michesmith can you please confirm on the same?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have confirmed with @HRAGANBC regarding this and there will be a future ticket that needs displaying of several other fields in the NOA screen. Will connect the ticket with out ticket for continuation.

noaApprovalStatus: AssessmentStatus;
applicationStatus: ApplicationStatus;
}
Expand Down