improvement: all confirmed suggestions implemented

This commit is contained in:
2026-09-04 17:04:48 +03:30
parent 7f92e735fb
commit 72f885d9dd
23 changed files with 1070 additions and 679 deletions

View File

@@ -72,7 +72,6 @@ export const LAB_WORKFLOW_STEPS = [
export type ProsthesisChartRegion = 'crown' | 'root' | 'arch';
export type ProsthesisStackGroup = 'restoration' | 'implant' | 'post_core' | 'arch';
export type ProsthesisAddonKind = '' | 'implant' | 'post_core';
export type ProsthesisTypeSeed = {
code: string;
@@ -83,7 +82,6 @@ export type ProsthesisTypeSeed = {
subcategory?: string;
chartRegion: ProsthesisChartRegion;
stackGroup: ProsthesisStackGroup;
addonKind?: ProsthesisAddonKind;
/** Manufacturing sequence. Packing and shipping are appended except for smile_design. */
manufacturingSteps: readonly string[];
};
@@ -138,7 +136,7 @@ function crown(
};
}
function implantAddon(
function implant(
code: string,
sortOrder: number,
manufacturingSteps: readonly string[],
@@ -150,7 +148,6 @@ function implantAddon(
category: 'implant',
chartRegion: 'root',
stackGroup: 'implant',
addonKind: 'implant',
manufacturingSteps,
...extra,
};
@@ -230,7 +227,6 @@ export const PROSTHESIS_TYPES: ProsthesisTypeSeed[] = [
category: 'post_core',
chartRegion: 'root',
stackGroup: 'post_core',
addonKind: 'post_core',
manufacturingSteps: POST_CORE,
},
{
@@ -239,29 +235,28 @@ export const PROSTHESIS_TYPES: ProsthesisTypeSeed[] = [
category: 'post_core',
chartRegion: 'root',
stackGroup: 'post_core',
addonKind: 'post_core',
manufacturingSteps: POST_CORE,
},
implantAddon('prefabricated_abutment', 40, [
implant('prefabricated_abutment', 40, [
'intraoral_scan',
'choosing_abutment',
'model_create',
'polish_prep',
]),
implantAddon('ti_base_abutment', 41, ['intraoral_scan', 'model_create', 'polish_prep']),
implantAddon('multi_unit_abutment', 42, [
implant('ti_base_abutment', 41, ['intraoral_scan', 'model_create', 'polish_prep']),
implant('multi_unit_abutment', 42, [
'intraoral_scan',
'choosing_abutment',
'model_create',
'polish_prep',
]),
implantAddon('customized_abutment', 43, [
implant('customized_abutment', 43, [
...SCAN_DESIGN_MODEL,
'milling_wet',
'polish_prep',
]),
implantAddon('zirconia_abutment', 44, [...SCAN_DESIGN_MODEL, 'milling_dry', 'sinter']),
implantAddon(
implant('zirconia_abutment', 44, [...SCAN_DESIGN_MODEL, 'milling_dry', 'sinter']),
implant(
'screw_retained',
45,
[...SCAN_DESIGN_MODEL, 'milling_wet', 'polish_prep'],

View File

@@ -41,25 +41,31 @@ const STACK_RULES = [
'restoration',
'One per tooth: crown, veneer, inlay, onlay, or overlay.',
],
['implant', 'One abutment add-on per tooth (Ti-base, custom, prefab, multi-unit, zirconia, screw-retained).'],
['post_core', 'One post & core, only if a restoration is already present. Blocked when screw-retained is on the tooth.'],
['implant', 'One implant type per tooth. Disabled when post & core is on the tooth.'],
[
'post_core',
'One post & core. Disabled when a restoration or implant is already on the tooth.',
],
[
'arch',
'Complete denture, overdenture, appliances, and digital use Upper/Lower arch labels (UA/LA). Not 16 FDI teeth.',
'Complete denture, overdenture, appliances, and digital use Upper/Lower/Both (UA/LA). The picker control remaps jobs (Both→Upper drops lower).',
],
[
'partial_denture',
'Tooth-selected (FDI), not the arch labels. All selected teeth become one lab job. May stack with implant add-ons.',
'Tooth-selected (FDI), not the arch labels. All selected teeth become one lab job.',
],
[
'screw_retained',
'Fills the implant slot (chart paints the crown) and stacks with a restoration. Blocks post & core.',
'Implant that paints the crown. No crown suggestion slot; Crown and Indirect are disabled. Does not stack with another restoration.',
],
[
'crown_suggestion',
'Implant or post & core (not screw-retained) shows a crown suggestion slot. A veneer/inlay/onlay/overlay hides it. After a crown is picked the slot stays filled so it can be changed.',
],
[
'connected',
'Connected teeth that share a type are one lab job. An extra type on one unit of the bridge is its own job. Unconnected teeth stay separate even if they share a type.',
],
['maximum', 'Usual maximum is 3 types per tooth (e.g. zirconia crown + Ti-base + fiber post).'],
['two_crowns', 'Two crowns cannot stack.'],
];
@@ -198,7 +204,6 @@ function buildWorkbook(): Buffer {
'label_nl',
'chartRegion',
'stackGroup',
'addonKind',
'active',
],
];
@@ -215,7 +220,6 @@ function buildWorkbook(): Buffer {
labels.nl ?? '',
type.chartRegion,
type.stackGroup,
type.addonKind ?? '',
type.isActive === false ? 'false' : 'true',
]);
}

View File

@@ -0,0 +1,3 @@
-- Crown suggestion slot replaced catalog addonKind (implant / post_core add-on lists).
ALTER TABLE "prosthesis_types" DROP COLUMN IF EXISTS "addonKind";

View File

@@ -359,8 +359,6 @@ model ProsthesisType {
chartRegion String @default("crown")
/// Mutual exclusion group: restoration | implant | post_core | arch
stackGroup String @default("restoration")
/// Also listed as an add-on: implant | post_core | empty
addonKind String @default("")
steps ProsthesisTypeStep[]

View File

@@ -191,7 +191,6 @@ async function main() {
subcategory: type.subcategory ?? '',
chartRegion: type.chartRegion,
stackGroup: type.stackGroup,
addonKind: type.addonKind ?? '',
};
const prosthesisType = await prisma.prosthesisType.upsert({
where: { code: type.code },

View File

@@ -16,7 +16,6 @@ export type ProsthesisTypeCatalogEntry = {
subcategory: string;
chartRegion: string;
stackGroup: string;
addonKind: string;
};
type CatalogRow = {
@@ -25,7 +24,6 @@ type CatalogRow = {
subcategory: string;
chartRegion: string;
stackGroup: string;
addonKind: string;
};
@Injectable()
@@ -53,7 +51,6 @@ export class ProsthesisCatalogService implements OnModuleInit {
subcategory: true,
chartRegion: true,
stackGroup: true,
addonKind: true,
},
});
@@ -66,7 +63,6 @@ export class ProsthesisCatalogService implements OnModuleInit {
subcategory: row.subcategory,
chartRegion: row.chartRegion,
stackGroup: row.stackGroup,
addonKind: row.addonKind,
},
]),
);
@@ -94,7 +90,6 @@ export class ProsthesisCatalogService implements OnModuleInit {
subcategory: row.subcategory,
chartRegion: row.chartRegion,
stackGroup: row.stackGroup,
addonKind: row.addonKind,
};
})
.sort((a, b) => a.sortOrder - b.sortOrder || a.code.localeCompare(b.code));