Add dental module phase 4 and phase 5 documentation, including treatment estimates, clinical operations, and preset content
- Introduced phase 4 documentation detailing treatment estimates, data models, state machines, API endpoints, and new dashboard metrics. - Added phase 5 documentation covering consumables, lab operations, periodontal charts, sterilization cycles, clinical images, and a checklist for professional review. - Created a preset content document outlining default dental service packages and protocols for clinics.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
# Practice domain belongs to the tenant, not only to the clinic
|
||||
|
||||
`practice_domain_id` originally lived on `clinics`, but every piece of operational data in this
|
||||
codebase is owned by an `(entity_type, entity_id)` pair where `entity_type` is `doctor` or `clinic`.
|
||||
A solo practice is a `doctor` tenant, so it could never declare a practice domain at all — the beauty
|
||||
domain has the same hole, it simply had not been noticed. The column is therefore added to `doctors`
|
||||
as well and read through a single `PracticeDomainResolver` that takes an `EntityContext`, so no
|
||||
caller has to know which kind of tenant it is looking at.
|
||||
|
||||
## Considered Options
|
||||
|
||||
Letting a doctor inherit the domain of a clinic they work at was rejected: a doctor with no clinic
|
||||
would stay domainless, and a doctor working at two clinics with different domains would be ambiguous.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Teeth are not Treatment Areas
|
||||
|
||||
A Treatment Area is a `CatalogCategory` snapshotted onto a case, which made "one category per tooth"
|
||||
look like a free way to get dental charting. It was rejected: FDI tooth numbering is a universal fact,
|
||||
not a per-clinic taxonomy, so it would duplicate 32 to 52 identical rows into every clinic's service
|
||||
tree, surfaces would need a further level below that, and the persistent condition of a tooth — missing,
|
||||
crowned, implanted years before the patient ever arrived — has nowhere to live on a settings row.
|
||||
A tooth is instead an FDI `smallint` on the record that targets it, and tooth condition is its own
|
||||
snapshot table in the Dental context.
|
||||
|
||||
## Consequences
|
||||
|
||||
Tooth condition must be updated after each visit, and that projection lives in exactly one class rather
|
||||
than being spread across controllers. In exchange, rendering a chart is one query and never a replay of
|
||||
history.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Dental attributes of a service live in an extension table, not on ServiceItem
|
||||
|
||||
Whether a service is priced per tooth, per surface or per canal — and whether booking it must ask for a
|
||||
tooth at all — is dental-only knowledge, but `ServiceItem` is shared by every practice domain. Those
|
||||
attributes therefore sit in a one-to-one `dental_service_profiles` row in the Dental context, keyed by
|
||||
`service_item_id`, so a beauty clinic carries no dental columns and the next domain is not invited to add
|
||||
its own set to the shared table. The cost is a join whenever the dental profile is needed, which is the
|
||||
same pattern the codebase already uses elsewhere.
|
||||
|
||||
## Consequences
|
||||
|
||||
The reverse choice was made deliberately one level down: the tooth and surfaces a visit line was actually
|
||||
billed for are columns on `SessionService` itself, because that row is the clinical and financial record
|
||||
of the visit rather than shared configuration, and splitting it would allow a billed line to lose its
|
||||
target unnoticed.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Domain-specific dashboard metrics come from tagged providers
|
||||
|
||||
`DashboardController` already serves four role dashboards from 803 lines and fifteen dependencies, so
|
||||
branching each of them on practice domain would double four code paths and make every clinic pay for
|
||||
queries only dentists need. Domain metrics instead come from a `DomainMetricProvider` interface resolved
|
||||
by a tagged-service registry keyed on the practice domain code — the same shape as `TreatmentWorkflow`
|
||||
in ADR 0005 — and the role endpoints simply attach whatever the provider returns.
|
||||
|
||||
## Consequences
|
||||
|
||||
Unlike the workflow registry there is no default implementation: a tenant with no domain, or a domain with
|
||||
no provider, gets `null` and the panel renders no extra section. An empty metrics block is worse than an
|
||||
absent one.
|
||||
Reference in New Issue
Block a user