Files
alla-tms/docs/organizers-module-enhancement-report.md
2026-07-16 09:53:14 +07:00

6.0 KiB

Organizers Module Enhancement Report

Executive Summary

The organizers module was upgraded from a minimal create-and-list page into a CRUD-oriented management flow that supports soft delete, shared validation, audit logging, and runtime filtering for inactive organizers. The implementation keeps the existing Auth.js and Drizzle architecture intact and avoids introducing a new permission pattern that would conflict with the current super-admin entry flow.

Current Architecture

  • Next.js App Router with route handlers under src/app/api
  • Auth.js session enrichment in src/auth.ts
  • Drizzle ORM schema in src/db/schema.ts
  • Feature-owned API/query/mutation contracts in src/features/organizers
  • Shared UI stack with Sheet, DropdownMenu, AlertModal, and PageContainer

Current Limitation

Before this enhancement, organizers only supported create and basic list rendering. There was no edit action, no soft delete, no inactive filtering in session flows, no feature API layer, and no organizer-specific audit events.

Root Cause Analysis

  • The original organizers page used direct fetch() calls and local state instead of the shared feature API/query pattern.
  • The database schema did not include soft-delete metadata for organizations.
  • Auth session enrichment loaded organizations without filtering inactive records.
  • Route handlers existed only for GET and POST, so update and delete behavior was missing.

Feature Comparison

Before

  • View organizers
  • Create organizer

After

  • View active and inactive organizers
  • Create organizer
  • Edit organizer name
  • Soft delete organizer
  • Validation for required, trim, duplicate, length, and invalid characters
  • Audit log for create, update, and soft delete
  • Session and switcher filtering for inactive organizers

Files Modified

  • src/db/schema.ts
  • drizzle/0017_organizers_soft_delete.sql
  • src/features/audit-logs/server/audit-service.ts
  • src/features/organizers/api/types.ts
  • src/features/organizers/api/service.ts
  • src/features/organizers/api/queries.ts
  • src/features/organizers/api/mutations.ts
  • src/features/organizers/schemas/organizer.ts
  • src/features/organizers/server/organizer-data.ts
  • src/app/api/organizations/route.ts
  • src/app/api/organizations/[id]/route.ts
  • src/app/api/organizations/active/route.ts
  • src/auth.ts
  • src/lib/auth/session.ts
  • src/features/users/server/user-data.ts
  • src/components/modal/alert-modal.tsx
  • src/components/org-switcher.tsx
  • src/features/organizers/components/organizer-form-sheet.tsx
  • src/features/organizers/components/organizer-card-actions.tsx
  • src/features/organizers/components/organizer-listing.tsx
  • src/features/organizers/components/organizers-page.tsx
  • src/app/dashboard/organizers/page.tsx

Database Changes

  • Added organizations.is_active
  • Added organizations.deleted_at
  • Added organizations.deleted_by
  • Added foreign key from deleted_by to users.id

API Changes

  • GET /api/organizations supports organizer status filtering
  • POST /api/organizations uses shared zod validation and duplicate checks
  • PATCH /api/organizations/[id] updates organizer name
  • DELETE /api/organizations/[id] performs soft delete only
  • PATCH /api/organizations/active rejects inactive organizers

UI Changes

  • Replaced the local-state page with a React Query driven listing
  • Added shared Sheet form for create and edit
  • Added shared dropdown row actions
  • Added confirmation modal for soft delete
  • Added active/inactive status display and management notes

Permission Changes

  • Read access remains aligned to the existing page gate for HRD and super admin
  • Create, edit, and soft delete are restricted to requireSuperAdmin() in the current architecture
  • The implementation intentionally did not force org-scoped permission helpers onto the organizer entry flow because they depend on an active organization

Validation Changes

  • Organizer name is required
  • Input is trimmed
  • Maximum length is enforced
  • Invalid characters are rejected
  • Duplicate active organizer names are rejected
  • Inactive and missing records are rejected on update/delete

Soft Delete Design

  • Soft delete updates the organizer record instead of physically deleting it
  • Disabled organizers are marked with is_active = false
  • Deletion metadata is stored in deleted_at and deleted_by
  • Related users, memberships, training data, permissions, and audit history remain intact
  • Inactive organizers are filtered out from runtime session and switcher flows

Audit Log

  • Added ORGANIZATIONS module
  • Added ORGANIZATION_CREATE
  • Added ORGANIZATION_UPDATE
  • Added ORGANIZATION_SOFT_DELETE

Testing Result

Create

  • Added backend validation and duplicate checks
  • Manual runtime verification still required

Edit

  • Added update route and audit logging
  • Manual runtime verification still required

Delete

  • Soft delete only
  • Inactive organizers are blocked from re-delete

Permission

  • Management actions remain server-protected by super-admin checks
  • UI hides management actions for non-managing users

Regression

  • Session loading now excludes inactive organizers
  • Organization switching now rejects inactive organizers
  • User management lookups now reject inactive target organizations

Risks

  • Existing data with duplicate organizer names may need manual review before relying on new duplicate constraints operationally
  • Super-admin users who disable many organizers should still be tested against real seeded data to confirm expected fallback behavior

Recommendations

  • Add focused route-handler tests for organizers create/update/delete flows
  • Add browser-level regression coverage for the organizers page and organization switcher
  • Consider introducing a dedicated system-scoped permission helper if organizer administration expands beyond super admin

Future Improvements

  • Add search and status filtering controls on the organizers page
  • Surface audit history for an organizer directly from the management UI
  • Support organization metadata expansion when the schema grows beyond name and plan