From 49dca2dc33fddf7baaf926d5c6e0b41516aa6b6e Mon Sep 17 00:00:00 2001 From: Ann Date: Thu, 4 May 2023 19:51:38 -0400 Subject: [PATCH 01/12] initial commit --- .../apps/api/src/app.institutions.module.ts | 12 ++ .../assessment/assessment.aest.controller.ts | 42 +----- .../assessment.controller.service.ts | 57 ++++++++ .../assessment.institutions.controller.ts | 119 +++++++++++++++ .../apps/api/src/route-controllers/index.ts | 1 + .../application-exception.service.ts | 7 + .../education-program-offering.service.ts | 14 +- .../aest/students/assessment/Request.vue | 13 +- .../src/constants/routes/RouteConstants.ts | 1 + sources/packages/web/src/router/AESTRoutes.ts | 2 +- .../web/src/router/InstitutionRoutes.ts | 20 ++- .../src/services/StudentAssessmentsService.ts | 9 +- .../src/services/http/StudentAssessmentApi.ts | 10 +- sources/packages/web/src/types/AppRoutes.ts | 15 +- .../web/src/views/aest/AssessmentsSummary.vue | 4 +- .../InstitutionStudentApplications.vue | 19 +++ .../InstitutionAssessmentsSummary.vue | 135 ++++++++++++++++++ 17 files changed, 418 insertions(+), 62 deletions(-) create mode 100644 sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts create mode 100644 sources/packages/web/src/views/institution/student/applicationDetails/InstitutionAssessmentsSummary.vue diff --git a/sources/packages/backend/apps/api/src/app.institutions.module.ts b/sources/packages/backend/apps/api/src/app.institutions.module.ts index c85a45927d..26a4809f68 100644 --- a/sources/packages/backend/apps/api/src/app.institutions.module.ts +++ b/sources/packages/backend/apps/api/src/app.institutions.module.ts @@ -23,6 +23,10 @@ import { StudentService, EducationProgramOfferingImportCSVService, EducationProgramOfferingValidationService, + DisbursementReceiptService, + StudentAppealService, + ApplicationExceptionService, + StudentAppealRequestsService, } from "./services"; import { DesignationAgreementInstitutionsController, @@ -44,6 +48,8 @@ import { ConfirmationOfEnrollmentControllerService, StudentInstitutionsController, StudentControllerService, + AssessmentInstitutionsController, + AssessmentControllerService, } from "./route-controllers"; import { AuthModule } from "./auth/auth.module"; import { @@ -77,6 +83,7 @@ import { UserControllerService } from "./route-controllers/user/user.controller. EducationProgramOfferingInstitutionsController, UserInstitutionsController, StudentInstitutionsController, + AssessmentInstitutionsController, ], providers: [ WorkflowClientService, @@ -123,6 +130,11 @@ import { UserControllerService } from "./route-controllers/user/user.controller. NoteSharedService, StudentControllerService, RestrictionSharedService, + AssessmentControllerService, + DisbursementReceiptService, + StudentAppealService, + ApplicationExceptionService, + StudentAppealRequestsService, ], }) export class AppInstitutionsModule {} diff --git a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.aest.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.aest.controller.ts index 9b1f5247dc..e85abaf01c 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.aest.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.aest.controller.ts @@ -39,50 +39,16 @@ export class AssessmentAESTController extends BaseController { /** * Get all pending and declined requests related to an application which would result * a new assessment when that request is approved. - * @param applicationId application number. + * @param applicationId application id. * @returns assessment requests or exceptions for a student application. */ @Get("application/:applicationId/requests") async getRequestedAssessmentSummary( @Param("applicationId", ParseIntPipe) applicationId: number, ): Promise { - const requestAssessmentSummary: RequestAssessmentSummaryAPIOutDTO[] = []; - const offeringChange = - await this.educationProgramOfferingService.getOfferingRequestsByApplicationId( - applicationId, - ); - if (offeringChange) { - requestAssessmentSummary.push({ - id: offeringChange.id, - submittedDate: offeringChange.submittedDate, - status: offeringChange.offeringStatus, - requestType: RequestAssessmentTypeAPIOutDTO.OfferingRequest, - programId: offeringChange.educationProgram.id, - }); - } - const applicationExceptions = - await this.applicationExceptionService.getExceptionsByApplicationId( - applicationId, - ApplicationExceptionStatus.Pending, - ApplicationExceptionStatus.Declined, - ); - // When a pending or denied application exception exist then no other request can exist - // for the given application. - if (applicationExceptions.length > 0) { - const applicationExceptionArray: RequestAssessmentSummaryAPIOutDTO[] = - applicationExceptions.map((applicationException) => ({ - id: applicationException.id, - submittedDate: applicationException.createdAt, - status: applicationException.exceptionStatus, - requestType: RequestAssessmentTypeAPIOutDTO.StudentException, - })); - return requestAssessmentSummary.concat(applicationExceptionArray); - } - const appeals = - await this.assessmentControllerService.getPendingAndDeniedAppeals( - applicationId, - ); - return requestAssessmentSummary.concat(appeals); + return this.assessmentControllerService.requestedStudentAssessmentSummary( + applicationId, + ); } /** diff --git a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts index aa7f6163ca..fbc7d3b0fd 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts @@ -3,6 +3,7 @@ import { COEStatus, DisbursementReceipt, AssessmentTriggerType, + ApplicationExceptionStatus, } from "@sims/sims-db"; import { Injectable, @@ -14,6 +15,8 @@ import { DisbursementReceiptService, StudentAppealService, StudentScholasticStandingsService, + EducationProgramOfferingService, + ApplicationExceptionService, } from "../../services"; import { AssessmentNOAAPIOutDTO, @@ -33,6 +36,8 @@ export class AssessmentControllerService { private readonly disbursementReceiptService: DisbursementReceiptService, private readonly studentAppealService: StudentAppealService, private readonly studentScholasticStandingsService: StudentScholasticStandingsService, + private readonly educationProgramOfferingService: EducationProgramOfferingService, + private readonly applicationExceptionService: ApplicationExceptionService, ) {} /** @@ -282,4 +287,56 @@ export class AssessmentControllerService { return history; } + + /** + * Get all pending and declined requests related to an application which would result + * a new assessment when that request is approved. + * @param applicationId application id. + * @param studentId student id. + * @returns assessment requests or exceptions for the student application. + */ + async requestedStudentAssessmentSummary( + applicationId: number, + studentId?: number, + ): Promise { + const requestAssessmentSummary: RequestAssessmentSummaryAPIOutDTO[] = []; + const offeringChange = + await this.educationProgramOfferingService.getOfferingRequestsByApplicationId( + applicationId, + studentId, + ); + if (offeringChange) { + requestAssessmentSummary.push({ + id: offeringChange.id, + submittedDate: offeringChange.submittedDate, + status: offeringChange.offeringStatus, + requestType: RequestAssessmentTypeAPIOutDTO.OfferingRequest, + programId: offeringChange.educationProgram.id, + }); + } + const applicationExceptions = + await this.applicationExceptionService.getExceptionsByApplicationId( + applicationId, + studentId, + ApplicationExceptionStatus.Pending, + ApplicationExceptionStatus.Declined, + ); + // When a pending or denied application exception exist then no other request can exist + // for the given application. + if (applicationExceptions.length > 0) { + const applicationExceptionArray: RequestAssessmentSummaryAPIOutDTO[] = + applicationExceptions.map((applicationException) => ({ + id: applicationException.id, + submittedDate: applicationException.createdAt, + status: applicationException.exceptionStatus, + requestType: RequestAssessmentTypeAPIOutDTO.StudentException, + })); + return requestAssessmentSummary.concat(applicationExceptionArray); + } + const appeals = await this.getPendingAndDeniedAppeals( + applicationId, + studentId, + ); + return requestAssessmentSummary.concat(appeals); + } } diff --git a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts new file mode 100644 index 0000000000..dc31387798 --- /dev/null +++ b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts @@ -0,0 +1,119 @@ +import { Controller, Get, Param, ParseIntPipe } from "@nestjs/common"; +import BaseController from "../BaseController"; +import { + AllowAuthorizedParty, + Groups, + HasStudentDataAccess, + IsBCPublicInstitution, +} from "../../auth/decorators"; +import { AuthorizedParties } from "../../auth/authorized-parties.enum"; +import { ClientTypeBaseRoute } from "../../types"; +import { UserGroups } from "../../auth/user-groups.enum"; +import { + AssessmentHistorySummaryAPIOutDTO, + AssessmentNOAAPIOutDTO, + RequestAssessmentSummaryAPIOutDTO, + AwardDetailsAPIOutDTO, + RequestAssessmentTypeAPIOutDTO, +} from "./models/assessment.dto"; +import { + ApiNotFoundResponse, + ApiTags, + ApiUnprocessableEntityResponse, +} from "@nestjs/swagger"; +import { AssessmentControllerService } from "./assessment.controller.service"; +import { + EducationProgramOfferingService, + ApplicationExceptionService, +} from "../../services"; +import { ApplicationExceptionStatus } from "@sims/sims-db"; + +/** + * Assessment controller for institutions. + */ +@AllowAuthorizedParty(AuthorizedParties.institution) +@Controller("assessment") +@ApiTags(`${ClientTypeBaseRoute.Institution}-assessment`) +export class AssessmentInstitutionsController extends BaseController { + constructor( + private readonly assessmentControllerService: AssessmentControllerService, + ) // private readonly educationProgramOfferingService: EducationProgramOfferingService, + // private readonly applicationExceptionService: ApplicationExceptionService, + { + super(); + } + + /** + * Get all pending and declined requests related to an application which would result + * a new assessment when that request is approved. + * @param studentId student id. + * @param applicationId application id. + * @returns assessment requests or exceptions for the student application. + */ + // @IsBCPublicInstitution() + // @HasStudentDataAccess("studentId") + @Get("/student/:studentId/application/:applicationId/requests") + async getRequestedAssessmentSummary( + @Param("studentId", ParseIntPipe) studentId: number, + @Param("applicationId", ParseIntPipe) applicationId: number, + ): Promise { + return this.assessmentControllerService.requestedStudentAssessmentSummary( + applicationId, + studentId, + ); + } + + // /** + // * Method to get history of assessments for an application, + // * i.e, this will have original assessment for the + // * student application, and all approved student + // * appeal and scholastic standings for the application + // * which will have different assessment status. + // * @param applicationId, application number. + // * @returns summary of the assessment history for a student application. + // */ + // @Get("application/:applicationId/history") + // async getAssessmentHistorySummary( + // @Param("applicationId", ParseIntPipe) applicationId: number, + // ): Promise { + // return this.assessmentControllerService.getAssessmentHistorySummary( + // applicationId, + // ); + // } + + // /** + // * Get the NOA values for a student application on a particular assessment. + // * @param assessmentId assessment id to get the NOA values. + // * @returns NOA and application data. + // */ + // @Get(":assessmentId/noa") + // @ApiNotFoundResponse({ + // description: "Assessment id not found.", + // }) + // @ApiUnprocessableEntityResponse({ + // description: "Notice of assessment data is not present.", + // }) + // async getAssessmentNOA( + // @Param("assessmentId", ParseIntPipe) assessmentId: number, + // ): Promise { + // return this.assessmentControllerService.getAssessmentNOA(assessmentId); + // } + + // /** + // * Get estimated and actual(if present) award details of an assessment. + // * @param assessmentId assessment to which awards details belong to. + // * @returns estimated and actual award details. + // */ + // @Get(":assessmentId/award") + // @ApiNotFoundResponse({ + // description: "Assessment not found.", + // }) + // async getAssessmentAwardDetails( + // @Param("assessmentId", ParseIntPipe) assessmentId: number, + // ): Promise { + // return this.assessmentControllerService.getAssessmentAwardDetails( + // assessmentId, + // true, + // ); + // } +} diff --git a/sources/packages/backend/apps/api/src/route-controllers/index.ts b/sources/packages/backend/apps/api/src/route-controllers/index.ts index 0284c81e90..de298042d9 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/index.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/index.ts @@ -57,3 +57,4 @@ export * from "./overaward/overaward.controller.service"; export * from "./overaward/overaward.aest.controller"; export * from "./overaward/overaward.students.controller"; export * from "./student/student.institutions.controller"; +export * from "./assessment/assessment.institutions.controller"; diff --git a/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts b/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts index 9b0adb3801..d1801192aa 100644 --- a/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts +++ b/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts @@ -66,10 +66,12 @@ export class ApplicationExceptionService extends RecordDataModelService { const query = this.repo @@ -84,6 +86,11 @@ export class ApplicationExceptionService extends RecordDataModelService { - return this.repo + const offeringRequest = this.repo .createQueryBuilder("offering") .select([ "offering.id", @@ -1228,8 +1230,14 @@ export class EducationProgramOfferingService extends RecordDataModelService - - + - + = [ }, children: [ { - path: AppRoutes.AESTStudentProfile, + path: AppRoutes.StudentProfile, name: AESTRoutesConst.STUDENT_PROFILE, props: true, component: StudentProfile, diff --git a/sources/packages/web/src/router/InstitutionRoutes.ts b/sources/packages/web/src/router/InstitutionRoutes.ts index 7f55f3e6e4..72bba0be32 100644 --- a/sources/packages/web/src/router/InstitutionRoutes.ts +++ b/sources/packages/web/src/router/InstitutionRoutes.ts @@ -43,6 +43,7 @@ import InstitutionStudentApplications from "@/views/institution/student/Institut import InstitutionStudentRestrictions from "@/views/institution/student/InstitutionStudentRestrictions.vue"; import InstitutionStudentFileUploads from "@/views/institution/student/InstitutionStudentFileUploads.vue"; import InstitutionStudentNotes from "@/views/institution/student/InstitutionStudentNotes.vue"; +import InstitutionAssessmentsSummary from "@/views/institution/student/applicationDetails/InstitutionAssessmentsSummary.vue"; export const institutionRoutes: Array = [ { @@ -447,7 +448,7 @@ export const institutionRoutes: Array = [ }, }, { - path: AppRoutes.InstitutionStudentDetail, + path: AppRoutes.StudentDetail, name: InstitutionRoutesConst.STUDENT_DETAILS, props: true, components: { @@ -464,7 +465,7 @@ export const institutionRoutes: Array = [ }, children: [ { - path: AppRoutes.InstitutionStudentProfile, + path: AppRoutes.StudentProfile, name: InstitutionRoutesConst.STUDENT_PROFILE, props: true, component: InstitutionStudentProfile, @@ -530,6 +531,21 @@ export const institutionRoutes: Array = [ }, ], }, + // todo: move the move inside application details as a child after guru, merge his PR + + { + path: AppRoutes.InstitutionAssessmentSummary, + name: InstitutionRoutesConst.ASSESSMENTS_SUMMARY, + props: true, + component: InstitutionAssessmentsSummary, + meta: { + clientType: ClientIdType.Institution, + institutionUserTypes: [ + InstitutionUserTypes.admin, + InstitutionUserTypes.user, + ], + }, + }, ], beforeEnter: (to, _from, next) => { AuthService.shared diff --git a/sources/packages/web/src/services/StudentAssessmentsService.ts b/sources/packages/web/src/services/StudentAssessmentsService.ts index 9e7f07727e..04e0fb3eed 100644 --- a/sources/packages/web/src/services/StudentAssessmentsService.ts +++ b/sources/packages/web/src/services/StudentAssessmentsService.ts @@ -21,13 +21,18 @@ export class StudentAssessmentsService { * Get all requested assessments for an student application, * i.e, this will fetch the combination of pending and denied * student appeal and scholastic standings for an application. - * @param applicationId, application number. + * @param applicationId, application id. + * @param studentId, student id. * @returns assessment requests for a student application. */ async getAssessmentRequest( applicationId: number, + studentId?: number, ): Promise { - return ApiClient.StudentAssessmentApi.getAssessmentRequest(applicationId); + return ApiClient.StudentAssessmentApi.getAssessmentRequest( + applicationId, + studentId, + ); } /** * Get history of assessments for an application, diff --git a/sources/packages/web/src/services/http/StudentAssessmentApi.ts b/sources/packages/web/src/services/http/StudentAssessmentApi.ts index 70ca73be56..68f93019ed 100644 --- a/sources/packages/web/src/services/http/StudentAssessmentApi.ts +++ b/sources/packages/web/src/services/http/StudentAssessmentApi.ts @@ -14,14 +14,20 @@ export class StudentAssessmentApi extends HttpBaseClient { * Get all requested assessments for an student application, * i.e, this will fetch the combination of pending and denied * student appeal and scholastic standings for an application. - * @param applicationId, application number. + * @param applicationId, application id. + * @param studentId, student id. * @returns Request assessment summary list. */ public async getAssessmentRequest( applicationId: number, + studentId?: number, ): Promise { + const endpoint = studentId + ? `assessment/student/${studentId}/application/${applicationId}/requests` + : `assessment/application/${applicationId}/requests`; + return this.getCall( - this.addClientRoot(`assessment/application/${applicationId}/requests`), + this.addClientRoot(endpoint), ); } /** diff --git a/sources/packages/web/src/types/AppRoutes.ts b/sources/packages/web/src/types/AppRoutes.ts index 488d7f942b..5325e8d380 100644 --- a/sources/packages/web/src/types/AppRoutes.ts +++ b/sources/packages/web/src/types/AppRoutes.ts @@ -47,17 +47,14 @@ export enum AppRoutes { InstitutionManageUsers = "manage-users", ActiveApplicationScholasticStandingView = "active-application/location/:locationId/scholastic-standing/:scholasticStandingId", OfferingsUpload = "offerings-upload", - InstitutionStudentDetail = "student/:studentId", - InstitutionStudentProfile = "profile", + InstitutionAssessmentSummary = "assessment-summary", // AEST AESTRoot = "/ministry", AESTDashboard = "dashboard", SearchStudents = "search-students", - StudentDetail = "student/:studentId", ProgramDetail = "institution/:institutionId/location/:locationId/program-detail/:programId", SearchInstitutions = "search-institutions", InstitutionDetail = "institution-detail/:institutionId", - AESTStudentProfile = "profile", AESTEditInstitutionLocation = "institution-location/institution/:institutionId/location/:locationId/edit", AESTInstitutionProfile = "institution-profile", AESTInstitutionProfileEdit = "institution-profile/:institutionId/edit", @@ -85,11 +82,7 @@ export enum AppRoutes { Locations = "locations", Users = "users", Designation = "designation", - Restrictions = "restrictions", - FileUploads = "files", - Notes = "notes", SINManagement = "sin-management", - Applications = "applications", ApplicationDetail = "student/:studentId/application/:applicationId", SupportingUserDetail = "supporting-user/:supportingUserId", // Supporting Users @@ -106,4 +99,10 @@ export enum AppRoutes { StudentNotes = "student-notes/:studentId", StudentRestrictions = "student-restrictions/:studentId", Overawards = "overawards", + StudentDetail = "student/:studentId", + StudentProfile = "profile", + Applications = "applications", + Restrictions = "restrictions", + FileUploads = "files", + Notes = "notes", } diff --git a/sources/packages/web/src/views/aest/AssessmentsSummary.vue b/sources/packages/web/src/views/aest/AssessmentsSummary.vue index 06db14bdc6..c75e55f6dd 100644 --- a/sources/packages/web/src/views/aest/AssessmentsSummary.vue +++ b/sources/packages/web/src/views/aest/AssessmentsSummary.vue @@ -10,14 +10,14 @@ subTitle="Assessment" /> - - @@ -10,6 +11,8 @@ diff --git a/sources/packages/web/src/views/institution/student/applicationDetails/InstitutionAssessmentsSummary.vue b/sources/packages/web/src/views/institution/student/applicationDetails/InstitutionAssessmentsSummary.vue new file mode 100644 index 0000000000..8eec978324 --- /dev/null +++ b/sources/packages/web/src/views/institution/student/applicationDetails/InstitutionAssessmentsSummary.vue @@ -0,0 +1,135 @@ + + + From cb9d3978e003cb545c603293443ff61cc20efea9 Mon Sep 17 00:00:00 2001 From: Ann Date: Mon, 8 May 2023 20:31:15 -0400 Subject: [PATCH 02/12] exception and appeal --- .../backend/apps/api/src/app.aest.module.ts | 4 + .../apps/api/src/app.institutions.module.ts | 14 ++- .../application-exception.aest.controller.ts | 22 +---- ...pplication-exception.controller.service.ts | 44 +++++++++ ...ation-exception.institutions.controller.ts | 42 ++++++++ .../assessment.controller.service.ts | 3 +- .../assessment.institutions.controller.ts | 65 +++++------- ...ucation-program.institutions.controller.ts | 2 +- .../apps/api/src/route-controllers/index.ts | 4 + .../student-appeal.aest.controller.ts | 25 +---- .../student-appeal.controller.service.ts | 46 +++++++++ .../student-appeal.institutions.controller.ts | 52 ++++++++++ .../student-appeal.students.controller.ts | 1 + .../application-exception.service.ts | 19 +++- .../student-assessment.service.ts | 2 +- .../student-scholastic-standings.service.ts | 15 ++- .../aest/students/assessment/History.vue | 5 + .../ApplicationExceptionsApproval.vue | 79 ++++++--------- .../StudentAppealRequestsApproval.vue | 72 ++++---------- .../sidebar/InstitutionApplicationSideBar.vue | 13 +++ .../src/constants/routes/RouteConstants.ts | 2 + sources/packages/web/src/router/AESTRoutes.ts | 8 +- .../web/src/router/InstitutionRoutes.ts | 20 +++- .../services/ApplicationExceptionService.ts | 9 +- .../web/src/services/StudentAppealService.ts | 9 +- .../src/services/StudentAssessmentsService.ts | 9 +- .../services/http/ApplicationExceptionApi.ts | 9 +- .../web/src/services/http/StudentAppealApi.ts | 10 +- .../src/services/http/StudentAssessmentApi.ts | 9 +- sources/packages/web/src/types/AppRoutes.ts | 8 +- .../ApplicationExceptionsApproval.vue | 77 +++++++++++++++ .../StudentAppealRequestsApproval.vue | 75 ++++++++++++++ .../ApplicationExceptions.vue | 46 +++++++++ .../InstitutionAssessmentsSummary.vue | 98 ++++++++++--------- .../StudentAppealRequest.vue | 44 +++++++++ 35 files changed, 706 insertions(+), 256 deletions(-) create mode 100644 sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.controller.service.ts create mode 100644 sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.institutions.controller.ts create mode 100644 sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts create mode 100644 sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts rename sources/packages/web/src/{views/aest => components/common/students/applicationDetails}/ApplicationExceptionsApproval.vue (67%) rename sources/packages/web/src/{views/aest => components/common/students/applicationDetails}/StudentAppealRequestsApproval.vue (68%) create mode 100644 sources/packages/web/src/views/aest/student/applicationDetails/ApplicationExceptionsApproval.vue create mode 100644 sources/packages/web/src/views/aest/student/applicationDetails/StudentAppealRequestsApproval.vue create mode 100644 sources/packages/web/src/views/institution/student/applicationDetails/ApplicationExceptions.vue create mode 100644 sources/packages/web/src/views/institution/student/applicationDetails/StudentAppealRequest.vue diff --git a/sources/packages/backend/apps/api/src/app.aest.module.ts b/sources/packages/backend/apps/api/src/app.aest.module.ts index 1461428adc..2a60ab30c7 100644 --- a/sources/packages/backend/apps/api/src/app.aest.module.ts +++ b/sources/packages/backend/apps/api/src/app.aest.module.ts @@ -64,6 +64,8 @@ import { ConfirmationOfEnrollmentControllerService, OverawardAESTController, OverawardControllerService, + ApplicationExceptionControllerService, + StudentAppealControllerService, } from "./route-controllers"; import { AuthModule } from "./auth/auth.module"; import { @@ -160,6 +162,8 @@ import { NoteSharedService, OverawardControllerService, RestrictionSharedService, + ApplicationExceptionControllerService, + StudentAppealControllerService, ], }) export class AppAESTModule {} diff --git a/sources/packages/backend/apps/api/src/app.institutions.module.ts b/sources/packages/backend/apps/api/src/app.institutions.module.ts index 7329a14c1d..874557b4ab 100644 --- a/sources/packages/backend/apps/api/src/app.institutions.module.ts +++ b/sources/packages/backend/apps/api/src/app.institutions.module.ts @@ -53,6 +53,13 @@ import { AssessmentInstitutionsController, AssessmentControllerService, OverawardControllerService, + ApplicationExceptionInstitutionsController, + ApplicationExceptionControllerService, + UserInstitutionsController, + ApplicationInstitutionsController, + UserControllerService, + StudentAppealInstitutionsController, + StudentAppealControllerService, } from "./route-controllers"; import { AuthModule } from "./auth/auth.module"; import { @@ -69,9 +76,6 @@ import { SFASApplicationService, SFASPartTimeApplicationsService, } from "@sims/services/sfas"; -import { UserInstitutionsController } from "./route-controllers/user/user.institutions.controller"; -import { UserControllerService } from "./route-controllers/user/user.controller.service"; -import { ApplicationInstitutionsController } from "./route-controllers/application/application.institutions.controller"; @Module({ imports: [AuthModule], @@ -90,6 +94,8 @@ import { ApplicationInstitutionsController } from "./route-controllers/applicati StudentInstitutionsController, AssessmentInstitutionsController, OverawardInstitutionsController, + ApplicationExceptionInstitutionsController, + StudentAppealInstitutionsController, ], providers: [ ApplicationControllerService, @@ -143,6 +149,8 @@ import { ApplicationInstitutionsController } from "./route-controllers/applicati ApplicationExceptionService, StudentAppealRequestsService, OverawardControllerService, + ApplicationExceptionControllerService, + StudentAppealControllerService, ], }) export class AppInstitutionsModule {} diff --git a/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.aest.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.aest.controller.ts index 9f0ce01b36..537e83da4c 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.aest.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.aest.controller.ts @@ -44,6 +44,7 @@ import { } from "../models/pagination.dto"; import { Role } from "../../auth/roles.enum"; import { WorkflowClientService } from "@sims/services"; +import { ApplicationExceptionControllerService } from "./application-exception.controller.service"; @AllowAuthorizedParty(AuthorizedParties.aest) @Groups(UserGroups.AESTUser) @@ -53,6 +54,7 @@ export class ApplicationExceptionAESTController extends BaseController { constructor( private readonly applicationExceptionService: ApplicationExceptionService, private readonly workflowClientService: WorkflowClientService, + private readonly applicationExceptionControllerService: ApplicationExceptionControllerService, ) { super(); } @@ -70,23 +72,9 @@ export class ApplicationExceptionAESTController extends BaseController { async getExceptionById( @Param("exceptionId", ParseIntPipe) exceptionId: number, ): Promise { - const applicationException = - await this.applicationExceptionService.getExceptionById(exceptionId); - if (!applicationException) { - throw new NotFoundException("Student application exception not found."); - } - return { - exceptionStatus: applicationException.exceptionStatus, - submittedDate: applicationException.createdAt, - noteDescription: applicationException.exceptionNote?.description, - assessedByUserName: getUserFullName(applicationException.assessedBy), - assessedDate: applicationException.assessedDate, - exceptionRequests: applicationException.exceptionRequests.map( - (request) => ({ - exceptionName: request.exceptionName, - }), - ), - }; + return this.applicationExceptionControllerService.getExceptionDetails( + exceptionId, + ); } /** diff --git a/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.controller.service.ts new file mode 100644 index 0000000000..9c54185066 --- /dev/null +++ b/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.controller.service.ts @@ -0,0 +1,44 @@ +import { Injectable, NotFoundException } from "@nestjs/common"; +import { ApplicationExceptionService } from "../../services"; +import { getUserFullName } from "../../utilities"; +import { ApplicationExceptionAPIOutDTO } from "./models/application-exception.dto"; + +@Injectable() +export class ApplicationExceptionControllerService { + constructor( + private readonly applicationExceptionService: ApplicationExceptionService, + ) {} + + /** + * Get a student application exception detected after the student application was + * submitted, for instance, when there are documents to be reviewed. + * @param exceptionId exception to be retrieved. + * @param studentId student id. + * @returns student application exception information. + */ + async getExceptionDetails( + exceptionId: number, + studentId?: number, + ): Promise { + const applicationException = + await this.applicationExceptionService.getExceptionDetails( + exceptionId, + studentId, + ); + if (!applicationException) { + throw new NotFoundException("Student application exception not found."); + } + return { + exceptionStatus: applicationException.exceptionStatus, + submittedDate: applicationException.createdAt, + noteDescription: applicationException.exceptionNote?.description, + assessedByUserName: getUserFullName(applicationException.assessedBy), + assessedDate: applicationException.assessedDate, + exceptionRequests: applicationException.exceptionRequests.map( + (request) => ({ + exceptionName: request.exceptionName, + }), + ), + }; + } +} diff --git a/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.institutions.controller.ts new file mode 100644 index 0000000000..e9e7803db2 --- /dev/null +++ b/sources/packages/backend/apps/api/src/route-controllers/application-exception/application-exception.institutions.controller.ts @@ -0,0 +1,42 @@ +import { Controller, Get, Param, ParseIntPipe } from "@nestjs/common"; +import { AllowAuthorizedParty } from "../../auth/decorators"; +import { AuthorizedParties } from "../../auth/authorized-parties.enum"; +import { ClientTypeBaseRoute } from "../../types"; +import { ApiNotFoundResponse, ApiTags } from "@nestjs/swagger"; +import BaseController from "../BaseController"; +import { ApplicationExceptionAPIOutDTO } from "./models/application-exception.dto"; +import { ApplicationExceptionControllerService } from "./application-exception.controller.service"; + +/** + * Application exception controller for institutions. + */ +@AllowAuthorizedParty(AuthorizedParties.institution) +@Controller("application-exception") +@ApiTags(`${ClientTypeBaseRoute.Institution}-application-exception`) +export class ApplicationExceptionInstitutionsController extends BaseController { + constructor( + private readonly applicationExceptionControllerService: ApplicationExceptionControllerService, + ) { + super(); + } + + /** + * Get a student application exception of a student. + * @param studentId student id. + * @param exceptionId exception to be retrieved. + * @returns student application exception information. + */ + @Get("student/:studentId/exception/:exceptionId") + @ApiNotFoundResponse({ + description: "Student application exception not found.", + }) + async getException( + @Param("studentId", ParseIntPipe) studentId: number, + @Param("exceptionId", ParseIntPipe) exceptionId: number, + ): Promise { + return this.applicationExceptionControllerService.getExceptionDetails( + exceptionId, + studentId, + ); + } +} diff --git a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts index fbc7d3b0fd..dd7132e404 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.controller.service.ts @@ -244,7 +244,7 @@ export class AssessmentControllerService { * Get history of approved assessment requests and * unsuccessful scholastic standing change requests(which will not create new assessment) * for an application. - * @param applicationId, application number. + * @param applicationId, application id. * @param studentId applicant student. * @returns summary of the assessment history for a student application. */ @@ -256,6 +256,7 @@ export class AssessmentControllerService { this.assessmentService.assessmentHistorySummary(applicationId, studentId), this.studentScholasticStandingsService.getUnsuccessfulScholasticStandings( applicationId, + studentId, ), ]); const history: AssessmentHistorySummaryAPIOutDTO[] = assessments.map( diff --git a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts index dc31387798..3cde305224 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts @@ -2,44 +2,29 @@ import { Controller, Get, Param, ParseIntPipe } from "@nestjs/common"; import BaseController from "../BaseController"; import { AllowAuthorizedParty, - Groups, HasStudentDataAccess, IsBCPublicInstitution, } from "../../auth/decorators"; import { AuthorizedParties } from "../../auth/authorized-parties.enum"; import { ClientTypeBaseRoute } from "../../types"; -import { UserGroups } from "../../auth/user-groups.enum"; import { AssessmentHistorySummaryAPIOutDTO, - AssessmentNOAAPIOutDTO, RequestAssessmentSummaryAPIOutDTO, - AwardDetailsAPIOutDTO, - RequestAssessmentTypeAPIOutDTO, } from "./models/assessment.dto"; -import { - ApiNotFoundResponse, - ApiTags, - ApiUnprocessableEntityResponse, -} from "@nestjs/swagger"; +import { ApiTags } from "@nestjs/swagger"; import { AssessmentControllerService } from "./assessment.controller.service"; -import { - EducationProgramOfferingService, - ApplicationExceptionService, -} from "../../services"; -import { ApplicationExceptionStatus } from "@sims/sims-db"; /** * Assessment controller for institutions. */ @AllowAuthorizedParty(AuthorizedParties.institution) @Controller("assessment") +@IsBCPublicInstitution() @ApiTags(`${ClientTypeBaseRoute.Institution}-assessment`) export class AssessmentInstitutionsController extends BaseController { constructor( - private readonly assessmentControllerService: AssessmentControllerService, - ) // private readonly educationProgramOfferingService: EducationProgramOfferingService, - // private readonly applicationExceptionService: ApplicationExceptionService, - { + private readonly assessmentControllerService: AssessmentControllerService, // private readonly educationProgramOfferingService: EducationProgramOfferingService, // private readonly applicationExceptionService: ApplicationExceptionService, + ) { super(); } @@ -50,9 +35,8 @@ export class AssessmentInstitutionsController extends BaseController { * @param applicationId application id. * @returns assessment requests or exceptions for the student application. */ - // @IsBCPublicInstitution() - // @HasStudentDataAccess("studentId") - @Get("/student/:studentId/application/:applicationId/requests") + @HasStudentDataAccess("studentId") + @Get("student/:studentId/application/:applicationId/requests") async getRequestedAssessmentSummary( @Param("studentId", ParseIntPipe) studentId: number, @Param("applicationId", ParseIntPipe) applicationId: number, @@ -63,23 +47,26 @@ export class AssessmentInstitutionsController extends BaseController { ); } - // /** - // * Method to get history of assessments for an application, - // * i.e, this will have original assessment for the - // * student application, and all approved student - // * appeal and scholastic standings for the application - // * which will have different assessment status. - // * @param applicationId, application number. - // * @returns summary of the assessment history for a student application. - // */ - // @Get("application/:applicationId/history") - // async getAssessmentHistorySummary( - // @Param("applicationId", ParseIntPipe) applicationId: number, - // ): Promise { - // return this.assessmentControllerService.getAssessmentHistorySummary( - // applicationId, - // ); - // } + /** + * Method to get history of assessments for an application, + * i.e, this will have original assessment for the + * student application, and all approved student + * appeal and scholastic standings for the application + * which will have different assessment status. + * @param studentId student id. + * @param applicationId, application id. + * @returns summary of the assessment history for a student application. + */ + @Get("student/:studentId/application/:applicationId/history") + async getAssessmentHistorySummary( + @Param("studentId", ParseIntPipe) studentId: number, + @Param("applicationId", ParseIntPipe) applicationId: number, + ): Promise { + return this.assessmentControllerService.getAssessmentHistorySummary( + applicationId, + studentId, + ); + } // /** // * Get the NOA values for a student application on a particular assessment. diff --git a/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts index 00417de70f..d88c6f44c0 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts @@ -53,7 +53,7 @@ export class EducationProgramInstitutionsController extends BaseController { * @param paginationOptions pagination options. * @returns paginated programs summary. */ - @HasLocationAccess("locationId") + // @HasLocationAccess("locationId") @Get("location/:locationId/summary") async getProgramsSummaryByLocationId( @Param("locationId", ParseIntPipe) locationId: number, diff --git a/sources/packages/backend/apps/api/src/route-controllers/index.ts b/sources/packages/backend/apps/api/src/route-controllers/index.ts index 081636dbc2..9fb09b963e 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/index.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/index.ts @@ -60,3 +60,7 @@ export * from "./overaward/overaward.institutions.controller"; export * from "./overaward/overaward.students.controller"; export * from "./student/student.institutions.controller"; export * from "./assessment/assessment.institutions.controller"; +export * from "./application-exception/application-exception.institutions.controller"; +export * from "./application-exception/application-exception.controller.service"; +export * from "./student-appeal/student-appeal.controller.service"; +export * from "./student-appeal/student-appeal.institutions.controller"; diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts index e05271973e..3358d9860a 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts @@ -47,6 +47,7 @@ import { StudentAppealPendingPaginationOptionsAPIInDTO, } from "../models/pagination.dto"; import { Role } from "../../auth/roles.enum"; +import { StudentAppealControllerService } from "./student-appeal.controller.service"; @AllowAuthorizedParty(AuthorizedParties.aest) @Groups(UserGroups.AESTUser) @@ -56,6 +57,7 @@ export class StudentAppealAESTController extends BaseController { constructor( private readonly studentAppealService: StudentAppealService, private readonly studentAssessmentService: StudentAssessmentService, + private readonly studentAppealControllerService: StudentAppealControllerService, ) { super(); } @@ -72,26 +74,9 @@ export class StudentAppealAESTController extends BaseController { async getStudentAppealWithRequests( @Param("appealId", ParseIntPipe) appealId: number, ): Promise { - const studentAppeal = - await this.studentAppealService.getAppealAndRequestsById(appealId); - if (!studentAppeal) { - throw new NotFoundException("Not able to find the student appeal."); - } - - return { - id: studentAppeal.id, - submittedDate: studentAppeal.submittedDate, - status: studentAppeal.status, - appealRequests: studentAppeal.appealRequests.map((appealRequest) => ({ - id: appealRequest.id, - appealStatus: appealRequest.appealStatus, - submittedData: appealRequest.submittedData, - submittedFormName: appealRequest.submittedFormName, - assessedDate: appealRequest.assessedDate, - noteDescription: appealRequest.note?.description, - assessedByUserName: getUserFullName(appealRequest.assessedBy), - })), - }; + return this.studentAppealControllerService.getStudentAppealWithRequest( + appealId, + ); } /** diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts new file mode 100644 index 0000000000..f8e8dd9e56 --- /dev/null +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts @@ -0,0 +1,46 @@ +import { NotFoundException } from "@nestjs/common"; +import { StudentAppealService } from "../../services"; +import BaseController from "../BaseController"; +import { StudentAppealAPIOutDTO } from "./models/student-appeal.dto"; +import { getUserFullName } from "../../utilities"; + +export class StudentAppealControllerService extends BaseController { + constructor(private readonly studentAppealService: StudentAppealService) { + super(); + } + + /** + * Get the student appeal and its requests. + * @param appealId appeal id to be retrieved. + * @param studentId student id. + * @returns the student appeal and its requests. + */ + async getStudentAppealWithRequest( + appealId: number, + studentId?: number, + ): Promise { + const studentAppeal = + await this.studentAppealService.getAppealAndRequestsById( + appealId, + studentId, + ); + if (!studentAppeal) { + throw new NotFoundException("Not able to find the student appeal."); + } + + return { + id: studentAppeal.id, + submittedDate: studentAppeal.submittedDate, + status: studentAppeal.status, + appealRequests: studentAppeal.appealRequests.map((appealRequest) => ({ + id: appealRequest.id, + appealStatus: appealRequest.appealStatus, + submittedData: appealRequest.submittedData, + submittedFormName: appealRequest.submittedFormName, + assessedDate: appealRequest.assessedDate, + noteDescription: appealRequest.note?.description, + assessedByUserName: getUserFullName(appealRequest.assessedBy), + })), + }; + } +} diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts new file mode 100644 index 0000000000..77a31e6665 --- /dev/null +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts @@ -0,0 +1,52 @@ +import { + Controller, + Param, + Get, + ParseIntPipe, +} from "@nestjs/common"; +import { AuthorizedParties } from "../../auth/authorized-parties.enum"; +import { + AllowAuthorizedParty, +} from "../../auth/decorators"; +import { + ApiNotFoundResponse, + ApiTags, +} from "@nestjs/swagger"; +import BaseController from "../BaseController"; +import { ClientTypeBaseRoute } from "../../types"; +import { StudentAppealAPIOutDTO } from "./models/student-appeal.dto"; +import { StudentAppealControllerService } from "./student-appeal.controller.service"; + +/** + * Student appeal controller for institutions. + */ +@AllowAuthorizedParty(AuthorizedParties.institution) +@Controller("appeal") +@ApiTags(`${ClientTypeBaseRoute.Institution}-appeal`) +export class StudentAppealInstitutionsController extends BaseController { + constructor( + private readonly studentAppealControllerService: StudentAppealControllerService, + ) { + super(); + } + + /** + * Get the student appeal and its requests. + * @param appealId appeal id to be retrieved. + * @param studentId student id. + * @returns the student appeal and its requests. + */ + @Get("student/:studentId/appeal/:appealId/requests") + @ApiNotFoundResponse({ + description: "Not able to find the student appeal.", + }) + async getStudentAppealWithRequest( + @Param("studentId", ParseIntPipe) studentId: number, + @Param("appealId", ParseIntPipe) appealId: number, + ): Promise { + return this.studentAppealControllerService.getStudentAppealWithRequest( + appealId, + studentId, + ); + } +} diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts index b4beb5bfc6..0ce07a948e 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts @@ -155,6 +155,7 @@ export class StudentAppealStudentsController extends BaseController { /** * Get the student appeal and its requests. * @param appealId appeal id to be retrieved. + * todo: ann controller service already created, dto is different work on it * @returns the student appeal and its requests. */ @Get(":appealId/requests") diff --git a/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts b/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts index d1801192aa..2683afc67a 100644 --- a/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts +++ b/sources/packages/backend/apps/api/src/services/application-exception/application-exception.service.ts @@ -39,10 +39,14 @@ export class ApplicationExceptionService extends RecordDataModelService { - return this.repo + async getExceptionDetails( + exceptionId: number, + studentId?: number, + ): Promise { + const exception = this.repo .createQueryBuilder("exception") .select([ "exception.id", @@ -57,8 +61,15 @@ export class ApplicationExceptionService extends RecordDataModelService { - return this.repo + const unsuccessfulScholasticStandings = this.repo .createQueryBuilder("studentScholasticStanding") .select([ "studentScholasticStanding.id", @@ -470,8 +472,15 @@ export class StudentScholasticStandingsService extends RecordDataModelService, required: true, }, + studentId: { + type: Number, + required: false, + }, }, setup(props, context) { const { dateOnlyLongString } = useFormatters(); @@ -114,6 +118,7 @@ export default defineComponent({ assessmentHistory.value = await StudentAssessmentsService.shared.getAssessmentHistory( props.applicationId, + props.studentId, ); }); diff --git a/sources/packages/web/src/views/aest/ApplicationExceptionsApproval.vue b/sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue similarity index 67% rename from sources/packages/web/src/views/aest/ApplicationExceptionsApproval.vue rename to sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue index 9b79557354..ace39cb9d1 100644 --- a/sources/packages/web/src/views/aest/ApplicationExceptionsApproval.vue +++ b/sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue @@ -4,7 +4,7 @@ - --> + + From 9fcedb63c3c0e5a9fec29cdfd648ef86175b11ea Mon Sep 17 00:00:00 2001 From: Ann Date: Tue, 9 May 2023 17:57:40 -0400 Subject: [PATCH 03/12] appeals --- .../student-appeal.controller.service.ts | 12 +++++------- .../student-appeal.institutions.controller.ts | 18 ++++-------------- sources/packages/web/package-lock.json | 17 +++++++++++------ sources/packages/web/package.json | 1 + 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts index f8e8dd9e56..3c6c3aa9cb 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts @@ -1,13 +1,11 @@ -import { NotFoundException } from "@nestjs/common"; -import { StudentAppealService } from "../../services"; -import BaseController from "../BaseController"; +import { Injectable, NotFoundException } from "@nestjs/common"; import { StudentAppealAPIOutDTO } from "./models/student-appeal.dto"; import { getUserFullName } from "../../utilities"; +import { StudentAppealService } from "../../services"; -export class StudentAppealControllerService extends BaseController { - constructor(private readonly studentAppealService: StudentAppealService) { - super(); - } +@Injectable() +export class StudentAppealControllerService { + constructor(private readonly studentAppealService: StudentAppealService) {} /** * Get the student appeal and its requests. diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts index 77a31e6665..6e520ad666 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts @@ -1,19 +1,9 @@ -import { - Controller, - Param, - Get, - ParseIntPipe, -} from "@nestjs/common"; +import { Controller, Param, Get, ParseIntPipe } from "@nestjs/common"; import { AuthorizedParties } from "../../auth/authorized-parties.enum"; -import { - AllowAuthorizedParty, -} from "../../auth/decorators"; -import { - ApiNotFoundResponse, - ApiTags, -} from "@nestjs/swagger"; +import { AllowAuthorizedParty } from "../../auth/decorators"; +import { ApiNotFoundResponse, ApiTags } from "@nestjs/swagger"; import BaseController from "../BaseController"; -import { ClientTypeBaseRoute } from "../../types"; +import { ClientTypeBaseRoute } from "../../types"; import { StudentAppealAPIOutDTO } from "./models/student-appeal.dto"; import { StudentAppealControllerService } from "./student-appeal.controller.service"; diff --git a/sources/packages/web/package-lock.json b/sources/packages/web/package-lock.json index 6f36629c71..afa3b2362b 100644 --- a/sources/packages/web/package-lock.json +++ b/sources/packages/web/package-lock.json @@ -13,6 +13,7 @@ "@types/vuelidate": "^0.7.13", "@vee-validate/rules": "^4.0.4", "axios": "^0.21.2", + "caniuse-lite": "^1.0.30001486", "core-js": "^3.8.3", "dayjs": "^1.10.7", "formiojs": "^4.13.4", @@ -5267,9 +5268,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001406", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz", - "integrity": "sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==", + "version": "1.0.30001486", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", + "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==", "funding": [ { "type": "opencollective", @@ -5278,6 +5279,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -21596,9 +21601,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001406", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz", - "integrity": "sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==" + "version": "1.0.30001486", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", + "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", diff --git a/sources/packages/web/package.json b/sources/packages/web/package.json index 23e4b542cf..952a8b69ca 100644 --- a/sources/packages/web/package.json +++ b/sources/packages/web/package.json @@ -15,6 +15,7 @@ "@types/vuelidate": "^0.7.13", "@vee-validate/rules": "^4.0.4", "axios": "^0.21.2", + "caniuse-lite": "^1.0.30001486", "core-js": "^3.8.3", "dayjs": "^1.10.7", "formiojs": "^4.13.4", From cefada3be5d7cef5889fc1bc863811df1c2f874b Mon Sep 17 00:00:00 2001 From: Ann Date: Tue, 9 May 2023 21:09:59 -0400 Subject: [PATCH 04/12] refactor --- .../backend/apps/api/src/app.aest.module.ts | 4 +- .../assessment.institutions.controller.ts | 38 +------ ...ucation-program.institutions.controller.ts | 2 +- .../models/student-appeal.dto.ts | 10 ++ .../student-appeal.aest.controller.ts | 6 +- .../student-appeal.controller.service.ts | 38 +++++-- .../student-appeal.institutions.controller.ts | 9 +- .../student-appeal.students.controller.ts | 26 +---- .../ApplicationExceptionsApproval.vue | 14 ++- .../StudentAppealRequestsApproval.vue | 100 ++++++++++-------- .../web/src/services/StudentAppealService.ts | 5 +- .../web/src/services/http/StudentAppealApi.ts | 11 +- .../services/http/dto/StudentAppeal.dto.ts | 10 ++ sources/packages/web/src/types/AppRoutes.ts | 1 - .../ApplicationExceptionsApproval.vue | 9 +- .../StudentAppealRequestsApproval.vue | 2 +- .../InstitutionAssessmentsSummary.vue | 55 +--------- 17 files changed, 146 insertions(+), 194 deletions(-) diff --git a/sources/packages/backend/apps/api/src/app.aest.module.ts b/sources/packages/backend/apps/api/src/app.aest.module.ts index 2a60ab30c7..a3e594099b 100644 --- a/sources/packages/backend/apps/api/src/app.aest.module.ts +++ b/sources/packages/backend/apps/api/src/app.aest.module.ts @@ -109,6 +109,8 @@ import { OverawardAESTController, ], providers: [ + ApplicationExceptionControllerService, + StudentAppealControllerService, WorkflowClientService, InstitutionRestrictionService, SupportingUserService, @@ -162,8 +164,6 @@ import { NoteSharedService, OverawardControllerService, RestrictionSharedService, - ApplicationExceptionControllerService, - StudentAppealControllerService, ], }) export class AppAESTModule {} diff --git a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts index 3cde305224..f6bc6d7b1d 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/assessment/assessment.institutions.controller.ts @@ -23,7 +23,7 @@ import { AssessmentControllerService } from "./assessment.controller.service"; @ApiTags(`${ClientTypeBaseRoute.Institution}-assessment`) export class AssessmentInstitutionsController extends BaseController { constructor( - private readonly assessmentControllerService: AssessmentControllerService, // private readonly educationProgramOfferingService: EducationProgramOfferingService, // private readonly applicationExceptionService: ApplicationExceptionService, + private readonly assessmentControllerService: AssessmentControllerService, ) { super(); } @@ -67,40 +67,4 @@ export class AssessmentInstitutionsController extends BaseController { studentId, ); } - - // /** - // * Get the NOA values for a student application on a particular assessment. - // * @param assessmentId assessment id to get the NOA values. - // * @returns NOA and application data. - // */ - // @Get(":assessmentId/noa") - // @ApiNotFoundResponse({ - // description: "Assessment id not found.", - // }) - // @ApiUnprocessableEntityResponse({ - // description: "Notice of assessment data is not present.", - // }) - // async getAssessmentNOA( - // @Param("assessmentId", ParseIntPipe) assessmentId: number, - // ): Promise { - // return this.assessmentControllerService.getAssessmentNOA(assessmentId); - // } - - // /** - // * Get estimated and actual(if present) award details of an assessment. - // * @param assessmentId assessment to which awards details belong to. - // * @returns estimated and actual award details. - // */ - // @Get(":assessmentId/award") - // @ApiNotFoundResponse({ - // description: "Assessment not found.", - // }) - // async getAssessmentAwardDetails( - // @Param("assessmentId", ParseIntPipe) assessmentId: number, - // ): Promise { - // return this.assessmentControllerService.getAssessmentAwardDetails( - // assessmentId, - // true, - // ); - // } } diff --git a/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts index d88c6f44c0..00417de70f 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/education-program/education-program.institutions.controller.ts @@ -53,7 +53,7 @@ export class EducationProgramInstitutionsController extends BaseController { * @param paginationOptions pagination options. * @returns paginated programs summary. */ - // @HasLocationAccess("locationId") + @HasLocationAccess("locationId") @Get("location/:locationId/summary") async getProgramsSummaryByLocationId( @Param("locationId", ParseIntPipe) locationId: number, diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/models/student-appeal.dto.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/models/student-appeal.dto.ts index 5d2c65e71a..136d40772d 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/models/student-appeal.dto.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/models/student-appeal.dto.ts @@ -41,6 +41,9 @@ export class StudentAppealRequestAPIOutDTO { submittedData: unknown; submittedFormName: string; appealStatus: StudentAppealStatus; +} + +export class DetailedStudentAppealRequestAPIOutDTO extends StudentAppealRequestAPIOutDTO { assessedDate?: Date; assessedByUserName?: string; noteDescription?: string; @@ -53,6 +56,13 @@ export class StudentAppealAPIOutDTO { appealRequests: StudentAppealRequestAPIOutDTO[]; } +export class DetailedStudentAppealAPIOutDTO { + id: number; + submittedDate: Date; + status: StudentAppealStatus; + appealRequests: DetailedStudentAppealRequestAPIOutDTO[]; +} + export class StudentAppealRequestApprovalAPIInDTO { @IsPositive() id: number; diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts index 3358d9860a..4da7e1c90c 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.aest.controller.ts @@ -30,7 +30,7 @@ import BaseController from "../BaseController"; import { ApiProcessError, ClientTypeBaseRoute } from "../../types"; import { UserGroups } from "../../auth/user-groups.enum"; import { - StudentAppealAPIOutDTO, + DetailedStudentAppealAPIOutDTO, StudentAppealApprovalAPIInDTO, StudentAppealPendingSummaryAPIOutDTO, } from "./models/student-appeal.dto"; @@ -73,9 +73,11 @@ export class StudentAppealAESTController extends BaseController { }) async getStudentAppealWithRequests( @Param("appealId", ParseIntPipe) appealId: number, - ): Promise { + ): Promise { return this.studentAppealControllerService.getStudentAppealWithRequest( appealId, + undefined, + {assessDetails: true} ); } diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts index 3c6c3aa9cb..3bb0e7c639 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.controller.service.ts @@ -1,5 +1,10 @@ import { Injectable, NotFoundException } from "@nestjs/common"; -import { StudentAppealAPIOutDTO } from "./models/student-appeal.dto"; +import { + StudentAppealAPIOutDTO, + DetailedStudentAppealAPIOutDTO, + StudentAppealRequestAPIOutDTO, + DetailedStudentAppealRequestAPIOutDTO, +} from "./models/student-appeal.dto"; import { getUserFullName } from "../../utilities"; import { StudentAppealService } from "../../services"; @@ -16,7 +21,10 @@ export class StudentAppealControllerService { async getStudentAppealWithRequest( appealId: number, studentId?: number, - ): Promise { + options?: { + assessDetails?: false; + }, + ): Promise { const studentAppeal = await this.studentAppealService.getAppealAndRequestsById( appealId, @@ -30,15 +38,23 @@ export class StudentAppealControllerService { id: studentAppeal.id, submittedDate: studentAppeal.submittedDate, status: studentAppeal.status, - appealRequests: studentAppeal.appealRequests.map((appealRequest) => ({ - id: appealRequest.id, - appealStatus: appealRequest.appealStatus, - submittedData: appealRequest.submittedData, - submittedFormName: appealRequest.submittedFormName, - assessedDate: appealRequest.assessedDate, - noteDescription: appealRequest.note?.description, - assessedByUserName: getUserFullName(appealRequest.assessedBy), - })), + appealRequests: studentAppeal.appealRequests.map((appealRequest) => { + const requests: DetailedStudentAppealRequestAPIOutDTO + = { + id: appealRequest.id, + appealStatus: appealRequest.appealStatus, + submittedData: appealRequest.submittedData, + submittedFormName: appealRequest.submittedFormName, + }; + if (options?.assessDetails) { + requests.assessedDate = appealRequest.assessedDate; + requests.noteDescription = appealRequest.note?.description; + requests.assessedByUserName = getUserFullName( + appealRequest.assessedBy, + ); + } + return requests; + }), }; } } diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts index 6e520ad666..a3f19d4208 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.institutions.controller.ts @@ -4,7 +4,7 @@ import { AllowAuthorizedParty } from "../../auth/decorators"; import { ApiNotFoundResponse, ApiTags } from "@nestjs/swagger"; import BaseController from "../BaseController"; import { ClientTypeBaseRoute } from "../../types"; -import { StudentAppealAPIOutDTO } from "./models/student-appeal.dto"; +import { DetailedStudentAppealAPIOutDTO } from "./models/student-appeal.dto"; import { StudentAppealControllerService } from "./student-appeal.controller.service"; /** @@ -21,10 +21,10 @@ export class StudentAppealInstitutionsController extends BaseController { } /** - * Get the student appeal and its requests. + * Get the student appeal details. * @param appealId appeal id to be retrieved. * @param studentId student id. - * @returns the student appeal and its requests. + * @returns the student appeal details. */ @Get("student/:studentId/appeal/:appealId/requests") @ApiNotFoundResponse({ @@ -33,10 +33,11 @@ export class StudentAppealInstitutionsController extends BaseController { async getStudentAppealWithRequest( @Param("studentId", ParseIntPipe) studentId: number, @Param("appealId", ParseIntPipe) appealId: number, - ): Promise { + ): Promise { return this.studentAppealControllerService.getStudentAppealWithRequest( appealId, studentId, + {assessDetails: true} ); } } diff --git a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts index 0ce07a948e..366ce67b61 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/student-appeal/student-appeal.students.controller.ts @@ -54,6 +54,7 @@ export class StudentAppealStudentsController extends BaseController { private readonly studentAppealService: StudentAppealService, private readonly applicationService: ApplicationService, private readonly formService: FormService, + private readonly studentAppealControllerService: StudentAppealControllerService, ) { super(); } @@ -155,7 +156,6 @@ export class StudentAppealStudentsController extends BaseController { /** * Get the student appeal and its requests. * @param appealId appeal id to be retrieved. - * todo: ann controller service already created, dto is different work on it * @returns the student appeal and its requests. */ @Get(":appealId/requests") @@ -166,25 +166,9 @@ export class StudentAppealStudentsController extends BaseController { @Param("appealId", ParseIntPipe) appealId: number, @UserToken() userToken: StudentUserToken, ): Promise { - const studentAppeal = - await this.studentAppealService.getAppealAndRequestsById( - appealId, - userToken.studentId, - ); - if (!studentAppeal) { - throw new NotFoundException("Not able to find the student appeal."); - } - - return { - id: studentAppeal.id, - submittedDate: studentAppeal.submittedDate, - status: studentAppeal.status, - appealRequests: studentAppeal.appealRequests.map((appealRequest) => ({ - id: appealRequest.id, - appealStatus: appealRequest.appealStatus, - submittedData: appealRequest.submittedData, - submittedFormName: appealRequest.submittedFormName, - })), - }; + return this.studentAppealControllerService.getStudentAppealWithRequest( + appealId, + userToken.studentId, + ); } } diff --git a/sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue b/sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue index ace39cb9d1..3e93346fca 100644 --- a/sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue +++ b/sources/packages/web/src/components/common/students/applicationDetails/ApplicationExceptionsApproval.vue @@ -36,8 +36,11 @@ import { ref, onMounted, defineComponent, PropType } from "vue"; import { RouteLocationRaw, useRouter } from "vue-router"; import { ApplicationExceptionService } from "@/services/ApplicationExceptionService"; -import { ApplicationExceptionStatus, Role } from "@/types"; -import { ApplicationExceptionAPIOutDTO } from "@/services/http/dto"; +import { ApplicationExceptionStatus, FormIOForm, Role } from "@/types"; +import { + ApplicationExceptionAPIOutDTO, + UpdateApplicationExceptionAPIInDTO, +} from "@/services/http/dto"; import { useAssessment, useFormatters } from "@/composables"; import HeaderTitleValue from "@/components/generic/HeaderTitleValue.vue"; import CheckPermissionRole from "@/components/generic/CheckPermissionRole.vue"; @@ -74,8 +77,11 @@ type ApplicationExceptionFormModel = Omit< }; export default defineComponent({ - // todo: ann emit new - emits: ["submitted"], + emits: { + submitted: (form: FormIOForm) => { + return !!form; + }, + }, components: { HeaderTitleValue, CheckPermissionRole }, props: { studentId: { diff --git a/sources/packages/web/src/components/common/students/applicationDetails/StudentAppealRequestsApproval.vue b/sources/packages/web/src/components/common/students/applicationDetails/StudentAppealRequestsApproval.vue index 27a61a7689..f452c1fedb 100644 --- a/sources/packages/web/src/components/common/students/applicationDetails/StudentAppealRequestsApproval.vue +++ b/sources/packages/web/src/components/common/students/applicationDetails/StudentAppealRequestsApproval.vue @@ -1,66 +1,72 @@