Add new AssignmentTransfers collection with fields for managing assignment transfer requests: - requestor, requestedAssignment, currentAssignment (relationships to users/assignments) - status (pending/approved/rejected/appealed/escalated/completed/cancelled) - rejectionReason, appealReason (for rejections and appeals) - transferAt, approvedAt, appealedAt, completedAt (audit timestamps) - transferLead (relationship to users, current and requested assignment leaders) - requestMessage, appealMessage (optional context messages) Add database migrations: - 20260831_180233_assignment_transfers: Create the main collection table - 20260901_014006_add_assignment_transfer_event_target: Add assignment-transfers to GameEventLogs target collections The collection enables the assignment transfer workflow where users can request transfers, leaders can approve/reject with reasons, and users can appeal rejections.
80 lines
7 KiB
TypeScript
80 lines
7 KiB
TypeScript
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
|
|
|
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
|
await db.execute(sql`
|
|
CREATE TYPE "public"."enum_assignment_transfers_status" AS ENUM('pending', 'rejected', 'awaiting_superuser', 'completed', 'cancelled', 'denied');
|
|
CREATE TYPE "public"."enum_assignment_transfers_escalation_reason" AS ENUM('no_leaders', 'appeal', 'leader_changed');
|
|
CREATE TYPE "public"."enum_assignment_transfers_from_leader_decision" AS ENUM('pending', 'approved', 'rejected', 'not_required');
|
|
CREATE TYPE "public"."enum_assignment_transfers_to_leader_decision" AS ENUM('pending', 'approved', 'rejected', 'not_required');
|
|
CREATE TABLE "assignment_transfers" (
|
|
"id" serial PRIMARY KEY NOT NULL,
|
|
"requester_id" integer NOT NULL,
|
|
"from_assignment_id" integer NOT NULL,
|
|
"to_assignment_id" integer NOT NULL,
|
|
"status" "enum_assignment_transfers_status" DEFAULT 'pending' NOT NULL,
|
|
"escalation_reason" "enum_assignment_transfers_escalation_reason",
|
|
"from_leader_decision" "enum_assignment_transfers_from_leader_decision" DEFAULT 'pending' NOT NULL,
|
|
"to_leader_decision" "enum_assignment_transfers_to_leader_decision" DEFAULT 'pending' NOT NULL,
|
|
"from_decision_by_id" integer,
|
|
"to_decision_by_id" integer,
|
|
"from_decided_at" timestamp(3) with time zone,
|
|
"to_decided_at" timestamp(3) with time zone,
|
|
"from_leader_snapshot_id" integer,
|
|
"to_leader_snapshot_id" integer,
|
|
"rejection_reason" varchar,
|
|
"request_note" varchar,
|
|
"appeal_note" varchar,
|
|
"resolved_by_id" integer,
|
|
"resolution_note" varchar,
|
|
"resolved_at" timestamp(3) with time zone,
|
|
"discord_from_leader_message_id" varchar,
|
|
"discord_to_leader_message_id" varchar,
|
|
"discord_requester_message_id" varchar,
|
|
"source_notified_to_user_id_id" integer,
|
|
"destination_notified_to_user_id_id" integer,
|
|
"discord_delivered_keys" jsonb DEFAULT '[]'::jsonb,
|
|
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
|
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
|
);
|
|
|
|
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "assignment_transfers_id" integer;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_requester_id_users_id_fk" FOREIGN KEY ("requester_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_from_assignment_id_assignments_id_fk" FOREIGN KEY ("from_assignment_id") REFERENCES "public"."assignments"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_to_assignment_id_assignments_id_fk" FOREIGN KEY ("to_assignment_id") REFERENCES "public"."assignments"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_from_decision_by_id_users_id_fk" FOREIGN KEY ("from_decision_by_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_to_decision_by_id_users_id_fk" FOREIGN KEY ("to_decision_by_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_from_leader_snapshot_id_users_id_fk" FOREIGN KEY ("from_leader_snapshot_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_to_leader_snapshot_id_users_id_fk" FOREIGN KEY ("to_leader_snapshot_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_resolved_by_id_users_id_fk" FOREIGN KEY ("resolved_by_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_source_notified_to_user_id_id_users_id_fk" FOREIGN KEY ("source_notified_to_user_id_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
ALTER TABLE "assignment_transfers" ADD CONSTRAINT "assignment_transfers_destination_notified_to_user_id_id_users_id_fk" FOREIGN KEY ("destination_notified_to_user_id_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
CREATE INDEX "assignment_transfers_requester_idx" ON "assignment_transfers" USING btree ("requester_id");
|
|
CREATE INDEX "assignment_transfers_from_assignment_idx" ON "assignment_transfers" USING btree ("from_assignment_id");
|
|
CREATE INDEX "assignment_transfers_to_assignment_idx" ON "assignment_transfers" USING btree ("to_assignment_id");
|
|
CREATE INDEX "assignment_transfers_status_idx" ON "assignment_transfers" USING btree ("status");
|
|
CREATE INDEX "assignment_transfers_from_decision_by_idx" ON "assignment_transfers" USING btree ("from_decision_by_id");
|
|
CREATE INDEX "assignment_transfers_to_decision_by_idx" ON "assignment_transfers" USING btree ("to_decision_by_id");
|
|
CREATE INDEX "assignment_transfers_from_leader_snapshot_idx" ON "assignment_transfers" USING btree ("from_leader_snapshot_id");
|
|
CREATE INDEX "assignment_transfers_to_leader_snapshot_idx" ON "assignment_transfers" USING btree ("to_leader_snapshot_id");
|
|
CREATE INDEX "assignment_transfers_resolved_by_idx" ON "assignment_transfers" USING btree ("resolved_by_id");
|
|
CREATE INDEX "assignment_transfers_source_notified_to_user_id_idx" ON "assignment_transfers" USING btree ("source_notified_to_user_id_id");
|
|
CREATE INDEX "assignment_transfers_destination_notified_to_user_id_idx" ON "assignment_transfers" USING btree ("destination_notified_to_user_id_id");
|
|
CREATE INDEX "assignment_transfers_updated_at_idx" ON "assignment_transfers" USING btree ("updated_at");
|
|
CREATE INDEX "assignment_transfers_created_at_idx" ON "assignment_transfers" USING btree ("created_at");
|
|
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_assignment_transfers_fk" FOREIGN KEY ("assignment_transfers_id") REFERENCES "public"."assignment_transfers"("id") ON DELETE cascade ON UPDATE no action;
|
|
CREATE INDEX "payload_locked_documents_rels_assignment_transfers_id_idx" ON "payload_locked_documents_rels" USING btree ("assignment_transfers_id");`)
|
|
}
|
|
|
|
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
|
await db.execute(sql`
|
|
ALTER TABLE "assignment_transfers" DISABLE ROW LEVEL SECURITY;
|
|
DROP TABLE "assignment_transfers" CASCADE;
|
|
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_assignment_transfers_fk";
|
|
|
|
DROP INDEX "payload_locked_documents_rels_assignment_transfers_id_idx";
|
|
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN "assignment_transfers_id";
|
|
DROP TYPE "public"."enum_assignment_transfers_status";
|
|
DROP TYPE "public"."enum_assignment_transfers_escalation_reason";
|
|
DROP TYPE "public"."enum_assignment_transfers_from_leader_decision";
|
|
DROP TYPE "public"."enum_assignment_transfers_to_leader_decision";`)
|
|
}
|