mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-01 19:23:28 +00:00
fix(exam): show the back office the real examination state
The COC detail page read the application status alone, so a candidate who had registered, been marked present, sat the paper and had a PASSED mark published still appeared to be awaiting an exam — and the officer was offered "Schedule exam" and "Record exam result" for work already done. ExamStatePanel reads GET /exams/applications/:id/state, which the server derives from the registration, the attempt and the published mark. Session, date and admission number while the exam is ahead; score, outcome and whether the exam engine or an examiner produced the mark once it is settled. Polled, because attendance is recorded and papers are marked while the officer has the page open. Same derivation the applicant's portal reads, so the two cannot disagree. The eligible-exams query, the scheduling mutation and the outcome mutation are gone from the RTK layer along with the endpoints behind them.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { baseApi } from '../../base-api';
|
||||
import type {
|
||||
ExamStateView,
|
||||
AppNotification,
|
||||
ApplicationDetail,
|
||||
ApplicationKind,
|
||||
@@ -649,6 +650,18 @@ export const licensingApi = baseApi
|
||||
error ? [] : [itemTag('LicenseApplication', id), listTag('ApplicationQueue')],
|
||||
}),
|
||||
|
||||
/**
|
||||
* The examination leg behind one application, as the server reads it.
|
||||
*
|
||||
* The COC detail page used to infer this from the application status
|
||||
* alone, which is how it kept offering "Schedule exam" for a paper the
|
||||
* candidate had already sat and passed.
|
||||
*/
|
||||
getExamStateForApplication: builder.query<ExamStateView, string>({
|
||||
query: (id) => ({ url: `/exams/applications/${id}/state` }),
|
||||
providesTags: (_r, _e, id) => [itemTag('LicenseApplication', id)],
|
||||
}),
|
||||
|
||||
// No `getEligibleExams`, `scheduleExam` or `recordExamOutcome`: the
|
||||
// endpoints behind them are gone. Sittings are published as master
|
||||
// schedules and candidates register for one themselves, and an outcome
|
||||
@@ -1053,6 +1066,7 @@ export const {
|
||||
useUpdateLicenseValidityMutation,
|
||||
useGetLicenseTypeRequirementsQuery,
|
||||
useCreateApplicationMutation,
|
||||
useGetExamStateForApplicationQuery,
|
||||
useGetMyApplicationsQuery,
|
||||
useGetApplicationQuery,
|
||||
useInitiatePaymentMutation,
|
||||
|
||||
@@ -748,3 +748,36 @@ export interface IssuedLicense {
|
||||
certificateFileKey: string | null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Where a certificate application stands in the examination leg, derived
|
||||
* server-side from the registration, the attempt and the published mark
|
||||
* (ExamStateService). The application status alone cannot answer this — which
|
||||
* is why the back office could show "awaiting exam" over a published pass.
|
||||
*/
|
||||
export type ExamState =
|
||||
| 'NOT_REGISTERED'
|
||||
| 'REGISTERED'
|
||||
| 'ATTENDANCE_CONFIRMED'
|
||||
| 'NOT_SITTING'
|
||||
| 'IN_PROGRESS'
|
||||
| 'UNDER_EVALUATION'
|
||||
| 'PASSED'
|
||||
| 'FAILED';
|
||||
|
||||
export interface ExamStateView {
|
||||
state: ExamState;
|
||||
registrationId: string | null;
|
||||
admissionNumber: string | null;
|
||||
examId: string | null;
|
||||
examTitle: { en?: string; am?: string } | null;
|
||||
examDate: string | null;
|
||||
attendanceStatus: string | null;
|
||||
attemptStatus: 'IN_PROGRESS' | 'SUBMITTED' | 'EXPIRED' | null;
|
||||
/** Only once the mark is published — before that it is not the candidate's. */
|
||||
score: number | null;
|
||||
outcome: 'PASSED' | 'FAILED' | null;
|
||||
publishedAt: string | null;
|
||||
/** Whether the exam engine produced the mark, or a person did. */
|
||||
autoGraded: boolean | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user