apps/recallassess/recallassess-api/src/api/integration/integration.controller.ts
api/integration/cr
Methods |
|
| Async downloadPreBatHtml | ||||||||||||
downloadPreBatHtml(learningGroupId: string, participantId: string, reply: FastifyReply)
|
||||||||||||
Decorators :
@Get('pre-bat-analysis/download')
|
||||||||||||
|
Download pre-BAT HTML endpoint GET /api/integration/cr/pre-bat-analysis/download
Parameters :
Returns :
Promise<void>
|
| Private Async getLearningGroupId | ||||||
getLearningGroupId(courseId: number)
|
||||||
|
Helper method to get learning group ID for a course
Parameters :
Returns :
Promise<number>
|
| Async getPreBatAnalysisData |
getPreBatAnalysisData(participantId: string, courseId: string)
|
Decorators :
@Get('pre-bat-analysis')
|
|
Get Pre-BAT Analysis data for individual report GET /api/integration/cr/pre-bat-analysis
Returns :
Promise<any>
|
| Async postBatAnalysis | ||||||
postBatAnalysis(dto: IntegrationPostBatAnalysisDto)
|
||||||
Decorators :
@Post('post-bat-analysis')
|
||||||
|
Post-BAT Analysis endpoint (Comparative Matrix) POST /api/integration/cr/post-bat-analysis
Parameters :
Returns :
Promise<literal type>
|
| Async postBatGroupAnalysis | ||||||
postBatGroupAnalysis(dto: IntegrationPostBatGroupAnalysisDto)
|
||||||
Decorators :
@Post('post-bat-group-analysis')
|
||||||
|
Post-BAT Group Analysis endpoint (Team Analysis - POST BAT) POST /api/integration/cr/post-bat-group-analysis
Parameters :
Returns :
Promise<literal type>
|
| Async preBatAnalysis | ||||||
preBatAnalysis(dto: IntegrationPreBatAnalysisDto)
|
||||||
Decorators :
@Post('pre-bat-analysis')
|
||||||
|
Pre-BAT Analysis endpoint POST /api/integration/cr/pre-bat-analysis
Parameters :
Returns :
Promise<literal type>
|
| Async preBatGroupAnalysis | ||||||
preBatGroupAnalysis(dto: IntegrationPreBatGroupAnalysisDto)
|
||||||
Decorators :
@Post('pre-bat-group-analysis')
|
||||||
|
Pre-BAT Group Analysis endpoint (Team Analysis - PRE BAT) POST /api/integration/cr/pre-bat-group-analysis
Parameters :
Returns :
Promise<literal type>
|
import { Public } from "@bish-nest/core/auth/decorator/public.decorator";
import {
Body,
Controller,
Get,
HttpCode,
HttpStatus,
NotFoundException,
Post,
Query,
Res,
UseGuards,
} from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiSecurity, ApiTags } from "@nestjs/swagger";
import { FastifyReply } from "fastify";
import {
IntegrationPostBatAnalysisDto,
IntegrationPostBatGroupAnalysisDto,
IntegrationPreBatAnalysisDto,
IntegrationPreBatGroupAnalysisDto,
} from "./dto";
import { ApiKeyGuard } from "./guards/api-key.guard";
import { IntegrationService } from "./integration.service";
@ApiTags("Integration - CodeRythm")
@ApiSecurity("ApiKey")
@Public() // Bypass JWT guard - API key guard will handle authentication
@Controller("api/integration/cr")
@UseGuards(ApiKeyGuard)
export class IntegrationController {
constructor(private readonly integrationService: IntegrationService) {}
/**
* Get Pre-BAT Analysis data for individual report
* GET /api/integration/cr/pre-bat-analysis
*/
@Get("pre-bat-analysis")
@UseGuards(ApiKeyGuard)
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Get pre-BAT analysis data for individual participant report" })
@ApiResponse({
status: 200,
description: "Pre-BAT analysis data returned successfully",
})
@ApiResponse({ status: 401, description: "Unauthorized - Invalid or missing API key" })
@ApiResponse({ status: 404, description: "Learning group, participant, or analysis not found" })
async getPreBatAnalysisData(
@Query("participant_id") participantId: string,
@Query("course_id") courseId: string,
): Promise<any> {
const participantIdNum = parseInt(participantId, 10);
const courseIdNum = parseInt(courseId, 10);
const learningGroupId = await this.getLearningGroupId(courseIdNum);
const course = await this.integrationService.getCourseForLearningGroup(learningGroupId);
const reportDataRaw = await this.integrationService.getPreBatAnalysisData(
learningGroupId,
participantIdNum,
course,
);
// Parse JSON strings to actual arrays/objects for frontend
const skillsParsed = JSON.parse(reportDataRaw.skills);
const preTrainingResultsParsed = JSON.parse(reportDataRaw.preTrainingResults);
return {
courseTitle: reportDataRaw.courseTitle,
participantName: reportDataRaw.participantName,
skills: skillsParsed,
ipq: reportDataRaw.ipq,
preTrainingResults: preTrainingResultsParsed,
preReport: reportDataRaw.preReport,
};
}
/**
* Pre-BAT Analysis endpoint
* POST /api/integration/cr/pre-bat-analysis
*/
@Post("pre-bat-analysis")
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Submit pre-BAT analysis for a participant" })
@ApiResponse({
status: 200,
description: "Pre-BAT analysis processed successfully",
schema: {
type: "object",
properties: {
success: { type: "boolean", example: true },
message: { type: "string", example: "Pre-BAT analysis processed successfully" },
},
},
})
@ApiResponse({ status: 401, description: "Unauthorized - Invalid or missing API key" })
@ApiResponse({ status: 404, description: "Learning group, participant, or course not found" })
async preBatAnalysis(@Body() dto: IntegrationPreBatAnalysisDto): Promise<{ success: boolean; message: string }> {
return this.integrationService.handlePreBatAnalysis(dto);
}
/**
* Post-BAT Analysis endpoint (Comparative Matrix)
* POST /api/integration/cr/post-bat-analysis
*/
@Post("post-bat-analysis")
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Submit post-BAT analysis (comparative matrix) for a participant" })
@ApiResponse({
status: 200,
description: "Post-BAT analysis processed successfully",
schema: {
type: "object",
properties: {
success: { type: "boolean", example: true },
message: { type: "string", example: "Post-BAT analysis (comparative matrix) processed successfully" },
},
},
})
@ApiResponse({ status: 401, description: "Unauthorized - Invalid or missing API key" })
@ApiResponse({ status: 404, description: "Learning group, participant, or course not found" })
async postBatAnalysis(
@Body() dto: IntegrationPostBatAnalysisDto,
): Promise<{ success: boolean; message: string }> {
return this.integrationService.handlePostBatAnalysis(dto);
}
/**
* Pre-BAT Group Analysis endpoint (Team Analysis - PRE BAT)
* POST /api/integration/cr/pre-bat-group-analysis
*/
@Post("pre-bat-group-analysis")
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Submit pre-BAT group analysis (team analysis - PRE BAT)" })
@ApiResponse({
status: 200,
description: "Pre-BAT group analysis processed successfully",
schema: {
type: "object",
properties: {
success: { type: "boolean", example: true },
message: { type: "string", example: "Pre-BAT group analysis (team analysis) processed successfully" },
},
},
})
@ApiResponse({ status: 401, description: "Unauthorized - Invalid or missing API key" })
@ApiResponse({ status: 404, description: "Learning group or course not found" })
async preBatGroupAnalysis(
@Body() dto: IntegrationPreBatGroupAnalysisDto,
): Promise<{ success: boolean; message: string }> {
return this.integrationService.handlePreBatGroupAnalysis(dto);
}
/**
* Post-BAT Group Analysis endpoint (Team Analysis - POST BAT)
* POST /api/integration/cr/post-bat-group-analysis
*/
@Post("post-bat-group-analysis")
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Submit post-BAT group analysis (team analysis - POST BAT)" })
@ApiResponse({
status: 200,
description: "Post-BAT group analysis processed successfully",
schema: {
type: "object",
properties: {
success: { type: "boolean", example: true },
message: { type: "string", example: "Post-BAT group analysis (team analysis) processed successfully" },
},
},
})
@ApiResponse({ status: 401, description: "Unauthorized - Invalid or missing API key" })
@ApiResponse({ status: 404, description: "Learning group or course not found" })
async postBatGroupAnalysis(
@Body() dto: IntegrationPostBatGroupAnalysisDto,
): Promise<{ success: boolean; message: string }> {
return this.integrationService.handlePostBatGroupAnalysis(dto);
}
/**
* Get list of published courses with related modules (for CodeRythm integration).
* GET /api/integration/cr/course
* This endpoint is used by external LMS integrations.
*/
@Get("course")
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Get list of published courses (code + title + modules)" })
@ApiResponse({
status: 200,
description: "Returns list of published courses with related modules.",
schema: {
type: "array",
items: {
type: "object",
properties: {
course_id: { type: "integer", example: 1 },
course_code: { type: "string", example: "COURSE_LEADERSHIP_101" },
course_title: { type: "string", example: "Leadership Foundations" },
modules: {
type: "array",
items: {
type: "object",
properties: {
module_id: { type: "integer", example: 1 },
module_code: { type: "string", example: "TSN01" },
module_title: { type: "string", example: "Negotiation Formats" },
},
},
},
},
},
},
})
async getCourses(): Promise<
Array<{
course_id: number;
course_code: string;
course_title: string;
modules: Array<{ module_id: number; module_code: string; module_title: string }>;
}>
> {
return this.integrationService.getCoursesForIntegration();
}
/**
* Download pre-BAT HTML endpoint
* GET /api/integration/cr/pre-bat-analysis/download
*/
@Get("pre-bat-analysis/download")
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: "Download pre-BAT analysis HTML for a participant" })
@ApiResponse({
status: 200,
description: "HTML content returned successfully",
content: {
"text/html": {
schema: {
type: "string",
},
},
},
})
@ApiResponse({ status: 401, description: "Unauthorized - Invalid or missing API key" })
@ApiResponse({ status: 404, description: "Learning group, participant, or analysis not found" })
async downloadPreBatHtml(
@Query("learning_group_id") learningGroupId: string,
@Query("participant_id") participantId: string,
@Res() reply: FastifyReply,
): Promise<void> {
const lgId = Number.parseInt(learningGroupId, 10);
const pId = Number.parseInt(participantId, 10);
// Generate fresh PDF instead of HTML
const course = await this.integrationService.getCourseForLearningGroup(lgId);
const pdfBuffer = await this.integrationService.generatePreBatPdfDirect(lgId, pId, course);
reply.header("Content-Type", "application/pdf");
reply.header("Content-Disposition", `attachment; filename="Pre-BAT-Report-${pId}.pdf"`);
reply.send(pdfBuffer);
}
/**
* Helper method to get learning group ID for a course
*/
private async getLearningGroupId(courseId: number): Promise<number> {
return this.integrationService.getLearningGroupIdForCourse(courseId);
}
}