File

apps/recallassess/recallassess-api/src/api/integration/integration.controller.ts

Prefix

api/integration/cr

Index

Methods

Methods

Async downloadPreBatHtml
downloadPreBatHtml(learningGroupId: string, participantId: string, reply: FastifyReply)
Decorators :
@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: undefined})
@ApiResponse({status: 401, description: 'Unauthorized - Invalid or missing API key'})
@ApiResponse({status: 404, description: 'Learning group, participant, or analysis not found'})

Download pre-BAT HTML endpoint GET /api/integration/cr/pre-bat-analysis/download

Parameters :
Name Type Optional
learningGroupId string No
participantId string No
reply FastifyReply No
Returns : Promise<void>
Async getCourses
getCourses()
Decorators :
@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: undefined})

Get list of published courses with related modules (for CodeRythm integration). GET /api/integration/cr/course This endpoint is used by external LMS integrations.

Returns : Promise<Array<literal type>>
Private Async getLearningGroupId
getLearningGroupId(courseId: number)

Helper method to get learning group ID for a course

Parameters :
Name Type Optional
courseId number No
Returns : Promise<number>
Async getPreBatAnalysisData
getPreBatAnalysisData(participantId: string, courseId: string)
Decorators :
@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'})

Get Pre-BAT Analysis data for individual report GET /api/integration/cr/pre-bat-analysis

Parameters :
Name Type Optional
participantId string No
courseId string No
Returns : Promise<any>
Async postBatAnalysis
postBatAnalysis(dto: IntegrationPostBatAnalysisDto)
Decorators :
@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: undefined})
@ApiResponse({status: 401, description: 'Unauthorized - Invalid or missing API key'})
@ApiResponse({status: 404, description: 'Learning group, participant, or course not found'})

Post-BAT Analysis endpoint (Comparative Matrix) POST /api/integration/cr/post-bat-analysis

Parameters :
Name Type Optional
dto IntegrationPostBatAnalysisDto No
Returns : Promise<literal type>
Async postBatGroupAnalysis
postBatGroupAnalysis(dto: IntegrationPostBatGroupAnalysisDto)
Decorators :
@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: undefined})
@ApiResponse({status: 401, description: 'Unauthorized - Invalid or missing API key'})
@ApiResponse({status: 404, description: 'Learning group or course not found'})

Post-BAT Group Analysis endpoint (Team Analysis - POST BAT) POST /api/integration/cr/post-bat-group-analysis

Parameters :
Name Type Optional
dto IntegrationPostBatGroupAnalysisDto No
Returns : Promise<literal type>
Async preBatAnalysis
preBatAnalysis(dto: IntegrationPreBatAnalysisDto)
Decorators :
@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: undefined})
@ApiResponse({status: 401, description: 'Unauthorized - Invalid or missing API key'})
@ApiResponse({status: 404, description: 'Learning group, participant, or course not found'})

Pre-BAT Analysis endpoint POST /api/integration/cr/pre-bat-analysis

Parameters :
Name Type Optional
dto IntegrationPreBatAnalysisDto No
Returns : Promise<literal type>
Async preBatGroupAnalysis
preBatGroupAnalysis(dto: IntegrationPreBatGroupAnalysisDto)
Decorators :
@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: undefined})
@ApiResponse({status: 401, description: 'Unauthorized - Invalid or missing API key'})
@ApiResponse({status: 404, description: 'Learning group or course not found'})

Pre-BAT Group Analysis endpoint (Team Analysis - PRE BAT) POST /api/integration/cr/pre-bat-group-analysis

Parameters :
Name Type Optional
dto IntegrationPreBatGroupAnalysisDto No
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);
  }
}

results matching ""

    No results matching ""