Task Management Solution

Task workflows with reusable tags and hierarchical classifications, from PostgreSQL to clients and console.

Purpose

  • Demonstrate task management and reusable taxonomy CRUD.
  • Keep the public object separate from JPA persistence.
  • Share one HTTP contract across Java, TypeScript, and Dart.
  • Include a practical React console and bulk data workflows.

Runtime

  • Spring Boot APIs: /api/v1/task, /api/v1/tag, /api/v1/nomenclature.
  • PostgreSQL persistence through Spring Data JPA.
  • Java, TypeScript, and Dart clients.
  • React, Vite, and MUI management console.
  • MkDocs documentation and Marp presentation in the same repo.

Public Contract

Field Rule
id Server-generated Long
code Required, unique, immutable string
label Required string
description Nullable string
status TODO / IN_PROGRESS / DONE / CANCELLED
priority LOW / NORMAL / HIGH / URGENT
Due / assignee Nullable YYYY-MM-DD date / string
Taxonomy tagIds: [], nullable nomenclatureId
Audit Server-owned timestamps and actors

Defaults: status TODO, priority NORMAL, no taxonomy assignment.

Task

{
  "id": 42,
  "code": "RELEASE-001",
  "label": "Prepare release",
  "description": "Review the release checklist",
  "status": "TODO",
  "priority": "HIGH",
  "dueDate": "2026-11-01",
  "assignedTo": "alice",
  "tagIds": [],
  "nomenclatureId": null,
  "createdDate": "2026-08-30T17:00:00Z",
  "lastModifiedDate": "2026-08-30T17:05:00Z",
  "createdBy": "admin",
  "lastModifiedBy": "alice"
}

API

Method Path
CRUD /api/v1/task[/{id}]
CRUD /api/v1/tag[/{id}]
CRUD /api/v1/nomenclature[/{id}]
POST /api/v1/task/seed
POST /api/v1/task/import.{json,csv}
GET /api/v1/task/export.{json,csv}
PDF /api/v1/task/{id}/print.pdf, /print.pdf, /print-selected.pdf

Seed and import upsert by code and ignore imported IDs and dates.
Create includes code; update excludes immutable code.

Reusable Taxonomy Domains

  • Tag: flat labels shared by tasks, such as Release or Documentation.
  • Nomenclature: classification tree, such as Engineering → Release.
  • Both: id, code, label, description, creation/modification dates and actors.
  • Nomenclatures add nullable parentId; null means a root.
  • References must exist; self-parenting and hierarchy cycles are rejected.
  • Referenced tags, task classifications, and parents with children cannot be deleted.

Model Boundary

  • Task, Tag, Nomenclature: public business objects.
  • Internal mutable JPA entities isolate persistence behavior.
  • The service maps between public and persistence models.
  • Namespace fr.tiogars.domaintemplate and artifact identities stay unchanged.

Demo Database

Apply java/api/src/main/resources/db/manual/task-domains.sql before API startup.
ddl-auto: update is not a data migration and does not remove legacy tables.

docker compose -f docker/compose.yml -f docker/compose.local.yml down --volumes
docker compose -f docker/compose.yml -f docker/compose.local.yml up -d postgres

Resetting the demo volume removes all stored data.
Reapply the task-domain migration, then run make docker-up.

Deploy Quickly

make docker-up

Take Away

Presenter note: Start by framing the demo as a complete, reusable CRUD pattern: tasks with reusable taxonomies, one contract, several clients, and a working console.

Presenter note: This is a reference implementation for a real CRUD feature: small enough to explain, complete enough to show how the stack fits together.

Presenter note: Walk through the runtime stack from API to database, then to clients and console. Emphasize this is not just backend-only work.

Presenter note: Explain the contract first. The important design decision is that the public model is stable and intentionally different from the database entity.

Presenter note: Use this example to show the actual JSON response and call out the immutable code value and timestamp semantics.

Presenter note: This is the main API surface. Highlight that seed and import are operational shortcuts, while the CRUD endpoints expose the standard model lifecycle.

Presenter note: Reinforce the architectural boundary: public domain model vs persistence model. This keeps the API honest and prevents leaking JPA details.

Presenter note: Mention the demo database setup and the known caveat that the old table is not auto-dropped, so a full volume reset is the cleanest way to start fresh.

Presenter note: End on the operational path: start the stack, open API, console, docs, and show that the repo is designed for quick local validation.

Presenter note: The container serves the interactive Bespoke deck plus the exported PDF and PPTX built at image build time.