feat(cohorts): rename Programs to Cohorts with data migration (#694)
* feat(cohorts): rename Programs to Cohorts with data migration - Add cohort database tables and Drizzle migration alongside legacy program tables - Introduce migrate-programs-to-cohorts script to copy existing program data safely - Rename API routes (/cohort), services, queries, validation, and error codes - Rename dashboard feature module, routes (/cohorts), navigation, and translations - Update docs, emails, and internal compliance cron endpoints for cohort terminology - Keep legacy program tables in place for rollback until explicitly removed Co-authored-by: Rotimi Best <[email protected]> * fix(db): restore migrate:answer-data script alongside cohort migration Co-authored-by: Rotimi Best <[email protected]> * fix(db): cast program enums when migrating data to cohort tables Co-authored-by: Rotimi Best <[email protected]> * fix(db): truncate cohort tables before program-to-cohort copy Co-authored-by: Rotimi Best <[email protected]> * fix(db): report accurate row counts in programs-to-cohorts migration Co-authored-by: Rotimi Best <[email protected]> --------- Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
co-authored by
Rotimi Best
Cursor Agent
parent
fe9f8c441f
commit
ec61bfe7d9
@@ -0,0 +1,114 @@
|
||||
CREATE TYPE "public"."COHORT_GOAL_ASSIGNMENT_STATUS" AS ENUM('not_started', 'in_progress', 'completed', 'at_risk', 'overdue', 'waived');--> statement-breakpoint
|
||||
CREATE TYPE "public"."COHORT_GOAL_DEADLINE_KIND" AS ENUM('absolute', 'relative_to_join', 'recurring', 'none');--> statement-breakpoint
|
||||
CREATE TYPE "public"."COHORT_GOAL_STATUS" AS ENUM('active', 'archived');--> statement-breakpoint
|
||||
CREATE TYPE "public"."COHORT_GOAL_TYPE" AS ENUM('complete_all', 'n_of_m', 'score', 'pass_rate', 'readiness');--> statement-breakpoint
|
||||
CREATE TYPE "public"."COHORT_STATUS" AS ENUM('ACTIVE', 'INACTIVE', 'ARCHIVED');--> statement-breakpoint
|
||||
CREATE TABLE "cohort" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now(),
|
||||
"organization_id" uuid NOT NULL,
|
||||
"name" varchar NOT NULL,
|
||||
"description" text,
|
||||
"cover_image" text,
|
||||
"status" "COHORT_STATUS" DEFAULT 'ACTIVE' NOT NULL,
|
||||
"created_by_profile_id" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "cohort_course" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"cohort_id" uuid NOT NULL,
|
||||
"course_id" uuid NOT NULL,
|
||||
"added_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "cohort_course_cohort_id_course_id_unique" UNIQUE("cohort_id","course_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "cohort_goal" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"cohort_id" uuid NOT NULL,
|
||||
"title" varchar(255) NOT NULL,
|
||||
"description" text,
|
||||
"type" "COHORT_GOAL_TYPE" NOT NULL,
|
||||
"course_ids" jsonb DEFAULT '[]'::jsonb NOT NULL,
|
||||
"required_count" integer,
|
||||
"score_threshold" integer,
|
||||
"team_pass_rate_threshold" integer,
|
||||
"deadline_kind" "COHORT_GOAL_DEADLINE_KIND" DEFAULT 'none' NOT NULL,
|
||||
"deadline_date" timestamp with time zone,
|
||||
"relative_days" integer,
|
||||
"recurring_months" integer,
|
||||
"reminder_days_before" jsonb DEFAULT '[7,1]'::jsonb NOT NULL,
|
||||
"status" "COHORT_GOAL_STATUS" DEFAULT 'active' NOT NULL,
|
||||
"created_by_profile_id" uuid,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "cohort_goal_assignment" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"goal_id" uuid NOT NULL,
|
||||
"cohort_member_id" uuid NOT NULL,
|
||||
"due_date" timestamp with time zone,
|
||||
"status" "COHORT_GOAL_ASSIGNMENT_STATUS" DEFAULT 'not_started' NOT NULL,
|
||||
"completed_count" integer DEFAULT 0 NOT NULL,
|
||||
"required_count" integer DEFAULT 0 NOT NULL,
|
||||
"completed_at" timestamp with time zone,
|
||||
"last_evaluated_at" timestamp with time zone,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "cohort_goal_assignment_goal_id_cohort_member_id_unique" UNIQUE("goal_id","cohort_member_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "cohort_member" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"cohort_id" uuid NOT NULL,
|
||||
"profile_id" uuid,
|
||||
"role_id" integer NOT NULL,
|
||||
"email" text,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "cohort_member_cohort_id_profile_id_unique" UNIQUE("cohort_id","profile_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "cohort_newsfeed" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"author_id" uuid,
|
||||
"cohort_id" uuid,
|
||||
"content" text,
|
||||
"reaction" jsonb DEFAULT '{"clap":[],"smile":[],"thumbsup":[],"thumbsdown":[]}'::jsonb,
|
||||
"is_pinned" boolean DEFAULT false NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "cohort_newsfeed_comment" (
|
||||
"id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "cohort_newsfeed_comment_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"author_id" uuid,
|
||||
"content" text,
|
||||
"cohort_newsfeed_id" uuid
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "cohort" ADD CONSTRAINT "cohort_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort" ADD CONSTRAINT "cohort_created_by_profile_id_fkey" FOREIGN KEY ("created_by_profile_id") REFERENCES "public"."profile"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_course" ADD CONSTRAINT "cohort_course_cohort_id_fkey" FOREIGN KEY ("cohort_id") REFERENCES "public"."cohort"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_course" ADD CONSTRAINT "cohort_course_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "public"."course"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_goal" ADD CONSTRAINT "cohort_goal_cohort_id_fkey" FOREIGN KEY ("cohort_id") REFERENCES "public"."cohort"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_goal" ADD CONSTRAINT "cohort_goal_created_by_profile_id_fkey" FOREIGN KEY ("created_by_profile_id") REFERENCES "public"."profile"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_goal_assignment" ADD CONSTRAINT "cohort_goal_assignment_goal_id_fkey" FOREIGN KEY ("goal_id") REFERENCES "public"."cohort_goal"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_goal_assignment" ADD CONSTRAINT "cohort_goal_assignment_cohort_member_id_fkey" FOREIGN KEY ("cohort_member_id") REFERENCES "public"."cohort_member"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_member" ADD CONSTRAINT "cohort_member_cohort_id_fkey" FOREIGN KEY ("cohort_id") REFERENCES "public"."cohort"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_member" ADD CONSTRAINT "cohort_member_profile_id_fkey" FOREIGN KEY ("profile_id") REFERENCES "public"."profile"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_member" ADD CONSTRAINT "cohort_member_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "public"."role"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_newsfeed" ADD CONSTRAINT "cohort_newsfeed_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."cohort_member"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_newsfeed" ADD CONSTRAINT "cohort_newsfeed_cohort_id_fkey" FOREIGN KEY ("cohort_id") REFERENCES "public"."cohort"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_newsfeed_comment" ADD CONSTRAINT "cohort_newsfeed_comment_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."cohort_member"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "cohort_newsfeed_comment" ADD CONSTRAINT "cohort_newsfeed_comment_cohort_newsfeed_id_fkey" FOREIGN KEY ("cohort_newsfeed_id") REFERENCES "public"."cohort_newsfeed"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_organization_id" ON "cohort" USING btree ("organization_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_course_cohort_id" ON "cohort_course" USING btree ("cohort_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_goal_cohort_id" ON "cohort_goal" USING btree ("cohort_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_goal_status" ON "cohort_goal" USING btree ("status");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_goal_assignment_goal_id" ON "cohort_goal_assignment" USING btree ("goal_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_goal_assignment_cohort_member_id" ON "cohort_goal_assignment" USING btree ("cohort_member_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_goal_assignment_due_date" ON "cohort_goal_assignment" USING btree ("due_date");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_member_cohort_id" ON "cohort_member" USING btree ("cohort_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_member_profile_id" ON "cohort_member" USING btree ("profile_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_cohort_newsfeed_cohort_id" ON "cohort_newsfeed" USING btree ("cohort_id");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,13 @@
|
||||
"when": 1782684436805,
|
||||
"tag": "0001_slow_lila_cheney",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "7",
|
||||
"when": 1782660458258,
|
||||
"tag": "0002_majestic_masked_marvel",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user