79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
|
|
import type { Prisma } from '@prisma/client';
|
||
|
|
|
||
|
|
/** Union several workflows: scan/design first, packing/shipping last, other steps first-seen. */
|
||
|
|
export function unionWorkflowStepCodes(lists: readonly (readonly string[])[]): string[] {
|
||
|
|
const middle: string[] = [];
|
||
|
|
const seenMiddle = new Set<string>();
|
||
|
|
let hasScan = false;
|
||
|
|
let hasDesign = false;
|
||
|
|
let hasPacking = false;
|
||
|
|
let hasShipping = false;
|
||
|
|
|
||
|
|
for (const list of lists) {
|
||
|
|
for (const code of list) {
|
||
|
|
if (code === 'intraoral_scan') hasScan = true;
|
||
|
|
else if (code === 'design') hasDesign = true;
|
||
|
|
else if (code === 'packing') hasPacking = true;
|
||
|
|
else if (code === 'shipping') hasShipping = true;
|
||
|
|
else if (!seenMiddle.has(code)) {
|
||
|
|
seenMiddle.add(code);
|
||
|
|
middle.push(code);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const out: string[] = [];
|
||
|
|
if (hasScan) out.push('intraoral_scan');
|
||
|
|
if (hasDesign) out.push('design');
|
||
|
|
out.push(...middle);
|
||
|
|
if (hasPacking) out.push('packing');
|
||
|
|
if (hasShipping) out.push('shipping');
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function prosthesisGroupKey(codes: readonly string[]): string {
|
||
|
|
return [...new Set(codes.filter(Boolean))].sort().join('+');
|
||
|
|
}
|
||
|
|
|
||
|
|
export function splitProsthesisGroupKey(key: string): string[] {
|
||
|
|
return key.split('+').map((part) => part.trim()).filter(Boolean);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function prosthesisTypeTaskWhere(code: string): Prisma.LabCaseTaskWhereInput {
|
||
|
|
return {
|
||
|
|
OR: [
|
||
|
|
{ prosthesisTypeCode: code },
|
||
|
|
{ prosthesisTypeCode: { startsWith: `${code}+` } },
|
||
|
|
{ prosthesisTypeCode: { endsWith: `+${code}` } },
|
||
|
|
{ prosthesisTypeCode: { contains: `+${code}+` } },
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export function prosthesisTypeCaseWhere(code: string): Prisma.LabCaseWhereInput {
|
||
|
|
return {
|
||
|
|
OR: [
|
||
|
|
{ toothProsthesis: { some: { prosthesisTypeCode: code } } },
|
||
|
|
{ tasks: { some: prosthesisTypeTaskWhere(code) } },
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export function atomicProsthesisCodes(codes: Iterable<string>): string[] {
|
||
|
|
const out = new Set<string>();
|
||
|
|
for (const code of codes) {
|
||
|
|
if (!code) continue;
|
||
|
|
for (const part of splitProsthesisGroupKey(code)) out.add(part);
|
||
|
|
}
|
||
|
|
return [...out];
|
||
|
|
}
|
||
|
|
|
||
|
|
export function prosthesisGroupLabel(
|
||
|
|
groupKey: string,
|
||
|
|
labels: ReadonlyMap<string, string>,
|
||
|
|
): string {
|
||
|
|
const parts = splitProsthesisGroupKey(groupKey);
|
||
|
|
if (parts.length === 0) return groupKey;
|
||
|
|
return parts.map((code) => labels.get(code) ?? code).join(' + ');
|
||
|
|
}
|