import { Body, Controller, Get, Param, ParseIntPipe, Post, Put, Query, Req, Res, UploadedFiles, UseGuards, UseInterceptors, } from '@nestjs/common'; import { FilesInterceptor } from '@nestjs/platform-express'; import { ApiBearerAuth, ApiBody, ApiConsumes, ApiOperation, ApiTags } from '@nestjs/swagger'; import { memoryStorage } from 'multer'; import type { Response } from 'express'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { SaveTreatmentDraftDto, SendTreatmentCaseDto } from './dto/treatment.dto'; import { TreatmentsService } from './treatments.service'; @ApiTags('treatments') @ApiBearerAuth('JWT-auth') @UseGuards(JwtAuthGuard) @Controller('treatments') export class TreatmentsController { constructor(private readonly treatmentsService: TreatmentsService) {} @Get('linked-organizations') @ApiOperation({ summary: 'List active linked counterpart organizations (TAB_TREATMENT_READ)' }) listLinkedOrganizations(@Req() req: { user: { id: string; organizationId?: string } }) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); return this.treatmentsService.listLinkedOrganizations(req.user.id, organizationId); } @Get('patients/:patientId/history') @ApiOperation({ summary: 'List completed treatments for a patient (TAB_TREATMENT_READ)' }) listPatientHistory( @Param('patientId') patientId: string, @Query('limit', new ParseIntPipe({ optional: true })) limit = 20, @Req() req: { user: { id: string; organizationId?: string } }, ) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); return this.treatmentsService.listPatientHistory( patientId, organizationId, req.user.id, limit, ); } @Get('appointments/:appointmentId/draft') @ApiOperation({ summary: 'Get draft treatment for an appointment (TAB_TREATMENT_READ)' }) getDraft( @Param('appointmentId') appointmentId: string, @Req() req: { user: { id: string; organizationId?: string } }, ) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); return this.treatmentsService.getDraftForAppointment( appointmentId, organizationId, req.user.id, ); } @Put('appointments/:appointmentId/draft') @ApiOperation({ summary: 'Save draft treatment for an appointment (TAB_TREATMENT_EDIT)' }) saveDraft( @Param('appointmentId') appointmentId: string, @Body() dto: SaveTreatmentDraftDto, @Req() req: { user: { id: string; organizationId?: string } }, ) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); return this.treatmentsService.saveDraftForAppointment( appointmentId, dto, organizationId, req.user.id, ); } @Post('appointments/:appointmentId/cases/:caseClientKey/attachments') @ApiOperation({ summary: 'Upload attachments for a draft case (TAB_TREATMENT_EDIT)' }) @ApiConsumes('multipart/form-data') @ApiBody({ schema: { type: 'object', properties: { files: { type: 'array', items: { type: 'string', format: 'binary' }, }, }, }, }) @UseInterceptors( FilesInterceptor('files', 20, { storage: memoryStorage(), }), ) uploadAttachments( @Param('appointmentId') appointmentId: string, @Param('caseClientKey') caseClientKey: string, @UploadedFiles() files: Express.Multer.File[], @Req() req: { user: { id: string; organizationId?: string } }, ) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); return this.treatmentsService.uploadCaseAttachments( appointmentId, caseClientKey, files, organizationId, req.user.id, ); } @Get('attachments/:attachmentId/file') @ApiOperation({ summary: 'Download a treatment attachment (TAB_TREATMENT_READ)' }) async downloadAttachment( @Param('attachmentId') attachmentId: string, @Req() req: { user: { id: string; organizationId?: string } }, @Res() res: Response, ) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); const file = await this.treatmentsService.streamAttachmentFile( attachmentId, organizationId, req.user.id, ); res.setHeader('Content-Type', file.mimeType); res.setHeader('Content-Disposition', `inline; filename="${file.fileName}"`); file.stream.pipe(res); } @Post('cases/:caseId/send') @ApiOperation({ summary: 'Send a treatment case to linked organizations (TAB_TREATMENT_EDIT)' }) sendCase( @Param('caseId') caseId: string, @Body() dto: SendTreatmentCaseDto, @Req() req: { user: { id: string; organizationId?: string } }, ) { const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user); return this.treatmentsService.sendCase(caseId, dto, organizationId, req.user.id); } }