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

#2001 - Changes to handle PD PPD Part 1 #2115

Merged
merged 11 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,8 @@ export const DUPLICATE_SABC_CODE = "DUPLICATE_SABC_CODE";
* Institution location not valid.
*/
export const INSTITUTION_LOCATION_NOT_VALID = "INSTITUTION_LOCATION_NOT_VALID";

/**
* Request for disability not allowed.
*/
export const DISABILITY_REQUEST_NOT_ALLOWED = "DISABILITY_REQUEST_NOT_ALLOWED";
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ describe("ApplicationOfferingChangeRequestInstitutionsController(e2e)-getComplet

const searchKeyword = "TestStudent";
const endpoint = `/institutions/location/${collegeFLocation.id}/application-offering-change-request/completed?page=0&pageLimit=10&searchCriteria=${searchKeyword}`;
console.log(endpoint);
Copy link
Contributor

Choose a reason for hiding this comment

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

👍


// Act/Assert
await request(app.getHttpServer())
.get(endpoint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import {
UserToken,
} from "../../auth/decorators";
import { StudentUserToken } from "../../auth/userToken.interface";
import { ClientTypeBaseRoute } from "../../types";
import { ApiProcessError, ClientTypeBaseRoute } from "../../types";
import BaseController from "../BaseController";
import { ATBCIntegrationProcessingService } from "@sims/integrations/atbc-integration";
import { DisabilityStatus } from "@sims/sims-db";
import { DISABILITY_REQUEST_NOT_ALLOWED } from "../../constants";

@AllowAuthorizedParty(AuthorizedParties.student)
@RequiresStudentAccount()
Expand All @@ -29,40 +31,41 @@ export class ATBCStudentController extends BaseController {
}

/**
* Creates the request for ATBC PD evaluation.
* Student should only be allowed to check the PD status once and the
* Creates the request for ATBC disability evaluation.
* Student should only be allowed to check the disability status once and the
* SIN validation must be already done with a successful result.
*/
@Patch("apply-pd-status")
@Patch("apply-disability-status")
@ApiUnprocessableEntityResponse({
description:
"Either the client does not have a validated SIN or the request was already sent to ATBC.",
})
async applyForPDStatus(
async applyForDisabilityStatus(
@UserToken() studentUserToken: StudentUserToken,
): Promise<void> {
// Get student details
const student = await this.studentService.getStudentById(
studentUserToken.studentId,
);
// Check the PD status in DB. Student should only be allowed to check the PD status once.
// studentPDSentAt is set when student apply for PD status for the first.
// studentPDVerified is null before PD scheduled job update status.
// studentPDVerified is true if PD confirmed by ATBC or is true from sfas_individual table.
// studentPDVerified is false if PD denied by ATBC.
// To apply for a disability status, SIN validation must be completed for the student and
// not applied for disability status already.
if (
!student.sinValidation.isValidSIN ||
!!student.studentPDSentAt ||
student.studentPDVerified !== null
student.disabilityStatus !== DisabilityStatus.NotRequested
ann-aot marked this conversation as resolved.
Show resolved Hide resolved
) {
throw new UnprocessableEntityException(
"Either the client does not have a validated SIN or the request was already sent to ATBC.",
new ApiProcessError(
Copy link
Collaborator

Choose a reason for hiding this comment

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

❤️

"Either SIN validation is not complete or requested for disability status already.",
DISABILITY_REQUEST_NOT_ALLOWED,
),
);
}
// This is the only place in application where we call an external application
// in API instead of using queues. This is because once the student applies for PD,
// after a successful API call the apply for PD button needs to be disabled to avoid
// duplicate requests coming.
await this.atbcIntegrationProcessingService.applyForPDStatus(student.id);
await this.atbcIntegrationProcessingService.applyForDisabilityStatus(
student.id,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
saveFakeStudent,
} from "@sims/test-utils";
import { Application, Institution, InstitutionLocation } from "@sims/sims-db";
import { determinePDStatus, getUserFullName } from "../../../../utilities";
import { getUserFullName } from "../../../../utilities";
import { getISODateOnlyString } from "@sims/utilities";
import { saveStudentApplicationForCollegeC } from "./student.institutions.utils";

Expand Down Expand Up @@ -86,7 +86,7 @@ describe("StudentInstitutionsController(e2e)-getStudentProfile", () => {
},
phone: student.contactInfo.phone,
},
pdStatus: determinePDStatus(student),
disabilityStatus: student.disabilityStatus,
validSin: student.sinValidation.isValidSIN,
sin: student.sinValidation.sin,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
mockUserLoginInfo,
} from "../../../../testHelpers";
import { saveFakeStudent } from "@sims/test-utils";
import { determinePDStatus, getUserFullName } from "../../../../utilities";
import { getUserFullName } from "../../../../utilities";
import { TestingModule } from "@nestjs/testing";

describe("StudentInstitutionsController(e2e)-getStudentProfile", () => {
Expand Down Expand Up @@ -62,7 +62,7 @@ describe("StudentInstitutionsController(e2e)-getStudentProfile", () => {
},
phone: student.contactInfo.phone,
},
pdStatus: determinePDStatus(student),
disabilityStatus: student.disabilityStatus,
validSin: student.sinValidation.isValidSIN,
sin: student.sinValidation.sin,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import {
FileOriginType,
NOTE_DESCRIPTION_MAX_LENGTH,
FILE_NAME_MAX_LENGTH,
DisabilityStatus,
} from "@sims/sims-db";
import {
AddressAPIOutDTO,
AddressDetailsAPIInDTO,
} from "../../../route-controllers/models/common.dto";
import { StudentPDStatus } from "../../../types";

export class ContactInformationAPIOutDTO {
address: AddressAPIOutDTO;
Expand Down Expand Up @@ -180,7 +180,7 @@ export class StudentProfileAPIOutDTO {
dateOfBirth: string;
contact: ContactInformationAPIOutDTO;
validSin: boolean;
pdStatus: StudentPDStatus;
disabilityStatus: DisabilityStatus;
sin: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
ApplicationPaginationOptionsAPIInDTO,
PaginatedResultsAPIOutDTO,
} from "../models/pagination.dto";
import { determinePDStatus, getUserFullName } from "../../utilities";
import { getUserFullName } from "../../utilities";
import { getISODateOnlyString } from "@sims/utilities";
import { AddressInfo, Application, Student } from "@sims/sims-db";
import {
Expand Down Expand Up @@ -131,7 +131,7 @@ export class StudentControllerService {
address: transformAddressDetailsForAddressBlockForm(address),
phone: student.contactInfo.phone,
},
pdStatus: determinePDStatus(student),
disabilityStatus: student.disabilityStatus,
validSin: student.sinValidation.isValidSIN,
sin: student.sinValidation.sin,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe("Test ATBC Controller", () => {

// Act/Assert
await request(app.getHttpServer())
.patch("/students/atbc/apply-pd-status")
.patch("/students/atbc/apply-disability-status")
.auth(accessToken, BEARER_AUTH_TYPE)
.expect(HttpStatus.OK);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
DisbursementOverawardOriginType,
RestrictionNotificationType,
StudentRestriction,
DisabilityStatus,
} from "@sims/sims-db";
import { DataSource, EntityManager } from "typeorm";
import { StudentUserToken } from "../../auth/userToken.interface";
Expand Down Expand Up @@ -69,6 +70,7 @@ export class StudentService extends RecordDataModelService<Student> {
"student.studentPDVerified",
"student.studentPDSentAt",
"student.studentPDUpdateAt",
"student.disabilityStatus",
"sinValidation.id",
"sinValidation.sin",
"sinValidation.isValidSIN",
Expand Down Expand Up @@ -166,11 +168,19 @@ export class StudentService extends RecordDataModelService<Student> {
student.sinConsent = studentInfo.sinConsent;
try {
// Get PD status from SFAS integration data.
student.studentPDVerified = await this.sfasIndividualService.getPDStatus(
user.lastName,
student.birthDate,
studentSIN,
);
const sfasIndividual =
await this.sfasIndividualService.getIndividualStudent(
user.lastName,
student.birthDate,
studentSIN,
);
// If SFAS individual exist with matching details, read the pd status.
if (sfasIndividual) {
student.studentPDVerified = sfasIndividual.pdStatus;
student.disabilityStatus = this.getDisabilityStatus(
sfasIndividual.pdStatus,
);
}
} catch (error) {
this.logger.error("Unable to get SFAS information of student.");
this.logger.error(error);
Expand Down Expand Up @@ -667,4 +677,19 @@ export class StudentService extends RecordDataModelService<Student> {
entityManager,
);
}

/**
* Get student disability status.
* @param pdVerified sfas pdVerified flag.
* @returns disability status.
*/
private getDisabilityStatus(pdVerified: boolean): DisabilityStatus {
if (pdVerified) {
return DisabilityStatus.PD;
}
if (pdVerified === false) {
return DisabilityStatus.Declined;
ann-aot marked this conversation as resolved.
Show resolved Hide resolved
}
return DisabilityStatus.NotRequested;
}
}
1 change: 0 additions & 1 deletion sources/packages/backend/apps/api/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ export * from "./formsFlow";
export * from "./institutionAuth";
export * from "./optionItem";
export * from "./apiProcessError";
export * from "./pdStatus";
export * from "./clientTypeBaseRoute";
9 changes: 0 additions & 9 deletions sources/packages/backend/apps/api/src/types/pdStatus.ts

This file was deleted.

21 changes: 0 additions & 21 deletions sources/packages/backend/apps/api/src/utilities/student-utils.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
import { StudentPDStatus } from "../types/pdStatus";
import { Student } from "@sims/sims-db";

/**
* Determines the permanent disability status from Student Entity.
* @param student
* @returns PDStatus enum
*/
export const determinePDStatus = (student: Student): StudentPDStatus => {
if (student.studentPDVerified) {
return StudentPDStatus.Yes;
}
if (student.studentPDVerified === false) {
return StudentPDStatus.No;
}
if (student.studentPDSentAt) {
return StudentPDStatus.Pending;
}
return StudentPDStatus.NotRequested;
};

export const deliveryMethod = (
deliveredOnline: boolean,
deliveredOnSite: boolean,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MigrationInterface, QueryRunner } from "typeorm";
import { getSQLFileData } from "../utilities/sqlLoader";

export class AddStudentDisabilityStatusCol1689350242512
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
getSQLFileData("Create-disability-status.sql", "Types"),
);
await queryRunner.query(
getSQLFileData("Add-col-disability-status.sql", "Student"),
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
getSQLFileData("Drop-col-disability-status.sql", "Student"),
);
await queryRunner.query(
getSQLFileData("Drop-disability-status.sql", "Types"),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ALTER TABLE
sims.students
ADD
COLUMN IF NOT EXISTS disability_status sims.disability_status NOT NULL DEFAULT 'Not requested';

COMMENT ON COLUMN sims.students.disability_status IS 'Disability status of the student. The disability could be PD or PPD.';

-- Update the disability_status column based on pd_verified and pd_date_sent for existing data.
UPDATE
sims.students
SET
disability_status = CASE
WHEN pd_verified IS NULL
AND pd_date_sent IS NOT NULL THEN 'Requested'
WHEN pd_verified = true THEN 'PD'
WHEN pd_verified = false THEN 'Declined'
ann-aot marked this conversation as resolved.
Show resolved Hide resolved
ELSE 'Not requested' :: sims.disability_status
Copy link
Collaborator

Choose a reason for hiding this comment

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

I get this update is written for the existing data in Test, but is there a chance that any PDs can be PPDs? are we considering any update in the existing data update from ATBC?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There is no PPD in our system so far so we cannot do anything in the query about it.

If a student is PPD, ATBC response will be read and updated in our system.

END;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE
sims.students DROP COLUMN disability_status;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TYPE sims.disability_status AS ENUM (
'Not requested',
'Requested',
'PD',
'PPD',
'Declined'
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TYPE sims.disability_status;
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ export class ATBCIntegrationProcessingService {
) {}

/**
* Apply for PD status calling the ATBC endpoint.
* Apply for disability status calling the ATBC endpoint.
* @param studentId student who applied for PD status.
* @returns ATBC response.
*/
async applyForPDStatus(studentId: number): Promise<ATBCCreateClientResponse> {
async applyForDisabilityStatus(
studentId: number,
): Promise<ATBCCreateClientResponse> {
// Student who requested to apply PD status.
const student = await this.studentService.getStudentById(studentId);
const payload: ATBCCreateClientPayload = {
Expand All @@ -45,7 +47,10 @@ export class ATBCIntegrationProcessingService {
if (response) {
const auditUser = await this.systemUsersService.systemUser();
// Update PD sent date.
await this.studentService.updatePDSentDate(student.id, auditUser);
await this.studentService.updateDisabilityRequested(
student.id,
auditUser,
);
}
return response;
}
Expand Down
Loading