improvement: Some improvements done. some bugs fixed.
This commit is contained in:
@@ -4,6 +4,9 @@ import {
|
||||
prosthesisGroupKey,
|
||||
unionWorkflowStepCodes,
|
||||
} from '../../common/prosthesis-group';
|
||||
import { sortProsthesisTeeth } from './lab-case-task.util';
|
||||
|
||||
const PARTIAL_DENTURE_CODE = 'partial_denture';
|
||||
|
||||
type TransactionClient = Prisma.TransactionClient;
|
||||
|
||||
@@ -64,7 +67,10 @@ export async function generateLabCaseTasks(
|
||||
const stepLabels = await resolveStepLabels(tx, allStepCodes, locale);
|
||||
|
||||
// Per tooth: stacked types become one group key; steps are the union.
|
||||
// Teeth are not merged even when they share the same type-set.
|
||||
// Unconnected teeth stay separate even when they share a type.
|
||||
// Connected (bridge) teeth that share a type merge into one pipeline; an extra
|
||||
// type on one unit of that bridge is its own pipeline. partial_denture is one
|
||||
// lab item per sourceKey.
|
||||
type ToothBucket = {
|
||||
sourceKey: string;
|
||||
treatmentDetailId: string | null;
|
||||
@@ -104,14 +110,140 @@ export async function generateLabCaseTasks(
|
||||
byTooth.set(toothKey, bucket);
|
||||
}
|
||||
|
||||
// One lab item per tooth (or arch sentinel): stacked types on that
|
||||
// tooth become one prosthesisTypeCode group key; steps are the union.
|
||||
const taskRows: Prisma.LabCaseTaskCreateManyInput[] = [];
|
||||
const teethByBridge = new Map<string, Set<string>>();
|
||||
for (const [toothKey, bucket] of byTooth) {
|
||||
if (!bucket.selectionGroupId) continue;
|
||||
const tooth = toothKey.slice(bucket.sourceKey.length + 2);
|
||||
const bridgeKey = `${bucket.sourceKey}::${bucket.selectionGroupId}`;
|
||||
const set = teethByBridge.get(bridgeKey) ?? new Set<string>();
|
||||
set.add(tooth);
|
||||
teethByBridge.set(bridgeKey, set);
|
||||
}
|
||||
const bridgeKeys = new Set(
|
||||
[...teethByBridge.entries()]
|
||||
.filter(([, teeth]) => teeth.size > 1)
|
||||
.map(([key]) => key),
|
||||
);
|
||||
|
||||
type Pipeline = {
|
||||
sourceKey: string;
|
||||
treatmentDetailId: string | null;
|
||||
lineId: string | null;
|
||||
treatmentType: string;
|
||||
selectionGroupId: string;
|
||||
tooth: string;
|
||||
teeth: string[];
|
||||
codes: string[];
|
||||
};
|
||||
|
||||
type PartialMerge = {
|
||||
sourceKey: string;
|
||||
treatmentDetailId: string | null;
|
||||
lineId: string | null;
|
||||
treatmentType: string;
|
||||
teeth: string[];
|
||||
groupIds: Set<string>;
|
||||
};
|
||||
|
||||
type ConnectedTypeMerge = {
|
||||
sourceKey: string;
|
||||
treatmentDetailId: string | null;
|
||||
lineId: string | null;
|
||||
treatmentType: string;
|
||||
selectionGroupId: string;
|
||||
code: string;
|
||||
teeth: string[];
|
||||
};
|
||||
|
||||
const pipelines: Pipeline[] = [];
|
||||
const partialMerges = new Map<string, PartialMerge>();
|
||||
const connectedTypeMerges = new Map<string, ConnectedTypeMerge>();
|
||||
|
||||
for (const [toothKey, bucket] of byTooth) {
|
||||
const tooth = toothKey.slice(bucket.sourceKey.length + 2);
|
||||
const codes = [...bucket.codes];
|
||||
const lists = codes.map((code) =>
|
||||
const codes = new Set(bucket.codes);
|
||||
if (codes.has(PARTIAL_DENTURE_CODE)) {
|
||||
codes.delete(PARTIAL_DENTURE_CODE);
|
||||
const merge = partialMerges.get(bucket.sourceKey) ?? {
|
||||
sourceKey: bucket.sourceKey,
|
||||
treatmentDetailId: bucket.treatmentDetailId,
|
||||
lineId: bucket.lineId,
|
||||
treatmentType: bucket.treatmentType,
|
||||
teeth: [],
|
||||
groupIds: new Set<string>(),
|
||||
};
|
||||
merge.teeth.push(tooth);
|
||||
if (bucket.selectionGroupId) merge.groupIds.add(bucket.selectionGroupId);
|
||||
partialMerges.set(bucket.sourceKey, merge);
|
||||
}
|
||||
if (codes.size === 0) continue;
|
||||
|
||||
const bridgeKey = bucket.selectionGroupId
|
||||
? `${bucket.sourceKey}::${bucket.selectionGroupId}`
|
||||
: '';
|
||||
if (bridgeKey && bridgeKeys.has(bridgeKey)) {
|
||||
for (const code of codes) {
|
||||
const typeKey = `${bridgeKey}::${code}`;
|
||||
const merge = connectedTypeMerges.get(typeKey) ?? {
|
||||
sourceKey: bucket.sourceKey,
|
||||
treatmentDetailId: bucket.treatmentDetailId,
|
||||
lineId: bucket.lineId,
|
||||
treatmentType: bucket.treatmentType,
|
||||
selectionGroupId: bucket.selectionGroupId,
|
||||
code,
|
||||
teeth: [],
|
||||
};
|
||||
if (!merge.teeth.includes(tooth)) merge.teeth.push(tooth);
|
||||
connectedTypeMerges.set(typeKey, merge);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
pipelines.push({
|
||||
sourceKey: bucket.sourceKey,
|
||||
treatmentDetailId: bucket.treatmentDetailId,
|
||||
lineId: bucket.lineId,
|
||||
treatmentType: bucket.treatmentType,
|
||||
selectionGroupId: bucket.selectionGroupId,
|
||||
tooth,
|
||||
teeth: [tooth],
|
||||
codes: [...codes],
|
||||
});
|
||||
}
|
||||
|
||||
for (const merge of connectedTypeMerges.values()) {
|
||||
const teeth = sortProsthesisTeeth(merge.teeth);
|
||||
pipelines.push({
|
||||
sourceKey: merge.sourceKey,
|
||||
treatmentDetailId: merge.treatmentDetailId,
|
||||
lineId: merge.lineId,
|
||||
treatmentType: merge.treatmentType,
|
||||
selectionGroupId: merge.selectionGroupId,
|
||||
tooth: teeth[0] ?? '',
|
||||
teeth,
|
||||
codes: [merge.code],
|
||||
});
|
||||
}
|
||||
|
||||
for (const merge of partialMerges.values()) {
|
||||
const teeth = sortProsthesisTeeth(merge.teeth);
|
||||
const sharedGroup = merge.groupIds.size === 1 ? [...merge.groupIds][0] : '';
|
||||
pipelines.push({
|
||||
sourceKey: merge.sourceKey,
|
||||
treatmentDetailId: merge.treatmentDetailId,
|
||||
lineId: merge.lineId,
|
||||
treatmentType: merge.treatmentType,
|
||||
selectionGroupId: sharedGroup,
|
||||
tooth: teeth[0] ?? '',
|
||||
teeth,
|
||||
codes: [PARTIAL_DENTURE_CODE],
|
||||
});
|
||||
}
|
||||
|
||||
const taskRows: Prisma.LabCaseTaskCreateManyInput[] = [];
|
||||
|
||||
for (const pipeline of pipelines) {
|
||||
const lists = pipeline.codes.map((code) =>
|
||||
(stepsByProsthesisCode.get(code) ?? []).map((s) => s.workflowStepCode),
|
||||
);
|
||||
const unioned = unionWorkflowStepCodes(lists);
|
||||
@@ -119,19 +251,19 @@ export async function generateLabCaseTasks(
|
||||
continue;
|
||||
}
|
||||
|
||||
const groupCode = prosthesisGroupKey(codes);
|
||||
const groupCode = prosthesisGroupKey(pipeline.codes);
|
||||
|
||||
unioned.forEach((workflowStepCode, index) => {
|
||||
taskRows.push({
|
||||
labCaseId,
|
||||
treatmentDetailId: bucket.treatmentDetailId,
|
||||
lineId: bucket.lineId,
|
||||
sourceKey: bucket.sourceKey,
|
||||
tooth,
|
||||
teeth: [tooth],
|
||||
treatmentType: bucket.treatmentType,
|
||||
treatmentDetailId: pipeline.treatmentDetailId,
|
||||
lineId: pipeline.lineId,
|
||||
sourceKey: pipeline.sourceKey,
|
||||
tooth: pipeline.tooth,
|
||||
teeth: pipeline.teeth,
|
||||
treatmentType: pipeline.treatmentType,
|
||||
prosthesisTypeCode: groupCode,
|
||||
selectionGroupId: bucket.selectionGroupId,
|
||||
selectionGroupId: pipeline.selectionGroupId,
|
||||
workflowStepCode,
|
||||
stepOrder: index + 1,
|
||||
stepLabel: stepLabels.get(workflowStepCode) ?? workflowStepCode,
|
||||
|
||||
Reference in New Issue
Block a user