apps/recallassess/recallassess-api/src/api/client/participant/dto/participant.dto.ts
Properties |
|
| courses_completed |
Type : number
|
Decorators :
@Expose()
|
| Optional current_course |
Type : string
|
Decorators :
@Expose()
|
| Optional current_stage |
Type : string
|
Decorators :
@Expose()
|
|
Stage of the participant's MOST RECENTLY allocated course assignment. One of: PENDING_INVITE, INVITED, ACCEPTED, PRE_BAT, E_LEARNING, POST_BAT, COMPLETED. Drives the row's stage pill in the client portal directory. |
| department |
Type : string
|
Decorators :
@Expose()
|
| Optional eligible_for_next |
Type : boolean
|
Decorators :
@Expose()
|
|
True when the most recently allocated course has reached e-Learning Done (status >= E_LEARNING_COMPLETED on the backend's progress timeline). Drives visibility of the "Allocate next course" menu item. |
Type : string
|
Decorators :
@Expose()
|
| Optional email_subscription_status |
Type : literal type
|
Decorators :
@Expose()
|
| Optional enrolled_courses |
Type : CLParticipantEnrolledCourse[]
|
Decorators :
@Expose()
|
|
All non-cancelled course enrollments for this participant. Populated for the list endpoint so the frontend can render the per-course breakdown inside the View Details dialog without an extra round-trip. |
| full_name |
Type : string
|
Decorators :
@Expose()
|
|
Only derive from DB row on PLAIN_TO_CLASS (plainToInstance). On CLASS_TO_PLAIN (HTTP serializer)
|
| Optional has_password |
Type : boolean
|
Decorators :
@Expose()
|
|
True when the participant has set up a password (users.password_hash IS NOT NULL). Distinguishes a brand-new INVITED user from a returning user whose new course just sits at ACCEPTED awaiting course-acceptance. |
| id |
Type : number
|
Decorators :
@Expose()
|
| last_active |
Type : string
|
Decorators :
@Expose()
|
| progress |
Type : number
|
Decorators :
@Expose()
|
| status |
Type : string
|
Decorators :
@Expose()
|
| total_courses |
Type : number
|
Decorators :
@Expose()
|
import { Exclude, Expose, Transform, TransformationType } from "class-transformer";
import { getFullName, getStatus } from "../utils";
/**
* Per-course enrollment summary — one entry per learning_group_participant row
* for a participant. Used by the View Details dialog to render every course
* with its own stage pill, progress, and meta info.
*
* `stage` carries the literal Prisma enum value (PENDING_INVITE, INVITED,
* ACCEPTED, PRE_BAT, E_LEARNING, POST_BAT, COMPLETED). Cancelled enrollments
* are excluded server-side and won't appear here.
*/
export interface CLParticipantEnrolledCourse {
enrollment_id: number;
learning_group_id: number;
course_name: string;
stage: string;
progress: number;
allocated_at: string;
last_active_at: string | null;
}
@Exclude()
export class CLParticipantDto {
@Expose()
id!: number;
/**
* Only derive from DB row on PLAIN_TO_CLASS (plainToInstance). On CLASS_TO_PLAIN (HTTP serializer)
* `obj` is this DTO instance, which has no first_name/last_name — re-running would yield "Unknown".
*/
@Expose()
@Transform(({ obj, value, type }) =>
type === TransformationType.PLAIN_TO_CLASS ? getFullName(obj) : value,
)
full_name!: string;
@Expose()
email!: string;
@Expose()
department!: string;
@Expose()
@Transform(({ obj, value, type }) =>
type === TransformationType.PLAIN_TO_CLASS ? getStatus(obj) : value,
)
status!: string;
@Expose()
last_active!: string;
@Expose()
progress!: number;
@Expose()
courses_completed!: number;
@Expose()
total_courses!: number;
@Expose()
current_course?: string;
// Email subscription status (optional - only included when requested)
@Expose()
email_subscription_status?: {
isUnsubscribed: boolean;
unsubscribedAt: string | null;
unsubscribedReason: string | null;
resubscribedAt: string | null;
resubscribeCount: number;
};
// === Invitation tracking fields — populated by the participants list service ===
/**
* Stage of the participant's MOST RECENTLY allocated course assignment.
* One of: PENDING_INVITE, INVITED, ACCEPTED, PRE_BAT, E_LEARNING, POST_BAT, COMPLETED.
* Drives the row's stage pill in the client portal directory.
*/
@Expose()
current_stage?: string;
/**
* True when the participant has set up a password (users.password_hash IS NOT NULL).
* Distinguishes a brand-new INVITED user from a returning user whose new course
* just sits at ACCEPTED awaiting course-acceptance.
*/
@Expose()
has_password?: boolean;
/**
* True when the most recently allocated course has reached e-Learning Done
* (status >= E_LEARNING_COMPLETED on the backend's progress timeline).
* Drives visibility of the "Allocate next course" menu item.
*/
@Expose()
eligible_for_next?: boolean;
/**
* All non-cancelled course enrollments for this participant. Populated for
* the list endpoint so the frontend can render the per-course breakdown
* inside the View Details dialog without an extra round-trip.
*/
@Expose()
enrolled_courses?: CLParticipantEnrolledCourse[];
}