TreatmentType and ProsthesisType database shcema and data updated. Lab dispatch wired through new data.
This commit is contained in:
154
backend/src/modules/cases/lab-case-task.generator.spec.ts
Normal file
154
backend/src/modules/cases/lab-case-task.generator.spec.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import { CatalogEntityKind } from '@prisma/client';
|
||||
import {
|
||||
PROSTHESIS_TYPES,
|
||||
buildProsthesisStepCodes,
|
||||
} from '../../../prisma/catalog-seed-data';
|
||||
import { generateLabCaseTasks } from './lab-case-task.generator';
|
||||
|
||||
function buildMockTx(options: {
|
||||
existingCount?: number;
|
||||
toothProsthesisRows: Array<{
|
||||
treatmentDetailId: string;
|
||||
tooth: string;
|
||||
prosthesisTypeCode: string;
|
||||
treatmentType?: string;
|
||||
}>;
|
||||
prosthesisTypes: Array<{
|
||||
code: string;
|
||||
steps: Array<{ stepOrder: number; workflowStepCode: string }>;
|
||||
}>;
|
||||
stepLabels?: Record<string, string>;
|
||||
}) {
|
||||
const created: unknown[] = [];
|
||||
|
||||
const tx = {
|
||||
labCaseTask: {
|
||||
count: jest.fn().mockResolvedValue(options.existingCount ?? 0),
|
||||
createMany: jest.fn().mockImplementation(({ data }) => {
|
||||
created.push(...data);
|
||||
return { count: data.length };
|
||||
}),
|
||||
},
|
||||
labCaseToothProsthesis: {
|
||||
findMany: jest.fn().mockResolvedValue(
|
||||
options.toothProsthesisRows.map((row) => ({
|
||||
treatmentDetailId: row.treatmentDetailId,
|
||||
tooth: row.tooth,
|
||||
prosthesisTypeCode: row.prosthesisTypeCode,
|
||||
detail: {
|
||||
id: row.treatmentDetailId,
|
||||
treatmentType: row.treatmentType ?? 'prosthesis',
|
||||
},
|
||||
})),
|
||||
),
|
||||
},
|
||||
prosthesisType: {
|
||||
findMany: jest.fn().mockResolvedValue(
|
||||
options.prosthesisTypes.map((type) => ({
|
||||
code: type.code,
|
||||
isActive: true,
|
||||
steps: type.steps.map((step) => ({
|
||||
stepOrder: step.stepOrder,
|
||||
labWorkflowStep: { code: step.workflowStepCode },
|
||||
})),
|
||||
})),
|
||||
),
|
||||
},
|
||||
catalogTranslation: {
|
||||
findMany: jest.fn().mockImplementation(({ where }) => {
|
||||
const codes = where.entityCode?.in ?? [];
|
||||
return codes.map((code: string) => ({
|
||||
entityCode: code,
|
||||
locale: 'en',
|
||||
label: options.stepLabels?.[code] ?? code,
|
||||
entityKind: CatalogEntityKind.LAB_WORKFLOW_STEP,
|
||||
}));
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
return { tx, created };
|
||||
}
|
||||
|
||||
function stepsFromSeed(code: string) {
|
||||
const seed = PROSTHESIS_TYPES.find((type) => type.code === code);
|
||||
if (!seed) {
|
||||
throw new Error(`Unknown prosthesis code: ${code}`);
|
||||
}
|
||||
return buildProsthesisStepCodes(seed).map((workflowStepCode, index) => ({
|
||||
stepOrder: index + 1,
|
||||
workflowStepCode,
|
||||
}));
|
||||
}
|
||||
|
||||
describe('generateLabCaseTasks', () => {
|
||||
it('creates tasks for pfm_crown with universal and type-specific steps', async () => {
|
||||
const pfmSteps = stepsFromSeed('pfm_crown');
|
||||
const { tx, created } = buildMockTx({
|
||||
toothProsthesisRows: [
|
||||
{
|
||||
treatmentDetailId: 'detail-1',
|
||||
tooth: '14',
|
||||
prosthesisTypeCode: 'pfm_crown',
|
||||
},
|
||||
],
|
||||
prosthesisTypes: [{ code: 'pfm_crown', steps: pfmSteps }],
|
||||
stepLabels: { intraoral_scan: 'Intraoral Scan', packing: 'Packing' },
|
||||
});
|
||||
|
||||
const count = await generateLabCaseTasks(tx as never, 'lab-case-1', 'en');
|
||||
|
||||
expect(count).toBe(pfmSteps.length);
|
||||
expect(created).toHaveLength(pfmSteps.length);
|
||||
expect(created[0]).toMatchObject({
|
||||
tooth: '14',
|
||||
prosthesisTypeCode: 'pfm_crown',
|
||||
workflowStepCode: 'intraoral_scan',
|
||||
stepLabel: 'Intraoral Scan',
|
||||
});
|
||||
const stepCodes = (created as Array<{ workflowStepCode: string }>).map(
|
||||
(row) => row.workflowStepCode,
|
||||
);
|
||||
expect(stepCodes).toEqual(pfmSteps.map((step) => step.workflowStepCode));
|
||||
expect(stepCodes).toContain('packing');
|
||||
expect(stepCodes).toContain('shipping');
|
||||
expect(stepCodes).toContain('milling_wet');
|
||||
});
|
||||
|
||||
it('omits packing and shipping for smile_design', async () => {
|
||||
const smileSteps = stepsFromSeed('smile_design');
|
||||
const { tx, created } = buildMockTx({
|
||||
toothProsthesisRows: [
|
||||
{
|
||||
treatmentDetailId: 'detail-1',
|
||||
tooth: '11',
|
||||
prosthesisTypeCode: 'smile_design',
|
||||
},
|
||||
],
|
||||
prosthesisTypes: [{ code: 'smile_design', steps: smileSteps }],
|
||||
});
|
||||
|
||||
const count = await generateLabCaseTasks(tx as never, 'lab-case-2', 'en');
|
||||
|
||||
expect(count).toBe(smileSteps.length);
|
||||
const stepCodes = (created as Array<{ workflowStepCode: string }>).map(
|
||||
(row) => row.workflowStepCode,
|
||||
);
|
||||
expect(stepCodes).not.toContain('packing');
|
||||
expect(stepCodes).not.toContain('shipping');
|
||||
expect(stepCodes).toContain('printer_resin');
|
||||
});
|
||||
|
||||
it('skips generation when tasks already exist', async () => {
|
||||
const { tx } = buildMockTx({
|
||||
existingCount: 3,
|
||||
toothProsthesisRows: [],
|
||||
prosthesisTypes: [],
|
||||
});
|
||||
|
||||
const count = await generateLabCaseTasks(tx as never, 'lab-case-3', 'en');
|
||||
|
||||
expect(count).toBe(0);
|
||||
expect(tx.labCaseTask.createMany).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user