Cases are one queue for what someone has to decide, each with a thread (internal notes for those deciding), an assignee and a decision. Reports about a product go to the teams of the catalogs hosting it and to moderators, and only the reporter and moderators know who reported. A creator lowering a rating opens a rating review; a catalog's owner asking to delete it opens a deletion request; a catalog's team can ask for a product's removal everywhere; the person an action affected can appeal it once, decided by another moderator (an admin may decide their own, flagged). Resolving carries the case out: the rating is lowered, the product removed, the catalog deleted. Notifications reach people on the website (a bell with the unread count) and their proxies (realtime): moderators' edits to their products, removals and restores, decisions and replies on their cases, membership decisions. Also: moderators can restore a removed product, and a product's creator and moderators can see it when it's adult without an adult account (getting and wearing it still need one). Co-Authored-By: Claude Opus 5.5 <[email protected]>
46 lines
2.8 KiB
SQL
46 lines
2.8 KiB
SQL
CREATE TABLE "case_note" (
|
|
"id" serial PRIMARY KEY NOT NULL,
|
|
"case_id" integer NOT NULL,
|
|
"by_id" text,
|
|
"body" text NOT NULL,
|
|
"internal" boolean DEFAULT false NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE "moderation_case" (
|
|
"id" serial PRIMARY KEY NOT NULL,
|
|
"kind" text NOT NULL,
|
|
"status" text DEFAULT 'open' NOT NULL,
|
|
"tags" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
"opened_by" text,
|
|
"assignee" text,
|
|
"reason" text DEFAULT '' NOT NULL,
|
|
"data" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
"resolution" text DEFAULT '' NOT NULL,
|
|
"decided_by" text,
|
|
"decided_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
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE "notification" (
|
|
"id" serial PRIMARY KEY NOT NULL,
|
|
"user_id" text NOT NULL,
|
|
"type" text NOT NULL,
|
|
"tags" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
"data" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"read_at" timestamp with time zone
|
|
);
|
|
--> statement-breakpoint
|
|
ALTER TABLE "case_note" ADD CONSTRAINT "case_note_case_id_moderation_case_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."moderation_case"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "case_note" ADD CONSTRAINT "case_note_by_id_user_id_fk" FOREIGN KEY ("by_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "moderation_case" ADD CONSTRAINT "moderation_case_opened_by_user_id_fk" FOREIGN KEY ("opened_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "moderation_case" ADD CONSTRAINT "moderation_case_assignee_user_id_fk" FOREIGN KEY ("assignee") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "moderation_case" ADD CONSTRAINT "moderation_case_decided_by_user_id_fk" FOREIGN KEY ("decided_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
ALTER TABLE "notification" ADD CONSTRAINT "notification_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
CREATE INDEX "case_note_case" ON "case_note" USING btree ("case_id","id");--> statement-breakpoint
|
|
CREATE INDEX "moderation_case_status" ON "moderation_case" USING btree ("status","id");--> statement-breakpoint
|
|
CREATE INDEX "moderation_case_opened_by" ON "moderation_case" USING btree ("opened_by");--> statement-breakpoint
|
|
CREATE INDEX "moderation_case_tags" ON "moderation_case" USING gin ("tags");--> statement-breakpoint
|
|
CREATE INDEX "notification_user" ON "notification" USING btree ("user_id","id"); |