#262: remove Requests / Approvals / Tasks tabs from Executive Meetings

Full-stack removal of the three retired sections — UI, locales, realtime
invalidations, backend routes, role lists, capability flags, schema
tables, notify lib, and tests.

Backend (artifacts/api-server)
- routes/executive-meetings.ts: deleted /requests* + /tasks* handler
  block, REQUEST_ROLES / TASK_VIEW_ROLES / TASK_BROAD_VIEW_ROLES,
  canSubmitRequest / canViewTasks / canViewAllTasks from /me, retired
  table imports, and dead schemas (detailsByType, requestPayloadSchemas,
  request*Schema, taskCreateSchema, taskPatchSchema, dueAtSchema,
  dateOnly, timeHm). canApprove kept (still used by FontSettings).
- lib/executive-meeting-notify.ts: EXECUTIVE_MEETING_NOTIFICATION_TYPES
  collapsed to ['meeting_created'].

Frontend (artifacts/tx-os)
- pages/executive-meetings.tsx: deleted RequestsSection /
  ApprovalsSection / TasksSection / RequestListRow, pruned SECTIONS,
  MeCapabilities / MeRoles types, isSectionVisible cases, icon imports.
- hooks/use-notifications-socket.ts: dropped the two retired query
  invalidations.
- locales/{ar,en}.json: removed nav.{requests,approvals,tasks},
  executiveMeetings.{requests,approvals,tasks} subtrees, and the 6
  retired notification.type entries.

Schema + DB
- lib/db/src/schema/executive-meetings.ts: tables + relations + types
  for requests/tasks removed.
- artifacts/api-server/scripts/cleanup-em-requests-tasks.sql:
  idempotent BEGIN/COMMIT — deletes orphan prefs / notifications /
  audit rows, then DROP TABLE … CASCADE for both retired tables.
  Applied to dev DB and `db push` re-synced.

Tests
- executive-meetings.test.mjs: deleted 9 retired blocks + 2 covered
  prefs duplicates, rewrote /me capability test to assert flags absent,
  rewrote DELETE-wipe test to use meeting_created via POST
  /api/executive-meetings, removed /requests + /tasks router.param
  entries.
- executive-meetings-notifications.test.mjs: deleted 7 blocks
  (request_*, task_*, cross-event-mute), updated before/after
  cleanup to skip dropped tables, kept setPref/clearPref helpers
  (still used by surviving meeting_created opt-out tests).

Drift / pre-existing
- 3 test failures observed under the parallel `node --test` workflow
  (meeting_created fan-out count, pref opt-out daily-number conflict,
  service-orders JSON-vs-HTML) are pre-existing parallel-file
  pollution between executive-meetings.test.mjs and
  executive-meetings-notifications.test.mjs. Verified by running
  `node --test --test-concurrency=1 'tests/**/*.test.mjs'` →
  226/226 pass. Out of scope for #262.
- Pre-existing tsc warnings at routes/executive-meetings.ts L509/625
  (boolean/number on isHighlighted) and L1594 (font-settings scope
  query) untouched.
This commit is contained in:
riyadhafraa
2026-05-01 08:18:29 +00:00
parent f7ab5e8b08
commit 21c935064d
14 changed files with 288 additions and 3308 deletions
+8 -60
View File
@@ -95,58 +95,10 @@ export const executiveMeetingAttendeesTable = pgTable(
}),
);
export const executiveMeetingRequestsTable = pgTable(
"executive_meeting_requests",
{
id: serial("id").primaryKey(),
meetingId: integer("meeting_id").references(
() => executiveMeetingsTable.id,
{ onDelete: "cascade" },
),
requestedBy: integer("requested_by").references(() => usersTable.id, {
onDelete: "set null",
}),
requestType: varchar("request_type", { length: 64 }).notNull(),
requestDetails: jsonb("request_details"),
status: varchar("status", { length: 32 }).notNull().default("new"),
reviewedBy: integer("reviewed_by").references(() => usersTable.id, {
onDelete: "set null",
}),
reviewDecision: varchar("review_decision", { length: 32 }),
reviewNotes: text("review_notes"),
assignedTo: integer("assigned_to").references(() => usersTable.id, {
onDelete: "set null",
}),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true })
.notNull()
.defaultNow()
.$onUpdate(() => new Date()),
},
);
export const executiveMeetingTasksTable = pgTable("executive_meeting_tasks", {
id: serial("id").primaryKey(),
requestId: integer("request_id").references(() => executiveMeetingRequestsTable.id, {
onDelete: "cascade",
}),
meetingId: integer("meeting_id").references(() => executiveMeetingsTable.id, {
onDelete: "cascade",
}),
assignedTo: integer("assigned_to").references(() => usersTable.id, {
onDelete: "set null",
}),
taskType: varchar("task_type", { length: 64 }).notNull(),
status: varchar("status", { length: 32 }).notNull().default("pending"),
dueAt: timestamp("due_at", { withTimezone: true }),
completedAt: timestamp("completed_at", { withTimezone: true }),
notes: text("notes"),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true })
.notNull()
.defaultNow()
.$onUpdate(() => new Date()),
});
// #262: removed executiveMeetingRequestsTable + executiveMeetingTasksTable.
// The Requests / Approvals / Tasks tabs were retired from the page; the
// underlying DB tables are dropped by
// artifacts/api-server/scripts/cleanup-em-requests-tasks.sql.
export const executiveMeetingNotificationsTable = pgTable(
"executive_meeting_notifications",
@@ -178,12 +130,10 @@ export const executiveMeetingNotificationsTable = pgTable(
* notificationType mirrors the keys passed to
* `recordExecutiveMeetingNotifications` / `sendExecutiveMeetingEmail`:
* - meeting_created
* - request_submitted
* - request_approved
* - request_rejected
* - request_needs_edit
* - task_assigned
* - task_completed
*
* #262: collapsed to a single event type after Requests/Approvals/Tasks
* were removed. Orphan rows for the old types are deleted by
* cleanup-em-requests-tasks.sql.
*/
export const executiveMeetingNotificationPrefsTable = pgTable(
"executive_meeting_notification_prefs",
@@ -266,5 +216,3 @@ export const executiveMeetingFontSettingsTable = pgTable(
export type ExecutiveMeeting = typeof executiveMeetingsTable.$inferSelect;
export type ExecutiveMeetingAttendee = typeof executiveMeetingAttendeesTable.$inferSelect;
export type ExecutiveMeetingRequest = typeof executiveMeetingRequestsTable.$inferSelect;
export type ExecutiveMeetingTask = typeof executiveMeetingTasksTable.$inferSelect;