Design: Category Taxonomy editor (G1) #790
ChakshuGautam
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Category Taxonomy editor
Architecture discussion for phase G1 of the CRS Configurator. Implementation tracked in (draft) PR draft PR #789. Stacked on the escalation foundation in PR #770.
G1: Category Taxonomy editor
Why
The CRS Configurator currently lets operators type a free-text category into the SLA
Matrix (
CRS.CategorySLA.category,subcategoryL1) shipped in PR #770. This is fragile —typos divorce SLA rows from real complaints, and there is no single source of truth that
the citizen submission form, the dashboard's "Distribution by category" indicator
(BRD Appendix C), and the IGE/IGSAE auto-routing (BRD §5.2 "Routing Logic") can all
share.
Phase G1 introduces
CRS.CategoryTaxonomy— a 3-level tree editor(Category → Subcategory L1 → Subcategory L2) — and switches the SLA Matrix
combobox from free text to a strict picker sourced from the taxonomy. BRD Appendix A
enumerates ~17 IGSAE categories and ~13 IGE categories with multi-level sub-categories;
that table becomes the first-seed XLSX bulk import.
Scope
In:
/manage/crs/categories(list + filter, create, edit, soft-delete).CRS.CategoryTaxonomy(full property shape — see below; this PR shipsonly the stub envelope).
IGE|IGSAE|BOTH).deprecatedReasonfield. Deleting an in-use category surfaces awarning that lists the SLA Matrix rows still referencing it.
Subcategory L2, Path) and writes through MDMS v2
_create.displayOrder) for citizen-facing dropdowns.free-text combobox (the SLA Matrix code change itself ships in a follow-up PR; this
phase only exports the component).
Not in (deferred):
displayNamein English only.
Form Customization).
(Path Routing).
and gets retrofitted (matches the G1-G3 / G4 split in the roadmap).
allowsOther: bool; the actual citizen-portal behaviour ships with the submissionform work in G8.
MDMS schemas
This PR commits
CRS.G1.jsonas an inert stub (isActive: false, emptyx-unique,no
properties) atutilities/default-data-handler/src/main/resources/schema/CRS.G1.json. The stub reservesthe schema code so the configurator UI and the importer can target a stable identifier
without waiting on schema review.
The full schema, to be filled in during implementation:
{ "tenantId": "{tenantid}", "code": "CRS.CategoryTaxonomy", "isActive": true, "definition": { "type": "object", "$schema": "http://json-schema.org/draft-07/schema#", "required": ["code", "path", "category", "subcategoryL1", "active"], "x-unique": ["path", "category", "subcategoryL1", "subcategoryL2"], "x-ref-schema": [], "additionalProperties": false, "properties": { "code": { "type": "string", "minLength": 1 }, "path": { "type": "string", "enum": ["IGE", "IGSAE", "BOTH"] }, "category": { "type": "string", "minLength": 1 }, "subcategoryL1": { "type": "string", "minLength": 1 }, "subcategoryL2": { "type": "string" }, "displayOrder": { "type": "number", "minimum": 0 }, "allowsOther": { "type": "boolean" }, "active": { "type": "boolean" }, "deprecatedReason": { "type": "string" }, "createdAt": { "type": "number" } } } }Conventions match the existing
CRS.*family (object type; explicitx-unique; emptyx-ref-schema;additionalProperties: false).Configurator routes + UI sketch
/manage/crs/categories— list + filter bypath+ search by name./manage/crs/categories/new— create form./manage/crs/categories/:code/edit— edit + soft-delete./manage/crs/categories/import— XLSX bulk importer.Sidebar nav: a new "CRS" group (or extend the existing one already used by the SLA
Matrix). Entry label: "Category Taxonomy". Ordered above SLA Matrix because the
matrix will depend on it.
ASCII wireframe of the list page:
Edit page anatomy: header crumb, form (path / category / L1 / L2 / order / allowsOther /
active), in-use panel (list of
CRS.CategorySLArows referencing the same(path, category, subcategoryL1)tuple — purely informational; soft-delete is stillallowed but operator must confirm).
API endpoints touched
CRS.CategorySLA:POST /mdms-v2/v2/_create/CRS.CategoryTaxonomyPOST /mdms-v2/v2/_search(filter bypath,active)POST /mdms-v2/v2/_update/CRS.CategoryTaxonomyover
_createcalls (MDMS v2 has no native bulk endpoint; the importer batches client-side and reports per-row outcomes).
CRS.SLAAuditLogwrites (already shipped by PR feat(pgr+configurator): escalation feature — OTEL-instrumented scheduler, /escalation/_trigger admin endpoint, configurator editor, embedded workflow designer, integration tests #770) — out of scope for G1, sincethe roadmap leaves audit-log integration to G4.
Dependencies on prior phases
Must ship first:
CRS.CategorySLAconsumer that thistaxonomy feeds. Stacked here.
refactor/scheduler-state-name-mdms, stacked on feat(pgr+configurator): escalation feature — OTEL-instrumented scheduler, /escalation/_trigger admin endpoint, configurator editor, embedded workflow designer, integration tests #770) — orthogonal but in thesame stack.
docs/categorysla-wiring-strategies) — orthogonal design doc; in the samestack.
This phase blocks:
(category, subcategoryL1?) → path, so it needs the picker source.code.
picker is a follow-up to G1, not part of G1 itself (so PR feat(pgr+configurator): escalation feature — OTEL-instrumented scheduler, /escalation/_trigger admin endpoint, configurator editor, embedded workflow designer, integration tests #770's free-text combobox
keeps working during the rollout).
Acceptance criteria
An operator with the
CRS_CONFIG_ADMINrole should be able to:/manage/crs/categorieson a fresh tenant and see an empty-state with a"Bulk import" CTA.
XLSX and see every row land in the list view.
page reload.
(path, category, subcategoryL1, subcategoryL2)andreceive a clear validation error (MDMS unique-key rejection surfaced
operator-friendly).
CRS.CategorySLArow and see a warningthat lists the referencing SLA rows by
(category, subcategoryL1).pathandhides
active: falserows by default.Estimated effort
M (~2-3 days) — straight MDMS CRUD on top of the patterns already established by the
SLA Matrix in PR #770. The nontrivial pieces are the XLSX importer (parsing + per-row
error reporting) and the in-use-warning panel on soft-delete. The picker export is
trivial.
Open questions
codebe operator-supplied or auto-generated fromslugify(path-category-subcategoryL1-subcategoryL2)? Auto-generated keeps importsdeterministic; operator-supplied lets two tenants share a category code for cross-
tenant reporting.
(category, subcategoryL1)tuple? Proposal: it doesn't — the complaint keeps itsdenormalised category strings; only NEW SLA Matrix rows and NEW complaints lose the
option from the picker.
code, or is it create-only? Roadmap issilent. Proposal: create-only for v1 (importer rejects rows whose
codecollides);upsert ships in G1.1 if operators ask for it.
allowsOther: bool) on each L1, or a magic row theimporter auto-inserts per category? The roadmap mentions both. Proposal: flag on L1;
the citizen-portal renders the "Other" free-text option only when the picked L1 has
allowsOther: true.digit-configuratoror fromdigit-ui-esbuild?The SLA Matrix lives in the configurator today; the citizen portal lives in the
esbuild bundle. Proposal: ship two thin wrappers (one per bundle) over a shared MDMS
_searchcall, since the bundles can't import from each other.Cross-references
docs/crs-configurator-roadmap.md— Phase G1 section.docs/escalation-feature-design.mddocs/categorysla-wiring-strategies.md(PR #B)CRS.CategorySLA,CRS.StateSLA,CRS.SLAAuditLog, the SLA Matrix page, and the scheduler patch this taxonomy willeventually constrain).
Beta Was this translation helpful? Give feedback.
All reactions