apps/recallassess/recallassess-api/src/api/client/reports/learning-group-reports.controller.ts
api/client/reports/learning-group
| Async acceptCourseInvitationForReports | |||||||||
acceptCourseInvitationForReports(learningGroupParticipantId: number, auth: CLAuthData)
|
|||||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
|||||||||
|
Accept course invitation - reports alias POST /api/client/reports/learning-group/accept-invitation/:learningGroupParticipantId
Parameters :
Returns :
Promise<literal type>
|
| Async createLearningGroupForReports | |||||||||
createLearningGroupForReports(dto: AddLearningGroupDto, auth: CLAuthData)
|
|||||||||
Decorators :
@HttpCode(HttpStatus.CREATED)
|
|||||||||
|
Create a new learning group (license allocation) - reports alias POST /api/client/reports/learning-group
Parameters :
Returns :
Promise<CLLearningGroupDto>
|
| Async getAllAllocatedParticipantsForReports | ||||||
getAllAllocatedParticipantsForReports(auth: CLAuthData)
|
||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
||||||
|
Get all participants already allocated to any course (reports namespace) GET /api/client/reports/learning-group/allocated-participants
Parameters :
Returns :
Promise<literal type>
|
| Async getAllLearningGroupsForReports | |||||||||
getAllLearningGroupsForReports(query: LearningGroupQueryDto, auth: CLAuthData)
|
|||||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
|||||||||
|
Get all learning groups (license allocations) for reporting with optional filtering and pagination GET /api/client/reports/learning-group?page=1&limit=20&sq=sales&status=active
Parameters :
Returns :
Promise<CLLearningGroupListResponse>
|
| Async getAllocatedParticipantsForReports | |||||||||
getAllocatedParticipantsForReports(courseId: number, auth: CLAuthData)
|
|||||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
|||||||||
|
Get participants already allocated to a specific course (reports namespace) GET /api/client/reports/learning-group/course/:courseId/allocated-participants
Parameters :
Returns :
Promise<literal type>
|
| Async getCourseLicenseUtilizationForReports | ||||||
getCourseLicenseUtilizationForReports(auth: CLAuthData)
|
||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
||||||
|
Get course license utilization data (reports namespace) GET /api/client/reports/learning-group/course-license-utilization
Parameters :
|
| Async getLearningGroupDetailForReports | |||||||||
getLearningGroupDetailForReports(id: number, auth: CLAuthData)
|
|||||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
|||||||||
|
Get a single learning group (license allocation) detail with participants - reports alias GET /api/client/reports/learning-group/:id
Parameters :
Returns :
Promise<unknown>
|
| Async getLicenseInfoForReports | ||||||
getLicenseInfoForReports(auth: CLAuthData)
|
||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
||||||
|
Get license information for the company (reports namespace) GET /api/client/reports/learning-group/licenses/info
Parameters :
Returns :
Promise<literal type>
|
| Async getSubscriptionBillingInfoForReports | ||||||
getSubscriptionBillingInfoForReports(auth: CLAuthData)
|
||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
||||||
|
Get subscription billing information for the company (reports namespace) GET /api/client/reports/learning-group/subscription/billing
Parameters :
Returns :
Promise<literal type>
|
| Async resendInvitationForReports | ||||||||||||
resendInvitationForReports(id: number, participantId: number, auth: CLAuthData)
|
||||||||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
||||||||||||
|
Resend invitation to a specific participant - reports alias POST /api/client/reports/learning-group/:id/resend-invitation/:participantId
Parameters :
Returns :
Promise<literal type>
|
| Async sendInvitationsToAllForReports | |||||||||
sendInvitationsToAllForReports(id: number, auth: CLAuthData)
|
|||||||||
Decorators :
@HttpCode(HttpStatus.OK)
|
|||||||||
|
Send invitations to all participants in a learning group - reports alias POST /api/client/reports/learning-group/:id/send-invitations
Parameters :
Returns :
Promise<literal type>
|
import { CLAuthData, ClientAuth } from "@api/shared/decorators";
import {
Body,
Controller,
Get,
HttpCode,
HttpStatus,
Param,
ParseIntPipe,
Post,
Query,
} from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import {
AddLearningGroupDto,
CLLearningGroupDto,
CLLearningGroupListResponse,
CourseLicenseUtilizationRowDto,
LearningGroupQueryDto,
} from "../learning-group/dto";
import { CLLearningGroupService } from "../learning-group/learning-group.service";
@ApiTags("Client - Reports - Learning Groups (License Allocations)")
@Controller("api/client/reports/learning-group")
export class CLLearningGroupReportsController {
constructor(private learningGroupService: CLLearningGroupService) {}
/**
* Get all learning groups (license allocations) for reporting with optional filtering and pagination
* GET /api/client/reports/learning-group?page=1&limit=20&sq=sales&status=active
*/
@HttpCode(HttpStatus.OK)
@Get()
@ApiOperation({
summary: "Get all learning groups for reports with pagination, search and filters",
description:
"Returns paginated learning groups filtered by search query and status with metadata, under the reports namespace",
})
@ApiResponse({
status: 200,
description:
"Returns paginated list of learning groups with metadata (page, limit, totalCount, totalPages, etc.)",
})
async getAllLearningGroupsForReports(
@Query() query: LearningGroupQueryDto,
@ClientAuth() auth: CLAuthData,
): Promise<CLLearningGroupListResponse> {
return this.learningGroupService.getFilteredLearningGroups(
auth.companyId,
query.page || 1,
query.limit || 20,
query.sq,
query.status,
);
}
/**
* Get license information for the company (reports namespace)
* GET /api/client/reports/learning-group/licenses/info
*/
@HttpCode(HttpStatus.OK)
@Get("licenses/info")
@ApiOperation({
summary: "Get license information (reports)",
description:
"Returns license information including total, available, consumed, and allocated licenses under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Returns license information",
})
async getLicenseInfoForReports(@ClientAuth() auth: CLAuthData): Promise<{
total: number;
available: number;
consumed: number;
allocated: number;
inTraining: number;
}> {
return this.learningGroupService.getLicenseInfo(auth.companyId);
}
/**
* Get subscription billing information for the company (reports namespace)
* GET /api/client/reports/learning-group/subscription/billing
*/
@HttpCode(HttpStatus.OK)
@Get("subscription/billing")
@ApiOperation({
summary: "Get subscription billing information (reports)",
description:
"Returns subscription billing info including monthly total and next renewal date under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Returns subscription billing information",
})
async getSubscriptionBillingInfoForReports(@ClientAuth() auth: CLAuthData): Promise<{
monthlyTotal: number;
nextRenewalDate: string | null;
licenseCount: number;
pricePerLicense: number | null;
packageName: string | null;
}> {
return this.learningGroupService.getSubscriptionBillingInfo(auth.companyId);
}
/**
* Get course license utilization data (reports namespace)
* GET /api/client/reports/learning-group/course-license-utilization
*/
@HttpCode(HttpStatus.OK)
@Get("course-license-utilization")
@ApiOperation({
summary: "Get course license utilization data (reports)",
description:
"Returns license utilization data per course including total allocated, used, available, and utilization percentage under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Returns array of course license utilization data",
type: CourseLicenseUtilizationRowDto,
isArray: true,
})
async getCourseLicenseUtilizationForReports(
@ClientAuth() auth: CLAuthData,
): Promise<CourseLicenseUtilizationRowDto[]> {
return this.learningGroupService.getCourseLicenseUtilization(auth.companyId);
}
/**
* Get participants already allocated to a specific course (reports namespace)
* GET /api/client/reports/learning-group/course/:courseId/allocated-participants
*/
@HttpCode(HttpStatus.OK)
@Get("course/:courseId/allocated-participants")
@ApiOperation({
summary: "Get participants already allocated to a course (reports)",
description:
"Returns list of participants with completion status that are already allocated to the specified course under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Returns array of participants with completion status",
})
async getAllocatedParticipantsForReports(
@Param("courseId", ParseIntPipe) courseId: number,
@ClientAuth() auth: CLAuthData,
): Promise<{
participants: Array<{
participantId: number;
participantName: string;
participantEmail: string;
isCompleted: boolean;
}>;
}> {
return this.learningGroupService.getAllocatedParticipantsForCourse(auth.companyId, courseId);
}
/**
* Get all participants already allocated to any course (reports namespace)
* GET /api/client/reports/learning-group/allocated-participants
*/
@HttpCode(HttpStatus.OK)
@Get("allocated-participants")
@ApiOperation({
summary: "Get all participants already allocated to any course (reports)",
description:
"Returns list of participants with their completion status that are already allocated to any course under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Returns array of participants with completion status",
})
async getAllAllocatedParticipantsForReports(
@ClientAuth() auth: CLAuthData,
): Promise<{
participants: Array<{
participantId: number;
isCompleted: boolean;
courseId: number;
courseName: string;
}>;
}> {
return this.learningGroupService.getAllAllocatedParticipants(auth.companyId);
}
/**
* Create a new learning group (license allocation) - reports alias
* POST /api/client/reports/learning-group
*/
@HttpCode(HttpStatus.CREATED)
@Post()
@ApiOperation({
summary: "Add a new learning group (license allocation) via reports alias",
description:
"Adds a learning group with assigned course and participants. This allocates licenses to the selected participants for the specified course.",
})
@ApiResponse({
status: 201,
description: "Learning group added successfully",
type: CLLearningGroupDto,
})
@ApiResponse({
status: 400,
description: "Invalid input data or participants not found",
})
async createLearningGroupForReports(
@Body() dto: AddLearningGroupDto,
@ClientAuth() auth: CLAuthData,
): Promise<CLLearningGroupDto> {
return this.learningGroupService.createLearningGroup(auth.companyId, auth.participantId, dto);
}
/**
* Get a single learning group (license allocation) detail with participants - reports alias
* GET /api/client/reports/learning-group/:id
*/
@HttpCode(HttpStatus.OK)
@Get(":id")
@ApiOperation({
summary: "Get learning group detail with participants (reports)",
description: "Returns a single learning group with all participant details under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Returns learning group detail with participants",
})
@ApiResponse({
status: 400,
description: "Learning group not found",
})
async getLearningGroupDetailForReports(
@Param("id", ParseIntPipe) id: number,
@ClientAuth() auth: CLAuthData,
): Promise<import("../learning-group/dto").CLLearningGroupDetailDto> {
const { CLLearningGroupDetailDto } = await import("../learning-group/dto");
return this.learningGroupService.getLearningGroupDetail(auth.companyId, id);
}
/**
* Send invitations to all participants in a learning group - reports alias
* POST /api/client/reports/learning-group/:id/send-invitations
*/
@HttpCode(HttpStatus.OK)
@Post(":id/send-invitations")
@ApiOperation({
summary: "Send invitations to all participants in a learning group (reports)",
description:
"Sends invitation emails to all participants with INVITED status in the learning group under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Invitations sent successfully",
})
@ApiResponse({
status: 400,
description: "Learning group not found or not in PENDING status",
})
async sendInvitationsToAllForReports(
@Param("id", ParseIntPipe) id: number,
@ClientAuth() auth: CLAuthData,
): Promise<{ message: string; invitationsSent: number }> {
return this.learningGroupService.sendInvitationsToAll(auth.companyId, id, auth.participantId);
}
/**
* Resend invitation to a specific participant - reports alias
* POST /api/client/reports/learning-group/:id/resend-invitation/:participantId
*/
@HttpCode(HttpStatus.OK)
@Post(":id/resend-invitation/:participantId")
@ApiOperation({
summary: "Resend invitation to a specific participant (reports)",
description: "Resends invitation email to a specific participant in the learning group under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Invitation resent successfully",
})
@ApiResponse({
status: 400,
description: "Participant not found or not in INVITED status",
})
async resendInvitationForReports(
@Param("id", ParseIntPipe) id: number,
@Param("participantId", ParseIntPipe) participantId: number,
@ClientAuth() auth: CLAuthData,
): Promise<{ message: string }> {
return this.learningGroupService.resendInvitation(auth.companyId, id, participantId, auth.participantId);
}
/**
* Accept course invitation - reports alias
* POST /api/client/reports/learning-group/accept-invitation/:learningGroupParticipantId
*/
@HttpCode(HttpStatus.OK)
@Post("accept-invitation/:learningGroupParticipantId")
@ApiOperation({
summary: "Accept course invitation (reports)",
description: "Accepts a course invitation for the current participant under the reports namespace",
})
@ApiResponse({
status: 200,
description: "Course invitation accepted successfully",
})
@ApiResponse({
status: 400,
description: "Course invitation not found or password not set",
})
async acceptCourseInvitationForReports(
@Param("learningGroupParticipantId", ParseIntPipe) learningGroupParticipantId: number,
@ClientAuth() auth: CLAuthData,
): Promise<{ success: boolean; message: string }> {
return this.learningGroupService.acceptCourseInvitation(auth.participantId, learningGroupParticipantId);
}
}