diff --git a/resolution-frontend/drizzle/0000_curly_raza.sql b/resolution-frontend/drizzle.backup/0000_curly_raza.sql similarity index 100% rename from resolution-frontend/drizzle/0000_curly_raza.sql rename to resolution-frontend/drizzle.backup/0000_curly_raza.sql diff --git a/resolution-frontend/drizzle/0001_burly_caretaker.sql b/resolution-frontend/drizzle.backup/0001_burly_caretaker.sql similarity index 100% rename from resolution-frontend/drizzle/0001_burly_caretaker.sql rename to resolution-frontend/drizzle.backup/0001_burly_caretaker.sql diff --git a/resolution-frontend/drizzle/0002_luxuriant_maria_hill.sql b/resolution-frontend/drizzle.backup/0002_luxuriant_maria_hill.sql similarity index 100% rename from resolution-frontend/drizzle/0002_luxuriant_maria_hill.sql rename to resolution-frontend/drizzle.backup/0002_luxuriant_maria_hill.sql diff --git a/resolution-frontend/drizzle/0003_misty_week_prize_image.sql b/resolution-frontend/drizzle.backup/0003_misty_week_prize_image.sql similarity index 100% rename from resolution-frontend/drizzle/0003_misty_week_prize_image.sql rename to resolution-frontend/drizzle.backup/0003_misty_week_prize_image.sql diff --git a/resolution-frontend/drizzle/0004_left_pretty_boy.sql b/resolution-frontend/drizzle.backup/0004_left_pretty_boy.sql similarity index 100% rename from resolution-frontend/drizzle/0004_left_pretty_boy.sql rename to resolution-frontend/drizzle.backup/0004_left_pretty_boy.sql diff --git a/resolution-frontend/drizzle/0005_add_package_type_and_orders.sql b/resolution-frontend/drizzle.backup/0005_add_package_type_and_orders.sql similarity index 100% rename from resolution-frontend/drizzle/0005_add_package_type_and_orders.sql rename to resolution-frontend/drizzle.backup/0005_add_package_type_and_orders.sql diff --git a/resolution-frontend/drizzle/0006_add_templates_and_batches.sql b/resolution-frontend/drizzle.backup/0006_add_templates_and_batches.sql similarity index 100% rename from resolution-frontend/drizzle/0006_add_templates_and_batches.sql rename to resolution-frontend/drizzle.backup/0006_add_templates_and_batches.sql diff --git a/resolution-frontend/drizzle.backup/0006_worried_hedge_knight.sql b/resolution-frontend/drizzle.backup/0006_worried_hedge_knight.sql new file mode 100644 index 0000000..08f6c9f --- /dev/null +++ b/resolution-frontend/drizzle.backup/0006_worried_hedge_knight.sql @@ -0,0 +1 @@ +DROP TABLE "fufiller_pathway" CASCADE; \ No newline at end of file diff --git a/resolution-frontend/drizzle/0007_add_label_tracking_fields.sql b/resolution-frontend/drizzle.backup/0007_add_label_tracking_fields.sql similarity index 100% rename from resolution-frontend/drizzle/0007_add_label_tracking_fields.sql rename to resolution-frontend/drizzle.backup/0007_add_label_tracking_fields.sql diff --git a/resolution-frontend/drizzle.backup/0007_tense_captain_cross.sql b/resolution-frontend/drizzle.backup/0007_tense_captain_cross.sql new file mode 100644 index 0000000..1ffd014 --- /dev/null +++ b/resolution-frontend/drizzle.backup/0007_tense_captain_cross.sql @@ -0,0 +1 @@ +ALTER TABLE "shop_orders" ADD COLUMN "phone" text; diff --git a/resolution-frontend/drizzle/0008_add_hs_code.sql b/resolution-frontend/drizzle.backup/0008_add_hs_code.sql similarity index 100% rename from resolution-frontend/drizzle/0008_add_hs_code.sql rename to resolution-frontend/drizzle.backup/0008_add_hs_code.sql diff --git a/resolution-frontend/drizzle/0009_add_packaging_columns.sql b/resolution-frontend/drizzle.backup/0009_add_packaging_columns.sql similarity index 100% rename from resolution-frontend/drizzle/0009_add_packaging_columns.sql rename to resolution-frontend/drizzle.backup/0009_add_packaging_columns.sql diff --git a/resolution-frontend/drizzle/0010_warehouse_indexes_and_tags.sql b/resolution-frontend/drizzle.backup/0010_warehouse_indexes_and_tags.sql similarity index 100% rename from resolution-frontend/drizzle/0010_warehouse_indexes_and_tags.sql rename to resolution-frontend/drizzle.backup/0010_warehouse_indexes_and_tags.sql diff --git a/resolution-frontend/drizzle.backup/0011_nosy_bloodstrike.sql b/resolution-frontend/drizzle.backup/0011_nosy_bloodstrike.sql new file mode 100644 index 0000000..df50141 --- /dev/null +++ b/resolution-frontend/drizzle.backup/0011_nosy_bloodstrike.sql @@ -0,0 +1,84 @@ +CREATE TYPE "public"."currency_txn_reason" AS ENUM('GRANT', 'PURCHASE', 'REFUND', 'ADJUSTMENT', 'OTHER');--> statement-breakpoint +CREATE TYPE "public"."shop_item_type" AS ENUM('PHYSICAL', 'DIGITAL');--> statement-breakpoint +CREATE TYPE "public"."shop_order_status" AS ENUM('PENDING', 'PROCESSING', 'FULFILLED', 'CANCELED');--> statement-breakpoint +CREATE TABLE "fufiller_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "assigned_at" timestamp DEFAULT now() NOT NULL, + "assigned_by" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "pathway_shop" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "is_enabled" boolean DEFAULT false NOT NULL, + "currency_name" text DEFAULT 'wish' NOT NULL, + "currency_name_plural" text DEFAULT 'wishes' NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "pathway_shop_pathway_unique" UNIQUE("pathway") +); +--> statement-breakpoint +CREATE TABLE "shop_item" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "name" text NOT NULL, + "description" text NOT NULL, + "item_url" text, + "item_price" integer NOT NULL, + "item_stock" integer, + "item_type" "shop_item_type" NOT NULL, + "is_active" boolean DEFAULT false NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "shop_orders" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text, + "pathway" "pathway" NOT NULL, + "order_stauts" "shop_order_status" DEFAULT 'PENDING' NOT NULL, + "amount" integer NOT NULL, + "shop_item_id" text, + "item_price_snapshot" integer NOT NULL, + "item_type_enum" "shop_item_type", + "item_name_snapshot" text NOT NULL, + "shipping_address" jsonb, + "user_notes" text, + "fufiller_notes" text, + "fufilled_by" text, + "fufilled_at" timestamp, + "cancelled_reason" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "currency_transactions" ( + "id" text PRIMARY KEY NOT NULL, + "tx_user_id" text, + "tx_pathway" "pathway" NOT NULL, + "tx_amount" integer NOT NULL, + "tx_reason" "currency_txn_reason" NOT NULL, + "tx_note" text, + "tx_granted_by" text, + "tx_ref_type" text, + "tx_ref_id" text, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "fufiller_pathway" ADD CONSTRAINT "fufiller_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "fufiller_pathway" ADD CONSTRAINT "fufiller_pathway_assigned_by_user_id_fk" FOREIGN KEY ("assigned_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "pathway_shop" ADD CONSTRAINT "pathway_shop_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_shop_item_id_shop_item_id_fk" FOREIGN KEY ("shop_item_id") REFERENCES "public"."shop_item"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_fufilled_by_user_id_fk" FOREIGN KEY ("fufilled_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_user_id_user_id_fk" FOREIGN KEY ("tx_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("tx_pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_granted_by_user_id_fk" FOREIGN KEY ("tx_granted_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +CREATE UNIQUE INDEX "fufiller_pathway_unique_idx" ON "fufiller_pathway" USING btree ("user_id","pathway"); \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup/meta/0000_snapshot.json b/resolution-frontend/drizzle.backup/meta/0000_snapshot.json new file mode 100644 index 0000000..b667fb0 --- /dev/null +++ b/resolution-frontend/drizzle.backup/meta/0000_snapshot.json @@ -0,0 +1,1344 @@ +{ + "id": "ee4874ac-fef8-4ca8-ab84-17f57639d40b", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ambassador_pathway": { + "name": "ambassador_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "ambassador_pathway_unique_idx": { + "name": "ambassador_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ambassador_pathway_user_id_user_id_fk": { + "name": "ambassador_pathway_user_id_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_pathway_assigned_by_user_id_fk": { + "name": "ambassador_pathway_assigned_by_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout": { + "name": "ambassador_payout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "payout_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "paid_at": { + "name": "paid_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_ambassador_id_user_id_fk": { + "name": "ambassador_payout_ambassador_id_user_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_season_id_program_season_id_fk": { + "name": "ambassador_payout_season_id_program_season_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout_item": { + "name": "ambassador_payout_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "payout_id": { + "name": "payout_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completion_count": { + "name": "completion_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate_cents_per_completion": { + "name": "rate_cents_per_completion", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_item_payout_id_ambassador_payout_id_fk": { + "name": "ambassador_payout_item_payout_id_ambassador_payout_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "ambassador_payout", + "columnsFrom": [ + "payout_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_item_workshop_id_workshop_id_fk": { + "name": "ambassador_payout_item_workshop_id_workshop_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_week_content": { + "name": "pathway_week_content", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pathway_week_content_unique_idx": { + "name": "pathway_week_content_unique_idx", + "columns": [ + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pathway_week_content_last_edited_by_user_id_fk": { + "name": "pathway_week_content_last_edited_by_user_id_fk", + "tableFrom": "pathway_week_content", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_enrollment": { + "name": "program_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enrollment_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ACTIVE'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "starting_week": { + "name": "starting_week", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "enrollment_user_season_role_idx": { + "name": "enrollment_user_season_role_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "program_enrollment_user_id_user_id_fk": { + "name": "program_enrollment_user_id_user_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "program_enrollment_season_id_program_season_id_fk": { + "name": "program_enrollment_season_id_program_season_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_season": { + "name": "program_season", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signup_opens_at": { + "name": "signup_opens_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "signup_closes_at": { + "name": "signup_closes_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "total_weeks": { + "name": "total_weeks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 8 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.weekly_ship": { + "name": "weekly_ship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "goal_text": { + "name": "goal_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ship_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PLANNED'" + }, + "proof_url": { + "name": "proof_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ship_user_season_week_idx": { + "name": "ship_user_season_week_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weekly_ship_user_id_user_id_fk": { + "name": "weekly_ship_user_id_user_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_season_id_program_season_id_fk": { + "name": "weekly_ship_season_id_program_season_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_workshop_id_workshop_id_fk": { + "name": "weekly_ship_workshop_id_workshop_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop": { + "name": "workshop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "difficulty": { + "name": "difficulty", + "type": "difficulty", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "estimated_hours": { + "name": "estimated_hours", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "published": { + "name": "published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_author_id_user_id_fk": { + "name": "workshop_author_id_user_id_fk", + "tableFrom": "workshop", + "tableTo": "user", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_season_id_program_season_id_fk": { + "name": "workshop_season_id_program_season_id_fk", + "tableFrom": "workshop", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_analytics": { + "name": "workshop_analytics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "starts": { + "name": "starts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "completions": { + "name": "completions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "avg_completion_mins": { + "name": "avg_completion_mins", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_analytics_workshop_id_workshop_id_fk": { + "name": "workshop_analytics_workshop_id_workshop_id_fk", + "tableFrom": "workshop_analytics", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workshop_analytics_workshop_id_unique": { + "name": "workshop_analytics_workshop_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workshop_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_completion": { + "name": "workshop_completion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant_id": { + "name": "participant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_url": { + "name": "project_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "completion_workshop_participant_season_idx": { + "name": "completion_workshop_participant_season_idx", + "columns": [ + { + "expression": "workshop_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "participant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workshop_completion_workshop_id_workshop_id_fk": { + "name": "workshop_completion_workshop_id_workshop_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_participant_id_user_id_fk": { + "name": "workshop_completion_participant_id_user_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "user", + "columnsFrom": [ + "participant_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_season_id_program_season_id_fk": { + "name": "workshop_completion_season_id_program_season_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.difficulty": { + "name": "difficulty", + "schema": "public", + "values": [ + "BEGINNER", + "INTERMEDIATE", + "ADVANCED" + ] + }, + "public.enrollment_role": { + "name": "enrollment_role", + "schema": "public", + "values": [ + "PARTICIPANT", + "AMBASSADOR" + ] + }, + "public.enrollment_status": { + "name": "enrollment_status", + "schema": "public", + "values": [ + "ACTIVE", + "DROPPED", + "COMPLETED" + ] + }, + "public.pathway": { + "name": "pathway", + "schema": "public", + "values": [ + "PYTHON", + "WEB_DEV", + "GAME_DEV", + "HARDWARE", + "DESIGN", + "GENERAL_CODING" + ] + }, + "public.payout_status": { + "name": "payout_status", + "schema": "public", + "values": [ + "DRAFT", + "PENDING", + "PAID", + "CANCELED" + ] + }, + "public.ship_status": { + "name": "ship_status", + "schema": "public", + "values": [ + "PLANNED", + "IN_PROGRESS", + "SHIPPED", + "MISSED" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup/meta/0001_snapshot.json b/resolution-frontend/drizzle.backup/meta/0001_snapshot.json new file mode 100644 index 0000000..7776dba --- /dev/null +++ b/resolution-frontend/drizzle.backup/meta/0001_snapshot.json @@ -0,0 +1,1511 @@ +{ + "id": "becd34cd-7692-4ef3-a912-458e58e190ad", + "prevId": "ee4874ac-fef8-4ca8-ab84-17f57639d40b", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ambassador_pathway": { + "name": "ambassador_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "ambassador_pathway_unique_idx": { + "name": "ambassador_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ambassador_pathway_user_id_user_id_fk": { + "name": "ambassador_pathway_user_id_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_pathway_assigned_by_user_id_fk": { + "name": "ambassador_pathway_assigned_by_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout": { + "name": "ambassador_payout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "payout_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "paid_at": { + "name": "paid_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_ambassador_id_user_id_fk": { + "name": "ambassador_payout_ambassador_id_user_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_season_id_program_season_id_fk": { + "name": "ambassador_payout_season_id_program_season_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout_item": { + "name": "ambassador_payout_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "payout_id": { + "name": "payout_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completion_count": { + "name": "completion_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate_cents_per_completion": { + "name": "rate_cents_per_completion", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_item_payout_id_ambassador_payout_id_fk": { + "name": "ambassador_payout_item_payout_id_ambassador_payout_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "ambassador_payout", + "columnsFrom": [ + "payout_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_item_workshop_id_workshop_id_fk": { + "name": "ambassador_payout_item_workshop_id_workshop_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_week_content": { + "name": "pathway_week_content", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pathway_week_content_unique_idx": { + "name": "pathway_week_content_unique_idx", + "columns": [ + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pathway_week_content_last_edited_by_user_id_fk": { + "name": "pathway_week_content_last_edited_by_user_id_fk", + "tableFrom": "pathway_week_content", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_enrollment": { + "name": "program_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enrollment_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ACTIVE'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "starting_week": { + "name": "starting_week", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "enrollment_user_season_role_idx": { + "name": "enrollment_user_season_role_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "program_enrollment_user_id_user_id_fk": { + "name": "program_enrollment_user_id_user_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "program_enrollment_season_id_program_season_id_fk": { + "name": "program_enrollment_season_id_program_season_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_season": { + "name": "program_season", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signup_opens_at": { + "name": "signup_opens_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "signup_closes_at": { + "name": "signup_closes_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "total_weeks": { + "name": "total_weeks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 8 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_link": { + "name": "referral_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.weekly_ship": { + "name": "weekly_ship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "goal_text": { + "name": "goal_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ship_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PLANNED'" + }, + "proof_url": { + "name": "proof_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ship_user_season_week_idx": { + "name": "ship_user_season_week_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weekly_ship_user_id_user_id_fk": { + "name": "weekly_ship_user_id_user_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_season_id_program_season_id_fk": { + "name": "weekly_ship_season_id_program_season_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_workshop_id_workshop_id_fk": { + "name": "weekly_ship_workshop_id_workshop_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop": { + "name": "workshop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "difficulty": { + "name": "difficulty", + "type": "difficulty", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "estimated_hours": { + "name": "estimated_hours", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "published": { + "name": "published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_author_id_user_id_fk": { + "name": "workshop_author_id_user_id_fk", + "tableFrom": "workshop", + "tableTo": "user", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_season_id_program_season_id_fk": { + "name": "workshop_season_id_program_season_id_fk", + "tableFrom": "workshop", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_analytics": { + "name": "workshop_analytics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "starts": { + "name": "starts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "completions": { + "name": "completions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "avg_completion_mins": { + "name": "avg_completion_mins", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_analytics_workshop_id_workshop_id_fk": { + "name": "workshop_analytics_workshop_id_workshop_id_fk", + "tableFrom": "workshop_analytics", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workshop_analytics_workshop_id_unique": { + "name": "workshop_analytics_workshop_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workshop_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_completion": { + "name": "workshop_completion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant_id": { + "name": "participant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_url": { + "name": "project_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "completion_workshop_participant_season_idx": { + "name": "completion_workshop_participant_season_idx", + "columns": [ + { + "expression": "workshop_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "participant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workshop_completion_workshop_id_workshop_id_fk": { + "name": "workshop_completion_workshop_id_workshop_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_participant_id_user_id_fk": { + "name": "workshop_completion_participant_id_user_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "user", + "columnsFrom": [ + "participant_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_season_id_program_season_id_fk": { + "name": "workshop_completion_season_id_program_season_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.difficulty": { + "name": "difficulty", + "schema": "public", + "values": [ + "BEGINNER", + "INTERMEDIATE", + "ADVANCED" + ] + }, + "public.enrollment_role": { + "name": "enrollment_role", + "schema": "public", + "values": [ + "PARTICIPANT", + "AMBASSADOR" + ] + }, + "public.enrollment_status": { + "name": "enrollment_status", + "schema": "public", + "values": [ + "ACTIVE", + "DROPPED", + "COMPLETED" + ] + }, + "public.pathway": { + "name": "pathway", + "schema": "public", + "values": [ + "PYTHON", + "WEB_DEV", + "GAME_DEV", + "HARDWARE", + "DESIGN", + "GENERAL_CODING" + ] + }, + "public.payout_status": { + "name": "payout_status", + "schema": "public", + "values": [ + "DRAFT", + "PENDING", + "PAID", + "CANCELED" + ] + }, + "public.ship_status": { + "name": "ship_status", + "schema": "public", + "values": [ + "PLANNED", + "IN_PROGRESS", + "SHIPPED", + "MISSED" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/resolution-frontend/drizzle/meta/0002_snapshot.json b/resolution-frontend/drizzle.backup/meta/0002_snapshot.json similarity index 100% rename from resolution-frontend/drizzle/meta/0002_snapshot.json rename to resolution-frontend/drizzle.backup/meta/0002_snapshot.json diff --git a/resolution-frontend/drizzle/meta/0004_snapshot.json b/resolution-frontend/drizzle.backup/meta/0004_snapshot.json similarity index 100% rename from resolution-frontend/drizzle/meta/0004_snapshot.json rename to resolution-frontend/drizzle.backup/meta/0004_snapshot.json diff --git a/resolution-frontend/drizzle.backup/meta/0006_snapshot.json b/resolution-frontend/drizzle.backup/meta/0006_snapshot.json new file mode 100644 index 0000000..772a4b7 --- /dev/null +++ b/resolution-frontend/drizzle.backup/meta/0006_snapshot.json @@ -0,0 +1,2143 @@ +{ + "id": "a0247220-e3e8-4974-96a1-81cf9283801b", + "prevId": "2fbbf398-fe52-49d5-bcef-27f714185921", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ambassador_pathway": { + "name": "ambassador_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "ambassador_pathway_unique_idx": { + "name": "ambassador_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ambassador_pathway_user_id_user_id_fk": { + "name": "ambassador_pathway_user_id_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_pathway_assigned_by_user_id_fk": { + "name": "ambassador_pathway_assigned_by_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout": { + "name": "ambassador_payout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "payout_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "paid_at": { + "name": "paid_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_ambassador_id_user_id_fk": { + "name": "ambassador_payout_ambassador_id_user_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_season_id_program_season_id_fk": { + "name": "ambassador_payout_season_id_program_season_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout_item": { + "name": "ambassador_payout_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "payout_id": { + "name": "payout_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completion_count": { + "name": "completion_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate_cents_per_completion": { + "name": "rate_cents_per_completion", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_item_payout_id_ambassador_payout_id_fk": { + "name": "ambassador_payout_item_payout_id_ambassador_payout_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "ambassador_payout", + "columnsFrom": [ + "payout_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_item_workshop_id_workshop_id_fk": { + "name": "ambassador_payout_item_workshop_id_workshop_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_shop": { + "name": "pathway_shop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "currency_name": { + "name": "currency_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wish'" + }, + "currency_name_plural": { + "name": "currency_name_plural", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wishes'" + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "pathway_shop_last_edited_by_user_id_fk": { + "name": "pathway_shop_last_edited_by_user_id_fk", + "tableFrom": "pathway_shop", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pathway_shop_pathway_unique": { + "name": "pathway_shop_pathway_unique", + "nullsNotDistinct": false, + "columns": [ + "pathway" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_week_content": { + "name": "pathway_week_content", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "prize_image_url": { + "name": "prize_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_submissions_open": { + "name": "is_submissions_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pathway_week_content_unique_idx": { + "name": "pathway_week_content_unique_idx", + "columns": [ + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pathway_week_content_last_edited_by_user_id_fk": { + "name": "pathway_week_content_last_edited_by_user_id_fk", + "tableFrom": "pathway_week_content", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_enrollment": { + "name": "program_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enrollment_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ACTIVE'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "starting_week": { + "name": "starting_week", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "enrollment_user_season_role_idx": { + "name": "enrollment_user_season_role_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "program_enrollment_user_id_user_id_fk": { + "name": "program_enrollment_user_id_user_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "program_enrollment_season_id_program_season_id_fk": { + "name": "program_enrollment_season_id_program_season_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_season": { + "name": "program_season", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signup_opens_at": { + "name": "signup_opens_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "signup_closes_at": { + "name": "signup_closes_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "total_weeks": { + "name": "total_weeks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 8 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_link": { + "name": "referral_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviewer_pathway": { + "name": "reviewer_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "reviewer_pathway_unique_idx": { + "name": "reviewer_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviewer_pathway_user_id_user_id_fk": { + "name": "reviewer_pathway_user_id_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reviewer_pathway_assigned_by_user_id_fk": { + "name": "reviewer_pathway_assigned_by_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_item": { + "name": "shop_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_url": { + "name": "item_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price": { + "name": "item_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_stock": { + "name": "item_stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "item_type": { + "name": "item_type", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_item_pathway_pathway_shop_pathway_fk": { + "name": "shop_item_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_item", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_last_edited_by_user_id_fk": { + "name": "shop_item_last_edited_by_user_id_fk", + "tableFrom": "shop_item", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_orders": { + "name": "shop_orders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "order_stauts": { + "name": "order_stauts", + "type": "shop_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "shop_item_id": { + "name": "shop_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price_snapshot": { + "name": "item_price_snapshot", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_type_enum": { + "name": "item_type_enum", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "item_name_snapshot": { + "name": "item_name_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shipping_address": { + "name": "shipping_address", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "user_notes": { + "name": "user_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufiller_notes": { + "name": "fufiller_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_by": { + "name": "fufilled_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_at": { + "name": "fufilled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancelled_reason": { + "name": "cancelled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_orders_user_id_user_id_fk": { + "name": "shop_orders_user_id_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_pathway_pathway_shop_pathway_fk": { + "name": "shop_orders_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_orders", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_orders_shop_item_id_shop_item_id_fk": { + "name": "shop_orders_shop_item_id_shop_item_id_fk", + "tableFrom": "shop_orders", + "tableTo": "shop_item", + "columnsFrom": [ + "shop_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_fufilled_by_user_id_fk": { + "name": "shop_orders_fufilled_by_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "fufilled_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.currency_transactions": { + "name": "currency_transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tx_user_id": { + "name": "tx_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_pathway": { + "name": "tx_pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_amount": { + "name": "tx_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tx_reason": { + "name": "tx_reason", + "type": "currency_txn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_note": { + "name": "tx_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_granted_by": { + "name": "tx_granted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_type": { + "name": "tx_ref_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_id": { + "name": "tx_ref_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "currency_transactions_tx_user_id_user_id_fk": { + "name": "currency_transactions_tx_user_id_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "currency_transactions_tx_pathway_pathway_shop_pathway_fk": { + "name": "currency_transactions_tx_pathway_pathway_shop_pathway_fk", + "tableFrom": "currency_transactions", + "tableTo": "pathway_shop", + "columnsFrom": [ + "tx_pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "currency_transactions_tx_granted_by_user_id_fk": { + "name": "currency_transactions_tx_granted_by_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.weekly_ship": { + "name": "weekly_ship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "goal_text": { + "name": "goal_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ship_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PLANNED'" + }, + "proof_url": { + "name": "proof_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ship_user_season_week_idx": { + "name": "ship_user_season_week_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weekly_ship_user_id_user_id_fk": { + "name": "weekly_ship_user_id_user_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_season_id_program_season_id_fk": { + "name": "weekly_ship_season_id_program_season_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_workshop_id_workshop_id_fk": { + "name": "weekly_ship_workshop_id_workshop_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop": { + "name": "workshop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "difficulty": { + "name": "difficulty", + "type": "difficulty", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "estimated_hours": { + "name": "estimated_hours", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "published": { + "name": "published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_author_id_user_id_fk": { + "name": "workshop_author_id_user_id_fk", + "tableFrom": "workshop", + "tableTo": "user", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_season_id_program_season_id_fk": { + "name": "workshop_season_id_program_season_id_fk", + "tableFrom": "workshop", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_analytics": { + "name": "workshop_analytics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "starts": { + "name": "starts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "completions": { + "name": "completions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "avg_completion_mins": { + "name": "avg_completion_mins", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_analytics_workshop_id_workshop_id_fk": { + "name": "workshop_analytics_workshop_id_workshop_id_fk", + "tableFrom": "workshop_analytics", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workshop_analytics_workshop_id_unique": { + "name": "workshop_analytics_workshop_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workshop_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_completion": { + "name": "workshop_completion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant_id": { + "name": "participant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_url": { + "name": "project_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "completion_workshop_participant_season_idx": { + "name": "completion_workshop_participant_season_idx", + "columns": [ + { + "expression": "workshop_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "participant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workshop_completion_workshop_id_workshop_id_fk": { + "name": "workshop_completion_workshop_id_workshop_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_participant_id_user_id_fk": { + "name": "workshop_completion_participant_id_user_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "user", + "columnsFrom": [ + "participant_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_season_id_program_season_id_fk": { + "name": "workshop_completion_season_id_program_season_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.currency_txn_reason": { + "name": "currency_txn_reason", + "schema": "public", + "values": [ + "GRANT", + "PURCHASE", + "REFUND", + "ADJUSTMENT", + "OTHER" + ] + }, + "public.difficulty": { + "name": "difficulty", + "schema": "public", + "values": [ + "BEGINNER", + "INTERMEDIATE", + "ADVANCED" + ] + }, + "public.enrollment_role": { + "name": "enrollment_role", + "schema": "public", + "values": [ + "PARTICIPANT", + "AMBASSADOR" + ] + }, + "public.enrollment_status": { + "name": "enrollment_status", + "schema": "public", + "values": [ + "ACTIVE", + "DROPPED", + "COMPLETED" + ] + }, + "public.pathway": { + "name": "pathway", + "schema": "public", + "values": [ + "PYTHON", + "RUST", + "GAME_DEV", + "HARDWARE", + "DESIGN", + "GENERAL_CODING" + ] + }, + "public.payout_status": { + "name": "payout_status", + "schema": "public", + "values": [ + "DRAFT", + "PENDING", + "PAID", + "CANCELED" + ] + }, + "public.ship_status": { + "name": "ship_status", + "schema": "public", + "values": [ + "PLANNED", + "IN_PROGRESS", + "SHIPPED", + "MISSED" + ] + }, + "public.shop_item_type": { + "name": "shop_item_type", + "schema": "public", + "values": [ + "PHYSICAL", + "DIGITAL" + ] + }, + "public.shop_order_status": { + "name": "shop_order_status", + "schema": "public", + "values": [ + "PENDING", + "PROCESSING", + "FULFILLED", + "CANCELED" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup/meta/0007_snapshot.json b/resolution-frontend/drizzle.backup/meta/0007_snapshot.json new file mode 100644 index 0000000..b6e44d5 --- /dev/null +++ b/resolution-frontend/drizzle.backup/meta/0007_snapshot.json @@ -0,0 +1,3111 @@ +{ + "id": "d61c6fea-7cc9-40a4-a375-fe0686294e7d", + "prevId": "2fbbf398-fe52-49d5-bcef-27f714185921", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ambassador_pathway": { + "name": "ambassador_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "ambassador_pathway_unique_idx": { + "name": "ambassador_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ambassador_pathway_user_id_user_id_fk": { + "name": "ambassador_pathway_user_id_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_pathway_assigned_by_user_id_fk": { + "name": "ambassador_pathway_assigned_by_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout": { + "name": "ambassador_payout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "payout_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "paid_at": { + "name": "paid_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_ambassador_id_user_id_fk": { + "name": "ambassador_payout_ambassador_id_user_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_season_id_program_season_id_fk": { + "name": "ambassador_payout_season_id_program_season_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout_item": { + "name": "ambassador_payout_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "payout_id": { + "name": "payout_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completion_count": { + "name": "completion_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate_cents_per_completion": { + "name": "rate_cents_per_completion", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_item_payout_id_ambassador_payout_id_fk": { + "name": "ambassador_payout_item_payout_id_ambassador_payout_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "ambassador_payout", + "columnsFrom": [ + "payout_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_item_workshop_id_workshop_id_fk": { + "name": "ambassador_payout_item_workshop_id_workshop_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_shop": { + "name": "pathway_shop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "currency_name": { + "name": "currency_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wish'" + }, + "currency_name_plural": { + "name": "currency_name_plural", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wishes'" + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "pathway_shop_last_edited_by_user_id_fk": { + "name": "pathway_shop_last_edited_by_user_id_fk", + "tableFrom": "pathway_shop", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pathway_shop_pathway_unique": { + "name": "pathway_shop_pathway_unique", + "nullsNotDistinct": false, + "columns": [ + "pathway" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_week_content": { + "name": "pathway_week_content", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "prize_image_url": { + "name": "prize_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_submissions_open": { + "name": "is_submissions_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pathway_week_content_unique_idx": { + "name": "pathway_week_content_unique_idx", + "columns": [ + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pathway_week_content_last_edited_by_user_id_fk": { + "name": "pathway_week_content_last_edited_by_user_id_fk", + "tableFrom": "pathway_week_content", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_enrollment": { + "name": "program_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enrollment_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ACTIVE'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "starting_week": { + "name": "starting_week", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "enrollment_user_season_role_idx": { + "name": "enrollment_user_season_role_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "program_enrollment_user_id_user_id_fk": { + "name": "program_enrollment_user_id_user_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "program_enrollment_season_id_program_season_id_fk": { + "name": "program_enrollment_season_id_program_season_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_season": { + "name": "program_season", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signup_opens_at": { + "name": "signup_opens_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "signup_closes_at": { + "name": "signup_closes_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "total_weeks": { + "name": "total_weeks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 8 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_link": { + "name": "referral_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviewer_pathway": { + "name": "reviewer_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "reviewer_pathway_unique_idx": { + "name": "reviewer_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviewer_pathway_user_id_user_id_fk": { + "name": "reviewer_pathway_user_id_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reviewer_pathway_assigned_by_user_id_fk": { + "name": "reviewer_pathway_assigned_by_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_item": { + "name": "shop_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_url": { + "name": "item_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price": { + "name": "item_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_stock": { + "name": "item_stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "item_type": { + "name": "item_type", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_item_pathway_pathway_shop_pathway_fk": { + "name": "shop_item_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_item", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_last_edited_by_user_id_fk": { + "name": "shop_item_last_edited_by_user_id_fk", + "tableFrom": "shop_item", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_orders": { + "name": "shop_orders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "order_stauts": { + "name": "order_stauts", + "type": "shop_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "shop_item_id": { + "name": "shop_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price_snapshot": { + "name": "item_price_snapshot", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_type_enum": { + "name": "item_type_enum", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "item_name_snapshot": { + "name": "item_name_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shipping_address": { + "name": "shipping_address", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_notes": { + "name": "user_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufiller_notes": { + "name": "fufiller_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_by": { + "name": "fufilled_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_at": { + "name": "fufilled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancelled_reason": { + "name": "cancelled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_orders_user_id_user_id_fk": { + "name": "shop_orders_user_id_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_pathway_pathway_shop_pathway_fk": { + "name": "shop_orders_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_orders", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_orders_shop_item_id_shop_item_id_fk": { + "name": "shop_orders_shop_item_id_shop_item_id_fk", + "tableFrom": "shop_orders", + "tableTo": "shop_item", + "columnsFrom": [ + "shop_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_fufilled_by_user_id_fk": { + "name": "shop_orders_fufilled_by_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "fufilled_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.currency_transactions": { + "name": "currency_transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tx_user_id": { + "name": "tx_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_pathway": { + "name": "tx_pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_amount": { + "name": "tx_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tx_reason": { + "name": "tx_reason", + "type": "currency_txn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_note": { + "name": "tx_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_granted_by": { + "name": "tx_granted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_type": { + "name": "tx_ref_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_id": { + "name": "tx_ref_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "currency_transactions_tx_user_id_user_id_fk": { + "name": "currency_transactions_tx_user_id_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "currency_transactions_tx_pathway_pathway_shop_pathway_fk": { + "name": "currency_transactions_tx_pathway_pathway_shop_pathway_fk", + "tableFrom": "currency_transactions", + "tableTo": "pathway_shop", + "columnsFrom": [ + "tx_pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "currency_transactions_tx_granted_by_user_id_fk": { + "name": "currency_transactions_tx_granted_by_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch": { + "name": "warehouse_batch", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_batch_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'AWAITING_MAPPING'" + }, + "csv_data": { + "name": "csv_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_mapping": { + "name": "field_mapping", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_count": { + "name": "address_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_batch_created_by_id_user_id_fk": { + "name": "warehouse_batch_created_by_id_user_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_batch_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_batch_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch_tag": { + "name": "warehouse_batch_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "warehouse_batch_tag_unique_idx": { + "name": "warehouse_batch_tag_unique_idx", + "columns": [ + { + "expression": "batch_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_batch_tag_batch_id_warehouse_batch_id_fk": { + "name": "warehouse_batch_tag_batch_id_warehouse_batch_id_fk", + "tableFrom": "warehouse_batch_tag", + "tableTo": "warehouse_batch", + "columnsFrom": [ + "batch_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_category": { + "name": "warehouse_category", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_item": { + "name": "warehouse_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "category_id": { + "name": "category_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sku": { + "name": "sku", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sizing": { + "name": "sizing", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "package_type": { + "name": "package_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'box'" + }, + "length_in": { + "name": "length_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "width_in": { + "name": "width_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "height_in": { + "name": "height_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "weight_grams": { + "name": "weight_grams", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "cost_cents": { + "name": "cost_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "hs_code": { + "name": "hs_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_item_category_id_warehouse_category_id_fk": { + "name": "warehouse_item_category_id_warehouse_category_id_fk", + "tableFrom": "warehouse_item", + "tableTo": "warehouse_category", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_item_sku_unique": { + "name": "warehouse_item_sku_unique", + "nullsNotDistinct": false, + "columns": [ + "sku" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order": { + "name": "warehouse_order", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fulfillment_id": { + "name": "fulfillment_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "warehouse_order_fulfillment_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_line_1": { + "name": "address_line_1", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address_line_2": { + "name": "address_line_2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "city": { + "name": "city", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_province": { + "name": "state_province", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "postal_code": { + "name": "postal_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "estimated_shipping_cents": { + "name": "estimated_shipping_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_duties_cents": { + "name": "estimated_duties_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_service_name": { + "name": "estimated_service_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_service_code": { + "name": "estimated_service_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_package_type": { + "name": "estimated_package_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_total_length_in": { + "name": "estimated_total_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_width_in": { + "name": "estimated_total_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_height_in": { + "name": "estimated_total_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_weight_grams": { + "name": "estimated_total_weight_grams", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_category": { + "name": "packaging_category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_label": { + "name": "packaging_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_length_in": { + "name": "packaging_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_width_in": { + "name": "packaging_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_height_in": { + "name": "packaging_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_subject_to_change": { + "name": "packaging_subject_to_change", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "tracking_number": { + "name": "tracking_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "label_url": { + "name": "label_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipping_method": { + "name": "shipping_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_status": { + "name": "billing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "billing_failure_reason": { + "name": "billing_failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_created_by_id_user_id_fk": { + "name": "warehouse_order_created_by_id_user_id_fk", + "tableFrom": "warehouse_order", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_order_fulfillment_id_unique": { + "name": "warehouse_order_fulfillment_id_unique", + "nullsNotDistinct": false, + "columns": [ + "fulfillment_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_item": { + "name": "warehouse_order_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "order_id": { + "name": "order_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "sizing_choice": { + "name": "sizing_choice", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "warehouse_order_item_order_id_idx": { + "name": "warehouse_order_item_order_id_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_item_warehouse_item_id_idx": { + "name": "warehouse_order_item_warehouse_item_id_idx", + "columns": [ + { + "expression": "warehouse_item_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_order_item_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_item_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_order", + "columnsFrom": [ + "order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_tag": { + "name": "warehouse_order_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "order_id": { + "name": "order_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "warehouse_order_tag_unique_idx": { + "name": "warehouse_order_tag_unique_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_tag_tag_idx": { + "name": "warehouse_order_tag_tag_idx", + "columns": [ + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_order_tag_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_tag_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_tag", + "tableTo": "warehouse_order", + "columnsFrom": [ + "order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_template": { + "name": "warehouse_order_template", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_public": { + "name": "is_public", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_template_created_by_id_user_id_fk": { + "name": "warehouse_order_template_created_by_id_user_id_fk", + "tableFrom": "warehouse_order_template", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_template_item": { + "name": "warehouse_order_template_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_template_item_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_order_template_item_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.weekly_ship": { + "name": "weekly_ship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "goal_text": { + "name": "goal_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ship_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PLANNED'" + }, + "proof_url": { + "name": "proof_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ship_user_season_week_idx": { + "name": "ship_user_season_week_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weekly_ship_user_id_user_id_fk": { + "name": "weekly_ship_user_id_user_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_season_id_program_season_id_fk": { + "name": "weekly_ship_season_id_program_season_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_workshop_id_workshop_id_fk": { + "name": "weekly_ship_workshop_id_workshop_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop": { + "name": "workshop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "difficulty": { + "name": "difficulty", + "type": "difficulty", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "estimated_hours": { + "name": "estimated_hours", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "published": { + "name": "published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_author_id_user_id_fk": { + "name": "workshop_author_id_user_id_fk", + "tableFrom": "workshop", + "tableTo": "user", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_season_id_program_season_id_fk": { + "name": "workshop_season_id_program_season_id_fk", + "tableFrom": "workshop", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_analytics": { + "name": "workshop_analytics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "starts": { + "name": "starts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "completions": { + "name": "completions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "avg_completion_mins": { + "name": "avg_completion_mins", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_analytics_workshop_id_workshop_id_fk": { + "name": "workshop_analytics_workshop_id_workshop_id_fk", + "tableFrom": "workshop_analytics", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workshop_analytics_workshop_id_unique": { + "name": "workshop_analytics_workshop_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workshop_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_completion": { + "name": "workshop_completion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant_id": { + "name": "participant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_url": { + "name": "project_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "completion_workshop_participant_season_idx": { + "name": "completion_workshop_participant_season_idx", + "columns": [ + { + "expression": "workshop_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "participant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workshop_completion_workshop_id_workshop_id_fk": { + "name": "workshop_completion_workshop_id_workshop_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_participant_id_user_id_fk": { + "name": "workshop_completion_participant_id_user_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "user", + "columnsFrom": [ + "participant_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_season_id_program_season_id_fk": { + "name": "workshop_completion_season_id_program_season_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.currency_txn_reason": { + "name": "currency_txn_reason", + "schema": "public", + "values": [ + "GRANT", + "PURCHASE", + "REFUND", + "ADJUSTMENT", + "OTHER" + ] + }, + "public.difficulty": { + "name": "difficulty", + "schema": "public", + "values": [ + "BEGINNER", + "INTERMEDIATE", + "ADVANCED" + ] + }, + "public.enrollment_role": { + "name": "enrollment_role", + "schema": "public", + "values": [ + "PARTICIPANT", + "AMBASSADOR" + ] + }, + "public.enrollment_status": { + "name": "enrollment_status", + "schema": "public", + "values": [ + "ACTIVE", + "DROPPED", + "COMPLETED" + ] + }, + "public.pathway": { + "name": "pathway", + "schema": "public", + "values": [ + "PYTHON", + "RUST", + "GAME_DEV", + "HARDWARE", + "DESIGN", + "GENERAL_CODING" + ] + }, + "public.payout_status": { + "name": "payout_status", + "schema": "public", + "values": [ + "DRAFT", + "PENDING", + "PAID", + "CANCELED" + ] + }, + "public.ship_status": { + "name": "ship_status", + "schema": "public", + "values": [ + "PLANNED", + "IN_PROGRESS", + "SHIPPED", + "MISSED" + ] + }, + "public.shop_item_type": { + "name": "shop_item_type", + "schema": "public", + "values": [ + "PHYSICAL", + "DIGITAL" + ] + }, + "public.shop_order_status": { + "name": "shop_order_status", + "schema": "public", + "values": [ + "PENDING", + "PROCESSING", + "FULFILLED", + "CANCELED" + ] + }, + "public.warehouse_batch_status": { + "name": "warehouse_batch_status", + "schema": "public", + "values": [ + "AWAITING_MAPPING", + "MAPPED", + "PROCESSED" + ] + }, + "public.warehouse_order_status": { + "name": "warehouse_order_status", + "schema": "public", + "values": [ + "DRAFT", + "ESTIMATED", + "APPROVED", + "SHIPPED", + "CANCELLED" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup/meta/0011_snapshot.json b/resolution-frontend/drizzle.backup/meta/0011_snapshot.json new file mode 100644 index 0000000..53da688 --- /dev/null +++ b/resolution-frontend/drizzle.backup/meta/0011_snapshot.json @@ -0,0 +1,2237 @@ +{ + "id": "2fbbf398-fe52-49d5-bcef-27f714185921", + "prevId": "a3a209aa-49a0-47e6-9126-892277549771", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ambassador_pathway": { + "name": "ambassador_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "ambassador_pathway_unique_idx": { + "name": "ambassador_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ambassador_pathway_user_id_user_id_fk": { + "name": "ambassador_pathway_user_id_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_pathway_assigned_by_user_id_fk": { + "name": "ambassador_pathway_assigned_by_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout": { + "name": "ambassador_payout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "payout_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "paid_at": { + "name": "paid_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_ambassador_id_user_id_fk": { + "name": "ambassador_payout_ambassador_id_user_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_season_id_program_season_id_fk": { + "name": "ambassador_payout_season_id_program_season_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout_item": { + "name": "ambassador_payout_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "payout_id": { + "name": "payout_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completion_count": { + "name": "completion_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate_cents_per_completion": { + "name": "rate_cents_per_completion", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_item_payout_id_ambassador_payout_id_fk": { + "name": "ambassador_payout_item_payout_id_ambassador_payout_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "ambassador_payout", + "columnsFrom": [ + "payout_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_item_workshop_id_workshop_id_fk": { + "name": "ambassador_payout_item_workshop_id_workshop_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.fufiller_pathway": { + "name": "fufiller_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "fufiller_pathway_unique_idx": { + "name": "fufiller_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "fufiller_pathway_user_id_user_id_fk": { + "name": "fufiller_pathway_user_id_user_id_fk", + "tableFrom": "fufiller_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "fufiller_pathway_assigned_by_user_id_fk": { + "name": "fufiller_pathway_assigned_by_user_id_fk", + "tableFrom": "fufiller_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_shop": { + "name": "pathway_shop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "currency_name": { + "name": "currency_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wish'" + }, + "currency_name_plural": { + "name": "currency_name_plural", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wishes'" + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "pathway_shop_last_edited_by_user_id_fk": { + "name": "pathway_shop_last_edited_by_user_id_fk", + "tableFrom": "pathway_shop", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pathway_shop_pathway_unique": { + "name": "pathway_shop_pathway_unique", + "nullsNotDistinct": false, + "columns": [ + "pathway" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_week_content": { + "name": "pathway_week_content", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "prize_image_url": { + "name": "prize_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_submissions_open": { + "name": "is_submissions_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pathway_week_content_unique_idx": { + "name": "pathway_week_content_unique_idx", + "columns": [ + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pathway_week_content_last_edited_by_user_id_fk": { + "name": "pathway_week_content_last_edited_by_user_id_fk", + "tableFrom": "pathway_week_content", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_enrollment": { + "name": "program_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enrollment_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ACTIVE'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "starting_week": { + "name": "starting_week", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "enrollment_user_season_role_idx": { + "name": "enrollment_user_season_role_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "program_enrollment_user_id_user_id_fk": { + "name": "program_enrollment_user_id_user_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "program_enrollment_season_id_program_season_id_fk": { + "name": "program_enrollment_season_id_program_season_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_season": { + "name": "program_season", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signup_opens_at": { + "name": "signup_opens_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "signup_closes_at": { + "name": "signup_closes_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "total_weeks": { + "name": "total_weeks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 8 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_link": { + "name": "referral_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviewer_pathway": { + "name": "reviewer_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "reviewer_pathway_unique_idx": { + "name": "reviewer_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviewer_pathway_user_id_user_id_fk": { + "name": "reviewer_pathway_user_id_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reviewer_pathway_assigned_by_user_id_fk": { + "name": "reviewer_pathway_assigned_by_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_item": { + "name": "shop_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_url": { + "name": "item_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price": { + "name": "item_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_stock": { + "name": "item_stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "item_type": { + "name": "item_type", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_item_pathway_pathway_shop_pathway_fk": { + "name": "shop_item_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_item", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_last_edited_by_user_id_fk": { + "name": "shop_item_last_edited_by_user_id_fk", + "tableFrom": "shop_item", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_orders": { + "name": "shop_orders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "order_stauts": { + "name": "order_stauts", + "type": "shop_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "shop_item_id": { + "name": "shop_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price_snapshot": { + "name": "item_price_snapshot", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_type_enum": { + "name": "item_type_enum", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "item_name_snapshot": { + "name": "item_name_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shipping_address": { + "name": "shipping_address", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "user_notes": { + "name": "user_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufiller_notes": { + "name": "fufiller_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_by": { + "name": "fufilled_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_at": { + "name": "fufilled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancelled_reason": { + "name": "cancelled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_orders_user_id_user_id_fk": { + "name": "shop_orders_user_id_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_pathway_pathway_shop_pathway_fk": { + "name": "shop_orders_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_orders", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_orders_shop_item_id_shop_item_id_fk": { + "name": "shop_orders_shop_item_id_shop_item_id_fk", + "tableFrom": "shop_orders", + "tableTo": "shop_item", + "columnsFrom": [ + "shop_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_fufilled_by_user_id_fk": { + "name": "shop_orders_fufilled_by_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "fufilled_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.currency_transactions": { + "name": "currency_transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tx_user_id": { + "name": "tx_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_pathway": { + "name": "tx_pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_amount": { + "name": "tx_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tx_reason": { + "name": "tx_reason", + "type": "currency_txn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_note": { + "name": "tx_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_granted_by": { + "name": "tx_granted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_type": { + "name": "tx_ref_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_id": { + "name": "tx_ref_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "currency_transactions_tx_user_id_user_id_fk": { + "name": "currency_transactions_tx_user_id_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "currency_transactions_tx_pathway_pathway_shop_pathway_fk": { + "name": "currency_transactions_tx_pathway_pathway_shop_pathway_fk", + "tableFrom": "currency_transactions", + "tableTo": "pathway_shop", + "columnsFrom": [ + "tx_pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "currency_transactions_tx_granted_by_user_id_fk": { + "name": "currency_transactions_tx_granted_by_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.weekly_ship": { + "name": "weekly_ship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "goal_text": { + "name": "goal_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ship_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PLANNED'" + }, + "proof_url": { + "name": "proof_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ship_user_season_week_idx": { + "name": "ship_user_season_week_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weekly_ship_user_id_user_id_fk": { + "name": "weekly_ship_user_id_user_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_season_id_program_season_id_fk": { + "name": "weekly_ship_season_id_program_season_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_workshop_id_workshop_id_fk": { + "name": "weekly_ship_workshop_id_workshop_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop": { + "name": "workshop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "difficulty": { + "name": "difficulty", + "type": "difficulty", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "estimated_hours": { + "name": "estimated_hours", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "published": { + "name": "published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_author_id_user_id_fk": { + "name": "workshop_author_id_user_id_fk", + "tableFrom": "workshop", + "tableTo": "user", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_season_id_program_season_id_fk": { + "name": "workshop_season_id_program_season_id_fk", + "tableFrom": "workshop", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_analytics": { + "name": "workshop_analytics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "starts": { + "name": "starts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "completions": { + "name": "completions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "avg_completion_mins": { + "name": "avg_completion_mins", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_analytics_workshop_id_workshop_id_fk": { + "name": "workshop_analytics_workshop_id_workshop_id_fk", + "tableFrom": "workshop_analytics", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workshop_analytics_workshop_id_unique": { + "name": "workshop_analytics_workshop_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workshop_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_completion": { + "name": "workshop_completion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant_id": { + "name": "participant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_url": { + "name": "project_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "completion_workshop_participant_season_idx": { + "name": "completion_workshop_participant_season_idx", + "columns": [ + { + "expression": "workshop_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "participant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workshop_completion_workshop_id_workshop_id_fk": { + "name": "workshop_completion_workshop_id_workshop_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_participant_id_user_id_fk": { + "name": "workshop_completion_participant_id_user_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "user", + "columnsFrom": [ + "participant_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_season_id_program_season_id_fk": { + "name": "workshop_completion_season_id_program_season_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.currency_txn_reason": { + "name": "currency_txn_reason", + "schema": "public", + "values": [ + "GRANT", + "PURCHASE", + "REFUND", + "ADJUSTMENT", + "OTHER" + ] + }, + "public.difficulty": { + "name": "difficulty", + "schema": "public", + "values": [ + "BEGINNER", + "INTERMEDIATE", + "ADVANCED" + ] + }, + "public.enrollment_role": { + "name": "enrollment_role", + "schema": "public", + "values": [ + "PARTICIPANT", + "AMBASSADOR" + ] + }, + "public.enrollment_status": { + "name": "enrollment_status", + "schema": "public", + "values": [ + "ACTIVE", + "DROPPED", + "COMPLETED" + ] + }, + "public.pathway": { + "name": "pathway", + "schema": "public", + "values": [ + "PYTHON", + "RUST", + "GAME_DEV", + "HARDWARE", + "DESIGN", + "GENERAL_CODING" + ] + }, + "public.payout_status": { + "name": "payout_status", + "schema": "public", + "values": [ + "DRAFT", + "PENDING", + "PAID", + "CANCELED" + ] + }, + "public.ship_status": { + "name": "ship_status", + "schema": "public", + "values": [ + "PLANNED", + "IN_PROGRESS", + "SHIPPED", + "MISSED" + ] + }, + "public.shop_item_type": { + "name": "shop_item_type", + "schema": "public", + "values": [ + "PHYSICAL", + "DIGITAL" + ] + }, + "public.shop_order_status": { + "name": "shop_order_status", + "schema": "public", + "values": [ + "PENDING", + "PROCESSING", + "FULFILLED", + "CANCELED" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup/meta/_journal.json b/resolution-frontend/drizzle.backup/meta/_journal.json new file mode 100644 index 0000000..2206f32 --- /dev/null +++ b/resolution-frontend/drizzle.backup/meta/_journal.json @@ -0,0 +1,104 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1770227074880, + "tag": "0000_curly_raza", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1771512581182, + "tag": "0001_burly_caretaker", + "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1772636037511, + "tag": "0002_luxuriant_maria_hill", + "breakpoints": true + }, + { + "idx": 3, + "version": "7", + "when": 1775185421664, + "tag": "0003_misty_week_prize_image", + "breakpoints": true + }, + { + "idx": 4, + "version": "7", + "when": 1776130671597, + "tag": "0004_left_pretty_boy", + "breakpoints": true + }, + { + "idx": 5, + "version": "7", + "when": 1776500000000, + "tag": "0005_add_package_type_and_orders", + "breakpoints": true + }, + { + "idx": 6, + "version": "7", + "when": 1776600000000, + "tag": "0006_add_templates_and_batches", + "breakpoints": true + }, + { + "idx": 7, + "version": "7", + "when": 1776700000000, + "tag": "0007_add_label_tracking_fields", + "breakpoints": true + }, + { + "idx": 8, + "version": "7", + "when": 1776800000000, + "tag": "0008_add_hs_code", + "breakpoints": true + }, + { + "idx": 9, + "version": "7", + "when": 1776900000000, + "tag": "0009_add_packaging_columns", + "breakpoints": true + }, + { + "idx": 10, + "version": "7", + "when": 1777000000000, + "tag": "0010_warehouse_indexes_and_tags", + "breakpoints": true + }, + { + "idx": 11, + "version": "7", + "when": 1778007365517, + "tag": "0011_nosy_bloodstrike", + "breakpoints": true + }, + { + "idx": 6, + "version": "7", + "when": 1778619728709, + "tag": "0006_worried_hedge_knight", + "breakpoints": true + }, + { + "idx": 7, + "version": "7", + "when": 1778708714355, + "tag": "0007_tense_captain_cross", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup2/0000_baseline.sql b/resolution-frontend/drizzle.backup2/0000_baseline.sql new file mode 100644 index 0000000..bcd78bd --- /dev/null +++ b/resolution-frontend/drizzle.backup2/0000_baseline.sql @@ -0,0 +1,421 @@ +CREATE TYPE "public"."currency_txn_reason" AS ENUM('GRANT', 'PURCHASE', 'REFUND', 'ADJUSTMENT', 'OTHER');--> statement-breakpoint +CREATE TYPE "public"."difficulty" AS ENUM('BEGINNER', 'INTERMEDIATE', 'ADVANCED');--> statement-breakpoint +CREATE TYPE "public"."enrollment_role" AS ENUM('PARTICIPANT', 'AMBASSADOR');--> statement-breakpoint +CREATE TYPE "public"."enrollment_status" AS ENUM('ACTIVE', 'DROPPED', 'COMPLETED');--> statement-breakpoint +CREATE TYPE "public"."pathway" AS ENUM('PYTHON', 'RUST', 'GAME_DEV', 'HARDWARE', 'DESIGN', 'GENERAL_CODING');--> statement-breakpoint +CREATE TYPE "public"."payout_status" AS ENUM('DRAFT', 'PENDING', 'PAID', 'CANCELED');--> statement-breakpoint +CREATE TYPE "public"."ship_status" AS ENUM('PLANNED', 'IN_PROGRESS', 'SHIPPED', 'MISSED');--> statement-breakpoint +CREATE TYPE "public"."shop_item_type" AS ENUM('PHYSICAL', 'DIGITAL');--> statement-breakpoint +CREATE TYPE "public"."shop_order_status" AS ENUM('PENDING', 'PROCESSING', 'FULFILLED', 'CANCELED');--> statement-breakpoint +CREATE TYPE "public"."warehouse_batch_status" AS ENUM('AWAITING_MAPPING', 'MAPPED', 'PROCESSED');--> statement-breakpoint +CREATE TYPE "public"."warehouse_order_status" AS ENUM('DRAFT', 'ESTIMATED', 'APPROVED', 'SHIPPED', 'CANCELLED');--> statement-breakpoint +CREATE TABLE "ambassador_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "assigned_at" timestamp DEFAULT now() NOT NULL, + "assigned_by" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "ambassador_payout" ( + "id" text PRIMARY KEY NOT NULL, + "ambassador_id" text NOT NULL, + "season_id" text NOT NULL, + "amount_cents" integer NOT NULL, + "status" "payout_status" DEFAULT 'DRAFT' NOT NULL, + "period_start" timestamp NOT NULL, + "period_end" timestamp NOT NULL, + "paid_at" timestamp, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "ambassador_payout_item" ( + "id" text PRIMARY KEY NOT NULL, + "payout_id" text NOT NULL, + "workshop_id" text NOT NULL, + "completion_count" integer NOT NULL, + "rate_cents_per_completion" integer NOT NULL, + "amount_cents" integer NOT NULL +); +--> statement-breakpoint +CREATE TABLE "pathway_shop" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "is_enabled" boolean DEFAULT false NOT NULL, + "currency_name" text DEFAULT 'wish' NOT NULL, + "currency_name_plural" text DEFAULT 'wishes' NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "pathway_shop_pathway_unique" UNIQUE("pathway") +); +--> statement-breakpoint +CREATE TABLE "pathway_week_content" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "week_number" integer NOT NULL, + "title" text DEFAULT '' NOT NULL, + "content" text DEFAULT '' NOT NULL, + "prize_image_url" text, + "is_published" boolean DEFAULT false NOT NULL, + "is_submissions_open" boolean DEFAULT true NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "program_enrollment" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "season_id" text NOT NULL, + "role" "enrollment_role" NOT NULL, + "status" "enrollment_status" DEFAULT 'ACTIVE' NOT NULL, + "joined_at" timestamp DEFAULT now() NOT NULL, + "starting_week" integer DEFAULT 1 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "program_season" ( + "id" text PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "slug" text NOT NULL, + "signup_opens_at" timestamp NOT NULL, + "signup_closes_at" timestamp NOT NULL, + "starts_at" timestamp NOT NULL, + "ends_at" timestamp NOT NULL, + "total_weeks" integer DEFAULT 8 NOT NULL, + "is_active" boolean DEFAULT true NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "program_season_slug_unique" UNIQUE("slug") +); +--> statement-breakpoint +CREATE TABLE "referral_link" ( + "id" text PRIMARY KEY NOT NULL, + "ambassador_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "code" text NOT NULL, + "label" text, + "is_active" boolean DEFAULT true NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "referral_link_code_unique" UNIQUE("code") +); +--> statement-breakpoint +CREATE TABLE "referral_signup" ( + "id" text PRIMARY KEY NOT NULL, + "referral_link_id" text NOT NULL, + "user_id" text NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "reviewer_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "assigned_at" timestamp DEFAULT now() NOT NULL, + "assigned_by" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "session" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "expires_at" timestamp NOT NULL +); +--> statement-breakpoint +CREATE TABLE "shop_item" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "name" text NOT NULL, + "description" text NOT NULL, + "item_url" text, + "item_price" integer NOT NULL, + "item_stock" integer, + "item_type" "shop_item_type" NOT NULL, + "is_active" boolean DEFAULT false NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "shop_orders" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text, + "pathway" "pathway" NOT NULL, + "order_stauts" "shop_order_status" DEFAULT 'PENDING' NOT NULL, + "amount" integer NOT NULL, + "shop_item_id" text, + "item_price_snapshot" integer NOT NULL, + "item_type_enum" "shop_item_type", + "item_name_snapshot" text NOT NULL, + "shipping_address" jsonb, + "phone" text, + "user_notes" text, + "fufiller_notes" text, + "fufilled_by" text, + "fufilled_at" timestamp, + "cancelled_reason" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "currency_transactions" ( + "id" text PRIMARY KEY NOT NULL, + "tx_user_id" text, + "tx_pathway" "pathway" NOT NULL, + "tx_amount" integer NOT NULL, + "tx_reason" "currency_txn_reason" NOT NULL, + "tx_note" text, + "tx_granted_by" text, + "tx_ref_type" text, + "tx_ref_id" text, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "user" ( + "id" text PRIMARY KEY NOT NULL, + "email" text NOT NULL, + "hack_club_id" text NOT NULL, + "first_name" text, + "last_name" text, + "slack_id" text, + "verification_status" text, + "ysws_eligible" boolean DEFAULT false NOT NULL, + "is_admin" boolean DEFAULT false NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "user_email_unique" UNIQUE("email"), + CONSTRAINT "user_hack_club_id_unique" UNIQUE("hack_club_id") +); +--> statement-breakpoint +CREATE TABLE "user_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_batch" ( + "id" text PRIMARY KEY NOT NULL, + "created_by_id" text NOT NULL, + "template_id" text NOT NULL, + "title" text, + "status" "warehouse_batch_status" DEFAULT 'AWAITING_MAPPING' NOT NULL, + "csv_data" text NOT NULL, + "field_mapping" text, + "address_count" integer DEFAULT 0 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_batch_tag" ( + "id" text PRIMARY KEY NOT NULL, + "batch_id" text NOT NULL, + "tag" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_category" ( + "id" text PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "sort_order" integer DEFAULT 0 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_item" ( + "id" text PRIMARY KEY NOT NULL, + "category_id" text, + "name" text NOT NULL, + "sku" text NOT NULL, + "sizing" text, + "package_type" text DEFAULT 'box' NOT NULL, + "length_in" real NOT NULL, + "width_in" real NOT NULL, + "height_in" real NOT NULL, + "weight_grams" real NOT NULL, + "cost_cents" integer NOT NULL, + "hs_code" text DEFAULT '' NOT NULL, + "quantity" integer DEFAULT 0 NOT NULL, + "image_url" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "warehouse_item_sku_unique" UNIQUE("sku") +); +--> statement-breakpoint +CREATE TABLE "warehouse_order" ( + "id" text PRIMARY KEY NOT NULL, + "fulfillment_id" integer GENERATED ALWAYS AS IDENTITY (sequence name "warehouse_order_fulfillment_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1), + "created_by_id" text NOT NULL, + "batch_id" text, + "status" "warehouse_order_status" DEFAULT 'DRAFT' NOT NULL, + "first_name" text NOT NULL, + "last_name" text NOT NULL, + "email" text NOT NULL, + "phone" text, + "address_line_1" text NOT NULL, + "address_line_2" text, + "city" text NOT NULL, + "state_province" text NOT NULL, + "postal_code" text, + "country" text NOT NULL, + "estimated_shipping_cents" integer, + "estimated_duties_cents" integer, + "estimated_service_name" text, + "estimated_service_code" text, + "estimated_package_type" text, + "estimated_total_length_in" real, + "estimated_total_width_in" real, + "estimated_total_height_in" real, + "estimated_total_weight_grams" real, + "packaging_category" text, + "packaging_label" text, + "packaging_length_in" real, + "packaging_width_in" real, + "packaging_height_in" real, + "packaging_subject_to_change" boolean DEFAULT false NOT NULL, + "tracking_number" text, + "label_url" text, + "shipping_method" text, + "billing_status" text DEFAULT 'PENDING' NOT NULL, + "billing_failure_reason" text, + "notes" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "warehouse_order_fulfillment_id_unique" UNIQUE("fulfillment_id") +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_item" ( + "id" text PRIMARY KEY NOT NULL, + "order_id" text NOT NULL, + "warehouse_item_id" text NOT NULL, + "quantity" integer DEFAULT 1 NOT NULL, + "sizing_choice" text +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_tag" ( + "id" text PRIMARY KEY NOT NULL, + "order_id" text NOT NULL, + "tag" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_template" ( + "id" text PRIMARY KEY NOT NULL, + "created_by_id" text NOT NULL, + "name" text NOT NULL, + "is_public" boolean DEFAULT false NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_template_item" ( + "id" text PRIMARY KEY NOT NULL, + "template_id" text NOT NULL, + "warehouse_item_id" text NOT NULL, + "quantity" integer DEFAULT 1 NOT NULL +); +--> statement-breakpoint +CREATE TABLE "weekly_ship" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "season_id" text NOT NULL, + "workshop_id" text, + "week_number" integer NOT NULL, + "goal_text" text NOT NULL, + "status" "ship_status" DEFAULT 'PLANNED' NOT NULL, + "proof_url" text, + "notes" text, + "shipped_at" timestamp, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "workshop" ( + "id" text PRIMARY KEY NOT NULL, + "author_id" text NOT NULL, + "season_id" text NOT NULL, + "title" text NOT NULL, + "description" text NOT NULL, + "pathway" "pathway" NOT NULL, + "difficulty" "difficulty" NOT NULL, + "estimated_hours" integer NOT NULL, + "published" boolean DEFAULT false NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "workshop_analytics" ( + "id" text PRIMARY KEY NOT NULL, + "workshop_id" text NOT NULL, + "views" integer DEFAULT 0 NOT NULL, + "starts" integer DEFAULT 0 NOT NULL, + "completions" integer DEFAULT 0 NOT NULL, + "avg_completion_mins" real, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "workshop_analytics_workshop_id_unique" UNIQUE("workshop_id") +); +--> statement-breakpoint +CREATE TABLE "workshop_completion" ( + "id" text PRIMARY KEY NOT NULL, + "workshop_id" text NOT NULL, + "participant_id" text NOT NULL, + "season_id" text NOT NULL, + "project_url" text, + "started_at" timestamp DEFAULT now() NOT NULL, + "completed_at" timestamp +); +--> statement-breakpoint +ALTER TABLE "ambassador_pathway" ADD CONSTRAINT "ambassador_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_pathway" ADD CONSTRAINT "ambassador_pathway_assigned_by_user_id_fk" FOREIGN KEY ("assigned_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout" ADD CONSTRAINT "ambassador_payout_ambassador_id_user_id_fk" FOREIGN KEY ("ambassador_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout" ADD CONSTRAINT "ambassador_payout_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout_item" ADD CONSTRAINT "ambassador_payout_item_payout_id_ambassador_payout_id_fk" FOREIGN KEY ("payout_id") REFERENCES "public"."ambassador_payout"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout_item" ADD CONSTRAINT "ambassador_payout_item_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "pathway_shop" ADD CONSTRAINT "pathway_shop_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "pathway_week_content" ADD CONSTRAINT "pathway_week_content_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "program_enrollment" ADD CONSTRAINT "program_enrollment_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "program_enrollment" ADD CONSTRAINT "program_enrollment_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "referral_link" ADD CONSTRAINT "referral_link_ambassador_id_user_id_fk" FOREIGN KEY ("ambassador_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "referral_signup" ADD CONSTRAINT "referral_signup_referral_link_id_referral_link_id_fk" FOREIGN KEY ("referral_link_id") REFERENCES "public"."referral_link"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "referral_signup" ADD CONSTRAINT "referral_signup_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "reviewer_pathway" ADD CONSTRAINT "reviewer_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "reviewer_pathway" ADD CONSTRAINT "reviewer_pathway_assigned_by_user_id_fk" FOREIGN KEY ("assigned_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_shop_item_id_shop_item_id_fk" FOREIGN KEY ("shop_item_id") REFERENCES "public"."shop_item"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_fufilled_by_user_id_fk" FOREIGN KEY ("fufilled_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_user_id_user_id_fk" FOREIGN KEY ("tx_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("tx_pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_granted_by_user_id_fk" FOREIGN KEY ("tx_granted_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "user_pathway" ADD CONSTRAINT "user_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_batch" ADD CONSTRAINT "warehouse_batch_created_by_id_user_id_fk" FOREIGN KEY ("created_by_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_batch" ADD CONSTRAINT "warehouse_batch_template_id_warehouse_order_template_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."warehouse_order_template"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_batch_tag" ADD CONSTRAINT "warehouse_batch_tag_batch_id_warehouse_batch_id_fk" FOREIGN KEY ("batch_id") REFERENCES "public"."warehouse_batch"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_item" ADD CONSTRAINT "warehouse_item_category_id_warehouse_category_id_fk" FOREIGN KEY ("category_id") REFERENCES "public"."warehouse_category"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order" ADD CONSTRAINT "warehouse_order_created_by_id_user_id_fk" FOREIGN KEY ("created_by_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_item" ADD CONSTRAINT "warehouse_order_item_order_id_warehouse_order_id_fk" FOREIGN KEY ("order_id") REFERENCES "public"."warehouse_order"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_item" ADD CONSTRAINT "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk" FOREIGN KEY ("warehouse_item_id") REFERENCES "public"."warehouse_item"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_tag" ADD CONSTRAINT "warehouse_order_tag_order_id_warehouse_order_id_fk" FOREIGN KEY ("order_id") REFERENCES "public"."warehouse_order"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_template" ADD CONSTRAINT "warehouse_order_template_created_by_id_user_id_fk" FOREIGN KEY ("created_by_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_template_item" ADD CONSTRAINT "warehouse_order_template_item_template_id_warehouse_order_template_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."warehouse_order_template"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_template_item" ADD CONSTRAINT "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk" FOREIGN KEY ("warehouse_item_id") REFERENCES "public"."warehouse_item"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "weekly_ship" ADD CONSTRAINT "weekly_ship_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "weekly_ship" ADD CONSTRAINT "weekly_ship_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "weekly_ship" ADD CONSTRAINT "weekly_ship_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop" ADD CONSTRAINT "workshop_author_id_user_id_fk" FOREIGN KEY ("author_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop" ADD CONSTRAINT "workshop_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_analytics" ADD CONSTRAINT "workshop_analytics_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_completion" ADD CONSTRAINT "workshop_completion_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_completion" ADD CONSTRAINT "workshop_completion_participant_id_user_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_completion" ADD CONSTRAINT "workshop_completion_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE UNIQUE INDEX "ambassador_pathway_unique_idx" ON "ambassador_pathway" USING btree ("user_id","pathway");--> statement-breakpoint +CREATE UNIQUE INDEX "pathway_week_content_unique_idx" ON "pathway_week_content" USING btree ("pathway","week_number");--> statement-breakpoint +CREATE UNIQUE INDEX "enrollment_user_season_role_idx" ON "program_enrollment" USING btree ("user_id","season_id","role");--> statement-breakpoint +CREATE UNIQUE INDEX "referral_signup_unique_idx" ON "referral_signup" USING btree ("referral_link_id","user_id");--> statement-breakpoint +CREATE UNIQUE INDEX "reviewer_pathway_unique_idx" ON "reviewer_pathway" USING btree ("user_id","pathway");--> statement-breakpoint +CREATE UNIQUE INDEX "user_pathway_unique_idx" ON "user_pathway" USING btree ("user_id","pathway");--> statement-breakpoint +CREATE UNIQUE INDEX "warehouse_batch_tag_unique_idx" ON "warehouse_batch_tag" USING btree ("batch_id","tag");--> statement-breakpoint +CREATE INDEX "warehouse_order_item_order_id_idx" ON "warehouse_order_item" USING btree ("order_id");--> statement-breakpoint +CREATE INDEX "warehouse_order_item_warehouse_item_id_idx" ON "warehouse_order_item" USING btree ("warehouse_item_id");--> statement-breakpoint +CREATE UNIQUE INDEX "warehouse_order_tag_unique_idx" ON "warehouse_order_tag" USING btree ("order_id","tag");--> statement-breakpoint +CREATE INDEX "warehouse_order_tag_tag_idx" ON "warehouse_order_tag" USING btree ("tag");--> statement-breakpoint +CREATE INDEX "ship_user_season_week_idx" ON "weekly_ship" USING btree ("user_id","season_id","week_number");--> statement-breakpoint +CREATE UNIQUE INDEX "completion_workshop_participant_season_idx" ON "workshop_completion" USING btree ("workshop_id","participant_id","season_id"); \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup2/meta/0000_snapshot.json b/resolution-frontend/drizzle.backup2/meta/0000_snapshot.json new file mode 100644 index 0000000..5b167e5 --- /dev/null +++ b/resolution-frontend/drizzle.backup2/meta/0000_snapshot.json @@ -0,0 +1,3111 @@ +{ + "id": "e2384d76-2d19-41ed-bd29-897f1528c49d", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ambassador_pathway": { + "name": "ambassador_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "ambassador_pathway_unique_idx": { + "name": "ambassador_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ambassador_pathway_user_id_user_id_fk": { + "name": "ambassador_pathway_user_id_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_pathway_assigned_by_user_id_fk": { + "name": "ambassador_pathway_assigned_by_user_id_fk", + "tableFrom": "ambassador_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout": { + "name": "ambassador_payout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "payout_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "paid_at": { + "name": "paid_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_ambassador_id_user_id_fk": { + "name": "ambassador_payout_ambassador_id_user_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_season_id_program_season_id_fk": { + "name": "ambassador_payout_season_id_program_season_id_fk", + "tableFrom": "ambassador_payout", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ambassador_payout_item": { + "name": "ambassador_payout_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "payout_id": { + "name": "payout_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "completion_count": { + "name": "completion_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rate_cents_per_completion": { + "name": "rate_cents_per_completion", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "amount_cents": { + "name": "amount_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ambassador_payout_item_payout_id_ambassador_payout_id_fk": { + "name": "ambassador_payout_item_payout_id_ambassador_payout_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "ambassador_payout", + "columnsFrom": [ + "payout_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ambassador_payout_item_workshop_id_workshop_id_fk": { + "name": "ambassador_payout_item_workshop_id_workshop_id_fk", + "tableFrom": "ambassador_payout_item", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_shop": { + "name": "pathway_shop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "currency_name": { + "name": "currency_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wish'" + }, + "currency_name_plural": { + "name": "currency_name_plural", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wishes'" + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "pathway_shop_last_edited_by_user_id_fk": { + "name": "pathway_shop_last_edited_by_user_id_fk", + "tableFrom": "pathway_shop", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pathway_shop_pathway_unique": { + "name": "pathway_shop_pathway_unique", + "nullsNotDistinct": false, + "columns": [ + "pathway" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pathway_week_content": { + "name": "pathway_week_content", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "prize_image_url": { + "name": "prize_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_submissions_open": { + "name": "is_submissions_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pathway_week_content_unique_idx": { + "name": "pathway_week_content_unique_idx", + "columns": [ + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pathway_week_content_last_edited_by_user_id_fk": { + "name": "pathway_week_content_last_edited_by_user_id_fk", + "tableFrom": "pathway_week_content", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_enrollment": { + "name": "program_enrollment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enrollment_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "enrollment_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ACTIVE'" + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "starting_week": { + "name": "starting_week", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "enrollment_user_season_role_idx": { + "name": "enrollment_user_season_role_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "program_enrollment_user_id_user_id_fk": { + "name": "program_enrollment_user_id_user_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "program_enrollment_season_id_program_season_id_fk": { + "name": "program_enrollment_season_id_program_season_id_fk", + "tableFrom": "program_enrollment", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.program_season": { + "name": "program_season", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signup_opens_at": { + "name": "signup_opens_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "signup_closes_at": { + "name": "signup_closes_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "total_weeks": { + "name": "total_weeks", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 8 + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_link": { + "name": "referral_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviewer_pathway": { + "name": "reviewer_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "reviewer_pathway_unique_idx": { + "name": "reviewer_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviewer_pathway_user_id_user_id_fk": { + "name": "reviewer_pathway_user_id_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reviewer_pathway_assigned_by_user_id_fk": { + "name": "reviewer_pathway_assigned_by_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_item": { + "name": "shop_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_url": { + "name": "item_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price": { + "name": "item_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_stock": { + "name": "item_stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "item_type": { + "name": "item_type", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_item_pathway_pathway_shop_pathway_fk": { + "name": "shop_item_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_item", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_last_edited_by_user_id_fk": { + "name": "shop_item_last_edited_by_user_id_fk", + "tableFrom": "shop_item", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_orders": { + "name": "shop_orders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "order_stauts": { + "name": "order_stauts", + "type": "shop_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "shop_item_id": { + "name": "shop_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price_snapshot": { + "name": "item_price_snapshot", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_type_enum": { + "name": "item_type_enum", + "type": "shop_item_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "item_name_snapshot": { + "name": "item_name_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shipping_address": { + "name": "shipping_address", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_notes": { + "name": "user_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufiller_notes": { + "name": "fufiller_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_by": { + "name": "fufilled_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_at": { + "name": "fufilled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancelled_reason": { + "name": "cancelled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_orders_user_id_user_id_fk": { + "name": "shop_orders_user_id_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_pathway_pathway_shop_pathway_fk": { + "name": "shop_orders_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_orders", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_orders_shop_item_id_shop_item_id_fk": { + "name": "shop_orders_shop_item_id_shop_item_id_fk", + "tableFrom": "shop_orders", + "tableTo": "shop_item", + "columnsFrom": [ + "shop_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_fufilled_by_user_id_fk": { + "name": "shop_orders_fufilled_by_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "fufilled_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.currency_transactions": { + "name": "currency_transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tx_user_id": { + "name": "tx_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_pathway": { + "name": "tx_pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_amount": { + "name": "tx_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tx_reason": { + "name": "tx_reason", + "type": "currency_txn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_note": { + "name": "tx_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_granted_by": { + "name": "tx_granted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_type": { + "name": "tx_ref_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_id": { + "name": "tx_ref_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "currency_transactions_tx_user_id_user_id_fk": { + "name": "currency_transactions_tx_user_id_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "currency_transactions_tx_pathway_pathway_shop_pathway_fk": { + "name": "currency_transactions_tx_pathway_pathway_shop_pathway_fk", + "tableFrom": "currency_transactions", + "tableTo": "pathway_shop", + "columnsFrom": [ + "tx_pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "currency_transactions_tx_granted_by_user_id_fk": { + "name": "currency_transactions_tx_granted_by_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch": { + "name": "warehouse_batch", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_batch_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'AWAITING_MAPPING'" + }, + "csv_data": { + "name": "csv_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_mapping": { + "name": "field_mapping", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_count": { + "name": "address_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_batch_created_by_id_user_id_fk": { + "name": "warehouse_batch_created_by_id_user_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_batch_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_batch_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch_tag": { + "name": "warehouse_batch_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "warehouse_batch_tag_unique_idx": { + "name": "warehouse_batch_tag_unique_idx", + "columns": [ + { + "expression": "batch_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_batch_tag_batch_id_warehouse_batch_id_fk": { + "name": "warehouse_batch_tag_batch_id_warehouse_batch_id_fk", + "tableFrom": "warehouse_batch_tag", + "tableTo": "warehouse_batch", + "columnsFrom": [ + "batch_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_category": { + "name": "warehouse_category", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_item": { + "name": "warehouse_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "category_id": { + "name": "category_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sku": { + "name": "sku", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sizing": { + "name": "sizing", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "package_type": { + "name": "package_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'box'" + }, + "length_in": { + "name": "length_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "width_in": { + "name": "width_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "height_in": { + "name": "height_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "weight_grams": { + "name": "weight_grams", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "cost_cents": { + "name": "cost_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "hs_code": { + "name": "hs_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_item_category_id_warehouse_category_id_fk": { + "name": "warehouse_item_category_id_warehouse_category_id_fk", + "tableFrom": "warehouse_item", + "tableTo": "warehouse_category", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_item_sku_unique": { + "name": "warehouse_item_sku_unique", + "nullsNotDistinct": false, + "columns": [ + "sku" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order": { + "name": "warehouse_order", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fulfillment_id": { + "name": "fulfillment_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "warehouse_order_fulfillment_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_line_1": { + "name": "address_line_1", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address_line_2": { + "name": "address_line_2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "city": { + "name": "city", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_province": { + "name": "state_province", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "postal_code": { + "name": "postal_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "estimated_shipping_cents": { + "name": "estimated_shipping_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_duties_cents": { + "name": "estimated_duties_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_service_name": { + "name": "estimated_service_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_service_code": { + "name": "estimated_service_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_package_type": { + "name": "estimated_package_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_total_length_in": { + "name": "estimated_total_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_width_in": { + "name": "estimated_total_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_height_in": { + "name": "estimated_total_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_weight_grams": { + "name": "estimated_total_weight_grams", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_category": { + "name": "packaging_category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_label": { + "name": "packaging_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_length_in": { + "name": "packaging_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_width_in": { + "name": "packaging_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_height_in": { + "name": "packaging_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_subject_to_change": { + "name": "packaging_subject_to_change", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "tracking_number": { + "name": "tracking_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "label_url": { + "name": "label_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipping_method": { + "name": "shipping_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_status": { + "name": "billing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "billing_failure_reason": { + "name": "billing_failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_created_by_id_user_id_fk": { + "name": "warehouse_order_created_by_id_user_id_fk", + "tableFrom": "warehouse_order", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_order_fulfillment_id_unique": { + "name": "warehouse_order_fulfillment_id_unique", + "nullsNotDistinct": false, + "columns": [ + "fulfillment_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_item": { + "name": "warehouse_order_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "order_id": { + "name": "order_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "sizing_choice": { + "name": "sizing_choice", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "warehouse_order_item_order_id_idx": { + "name": "warehouse_order_item_order_id_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_item_warehouse_item_id_idx": { + "name": "warehouse_order_item_warehouse_item_id_idx", + "columns": [ + { + "expression": "warehouse_item_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_order_item_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_item_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_order", + "columnsFrom": [ + "order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_tag": { + "name": "warehouse_order_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "order_id": { + "name": "order_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "warehouse_order_tag_unique_idx": { + "name": "warehouse_order_tag_unique_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_tag_tag_idx": { + "name": "warehouse_order_tag_tag_idx", + "columns": [ + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_order_tag_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_tag_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_tag", + "tableTo": "warehouse_order", + "columnsFrom": [ + "order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_template": { + "name": "warehouse_order_template", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_public": { + "name": "is_public", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_template_created_by_id_user_id_fk": { + "name": "warehouse_order_template_created_by_id_user_id_fk", + "tableFrom": "warehouse_order_template", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_template_item": { + "name": "warehouse_order_template_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_template_item_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_order_template_item_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.weekly_ship": { + "name": "weekly_ship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "week_number": { + "name": "week_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "goal_text": { + "name": "goal_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "ship_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PLANNED'" + }, + "proof_url": { + "name": "proof_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipped_at": { + "name": "shipped_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "ship_user_season_week_idx": { + "name": "ship_user_season_week_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "week_number", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "weekly_ship_user_id_user_id_fk": { + "name": "weekly_ship_user_id_user_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_season_id_program_season_id_fk": { + "name": "weekly_ship_season_id_program_season_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "weekly_ship_workshop_id_workshop_id_fk": { + "name": "weekly_ship_workshop_id_workshop_id_fk", + "tableFrom": "weekly_ship", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop": { + "name": "workshop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "difficulty": { + "name": "difficulty", + "type": "difficulty", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "estimated_hours": { + "name": "estimated_hours", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "published": { + "name": "published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_author_id_user_id_fk": { + "name": "workshop_author_id_user_id_fk", + "tableFrom": "workshop", + "tableTo": "user", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_season_id_program_season_id_fk": { + "name": "workshop_season_id_program_season_id_fk", + "tableFrom": "workshop", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_analytics": { + "name": "workshop_analytics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "starts": { + "name": "starts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "completions": { + "name": "completions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "avg_completion_mins": { + "name": "avg_completion_mins", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workshop_analytics_workshop_id_workshop_id_fk": { + "name": "workshop_analytics_workshop_id_workshop_id_fk", + "tableFrom": "workshop_analytics", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workshop_analytics_workshop_id_unique": { + "name": "workshop_analytics_workshop_id_unique", + "nullsNotDistinct": false, + "columns": [ + "workshop_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workshop_completion": { + "name": "workshop_completion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workshop_id": { + "name": "workshop_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "participant_id": { + "name": "participant_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "season_id": { + "name": "season_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_url": { + "name": "project_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "completion_workshop_participant_season_idx": { + "name": "completion_workshop_participant_season_idx", + "columns": [ + { + "expression": "workshop_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "participant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "season_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workshop_completion_workshop_id_workshop_id_fk": { + "name": "workshop_completion_workshop_id_workshop_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "workshop", + "columnsFrom": [ + "workshop_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_participant_id_user_id_fk": { + "name": "workshop_completion_participant_id_user_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "user", + "columnsFrom": [ + "participant_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workshop_completion_season_id_program_season_id_fk": { + "name": "workshop_completion_season_id_program_season_id_fk", + "tableFrom": "workshop_completion", + "tableTo": "program_season", + "columnsFrom": [ + "season_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.currency_txn_reason": { + "name": "currency_txn_reason", + "schema": "public", + "values": [ + "GRANT", + "PURCHASE", + "REFUND", + "ADJUSTMENT", + "OTHER" + ] + }, + "public.difficulty": { + "name": "difficulty", + "schema": "public", + "values": [ + "BEGINNER", + "INTERMEDIATE", + "ADVANCED" + ] + }, + "public.enrollment_role": { + "name": "enrollment_role", + "schema": "public", + "values": [ + "PARTICIPANT", + "AMBASSADOR" + ] + }, + "public.enrollment_status": { + "name": "enrollment_status", + "schema": "public", + "values": [ + "ACTIVE", + "DROPPED", + "COMPLETED" + ] + }, + "public.pathway": { + "name": "pathway", + "schema": "public", + "values": [ + "PYTHON", + "RUST", + "GAME_DEV", + "HARDWARE", + "DESIGN", + "GENERAL_CODING" + ] + }, + "public.payout_status": { + "name": "payout_status", + "schema": "public", + "values": [ + "DRAFT", + "PENDING", + "PAID", + "CANCELED" + ] + }, + "public.ship_status": { + "name": "ship_status", + "schema": "public", + "values": [ + "PLANNED", + "IN_PROGRESS", + "SHIPPED", + "MISSED" + ] + }, + "public.shop_item_type": { + "name": "shop_item_type", + "schema": "public", + "values": [ + "PHYSICAL", + "DIGITAL" + ] + }, + "public.shop_order_status": { + "name": "shop_order_status", + "schema": "public", + "values": [ + "PENDING", + "PROCESSING", + "FULFILLED", + "CANCELED" + ] + }, + "public.warehouse_batch_status": { + "name": "warehouse_batch_status", + "schema": "public", + "values": [ + "AWAITING_MAPPING", + "MAPPED", + "PROCESSED" + ] + }, + "public.warehouse_order_status": { + "name": "warehouse_order_status", + "schema": "public", + "values": [ + "DRAFT", + "ESTIMATED", + "APPROVED", + "SHIPPED", + "CANCELLED" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/resolution-frontend/drizzle.backup2/meta/_journal.json b/resolution-frontend/drizzle.backup2/meta/_journal.json new file mode 100644 index 0000000..ae2f559 --- /dev/null +++ b/resolution-frontend/drizzle.backup2/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1778709057473, + "tag": "0000_baseline", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/resolution-frontend/drizzle/0000_redundant_gamora.sql b/resolution-frontend/drizzle/0000_redundant_gamora.sql new file mode 100644 index 0000000..a3675cb --- /dev/null +++ b/resolution-frontend/drizzle/0000_redundant_gamora.sql @@ -0,0 +1,424 @@ +CREATE TYPE "public"."currency_txn_reason" AS ENUM('GRANT', 'PURCHASE', 'REFUND', 'ADJUSTMENT', 'OTHER');--> statement-breakpoint +CREATE TYPE "public"."difficulty" AS ENUM('BEGINNER', 'INTERMEDIATE', 'ADVANCED');--> statement-breakpoint +CREATE TYPE "public"."enrollment_role" AS ENUM('PARTICIPANT', 'AMBASSADOR');--> statement-breakpoint +CREATE TYPE "public"."enrollment_status" AS ENUM('ACTIVE', 'DROPPED', 'COMPLETED');--> statement-breakpoint +CREATE TYPE "public"."pathway" AS ENUM('PYTHON', 'RUST', 'GAME_DEV', 'HARDWARE', 'DESIGN', 'GENERAL_CODING');--> statement-breakpoint +CREATE TYPE "public"."payout_status" AS ENUM('DRAFT', 'PENDING', 'PAID', 'CANCELED');--> statement-breakpoint +CREATE TYPE "public"."ship_status" AS ENUM('PLANNED', 'IN_PROGRESS', 'SHIPPED', 'MISSED');--> statement-breakpoint +CREATE TYPE "public"."shop_item_source" AS ENUM('CUSTOM', 'WAREHOUSE_ITEM', 'WAREHOUSE_TEMPLATE');--> statement-breakpoint +CREATE TYPE "public"."shop_order_status" AS ENUM('PENDING', 'PROCESSING', 'FULFILLED', 'CANCELED');--> statement-breakpoint +CREATE TYPE "public"."warehouse_batch_status" AS ENUM('AWAITING_MAPPING', 'MAPPED', 'PROCESSED');--> statement-breakpoint +CREATE TYPE "public"."warehouse_order_status" AS ENUM('DRAFT', 'ESTIMATED', 'APPROVED', 'SHIPPED', 'CANCELLED');--> statement-breakpoint +CREATE TABLE "ambassador_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "assigned_at" timestamp DEFAULT now() NOT NULL, + "assigned_by" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "ambassador_payout" ( + "id" text PRIMARY KEY NOT NULL, + "ambassador_id" text NOT NULL, + "season_id" text NOT NULL, + "amount_cents" integer NOT NULL, + "status" "payout_status" DEFAULT 'DRAFT' NOT NULL, + "period_start" timestamp NOT NULL, + "period_end" timestamp NOT NULL, + "paid_at" timestamp, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "ambassador_payout_item" ( + "id" text PRIMARY KEY NOT NULL, + "payout_id" text NOT NULL, + "workshop_id" text NOT NULL, + "completion_count" integer NOT NULL, + "rate_cents_per_completion" integer NOT NULL, + "amount_cents" integer NOT NULL +); +--> statement-breakpoint +CREATE TABLE "pathway_shop" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "is_enabled" boolean DEFAULT false NOT NULL, + "currency_name" text DEFAULT 'wish' NOT NULL, + "currency_name_plural" text DEFAULT 'wishes' NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "pathway_shop_pathway_unique" UNIQUE("pathway") +); +--> statement-breakpoint +CREATE TABLE "pathway_week_content" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "week_number" integer NOT NULL, + "title" text DEFAULT '' NOT NULL, + "content" text DEFAULT '' NOT NULL, + "prize_image_url" text, + "is_published" boolean DEFAULT false NOT NULL, + "is_submissions_open" boolean DEFAULT true NOT NULL, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "program_enrollment" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "season_id" text NOT NULL, + "role" "enrollment_role" NOT NULL, + "status" "enrollment_status" DEFAULT 'ACTIVE' NOT NULL, + "joined_at" timestamp DEFAULT now() NOT NULL, + "starting_week" integer DEFAULT 1 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "program_season" ( + "id" text PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "slug" text NOT NULL, + "signup_opens_at" timestamp NOT NULL, + "signup_closes_at" timestamp NOT NULL, + "starts_at" timestamp NOT NULL, + "ends_at" timestamp NOT NULL, + "total_weeks" integer DEFAULT 8 NOT NULL, + "is_active" boolean DEFAULT true NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "program_season_slug_unique" UNIQUE("slug") +); +--> statement-breakpoint +CREATE TABLE "referral_link" ( + "id" text PRIMARY KEY NOT NULL, + "ambassador_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "code" text NOT NULL, + "label" text, + "is_active" boolean DEFAULT true NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "referral_link_code_unique" UNIQUE("code") +); +--> statement-breakpoint +CREATE TABLE "referral_signup" ( + "id" text PRIMARY KEY NOT NULL, + "referral_link_id" text NOT NULL, + "user_id" text NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "reviewer_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "assigned_at" timestamp DEFAULT now() NOT NULL, + "assigned_by" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "session" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "expires_at" timestamp NOT NULL +); +--> statement-breakpoint +CREATE TABLE "shop_item" ( + "id" text PRIMARY KEY NOT NULL, + "pathway" "pathway" NOT NULL, + "name" text NOT NULL, + "description" text NOT NULL, + "item_image_url" text, + "item_price" integer NOT NULL, + "item_stock" integer, + "is_active" boolean DEFAULT false NOT NULL, + "source_type" "shop_item_source" DEFAULT 'CUSTOM' NOT NULL, + "linked_warehouse_item_id" text, + "linked_warehouse_template_id" text, + "last_edited_by" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "shop_orders" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text, + "pathway" "pathway" NOT NULL, + "order_status" "shop_order_status" DEFAULT 'PENDING' NOT NULL, + "amount" integer NOT NULL, + "shop_item_id" text, + "item_price_snapshot" integer NOT NULL, + "item_name_snapshot" text NOT NULL, + "shipping_address" jsonb, + "phone" text, + "user_notes" text, + "fufiller_notes" text, + "fufilled_by" text, + "fufilled_at" timestamp, + "cancelled_reason" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "currency_transactions" ( + "id" text PRIMARY KEY NOT NULL, + "tx_user_id" text, + "tx_pathway" "pathway" NOT NULL, + "tx_amount" integer NOT NULL, + "tx_reason" "currency_txn_reason" NOT NULL, + "tx_note" text, + "tx_granted_by" text, + "tx_ref_type" text, + "tx_ref_id" text, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "user" ( + "id" text PRIMARY KEY NOT NULL, + "email" text NOT NULL, + "hack_club_id" text NOT NULL, + "first_name" text, + "last_name" text, + "slack_id" text, + "verification_status" text, + "ysws_eligible" boolean DEFAULT false NOT NULL, + "is_admin" boolean DEFAULT false NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "user_email_unique" UNIQUE("email"), + CONSTRAINT "user_hack_club_id_unique" UNIQUE("hack_club_id") +); +--> statement-breakpoint +CREATE TABLE "user_pathway" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "pathway" "pathway" NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_batch" ( + "id" text PRIMARY KEY NOT NULL, + "created_by_id" text NOT NULL, + "template_id" text NOT NULL, + "title" text, + "status" "warehouse_batch_status" DEFAULT 'AWAITING_MAPPING' NOT NULL, + "csv_data" text NOT NULL, + "field_mapping" text, + "address_count" integer DEFAULT 0 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_batch_tag" ( + "id" text PRIMARY KEY NOT NULL, + "batch_id" text NOT NULL, + "tag" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_category" ( + "id" text PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "sort_order" integer DEFAULT 0 NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_item" ( + "id" text PRIMARY KEY NOT NULL, + "category_id" text, + "name" text NOT NULL, + "sku" text NOT NULL, + "sizing" text, + "package_type" text DEFAULT 'box' NOT NULL, + "length_in" real NOT NULL, + "width_in" real NOT NULL, + "height_in" real NOT NULL, + "weight_grams" real NOT NULL, + "cost_cents" integer NOT NULL, + "hs_code" text DEFAULT '' NOT NULL, + "quantity" integer DEFAULT 0 NOT NULL, + "image_url" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "warehouse_item_sku_unique" UNIQUE("sku") +); +--> statement-breakpoint +CREATE TABLE "warehouse_order" ( + "id" text PRIMARY KEY NOT NULL, + "fulfillment_id" integer GENERATED ALWAYS AS IDENTITY (sequence name "warehouse_order_fulfillment_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1), + "created_by_id" text NOT NULL, + "batch_id" text, + "status" "warehouse_order_status" DEFAULT 'DRAFT' NOT NULL, + "first_name" text NOT NULL, + "last_name" text NOT NULL, + "email" text NOT NULL, + "phone" text, + "address_line_1" text NOT NULL, + "address_line_2" text, + "city" text NOT NULL, + "state_province" text NOT NULL, + "postal_code" text, + "country" text NOT NULL, + "estimated_shipping_cents" integer, + "estimated_duties_cents" integer, + "estimated_service_name" text, + "estimated_service_code" text, + "estimated_package_type" text, + "estimated_total_length_in" real, + "estimated_total_width_in" real, + "estimated_total_height_in" real, + "estimated_total_weight_grams" real, + "packaging_category" text, + "packaging_label" text, + "packaging_length_in" real, + "packaging_width_in" real, + "packaging_height_in" real, + "packaging_subject_to_change" boolean DEFAULT false NOT NULL, + "tracking_number" text, + "label_url" text, + "shipping_method" text, + "billing_status" text DEFAULT 'PENDING' NOT NULL, + "billing_failure_reason" text, + "notes" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "warehouse_order_fulfillment_id_unique" UNIQUE("fulfillment_id") +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_item" ( + "id" text PRIMARY KEY NOT NULL, + "order_id" text NOT NULL, + "warehouse_item_id" text NOT NULL, + "quantity" integer DEFAULT 1 NOT NULL, + "sizing_choice" text +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_tag" ( + "id" text PRIMARY KEY NOT NULL, + "order_id" text NOT NULL, + "tag" text NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_template" ( + "id" text PRIMARY KEY NOT NULL, + "created_by_id" text NOT NULL, + "name" text NOT NULL, + "is_public" boolean DEFAULT false NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "warehouse_order_template_item" ( + "id" text PRIMARY KEY NOT NULL, + "template_id" text NOT NULL, + "warehouse_item_id" text NOT NULL, + "quantity" integer DEFAULT 1 NOT NULL +); +--> statement-breakpoint +CREATE TABLE "weekly_ship" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "season_id" text NOT NULL, + "workshop_id" text, + "week_number" integer NOT NULL, + "goal_text" text NOT NULL, + "status" "ship_status" DEFAULT 'PLANNED' NOT NULL, + "proof_url" text, + "notes" text, + "shipped_at" timestamp, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "workshop" ( + "id" text PRIMARY KEY NOT NULL, + "author_id" text NOT NULL, + "season_id" text NOT NULL, + "title" text NOT NULL, + "description" text NOT NULL, + "pathway" "pathway" NOT NULL, + "difficulty" "difficulty" NOT NULL, + "estimated_hours" integer NOT NULL, + "published" boolean DEFAULT false NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "workshop_analytics" ( + "id" text PRIMARY KEY NOT NULL, + "workshop_id" text NOT NULL, + "views" integer DEFAULT 0 NOT NULL, + "starts" integer DEFAULT 0 NOT NULL, + "completions" integer DEFAULT 0 NOT NULL, + "avg_completion_mins" real, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "workshop_analytics_workshop_id_unique" UNIQUE("workshop_id") +); +--> statement-breakpoint +CREATE TABLE "workshop_completion" ( + "id" text PRIMARY KEY NOT NULL, + "workshop_id" text NOT NULL, + "participant_id" text NOT NULL, + "season_id" text NOT NULL, + "project_url" text, + "started_at" timestamp DEFAULT now() NOT NULL, + "completed_at" timestamp +); +--> statement-breakpoint +ALTER TABLE "ambassador_pathway" ADD CONSTRAINT "ambassador_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_pathway" ADD CONSTRAINT "ambassador_pathway_assigned_by_user_id_fk" FOREIGN KEY ("assigned_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout" ADD CONSTRAINT "ambassador_payout_ambassador_id_user_id_fk" FOREIGN KEY ("ambassador_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout" ADD CONSTRAINT "ambassador_payout_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout_item" ADD CONSTRAINT "ambassador_payout_item_payout_id_ambassador_payout_id_fk" FOREIGN KEY ("payout_id") REFERENCES "public"."ambassador_payout"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "ambassador_payout_item" ADD CONSTRAINT "ambassador_payout_item_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "pathway_shop" ADD CONSTRAINT "pathway_shop_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "pathway_week_content" ADD CONSTRAINT "pathway_week_content_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "program_enrollment" ADD CONSTRAINT "program_enrollment_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "program_enrollment" ADD CONSTRAINT "program_enrollment_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "referral_link" ADD CONSTRAINT "referral_link_ambassador_id_user_id_fk" FOREIGN KEY ("ambassador_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "referral_signup" ADD CONSTRAINT "referral_signup_referral_link_id_referral_link_id_fk" FOREIGN KEY ("referral_link_id") REFERENCES "public"."referral_link"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "referral_signup" ADD CONSTRAINT "referral_signup_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "reviewer_pathway" ADD CONSTRAINT "reviewer_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "reviewer_pathway" ADD CONSTRAINT "reviewer_pathway_assigned_by_user_id_fk" FOREIGN KEY ("assigned_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_linked_warehouse_item_id_warehouse_item_id_fk" FOREIGN KEY ("linked_warehouse_item_id") REFERENCES "public"."warehouse_item"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_linked_warehouse_template_id_warehouse_order_template_id_fk" FOREIGN KEY ("linked_warehouse_template_id") REFERENCES "public"."warehouse_order_template"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_item" ADD CONSTRAINT "shop_item_last_edited_by_user_id_fk" FOREIGN KEY ("last_edited_by") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_shop_item_id_shop_item_id_fk" FOREIGN KEY ("shop_item_id") REFERENCES "public"."shop_item"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "shop_orders" ADD CONSTRAINT "shop_orders_fufilled_by_user_id_fk" FOREIGN KEY ("fufilled_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_user_id_user_id_fk" FOREIGN KEY ("tx_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_pathway_pathway_shop_pathway_fk" FOREIGN KEY ("tx_pathway") REFERENCES "public"."pathway_shop"("pathway") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "currency_transactions" ADD CONSTRAINT "currency_transactions_tx_granted_by_user_id_fk" FOREIGN KEY ("tx_granted_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "user_pathway" ADD CONSTRAINT "user_pathway_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_batch" ADD CONSTRAINT "warehouse_batch_created_by_id_user_id_fk" FOREIGN KEY ("created_by_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_batch" ADD CONSTRAINT "warehouse_batch_template_id_warehouse_order_template_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."warehouse_order_template"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_batch_tag" ADD CONSTRAINT "warehouse_batch_tag_batch_id_warehouse_batch_id_fk" FOREIGN KEY ("batch_id") REFERENCES "public"."warehouse_batch"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_item" ADD CONSTRAINT "warehouse_item_category_id_warehouse_category_id_fk" FOREIGN KEY ("category_id") REFERENCES "public"."warehouse_category"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order" ADD CONSTRAINT "warehouse_order_created_by_id_user_id_fk" FOREIGN KEY ("created_by_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_item" ADD CONSTRAINT "warehouse_order_item_order_id_warehouse_order_id_fk" FOREIGN KEY ("order_id") REFERENCES "public"."warehouse_order"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_item" ADD CONSTRAINT "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk" FOREIGN KEY ("warehouse_item_id") REFERENCES "public"."warehouse_item"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_tag" ADD CONSTRAINT "warehouse_order_tag_order_id_warehouse_order_id_fk" FOREIGN KEY ("order_id") REFERENCES "public"."warehouse_order"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_template" ADD CONSTRAINT "warehouse_order_template_created_by_id_user_id_fk" FOREIGN KEY ("created_by_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_template_item" ADD CONSTRAINT "warehouse_order_template_item_template_id_warehouse_order_template_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."warehouse_order_template"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "warehouse_order_template_item" ADD CONSTRAINT "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk" FOREIGN KEY ("warehouse_item_id") REFERENCES "public"."warehouse_item"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "weekly_ship" ADD CONSTRAINT "weekly_ship_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "weekly_ship" ADD CONSTRAINT "weekly_ship_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "weekly_ship" ADD CONSTRAINT "weekly_ship_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop" ADD CONSTRAINT "workshop_author_id_user_id_fk" FOREIGN KEY ("author_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop" ADD CONSTRAINT "workshop_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_analytics" ADD CONSTRAINT "workshop_analytics_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_completion" ADD CONSTRAINT "workshop_completion_workshop_id_workshop_id_fk" FOREIGN KEY ("workshop_id") REFERENCES "public"."workshop"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_completion" ADD CONSTRAINT "workshop_completion_participant_id_user_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "workshop_completion" ADD CONSTRAINT "workshop_completion_season_id_program_season_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."program_season"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE UNIQUE INDEX "ambassador_pathway_unique_idx" ON "ambassador_pathway" USING btree ("user_id","pathway");--> statement-breakpoint +CREATE UNIQUE INDEX "pathway_week_content_unique_idx" ON "pathway_week_content" USING btree ("pathway","week_number");--> statement-breakpoint +CREATE UNIQUE INDEX "enrollment_user_season_role_idx" ON "program_enrollment" USING btree ("user_id","season_id","role");--> statement-breakpoint +CREATE UNIQUE INDEX "referral_signup_unique_idx" ON "referral_signup" USING btree ("referral_link_id","user_id");--> statement-breakpoint +CREATE UNIQUE INDEX "reviewer_pathway_unique_idx" ON "reviewer_pathway" USING btree ("user_id","pathway");--> statement-breakpoint +CREATE UNIQUE INDEX "user_pathway_unique_idx" ON "user_pathway" USING btree ("user_id","pathway");--> statement-breakpoint +CREATE UNIQUE INDEX "warehouse_batch_tag_unique_idx" ON "warehouse_batch_tag" USING btree ("batch_id","tag");--> statement-breakpoint +CREATE INDEX "warehouse_order_item_order_id_idx" ON "warehouse_order_item" USING btree ("order_id");--> statement-breakpoint +CREATE INDEX "warehouse_order_item_warehouse_item_id_idx" ON "warehouse_order_item" USING btree ("warehouse_item_id");--> statement-breakpoint +CREATE UNIQUE INDEX "warehouse_order_tag_unique_idx" ON "warehouse_order_tag" USING btree ("order_id","tag");--> statement-breakpoint +CREATE INDEX "warehouse_order_tag_tag_idx" ON "warehouse_order_tag" USING btree ("tag");--> statement-breakpoint +CREATE INDEX "ship_user_season_week_idx" ON "weekly_ship" USING btree ("user_id","season_id","week_number");--> statement-breakpoint +CREATE UNIQUE INDEX "completion_workshop_participant_season_idx" ON "workshop_completion" USING btree ("workshop_id","participant_id","season_id"); \ No newline at end of file diff --git a/resolution-frontend/drizzle/0001_sloppy_namora.sql b/resolution-frontend/drizzle/0001_sloppy_namora.sql new file mode 100644 index 0000000..89b9647 --- /dev/null +++ b/resolution-frontend/drizzle/0001_sloppy_namora.sql @@ -0,0 +1,4 @@ +ALTER TYPE "public"."shop_order_status" ADD VALUE 'REJECTED';--> statement-breakpoint +ALTER TABLE "shop_orders" ADD COLUMN "tracking_number" text;--> statement-breakpoint +ALTER TABLE "warehouse_order" ADD COLUMN "shop_order_id" text;--> statement-breakpoint +ALTER TABLE "warehouse_order" ADD CONSTRAINT "warehouse_order_shop_order_id_shop_orders_id_fk" FOREIGN KEY ("shop_order_id") REFERENCES "public"."shop_orders"("id") ON DELETE set null ON UPDATE no action; \ No newline at end of file diff --git a/resolution-frontend/drizzle/meta/0000_snapshot.json b/resolution-frontend/drizzle/meta/0000_snapshot.json index b667fb0..630239c 100644 --- a/resolution-frontend/drizzle/meta/0000_snapshot.json +++ b/resolution-frontend/drizzle/meta/0000_snapshot.json @@ -1,5 +1,5 @@ { - "id": "ee4874ac-fef8-4ca8-ab84-17f57639d40b", + "id": "04f6d62e-e75a-447d-9462-ec816fc41e19", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -271,6 +271,95 @@ "checkConstraints": {}, "isRLSEnabled": false }, + "public.pathway_shop": { + "name": "pathway_shop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "currency_name": { + "name": "currency_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wish'" + }, + "currency_name_plural": { + "name": "currency_name_plural", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wishes'" + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "pathway_shop_last_edited_by_user_id_fk": { + "name": "pathway_shop_last_edited_by_user_id_fk", + "tableFrom": "pathway_shop", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pathway_shop_pathway_unique": { + "name": "pathway_shop_pathway_unique", + "nullsNotDistinct": false, + "columns": [ + "pathway" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, "public.pathway_week_content": { "name": "pathway_week_content", "schema": "", @@ -308,6 +397,12 @@ "notNull": true, "default": "''" }, + "prize_image_url": { + "name": "prize_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, "is_published": { "name": "is_published", "type": "boolean", @@ -315,6 +410,13 @@ "notNull": true, "default": false }, + "is_submissions_open": { + "name": "is_submissions_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, "last_edited_by": { "name": "last_edited_by", "type": "text", @@ -574,11 +676,1555 @@ "foreignKeys": {}, "compositePrimaryKeys": {}, "uniqueConstraints": { - "program_season_slug_unique": { - "name": "program_season_slug_unique", + "program_season_slug_unique": { + "name": "program_season_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_link": { + "name": "referral_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ambassador_id": { + "name": "ambassador_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviewer_pathway": { + "name": "reviewer_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "reviewer_pathway_unique_idx": { + "name": "reviewer_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviewer_pathway_user_id_user_id_fk": { + "name": "reviewer_pathway_user_id_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reviewer_pathway_assigned_by_user_id_fk": { + "name": "reviewer_pathway_assigned_by_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_item": { + "name": "shop_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_image_url": { + "name": "item_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price": { + "name": "item_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_stock": { + "name": "item_stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "source_type": { + "name": "source_type", + "type": "shop_item_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'CUSTOM'" + }, + "linked_warehouse_item_id": { + "name": "linked_warehouse_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "linked_warehouse_template_id": { + "name": "linked_warehouse_template_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_item_pathway_pathway_shop_pathway_fk": { + "name": "shop_item_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_item", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_linked_warehouse_item_id_warehouse_item_id_fk": { + "name": "shop_item_linked_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "shop_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "linked_warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_linked_warehouse_template_id_warehouse_order_template_id_fk": { + "name": "shop_item_linked_warehouse_template_id_warehouse_order_template_id_fk", + "tableFrom": "shop_item", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "linked_warehouse_template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_last_edited_by_user_id_fk": { + "name": "shop_item_last_edited_by_user_id_fk", + "tableFrom": "shop_item", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_orders": { + "name": "shop_orders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "order_status": { + "name": "order_status", + "type": "shop_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "shop_item_id": { + "name": "shop_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price_snapshot": { + "name": "item_price_snapshot", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_name_snapshot": { + "name": "item_name_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shipping_address": { + "name": "shipping_address", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_notes": { + "name": "user_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufiller_notes": { + "name": "fufiller_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_by": { + "name": "fufilled_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_at": { + "name": "fufilled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancelled_reason": { + "name": "cancelled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_orders_user_id_user_id_fk": { + "name": "shop_orders_user_id_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_pathway_pathway_shop_pathway_fk": { + "name": "shop_orders_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_orders", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_orders_shop_item_id_shop_item_id_fk": { + "name": "shop_orders_shop_item_id_shop_item_id_fk", + "tableFrom": "shop_orders", + "tableTo": "shop_item", + "columnsFrom": [ + "shop_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_fufilled_by_user_id_fk": { + "name": "shop_orders_fufilled_by_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "fufilled_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.currency_transactions": { + "name": "currency_transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tx_user_id": { + "name": "tx_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_pathway": { + "name": "tx_pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_amount": { + "name": "tx_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tx_reason": { + "name": "tx_reason", + "type": "currency_txn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_note": { + "name": "tx_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_granted_by": { + "name": "tx_granted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_type": { + "name": "tx_ref_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_id": { + "name": "tx_ref_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "currency_transactions_tx_user_id_user_id_fk": { + "name": "currency_transactions_tx_user_id_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "currency_transactions_tx_pathway_pathway_shop_pathway_fk": { + "name": "currency_transactions_tx_pathway_pathway_shop_pathway_fk", + "tableFrom": "currency_transactions", + "tableTo": "pathway_shop", + "columnsFrom": [ + "tx_pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "currency_transactions_tx_granted_by_user_id_fk": { + "name": "currency_transactions_tx_granted_by_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch": { + "name": "warehouse_batch", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_batch_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'AWAITING_MAPPING'" + }, + "csv_data": { + "name": "csv_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_mapping": { + "name": "field_mapping", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_count": { + "name": "address_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_batch_created_by_id_user_id_fk": { + "name": "warehouse_batch_created_by_id_user_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_batch_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_batch_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch_tag": { + "name": "warehouse_batch_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "warehouse_batch_tag_unique_idx": { + "name": "warehouse_batch_tag_unique_idx", + "columns": [ + { + "expression": "batch_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_batch_tag_batch_id_warehouse_batch_id_fk": { + "name": "warehouse_batch_tag_batch_id_warehouse_batch_id_fk", + "tableFrom": "warehouse_batch_tag", + "tableTo": "warehouse_batch", + "columnsFrom": [ + "batch_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_category": { + "name": "warehouse_category", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_item": { + "name": "warehouse_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "category_id": { + "name": "category_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sku": { + "name": "sku", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sizing": { + "name": "sizing", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "package_type": { + "name": "package_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'box'" + }, + "length_in": { + "name": "length_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "width_in": { + "name": "width_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "height_in": { + "name": "height_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "weight_grams": { + "name": "weight_grams", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "cost_cents": { + "name": "cost_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "hs_code": { + "name": "hs_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_item_category_id_warehouse_category_id_fk": { + "name": "warehouse_item_category_id_warehouse_category_id_fk", + "tableFrom": "warehouse_item", + "tableTo": "warehouse_category", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_item_sku_unique": { + "name": "warehouse_item_sku_unique", + "nullsNotDistinct": false, + "columns": [ + "sku" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order": { + "name": "warehouse_order", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fulfillment_id": { + "name": "fulfillment_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "warehouse_order_fulfillment_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_line_1": { + "name": "address_line_1", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address_line_2": { + "name": "address_line_2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "city": { + "name": "city", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_province": { + "name": "state_province", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "postal_code": { + "name": "postal_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "estimated_shipping_cents": { + "name": "estimated_shipping_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_duties_cents": { + "name": "estimated_duties_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_service_name": { + "name": "estimated_service_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_service_code": { + "name": "estimated_service_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_package_type": { + "name": "estimated_package_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_total_length_in": { + "name": "estimated_total_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_width_in": { + "name": "estimated_total_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_height_in": { + "name": "estimated_total_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_weight_grams": { + "name": "estimated_total_weight_grams", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_category": { + "name": "packaging_category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_label": { + "name": "packaging_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_length_in": { + "name": "packaging_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_width_in": { + "name": "packaging_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_height_in": { + "name": "packaging_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_subject_to_change": { + "name": "packaging_subject_to_change", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "tracking_number": { + "name": "tracking_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "label_url": { + "name": "label_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipping_method": { + "name": "shipping_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_status": { + "name": "billing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "billing_failure_reason": { + "name": "billing_failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_created_by_id_user_id_fk": { + "name": "warehouse_order_created_by_id_user_id_fk", + "tableFrom": "warehouse_order", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_order_fulfillment_id_unique": { + "name": "warehouse_order_fulfillment_id_unique", "nullsNotDistinct": false, "columns": [ - "slug" + "fulfillment_id" ] } }, @@ -586,8 +2232,8 @@ "checkConstraints": {}, "isRLSEnabled": false }, - "public.session": { - "name": "session", + "public.warehouse_order_item": { + "name": "warehouse_order_item", "schema": "", "columns": { "id": { @@ -596,33 +2242,90 @@ "primaryKey": true, "notNull": true }, - "user_id": { - "name": "user_id", + "order_id": { + "name": "order_id", "type": "text", "primaryKey": false, "notNull": true }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", "primaryKey": false, "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "sizing_choice": { + "name": "sizing_choice", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "warehouse_order_item_order_id_idx": { + "name": "warehouse_order_item_order_id_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_item_warehouse_item_id_idx": { + "name": "warehouse_order_item_warehouse_item_id_idx", + "columns": [ + { + "expression": "warehouse_item_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} } }, - "indexes": {}, "foreignKeys": { - "session_user_id_user_id_fk": { - "name": "session_user_id_user_id_fk", - "tableFrom": "session", - "tableTo": "user", + "warehouse_order_item_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_item_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_order", "columnsFrom": [ - "user_id" + "order_id" ], "columnsTo": [ "id" ], "onDelete": "cascade", "onUpdate": "no action" + }, + "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, @@ -631,8 +2334,8 @@ "checkConstraints": {}, "isRLSEnabled": false }, - "public.user": { - "name": "user", + "public.warehouse_order_tag": { + "name": "warehouse_order_tag", "schema": "", "columns": { "id": { @@ -641,58 +2344,116 @@ "primaryKey": true, "notNull": true }, - "email": { - "name": "email", + "order_id": { + "name": "order_id", "type": "text", "primaryKey": false, "notNull": true }, - "hack_club_id": { - "name": "hack_club_id", + "tag": { + "name": "tag", "type": "text", "primaryKey": false, "notNull": true + } + }, + "indexes": { + "warehouse_order_tag_unique_idx": { + "name": "warehouse_order_tag_unique_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} }, - "first_name": { - "name": "first_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_name": { - "name": "last_name", + "warehouse_order_tag_tag_idx": { + "name": "warehouse_order_tag_tag_idx", + "columns": [ + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_order_tag_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_tag_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_tag", + "tableTo": "warehouse_order", + "columnsFrom": [ + "order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order_template": { + "name": "warehouse_order_template", + "schema": "", + "columns": { + "id": { + "name": "id", "type": "text", - "primaryKey": false, - "notNull": false + "primaryKey": true, + "notNull": true }, - "slack_id": { - "name": "slack_id", + "created_by_id": { + "name": "created_by_id", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true }, - "verification_status": { - "name": "verification_status", + "name": { + "name": "name", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true }, - "ysws_eligible": { - "name": "ysws_eligible", + "is_public": { + "name": "is_public", "type": "boolean", "primaryKey": false, "notNull": true, "default": false }, - "is_admin": { - "name": "is_admin", - "type": "boolean", + "created_at": { + "name": "created_at", + "type": "timestamp", "primaryKey": false, "notNull": true, - "default": false + "default": "now()" }, - "created_at": { - "name": "created_at", + "updated_at": { + "name": "updated_at", "type": "timestamp", "primaryKey": false, "notNull": true, @@ -700,30 +2461,29 @@ } }, "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - }, - "user_hack_club_id_unique": { - "name": "user_hack_club_id_unique", - "nullsNotDistinct": false, - "columns": [ - "hack_club_id" - ] + "foreignKeys": { + "warehouse_order_template_created_by_id_user_id_fk": { + "name": "warehouse_order_template_created_by_id_user_id_fk", + "tableFrom": "warehouse_order_template", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" } }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, "policies": {}, "checkConstraints": {}, "isRLSEnabled": false }, - "public.user_pathway": { - "name": "user_pathway", + "public.warehouse_order_template_item": { + "name": "warehouse_order_template_item", "schema": "", "columns": { "id": { @@ -732,63 +2492,53 @@ "primaryKey": true, "notNull": true }, - "user_id": { - "name": "user_id", + "template_id": { + "name": "template_id", "type": "text", "primaryKey": false, "notNull": true }, - "pathway": { - "name": "pathway", - "type": "pathway", - "typeSchema": "public", + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", "primaryKey": false, "notNull": true }, - "created_at": { - "name": "created_at", - "type": "timestamp", + "quantity": { + "name": "quantity", + "type": "integer", "primaryKey": false, "notNull": true, - "default": "now()" - } - }, - "indexes": { - "user_pathway_unique_idx": { - "name": "user_pathway_unique_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "pathway", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} + "default": 1 } }, + "indexes": {}, "foreignKeys": { - "user_pathway_user_id_user_id_fk": { - "name": "user_pathway_user_id_user_id_fk", - "tableFrom": "user_pathway", - "tableTo": "user", + "warehouse_order_template_item_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_order_template_item_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_order_template", "columnsFrom": [ - "user_id" + "template_id" ], "columnsTo": [ "id" ], "onDelete": "cascade", "onUpdate": "no action" + }, + "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, @@ -1272,6 +3022,17 @@ } }, "enums": { + "public.currency_txn_reason": { + "name": "currency_txn_reason", + "schema": "public", + "values": [ + "GRANT", + "PURCHASE", + "REFUND", + "ADJUSTMENT", + "OTHER" + ] + }, "public.difficulty": { "name": "difficulty", "schema": "public", @@ -1303,7 +3064,7 @@ "schema": "public", "values": [ "PYTHON", - "WEB_DEV", + "RUST", "GAME_DEV", "HARDWARE", "DESIGN", @@ -1329,6 +3090,45 @@ "SHIPPED", "MISSED" ] + }, + "public.shop_item_source": { + "name": "shop_item_source", + "schema": "public", + "values": [ + "CUSTOM", + "WAREHOUSE_ITEM", + "WAREHOUSE_TEMPLATE" + ] + }, + "public.shop_order_status": { + "name": "shop_order_status", + "schema": "public", + "values": [ + "PENDING", + "PROCESSING", + "FULFILLED", + "CANCELED" + ] + }, + "public.warehouse_batch_status": { + "name": "warehouse_batch_status", + "schema": "public", + "values": [ + "AWAITING_MAPPING", + "MAPPED", + "PROCESSED" + ] + }, + "public.warehouse_order_status": { + "name": "warehouse_order_status", + "schema": "public", + "values": [ + "DRAFT", + "ESTIMATED", + "APPROVED", + "SHIPPED", + "CANCELLED" + ] } }, "schemas": {}, diff --git a/resolution-frontend/drizzle/meta/0001_snapshot.json b/resolution-frontend/drizzle/meta/0001_snapshot.json index 7776dba..ad799f3 100644 --- a/resolution-frontend/drizzle/meta/0001_snapshot.json +++ b/resolution-frontend/drizzle/meta/0001_snapshot.json @@ -1,6 +1,6 @@ { - "id": "becd34cd-7692-4ef3-a912-458e58e190ad", - "prevId": "ee4874ac-fef8-4ca8-ab84-17f57639d40b", + "id": "c85863ec-bd59-4e37-bd13-da29f490bb62", + "prevId": "04f6d62e-e75a-447d-9462-ec816fc41e19", "version": "7", "dialect": "postgresql", "tables": { @@ -271,6 +271,95 @@ "checkConstraints": {}, "isRLSEnabled": false }, + "public.pathway_shop": { + "name": "pathway_shop", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "is_enabled": { + "name": "is_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "currency_name": { + "name": "currency_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wish'" + }, + "currency_name_plural": { + "name": "currency_name_plural", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'wishes'" + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "pathway_shop_last_edited_by_user_id_fk": { + "name": "pathway_shop_last_edited_by_user_id_fk", + "tableFrom": "pathway_shop", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "pathway_shop_pathway_unique": { + "name": "pathway_shop_pathway_unique", + "nullsNotDistinct": false, + "columns": [ + "pathway" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, "public.pathway_week_content": { "name": "pathway_week_content", "schema": "", @@ -308,6 +397,12 @@ "notNull": true, "default": "''" }, + "prize_image_url": { + "name": "prize_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, "is_published": { "name": "is_published", "type": "boolean", @@ -315,6 +410,13 @@ "notNull": true, "default": false }, + "is_submissions_open": { + "name": "is_submissions_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, "last_edited_by": { "name": "last_edited_by", "type": "text", @@ -638,27 +740,1516 @@ }, "indexes": {}, "foreignKeys": { - "referral_link_ambassador_id_user_id_fk": { - "name": "referral_link_ambassador_id_user_id_fk", - "tableFrom": "referral_link", + "referral_link_ambassador_id_user_id_fk": { + "name": "referral_link_ambassador_id_user_id_fk", + "tableFrom": "referral_link", + "tableTo": "user", + "columnsFrom": [ + "ambassador_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "referral_link_code_unique": { + "name": "referral_link_code_unique", + "nullsNotDistinct": false, + "columns": [ + "code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.referral_signup": { + "name": "referral_signup", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "referral_link_id": { + "name": "referral_link_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "referral_signup_unique_idx": { + "name": "referral_signup_unique_idx", + "columns": [ + { + "expression": "referral_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "referral_signup_referral_link_id_referral_link_id_fk": { + "name": "referral_signup_referral_link_id_referral_link_id_fk", + "tableFrom": "referral_signup", + "tableTo": "referral_link", + "columnsFrom": [ + "referral_link_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "referral_signup_user_id_user_id_fk": { + "name": "referral_signup_user_id_user_id_fk", + "tableFrom": "referral_signup", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviewer_pathway": { + "name": "reviewer_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "assigned_by": { + "name": "assigned_by", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "reviewer_pathway_unique_idx": { + "name": "reviewer_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviewer_pathway_user_id_user_id_fk": { + "name": "reviewer_pathway_user_id_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reviewer_pathway_assigned_by_user_id_fk": { + "name": "reviewer_pathway_assigned_by_user_id_fk", + "tableFrom": "reviewer_pathway", + "tableTo": "user", + "columnsFrom": [ + "assigned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_item": { + "name": "shop_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_image_url": { + "name": "item_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price": { + "name": "item_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_stock": { + "name": "item_stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "source_type": { + "name": "source_type", + "type": "shop_item_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'CUSTOM'" + }, + "linked_warehouse_item_id": { + "name": "linked_warehouse_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "linked_warehouse_template_id": { + "name": "linked_warehouse_template_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_edited_by": { + "name": "last_edited_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_item_pathway_pathway_shop_pathway_fk": { + "name": "shop_item_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_item", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_linked_warehouse_item_id_warehouse_item_id_fk": { + "name": "shop_item_linked_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "shop_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "linked_warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_linked_warehouse_template_id_warehouse_order_template_id_fk": { + "name": "shop_item_linked_warehouse_template_id_warehouse_order_template_id_fk", + "tableFrom": "shop_item", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "linked_warehouse_template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_item_last_edited_by_user_id_fk": { + "name": "shop_item_last_edited_by_user_id_fk", + "tableFrom": "shop_item", + "tableTo": "user", + "columnsFrom": [ + "last_edited_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shop_orders": { + "name": "shop_orders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "order_status": { + "name": "order_status", + "type": "shop_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "shop_item_id": { + "name": "shop_item_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "item_price_snapshot": { + "name": "item_price_snapshot", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "item_name_snapshot": { + "name": "item_name_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shipping_address": { + "name": "shipping_address", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_notes": { + "name": "user_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufiller_notes": { + "name": "fufiller_notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_by": { + "name": "fufilled_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fufilled_at": { + "name": "fufilled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "tracking_number": { + "name": "tracking_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancelled_reason": { + "name": "cancelled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "shop_orders_user_id_user_id_fk": { + "name": "shop_orders_user_id_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_pathway_pathway_shop_pathway_fk": { + "name": "shop_orders_pathway_pathway_shop_pathway_fk", + "tableFrom": "shop_orders", + "tableTo": "pathway_shop", + "columnsFrom": [ + "pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shop_orders_shop_item_id_shop_item_id_fk": { + "name": "shop_orders_shop_item_id_shop_item_id_fk", + "tableFrom": "shop_orders", + "tableTo": "shop_item", + "columnsFrom": [ + "shop_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "shop_orders_fufilled_by_user_id_fk": { + "name": "shop_orders_fufilled_by_user_id_fk", + "tableFrom": "shop_orders", + "tableTo": "user", + "columnsFrom": [ + "fufilled_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.currency_transactions": { + "name": "currency_transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tx_user_id": { + "name": "tx_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_pathway": { + "name": "tx_pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_amount": { + "name": "tx_amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tx_reason": { + "name": "tx_reason", + "type": "currency_txn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "tx_note": { + "name": "tx_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_granted_by": { + "name": "tx_granted_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_type": { + "name": "tx_ref_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tx_ref_id": { + "name": "tx_ref_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "currency_transactions_tx_user_id_user_id_fk": { + "name": "currency_transactions_tx_user_id_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "currency_transactions_tx_pathway_pathway_shop_pathway_fk": { + "name": "currency_transactions_tx_pathway_pathway_shop_pathway_fk", + "tableFrom": "currency_transactions", + "tableTo": "pathway_shop", + "columnsFrom": [ + "tx_pathway" + ], + "columnsTo": [ + "pathway" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "currency_transactions_tx_granted_by_user_id_fk": { + "name": "currency_transactions_tx_granted_by_user_id_fk", + "tableFrom": "currency_transactions", + "tableTo": "user", + "columnsFrom": [ + "tx_granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hack_club_id": { + "name": "hack_club_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slack_id": { + "name": "slack_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verification_status": { + "name": "verification_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ysws_eligible": { + "name": "ysws_eligible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_hack_club_id_unique": { + "name": "user_hack_club_id_unique", + "nullsNotDistinct": false, + "columns": [ + "hack_club_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_pathway": { + "name": "user_pathway", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pathway": { + "name": "pathway", + "type": "pathway", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_pathway_unique_idx": { + "name": "user_pathway_unique_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "pathway", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_pathway_user_id_user_id_fk": { + "name": "user_pathway_user_id_user_id_fk", + "tableFrom": "user_pathway", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch": { + "name": "warehouse_batch", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_batch_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'AWAITING_MAPPING'" + }, + "csv_data": { + "name": "csv_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_mapping": { + "name": "field_mapping", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_count": { + "name": "address_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_batch_created_by_id_user_id_fk": { + "name": "warehouse_batch_created_by_id_user_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "warehouse_batch_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_batch_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_batch", + "tableTo": "warehouse_order_template", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_batch_tag": { + "name": "warehouse_batch_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "warehouse_batch_tag_unique_idx": { + "name": "warehouse_batch_tag_unique_idx", + "columns": [ + { + "expression": "batch_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "warehouse_batch_tag_batch_id_warehouse_batch_id_fk": { + "name": "warehouse_batch_tag_batch_id_warehouse_batch_id_fk", + "tableFrom": "warehouse_batch_tag", + "tableTo": "warehouse_batch", + "columnsFrom": [ + "batch_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_category": { + "name": "warehouse_category", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_item": { + "name": "warehouse_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "category_id": { + "name": "category_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sku": { + "name": "sku", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sizing": { + "name": "sizing", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "package_type": { + "name": "package_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'box'" + }, + "length_in": { + "name": "length_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "width_in": { + "name": "width_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "height_in": { + "name": "height_in", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "weight_grams": { + "name": "weight_grams", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "cost_cents": { + "name": "cost_cents", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "hs_code": { + "name": "hs_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_item_category_id_warehouse_category_id_fk": { + "name": "warehouse_item_category_id_warehouse_category_id_fk", + "tableFrom": "warehouse_item", + "tableTo": "warehouse_category", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "warehouse_item_sku_unique": { + "name": "warehouse_item_sku_unique", + "nullsNotDistinct": false, + "columns": [ + "sku" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.warehouse_order": { + "name": "warehouse_order", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "fulfillment_id": { + "name": "fulfillment_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "identity": { + "type": "always", + "name": "warehouse_order_fulfillment_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "created_by_id": { + "name": "created_by_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "shop_order_id": { + "name": "shop_order_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "batch_id": { + "name": "batch_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "warehouse_order_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'DRAFT'" + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "address_line_1": { + "name": "address_line_1", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address_line_2": { + "name": "address_line_2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "city": { + "name": "city", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_province": { + "name": "state_province", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "postal_code": { + "name": "postal_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "estimated_shipping_cents": { + "name": "estimated_shipping_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_duties_cents": { + "name": "estimated_duties_cents", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "estimated_service_name": { + "name": "estimated_service_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_service_code": { + "name": "estimated_service_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_package_type": { + "name": "estimated_package_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "estimated_total_length_in": { + "name": "estimated_total_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_width_in": { + "name": "estimated_total_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_height_in": { + "name": "estimated_total_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "estimated_total_weight_grams": { + "name": "estimated_total_weight_grams", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_category": { + "name": "packaging_category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_label": { + "name": "packaging_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "packaging_length_in": { + "name": "packaging_length_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_width_in": { + "name": "packaging_width_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_height_in": { + "name": "packaging_height_in", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "packaging_subject_to_change": { + "name": "packaging_subject_to_change", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "tracking_number": { + "name": "tracking_number", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "label_url": { + "name": "label_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shipping_method": { + "name": "shipping_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "billing_status": { + "name": "billing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'PENDING'" + }, + "billing_failure_reason": { + "name": "billing_failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "warehouse_order_created_by_id_user_id_fk": { + "name": "warehouse_order_created_by_id_user_id_fk", + "tableFrom": "warehouse_order", "tableTo": "user", "columnsFrom": [ - "ambassador_id" + "created_by_id" ], "columnsTo": [ "id" ], "onDelete": "cascade", "onUpdate": "no action" + }, + "warehouse_order_shop_order_id_shop_orders_id_fk": { + "name": "warehouse_order_shop_order_id_shop_orders_id_fk", + "tableFrom": "warehouse_order", + "tableTo": "shop_orders", + "columnsFrom": [ + "shop_order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, "uniqueConstraints": { - "referral_link_code_unique": { - "name": "referral_link_code_unique", + "warehouse_order_fulfillment_id_unique": { + "name": "warehouse_order_fulfillment_id_unique", "nullsNotDistinct": false, "columns": [ - "code" + "fulfillment_id" ] } }, @@ -666,8 +2257,8 @@ "checkConstraints": {}, "isRLSEnabled": false }, - "public.referral_signup": { - "name": "referral_signup", + "public.warehouse_order_item": { + "name": "warehouse_order_item", "schema": "", "columns": { "id": { @@ -676,56 +2267,71 @@ "primaryKey": true, "notNull": true }, - "referral_link_id": { - "name": "referral_link_id", + "order_id": { + "name": "order_id", "type": "text", "primaryKey": false, "notNull": true }, - "user_id": { - "name": "user_id", + "warehouse_item_id": { + "name": "warehouse_item_id", "type": "text", "primaryKey": false, "notNull": true }, - "created_at": { - "name": "created_at", - "type": "timestamp", + "quantity": { + "name": "quantity", + "type": "integer", "primaryKey": false, "notNull": true, - "default": "now()" + "default": 1 + }, + "sizing_choice": { + "name": "sizing_choice", + "type": "text", + "primaryKey": false, + "notNull": false } }, "indexes": { - "referral_signup_unique_idx": { - "name": "referral_signup_unique_idx", + "warehouse_order_item_order_id_idx": { + "name": "warehouse_order_item_order_id_idx", "columns": [ { - "expression": "referral_link_id", + "expression": "order_id", "isExpression": false, "asc": true, "nulls": "last" - }, + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_item_warehouse_item_id_idx": { + "name": "warehouse_order_item_warehouse_item_id_idx", + "columns": [ { - "expression": "user_id", + "expression": "warehouse_item_id", "isExpression": false, "asc": true, "nulls": "last" } ], - "isUnique": true, + "isUnique": false, "concurrently": false, "method": "btree", "with": {} } }, "foreignKeys": { - "referral_signup_referral_link_id_referral_link_id_fk": { - "name": "referral_signup_referral_link_id_referral_link_id_fk", - "tableFrom": "referral_signup", - "tableTo": "referral_link", + "warehouse_order_item_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_item_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_order", "columnsFrom": [ - "referral_link_id" + "order_id" ], "columnsTo": [ "id" @@ -733,17 +2339,17 @@ "onDelete": "cascade", "onUpdate": "no action" }, - "referral_signup_user_id_user_id_fk": { - "name": "referral_signup_user_id_user_id_fk", - "tableFrom": "referral_signup", - "tableTo": "user", + "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_item", + "tableTo": "warehouse_item", "columnsFrom": [ - "user_id" + "warehouse_item_id" ], "columnsTo": [ "id" ], - "onDelete": "cascade", + "onDelete": "restrict", "onUpdate": "no action" } }, @@ -753,8 +2359,8 @@ "checkConstraints": {}, "isRLSEnabled": false }, - "public.session": { - "name": "session", + "public.warehouse_order_tag": { + "name": "warehouse_order_tag", "schema": "", "columns": { "id": { @@ -763,27 +2369,64 @@ "primaryKey": true, "notNull": true }, - "user_id": { - "name": "user_id", + "order_id": { + "name": "order_id", "type": "text", "primaryKey": false, "notNull": true }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", + "tag": { + "name": "tag", + "type": "text", "primaryKey": false, "notNull": true } }, - "indexes": {}, + "indexes": { + "warehouse_order_tag_unique_idx": { + "name": "warehouse_order_tag_unique_idx", + "columns": [ + { + "expression": "order_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "warehouse_order_tag_tag_idx": { + "name": "warehouse_order_tag_tag_idx", + "columns": [ + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, "foreignKeys": { - "session_user_id_user_id_fk": { - "name": "session_user_id_user_id_fk", - "tableFrom": "session", - "tableTo": "user", + "warehouse_order_tag_order_id_warehouse_order_id_fk": { + "name": "warehouse_order_tag_order_id_warehouse_order_id_fk", + "tableFrom": "warehouse_order_tag", + "tableTo": "warehouse_order", "columnsFrom": [ - "user_id" + "order_id" ], "columnsTo": [ "id" @@ -798,8 +2441,8 @@ "checkConstraints": {}, "isRLSEnabled": false }, - "public.user": { - "name": "user", + "public.warehouse_order_template": { + "name": "warehouse_order_template", "schema": "", "columns": { "id": { @@ -808,58 +2451,34 @@ "primaryKey": true, "notNull": true }, - "email": { - "name": "email", + "created_by_id": { + "name": "created_by_id", "type": "text", "primaryKey": false, "notNull": true }, - "hack_club_id": { - "name": "hack_club_id", + "name": { + "name": "name", "type": "text", "primaryKey": false, "notNull": true }, - "first_name": { - "name": "first_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_name": { - "name": "last_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slack_id": { - "name": "slack_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "verification_status": { - "name": "verification_status", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ysws_eligible": { - "name": "ysws_eligible", + "is_public": { + "name": "is_public", "type": "boolean", "primaryKey": false, "notNull": true, "default": false }, - "is_admin": { - "name": "is_admin", - "type": "boolean", + "created_at": { + "name": "created_at", + "type": "timestamp", "primaryKey": false, "notNull": true, - "default": false + "default": "now()" }, - "created_at": { - "name": "created_at", + "updated_at": { + "name": "updated_at", "type": "timestamp", "primaryKey": false, "notNull": true, @@ -867,30 +2486,29 @@ } }, "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_email_unique": { - "name": "user_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - }, - "user_hack_club_id_unique": { - "name": "user_hack_club_id_unique", - "nullsNotDistinct": false, - "columns": [ - "hack_club_id" - ] + "foreignKeys": { + "warehouse_order_template_created_by_id_user_id_fk": { + "name": "warehouse_order_template_created_by_id_user_id_fk", + "tableFrom": "warehouse_order_template", + "tableTo": "user", + "columnsFrom": [ + "created_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" } }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, "policies": {}, "checkConstraints": {}, "isRLSEnabled": false }, - "public.user_pathway": { - "name": "user_pathway", + "public.warehouse_order_template_item": { + "name": "warehouse_order_template_item", "schema": "", "columns": { "id": { @@ -899,63 +2517,53 @@ "primaryKey": true, "notNull": true }, - "user_id": { - "name": "user_id", + "template_id": { + "name": "template_id", "type": "text", "primaryKey": false, "notNull": true }, - "pathway": { - "name": "pathway", - "type": "pathway", - "typeSchema": "public", + "warehouse_item_id": { + "name": "warehouse_item_id", + "type": "text", "primaryKey": false, "notNull": true }, - "created_at": { - "name": "created_at", - "type": "timestamp", + "quantity": { + "name": "quantity", + "type": "integer", "primaryKey": false, "notNull": true, - "default": "now()" - } - }, - "indexes": { - "user_pathway_unique_idx": { - "name": "user_pathway_unique_idx", - "columns": [ - { - "expression": "user_id", - "isExpression": false, - "asc": true, - "nulls": "last" - }, - { - "expression": "pathway", - "isExpression": false, - "asc": true, - "nulls": "last" - } - ], - "isUnique": true, - "concurrently": false, - "method": "btree", - "with": {} + "default": 1 } }, + "indexes": {}, "foreignKeys": { - "user_pathway_user_id_user_id_fk": { - "name": "user_pathway_user_id_user_id_fk", - "tableFrom": "user_pathway", - "tableTo": "user", + "warehouse_order_template_item_template_id_warehouse_order_template_id_fk": { + "name": "warehouse_order_template_item_template_id_warehouse_order_template_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_order_template", "columnsFrom": [ - "user_id" + "template_id" ], "columnsTo": [ "id" ], "onDelete": "cascade", "onUpdate": "no action" + }, + "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk": { + "name": "warehouse_order_template_item_warehouse_item_id_warehouse_item_id_fk", + "tableFrom": "warehouse_order_template_item", + "tableTo": "warehouse_item", + "columnsFrom": [ + "warehouse_item_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, @@ -1439,6 +3047,17 @@ } }, "enums": { + "public.currency_txn_reason": { + "name": "currency_txn_reason", + "schema": "public", + "values": [ + "GRANT", + "PURCHASE", + "REFUND", + "ADJUSTMENT", + "OTHER" + ] + }, "public.difficulty": { "name": "difficulty", "schema": "public", @@ -1470,7 +3089,7 @@ "schema": "public", "values": [ "PYTHON", - "WEB_DEV", + "RUST", "GAME_DEV", "HARDWARE", "DESIGN", @@ -1496,6 +3115,46 @@ "SHIPPED", "MISSED" ] + }, + "public.shop_item_source": { + "name": "shop_item_source", + "schema": "public", + "values": [ + "CUSTOM", + "WAREHOUSE_ITEM", + "WAREHOUSE_TEMPLATE" + ] + }, + "public.shop_order_status": { + "name": "shop_order_status", + "schema": "public", + "values": [ + "PENDING", + "PROCESSING", + "FULFILLED", + "CANCELED", + "REJECTED" + ] + }, + "public.warehouse_batch_status": { + "name": "warehouse_batch_status", + "schema": "public", + "values": [ + "AWAITING_MAPPING", + "MAPPED", + "PROCESSED" + ] + }, + "public.warehouse_order_status": { + "name": "warehouse_order_status", + "schema": "public", + "values": [ + "DRAFT", + "ESTIMATED", + "APPROVED", + "SHIPPED", + "CANCELLED" + ] } }, "schemas": {}, diff --git a/resolution-frontend/drizzle/meta/_journal.json b/resolution-frontend/drizzle/meta/_journal.json index 66c0660..4004dd0 100644 --- a/resolution-frontend/drizzle/meta/_journal.json +++ b/resolution-frontend/drizzle/meta/_journal.json @@ -5,79 +5,16 @@ { "idx": 0, "version": "7", - "when": 1770227074880, - "tag": "0000_curly_raza", + "when": 1778903874976, + "tag": "0000_redundant_gamora", "breakpoints": true }, { "idx": 1, "version": "7", - "when": 1771512581182, - "tag": "0001_burly_caretaker", - "breakpoints": true - }, - { - "idx": 2, - "version": "7", - "when": 1772636037511, - "tag": "0002_luxuriant_maria_hill", - "breakpoints": true - }, - { - "idx": 3, - "version": "7", - "when": 1775185421664, - "tag": "0003_misty_week_prize_image", - "breakpoints": true - }, - { - "idx": 4, - "version": "7", - "when": 1776130671597, - "tag": "0004_left_pretty_boy", - "breakpoints": true - }, - { - "idx": 5, - "version": "7", - "when": 1776500000000, - "tag": "0005_add_package_type_and_orders", - "breakpoints": true - }, - { - "idx": 6, - "version": "7", - "when": 1776600000000, - "tag": "0006_add_templates_and_batches", - "breakpoints": true - }, - { - "idx": 7, - "version": "7", - "when": 1776700000000, - "tag": "0007_add_label_tracking_fields", - "breakpoints": true - }, - { - "idx": 8, - "version": "7", - "when": 1776800000000, - "tag": "0008_add_hs_code", - "breakpoints": true - }, - { - "idx": 9, - "version": "7", - "when": 1776900000000, - "tag": "0009_add_packaging_columns", - "breakpoints": true - }, - { - "idx": 10, - "version": "7", - "when": 1777000000000, - "tag": "0010_warehouse_indexes_and_tags", + "when": 1778950267393, + "tag": "0001_sloppy_namora", "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/resolution-frontend/src/hooks.server.test.ts b/resolution-frontend/src/hooks.server.test.ts index 40d7756..1672ec6 100644 --- a/resolution-frontend/src/hooks.server.test.ts +++ b/resolution-frontend/src/hooks.server.test.ts @@ -17,6 +17,10 @@ vi.mock('$lib/server/season', () => ({ ensureSeasonFromEnv: () => Promise.resolve() })); +vi.mock('$lib/server/devSeed', () => ({ + seedDevShops: () => Promise.resolve() +})); + const { handle } = await import('./hooks.server'); function createMockEvent() { diff --git a/resolution-frontend/src/hooks.server.ts b/resolution-frontend/src/hooks.server.ts index 375a540..2a963a0 100644 --- a/resolution-frontend/src/hooks.server.ts +++ b/resolution-frontend/src/hooks.server.ts @@ -1,10 +1,14 @@ import { lucia } from '$lib/server/auth'; import type { Handle } from '@sveltejs/kit'; import { ensureSeasonFromEnv } from '$lib/server/season'; +import { seedDevShops } from '$lib/server/devSeed'; // Sync season from env on startup ensureSeasonFromEnv().catch(console.error); +// Seed pathway shops + a starter item per pathway when running in dev +seedDevShops().catch(console.error); + export const handle: Handle = async ({ event, resolve }) => { const sessionId = event.cookies.get(lucia.sessionCookieName); diff --git a/resolution-frontend/src/lib/server/db/schema.ts b/resolution-frontend/src/lib/server/db/schema.ts index 499ff96..9f702c3 100644 --- a/resolution-frontend/src/lib/server/db/schema.ts +++ b/resolution-frontend/src/lib/server/db/schema.ts @@ -1,6 +1,7 @@ -import { pgTable, text, timestamp, boolean, integer, real, pgEnum, uniqueIndex, index } from 'drizzle-orm/pg-core'; +import { pgTable, text, timestamp, boolean, integer, real, pgEnum, uniqueIndex, index, jsonb } from 'drizzle-orm/pg-core'; import { relations } from 'drizzle-orm'; import { createId } from '@paralleldrive/cuid2'; +import type { AddressInput } from '../validation'; // Enums export const enrollmentRoleEnum = pgEnum('enrollment_role', ['PARTICIPANT', 'AMBASSADOR']); @@ -11,6 +12,9 @@ export const shipStatusEnum = pgEnum('ship_status', ['PLANNED', 'IN_PROGRESS', ' export const payoutStatusEnum = pgEnum('payout_status', ['DRAFT', 'PENDING', 'PAID', 'CANCELED']); export const warehouseOrderStatusEnum = pgEnum('warehouse_order_status', ['DRAFT', 'ESTIMATED', 'APPROVED', 'SHIPPED', 'CANCELLED']); export const warehouseBatchStatusEnum = pgEnum('warehouse_batch_status', ['AWAITING_MAPPING', 'MAPPED', 'PROCESSED']); +export const shopOrderStatusEnum = pgEnum('shop_order_status', ['PENDING', 'PROCESSING', 'FULFILLED', 'CANCELED', 'REJECTED']); // order tracking for frontend (users) +export const shopItemSourceEnum = pgEnum('shop_item_source', ['CUSTOM', 'WAREHOUSE_ITEM', 'WAREHOUSE_TEMPLATE']); // discriminator: where the item's fulfillment data comes from +export const currencyTxnReasonEnum = pgEnum('currency_txn_reason', ['GRANT', 'PURCHASE', 'REFUND', 'ADJUSTMENT', 'OTHER']); // logging why transaction occured // Tables export const user = pgTable('user', { @@ -141,6 +145,74 @@ export const userPathway = pgTable('user_pathway', { uniqueIndex('user_pathway_unique_idx').on(table.userId, table.pathway) ]); +export const pathwayShop = pgTable('pathway_shop', { + id: text('id').primaryKey().$defaultFn(() => createId()), + pathway: pathwayEnum('pathway').notNull().unique(), + isEnabled: boolean('is_enabled').notNull().default(false), // default to not displaying unless ambassador flips switch + currencyName: text('currency_name').notNull().default('wish'), // bcs. idk. resolution = a wish or something idk + currencyNamePlural: text('currency_name_plural').notNull().default('wishes'), + lastEditedBy: text('last_edited_by').references(() => user.id), + createdAt: timestamp('created_at', { mode: 'date' }).notNull().defaultNow(), + updatedAt: timestamp('updated_at', { mode: 'date' }).notNull().defaultNow().$onUpdate(() => new Date()) +}); + +export const shopItem = pgTable('shop_item', { + id: text('id').primaryKey().$defaultFn(() => createId()), + pathway: pathwayEnum('pathway').notNull().references(() => pathwayShop.pathway, { onDelete: 'cascade' }), + name: text('name').notNull(), + description: text('description').notNull(), + itemImageUrl: text('item_image_url'), + price: integer('item_price').notNull(), + // stock is nullable β€” null means unlimited stock + stock: integer('item_stock'), + isActive: boolean('is_active').notNull().default(false), + sourceType: shopItemSourceEnum('source_type').notNull().default('CUSTOM'), + linkedWarehouseItemId: text('linked_warehouse_item_id').references(() => warehouseItem.id, { onDelete: 'cascade' }), // TODO: ADD WARNING WHEN DELETING WAREHOUSE ITEM OR TEMPLATE + linkedWarehouseTemplateId: text('linked_warehouse_template_id').references(() => warehouseOrderTemplate.id, { onDelete: 'cascade' }), + lastEditedBy: text('last_edited_by').references(() => user.id), + createdAt: timestamp('created_at', { mode: 'date' }).notNull().defaultNow(), + updatedAt: timestamp('updated_at', { mode: 'date' }).notNull().defaultNow().$onUpdate(() => new Date()) +}); + +export const transactionLedger = pgTable('currency_transactions', { + id: text('id').primaryKey().$defaultFn(() => createId()), + userId: text('tx_user_id').references(() => user.id, { onDelete: 'set null' }), + pathway: pathwayEnum('tx_pathway').notNull().references(() => pathwayShop.pathway, { onDelete: 'cascade' }), + amount: integer('tx_amount').notNull(), + reason: currencyTxnReasonEnum('tx_reason').notNull(), + note: text('tx_note'), + grantedBy: text('tx_granted_by').references(() => user.id, { onDelete: 'set null' }), + refType: text('tx_ref_type'), // SHOP, SHIP, etc. + refId: text('tx_ref_id'), // ID, such as for shop order + createdAt: timestamp('created_at', { mode: 'date' }).notNull().defaultNow() +}); + +//TODO: evalute if this should have the shipping address encrypted +export const shopOrder = pgTable('shop_orders', { + id: text('id').primaryKey().$defaultFn(() => createId()), + userId: text('user_id').references(() => user.id, { onDelete: 'set null' }), + pathway: pathwayEnum('pathway').notNull().references(() => pathwayShop.pathway, { onDelete: 'cascade' }), + status: shopOrderStatusEnum('order_status').notNull().default("PENDING"), + totalAmount: integer('amount').notNull(), + item: text('shop_item_id').references(() => shopItem.id, { onDelete: 'set null' }), + itemPriceSnapshot: integer('item_price_snapshot').notNull(), + itemNameSnapshot: text('item_name_snapshot').notNull(), + shippingAddress: jsonb('shipping_address').$type(), + phone: text('phone'), + userNotes: text('user_notes'), + fufillerNotes: text('fufiller_notes'), + // claimedBy: + fufilledBy: text('fufilled_by').references(() => user.id, { onDelete: 'set null' }), + fufilledAt: timestamp('fufilled_at', { mode: 'date' }), + // Populated by the warehouse fulfillment flow when a label is created. + // Mirrors warehouseOrder.trackingNumber so the participant can see it on + // their order without needing access to the warehouse tables. + trackingNumber: text('tracking_number'), + cancelledReason: text('cancelled_reason'), + createdAt: timestamp('created_at', { mode: 'date' }).notNull().defaultNow(), + updatedAt: timestamp('updated_at', { mode: 'date' }).notNull().defaultNow().$onUpdate(() => new Date()), +}) + // Relations export const userRelations = relations(user, ({ many }) => ({ pathways: many(userPathway), @@ -152,8 +224,10 @@ export const userRelations = relations(user, ({ many }) => ({ payouts: many(ambassadorPayout), referralLinks: many(referralLink), warehouseOrders: many(warehouseOrder), - reviewerAssignments: many(reviewerPathway) - })); + reviewerAssignments: many(reviewerPathway), + currencyTransactions: many(transactionLedger), + shopOrders: many(shopOrder) +})); export const sessionRelations = relations(session, ({ one }) => ({ user: one(user, { fields: [session.userId], references: [user.id] }) @@ -329,6 +403,12 @@ export const warehouseOrder = pgTable('warehouse_order', { id: text('id').primaryKey().$defaultFn(() => createId()), fulfillmentId: integer('fulfillment_id').generatedAlwaysAsIdentity().unique(), createdById: text('created_by_id').notNull().references(() => user.id, { onDelete: 'cascade' }), + // Back reference to the originating shop order, set when a warehouse + // order is created via the shop fufill flow. Null for warehouse orders + // created directly (admin or ambassador swag). On shipping success the + // fulfillment endpoint flips the linked shop order to FULFILLED and + // copies trackingNumber across so the participant can see it. + shopOrderId: text('shop_order_id').references(() => shopOrder.id, { onDelete: 'set null' }), batchId: text('batch_id'), status: warehouseOrderStatusEnum('status').notNull().default('DRAFT'), firstName: text('first_name').notNull(), @@ -398,6 +478,7 @@ export const warehouseOrderTag = pgTable('warehouse_order_tag', { export const warehouseOrderRelations = relations(warehouseOrder, ({ one, many }) => ({ createdBy: one(user, { fields: [warehouseOrder.createdById], references: [user.id] }), + shopOrder: one(shopOrder, { fields: [warehouseOrder.shopOrderId], references: [shopOrder.id] }), items: many(warehouseOrderItem), tags: many(warehouseOrderTag) })); @@ -478,3 +559,31 @@ export const warehouseBatchTagRelations = relations(warehouseBatchTag, ({ one }) batch: one(warehouseBatch, { fields: [warehouseBatchTag.batchId], references: [warehouseBatch.id] }) })); +export const pathwayShopRelations = relations(pathwayShop, ({ one, many }) => ({ + editor: one(user, { fields: [pathwayShop.lastEditedBy], references: [user.id] }), + items: many(shopItem), + transactions: many(transactionLedger), + orders: many(shopOrder) +})); + +export const shopItemRelations = relations(shopItem, ({ one, many }) => ({ + shop: one(pathwayShop, { fields: [shopItem.pathway], references: [pathwayShop.pathway] }), + editor: one(user, { fields: [shopItem.lastEditedBy], references: [user.id] }), + orders: many(shopOrder) +})); + +export const transactionLedgerRelations = relations(transactionLedger, ({ one }) => ({ + user: one(user, { fields: [transactionLedger.userId], references: [user.id] }), + grantedByUser: one(user, { fields: [transactionLedger.grantedBy], references: [user.id] }), + shop: one(pathwayShop, { fields: [transactionLedger.pathway], references: [pathwayShop.pathway] }) +})); + +export const shopOrderRelations = relations(shopOrder, ({ one }) => ({ + user: one(user, { fields: [shopOrder.userId], references: [user.id] }), + shop: one(pathwayShop, { fields: [shopOrder.pathway], references: [pathwayShop.pathway] }), + item: one(shopItem, { fields: [shopOrder.item], references: [shopItem.id] }), + fufiller: one(user, { fields: [shopOrder.fufilledBy], references: [user.id] }), + warehouseOrder: one(warehouseOrder, { fields: [shopOrder.id], references: [warehouseOrder.shopOrderId] }) +})); + + diff --git a/resolution-frontend/src/lib/server/devSeed.ts b/resolution-frontend/src/lib/server/devSeed.ts new file mode 100644 index 0000000..9d19a40 --- /dev/null +++ b/resolution-frontend/src/lib/server/devSeed.ts @@ -0,0 +1,119 @@ +import { dev } from '$app/environment'; +import { db } from './db'; +import { + pathwayShop, + shopItem, + shopOrder, + user, + userPathway +} from './db/schema'; +import { and, eq } from 'drizzle-orm'; +import { PATHWAYS } from '$lib/pathways'; + +const TEST_USER_ID = 'dev-seed-participant'; +const TEST_USER_HACK_CLUB_ID = 'dev-seed-hackclub-id'; +const TEST_USER_EMAIL = 'dev-seed-participant@example.com'; + +const TEST_ADDRESS = { + addressLine1: '15 Falls Rd', + addressLine2: '', + city: 'Shelburne', + stateProvince: 'VT', + country: 'United States', + zipPostalCode: '05482' +}; + +/** + * Dev-only seed: ensure every pathway has an enabled `pathwayShop`, at least + * one `shopItem`, and a couple of pending `shopOrder`s pointed at a fake + * participant so the fulfill flow has something to render. No-op in production. + */ +export async function seedDevShops() { + if (!dev) return; + + // Make sure a stable fake participant exists so we can hang seeded orders + // off a real user row. Insert is idempotent via ON CONFLICT DO NOTHING. + await db + .insert(user) + .values({ + id: TEST_USER_ID, + email: TEST_USER_EMAIL, + hackClubId: TEST_USER_HACK_CLUB_ID, + firstName: 'Devon', + lastName: 'Seeder' + }) + .onConflictDoNothing(); + + for (const { id, label } of PATHWAYS) { + const existingShop = await db.query.pathwayShop.findFirst({ + where: eq(pathwayShop.pathway, id) + }); + + if (!existingShop) { + await db.insert(pathwayShop).values({ + pathway: id, + isEnabled: true, + currencyName: 'wish', + currencyNamePlural: 'wishes' + }); + } else if (!existingShop.isEnabled) { + await db + .update(pathwayShop) + .set({ isEnabled: true }) + .where(eq(pathwayShop.pathway, id)); + } + + let item = await db.query.shopItem.findFirst({ + where: and(eq(shopItem.pathway, id), eq(shopItem.isActive, true)) + }); + + if (!item) { + [item] = await db + .insert(shopItem) + .values({ + pathway: id, + name: `${label} starter sticker`, + description: `A test ${label} sticker seeded automatically in dev. Remove me before going live.`, + price: 5, + stock: 25, + isActive: true + }) + .returning(); + } + + // Make sure the test participant belongs to this pathway. Cheap insert, + // guarded by the unique (user, pathway) index. + await db + .insert(userPathway) + .values({ userId: TEST_USER_ID, pathway: id }) + .onConflictDoNothing(); + + // Seed exactly one pending order per pathway/item pair so the fulfill + // page has something to render. Skip if we've already seeded one. + const existingOrder = await db.query.shopOrder.findFirst({ + where: and( + eq(shopOrder.pathway, id), + eq(shopOrder.userId, TEST_USER_ID), + eq(shopOrder.item, item!.id), + eq(shopOrder.status, 'PENDING') + ) + }); + + if (!existingOrder) { + await db.insert(shopOrder).values({ + userId: TEST_USER_ID, + pathway: id, + status: 'PENDING', + totalAmount: item!.price, + item: item!.id, + itemPriceSnapshot: item!.price, + itemNameSnapshot: item!.name, + shippingAddress: TEST_ADDRESS, + phone: '555-0100', + userNotes: `Auto-seeded test order for ${label}` + }); + } + } + + console.log('[dev seed] pathway shops + items + sample orders ensured'); +} diff --git a/resolution-frontend/src/lib/server/validation/schemas.ts b/resolution-frontend/src/lib/server/validation/schemas.ts index bb90e53..f5fec2b 100644 --- a/resolution-frontend/src/lib/server/validation/schemas.ts +++ b/resolution-frontend/src/lib/server/validation/schemas.ts @@ -64,6 +64,17 @@ const safeUrl = z.string().url('Please enter a valid URL').max(2000).refine( { message: 'URL must use http or https' } ); +export const addressSchema = z.object({ + addressLine1: z.string().min(1, 'Address is required').max(200), + addressLine2: z.string().max(200).optional().default(''), + city: z.string().min(1, 'City is required').max(100), + stateProvince: z.string().min(1, 'State / Province is required').max(100), + country: z.string().min(1, 'Country is required').max(100), + zipPostalCode: z.string().min(1, 'ZIP / Postal code is required').max(20) +}); + +export type AddressInput = z.infer; + export const projectSubmissionSchema = z.object({ codeUrl: safeUrl.refine( (val) => /^https:\/\/github\.com\/.+\/.+/.test(val), @@ -78,12 +89,7 @@ export const projectSubmissionSchema = z.object({ email: z.string().email('Please enter a valid email').max(254).transform((v) => v.trim().toLowerCase()), description: z.string().min(1, 'Description is required').max(2000), githubUsername: z.string().min(1, 'GitHub username is required').max(100), - addressLine1: z.string().min(1, 'Address is required').max(200), - addressLine2: z.string().max(200).optional().default(''), - city: z.string().min(1, 'City is required').max(100), - stateProvince: z.string().min(1, 'State / Province is required').max(100), - country: z.string().min(1, 'Country is required').max(100), - zipPostalCode: z.string().min(1, 'ZIP / Postal code is required').max(20), + ...addressSchema.shape, // needed for shop order validation birthday: z.string().min(1, 'Birthday is required').regex(/^\d{4}-\d{2}-\d{2}$/, 'Please enter a valid date'), hackatimeProject: z.string().min(1, 'Hackatime project is required').max(200), hoursSpent: z diff --git a/resolution-frontend/src/lib/shop/utils.ts b/resolution-frontend/src/lib/shop/utils.ts new file mode 100644 index 0000000..ad81c03 --- /dev/null +++ b/resolution-frontend/src/lib/shop/utils.ts @@ -0,0 +1,40 @@ +import { db } from '$lib/server/db'; +import { + userPathway, + pathwayShop, +} from '$lib/server/db/schema'; +import { and, eq } from 'drizzle-orm'; +import { error, redirect } from '@sveltejs/kit'; +import { PATHWAY_IDS, type PathwayId } from '$lib/pathways'; + +type DbOrTx = typeof db | Parameters[0]>[0]; + +export class shopError extends Error { + constructor(public status: number, public body: { message: string }) { + super(body.message); + } +} + +export async function assertShopAccess(userId: string, pathwayParam: string, conn: DbOrTx = db) { + const pathwayId = pathwayParam.toUpperCase(); + if (!PATHWAY_IDS.includes(pathwayId as PathwayId)) throw error(404, 'Pathway not found'); + const typedPathwayId = pathwayId as PathwayId; + + const membership = await conn + .select() + .from(userPathway) + .where(and(eq(userPathway.userId, userId), eq(userPathway.pathway, typedPathwayId))) + .limit(1); + if (membership.length === 0) throw redirect(302, '/app'); + + const pathwayShopRow = await conn + .select() + .from(pathwayShop) + .where(eq(pathwayShop.pathway, typedPathwayId)) + .limit(1); + if (pathwayShopRow.length === 0 || !pathwayShopRow[0].isEnabled) { + throw error(404); + } + + return { typedPathwayId, shop: pathwayShopRow[0] }; +} \ No newline at end of file diff --git a/resolution-frontend/src/routes/api/fulfillment/get-label/+server.ts b/resolution-frontend/src/routes/api/fulfillment/get-label/+server.ts index dc9a3e5..ec55dcc 100644 --- a/resolution-frontend/src/routes/api/fulfillment/get-label/+server.ts +++ b/resolution-frontend/src/routes/api/fulfillment/get-label/+server.ts @@ -1,7 +1,7 @@ import { env } from '$env/dynamic/private'; import { json, error } from '@sveltejs/kit'; import { db } from '$lib/server/db'; -import { warehouseOrder, ambassadorPathway } from '$lib/server/db/schema'; +import { warehouseOrder, ambassadorPathway, shopOrder } from '$lib/server/db/schema'; import { eq, and } from 'drizzle-orm'; import type { RequestHandler } from './$types'; import { requireAuth } from '$lib/server/auth/guard'; @@ -359,6 +359,20 @@ export const POST: RequestHandler = async (event) => { }) .where(eq(warehouseOrder.id, orderId)); + // If this warehouse order was created from a shop order, flip the linked + // shop order to FULFILLED and copy the tracking number so the participant + // can see it on their order page. Lettermail can ship without a tracking + // number, so trackingNumber may legitimately be null here. + if (order.shopOrderId) { + await db.update(shopOrder) + .set({ + status: 'FULFILLED', + fufilledAt: new Date(), + trackingNumber: trackingNumber ?? null + }) + .where(eq(shopOrder.id, order.shopOrderId)); + } + return json({ trackingNumber, labelUrl, diff --git a/resolution-frontend/src/routes/app/ambassador/+page.svelte b/resolution-frontend/src/routes/app/ambassador/+page.svelte index 464dd4e..2a157bf 100644 --- a/resolution-frontend/src/routes/app/ambassador/+page.svelte +++ b/resolution-frontend/src/routes/app/ambassador/+page.svelte @@ -61,6 +61,18 @@ height="32" />

{info.label}

+ + + Shop +
@@ -188,6 +200,24 @@ margin-bottom: 1.25rem; } + .shop-btn { + margin-left: auto; + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.4rem 0.85rem; + border-radius: 20px; + background: rgba(255, 255, 255, 0.8); + border: 1px solid #a633d6; + color: #a633d6; + font-family: 'Kodchasan', sans-serif; + text-decoration: none; + font-size: 0.85rem; + } + .shop-btn:hover { + background: #fff; + } + h2 { font-size: 1.25rem; margin: 0; diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+layout.server.ts b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+layout.server.ts new file mode 100644 index 0000000..2c03a96 --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+layout.server.ts @@ -0,0 +1,24 @@ +import type { LayoutServerLoad } from './$types'; +import { db } from '$lib/server/db'; +import { ambassadorPathway } from '$lib/server/db/schema'; +import { and, eq } from 'drizzle-orm'; +import { error } from '@sveltejs/kit'; +import { PATHWAY_IDS, type PathwayId } from '$lib/pathways'; + +export const load: LayoutServerLoad = async ({ params, parent }) => { + const { user } = await parent(); + + const raw = params.pathway.toUpperCase(); + if (!PATHWAY_IDS.includes(raw)) throw error(404, 'Pathway not found'); + const pathwayId = raw as PathwayId; + + const isAmbassador = await db.query.ambassadorPathway.findFirst({ + where: and( + eq(ambassadorPathway.userId, user.id), + eq(ambassadorPathway.pathway, pathwayId) + ) + }); + if (!isAmbassador) throw error(403, 'You are not an ambassador for this pathway'); + + return { pathwayId }; +}; diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+page.server.ts b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+page.server.ts new file mode 100644 index 0000000..96ee189 --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+page.server.ts @@ -0,0 +1,40 @@ +import type { PageServerLoad } from './$types'; +import { db } from '$lib/server/db'; +import { pathwayShop, shopItem, shopOrder } from '$lib/server/db/schema'; +import { and, desc, eq, notInArray } from 'drizzle-orm'; +import { error } from '@sveltejs/kit'; + +export const load: PageServerLoad = async ({ parent }) => { + const { pathwayId } = await parent(); + + const shop = await db.query.pathwayShop.findFirst({ + where: eq(pathwayShop.pathway, pathwayId) + }); + if (!shop) throw error(404, 'Shop not found for this pathway'); + + const items = await db + .select() + .from(shopItem) + .where(eq(shopItem.pathway, pathwayId)) + .orderBy(desc(shopItem.createdAt)); + + const totalOrders = await db.$count(shopOrder, eq(shopOrder.pathway, pathwayId)); + const awaitingFufillment = await db.$count( + shopOrder, + and( + eq(shopOrder.pathway, pathwayId), + notInArray(shopOrder.status, ['FULFILLED', 'CANCELED']) + ) + ); + + return { + shop: { + isEnabled: shop.isEnabled, + currencyName: shop.currencyName, + currencyNamePlural: shop.currencyNamePlural + }, + items, + totalOrders, + awaitingFufillment + }; +}; diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+page.svelte b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+page.svelte new file mode 100644 index 0000000..756db1a --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/+page.svelte @@ -0,0 +1,308 @@ + + + + {info?.label ?? data.pathwayId} Shop - Ambassador + + +
+ + Back + Back to Ambassador Dashboard + + +
+
+
+ + {info?.label ?? data.pathwayId} + +

Shop Management

+

+ Currency: {data.shop.currencyName} / {data.shop.currencyNamePlural} Β· + {#if data.shop.isEnabled} + Enabled + {:else} + Disabled + {/if} +

+
+ +
+
+ +
+
+
Total orders
+
{data.totalOrders}
+
+ +
Awaiting fulfillment
+
0}>{data.awaitingFufillment}
+
+
+
Active items
+
{data.items.filter((i) => i.isActive).length}
+
+
+ +
+

Items ({data.items.length})

+ {#if data.items.length === 0} +
+

No items yet.

+ Create your first item +
+ {:else} +
    + {#each data.items as item (item.id)} +
  • +
    + {#if item.itemImageUrl} + {item.name} + {:else} +
    No image
    + {/if} +
    +
    +
    +

    {item.name}

    + {sourceLabel(item.sourceType)} + {#if item.isActive} + Active + {:else} + Inactive + {/if} +
    +

    {item.description}

    +
    + {priceLabel(item.price)} + Β· + + {#if item.stock === null} + Unlimited stock + {:else} + {item.stock} in stock + {/if} + +
    +
    +
  • + {/each} +
+ {/if} +
+
+ + diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/+page.server.ts b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/+page.server.ts new file mode 100644 index 0000000..f2d9ac0 --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/+page.server.ts @@ -0,0 +1,247 @@ +// TODO: write tests! +import type { PageServerLoad, Actions } from './$types'; +import { db } from '$lib/server/db'; +import { + shopItem, + pathwayEnum, + ambassadorPathway, + warehouseOrderTemplate, + warehouseOrderTemplateItem, + warehouseItem +} from '$lib/server/db/schema'; +import { and, eq, or } from 'drizzle-orm'; +import { error, redirect } from '@sveltejs/kit'; +// import { PATHWAY_IDS, type PathwayId } from '$lib/pathways'; +import { z } from 'zod'; +import { PATHWAYS, type PathwayId } from '$lib/pathways'; + +const pathwayIdSchema = z.enum( + PATHWAYS.map((p) => p.id) as [PathwayId, ...PathwayId[]] +); + +const addCustomItemSchema = z.object({ // for grants + name: z.string().min(1).max(50), + description: z.string().min(1).max(2000), + imageUrl: z.url(), + price: z.coerce.number().int(), + stock: z.coerce.number().int(), + isActive: z.coerce.boolean().default(false) // used because ambassador may not want it to be instantly available +}) + +const addWarehouseItemSchema = z.object({ + id: z.string().min(1), // item ID from warehouse + // auto pull from warehouse but add optional overrides + name: z.string().min(1).max(50).or(z.string().max(0)), + description: z.string().min(1), // required bcs warehouse doesn't provide + imageUrl: z.union([z.url(), z.literal('')]).optional(), + price: z.coerce.number().int(), + // stock should be auto populated + // stock: z.int().optional(), // optional stock override, check later that this is not over current stock + isActive: z.coerce.boolean().default(false) +}) + +const addWarehouseTemplateSchema = z.object({ + id: z.string().min(1), // template ID from warehouse + name: z.string().min(1).max(50).or(z.string().max(0)), // not necessarily going to match template name + description: z.string().min(1).max(2000), + imageUrl: z.url(), + price: z.coerce.number().int(), + // should be autopopulated + // stock: z.int(), // set max as current stock + isActive: z.coerce.boolean().default(false) +}) + +export const load: PageServerLoad = async ({ parent }) => { + const { user, pathwayId } = await parent(); + + const warehouseTemplates = await db + .select() + .from(warehouseOrderTemplate) + .where(or(eq(warehouseOrderTemplate.createdById, user.id), eq(warehouseOrderTemplate.isPublic, true))); + + const warehouseItems = await db.select().from(warehouseItem); + + return { warehouseTemplates, warehouseItems, pathwayId }; +}; + +export const actions: Actions = { + createCustom: async ({ request, params, locals }) => { + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + // pathway validation from param + const rawPathway = params.pathway?.toUpperCase() ?? ''; + const pathwayParsed = pathwayIdSchema.safeParse(rawPathway); + if (!pathwayParsed.success) throw error(404, 'Pathway not found'); + const pathwayId = pathwayParsed.data; + + // make sure its gated to ambassadors + const assignment = await db.query.ambassadorPathway.findFirst({ + where: and(eq(ambassadorPathway.userId, userId), eq(ambassadorPathway.pathway, pathwayId)) + }); + if (!assignment) throw error(403, 'You are not authorized to do this action'); + + const form = Object.fromEntries(await request.formData()); + const addItemObj = addCustomItemSchema.safeParse(form); + if (!addItemObj.success) throw error(400, 'Invalid request data'); + + const data = addItemObj.data; + + const [inserted] = await db + .insert(shopItem) + .values({ + pathway: pathwayId, + name: data.name, + description: data.description, + itemImageUrl: data.imageUrl, + price: data.price, + stock: data.stock, + isActive: data.isActive, + sourceType: 'CUSTOM', + lastEditedBy: userId + }) + .returning(); + + return { success: true, item: inserted }; + }, + createWarehouse: async ({ request, params, locals }) => { + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + // pathway validation from param + const rawPathway = params.pathway?.toUpperCase() ?? ''; + const pathwayParsed = pathwayIdSchema.safeParse(rawPathway); + if (!pathwayParsed.success) throw error(404, 'Pathway not found'); + const pathwayId = pathwayParsed.data; + + // make sure its gated to ambassadors + const assignment = await db.query.ambassadorPathway.findFirst({ + where: and(eq(ambassadorPathway.userId, userId), eq(ambassadorPathway.pathway, pathwayId)) + }); + if (!assignment) throw error(403, 'You are not authorized to do this action'); + + const form = Object.fromEntries(await request.formData()); + const addItemObj = addWarehouseItemSchema.safeParse(form); + if (!addItemObj.success) throw error(400, 'Invalid request data'); + + const data = addItemObj.data; + + const wh = await db.query.warehouseItem.findFirst({ + where: eq(warehouseItem.id, data.id) + }); + if (!wh) throw error(404, 'Warehouse item not found'); + + // form values win when non-empty/non-null; otherwise fall back to the warehouse row + const [inserted] = await db + .insert(shopItem) + .values({ + pathway: pathwayId, + name: data.name?.trim() || wh.name, + description: data.description, // required from form + itemImageUrl: data.imageUrl ?? wh.imageUrl, + price: data.price, + stock: wh.quantity, + isActive: data.isActive, + sourceType: 'WAREHOUSE_ITEM', + linkedWarehouseItemId: wh.id, + lastEditedBy: userId + }) + .returning(); + + return { success: true, item: inserted }; + + }, + createWarehouseTemplate: async ({ request, params, locals }) => { + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + // pathway validation from param + const rawPathway = params.pathway?.toUpperCase() ?? ''; + const pathwayParsed = pathwayIdSchema.safeParse(rawPathway); + if (!pathwayParsed.success) throw error(404, 'Pathway not found'); + const pathwayId = pathwayParsed.data; + + // make sure its gated to ambassadors + const assignment = await db.query.ambassadorPathway.findFirst({ + where: and(eq(ambassadorPathway.userId, userId), eq(ambassadorPathway.pathway, pathwayId)) + }); + if (!assignment) throw error(403, 'You are not authorized to do this action'); + + const form = Object.fromEntries(await request.formData()); + const addItemObj = addWarehouseTemplateSchema.safeParse(form); + if (!addItemObj.success) throw error(400, 'Invalid request data'); + + const data = addItemObj.data; + + // fetch template, ensure access + const tpl = await db.query.warehouseOrderTemplate.findFirst({ + where: eq(warehouseOrderTemplate.id, data.id) + }); + if (!tpl) throw error(404, 'Warehouse template not found'); + if (tpl.createdById !== userId && !tpl.isPublic) { + throw error(403, 'You cannot use this template'); + } + + // find max stock based on the stock of items within the template + const tplItems = await db + .select({ + perOrder: warehouseOrderTemplateItem.quantity, + available: warehouseItem.quantity + }) + .from(warehouseOrderTemplateItem) + .innerJoin( + warehouseItem, + eq(warehouseItem.id, warehouseOrderTemplateItem.warehouseItemId) + ) + .where(eq(warehouseOrderTemplateItem.templateId, tpl.id)); + + if (tplItems.length === 0) throw error(400, 'Template has no items'); + + // should be autopopulated + const stock = Math.min( + ...tplItems.map((i) => Math.floor(i.available / i.perOrder)) + ); + + // form values win when provided; otherwise fall back to the template's name. + const [inserted] = await db + .insert(shopItem) + .values({ + pathway: pathwayId, + name: data.name?.trim() || tpl.name, + description: data.description, + itemImageUrl: data.imageUrl, + price: data.price, + stock, + isActive: data.isActive, + sourceType: 'WAREHOUSE_TEMPLATE', + linkedWarehouseTemplateId: tpl.id, + lastEditedBy: userId + }) + .returning(); + + return { success: true, item: inserted }; + } +} + +// TODO: use this on item loads +// const items = await db +// .select({ +// id: shopItem.id, +// name: shopItem.name, +// sourceType: shopItem.sourceType, +// // … +// effectiveStock: sql` +// CASE +// WHEN ${shopItem.sourceType} = 'WAREHOUSE_ITEM' THEN ${warehouseItem.stock} +// WHEN ${shopItem.sourceType} = 'WAREHOUSE_TEMPLATE' THEN ( +// SELECT MIN(wi.stock / wt.quantity) +// FROM warehouse_order_template_item wt +// JOIN warehouse_item wi ON wi.id = wt.warehouse_item_id +// WHERE wt.template_id = ${shopItem.linkedWarehouseTemplateId} +// ) +// ELSE ${shopItem.stock} +// END +// ` +// }) +// .from(shopItem) +// .leftJoin(warehouseItem, eq(warehouseItem.id, shopItem.linkedWarehouseItemId)); \ No newline at end of file diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/+page.svelte b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/+page.svelte new file mode 100644 index 0000000..c03b9ca --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/+page.svelte @@ -0,0 +1,296 @@ + + + + Add Shop Item - {info?.label ?? data.pathwayId} + + +
+ + Back + Back to Shop + + +
+

Add a Shop Item

+

Add an item that participants can spend their pathway currency on.

+
+ + {#if form?.success} +
+ Created item {form.item?.name}. + Back to shop +
+ {/if} + +
+ + + +
+ + {#if activeTab === 'custom'} +
+

Custom item

+

A pure custom listing (e.g., a grant or a digital reward). You handle fulfillment manually.

+ +
+ + + +
+ + +
+ + +
+
+ {:else if activeTab === 'warehouse'} +
+

Warehouse item

+

Link directly to a single warehouse item. Stock is pulled from the warehouse.

+ + {#if data.warehouseItems.length === 0} +

No warehouse items available.

+ {:else} +
+ + + + + + + +
+ {/if} +
+ {:else} +
+

Warehouse template

+

Link to a warehouse template (a bundle of items). Stock is computed from template components.

+ + {#if data.warehouseTemplates.length === 0} +

No warehouse templates available.

+ {:else} +
+ + + + + + + +
+ {/if} +
+ {/if} +
+ + diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/page.server.test.ts b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/page.server.test.ts new file mode 100644 index 0000000..11db9aa --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/create/page.server.test.ts @@ -0,0 +1,250 @@ +/** + * Action-level tests for the shop item creation page. Covers all three + * "source" types β€” CUSTOM, WAREHOUSE_ITEM, and WAREHOUSE_TEMPLATE β€” with + * the db, including warehouse lookups, fully mocked. + */ +import { describe, it, expect, vi, beforeEach } from 'vitest'; + +type Queue = unknown[]; + +function makeChain(queue: Queue) { + const handler: ProxyHandler = { + get(_, prop) { + if (prop === 'then') { + const value = queue.length > 0 ? queue.shift() : undefined; + const p = Promise.resolve(value); + return p.then.bind(p); + } + return () => proxy; + } + }; + const proxy: object = new Proxy({}, handler); + return proxy; +} + +const insertQueue: Queue = []; +const selectQueue: Queue = []; + +const mockAmbassadorFindFirst = vi.fn(); +const mockWarehouseItemFindFirst = vi.fn(); +const mockWarehouseTemplateFindFirst = vi.fn(); + +vi.mock('$lib/server/db', () => ({ + db: { + query: { + ambassadorPathway: { + findFirst: (...args: unknown[]) => mockAmbassadorFindFirst(...args) + }, + warehouseItem: { + findFirst: (...args: unknown[]) => mockWarehouseItemFindFirst(...args) + }, + warehouseOrderTemplate: { + findFirst: (...args: unknown[]) => mockWarehouseTemplateFindFirst(...args) + } + }, + select: () => makeChain(selectQueue), + insert: () => makeChain(insertQueue) + } +})); + +const { actions } = await import('./+page.server'); + +function makeFormData(data: Record) { + return { + formData: async () => { + const fd = new FormData(); + for (const [k, v] of Object.entries(data)) fd.append(k, v); + return fd; + } + }; +} + +function makeEvent(opts: { + form: Record; + pathway?: string; + user?: { id: string } | null; +}) { + const { form, pathway = 'python', user = { id: 'amb-1' } } = opts; + return { + request: makeFormData(form), + params: { pathway }, + locals: { user } + } as any; +} + +beforeEach(() => { + insertQueue.length = 0; + selectQueue.length = 0; + vi.clearAllMocks(); +}); + +// ---- createCustom ----------------------------------------------------------- + +describe('createCustom action', () => { + const validForm = { + name: 'Free Sticker', + description: 'A sticker as a grant reward.', + imageUrl: 'https://example.com/sticker.png', + price: '0', + stock: '10' + }; + + it('inserts a CUSTOM shop item and returns it', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + insertQueue.push([{ id: 'item-1', name: 'Free Sticker', sourceType: 'CUSTOM' }]); + + const event = makeEvent({ form: validForm }); + const result = await actions.createCustom(event); + + expect(result).toEqual({ + success: true, + item: { id: 'item-1', name: 'Free Sticker', sourceType: 'CUSTOM' } + }); + }); + + it('rejects unauthenticated users with a redirect', async () => { + const event = makeEvent({ form: validForm, user: null }); + await expect(actions.createCustom(event)).rejects.toMatchObject({ status: 302 }); + }); + + it('throws 404 for an invalid pathway slug', async () => { + const event = makeEvent({ form: validForm, pathway: 'imaginary' }); + await expect(actions.createCustom(event)).rejects.toMatchObject({ status: 404 }); + }); + + it('throws 403 when the caller is not an ambassador for the pathway', async () => { + mockAmbassadorFindFirst.mockResolvedValue(undefined); + + const event = makeEvent({ form: validForm }); + await expect(actions.createCustom(event)).rejects.toMatchObject({ status: 403 }); + }); + + it('throws 400 on invalid form data', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + + const event = makeEvent({ + form: { ...validForm, imageUrl: 'not a url' } + }); + await expect(actions.createCustom(event)).rejects.toMatchObject({ status: 400 }); + }); +}); + +// ---- createWarehouse -------------------------------------------------------- + +describe('createWarehouse action', () => { + const validForm = { + id: 'wh-1', + name: '', + description: 'Pulled from warehouse stock.', + price: '15' + }; + + it('inserts a WAREHOUSE_ITEM-backed shop item using warehouse defaults', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockWarehouseItemFindFirst.mockResolvedValue({ + id: 'wh-1', + name: 'Holographic Sticker', + imageUrl: 'https://example.com/holo.png', + quantity: 42 + }); + insertQueue.push([ + { id: 'shop-1', name: 'Holographic Sticker', sourceType: 'WAREHOUSE_ITEM' } + ]); + + const event = makeEvent({ form: validForm }); + const result = await actions.createWarehouse(event); + + expect(result).toMatchObject({ + success: true, + item: { sourceType: 'WAREHOUSE_ITEM' } + }); + }); + + it('throws 404 when the linked warehouse item does not exist', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockWarehouseItemFindFirst.mockResolvedValue(undefined); + + const event = makeEvent({ form: validForm }); + await expect(actions.createWarehouse(event)).rejects.toMatchObject({ status: 404 }); + }); + + it('throws 403 for non-ambassadors', async () => { + mockAmbassadorFindFirst.mockResolvedValue(undefined); + const event = makeEvent({ form: validForm }); + await expect(actions.createWarehouse(event)).rejects.toMatchObject({ status: 403 }); + }); +}); + +// ---- createWarehouseTemplate ------------------------------------------------ + +describe('createWarehouseTemplate action', () => { + const validForm = { + id: 'tpl-1', + name: 'Starter Pack', + description: 'Bundle of stickers and a pin.', + imageUrl: 'https://example.com/bundle.png', + price: '50' + }; + + it('computes max stock from the cheapest template component and inserts the shop item', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockWarehouseTemplateFindFirst.mockResolvedValue({ + id: 'tpl-1', + name: 'Starter Pack', + createdById: 'amb-1', + isPublic: false + }); + // Template-items join lookup: 3 stickers (stock 30 β†’ 10) and 1 pin (stock 8 β†’ 8). + // min(10, 8) = 8 expected stock. + selectQueue.push([ + { perOrder: 3, available: 30 }, + { perOrder: 1, available: 8 } + ]); + insertQueue.push([ + { id: 'shop-2', name: 'Starter Pack', sourceType: 'WAREHOUSE_TEMPLATE', stock: 8 } + ]); + + const event = makeEvent({ form: validForm }); + const result = await actions.createWarehouseTemplate(event); + + expect(result).toMatchObject({ + success: true, + item: { sourceType: 'WAREHOUSE_TEMPLATE', stock: 8 } + }); + }); + + it('throws 400 if the template has no items', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockWarehouseTemplateFindFirst.mockResolvedValue({ + id: 'tpl-1', + name: 'Empty', + createdById: 'amb-1', + isPublic: false + }); + selectQueue.push([]); + + const event = makeEvent({ form: validForm }); + await expect(actions.createWarehouseTemplate(event)).rejects.toMatchObject({ status: 400 }); + }); + + it('throws 403 when caller is not the template owner and template is private', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockWarehouseTemplateFindFirst.mockResolvedValue({ + id: 'tpl-1', + name: 'Other', + createdById: 'somebody-else', + isPublic: false + }); + + const event = makeEvent({ form: validForm }); + await expect(actions.createWarehouseTemplate(event)).rejects.toMatchObject({ status: 403 }); + }); + + it('throws 404 when template not found', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockWarehouseTemplateFindFirst.mockResolvedValue(undefined); + + const event = makeEvent({ form: validForm }); + await expect(actions.createWarehouseTemplate(event)).rejects.toMatchObject({ status: 404 }); + }); +}); diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/+page.server.ts b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/+page.server.ts new file mode 100644 index 0000000..ee9839d --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/+page.server.ts @@ -0,0 +1,490 @@ +// NOTE: MOST OF THE HCB LOGIC IS VIBED. I DON'T TRUST MYSELF WITH WAREHOUSE OR HCB. +import type { PageServerLoad, Actions } from './$types'; +import { db } from '$lib/server/db'; +import { + shopItem, + pathwayEnum, + ambassadorPathway, + warehouseOrder, + warehouseOrderItem, + warehouseOrderTemplate, + warehouseOrderTemplateItem, + warehouseItem, + shopOrder +} from '$lib/server/db/schema'; +import { and, eq, gte, inArray, or, sql } from 'drizzle-orm'; +import { error, fail, redirect } from '@sveltejs/kit'; +// import { PATHWAY_IDS, type PathwayId } from '$lib/pathways'; +import { z } from 'zod'; +import { PATHWAYS, type PathwayId } from '$lib/pathways'; +import { createHcbTransfer, getOrgIdForPathway } from '$lib/server/hcb'; +import { selectPackaging } from '$lib/server/packaging'; +import { fetchCheapestRate } from '$lib/server/canada-post'; +import { resolveCountryCode } from '$lib/server/countries'; + +// Hard cap on the auto fetched shipping estimate. Mirrors the limit in +// /warehouse/orders/new so a rogue rate response cannot trigger a huge +// HCB transfer. +const MAX_SHIPPING_CENTS = 50_000; + +const pathwayIdSchema = z.enum( + PATHWAYS.map((p) => p.id) as [PathwayId, ...PathwayId[]] +); + +const approveSchema = z.object({ + // pathway: pathwayIdSchema, + id: z.string().min(1).max(100), // id for the order + note: z.string().optional() +}) + +const rejectSchema = z.object({ + // pathway: pathwayIdSchema + id: z.string().min(1).max(100), + note: z.string() +}) + +export const load: PageServerLoad = async ({ params, parent }) => { + const { user, pathwayId } = await parent(); + + const pendingOrders = await db.query.shopOrder.findMany({ + where: and(eq(shopOrder.pathway, pathwayId), eq(shopOrder.status, 'PENDING')), + with: { item: true, user: true } + }); + + // Collect every warehouse item and template needed across all orders so + // we can batch the lookups instead of N round trips. + const directItemIds = new Set(); + const templateIds = new Set(); + for (const o of pendingOrders) { + if (!o.item) continue; + if (o.item.sourceType === 'WAREHOUSE_ITEM' && o.item.linkedWarehouseItemId) { + directItemIds.add(o.item.linkedWarehouseItemId); + } else if (o.item.sourceType === 'WAREHOUSE_TEMPLATE' && o.item.linkedWarehouseTemplateId) { + templateIds.add(o.item.linkedWarehouseTemplateId); + } + } + + const templateItemRows = templateIds.size > 0 + ? await db + .select() + .from(warehouseOrderTemplateItem) + .where(inArray(warehouseOrderTemplateItem.templateId, [...templateIds])) + : []; + + const templateMap = new Map(); + for (const ti of templateItemRows) { + const list = templateMap.get(ti.templateId) ?? []; + list.push({ warehouseItemId: ti.warehouseItemId, quantity: ti.quantity }); + templateMap.set(ti.templateId, list); + directItemIds.add(ti.warehouseItemId); + } + + const stockRows = directItemIds.size > 0 + ? await db + .select({ + id: warehouseItem.id, + costCents: warehouseItem.costCents, + lengthIn: warehouseItem.lengthIn, + widthIn: warehouseItem.widthIn, + heightIn: warehouseItem.heightIn, + weightGrams: warehouseItem.weightGrams + }) + .from(warehouseItem) + .where(inArray(warehouseItem.id, [...directItemIds])) + : []; + const stockMap = new Map(stockRows.map((s) => [s.id, s])); + + // Quote each order in parallel. Shipping calls the carrier APIs so this + // can be slow on big lists; CUSTOM orders are skipped entirely. + const estimates = await Promise.all(pendingOrders.map(async (o) => { + if (!o.item) return null; + if (o.item.sourceType === 'CUSTOM') return null; + + let lineItems: { warehouseItemId: string; quantity: number }[] = []; + if (o.item.sourceType === 'WAREHOUSE_ITEM' && o.item.linkedWarehouseItemId) { + lineItems = [{ warehouseItemId: o.item.linkedWarehouseItemId, quantity: 1 }]; + } else if (o.item.sourceType === 'WAREHOUSE_TEMPLATE' && o.item.linkedWarehouseTemplateId) { + lineItems = templateMap.get(o.item.linkedWarehouseTemplateId) ?? []; + } + if (lineItems.length === 0) return null; + + let itemTotalCents = 0; + const packagingItems = []; + for (const li of lineItems) { + const s = stockMap.get(li.warehouseItemId); + if (!s) return null; + itemTotalCents += s.costCents * li.quantity; + packagingItems.push({ + lengthIn: s.lengthIn, + widthIn: s.widthIn, + heightIn: s.heightIn, + weightGrams: s.weightGrams, + quantity: li.quantity + }); + } + + let estimatedShippingCents: number | null = null; + if (o.shippingAddress) { + try { + const packaging = selectPackaging(packagingItems); + const quote = await fetchCheapestRate({ + country: resolveCountryCode(o.shippingAddress.country), + postalCode: o.shippingAddress.zipPostalCode || undefined, + province: o.shippingAddress.stateProvince, + weightGrams: packaging.weightGrams, + lengthIn: packaging.lengthIn, + widthIn: packaging.widthIn, + heightIn: packaging.heightIn, + packageType: packaging.category === 'box' ? 'box' : 'flat' + }); + if (quote) { + estimatedShippingCents = Math.min( + Math.round(quote.shippingCostUsd * 100), + MAX_SHIPPING_CENTS + ); + } + } catch (e) { + console.error(`Shipping quote failed for order ${o.id}:`, e); + } + } + + return { + orderId: o.id, + itemTotalCents, + estimatedShippingCents, + totalCents: itemTotalCents + (estimatedShippingCents ?? 0) + }; + })); + + const estimatesByOrderId: Record = {}; + for (const e of estimates) { + if (e) estimatesByOrderId[e.orderId] = { + itemTotalCents: e.itemTotalCents, + estimatedShippingCents: e.estimatedShippingCents, + totalCents: e.totalCents + }; + } + + return { pendingOrders, estimatesByOrderId }; +}; + +export const actions: Actions = { + approve: async ({request, params, locals}) => { + // frontend should send ID + // 1. gate to ambassadors only (done) + // 2. confirm ID exists (done) + // 3. check if item is linked to wh template or item (done) + // 3a. if 3 is yes, order (done) + // 3b. (frontend) if 3 is no, notify ambassador they have to manually fufill (done) + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + // pathway validation from param + const rawPathway = params.pathway?.toUpperCase() ?? ''; + const pathwayParsed = pathwayIdSchema.safeParse(rawPathway); + if (!pathwayParsed.success) throw error(404, 'Pathway not found'); + const pathwayId = pathwayParsed.data; + + // make sure its gated to ambassadors + const assignment = await db.query.ambassadorPathway.findFirst({ + where: and(eq(ambassadorPathway.userId, userId), eq(ambassadorPathway.pathway, pathwayId)) + }); + if (!assignment) throw error(403, 'You are not authorized to do this action'); + + const form = Object.fromEntries(await request.formData()); + const orderObj = approveSchema.safeParse(form); + if (!orderObj.success) throw error(400, 'Invalid request data'); + + const data = orderObj.data + const order = await db.query.shopOrder.findFirst({ + where: and(eq(shopOrder.pathway, pathwayId), eq(shopOrder.id, data.id)), + with: { item: true, user: true } + }); + + if (!order) throw error(404, 'Order not found') + if (!order.item) throw error(400, 'Nonexistant order item') + if (!order.user) throw error(400, 'Order has no associated user') + if (!order.shippingAddress) throw error(400, 'Order missing shipping address') + + // need to build the warehouse items + type LineItem = { warehouseItemId: string; quantity: number; sizingChoice: string | null }; + let lineItems: LineItem[] = []; + + if (order.item.sourceType === 'WAREHOUSE_ITEM') { + if (!order.item.linkedWarehouseItemId) { + throw error(400, 'Shop item is missing its linked warehouse item'); + } + lineItems = [{ + warehouseItemId: order.item.linkedWarehouseItemId, + quantity: 1, + sizingChoice: null + }]; + } + else if (order.item.sourceType === 'WAREHOUSE_TEMPLATE') { + if (!order.item.linkedWarehouseTemplateId) { + throw error(400, 'Shop item is missing its linked warehouse template'); + } + const tplItems = await db + .select() + .from(warehouseOrderTemplateItem) + .where(eq(warehouseOrderTemplateItem.templateId, order.item.linkedWarehouseTemplateId)); + if (tplItems.length === 0) { + throw error(400, 'Linked warehouse template has no items'); + } + lineItems = tplItems.map((t) => ({ + warehouseItemId: t.warehouseItemId, + quantity: t.quantity, + sizingChoice: null + })); + } + else { + // nothing to ship so just mark it as done + try { + await db.transaction(async (tx) => { + await tx.update(shopOrder) + .set({ + status: 'FULFILLED', + fufilledBy: userId, + fufilledAt: new Date(), + fufillerNotes: data.note ?? null + }) + .where(eq(shopOrder.id, order.id)); + }); + } catch (e: any) { + return fail(500, { error: e?.message || 'Failed to mark order as fulfilled' }); + } + return { success: true }; + } + + // make sure stock is available before continuing + const itemIds = lineItems.map((i) => i.warehouseItemId); + const stock = await db + .select({ + id: warehouseItem.id, + name: warehouseItem.name, + quantity: warehouseItem.quantity, + costCents: warehouseItem.costCents, + lengthIn: warehouseItem.lengthIn, + widthIn: warehouseItem.widthIn, + heightIn: warehouseItem.heightIn, + weightGrams: warehouseItem.weightGrams, + packageType: warehouseItem.packageType + }) + .from(warehouseItem) + .where(inArray(warehouseItem.id, itemIds)); + const stockMap = new Map(stock.map((s) => [s.id, s])); + for (const li of lineItems) { + const s = stockMap.get(li.warehouseItemId); + if (!s || s.quantity < li.quantity) { + const name = s?.name ?? li.warehouseItemId; + const available = s?.quantity ?? 0; + return fail(400, { + error: `Insufficient stock for "${name}": ${available} available, ${li.quantity} requested` + }); + } + } + + const addr = order.shippingAddress; + const firstName = order.user.firstName ?? ''; + const lastName = order.user.lastName ?? ''; + const countryCode = resolveCountryCode(addr.country); + + // Build packaging from item dimensions, then quote the cheapest + // carrier rate. Result is in USD dollars; warehouseOrder stores cents + // so we convert and cap. Failures fall back to a 0 estimate, which + // matches the behavior of the warehouse new order form when the + // ambassador skips the quote step. + const packagingItems = lineItems.map((li) => { + const s = stockMap.get(li.warehouseItemId)!; + return { + lengthIn: s.lengthIn, + widthIn: s.widthIn, + heightIn: s.heightIn, + weightGrams: s.weightGrams, + quantity: li.quantity + }; + }); + const packaging = selectPackaging(packagingItems); + + let estimatedShippingCents: number | null = null; + let estimatedServiceName: string | null = null; + try { + const quote = await fetchCheapestRate({ + country: countryCode, + postalCode: addr.zipPostalCode || undefined, + province: addr.stateProvince, + weightGrams: packaging.weightGrams, + lengthIn: packaging.lengthIn, + widthIn: packaging.widthIn, + heightIn: packaging.heightIn, + packageType: packaging.category === 'box' ? 'box' : 'flat' + }); + if (quote) { + const cents = Math.round(quote.shippingCostUsd * 100); + estimatedShippingCents = Math.min(cents, MAX_SHIPPING_CENTS); + estimatedServiceName = quote.serviceName; + } + } catch (e) { + console.error(`Shipping rate quote failed for shop order ${order.id}:`, e); + } + + let warehouseOrderId: string; + try { + warehouseOrderId = await db.transaction(async (tx) => { + const [wo] = await tx.insert(warehouseOrder).values({ + createdById: userId, + shopOrderId: order.id, + firstName, + lastName, + email: order.user!.email, + phone: order.phone ?? null, + addressLine1: addr.addressLine1, + addressLine2: addr.addressLine2 || null, + city: addr.city, + stateProvince: addr.stateProvince, + postalCode: addr.zipPostalCode ?? null, + country: addr.country, + status: 'APPROVED', + billingStatus: 'PENDING', + estimatedShippingCents, + estimatedServiceName, + packagingCategory: packaging.category, + packagingLabel: packaging.label, + packagingLengthIn: packaging.lengthIn, + packagingWidthIn: packaging.widthIn, + packagingHeightIn: packaging.heightIn, + packagingSubjectToChange: packaging.subjectToChange ?? false, + notes: `Shop order ${order.id}` + }).returning({ id: warehouseOrder.id }); + + await Promise.all( + lineItems.map((li) => + tx.insert(warehouseOrderItem).values({ + orderId: wo.id, + warehouseItemId: li.warehouseItemId, + quantity: li.quantity, + sizingChoice: li.sizingChoice + }) + ) + ); + + // ensure no overselling + for (const li of lineItems) { + const s = stockMap.get(li.warehouseItemId); + const name = s?.name ?? li.warehouseItemId; + const [updated] = await tx + .update(warehouseItem) + .set({ quantity: sql`${warehouseItem.quantity} - ${li.quantity}` }) + .where(and( + eq(warehouseItem.id, li.warehouseItemId), + gte(warehouseItem.quantity, li.quantity) + )) + .returning({ id: warehouseItem.id }); + if (!updated) { + throw new Error(`Insufficient stock for "${name}", another order claimed it. Please retry.`); + } + } + + await tx.update(shopOrder) + .set({ status: 'PROCESSING', fufilledBy: userId, fufillerNotes: data.note ?? null }) + .where(eq(shopOrder.id, order.id)); + + return wo.id; + }); + } catch (e: any) { + return fail(409, { error: e?.message || 'Order creation failed. Please try again.' }); + } + + // Bill the pathway's HCB org for item cost plus the estimated + // shipping we just quoted. Mirrors /warehouse/orders/new: this is an + // estimate!! + // Failures are recorded on the warehouse order for manual + // reconciliation rather than rolling back the order, since the items + // are already reserved. + const orgId = getOrgIdForPathway(pathwayId); + if (orgId) { + let itemsTotalCents = 0; + for (const li of lineItems) { + const s = stockMap.get(li.warehouseItemId); + if (s) itemsTotalCents += s.costCents * li.quantity; + } + const totalCents = itemsTotalCents + (estimatedShippingCents ?? 0); + + if (totalCents > 0) { + try { + await createHcbTransfer( + orgId, + totalCents, + `Shop fulfillment: warehouse order ${warehouseOrderId} (shop order ${order.id})` + ); + await db.update(warehouseOrder) + .set({ billingStatus: 'CHARGED', updatedAt: new Date() }) + .where(eq(warehouseOrder.id, warehouseOrderId)); + } catch (e: any) { + const reason = e?.message ? String(e.message).slice(0, 500) : 'Unknown error'; + console.error(`HCB transfer failed for warehouse order ${warehouseOrderId}:`, reason); + await db.update(warehouseOrder) + .set({ + billingStatus: 'FAILED', + billingFailureReason: reason, + updatedAt: new Date() + }) + .where(eq(warehouseOrder.id, warehouseOrderId)); + } + } else { + await db.update(warehouseOrder) + .set({ billingStatus: 'CHARGED', updatedAt: new Date() }) + .where(eq(warehouseOrder.id, warehouseOrderId)); + } + } else { + // No HCB org mapped for this pathway, mark as not applicable so + // the order is not stuck in PENDING forever. + await db.update(warehouseOrder) + .set({ billingStatus: 'NOT_APPLICABLE', updatedAt: new Date() }) + .where(eq(warehouseOrder.id, warehouseOrderId)); + } + + return { success: true, warehouseOrderId }; + }, + deny: async ({request, params, locals}) => { + // 1: mark the order as rejected + // 2: add reason + // 3: yeah + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + // pathway validation from param + const rawPathway = params.pathway?.toUpperCase() ?? ''; + const pathwayParsed = pathwayIdSchema.safeParse(rawPathway); + if (!pathwayParsed.success) throw error(404, 'Pathway not found'); + const pathwayId = pathwayParsed.data; + + // make sure its gated to ambassadors + const assignment = await db.query.ambassadorPathway.findFirst({ + where: and(eq(ambassadorPathway.userId, userId), eq(ambassadorPathway.pathway, pathwayId)) + }); + if (!assignment) throw error(403, 'You are not authorized to do this action'); + + const form = Object.fromEntries(await request.formData()); + const orderObj = rejectSchema.safeParse(form); + if (!orderObj.success) throw error(400, 'Invalid request data'); + + const data = orderObj.data + const order = await db.query.shopOrder.findFirst({ + where: and(eq(shopOrder.pathway, pathwayId), eq(shopOrder.id, data.id)), + with: { item: true, user: true } + }); + + if (!order) throw error(400, 'Order ID does not exist'); + + await db.update(shopOrder) + .set({ status: 'REJECTED', cancelledReason: data.note}) + .where(eq(shopOrder.id, data.id)); + + return { success: true, orderId: data.id } + } +} \ No newline at end of file diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/+page.svelte b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/+page.svelte new file mode 100644 index 0000000..2e39b15 --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/+page.svelte @@ -0,0 +1,328 @@ + + + + Fulfill Orders - {info?.label ?? data.pathwayId} + + +
+ + Back + Back to Shop + + +
+

Fulfill Orders

+

+ {data.pendingOrders.length} pending order{data.pendingOrders.length === 1 ? '' : 's'} for {info?.label ?? data.pathwayId}. +

+
+ + {#if form && 'error' in form && form.error} +
{form.error}
+ {/if} + {#if form?.success} +
+ Order updated.{#if 'warehouseOrderId' in form && form.warehouseOrderId} + Warehouse order created: {form.warehouseOrderId} + {/if} +
+ {/if} + + {#if data.pendingOrders.length === 0} +
+

No pending orders right now. πŸŽ‰

+
+ {:else} +
    + {#each data.pendingOrders as order (order.id)} + {@const est = data.estimatesByOrderId[order.id]} + {@const sourceType = order.item?.sourceType ?? 'CUSTOM'} + {@const isCustom = sourceType === 'CUSTOM'} +
  • +
    +
    +

    {order.itemNameSnapshot}

    +
    + {sourceLabel(sourceType)} + Β· + {order.totalAmount} {order.totalAmount === 1 ? 'wish' : 'wishes'} + Β· + {new Date(order.createdAt).toLocaleString()} +
    +
    +
    #{order.id.slice(0, 8)}
    +
    + +
    +
    +
    Buyer
    + {#if order.user} +
    {order.user.firstName ?? ''} {order.user.lastName ?? ''}
    +
    {order.user.email}
    + {:else} +
    User no longer exists
    + {/if} + {#if order.phone} +
    {order.phone}
    + {/if} +
    + +
    +
    Shipping address
    + {#if order.shippingAddress} +
    {order.shippingAddress.addressLine1}
    + {#if order.shippingAddress.addressLine2} +
    {order.shippingAddress.addressLine2}
    + {/if} +
    + {order.shippingAddress.city}, {order.shippingAddress.stateProvince} + {order.shippingAddress.zipPostalCode} +
    +
    {order.shippingAddress.country}
    + {:else} +
    No shipping address (digital / grant)
    + {/if} +
    + + {#if !isCustom} +
    +
    Estimated cost
    + {#if est} +
    Items: {formatCents(est.itemTotalCents)}
    +
    + Shipping: + {formatCents(est.estimatedShippingCents)} + {#if est.estimatedShippingCents == null} + (no quote) + {/if} +
    +
    Total: {formatCents(est.totalCents)}
    + {:else} +
    No estimate available
    + {/if} +
    + {/if} +
    + + {#if order.userNotes} +
    + Buyer note: {order.userNotes} +
    + {/if} + + {#if isCustom} +
    + This is a custom item. Approving will mark the order fulfilled β€” you handle delivery manually. +
    + {/if} + +
    +
    + + + +
    + + {#if denyOpenFor === order.id} +
    + + + + +
    + {:else} + + {/if} +
    +
  • + {/each} +
+ {/if} +
+ + diff --git a/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/page.server.test.ts b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/page.server.test.ts new file mode 100644 index 0000000..5df352c --- /dev/null +++ b/resolution-frontend/src/routes/app/ambassador/[pathway]/shop/fufill/page.server.test.ts @@ -0,0 +1,422 @@ +/** + * Action-level tests for the shop fulfill page. We mock the db (drizzle's + * fluent builder), packaging/shipping helpers, and HCB so the tests run + * with no real warehouse items and no live HCB integration β€” mirroring a + * local dev environment. + */ +import { describe, it, expect, vi, beforeEach } from 'vitest'; + +// ---- db mock ---------------------------------------------------------------- + +type Queue = unknown[]; + +/** + * Drizzle's query builder is chainable (e.g. db.select().from().where()). + * This proxy lets any chain end in an awaited value pulled from a queue, + * so each test can pre-seed the values its action will see. + */ +function makeChain(queue: Queue) { + const handler: ProxyHandler = { + get(_, prop) { + if (prop === 'then') { + const value = queue.length > 0 ? queue.shift() : undefined; + const p = Promise.resolve(value); + return p.then.bind(p); + } + if (prop === 'catch') { + const p = Promise.resolve(undefined); + return p.catch.bind(p); + } + return () => proxy; + } + }; + const proxy: object = new Proxy({}, handler); + return proxy; +} + +const selectQueue: Queue = []; +const insertQueue: Queue = []; +const updateQueue: Queue = []; + +const txSelectQueue: Queue = []; +const txInsertQueue: Queue = []; +const txUpdateQueue: Queue = []; + +const mockAmbassadorFindFirst = vi.fn(); +const mockShopOrderFindFirst = vi.fn(); + +vi.mock('$lib/server/db', () => ({ + db: { + query: { + ambassadorPathway: { + findFirst: (...args: unknown[]) => mockAmbassadorFindFirst(...args) + }, + shopOrder: { + findFirst: (...args: unknown[]) => mockShopOrderFindFirst(...args) + } + }, + select: () => makeChain(selectQueue), + insert: () => makeChain(insertQueue), + update: () => makeChain(updateQueue), + transaction: async (cb: (tx: unknown) => Promise) => { + const tx = { + select: () => makeChain(txSelectQueue), + insert: () => makeChain(txInsertQueue), + update: () => makeChain(txUpdateQueue) + }; + return cb(tx); + } + } +})); + +// ---- external helper mocks -------------------------------------------------- + +const mockSelectPackaging = vi.fn(); +const mockFetchCheapestRate = vi.fn(); +const mockGetOrgIdForPathway = vi.fn(); +const mockCreateHcbTransfer = vi.fn(); +const mockResolveCountryCode = vi.fn(); + +vi.mock('$lib/server/packaging', () => ({ + selectPackaging: (...args: unknown[]) => mockSelectPackaging(...args) +})); +vi.mock('$lib/server/canada-post', () => ({ + fetchCheapestRate: (...args: unknown[]) => mockFetchCheapestRate(...args) +})); +vi.mock('$lib/server/hcb', () => ({ + getOrgIdForPathway: (...args: unknown[]) => mockGetOrgIdForPathway(...args), + createHcbTransfer: (...args: unknown[]) => mockCreateHcbTransfer(...args) +})); +vi.mock('$lib/server/countries', () => ({ + resolveCountryCode: (...args: unknown[]) => mockResolveCountryCode(...args) +})); + +const { actions } = await import('./+page.server'); + +// ---- helpers ---------------------------------------------------------------- + +function makeFormData(data: Record) { + return { + formData: async () => { + const fd = new FormData(); + for (const [k, v] of Object.entries(data)) fd.append(k, v); + return fd; + } + }; +} + +function makeEvent(opts: { + form: Record; + pathway?: string; + user?: { id: string } | null; +}) { + const { form, pathway = 'python', user = { id: 'amb-1' } } = opts; + return { + request: makeFormData(form), + params: { pathway }, + locals: { user } + } as any; +} + +const SAMPLE_ADDRESS = { + addressLine1: '15 Falls Rd', + addressLine2: '', + city: 'Shelburne', + stateProvince: 'VT', + country: 'United States', + zipPostalCode: '05482' +}; + +const SAMPLE_USER = { + id: 'user-1', + email: 'buyer@example.com', + firstName: 'Buyer', + lastName: 'Person' +}; + +const SAMPLE_PACKAGING = { + category: 'box' as const, + label: 'small box', + lengthIn: 6, + widthIn: 4, + heightIn: 2, + weightGrams: 200, + subjectToChange: false +}; + +function reset() { + selectQueue.length = 0; + insertQueue.length = 0; + updateQueue.length = 0; + txSelectQueue.length = 0; + txInsertQueue.length = 0; + txUpdateQueue.length = 0; + vi.clearAllMocks(); + mockGetOrgIdForPathway.mockReturnValue(null); // simulate no HCB linked + mockResolveCountryCode.mockReturnValue('US'); + mockSelectPackaging.mockReturnValue(SAMPLE_PACKAGING); + mockFetchCheapestRate.mockResolvedValue({ shippingCostUsd: 5, serviceName: 'Test Mail' }); +} + +beforeEach(reset); + +// ---- deny tests ------------------------------------------------------------- + +describe('deny action', () => { + it('marks the order as REJECTED with the provided reason', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue({ + id: 'order-1', + pathway: 'PYTHON', + item: null, + user: SAMPLE_USER + }); + // `db.update(shopOrder).set(...).where(...)` β€” pop one value (unused). + updateQueue.push(undefined); + + const event = makeEvent({ form: { id: 'order-1', note: 'spammy address' } }); + const result = await actions.deny(event); + + expect(result).toEqual({ success: true, orderId: 'order-1' }); + }); + + it('throws 403 when caller is not an ambassador for the pathway', async () => { + mockAmbassadorFindFirst.mockResolvedValue(undefined); + + const event = makeEvent({ form: { id: 'order-1', note: 'no' } }); + await expect(actions.deny(event)).rejects.toMatchObject({ status: 403 }); + }); + + it('throws 400 when input validation fails (missing required reason)', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + + const event = makeEvent({ form: { id: 'order-1' } }); + await expect(actions.deny(event)).rejects.toMatchObject({ status: 400 }); + }); + + it('redirects to login when not authenticated', async () => { + const event = makeEvent({ form: { id: 'order-1', note: 'x' }, user: null }); + await expect(actions.deny(event)).rejects.toMatchObject({ status: 302 }); + }); + + it('throws 404 for unknown pathway in URL', async () => { + const event = makeEvent({ form: { id: 'order-1', note: 'x' }, pathway: 'not_a_pathway' }); + await expect(actions.deny(event)).rejects.toMatchObject({ status: 404 }); + }); + + it('throws 400 when order id does not exist', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue(undefined); + + const event = makeEvent({ form: { id: 'missing', note: 'x' } }); + await expect(actions.deny(event)).rejects.toMatchObject({ status: 400 }); + }); +}); + +// ---- approve tests ---------------------------------------------------------- + +describe('approve action β€” CUSTOM items', () => { + it('marks the order FULFILLED without touching the warehouse', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue({ + id: 'order-1', + pathway: 'PYTHON', + item: { id: 'item-1', sourceType: 'CUSTOM', linkedWarehouseItemId: null, linkedWarehouseTemplateId: null }, + user: SAMPLE_USER, + shippingAddress: SAMPLE_ADDRESS + }); + // The CUSTOM branch wraps the shopOrder update in a transaction. + txUpdateQueue.push(undefined); + + const event = makeEvent({ form: { id: 'order-1', note: 'gifted manually' } }); + const result = await actions.approve(event); + + expect(result).toEqual({ success: true }); + expect(mockFetchCheapestRate).not.toHaveBeenCalled(); + expect(mockCreateHcbTransfer).not.toHaveBeenCalled(); + }); +}); + +describe('approve action β€” WAREHOUSE_ITEM', () => { + const baseOrder = { + id: 'order-2', + pathway: 'PYTHON', + item: { + id: 'shop-item-1', + sourceType: 'WAREHOUSE_ITEM', + linkedWarehouseItemId: 'wh-1', + linkedWarehouseTemplateId: null + }, + user: SAMPLE_USER, + shippingAddress: SAMPLE_ADDRESS, + phone: '555-0100' + }; + + it('creates a warehouse order and decrements stock when HCB is not linked', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue(baseOrder); + // Stock lookup: one warehouse item with plenty of stock. + selectQueue.push([ + { + id: 'wh-1', + name: 'Sticker', + quantity: 10, + costCents: 100, + lengthIn: 6, + widthIn: 4, + heightIn: 0.5, + weightGrams: 50, + packageType: 'flat' + } + ]); + // Inside transaction: warehouseOrder insert returns the new id, then + // per-line insert returns nothing, then the stock-decrement update + // must return a row to satisfy the "another order claimed it" check, + // then the shopOrder update is awaited. + txInsertQueue.push([{ id: 'wo-1' }]); // warehouseOrder insert + txInsertQueue.push(undefined); // warehouseOrderItem insert + txUpdateQueue.push([{ id: 'wh-1' }]); // decrement stock + txUpdateQueue.push(undefined); // shopOrder update + // After tx, billing branch: getOrgIdForPathway β†’ null (no HCB), so we + // hit `db.update(warehouseOrder).set({billingStatus: 'NOT_APPLICABLE'})`. + updateQueue.push(undefined); + + const event = makeEvent({ form: { id: 'order-2' } }); + const result = await actions.approve(event); + + expect(result).toEqual({ success: true, warehouseOrderId: 'wo-1' }); + expect(mockGetOrgIdForPathway).toHaveBeenCalledWith('PYTHON'); + expect(mockCreateHcbTransfer).not.toHaveBeenCalled(); + expect(mockFetchCheapestRate).toHaveBeenCalled(); + }); + + it('returns a 400 ActionFailure when stock is insufficient', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue(baseOrder); + // Stock lookup: not enough quantity (0 < 1). + selectQueue.push([ + { + id: 'wh-1', + name: 'Sticker', + quantity: 0, + costCents: 100, + lengthIn: 6, + widthIn: 4, + heightIn: 0.5, + weightGrams: 50, + packageType: 'flat' + } + ]); + + const event = makeEvent({ form: { id: 'order-2' } }); + const result = await actions.approve(event); + + // fail() returns an ActionFailure object, not a thrown error. + expect(result).toMatchObject({ + status: 400, + data: { error: expect.stringContaining('Insufficient stock') } + }); + }); + + it('errors when the shop item lost its warehouse link', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue({ + ...baseOrder, + item: { ...baseOrder.item, linkedWarehouseItemId: null } + }); + + const event = makeEvent({ form: { id: 'order-2' } }); + await expect(actions.approve(event)).rejects.toMatchObject({ status: 400 }); + }); +}); + +describe('approve action β€” WAREHOUSE_TEMPLATE', () => { + const baseOrder = { + id: 'order-3', + pathway: 'PYTHON', + item: { + id: 'shop-item-2', + sourceType: 'WAREHOUSE_TEMPLATE', + linkedWarehouseItemId: null, + linkedWarehouseTemplateId: 'tpl-1' + }, + user: SAMPLE_USER, + shippingAddress: SAMPLE_ADDRESS, + phone: null + }; + + it('expands the template into multiple line items and creates the warehouse order', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue(baseOrder); + // Template items lookup (`db.select().from(warehouseOrderTemplateItem)`). + selectQueue.push([ + { id: 'ti-1', templateId: 'tpl-1', warehouseItemId: 'wh-1', quantity: 2 }, + { id: 'ti-2', templateId: 'tpl-1', warehouseItemId: 'wh-2', quantity: 1 } + ]); + // Stock lookup for both warehouse items. + selectQueue.push([ + { + id: 'wh-1', name: 'Sticker', quantity: 50, + costCents: 100, lengthIn: 6, widthIn: 4, heightIn: 0.5, + weightGrams: 50, packageType: 'flat' + }, + { + id: 'wh-2', name: 'Pin', quantity: 30, + costCents: 250, lengthIn: 1, widthIn: 1, heightIn: 0.5, + weightGrams: 20, packageType: 'flat' + } + ]); + // Transaction queues: + txInsertQueue.push([{ id: 'wo-2' }]); // warehouseOrder + txInsertQueue.push(undefined); // warehouseOrderItem insert (wh-1) + txInsertQueue.push(undefined); // warehouseOrderItem insert (wh-2) + // Two stock decrement updates, then the shopOrder transition. + txUpdateQueue.push([{ id: 'wh-1' }]); + txUpdateQueue.push([{ id: 'wh-2' }]); + txUpdateQueue.push(undefined); // shopOrder update + // Post-tx billing branch: no HCB, so one update to mark NOT_APPLICABLE. + updateQueue.push(undefined); + + const event = makeEvent({ form: { id: 'order-3' } }); + const result = await actions.approve(event); + + expect(result).toEqual({ success: true, warehouseOrderId: 'wo-2' }); + // 1 wo + 2 line item inserts inside the tx. + expect(mockCreateHcbTransfer).not.toHaveBeenCalled(); + }); + + it('errors when the template has no items', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue(baseOrder); + selectQueue.push([]); // empty template + + const event = makeEvent({ form: { id: 'order-3' } }); + await expect(actions.approve(event)).rejects.toMatchObject({ status: 400 }); + }); +}); + +describe('approve action β€” auth & validation', () => { + it('redirects to login when not authenticated', async () => { + const event = makeEvent({ form: { id: 'order-1' }, user: null }); + await expect(actions.approve(event)).rejects.toMatchObject({ status: 302 }); + }); + + it('throws 403 when caller is not an ambassador', async () => { + mockAmbassadorFindFirst.mockResolvedValue(undefined); + const event = makeEvent({ form: { id: 'order-1' } }); + await expect(actions.approve(event)).rejects.toMatchObject({ status: 403 }); + }); + + it('throws 404 when pathway is not recognized', async () => { + const event = makeEvent({ form: { id: 'order-1' }, pathway: 'martian' }); + await expect(actions.approve(event)).rejects.toMatchObject({ status: 404 }); + }); + + it('throws 404 when the order id is not found', async () => { + mockAmbassadorFindFirst.mockResolvedValue({ id: 'ap-1' }); + mockShopOrderFindFirst.mockResolvedValue(undefined); + + const event = makeEvent({ form: { id: 'missing' } }); + await expect(actions.approve(event)).rejects.toMatchObject({ status: 404 }); + }); +}); diff --git a/resolution-frontend/src/routes/app/pathway/[pathway]/+page.svelte b/resolution-frontend/src/routes/app/pathway/[pathway]/+page.svelte index 6c794fa..52e11cd 100644 --- a/resolution-frontend/src/routes/app/pathway/[pathway]/+page.svelte +++ b/resolution-frontend/src/routes/app/pathway/[pathway]/+page.svelte @@ -90,6 +90,25 @@

brought to you by {data.curator}

+ + +
+ Visit the shop + Spend what you've earned on swag and goodies +
+ +
+
{#each weeks as week} {@const published = isWeekPublished(week)} @@ -172,6 +191,54 @@ font-weight: 600; } + .shop-link { + display: flex; + align-items: center; + gap: 1rem; + width: 100%; + max-width: 800px; + padding: 1rem 1.25rem; + margin-bottom: 2rem; + background: rgba(255, 255, 255, 0.85); + border: 2px solid #af98ff; + border-radius: 16px; + text-decoration: none; + color: #1a1a2e; + font-family: 'Kodchasan', sans-serif; + transition: transform 0.15s, border-color 0.15s; + } + + .shop-link:hover { + transform: translateY(-2px); + border-color: #33d6a6; + } + + .shop-icon { + width: 32px; + height: 32px; + } + + .shop-text { + display: flex; + flex-direction: column; + flex: 1; + } + + .shop-title { + font-weight: 600; + font-size: 1rem; + } + + .shop-sub { + font-size: 0.85rem; + color: #8492a6; + } + + .shop-chevron { + width: 20px; + height: 20px; + } + .weeks-grid { display: grid; grid-template-columns: repeat(4, 1fr); diff --git a/resolution-frontend/src/routes/app/pathway/[pathway]/shop/+page.server.ts b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/+page.server.ts new file mode 100644 index 0000000..dd633cc --- /dev/null +++ b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/+page.server.ts @@ -0,0 +1,210 @@ +import type { PageServerLoad, Actions } from './$types'; +import { db } from '$lib/server/db'; +import { + userPathway, + pathwayShop, + shopItem, + shopOrder, + transactionLedger +} from '$lib/server/db/schema'; +import { and, eq, sql, desc, or } from 'drizzle-orm'; +import { error, fail, redirect } from '@sveltejs/kit'; +import { PATHWAY_IDS, type PathwayId } from '$lib/pathways'; +import { z } from 'zod'; +import { addressSchema, validateFormData } from '$lib/server/validation'; +import { assertShopAccess, shopError } from '$lib/shop/utils' +import { guardAdminOrAmbassador } from '$lib/server/auth/guard'; + +const purchaseSchema = z.object({ + itemId: z.string().min(1), + userNotes: z.string().max(500).optional(), + shippingAddress: addressSchema.optional() // optional as user might not actually be buying a physical item, in which case i don't think we need it +}); + +const cancelSchema = z.object({ + orderId: z.string().min(1), // needs to be a valid string + cancelReason: z.string().min(1) +}); + +export const load: PageServerLoad = async ({ params, parent }) => { + const { user } = await parent(); + const { typedPathwayId, shop } = await assertShopAccess(user.id, params.pathway); + + const pathwayItems = await db + .select() + .from(shopItem) + .where(and(eq(shopItem.pathway, typedPathwayId), eq(shopItem.isActive, true))); // return all items minus inactive + + const [{ balance }] = await db + .select({ + balance: sql`COALESCE(SUM(${transactionLedger.amount}), 0)`.mapWith(Number) + }) + .from(transactionLedger) + .where(and( + eq(transactionLedger.userId, user.id), + eq(transactionLedger.pathway, typedPathwayId) + )); + + const recentOrders = await db + .select() + .from(shopOrder) + .where(and(eq(shopOrder.userId, user.id), eq(shopOrder.pathway, typedPathwayId))) + .orderBy(desc(shopOrder.createdAt)) + .limit(5); // link to a seperate orders page, so we only need a preview + + return { + pathwayId: typedPathwayId, + shop: { + isEnabled: shop.isEnabled, + currencyName: shop.currencyName, + currencyNamePlural: shop.currencyNamePlural + }, + items: pathwayItems, + balance, // this is the user bal btw just so we're clear + orders: recentOrders + }; +}; + +export const actions: Actions = { + // commented out as this should probably be in ./[id] + // purchase: async ({ request, params, locals }) => { + // if (!locals.user) throw redirect(302, '/api/auth/login'); + // const userId = locals.user.id; + + // const purchaseData = await validateFormData(purchaseSchema, request); + + // let orderId: string; + // try { + // orderId = await db.transaction(async (tx) => { + // const { typedPathwayId } = await assertShopAccess(userId, params.pathway, tx); + + // const [item] = await tx + // .select() + // .from(shopItem) + // .where(and( + // eq(shopItem.id, purchaseData.itemId), + // eq(shopItem.pathway, typedPathwayId), + // eq(shopItem.isActive, true) + // )) + // .limit(1); + + // if (!item) throw new ShopError(400, { message: 'Item not found' }); + + // if (item.itemType === 'PHYSICAL' && !purchaseData.shippingAddress) { + // throw new ShopError(400, { message: 'Shipping address required for physical items' }); + // } + + // const [{ balance }] = await tx + // .select({ + // balance: sql`COALESCE(SUM(${transactionLedger.amount}), 0)`.mapWith(Number) + // }) + // .from(transactionLedger) + // .where(and( + // eq(transactionLedger.userId, userId), + // eq(transactionLedger.pathway, typedPathwayId) + // )); + + // if (balance < item.price) { + // throw new ShopError(400, { message: 'Not enough currency' }); + // } + + // if (item.stock !== null) { + // if (item.stock <= 0) throw new ShopError(400, { message: 'No stock remaining' }); + // await tx.update(shopItem) + // .set({ stock: item.stock - 1 }) + // .where(eq(shopItem.id, item.id)); + // } + + // const [order] = await tx + // .insert(shopOrder) + // .values({ + // userId, + // pathway: typedPathwayId, + // totalAmount: item.price, + // item: item.id, + // itemPriceSnapshot: item.price, + // itemTypeSnapshot: item.itemType, + // itemNameSnapshot: item.name, + // shippingAddress: purchaseData.shippingAddress ?? null, + // userNotes: purchaseData.userNotes ?? null + // }) + // .returning({ id: shopOrder.id }); + + // await tx.insert(transactionLedger).values({ + // userId, + // pathway: typedPathwayId, + // amount: -item.price, + // reason: 'PURCHASE', + // refType: 'SHOP', + // refId: order.id // ← ties the ledger entry to the order + // }); + + // return order.id; + // }); + // } catch (e) { + // if (e instanceof ShopError) return fail(e.status, e.body); + // throw e; + // } + + // return { success: true, orderId }; + // }, + + cancel: async ({ request, params, locals }) => { + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + const cancelData = await validateFormData(cancelSchema, request); + + try { + await db.transaction(async (tx) => { + const { typedPathwayId } = await assertShopAccess(userId, params.pathway, tx); + + const [order] = await tx + .select() + .from(shopOrder) + .where(and( + eq(shopOrder.id, cancelData.orderId), + eq(shopOrder.userId, userId), + eq(shopOrder.pathway, typedPathwayId), + eq(shopOrder.status, 'PENDING') + )) + .limit(1); + + if (!order) throw new shopError(404, { message: 'No such order' }); + + await tx.update(shopOrder) + .set({ status: 'CANCELED', cancelledReason: cancelData.cancelReason }) + .where(eq(shopOrder.id, order.id)); + + // restore stock if the item still exists and tracks stock + if (order.item) { + const [item] = await tx + .select() + .from(shopItem) + .where(eq(shopItem.id, order.item)) + .limit(1); + if (item && item.stock !== null) { + await tx.update(shopItem) + .set({ stock: item.stock + 1 }) + .where(eq(shopItem.id, item.id)); + } + } + + // refund: positive ledger entry equal to what was originally charged + await tx.insert(transactionLedger).values({ + userId, + pathway: typedPathwayId, + amount: order.totalAmount, // amount that they paid + reason: 'REFUND', + refType: 'SHOP', + refId: order.id + }); + }); + } catch (e) { + if (e instanceof shopError) return fail(e.status, e.body); + throw e; + } + + return { success: true }; + } +}; diff --git a/resolution-frontend/src/routes/app/pathway/[pathway]/shop/+page.svelte b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/+page.svelte new file mode 100644 index 0000000..c05efd7 --- /dev/null +++ b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/+page.svelte @@ -0,0 +1,491 @@ + + + + {pathway?.label ?? 'Pathway'} Shop - Resolution + + + +
+ + Back + Back to {pathway?.label ?? 'pathway'} + +
+ + +
+

Items

+ {#if data.items.length === 0} +
+

No items in the shop yet. Check back soon!

+
+ {:else} +
+ {#each data.items as item, index (item.id)} + {#if index <= 3 || showAll} + {@const outOfStock = item.stock !== null && item.stock <= 0} + {@const cantAfford = data.balance < item.price} + +
+ {#if item.itemImageUrl} + {item.name} + {:else} +
No image
+ {/if} + {#if outOfStock} +
Out of stock
+ {/if} +
+
+
+

{item.name}

+
+

{item.description}

+
+ + {priceLabel(item.price)} + + {#if item.stock !== null && !outOfStock} + {item.stock} left + {/if} +
+
+
+ {/if} + {/each} +
+ {#if data.items.length > 3} + + {/if} + {/if} +
+ +
+

Recent orders

+ {#if data.orders.length === 0} +
+

You haven't placed any orders yet.

+
+ {:else} +
    + {#each data.orders as order (order.id)} +
  • +
    +
    {order.itemNameSnapshot}
    +
    + {new Date(order.createdAt).toLocaleDateString()} Β· + {priceLabel(order.totalAmount)} +
    +
    + + {statusLabel(order.status)} + +
  • + {/each} +
+ {/if} +
+
+
+
+ + diff --git a/resolution-frontend/src/routes/app/pathway/[pathway]/shop/[id]/+page.server.ts b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/[id]/+page.server.ts new file mode 100644 index 0000000..216eb97 --- /dev/null +++ b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/[id]/+page.server.ts @@ -0,0 +1,194 @@ +import type { PageServerLoad, Actions } from './$types'; +import { db } from '$lib/server/db'; +import { + userPathway, + pathwayShop, + shopItem, + shopOrder, + transactionLedger +} from '$lib/server/db/schema'; +import { and, eq, sql } from 'drizzle-orm'; +import { error, fail, redirect } from '@sveltejs/kit'; +import { PATHWAY_IDS, type PathwayId } from '$lib/pathways'; +import { z } from 'zod'; +import { addressSchema, validateFormData } from '$lib/server/validation'; + +// thrown inside transactions to abort + roll back; caught outside to convert to fail() +class ShopError extends Error { + constructor(public status: number, public body: { message: string }) { + super(body.message); + } +} + +// always collect a shipping address regardless of item type +const buySchema = z.object({ + userNotes: z.string().max(500).optional().default(''), + phone: z + .string() + .min(1, 'Phone number is required') + .max(30, 'Phone number is too long'), + ...addressSchema.shape +}); + +type DbOrTx = typeof db | Parameters[0]>[0]; + +async function assertShopAccess(userId: string, pathwayParam: string, conn: DbOrTx = db) { + const pathwayId = pathwayParam.toUpperCase(); + if (!PATHWAY_IDS.includes(pathwayId as PathwayId)) throw error(404, 'Pathway not found'); + const typedPathwayId = pathwayId as PathwayId; + + const membership = await conn + .select() + .from(userPathway) + .where(and(eq(userPathway.userId, userId), eq(userPathway.pathway, typedPathwayId))) + .limit(1); + if (membership.length === 0) throw redirect(302, '/app'); + + const pathwayShopRow = await conn + .select() + .from(pathwayShop) + .where(eq(pathwayShop.pathway, typedPathwayId)) + .limit(1); + if (pathwayShopRow.length === 0 || !pathwayShopRow[0].isEnabled) { + throw error(404); + } + + return { typedPathwayId, shop: pathwayShopRow[0] }; +} + +export const load: PageServerLoad = async ({ params, parent }) => { + const { user } = await parent(); + const { typedPathwayId, shop } = await assertShopAccess(user.id, params.pathway); + + const [item] = await db + .select() + .from(shopItem) + .where( + and( + eq(shopItem.id, params.id), + eq(shopItem.pathway, typedPathwayId), + eq(shopItem.isActive, true) + ) + ) + .limit(1); + + if (!item) throw error(404, 'Item not found'); + + const [{ balance }] = await db + .select({ + balance: sql`COALESCE(SUM(${transactionLedger.amount}), 0)`.mapWith(Number) + }) + .from(transactionLedger) + .where( + and(eq(transactionLedger.userId, user.id), eq(transactionLedger.pathway, typedPathwayId)) + ); + + return { + pathwayId: typedPathwayId, + shop: { + currencyName: shop.currencyName, + currencyNamePlural: shop.currencyNamePlural + }, + item, + balance, + user: { + firstName: user.firstName ?? '', + lastName: user.lastName ?? '', + email: user.email ?? '' + } + }; +}; + +export const actions = { + buy: async ({ request, params, locals }) => { + if (!locals.user) throw redirect(302, '/api/auth/login'); + const userId = locals.user.id; + + const buyData = await validateFormData(buySchema, request); + + const shippingAddress = { + addressLine1: buyData.addressLine1, + addressLine2: buyData.addressLine2, + city: buyData.city, + stateProvince: buyData.stateProvince, + country: buyData.country, + zipPostalCode: buyData.zipPostalCode + }; + + let orderId: string; + try { + orderId = await db.transaction(async (tx) => { + const { typedPathwayId } = await assertShopAccess(userId, params.pathway, tx); + + const [item] = await tx + .select() + .from(shopItem) + .where( + and( + eq(shopItem.id, params.id), + eq(shopItem.pathway, typedPathwayId), + eq(shopItem.isActive, true) + ) + ) + .limit(1); + + if (!item) throw new ShopError(404, { message: 'Item not found' }); + + const [{ balance }] = await tx + .select({ + balance: sql`COALESCE(SUM(${transactionLedger.amount}), 0)`.mapWith(Number) + }) + .from(transactionLedger) + .where( + and( + eq(transactionLedger.userId, userId), + eq(transactionLedger.pathway, typedPathwayId) + ) + ); + + if (balance < item.price) { + throw new ShopError(400, { message: 'Not enough currency' }); + } + + if (item.stock !== null) { + if (item.stock <= 0) throw new ShopError(400, { message: 'No stock remaining' }); + await tx + .update(shopItem) + .set({ stock: item.stock - 1 }) + .where(eq(shopItem.id, item.id)); + } + + const [order] = await tx + .insert(shopOrder) + .values({ + userId, + pathway: typedPathwayId, + totalAmount: item.price, + item: item.id, + itemPriceSnapshot: item.price, + itemNameSnapshot: item.name, + shippingAddress, + phone: buyData.phone, + userNotes: buyData.userNotes || null + }) + .returning({ id: shopOrder.id }); + + await tx.insert(transactionLedger).values({ + userId, + pathway: typedPathwayId, + amount: -item.price, + reason: 'PURCHASE', + refType: 'SHOP', + refId: order.id + }); + + return order.id; + }); + } catch (e) { + if (e instanceof ShopError) return fail(e.status, e.body); + throw e; + } + + return { success: true, orderId }; + } +} satisfies Actions; diff --git a/resolution-frontend/src/routes/app/pathway/[pathway]/shop/[id]/+page.svelte b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/[id]/+page.svelte new file mode 100644 index 0000000..19416f7 --- /dev/null +++ b/resolution-frontend/src/routes/app/pathway/[pathway]/shop/[id]/+page.svelte @@ -0,0 +1,453 @@ + + + + {data.item.name} - Shop - Resolution + + + +
+ + Back + Back to shop + + + {#if form?.success} +
+

Order placed!

+

+ Your order for {data.item.name} has been received. + We'll get it to you as soon as we can. +

+ + Back to shop + +
+ {:else} +
{ + isSubmitting = true; + return async ({ update }) => { + await update(); + isSubmitting = false; + }; + }}> +
+
+

Complete your order

+

{data.item.description}

+
+ + {#if form && !form.success && 'message' in form} +
{form.message}
+ {/if} + + {#if !canAfford} +
+ You don't have enough {data.shop.currencyNamePlural}. You need + {data.item.price - data.balance} more. +
+ {/if} + + {#if !inStock} +
This item is out of stock.
+ {/if} + +
+

Your details

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ +
+

Shipping address

+

Where should we send this?

+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+ +
+

Notes (optional)

+

Anything the fulfiller should know? (size, color, etc.)

+
+ +
+
+
+ +
+
+ {#if data.item.itemImageUrl} + {data.item.name} + {:else} +
No image
+ {/if} +
+ +
+
{data.item.name}
+
+ {data.item.price} {currencyLabel} +
+
+ You have {data.balance} {data.shop.currencyNamePlural} +
+
+ + +
+
+ {/if} +
+
+ +