TreatmentType and ProsthesisType database shcema and data updated. Lab dispatch wired through new data.
This commit is contained in:
@@ -4,9 +4,13 @@ import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { LabTaskStatus, Prisma } from '@prisma/client';
|
||||
import { CatalogEntityKind, LabTaskStatus, Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../../../prisma/prisma.service';
|
||||
import { normalizeMobile } from '../../common/phone';
|
||||
import {
|
||||
CatalogLabelService,
|
||||
normalizeCatalogLocale,
|
||||
} from '../catalog/catalog-label.service';
|
||||
import { TreatmentCatalogService } from '../treatment-catalog/treatment-catalog.service';
|
||||
import { normalizeTeeth } from '../treatments/treatment.utils';
|
||||
import { ListLabCasesDto, UpdateLabCaseTaskDto } from './dto/cases.dto';
|
||||
@@ -52,6 +56,7 @@ export class CasesService {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly treatmentCatalog: TreatmentCatalogService,
|
||||
private readonly catalogLabels: CatalogLabelService,
|
||||
) {}
|
||||
|
||||
getOrganizationIdFromUser(user: { organizationId?: string }) {
|
||||
@@ -142,8 +147,8 @@ export class CasesService {
|
||||
}
|
||||
}
|
||||
|
||||
const treatmentTypes = this.treatmentCatalog
|
||||
.list()
|
||||
const catalog = await this.treatmentCatalog.list();
|
||||
const treatmentTypes = catalog
|
||||
.filter((entry) => entry.labDependent && typeCodes.has(entry.code))
|
||||
.map((entry) => ({ code: entry.code, labDependent: entry.labDependent }));
|
||||
|
||||
@@ -218,6 +223,7 @@ export class CasesService {
|
||||
labCaseId: string,
|
||||
clinicOrganizationId: string,
|
||||
labOrganizationId: string,
|
||||
localeInput?: string | null,
|
||||
) {
|
||||
const labCase = await this.prisma.labCase.findFirst({
|
||||
where: {
|
||||
@@ -233,10 +239,18 @@ export class CasesService {
|
||||
throw new NotFoundException('Case not found');
|
||||
}
|
||||
|
||||
return { success: true, data: this.mapLabCaseDetail(labCase) };
|
||||
return {
|
||||
success: true,
|
||||
data: await this.mapLabCaseDetail(labCase, localeInput),
|
||||
};
|
||||
}
|
||||
|
||||
async getOne(labCaseId: string, labOrganizationId: string, actorUserId: string) {
|
||||
async getOne(
|
||||
labCaseId: string,
|
||||
labOrganizationId: string,
|
||||
actorUserId: string,
|
||||
localeInput?: string | null,
|
||||
) {
|
||||
await this.assertCanReadCases(actorUserId, labOrganizationId);
|
||||
|
||||
const labCase = await this.prisma.labCase.findFirst({
|
||||
@@ -252,7 +266,7 @@ export class CasesService {
|
||||
throw new NotFoundException('Case not found');
|
||||
}
|
||||
|
||||
return { success: true, data: this.mapLabCaseDetail(labCase) };
|
||||
return { success: true, data: await this.mapLabCaseDetail(labCase, localeInput) };
|
||||
}
|
||||
|
||||
async updateTask(
|
||||
@@ -261,6 +275,7 @@ export class CasesService {
|
||||
dto: UpdateLabCaseTaskDto,
|
||||
labOrganizationId: string,
|
||||
actorUserId: string,
|
||||
localeInput?: string | null,
|
||||
) {
|
||||
await this.assertCanEditCases(actorUserId, labOrganizationId);
|
||||
|
||||
@@ -299,7 +314,14 @@ export class CasesService {
|
||||
},
|
||||
});
|
||||
|
||||
return { success: true, data: this.mapTask(updated) };
|
||||
const locale = normalizeCatalogLocale(localeInput);
|
||||
const prosthesisLabels = await this.catalogLabels.resolveLabels(
|
||||
CatalogEntityKind.PROSTHESIS_TYPE,
|
||||
[updated.prosthesisTypeCode],
|
||||
locale,
|
||||
);
|
||||
|
||||
return { success: true, data: this.mapTask(updated, prosthesisLabels) };
|
||||
}
|
||||
|
||||
async listAssignableMembers(labOrganizationId: string, actorUserId: string) {
|
||||
@@ -431,9 +453,19 @@ export class CasesService {
|
||||
};
|
||||
}
|
||||
|
||||
private mapLabCaseDetail(lc: Prisma.LabCaseGetPayload<{ include: typeof labCaseListInclude }>) {
|
||||
private async mapLabCaseDetail(
|
||||
lc: Prisma.LabCaseGetPayload<{ include: typeof labCaseListInclude }>,
|
||||
localeInput?: string | null,
|
||||
) {
|
||||
const locale = normalizeCatalogLocale(localeInput);
|
||||
const treatmentTypes = [...new Set(lc.details.map((d) => d.detail.treatmentType))];
|
||||
const tasksByTooth = this.groupTasksByTooth(lc.tasks);
|
||||
const prosthesisCodes = [...new Set(lc.tasks.map((t) => t.prosthesisTypeCode).filter(Boolean))];
|
||||
const prosthesisLabels = await this.catalogLabels.resolveLabels(
|
||||
CatalogEntityKind.PROSTHESIS_TYPE,
|
||||
prosthesisCodes,
|
||||
locale,
|
||||
);
|
||||
const tasksByTooth = this.groupTasksByTooth(lc.tasks, prosthesisLabels);
|
||||
|
||||
return {
|
||||
id: lc.id,
|
||||
@@ -454,7 +486,7 @@ export class CasesService {
|
||||
organizationName: s.organization.name,
|
||||
sentAt: s.sentAt.toISOString(),
|
||||
})),
|
||||
tasks: lc.tasks.map((t) => this.mapTask(t)),
|
||||
tasks: lc.tasks.map((t) => this.mapTask(t, prosthesisLabels)),
|
||||
tasksByTooth,
|
||||
taskProgress: {
|
||||
completed: lc.tasks.filter((t) => t.status === LabTaskStatus.COMPLETED).length,
|
||||
@@ -468,6 +500,7 @@ export class CasesService {
|
||||
id: string;
|
||||
tooth: string;
|
||||
treatmentType: string;
|
||||
prosthesisTypeCode: string;
|
||||
stepOrder: number;
|
||||
stepLabel: string;
|
||||
status: LabTaskStatus;
|
||||
@@ -477,47 +510,62 @@ export class CasesService {
|
||||
createdAt: Date;
|
||||
assignee: { id: string; name: string; email: string } | null;
|
||||
}>,
|
||||
prosthesisLabels: Map<string, string>,
|
||||
) {
|
||||
const groups = new Map<
|
||||
string,
|
||||
{
|
||||
tooth: string;
|
||||
treatmentType: string;
|
||||
prosthesisTypeCode: string;
|
||||
prosthesisTypeLabel: string;
|
||||
tasks: ReturnType<CasesService['mapTask']>[];
|
||||
}
|
||||
>();
|
||||
|
||||
for (const task of tasks) {
|
||||
const key = `${task.tooth}:${task.treatmentType}`;
|
||||
const key = `${task.tooth}:${task.treatmentType}:${task.prosthesisTypeCode}`;
|
||||
const entry = groups.get(key) ?? {
|
||||
tooth: task.tooth,
|
||||
treatmentType: task.treatmentType,
|
||||
prosthesisTypeCode: task.prosthesisTypeCode,
|
||||
prosthesisTypeLabel:
|
||||
prosthesisLabels.get(task.prosthesisTypeCode) ?? task.prosthesisTypeCode,
|
||||
tasks: [],
|
||||
};
|
||||
entry.tasks.push(this.mapTask(task));
|
||||
entry.tasks.push(this.mapTask(task, prosthesisLabels));
|
||||
groups.set(key, entry);
|
||||
}
|
||||
|
||||
return [...groups.values()];
|
||||
}
|
||||
|
||||
private mapTask(task: {
|
||||
id: string;
|
||||
tooth: string;
|
||||
treatmentType: string;
|
||||
stepOrder: number;
|
||||
stepLabel: string;
|
||||
status: LabTaskStatus;
|
||||
priority: number;
|
||||
assigneeUserId: string | null;
|
||||
assignedAt: Date | null;
|
||||
createdAt: Date;
|
||||
assignee: { id: string; name: string; email: string } | null;
|
||||
}) {
|
||||
private mapTask(
|
||||
task: {
|
||||
id: string;
|
||||
tooth: string;
|
||||
treatmentType: string;
|
||||
prosthesisTypeCode: string;
|
||||
workflowStepCode?: string;
|
||||
stepOrder: number;
|
||||
stepLabel: string;
|
||||
status: LabTaskStatus;
|
||||
priority: number;
|
||||
assigneeUserId: string | null;
|
||||
assignedAt: Date | null;
|
||||
createdAt: Date;
|
||||
assignee: { id: string; name: string; email: string } | null;
|
||||
},
|
||||
prosthesisLabels: Map<string, string>,
|
||||
) {
|
||||
return {
|
||||
id: task.id,
|
||||
tooth: task.tooth,
|
||||
treatmentType: task.treatmentType,
|
||||
prosthesisTypeCode: task.prosthesisTypeCode,
|
||||
prosthesisTypeLabel:
|
||||
prosthesisLabels.get(task.prosthesisTypeCode) ?? task.prosthesisTypeCode,
|
||||
workflowStepCode: task.workflowStepCode ?? '',
|
||||
stepOrder: task.stepOrder,
|
||||
stepLabel: task.stepLabel,
|
||||
status: task.status,
|
||||
|
||||
Reference in New Issue
Block a user