improvement: pdf generation added to cases feature.
This commit is contained in:
@@ -14,7 +14,7 @@ import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { LabOrgGuard } from '../../common/guards/lab-org.guard';
|
||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
||||
import { CasesService } from './cases.service';
|
||||
import { ListLabCasesDto, UpdateLabCaseImportantDto, AssignLabCaseTaskDto } from './dto/cases.dto';
|
||||
import { ListLabCasesDto, UpdateLabCaseImportantDto, UpdateLabCaseExternalCodeDto, AssignLabCaseTaskDto } from './dto/cases.dto';
|
||||
|
||||
@ApiTags('cases')
|
||||
@ApiBearerAuth('JWT-auth')
|
||||
@@ -82,6 +82,17 @@ export class CasesController {
|
||||
return this.casesService.setCaseImportant(id, dto, organizationId, req.user.id, req.user.language);
|
||||
}
|
||||
|
||||
@Patch(':id/external-code')
|
||||
@ApiOperation({ summary: 'Set or clear the optional external order code for a case' })
|
||||
setCaseExternalCode(
|
||||
@Param('id') id: string,
|
||||
@Body() dto: UpdateLabCaseExternalCodeDto,
|
||||
@Req() req,
|
||||
) {
|
||||
const organizationId = this.casesService.getOrganizationIdFromUser(req.user);
|
||||
return this.casesService.setCaseExternalCode(id, dto, organizationId, req.user.id, req.user.language);
|
||||
}
|
||||
|
||||
@Patch(':caseId/tasks/:taskId/assign')
|
||||
@ApiOperation({ summary: 'Assign or unassign a task to lab staff' })
|
||||
assignTask(
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from '../catalog/catalog-label.service';
|
||||
import { ProsthesisCatalogService } from '../prosthesis-catalog/prosthesis-catalog.service';
|
||||
import { normalizeTeeth } from '../treatments/treatment.utils';
|
||||
import { ListLabCasesDto, UpdateLabCaseImportantDto, AssignLabCaseTaskDto } from './dto/cases.dto';
|
||||
import { ListLabCasesDto, UpdateLabCaseImportantDto, UpdateLabCaseExternalCodeDto, AssignLabCaseTaskDto } from './dto/cases.dto';
|
||||
import {
|
||||
isLabCaseOverdue,
|
||||
} from '../../common/lab-case-due-date';
|
||||
@@ -131,7 +131,15 @@ export class CasesService {
|
||||
patient: { select: { id: true, firstName: true, lastName: true, mobile: true } },
|
||||
},
|
||||
},
|
||||
tasks: { select: { id: true, status: true, prosthesisTypeCode: true, teeth: true } },
|
||||
tasks: {
|
||||
select: {
|
||||
id: true,
|
||||
status: true,
|
||||
prosthesisTypeCode: true,
|
||||
teeth: true,
|
||||
selectionGroupId: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: [{ sentAt: 'desc' }],
|
||||
skip,
|
||||
@@ -244,7 +252,15 @@ export class CasesService {
|
||||
patient: { select: { id: true, firstName: true, lastName: true, mobile: true } },
|
||||
},
|
||||
},
|
||||
tasks: { select: { id: true, status: true, prosthesisTypeCode: true, teeth: true } },
|
||||
tasks: {
|
||||
select: {
|
||||
id: true,
|
||||
status: true,
|
||||
prosthesisTypeCode: true,
|
||||
teeth: true,
|
||||
selectionGroupId: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: [{ sentAt: 'desc' }],
|
||||
skip,
|
||||
@@ -405,6 +421,46 @@ export class CasesService {
|
||||
return { success: true, data: await this.mapLabCaseDetail(labCase, localeInput) };
|
||||
}
|
||||
|
||||
async setCaseExternalCode(
|
||||
labCaseId: string,
|
||||
dto: UpdateLabCaseExternalCodeDto,
|
||||
labOrganizationId: string,
|
||||
actorUserId: string,
|
||||
localeInput?: string | null,
|
||||
) {
|
||||
await this.assertCanEditCases(actorUserId, labOrganizationId);
|
||||
|
||||
const existing = await this.prisma.labCase.findFirst({
|
||||
where: {
|
||||
id: labCaseId,
|
||||
sentAt: { not: null },
|
||||
sends: { some: { organizationId: labOrganizationId } },
|
||||
},
|
||||
select: { id: true },
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
throw new NotFoundException('Case not found');
|
||||
}
|
||||
|
||||
const externalCode =
|
||||
dto.externalCode == null || !String(dto.externalCode).trim()
|
||||
? null
|
||||
: String(dto.externalCode).trim().slice(0, 64);
|
||||
|
||||
await this.prisma.labCase.update({
|
||||
where: { id: labCaseId },
|
||||
data: { externalCode },
|
||||
});
|
||||
|
||||
const labCase = await this.prisma.labCase.findFirstOrThrow({
|
||||
where: { id: labCaseId },
|
||||
include: labCaseListInclude,
|
||||
});
|
||||
|
||||
return { success: true, data: await this.mapLabCaseDetail(labCase, localeInput) };
|
||||
}
|
||||
|
||||
async listAssignableStaff(labOrganizationId: string, actorUserId: string) {
|
||||
await this.assertCanEditCases(actorUserId, labOrganizationId);
|
||||
|
||||
@@ -648,6 +704,7 @@ export class CasesService {
|
||||
dueDate: lc.dueDate?.toISOString() ?? null,
|
||||
isOverdue: isLabCaseOverdue(lc.dueDate, lc.tasks),
|
||||
isImportant: lc.isImportant,
|
||||
externalCode: lc.externalCode ?? null,
|
||||
shareUrl,
|
||||
clinic: lc.treatment.organization,
|
||||
patient: lc.treatment.patient,
|
||||
@@ -665,6 +722,7 @@ export class CasesService {
|
||||
treatmentDetailId: row.treatmentDetailId,
|
||||
tooth: row.tooth,
|
||||
prosthesisTypeCode: row.prosthesisTypeCode,
|
||||
selectionGroupId: row.selectionGroupId?.trim() || undefined,
|
||||
})),
|
||||
attachments: lc.attachments.map((row) => ({
|
||||
id: row.attachment.id,
|
||||
@@ -764,7 +822,16 @@ export class CasesService {
|
||||
groups.set(key, entry);
|
||||
}
|
||||
|
||||
return [...groups.values()];
|
||||
return [...groups.values()].map((group) => ({
|
||||
treatmentDetailId: group.treatmentDetailId,
|
||||
teeth: [...new Set(group.teeth)],
|
||||
treatmentType: group.treatmentType,
|
||||
prosthesisTypeCode: group.prosthesisTypeCode,
|
||||
prosthesisTypeLabel: group.prosthesisTypeLabel,
|
||||
selectionGroupId: group.selectionGroupId || undefined,
|
||||
connected: Boolean(group.selectionGroupId) && [...new Set(group.teeth)].length > 1,
|
||||
tasks: group.tasks,
|
||||
}));
|
||||
}
|
||||
|
||||
private mapTask(
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsDateString, IsInt, IsOptional, IsString, IsUUID, Max, Min } from 'class-validator';
|
||||
import { IsBoolean, IsDateString, IsInt, IsOptional, IsString, IsUUID, Max, MaxLength, Min } from 'class-validator';
|
||||
|
||||
export class UpdateLabCaseImportantDto {
|
||||
@IsBoolean()
|
||||
isImportant: boolean;
|
||||
}
|
||||
|
||||
export class UpdateLabCaseExternalCodeDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(64)
|
||||
externalCode?: string | null;
|
||||
}
|
||||
|
||||
export class AssignLabCaseTaskDto {
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
|
||||
Reference in New Issue
Block a user