Files
dyolink/backend/src/modules/treatments/treatments.controller.ts

193 lines
6.4 KiB
TypeScript

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 { ClinicOrgGuard } from '../../common/guards/clinic-org.guard';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import {
SaveTreatmentDraftDto,
SaveTreatmentLabCasesDto,
} from './dto/treatment.dto';
import { TreatmentsService } from './treatments.service';
@ApiTags('treatments')
@ApiBearerAuth('JWT-auth')
@UseGuards(JwtAuthGuard, ClinicOrgGuard)
@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 details 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,
);
}
@Put('appointments/:appointmentId/lab-cases')
@ApiOperation({ summary: 'Save lab case groupings for a draft treatment (TAB_TREATMENT_EDIT)' })
saveLabCases(
@Param('appointmentId') appointmentId: string,
@Body() dto: SaveTreatmentLabCasesDto,
@Req() req: { user: { id: string; organizationId?: string } },
) {
const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user);
return this.treatmentsService.saveLabCasesForAppointment(
appointmentId,
dto,
organizationId,
req.user.id,
);
}
@Post('appointments/:appointmentId/details/:detailClientKey/attachments')
@ApiOperation({ summary: 'Upload attachments for a draft treatment detail (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(),
}),
)
uploadDetailAttachments(
@Param('appointmentId') appointmentId: string,
@Param('detailClientKey') detailClientKey: string,
@UploadedFiles() files: Express.Multer.File[],
@Req() req: { user: { id: string; organizationId?: string } },
) {
const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user);
return this.treatmentsService.uploadDetailAttachments(
appointmentId,
detailClientKey,
files,
organizationId,
req.user.id,
);
}
/** @deprecated Use details/:detailClientKey/attachments */
@Post('appointments/:appointmentId/cases/:caseClientKey/attachments')
@ApiOperation({ summary: 'Legacy alias for detail attachment upload' })
@ApiConsumes('multipart/form-data')
@UseInterceptors(
FilesInterceptor('files', 20, {
storage: memoryStorage(),
}),
)
uploadDetailAttachmentsLegacy(
@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.uploadDetailAttachments(
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('lab-cases/:labCaseId/send')
@ApiOperation({ summary: 'Send a lab case to its destination organization (TAB_TREATMENT_EDIT)' })
sendLabCase(
@Param('labCaseId') labCaseId: string,
@Req() req: { user: { id: string; organizationId?: string } },
) {
const organizationId = this.treatmentsService.getOrganizationIdFromUser(req.user);
return this.treatmentsService.sendLabCase(labCaseId, organizationId, req.user.id);
}
}