feature: Phase3 - Task templates + generation on send
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
ArrayMinSize,
|
||||
IsArray,
|
||||
IsIn,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUUID,
|
||||
@@ -10,8 +9,6 @@ import {
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
const TREATMENT_TYPES = ['consultation', 'filling', 'endo', 'visit', 'hygiene'] as const;
|
||||
|
||||
export class SaveTreatmentDetailDto {
|
||||
@IsString()
|
||||
@MaxLength(64)
|
||||
@@ -21,7 +18,8 @@ export class SaveTreatmentDetailDto {
|
||||
@IsUUID()
|
||||
id?: string;
|
||||
|
||||
@IsIn(TREATMENT_TYPES)
|
||||
@IsString()
|
||||
@MaxLength(64)
|
||||
treatmentType: string;
|
||||
|
||||
@IsArray()
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import { TreatmentStatus } from '@prisma/client';
|
||||
|
||||
const TREATMENT_TYPES = ['consultation', 'filling', 'endo', 'visit', 'hygiene'] as const;
|
||||
|
||||
export type TreatmentTypeValue = (typeof TREATMENT_TYPES)[number];
|
||||
|
||||
export function isTreatmentType(value: string): value is TreatmentTypeValue {
|
||||
return (TREATMENT_TYPES as readonly string[]).includes(value);
|
||||
}
|
||||
|
||||
const FDI_TOOTH_IDS = new Set([
|
||||
'11', '12', '13', '14', '15', '16', '17', '18',
|
||||
'21', '22', '23', '24', '25', '26', '27', '28',
|
||||
|
||||
@@ -9,13 +9,14 @@ import { createReadStream, existsSync, mkdirSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { PrismaService } from '../../../prisma/prisma.service';
|
||||
import { generateLabCaseTasks } from '../cases/lab-case-task.generator';
|
||||
import { TreatmentCatalogService } from '../treatment-catalog/treatment-catalog.service';
|
||||
import {
|
||||
SaveTreatmentDraftDto,
|
||||
SaveTreatmentLabCasesDto,
|
||||
} from './dto/treatment.dto';
|
||||
import {
|
||||
generateTreatmentTitle,
|
||||
isTreatmentType,
|
||||
mapTreatmentStatusForApi,
|
||||
normalizeTeeth,
|
||||
} from './treatment.utils';
|
||||
@@ -61,7 +62,10 @@ const treatmentInclude = {
|
||||
export class TreatmentsService {
|
||||
private readonly uploadRoot = join(process.cwd(), 'uploads', 'treatments');
|
||||
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly treatmentCatalog: TreatmentCatalogService,
|
||||
) {}
|
||||
|
||||
getOrganizationIdFromUser(user: { organizationId?: string }) {
|
||||
if (!user?.organizationId) {
|
||||
@@ -163,9 +167,7 @@ export class TreatmentsService {
|
||||
);
|
||||
|
||||
for (const d of dto.details) {
|
||||
if (!isTreatmentType(d.treatmentType)) {
|
||||
throw new BadRequestException(`Invalid treatment type: ${d.treatmentType}`);
|
||||
}
|
||||
this.treatmentCatalog.assertKnownTreatmentType(d.treatmentType);
|
||||
}
|
||||
|
||||
const normalizedDetails = dto.details.map((d, index) => ({
|
||||
@@ -328,12 +330,16 @@ export class TreatmentsService {
|
||||
|
||||
const details = await this.prisma.treatmentDetail.findMany({
|
||||
where: { treatmentId: treatment.id, id: { in: detailIds } },
|
||||
select: { id: true },
|
||||
select: { id: true, treatmentType: true },
|
||||
});
|
||||
if (details.length !== uniqueDetailIds.size) {
|
||||
throw new BadRequestException('One or more treatment details were not found');
|
||||
}
|
||||
|
||||
for (const detail of details) {
|
||||
this.treatmentCatalog.assertLabDependentTreatmentType(detail.treatmentType);
|
||||
}
|
||||
|
||||
const linkedOrgIds = await this.getActiveLinkedOrganizationIds(organizationId);
|
||||
|
||||
for (const lc of dto.labCases) {
|
||||
@@ -470,6 +476,8 @@ export class TreatmentsService {
|
||||
data: { sentAt: now },
|
||||
});
|
||||
}
|
||||
|
||||
await generateLabCaseTasks(tx, labCaseId);
|
||||
});
|
||||
|
||||
const refreshed = await this.prisma.labCase.findUniqueOrThrow({
|
||||
|
||||
Reference in New Issue
Block a user