diff --git a/docs/design-project-metadata-rework-2026-05-20.md b/docs/design-project-metadata-rework-2026-05-20.md new file mode 100644 index 0000000..2fe3345 --- /dev/null +++ b/docs/design-project-metadata-rework-2026-05-20.md @@ -0,0 +1,686 @@ +# Project metadata rework — Client Role + auto-derived project codes + +Status: design, ready for head review (2026-05-20) +Task: t-paliad-222 +Issues: m/paliad#47 (Client Role) + m/paliad#50 (project codes) +Branch: `mai/kepler/inventorcoder-project` + +Pairs two related changes because both touch `paliad.projects` schema, the +project form, and downstream consumers (Fristenrechner Determinator, +submission templates, Verlauf, picker / breadcrumb surfaces). One design, +two migrations, one coder shift. + +--- + +## §1 Scope & non-goals + +In scope: + +- Drop "Wir vertreten" entirely on `type='client'`, `'litigation'`, `'patent'`. +- Rename to "Client Role" / "Mandantenrolle" on `type='case'` with new + option set (Active / Reactive / Third Party / Other). +- Widen `paliad.projects.our_side` CHECK to the new sub-role values; drop + `'court'` and `'both'`; backfill existing rows to NULL. +- Add `paliad.projects.opponent_code text` on `type='litigation'` rows + (segment source for project codes). +- New Go helper `services.BuildProjectCode(ctx, projectID) (string, error)` + that walks the ancestor chain via the existing ltree `path` and assembles + the dotted code. Custom `paliad.projects.reference` on the project itself + wins. +- Wire the helper into project header, breadcrumb, picker labels, the + submission-template variable bag (`{{project.code}}`), and the Excel + export `__meta` sheet. + +Out of scope (handled separately or dropped): + +- Reshaping `paliad.parties` (per-party role rows are unchanged). +- New analytics / reports breaking out sub-roles. +- Bulk-renaming user-facing copy that says "Klägerseite" / + "Beklagtenseite" outside the project form. +- Reverse lookup (project by code) — already works via `reference`. +- Audit-history for who changed an override and when — not requested. +- Bulk regeneration of existing `reference` strings — manual entries stay + intact; auto-derive only fills empty slots. +- Renaming the `our_side` DB column — see §2.2 / Q1. + +--- + +## §2 Issue #47 — Client Role rework + +### §2.1 Current state (verified 2026-05-20) + +- Column: `paliad.projects.our_side text`, CHECK constraint + `projects_our_side_check` allows `('claimant','defendant','court','both',NULL)` + (mig 072). +- Live data audit (`SELECT our_side, count(*) FROM paliad.projects + GROUP BY our_side`): **all 12 rows are NULL**. Zero rows on + `'court'` or `'both'` — backfill is a no-op. The migration is risk-free + on the current dataset. +- Form: rendered for every project type by + `frontend/src/components/ProjectFormFields.tsx:156-168` (one + ` +

+ Kurzes Kürzel der Gegenseite (Grossbuchstaben, Ziffern, Bindestriche, max. 16 Zeichen). Wird als mittleres Segment in automatisch abgeleiteten Projekt-Codes verwendet (z.B. EXMPL.OPNT.567.INF.CFI). +

+ + + {/* Case-specific */} - -
- - -

- Bestimmt die Voreinstellung der Perspektive im Fristenrechner-Determinator. Lässt sich dort jederzeit überschreiben. -

+
+ + +

+ Bestimmt die Voreinstellung der Perspektive im Fristenrechner-Determinator: Aktiv → Klägerseite, Reaktiv → Beklagtenseite. Lässt sich dort jederzeit überschreiben. +

+
diff --git a/frontend/src/i18n-keys.ts b/frontend/src/i18n-keys.ts index e6c73e2..ecdf235 100644 --- a/frontend/src/i18n-keys.ts +++ b/frontend/src/i18n-keys.ts @@ -2163,6 +2163,19 @@ export type I18nKey = | "projects.field.billing_reference" | "projects.field.case_number" | "projects.field.client_number" + | "projects.field.client_role" + | "projects.field.client_role.appellant" + | "projects.field.client_role.applicant" + | "projects.field.client_role.claimant" + | "projects.field.client_role.defendant" + | "projects.field.client_role.group.active" + | "projects.field.client_role.group.other" + | "projects.field.client_role.group.reactive" + | "projects.field.client_role.hint" + | "projects.field.client_role.other" + | "projects.field.client_role.respondent" + | "projects.field.client_role.third_party" + | "projects.field.client_role.unset" | "projects.field.clientmatter.hint" | "projects.field.collaborators" | "projects.field.collaborators.hint" @@ -2180,13 +2193,21 @@ export type I18nKey = | "projects.field.matter_number" | "projects.field.netdocuments_url" | "projects.field.office" + | "projects.field.opponent_code" + | "projects.field.opponent_code.hint" + | "projects.field.opponent_code.placeholder" | "projects.field.our_side" + | "projects.field.our_side.appellant" + | "projects.field.our_side.applicant" | "projects.field.our_side.both" | "projects.field.our_side.claimant" | "projects.field.our_side.court" | "projects.field.our_side.defendant" | "projects.field.our_side.hint" | "projects.field.our_side.none" + | "projects.field.our_side.other" + | "projects.field.our_side.respondent" + | "projects.field.our_side.third_party" | "projects.field.our_side.unset" | "projects.field.parent" | "projects.field.parent.hint" diff --git a/frontend/src/projects-detail.tsx b/frontend/src/projects-detail.tsx index 2282da6..867ae7c 100644 --- a/frontend/src/projects-detail.tsx +++ b/frontend/src/projects-detail.tsx @@ -50,6 +50,14 @@ export function renderProjectsDetail(): string {
+ {/* Auto-derived project code (t-paliad-222 / m/paliad#50). + Rendered as a separate badge so the user can still + distinguish a custom reference (left badge) from a + tree-derived code (right badge); when reference is + blank, the derived code IS reference and only this + badge shows. Hidden via inline style until the + client populates it. */} +