task-fic-display
This commit is contained in:
772
plans/task-fix-display.md
Normal file
772
plans/task-fix-display.md
Normal file
@@ -0,0 +1,772 @@
|
||||
# Task Foundation Cleanup: Admin Display Names, MS Option CRUD, Seed & Database Script Standardization
|
||||
|
||||
## Status
|
||||
|
||||
Planned
|
||||
|
||||
## Objective
|
||||
|
||||
Clean up foundational admin experience and system bootstrap workflow before continuing feature development.
|
||||
|
||||
This task focuses on:
|
||||
|
||||
* displaying human-readable names instead of raw IDs
|
||||
* adding CRUD management for `ms_options`
|
||||
* consolidating seed scripts
|
||||
* creating a clear system bootstrap script
|
||||
* creating a reset database script for development
|
||||
* auditing old seed/verify/audit scripts
|
||||
* documenting what system admin must run when starting from a fresh database
|
||||
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
Current system still exposes raw IDs in some UI/API responses, such as:
|
||||
|
||||
```txt
|
||||
createdBy
|
||||
updatedBy
|
||||
assignedBy
|
||||
branchId
|
||||
salesmanId
|
||||
assignedToUserId
|
||||
closedByUserId
|
||||
generatedBy
|
||||
uploadedBy
|
||||
approvedBy
|
||||
```
|
||||
|
||||
This makes admin screens, CRM pages, approval history, audit views, and document settings difficult to read.
|
||||
|
||||
Current seed/setup scripts are also fragmented:
|
||||
|
||||
```json
|
||||
"seed:super-admin"
|
||||
"seed:foundation"
|
||||
"seed:crm-uat"
|
||||
"seed:pdf-template-version"
|
||||
"migrate:membership-business-roles"
|
||||
"seed:task-h1-fixture"
|
||||
"verify:task-h1"
|
||||
"verify:task-h3"
|
||||
"verify:crm-access"
|
||||
"audit:pdf:*"
|
||||
"setup:db"
|
||||
```
|
||||
|
||||
There is no clear single command for:
|
||||
|
||||
```txt
|
||||
Fresh system bootstrap
|
||||
Development reset
|
||||
UAT seed
|
||||
PDF template reseed
|
||||
Verification
|
||||
Audit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope 1: Human-Readable Display Names
|
||||
|
||||
## Objective
|
||||
|
||||
Replace raw ID display with readable names across active UI and API DTOs.
|
||||
|
||||
## Required Display Mapping
|
||||
|
||||
### User-related fields
|
||||
|
||||
Fields that should expose display names:
|
||||
|
||||
```txt
|
||||
createdBy
|
||||
updatedBy
|
||||
assignedBy
|
||||
assignedToUserId
|
||||
assignedSalesOwnerId
|
||||
salesmanId
|
||||
closedByUserId
|
||||
approvedBy
|
||||
requestedBy
|
||||
actedBy
|
||||
generatedBy
|
||||
uploadedBy
|
||||
voidedBy
|
||||
lockedBy
|
||||
```
|
||||
|
||||
Add readable fields where applicable:
|
||||
|
||||
```ts
|
||||
createdByName
|
||||
updatedByName
|
||||
assignedByName
|
||||
assignedToUserName
|
||||
assignedSalesOwnerName
|
||||
salesmanName
|
||||
closedByName
|
||||
approvedByName
|
||||
requestedByName
|
||||
actedByName
|
||||
generatedByName
|
||||
uploadedByName
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* Keep raw IDs for system integrity.
|
||||
* Add display fields for UI.
|
||||
* Do not remove ID fields from API unless all consumers are migrated.
|
||||
* Use fallback:
|
||||
|
||||
* user name
|
||||
* email
|
||||
* ID as last resort
|
||||
|
||||
---
|
||||
|
||||
### Branch-related fields
|
||||
|
||||
Fields that should expose readable branch data:
|
||||
|
||||
```txt
|
||||
branchId
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```ts
|
||||
branchName
|
||||
branchCode
|
||||
```
|
||||
|
||||
If branch master is not a dedicated table and comes from `ms_options`, resolve from master option category.
|
||||
|
||||
---
|
||||
|
||||
### Option-related fields
|
||||
|
||||
Fields that should expose labels:
|
||||
|
||||
```txt
|
||||
productType
|
||||
status
|
||||
priority
|
||||
stage
|
||||
outcomeStatus
|
||||
lostReason
|
||||
cancelReason
|
||||
noQuotationReason
|
||||
customerType
|
||||
customerStatus
|
||||
leadChannel
|
||||
quotationType
|
||||
discountType
|
||||
currency
|
||||
unit
|
||||
taxRate
|
||||
```
|
||||
|
||||
Add display labels:
|
||||
|
||||
```ts
|
||||
productTypeLabel
|
||||
statusLabel
|
||||
priorityLabel
|
||||
stageLabel
|
||||
outcomeStatusLabel
|
||||
lostReasonLabel
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* Use `ms_options` as source of display labels.
|
||||
* Do not hardcode labels in UI.
|
||||
* Support fallback to raw code if option label is missing.
|
||||
|
||||
---
|
||||
|
||||
## Target Areas
|
||||
|
||||
Review and update active UI/API areas:
|
||||
|
||||
```txt
|
||||
src/features/crm/leads/**
|
||||
src/features/crm/opportunities/**
|
||||
src/features/crm/quotations/**
|
||||
src/features/crm/customers/**
|
||||
src/features/crm/approval/**
|
||||
src/features/foundation/approval/**
|
||||
src/features/foundation/notifications/**
|
||||
src/features/crm/dashboard/**
|
||||
src/features/crm/document-templates/**
|
||||
```
|
||||
|
||||
High-priority pages:
|
||||
|
||||
```txt
|
||||
Lead list/detail
|
||||
Opportunity list/detail
|
||||
Quotation list/detail
|
||||
Approval history
|
||||
Approval settings
|
||||
Notification inbox
|
||||
Template settings
|
||||
Dashboard widgets
|
||||
Audit-safe activity views
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope 2: Create Shared Display Resolver
|
||||
|
||||
## Objective
|
||||
|
||||
Avoid repeating joins and label mapping everywhere.
|
||||
|
||||
Create shared foundation utilities:
|
||||
|
||||
```txt
|
||||
src/features/foundation/display/server/user-display-resolver.ts
|
||||
src/features/foundation/display/server/option-display-resolver.ts
|
||||
src/features/foundation/display/server/branch-display-resolver.ts
|
||||
src/features/foundation/display/server/display-resolver.ts
|
||||
```
|
||||
|
||||
Recommended APIs:
|
||||
|
||||
```ts
|
||||
resolveUserDisplays(ctx, userIds: string[])
|
||||
resolveOptionLabels(ctx, category: string, codes: string[])
|
||||
resolveBranchDisplays(ctx, branchIds: string[])
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* batch load to avoid N+1 queries
|
||||
* organization scoped
|
||||
* safe fallback
|
||||
* reusable by CRM services
|
||||
* not tied to one feature
|
||||
|
||||
---
|
||||
|
||||
# Scope 3: MS Option CRUD
|
||||
|
||||
## Objective
|
||||
|
||||
Add admin management for `ms_options`.
|
||||
|
||||
## Required APIs
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
GET /api/foundation/ms-options
|
||||
POST /api/foundation/ms-options
|
||||
GET /api/foundation/ms-options/[id]
|
||||
PATCH /api/foundation/ms-options/[id]
|
||||
DELETE /api/foundation/ms-options/[id]
|
||||
```
|
||||
|
||||
Optional category-specific API:
|
||||
|
||||
```txt
|
||||
GET /api/foundation/ms-options/categories
|
||||
GET /api/foundation/ms-options?category=crm_opportunity_stage
|
||||
```
|
||||
|
||||
## Required UI
|
||||
|
||||
Create settings page:
|
||||
|
||||
```txt
|
||||
/dashboard/settings/master-options
|
||||
```
|
||||
|
||||
or if CRM-scoped:
|
||||
|
||||
```txt
|
||||
/dashboard/crm/settings/master-options
|
||||
```
|
||||
|
||||
Recommended UI:
|
||||
|
||||
* category filter
|
||||
* option table
|
||||
* create option sheet
|
||||
* edit option sheet
|
||||
* soft delete / deactivate
|
||||
* active toggle
|
||||
* sort order
|
||||
* metadata JSON viewer/editor if needed
|
||||
|
||||
Fields:
|
||||
|
||||
```txt
|
||||
category
|
||||
code
|
||||
label
|
||||
value
|
||||
parentId
|
||||
sortOrder
|
||||
isActive
|
||||
metadata
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* `category + code + organizationId` must remain unique
|
||||
* cannot hard delete; use soft delete
|
||||
* inactive options should not appear in normal dropdowns
|
||||
* admin can view inactive options
|
||||
* no duplicate code in same category
|
||||
* code should be normalized to snake_case or documented format
|
||||
|
||||
---
|
||||
|
||||
# Scope 4: Seed Script Consolidation
|
||||
|
||||
## Objective
|
||||
|
||||
Create a clear, predictable seed hierarchy.
|
||||
|
||||
## Recommended Seed Layers
|
||||
|
||||
### 1. System seed
|
||||
|
||||
Required for system to boot:
|
||||
|
||||
```txt
|
||||
organization
|
||||
super admin
|
||||
admin membership
|
||||
base roles/permissions
|
||||
foundation master options
|
||||
document sequences
|
||||
approval default workflow
|
||||
approval matrix default
|
||||
notification templates
|
||||
quotation PDF template metadata
|
||||
```
|
||||
|
||||
Command:
|
||||
|
||||
```json
|
||||
"seed:system": "node --experimental-strip-types src/db/seeds/system.seed.ts"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. UAT seed
|
||||
|
||||
Demo/testing data only:
|
||||
|
||||
```txt
|
||||
sample customers
|
||||
sample contacts
|
||||
sample leads
|
||||
sample opportunities
|
||||
sample quotations
|
||||
sample approvals
|
||||
sample notifications
|
||||
```
|
||||
|
||||
Command:
|
||||
|
||||
```json
|
||||
"seed:uat": "node --experimental-strip-types src/db/seeds/uat.seed.ts"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. PDF template seed
|
||||
|
||||
Template-only reseed:
|
||||
|
||||
```json
|
||||
"seed:pdf-template": "node --experimental-strip-types scripts/reseed-pdf-template-version.ts"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Verification scripts
|
||||
|
||||
Keep as verification, not seed:
|
||||
|
||||
```json
|
||||
"verify:encoding"
|
||||
"verify:crm-access"
|
||||
"verify:pdf"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## New Standard Commands
|
||||
|
||||
Recommended `package.json` script structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:studio": "drizzle-kit studio",
|
||||
|
||||
"db:reset": "node --experimental-strip-types scripts/db/reset-database.ts",
|
||||
"db:setup": "npm run db:migrate && npm run seed:system",
|
||||
"db:setup:uat": "npm run db:setup && npm run seed:uat",
|
||||
"db:fresh": "npm run db:reset && npm run db:migrate && npm run seed:system",
|
||||
"db:fresh:uat": "npm run db:reset && npm run db:migrate && npm run seed:system && npm run seed:uat",
|
||||
|
||||
"seed:system": "node --experimental-strip-types src/db/seeds/system.seed.ts",
|
||||
"seed:uat": "node --experimental-strip-types src/db/seeds/uat.seed.ts",
|
||||
"seed:pdf-template": "node --experimental-strip-types scripts/reseed-pdf-template-version.ts",
|
||||
|
||||
"verify:encoding": "node scripts/verify-encoding.mjs",
|
||||
"verify:crm-access": "node --experimental-strip-types scripts/security/verify-crm-access.ts",
|
||||
"verify:pdf": "npm run audit:pdf",
|
||||
|
||||
"audit:pdf": "npm run audit:pdf:inventory && npm run audit:pdf:coverage && npm run audit:pdf:runtime && npm run audit:pdf:versions && npm run audit:pdf:placeholders && npm run audit:pdf:parity && npm run audit:pdf:snapshot && npm run audit:pdf:report && npm run audit:pdf:integrity"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope 5: Reset Database Script
|
||||
|
||||
## Objective
|
||||
|
||||
Create a controlled development reset script.
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
scripts/db/reset-database.ts
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
* connect to configured database
|
||||
* confirm environment is not production
|
||||
* drop public schema
|
||||
* recreate public schema
|
||||
* drop drizzle schema if present
|
||||
* exit cleanly
|
||||
|
||||
Required safety guard:
|
||||
|
||||
```txt
|
||||
NODE_ENV must not be production
|
||||
DATABASE_URL must not include production host/name
|
||||
ALLOW_DB_RESET=true required
|
||||
```
|
||||
|
||||
Example command:
|
||||
|
||||
```bash
|
||||
ALLOW_DB_RESET=true npm run db:reset
|
||||
```
|
||||
|
||||
Recommended SQL:
|
||||
|
||||
```sql
|
||||
DROP SCHEMA IF EXISTS public CASCADE;
|
||||
CREATE SCHEMA public;
|
||||
|
||||
DROP SCHEMA IF EXISTS drizzle CASCADE;
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* never run reset without explicit env flag
|
||||
* log target database before reset
|
||||
* fail fast if DATABASE_URL missing
|
||||
|
||||
---
|
||||
|
||||
# Scope 6: Existing Script Audit
|
||||
|
||||
## Objective
|
||||
|
||||
Classify existing scripts into keep, rename, merge, or remove.
|
||||
|
||||
Current scripts to audit:
|
||||
|
||||
```json
|
||||
"seed:super-admin": "node scripts/seed-super-admin.js",
|
||||
"seed:foundation": "node --experimental-strip-types src/db/seeds/foundation.seed.ts",
|
||||
"seed:crm-uat": "node --experimental-strip-types src/db/seeds/crm-uat.seed.ts",
|
||||
"seed:pdf-template-version": "node --experimental-strip-types scripts/reseed-pdf-template-version.ts",
|
||||
"migrate:membership-business-roles": "node --experimental-strip-types scripts/migrate-membership-business-roles.ts",
|
||||
"seed:task-h1-fixture": "node scripts/seed-task-h1-fixture.js",
|
||||
"verify:task-h1": "node scripts/verify-task-h1.js",
|
||||
"verify:task-h3": "node --experimental-strip-types scripts/verify-task-h3.js",
|
||||
"verify:crm-access": "node --experimental-strip-types scripts/security/verify-crm-access.ts",
|
||||
"audit:pdf:inventory": "node --experimental-strip-types scripts/audit-pdf-template-inventory.ts",
|
||||
"audit:pdf:coverage": "node --experimental-strip-types scripts/audit-pdf-mapping-coverage.ts",
|
||||
"audit:pdf:runtime": "node --experimental-strip-types scripts/audit-pdf-runtime-payload.ts",
|
||||
"audit:pdf:report": "node --experimental-strip-types scripts/generate-pdf-audit-report.ts",
|
||||
"verify:encoding": "node scripts/verify-encoding.mjs",
|
||||
"audit:pdf:versions": "node --experimental-strip-types scripts/audit-template-version-integrity.ts",
|
||||
"audit:pdf:placeholders": "node --experimental-strip-types scripts/audit-placeholder-integrity.ts",
|
||||
"audit:pdf:parity": "node --experimental-strip-types scripts/audit-payload-parity.ts",
|
||||
"audit:pdf:snapshot": "node --experimental-strip-types scripts/audit-approved-snapshot-parity.ts",
|
||||
"audit:pdf:integrity": "node --experimental-strip-types scripts/generate-pdf-integrity-report.ts",
|
||||
"audit:pdf": "npm run audit:pdf:inventory && npm run audit:pdf:coverage && npm run audit:pdf:runtime && npm run audit:pdf:versions && npm run audit:pdf:placeholders && npm run audit:pdf:parity && npm run audit:pdf:snapshot && npm run audit:pdf:report && npm run audit:pdf:integrity",
|
||||
"setup:db": "npm run migrate && npm run seed:super-admin && npm run seed:foundation"
|
||||
```
|
||||
|
||||
## Recommended Classification
|
||||
|
||||
### Rename / merge
|
||||
|
||||
```txt
|
||||
seed:super-admin
|
||||
seed:foundation
|
||||
```
|
||||
|
||||
Merge into:
|
||||
|
||||
```txt
|
||||
seed:system
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Rename
|
||||
|
||||
```txt
|
||||
seed:crm-uat
|
||||
```
|
||||
|
||||
to:
|
||||
|
||||
```txt
|
||||
seed:uat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Rename
|
||||
|
||||
```txt
|
||||
seed:pdf-template-version
|
||||
```
|
||||
|
||||
to:
|
||||
|
||||
```txt
|
||||
seed:pdf-template
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Keep but mark legacy/dev fixture
|
||||
|
||||
```txt
|
||||
seed:task-h1-fixture
|
||||
verify:task-h1
|
||||
verify:task-h3
|
||||
```
|
||||
|
||||
Move under:
|
||||
|
||||
```txt
|
||||
scripts/legacy/task-fixtures/
|
||||
```
|
||||
|
||||
or rename:
|
||||
|
||||
```txt
|
||||
legacy:seed:task-h1-fixture
|
||||
legacy:verify:task-h1
|
||||
legacy:verify:task-h3
|
||||
```
|
||||
|
||||
If no longer used, remove after confirming no docs/CI references them.
|
||||
|
||||
---
|
||||
|
||||
### Review migration script
|
||||
|
||||
```txt
|
||||
migrate:membership-business-roles
|
||||
```
|
||||
|
||||
If this was one-time historical migration, move to:
|
||||
|
||||
```txt
|
||||
scripts/legacy/migrations/
|
||||
```
|
||||
|
||||
and remove from common package scripts.
|
||||
|
||||
If still needed after reset, fold into migration or seed.
|
||||
|
||||
---
|
||||
|
||||
### Keep
|
||||
|
||||
```txt
|
||||
verify:crm-access
|
||||
verify:encoding
|
||||
audit:pdf:*
|
||||
audit:pdf
|
||||
```
|
||||
|
||||
These are still useful.
|
||||
|
||||
---
|
||||
|
||||
### Replace
|
||||
|
||||
```txt
|
||||
setup:db
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```txt
|
||||
db:setup
|
||||
db:setup:uat
|
||||
db:fresh
|
||||
db:fresh:uat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope 7: Bootstrap Documentation
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
docs/operations/system-bootstrap.md
|
||||
```
|
||||
|
||||
Must explain:
|
||||
|
||||
## Fresh local development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run db:fresh
|
||||
npm exec tsc --noEmit
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Fresh UAT/demo data
|
||||
|
||||
```bash
|
||||
npm run db:fresh:uat
|
||||
```
|
||||
|
||||
## Existing database upgrade
|
||||
|
||||
```bash
|
||||
npm run db:migrate
|
||||
npm run seed:system
|
||||
```
|
||||
|
||||
## PDF template reseed only
|
||||
|
||||
```bash
|
||||
npm run seed:pdf-template
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
npm exec tsc --noEmit
|
||||
npm run build
|
||||
npm run verify:encoding
|
||||
npm run verify:crm-access
|
||||
npm run audit:pdf
|
||||
```
|
||||
|
||||
## Script guide
|
||||
|
||||
Explain:
|
||||
|
||||
```txt
|
||||
db:* = database lifecycle
|
||||
seed:* = data bootstrap
|
||||
verify:* = validation
|
||||
audit:* = diagnostics
|
||||
legacy:* = old task-specific tools
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope 8: Acceptance Criteria
|
||||
|
||||
## Display names
|
||||
|
||||
* Created by / Updated by / Assigned by display as readable names
|
||||
* Branch displays as branch name/code
|
||||
* Option fields display labels
|
||||
* Raw IDs are not shown in normal user-facing UI unless intentionally technical
|
||||
|
||||
## MS option CRUD
|
||||
|
||||
* Admin can list options
|
||||
* Admin can create option
|
||||
* Admin can update option
|
||||
* Admin can deactivate / soft delete option
|
||||
* Dropdowns continue to use active options
|
||||
* Duplicate category/code is blocked
|
||||
|
||||
## Seed and setup
|
||||
|
||||
* `seed:system` exists
|
||||
* `seed:uat` exists
|
||||
* `db:reset` exists with safety guard
|
||||
* `db:fresh` works
|
||||
* `db:fresh:uat` works
|
||||
* old scripts are classified or removed
|
||||
* system bootstrap docs exist
|
||||
|
||||
## Verification
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm exec tsc --noEmit
|
||||
npm run build
|
||||
npm run verify:encoding
|
||||
```
|
||||
|
||||
Optional:
|
||||
|
||||
```bash
|
||||
npm run db:fresh
|
||||
npm run db:fresh:uat
|
||||
npm run verify:crm-access
|
||||
npm run audit:pdf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Definition of Done
|
||||
|
||||
Task is complete when:
|
||||
|
||||
* active UI no longer exposes raw user/branch/option IDs where display names are expected
|
||||
* `ms_options` has CRUD API and settings UI
|
||||
* system seed is consolidated
|
||||
* UAT seed is separated
|
||||
* database reset script exists and is guarded
|
||||
* package scripts are organized and understandable
|
||||
* old scripts are documented, renamed, moved, or removed
|
||||
* bootstrap documentation is available
|
||||
|
||||
Result:
|
||||
|
||||
```txt
|
||||
Foundation Admin UX = Improved
|
||||
Master Option Management = Operational
|
||||
System Bootstrap = Standardized
|
||||
Database Reset = Safe and Repeatable
|
||||
Script Surface = Clean and Understandable
|
||||
```
|
||||
Reference in New Issue
Block a user