@@ -104,49 +142,46 @@ function MessageThread({ readOnly }: { readOnly: boolean }) {
{messages.length === 0 ? (
-
-
{msg.text}
-
-
- {new Date(msg.timestamp).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" })}
-
- {msg.sender === "customer" && (
- msg.read
- ?
- :
- )}
+ messages.map((msg: ApiMessage) => {
+ const sender = msg.direction === "inbound" ? "customer" : "business";
+ return (
+
+
+ {msg.body &&
{msg.body}
}
+
+
+ {new Date(msg.createdAt).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" })}
+
+
-
- ))
+ );
+ })
+ )}
+ {hasMore && (
+
+
+
)}
- {!readOnly && (
-
-
setNewMessage(e.target.value)}
- onKeyDown={e => e.key === "Enter" && handleSend()}
- placeholder="Type a message..."
- className="flex-1 border border-stone-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-(--color-accent)/30 focus:border-(--color-accent)"
- />
-
+
+
+ Reply from your phone
- )}
+
);
}
@@ -176,10 +211,10 @@ function NotificationPreferences({ readOnly }: { readOnly: boolean }) {
const categories: { key: PrefKey; label: string; desc: string; icon: typeof Bell }[] = [
{ key: "appointmentReminders", label: "Appointment Reminders", desc: "Upcoming appointment notifications", icon: Bell },
- { key: "vaccinationAlerts", label: "Vaccination Alerts", desc: "Expiration and renewal reminders", icon: FileText },
- { key: "promotional", label: "Promotions & Offers", desc: "Deals and seasonal specials", icon: Megaphone },
- { key: "reportCards", label: "Report Cards", desc: "Grooming report card delivery", icon: FileText },
- { key: "invoiceReceipts", label: "Invoice & Receipts", desc: "Payment confirmations", icon: CreditCard },
+ { key: "vaccinationAlerts", label: "Vaccination Alerts", desc: "Expiration and renewal reminders", icon: Mail },
+ { key: "promotional", label: "Promotions & Offers", desc: "Deals and seasonal specials", icon: Smartphone },
+ { key: "reportCards", label: "Report Cards", desc: "Grooming report card delivery", icon: Mail },
+ { key: "invoiceReceipts", label: "Invoice & Receipts", desc: "Payment confirmations", icon: Bell },
];
const channels: { key: ChannelKey; label: string; icon: typeof Mail }[] = [
@@ -236,4 +271,4 @@ function NotificationPreferences({ readOnly }: { readOnly: boolean }) {
);
}
-export default Communication;
+export default Communication;
\ No newline at end of file
diff --git a/packages/db/migrations/0031_steady_veda.sql b/packages/db/migrations/0031_steady_veda.sql
new file mode 100644
index 0000000..a636215
--- /dev/null
+++ b/packages/db/migrations/0031_steady_veda.sql
@@ -0,0 +1,356 @@
+CREATE TYPE "public"."client_status" AS ENUM('active', 'disabled');--> statement-breakpoint
+CREATE TYPE "public"."coat_type" AS ENUM('smooth', 'double', 'curly', 'wire', 'long', 'hairless');--> statement-breakpoint
+CREATE TYPE "public"."impersonation_session_status" AS ENUM('active', 'ended', 'expired');--> statement-breakpoint
+CREATE TYPE "public"."invoice_status" AS ENUM('draft', 'pending', 'paid', 'void');--> statement-breakpoint
+CREATE TYPE "public"."message_consent_kind" AS ENUM('opt_in', 'opt_out', 'help');--> statement-breakpoint
+CREATE TYPE "public"."message_direction" AS ENUM('inbound', 'outbound');--> statement-breakpoint
+CREATE TYPE "public"."message_status" AS ENUM('queued', 'sent', 'delivered', 'failed', 'received');--> statement-breakpoint
+CREATE TYPE "public"."messaging_channel" AS ENUM('sms', 'mms');--> statement-breakpoint
+CREATE TYPE "public"."payment_method" AS ENUM('cash', 'card', 'check', 'other');--> statement-breakpoint
+CREATE TYPE "public"."pet_size_category" AS ENUM('small', 'medium', 'large', 'xlarge');--> statement-breakpoint
+CREATE TYPE "public"."waitlist_status" AS ENUM('active', 'notified', 'expired', 'cancelled');--> statement-breakpoint
+CREATE TABLE "account" (
+ "id" text PRIMARY KEY NOT NULL,
+ "account_id" text NOT NULL,
+ "provider_id" text NOT NULL,
+ "user_id" text NOT NULL,
+ "access_token" text,
+ "refresh_token" text,
+ "id_token" text,
+ "access_token_expires_at" timestamp,
+ "refresh_token_expires_at" timestamp,
+ "scope" text,
+ "password" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "appointment_groups" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "client_id" uuid NOT NULL,
+ "notes" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "auth_provider_config" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "provider_id" text NOT NULL,
+ "display_name" text NOT NULL,
+ "issuer_url" text NOT NULL,
+ "internal_base_url" text,
+ "client_id" text NOT NULL,
+ "client_secret" text NOT NULL,
+ "scopes" text DEFAULT 'openid profile email' NOT NULL,
+ "enabled" boolean DEFAULT true NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "auth_provider_config_provider_id_unique" UNIQUE("provider_id")
+);
+--> statement-breakpoint
+CREATE TABLE "buffer_time_rules" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "service_id" uuid NOT NULL,
+ "size_category" "pet_size_category",
+ "coat_type" "coat_type",
+ "buffer_minutes" integer NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "buffer_time_rules_service_id_size_category_coat_type_unique" UNIQUE("service_id","size_category","coat_type")
+);
+--> statement-breakpoint
+CREATE TABLE "business_settings" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "business_name" text DEFAULT 'GroomBook' NOT NULL,
+ "logo_base64" text,
+ "logo_mime_type" text,
+ "logo_key" text,
+ "primary_color" text DEFAULT '#4f8a6f' NOT NULL,
+ "accent_color" text DEFAULT '#8b7355' NOT NULL,
+ "messaging_phone_number" text,
+ "telnyx_messaging_profile_id" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "conversations" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "business_id" uuid NOT NULL,
+ "client_id" uuid NOT NULL,
+ "channel" "messaging_channel" NOT NULL,
+ "external_number" text NOT NULL,
+ "business_number" text NOT NULL,
+ "last_message_at" timestamp,
+ "status" text DEFAULT 'active' NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "uq_conversations_business_client_number" UNIQUE("business_id","client_id","business_number")
+);
+--> statement-breakpoint
+CREATE TABLE "grooming_visit_logs" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "pet_id" uuid NOT NULL,
+ "appointment_id" uuid,
+ "staff_id" uuid,
+ "cut_style" text,
+ "products_used" text,
+ "notes" text,
+ "groomed_at" timestamp DEFAULT now() NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "impersonation_audit_logs" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "session_id" uuid NOT NULL,
+ "action" text NOT NULL,
+ "page_visited" text,
+ "metadata" jsonb,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "impersonation_sessions" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "staff_id" uuid NOT NULL,
+ "client_id" uuid NOT NULL,
+ "reason" text,
+ "status" "impersonation_session_status" DEFAULT 'active' NOT NULL,
+ "started_at" timestamp DEFAULT now() NOT NULL,
+ "ended_at" timestamp,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "invoice_line_items" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "invoice_id" uuid NOT NULL,
+ "description" text NOT NULL,
+ "quantity" integer DEFAULT 1 NOT NULL,
+ "unit_price_cents" integer NOT NULL,
+ "total_cents" integer NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "invoice_tip_splits" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "invoice_id" uuid NOT NULL,
+ "staff_id" uuid,
+ "staff_name" text NOT NULL,
+ "share_pct" numeric(5, 2) NOT NULL,
+ "share_cents" integer NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "invoices" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "appointment_id" uuid,
+ "client_id" uuid NOT NULL,
+ "subtotal_cents" integer NOT NULL,
+ "tax_cents" integer DEFAULT 0 NOT NULL,
+ "tip_cents" integer DEFAULT 0 NOT NULL,
+ "total_cents" integer NOT NULL,
+ "status" "invoice_status" DEFAULT 'draft' NOT NULL,
+ "payment_method" "payment_method",
+ "paid_at" timestamp,
+ "stripe_payment_intent_id" text,
+ "stripe_refund_id" text,
+ "payment_failure_reason" text,
+ "notes" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "message_attachments" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "message_id" uuid NOT NULL,
+ "content_type" text NOT NULL,
+ "url" text NOT NULL,
+ "size" integer NOT NULL,
+ "provider_media_id" text
+);
+--> statement-breakpoint
+CREATE TABLE "message_consent_events" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "client_id" uuid NOT NULL,
+ "business_id" uuid NOT NULL,
+ "kind" "message_consent_kind" NOT NULL,
+ "source" text,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "messages" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "conversation_id" uuid NOT NULL,
+ "direction" "message_direction" NOT NULL,
+ "body" text,
+ "status" "message_status" DEFAULT 'queued' NOT NULL,
+ "provider_message_id" text,
+ "error_code" text,
+ "error_message" text,
+ "sent_by_staff_id" uuid,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "delivered_at" timestamp,
+ "read_by_client_at" timestamp,
+ CONSTRAINT "uq_messages_provider_message_id" UNIQUE("provider_message_id")
+);
+--> statement-breakpoint
+CREATE TABLE "recurring_series" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "frequency_weeks" integer NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "refunds" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "invoice_id" uuid NOT NULL,
+ "stripe_refund_id" text NOT NULL,
+ "idempotency_key" text,
+ "amount_cents" integer,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "refunds_idempotency_key_unique" UNIQUE("idempotency_key")
+);
+--> statement-breakpoint
+CREATE TABLE "reminder_logs" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "appointment_id" uuid NOT NULL,
+ "reminder_type" text NOT NULL,
+ "channel" text DEFAULT 'email' NOT NULL,
+ "sent_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "reminder_logs_appointment_id_reminder_type_channel_unique" UNIQUE("appointment_id","reminder_type","channel")
+);
+--> statement-breakpoint
+CREATE TABLE "session" (
+ "id" text PRIMARY KEY NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "token" text NOT NULL,
+ "ip_address" text,
+ "user_agent" text,
+ "user_id" text NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "session_token_unique" UNIQUE("token")
+);
+--> statement-breakpoint
+CREATE TABLE "user" (
+ "id" text PRIMARY KEY NOT NULL,
+ "name" text NOT NULL,
+ "email" text NOT NULL,
+ "email_verified" boolean DEFAULT false NOT NULL,
+ "image" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT "user_email_unique" UNIQUE("email")
+);
+--> statement-breakpoint
+CREATE TABLE "verification" (
+ "id" text PRIMARY KEY NOT NULL,
+ "identifier" text NOT NULL,
+ "value" text NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "waitlist_entries" (
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "client_id" uuid NOT NULL,
+ "pet_id" uuid NOT NULL,
+ "service_id" uuid NOT NULL,
+ "preferred_date" text NOT NULL,
+ "preferred_time" text NOT NULL,
+ "status" "waitlist_status" DEFAULT 'active' NOT NULL,
+ "notified_at" timestamp,
+ "expires_at" timestamp,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+ALTER TABLE "clients" ALTER COLUMN "email" SET NOT NULL;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "bather_staff_id" uuid;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "series_id" uuid;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "series_index" integer;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "group_id" uuid;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "confirmation_status" text DEFAULT 'pending' NOT NULL;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "confirmed_at" timestamp;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "cancelled_at" timestamp;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "buffer_minutes" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "confirmation_token" text;--> statement-breakpoint
+ALTER TABLE "appointments" ADD COLUMN "customer_notes" text;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "email_opt_out" boolean DEFAULT false NOT NULL;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "sms_opt_in" boolean DEFAULT false NOT NULL;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "sms_consent_date" timestamp;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "sms_opt_out_date" timestamp;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "sms_consent_text" text;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "stripe_customer_id" text;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "status" "client_status" DEFAULT 'active' NOT NULL;--> statement-breakpoint
+ALTER TABLE "clients" ADD COLUMN "disabled_at" timestamp;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "health_alerts" text;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "cut_style" text;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "shampoo_preference" text;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "special_care_notes" text;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "custom_fields" jsonb DEFAULT '{}'::jsonb NOT NULL;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "photo_key" text;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "photo_uploaded_at" timestamp;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "image" text;--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "size_category" "pet_size_category";--> statement-breakpoint
+ALTER TABLE "pets" ADD COLUMN "coat_type" "coat_type";--> statement-breakpoint
+ALTER TABLE "services" ADD COLUMN "default_buffer_minutes" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
+ALTER TABLE "staff" ADD COLUMN "user_id" text;--> statement-breakpoint
+ALTER TABLE "staff" ADD COLUMN "is_super_user" boolean DEFAULT false NOT NULL;--> statement-breakpoint
+ALTER TABLE "staff" ADD COLUMN "ical_token" text;--> statement-breakpoint
+ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "appointment_groups" ADD CONSTRAINT "appointment_groups_client_id_clients_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."clients"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "buffer_time_rules" ADD CONSTRAINT "buffer_time_rules_service_id_services_id_fk" FOREIGN KEY ("service_id") REFERENCES "public"."services"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "conversations" ADD CONSTRAINT "conversations_client_id_clients_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "grooming_visit_logs" ADD CONSTRAINT "grooming_visit_logs_pet_id_pets_id_fk" FOREIGN KEY ("pet_id") REFERENCES "public"."pets"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "grooming_visit_logs" ADD CONSTRAINT "grooming_visit_logs_appointment_id_appointments_id_fk" FOREIGN KEY ("appointment_id") REFERENCES "public"."appointments"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "grooming_visit_logs" ADD CONSTRAINT "grooming_visit_logs_staff_id_staff_id_fk" FOREIGN KEY ("staff_id") REFERENCES "public"."staff"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "impersonation_audit_logs" ADD CONSTRAINT "impersonation_audit_logs_session_id_impersonation_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."impersonation_sessions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "impersonation_sessions" ADD CONSTRAINT "impersonation_sessions_staff_id_staff_id_fk" FOREIGN KEY ("staff_id") REFERENCES "public"."staff"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "impersonation_sessions" ADD CONSTRAINT "impersonation_sessions_client_id_clients_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."clients"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "invoice_line_items" ADD CONSTRAINT "invoice_line_items_invoice_id_invoices_id_fk" FOREIGN KEY ("invoice_id") REFERENCES "public"."invoices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "invoice_tip_splits" ADD CONSTRAINT "invoice_tip_splits_invoice_id_invoices_id_fk" FOREIGN KEY ("invoice_id") REFERENCES "public"."invoices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "invoice_tip_splits" ADD CONSTRAINT "invoice_tip_splits_staff_id_staff_id_fk" FOREIGN KEY ("staff_id") REFERENCES "public"."staff"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "invoices" ADD CONSTRAINT "invoices_appointment_id_appointments_id_fk" FOREIGN KEY ("appointment_id") REFERENCES "public"."appointments"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "invoices" ADD CONSTRAINT "invoices_client_id_clients_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."clients"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "message_attachments" ADD CONSTRAINT "message_attachments_message_id_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "message_consent_events" ADD CONSTRAINT "message_consent_events_client_id_clients_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "messages" ADD CONSTRAINT "messages_conversation_id_conversations_id_fk" FOREIGN KEY ("conversation_id") REFERENCES "public"."conversations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "messages" ADD CONSTRAINT "messages_sent_by_staff_id_staff_id_fk" FOREIGN KEY ("sent_by_staff_id") REFERENCES "public"."staff"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "refunds" ADD CONSTRAINT "refunds_invoice_id_invoices_id_fk" FOREIGN KEY ("invoice_id") REFERENCES "public"."invoices"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "reminder_logs" ADD CONSTRAINT "reminder_logs_appointment_id_appointments_id_fk" FOREIGN KEY ("appointment_id") REFERENCES "public"."appointments"("id") ON DELETE cascade 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 "waitlist_entries" ADD CONSTRAINT "waitlist_entries_client_id_clients_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "waitlist_entries" ADD CONSTRAINT "waitlist_entries_pet_id_pets_id_fk" FOREIGN KEY ("pet_id") REFERENCES "public"."pets"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "waitlist_entries" ADD CONSTRAINT "waitlist_entries_service_id_services_id_fk" FOREIGN KEY ("service_id") REFERENCES "public"."services"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "idx_buffer_rules_service_id" ON "buffer_time_rules" USING btree ("service_id");--> statement-breakpoint
+CREATE INDEX "idx_conversations_business_id_last_message_at" ON "conversations" USING btree ("business_id","last_message_at" DESC NULLS LAST);--> statement-breakpoint
+CREATE INDEX "impersonation_audit_logs_session_id_idx" ON "impersonation_audit_logs" USING btree ("session_id");--> statement-breakpoint
+CREATE INDEX "impersonation_sessions_staff_id_status_idx" ON "impersonation_sessions" USING btree ("staff_id","status");--> statement-breakpoint
+CREATE INDEX "impersonation_sessions_client_id_idx" ON "impersonation_sessions" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "idx_invoice_line_items_invoice_id" ON "invoice_line_items" USING btree ("invoice_id");--> statement-breakpoint
+CREATE INDEX "idx_invoice_tip_splits_invoice_id" ON "invoice_tip_splits" USING btree ("invoice_id");--> statement-breakpoint
+CREATE INDEX "idx_invoices_client_id" ON "invoices" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "idx_invoices_status" ON "invoices" USING btree ("status");--> statement-breakpoint
+CREATE INDEX "idx_invoices_created_at" ON "invoices" USING btree ("created_at");--> statement-breakpoint
+CREATE INDEX "idx_invoices_stripe_payment_intent_id" ON "invoices" USING btree ("stripe_payment_intent_id");--> statement-breakpoint
+CREATE INDEX "idx_message_attachments_message_id" ON "message_attachments" USING btree ("message_id");--> statement-breakpoint
+CREATE INDEX "idx_message_consent_events_client_id" ON "message_consent_events" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "idx_messages_conversation_id_created_at" ON "messages" USING btree ("conversation_id","created_at" DESC NULLS LAST);--> statement-breakpoint
+CREATE INDEX "idx_refunds_invoice_id" ON "refunds" USING btree ("invoice_id");--> statement-breakpoint
+CREATE INDEX "idx_refunds_idempotency_key" ON "refunds" USING btree ("idempotency_key");--> statement-breakpoint
+CREATE INDEX "idx_waitlist_client_id" ON "waitlist_entries" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "idx_waitlist_preferred_date" ON "waitlist_entries" USING btree ("preferred_date");--> statement-breakpoint
+CREATE INDEX "idx_waitlist_status" ON "waitlist_entries" USING btree ("status");--> statement-breakpoint
+ALTER TABLE "appointments" ADD CONSTRAINT "appointments_bather_staff_id_staff_id_fk" FOREIGN KEY ("bather_staff_id") REFERENCES "public"."staff"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "appointments" ADD CONSTRAINT "appointments_series_id_recurring_series_id_fk" FOREIGN KEY ("series_id") REFERENCES "public"."recurring_series"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "appointments" ADD CONSTRAINT "appointments_group_id_appointment_groups_id_fk" FOREIGN KEY ("group_id") REFERENCES "public"."appointment_groups"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "staff" ADD CONSTRAINT "staff_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "idx_appointments_client_id" ON "appointments" USING btree ("client_id");--> statement-breakpoint
+CREATE INDEX "idx_appointments_staff_id" ON "appointments" USING btree ("staff_id");--> statement-breakpoint
+CREATE INDEX "idx_appointments_start_time" ON "appointments" USING btree ("start_time");--> statement-breakpoint
+CREATE INDEX "idx_appointments_status" ON "appointments" USING btree ("status");--> statement-breakpoint
+CREATE INDEX "idx_clients_email" ON "clients" USING btree ("email");--> statement-breakpoint
+CREATE INDEX "idx_pets_client_id" ON "pets" USING btree ("client_id");--> statement-breakpoint
+ALTER TABLE "appointments" ADD CONSTRAINT "appointments_confirmation_token_unique" UNIQUE("confirmation_token");--> statement-breakpoint
+ALTER TABLE "services" ADD CONSTRAINT "services_name_unique" UNIQUE("name");--> statement-breakpoint
+ALTER TABLE "staff" ADD CONSTRAINT "staff_ical_token_unique" UNIQUE("ical_token");
\ No newline at end of file
diff --git a/packages/db/migrations/0032_add_staff_read_at.sql b/packages/db/migrations/0032_add_staff_read_at.sql
new file mode 100644
index 0000000..8c525a9
--- /dev/null
+++ b/packages/db/migrations/0032_add_staff_read_at.sql
@@ -0,0 +1,4 @@
+-- Add staffReadAt column to conversations for unread tracking
+ALTER TABLE "conversations" ADD COLUMN "staff_read_at" timestamp;
+
+CREATE INDEX "idx_conversations_business_id_staff_read_at" ON "conversations"("business_id", "staff_read_at" DESC);
diff --git a/packages/db/migrations/meta/0011_snapshot.json b/packages/db/migrations/meta/0011_snapshot.json
deleted file mode 100644
index 2d20d90..0000000
--- a/packages/db/migrations/meta/0011_snapshot.json
+++ /dev/null
@@ -1,1468 +0,0 @@
-{
- "id": "db89d732-7cd5-414e-848b-7f113dcd94c1",
- "prevId": "477cddf9-970f-41c5-9cad-c1ed48c2bedf",
- "version": "7",
- "dialect": "postgresql",
- "tables": {
- "public.appointment_groups": {
- "name": "appointment_groups",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "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": {
- "appointment_groups_client_id_clients_id_fk": {
- "name": "appointment_groups_client_id_clients_id_fk",
- "tableFrom": "appointment_groups",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointments": {
- "name": "appointments",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "service_id": {
- "name": "service_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "bather_staff_id": {
- "name": "bather_staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "status": {
- "name": "status",
- "type": "appointment_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'scheduled'"
- },
- "start_time": {
- "name": "start_time",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "end_time": {
- "name": "end_time",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "price_cents": {
- "name": "price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": false
- },
- "series_id": {
- "name": "series_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "series_index": {
- "name": "series_index",
- "type": "integer",
- "primaryKey": false,
- "notNull": false
- },
- "group_id": {
- "name": "group_id",
- "type": "uuid",
- "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": {
- "appointments_client_id_clients_id_fk": {
- "name": "appointments_client_id_clients_id_fk",
- "tableFrom": "appointments",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_pet_id_pets_id_fk": {
- "name": "appointments_pet_id_pets_id_fk",
- "tableFrom": "appointments",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_service_id_services_id_fk": {
- "name": "appointments_service_id_services_id_fk",
- "tableFrom": "appointments",
- "tableTo": "services",
- "columnsFrom": [
- "service_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_staff_id_staff_id_fk": {
- "name": "appointments_staff_id_staff_id_fk",
- "tableFrom": "appointments",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_bather_staff_id_staff_id_fk": {
- "name": "appointments_bather_staff_id_staff_id_fk",
- "tableFrom": "appointments",
- "tableTo": "staff",
- "columnsFrom": [
- "bather_staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_series_id_recurring_series_id_fk": {
- "name": "appointments_series_id_recurring_series_id_fk",
- "tableFrom": "appointments",
- "tableTo": "recurring_series",
- "columnsFrom": [
- "series_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_group_id_appointment_groups_id_fk": {
- "name": "appointments_group_id_appointment_groups_id_fk",
- "tableFrom": "appointments",
- "tableTo": "appointment_groups",
- "columnsFrom": [
- "group_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.business_settings": {
- "name": "business_settings",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "business_name": {
- "name": "business_name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'GroomBook'"
- },
- "logo_base64": {
- "name": "logo_base64",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "logo_mime_type": {
- "name": "logo_mime_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "primary_color": {
- "name": "primary_color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'#4f8a6f'"
- },
- "accent_color": {
- "name": "accent_color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'#8b7355'"
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.clients": {
- "name": "clients",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "phone": {
- "name": "phone",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "address": {
- "name": "address",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "email_opt_out": {
- "name": "email_opt_out",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "status": {
- "name": "status",
- "type": "client_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "disabled_at": {
- "name": "disabled_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": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.grooming_visit_logs": {
- "name": "grooming_visit_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "cut_style": {
- "name": "cut_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "products_used": {
- "name": "products_used",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "groomed_at": {
- "name": "groomed_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "grooming_visit_logs_pet_id_pets_id_fk": {
- "name": "grooming_visit_logs_pet_id_pets_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "grooming_visit_logs_appointment_id_appointments_id_fk": {
- "name": "grooming_visit_logs_appointment_id_appointments_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "grooming_visit_logs_staff_id_staff_id_fk": {
- "name": "grooming_visit_logs_staff_id_staff_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_audit_logs": {
- "name": "impersonation_audit_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "session_id": {
- "name": "session_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "action": {
- "name": "action",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "page_visited": {
- "name": "page_visited",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "metadata": {
- "name": "metadata",
- "type": "jsonb",
- "primaryKey": false,
- "notNull": false
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {
- "impersonation_audit_logs_session_id_idx": {
- "name": "impersonation_audit_logs_session_id_idx",
- "columns": [
- {
- "expression": "session_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "impersonation_audit_logs_session_id_impersonation_sessions_id_fk": {
- "name": "impersonation_audit_logs_session_id_impersonation_sessions_id_fk",
- "tableFrom": "impersonation_audit_logs",
- "tableTo": "impersonation_sessions",
- "columnsFrom": [
- "session_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_sessions": {
- "name": "impersonation_sessions",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "reason": {
- "name": "reason",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "status": {
- "name": "status",
- "type": "impersonation_session_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "started_at": {
- "name": "started_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- },
- "ended_at": {
- "name": "ended_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {
- "impersonation_sessions_staff_id_status_idx": {
- "name": "impersonation_sessions_staff_id_status_idx",
- "columns": [
- {
- "expression": "staff_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- },
- {
- "expression": "status",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "impersonation_sessions_client_id_idx": {
- "name": "impersonation_sessions_client_id_idx",
- "columns": [
- {
- "expression": "client_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "impersonation_sessions_staff_id_staff_id_fk": {
- "name": "impersonation_sessions_staff_id_staff_id_fk",
- "tableFrom": "impersonation_sessions",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "impersonation_sessions_client_id_clients_id_fk": {
- "name": "impersonation_sessions_client_id_clients_id_fk",
- "tableFrom": "impersonation_sessions",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_line_items": {
- "name": "invoice_line_items",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "invoice_id": {
- "name": "invoice_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "quantity": {
- "name": "quantity",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 1
- },
- "unit_price_cents": {
- "name": "unit_price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "total_cents": {
- "name": "total_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_line_items_invoice_id_invoices_id_fk": {
- "name": "invoice_line_items_invoice_id_invoices_id_fk",
- "tableFrom": "invoice_line_items",
- "tableTo": "invoices",
- "columnsFrom": [
- "invoice_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_tip_splits": {
- "name": "invoice_tip_splits",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "invoice_id": {
- "name": "invoice_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "staff_name": {
- "name": "staff_name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "share_pct": {
- "name": "share_pct",
- "type": "numeric(5, 2)",
- "primaryKey": false,
- "notNull": true
- },
- "share_cents": {
- "name": "share_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_tip_splits_invoice_id_invoices_id_fk": {
- "name": "invoice_tip_splits_invoice_id_invoices_id_fk",
- "tableFrom": "invoice_tip_splits",
- "tableTo": "invoices",
- "columnsFrom": [
- "invoice_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "invoice_tip_splits_staff_id_staff_id_fk": {
- "name": "invoice_tip_splits_staff_id_staff_id_fk",
- "tableFrom": "invoice_tip_splits",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoices": {
- "name": "invoices",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "subtotal_cents": {
- "name": "subtotal_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "tax_cents": {
- "name": "tax_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 0
- },
- "tip_cents": {
- "name": "tip_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 0
- },
- "total_cents": {
- "name": "total_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "status": {
- "name": "status",
- "type": "invoice_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'draft'"
- },
- "payment_method": {
- "name": "payment_method",
- "type": "payment_method",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": false
- },
- "paid_at": {
- "name": "paid_at",
- "type": "timestamp",
- "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": {
- "invoices_appointment_id_appointments_id_fk": {
- "name": "invoices_appointment_id_appointments_id_fk",
- "tableFrom": "invoices",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "invoices_client_id_clients_id_fk": {
- "name": "invoices_client_id_clients_id_fk",
- "tableFrom": "invoices",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.pets": {
- "name": "pets",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "species": {
- "name": "species",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "breed": {
- "name": "breed",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "weight_kg": {
- "name": "weight_kg",
- "type": "numeric(5, 2)",
- "primaryKey": false,
- "notNull": false
- },
- "date_of_birth": {
- "name": "date_of_birth",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "health_alerts": {
- "name": "health_alerts",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "grooming_notes": {
- "name": "grooming_notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "cut_style": {
- "name": "cut_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "shampoo_preference": {
- "name": "shampoo_preference",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "special_care_notes": {
- "name": "special_care_notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "custom_fields": {
- "name": "custom_fields",
- "type": "jsonb",
- "primaryKey": false,
- "notNull": true,
- "default": "'{}'::jsonb"
- },
- "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": {
- "pets_client_id_clients_id_fk": {
- "name": "pets_client_id_clients_id_fk",
- "tableFrom": "pets",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.recurring_series": {
- "name": "recurring_series",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "frequency_weeks": {
- "name": "frequency_weeks",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.reminder_logs": {
- "name": "reminder_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "reminder_type": {
- "name": "reminder_type",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "sent_at": {
- "name": "sent_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "reminder_logs_appointment_id_appointments_id_fk": {
- "name": "reminder_logs_appointment_id_appointments_id_fk",
- "tableFrom": "reminder_logs",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "reminder_logs_appointment_id_reminder_type_unique": {
- "name": "reminder_logs_appointment_id_reminder_type_unique",
- "nullsNotDistinct": false,
- "columns": [
- "appointment_id",
- "reminder_type"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.services": {
- "name": "services",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "base_price_cents": {
- "name": "base_price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "duration_minutes": {
- "name": "duration_minutes",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "active": {
- "name": "active",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": true
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.staff": {
- "name": "staff",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "oidc_sub": {
- "name": "oidc_sub",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "role": {
- "name": "role",
- "type": "staff_role",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'groomer'"
- },
- "active": {
- "name": "active",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": true
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "staff_email_unique": {
- "name": "staff_email_unique",
- "nullsNotDistinct": false,
- "columns": [
- "email"
- ]
- },
- "staff_oidc_sub_unique": {
- "name": "staff_oidc_sub_unique",
- "nullsNotDistinct": false,
- "columns": [
- "oidc_sub"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- }
- },
- "enums": {
- "public.appointment_status": {
- "name": "appointment_status",
- "schema": "public",
- "values": [
- "scheduled",
- "confirmed",
- "in_progress",
- "completed",
- "cancelled",
- "no_show"
- ]
- },
- "public.client_status": {
- "name": "client_status",
- "schema": "public",
- "values": [
- "active",
- "disabled"
- ]
- },
- "public.impersonation_session_status": {
- "name": "impersonation_session_status",
- "schema": "public",
- "values": [
- "active",
- "ended",
- "expired"
- ]
- },
- "public.invoice_status": {
- "name": "invoice_status",
- "schema": "public",
- "values": [
- "draft",
- "pending",
- "paid",
- "void"
- ]
- },
- "public.payment_method": {
- "name": "payment_method",
- "schema": "public",
- "values": [
- "cash",
- "card",
- "check",
- "other"
- ]
- },
- "public.staff_role": {
- "name": "staff_role",
- "schema": "public",
- "values": [
- "groomer",
- "receptionist",
- "manager"
- ]
- }
- },
- "schemas": {},
- "sequences": {},
- "roles": {},
- "policies": {},
- "views": {},
- "_meta": {
- "columns": {},
- "schemas": {},
- "tables": {}
- }
-}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0019_snapshot.json b/packages/db/migrations/meta/0019_snapshot.json
deleted file mode 100644
index 1a65df3..0000000
--- a/packages/db/migrations/meta/0019_snapshot.json
+++ /dev/null
@@ -1,2048 +0,0 @@
-{
- "id": "b3a381ca-f7a4-450f-aa7e-fdc2d652dc97",
- "prevId": "db89d732-7cd5-414e-848b-7f113dcd94c1",
- "version": "7",
- "dialect": "postgresql",
- "tables": {
- "public.account": {
- "name": "account",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "account_id": {
- "name": "account_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "provider_id": {
- "name": "provider_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "access_token": {
- "name": "access_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "refresh_token": {
- "name": "refresh_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "id_token": {
- "name": "id_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "access_token_expires_at": {
- "name": "access_token_expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "refresh_token_expires_at": {
- "name": "refresh_token_expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "scope": {
- "name": "scope",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "password": {
- "name": "password",
- "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": {
- "account_user_id_user_id_fk": {
- "name": "account_user_id_user_id_fk",
- "tableFrom": "account",
- "tableTo": "user",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointment_groups": {
- "name": "appointment_groups",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "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": {
- "appointment_groups_client_id_clients_id_fk": {
- "name": "appointment_groups_client_id_clients_id_fk",
- "tableFrom": "appointment_groups",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointments": {
- "name": "appointments",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "service_id": {
- "name": "service_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "bather_staff_id": {
- "name": "bather_staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "status": {
- "name": "status",
- "type": "appointment_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'scheduled'"
- },
- "start_time": {
- "name": "start_time",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "end_time": {
- "name": "end_time",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "price_cents": {
- "name": "price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": false
- },
- "series_id": {
- "name": "series_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "series_index": {
- "name": "series_index",
- "type": "integer",
- "primaryKey": false,
- "notNull": false
- },
- "group_id": {
- "name": "group_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "confirmation_status": {
- "name": "confirmation_status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'pending'"
- },
- "confirmed_at": {
- "name": "confirmed_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "cancelled_at": {
- "name": "cancelled_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "confirmation_token": {
- "name": "confirmation_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "customer_notes": {
- "name": "customer_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": {
- "appointments_client_id_clients_id_fk": {
- "name": "appointments_client_id_clients_id_fk",
- "tableFrom": "appointments",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_pet_id_pets_id_fk": {
- "name": "appointments_pet_id_pets_id_fk",
- "tableFrom": "appointments",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_service_id_services_id_fk": {
- "name": "appointments_service_id_services_id_fk",
- "tableFrom": "appointments",
- "tableTo": "services",
- "columnsFrom": [
- "service_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_staff_id_staff_id_fk": {
- "name": "appointments_staff_id_staff_id_fk",
- "tableFrom": "appointments",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_bather_staff_id_staff_id_fk": {
- "name": "appointments_bather_staff_id_staff_id_fk",
- "tableFrom": "appointments",
- "tableTo": "staff",
- "columnsFrom": [
- "bather_staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_series_id_recurring_series_id_fk": {
- "name": "appointments_series_id_recurring_series_id_fk",
- "tableFrom": "appointments",
- "tableTo": "recurring_series",
- "columnsFrom": [
- "series_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_group_id_appointment_groups_id_fk": {
- "name": "appointments_group_id_appointment_groups_id_fk",
- "tableFrom": "appointments",
- "tableTo": "appointment_groups",
- "columnsFrom": [
- "group_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "appointments_confirmation_token_unique": {
- "name": "appointments_confirmation_token_unique",
- "nullsNotDistinct": false,
- "columns": [
- "confirmation_token"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.business_settings": {
- "name": "business_settings",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "business_name": {
- "name": "business_name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'GroomBook'"
- },
- "logo_base64": {
- "name": "logo_base64",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "logo_mime_type": {
- "name": "logo_mime_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "primary_color": {
- "name": "primary_color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'#4f8a6f'"
- },
- "accent_color": {
- "name": "accent_color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'#8b7355'"
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.clients": {
- "name": "clients",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "phone": {
- "name": "phone",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "address": {
- "name": "address",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "email_opt_out": {
- "name": "email_opt_out",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "status": {
- "name": "status",
- "type": "client_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "disabled_at": {
- "name": "disabled_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": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.grooming_visit_logs": {
- "name": "grooming_visit_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "cut_style": {
- "name": "cut_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "products_used": {
- "name": "products_used",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "groomed_at": {
- "name": "groomed_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "grooming_visit_logs_pet_id_pets_id_fk": {
- "name": "grooming_visit_logs_pet_id_pets_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "grooming_visit_logs_appointment_id_appointments_id_fk": {
- "name": "grooming_visit_logs_appointment_id_appointments_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "grooming_visit_logs_staff_id_staff_id_fk": {
- "name": "grooming_visit_logs_staff_id_staff_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_audit_logs": {
- "name": "impersonation_audit_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "session_id": {
- "name": "session_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "action": {
- "name": "action",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "page_visited": {
- "name": "page_visited",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "metadata": {
- "name": "metadata",
- "type": "jsonb",
- "primaryKey": false,
- "notNull": false
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {
- "impersonation_audit_logs_session_id_idx": {
- "name": "impersonation_audit_logs_session_id_idx",
- "columns": [
- {
- "expression": "session_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "impersonation_audit_logs_session_id_impersonation_sessions_id_fk": {
- "name": "impersonation_audit_logs_session_id_impersonation_sessions_id_fk",
- "tableFrom": "impersonation_audit_logs",
- "tableTo": "impersonation_sessions",
- "columnsFrom": [
- "session_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_sessions": {
- "name": "impersonation_sessions",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "reason": {
- "name": "reason",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "status": {
- "name": "status",
- "type": "impersonation_session_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "started_at": {
- "name": "started_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- },
- "ended_at": {
- "name": "ended_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {
- "impersonation_sessions_staff_id_status_idx": {
- "name": "impersonation_sessions_staff_id_status_idx",
- "columns": [
- {
- "expression": "staff_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- },
- {
- "expression": "status",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "impersonation_sessions_client_id_idx": {
- "name": "impersonation_sessions_client_id_idx",
- "columns": [
- {
- "expression": "client_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "impersonation_sessions_staff_id_staff_id_fk": {
- "name": "impersonation_sessions_staff_id_staff_id_fk",
- "tableFrom": "impersonation_sessions",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "impersonation_sessions_client_id_clients_id_fk": {
- "name": "impersonation_sessions_client_id_clients_id_fk",
- "tableFrom": "impersonation_sessions",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_line_items": {
- "name": "invoice_line_items",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "invoice_id": {
- "name": "invoice_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "quantity": {
- "name": "quantity",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 1
- },
- "unit_price_cents": {
- "name": "unit_price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "total_cents": {
- "name": "total_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_line_items_invoice_id_invoices_id_fk": {
- "name": "invoice_line_items_invoice_id_invoices_id_fk",
- "tableFrom": "invoice_line_items",
- "tableTo": "invoices",
- "columnsFrom": [
- "invoice_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_tip_splits": {
- "name": "invoice_tip_splits",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "invoice_id": {
- "name": "invoice_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "staff_name": {
- "name": "staff_name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "share_pct": {
- "name": "share_pct",
- "type": "numeric(5, 2)",
- "primaryKey": false,
- "notNull": true
- },
- "share_cents": {
- "name": "share_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_tip_splits_invoice_id_invoices_id_fk": {
- "name": "invoice_tip_splits_invoice_id_invoices_id_fk",
- "tableFrom": "invoice_tip_splits",
- "tableTo": "invoices",
- "columnsFrom": [
- "invoice_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "invoice_tip_splits_staff_id_staff_id_fk": {
- "name": "invoice_tip_splits_staff_id_staff_id_fk",
- "tableFrom": "invoice_tip_splits",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoices": {
- "name": "invoices",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "subtotal_cents": {
- "name": "subtotal_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "tax_cents": {
- "name": "tax_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 0
- },
- "tip_cents": {
- "name": "tip_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 0
- },
- "total_cents": {
- "name": "total_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "status": {
- "name": "status",
- "type": "invoice_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'draft'"
- },
- "payment_method": {
- "name": "payment_method",
- "type": "payment_method",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": false
- },
- "paid_at": {
- "name": "paid_at",
- "type": "timestamp",
- "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": {
- "invoices_appointment_id_appointments_id_fk": {
- "name": "invoices_appointment_id_appointments_id_fk",
- "tableFrom": "invoices",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "invoices_client_id_clients_id_fk": {
- "name": "invoices_client_id_clients_id_fk",
- "tableFrom": "invoices",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.pets": {
- "name": "pets",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "species": {
- "name": "species",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "breed": {
- "name": "breed",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "weight_kg": {
- "name": "weight_kg",
- "type": "numeric(5, 2)",
- "primaryKey": false,
- "notNull": false
- },
- "date_of_birth": {
- "name": "date_of_birth",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "health_alerts": {
- "name": "health_alerts",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "grooming_notes": {
- "name": "grooming_notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "cut_style": {
- "name": "cut_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "shampoo_preference": {
- "name": "shampoo_preference",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "special_care_notes": {
- "name": "special_care_notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "custom_fields": {
- "name": "custom_fields",
- "type": "jsonb",
- "primaryKey": false,
- "notNull": true,
- "default": "'{}'::jsonb"
- },
- "photo_key": {
- "name": "photo_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "photo_uploaded_at": {
- "name": "photo_uploaded_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": {},
- "foreignKeys": {
- "pets_client_id_clients_id_fk": {
- "name": "pets_client_id_clients_id_fk",
- "tableFrom": "pets",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.recurring_series": {
- "name": "recurring_series",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "frequency_weeks": {
- "name": "frequency_weeks",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.reminder_logs": {
- "name": "reminder_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "reminder_type": {
- "name": "reminder_type",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "sent_at": {
- "name": "sent_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "reminder_logs_appointment_id_appointments_id_fk": {
- "name": "reminder_logs_appointment_id_appointments_id_fk",
- "tableFrom": "reminder_logs",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "reminder_logs_appointment_id_reminder_type_unique": {
- "name": "reminder_logs_appointment_id_reminder_type_unique",
- "nullsNotDistinct": false,
- "columns": [
- "appointment_id",
- "reminder_type"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.services": {
- "name": "services",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "base_price_cents": {
- "name": "base_price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "duration_minutes": {
- "name": "duration_minutes",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "active": {
- "name": "active",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": true
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.session": {
- "name": "session",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "token": {
- "name": "token",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "ip_address": {
- "name": "ip_address",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "user_agent": {
- "name": "user_agent",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "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": {
- "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": {
- "session_token_unique": {
- "name": "session_token_unique",
- "nullsNotDistinct": false,
- "columns": [
- "token"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.staff": {
- "name": "staff",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "oidc_sub": {
- "name": "oidc_sub",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "role": {
- "name": "role",
- "type": "staff_role",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'groomer'"
- },
- "is_super_user": {
- "name": "is_super_user",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "active": {
- "name": "active",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": true
- },
- "ical_token": {
- "name": "ical_token",
- "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": {
- "staff_user_id_user_id_fk": {
- "name": "staff_user_id_user_id_fk",
- "tableFrom": "staff",
- "tableTo": "user",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "staff_email_unique": {
- "name": "staff_email_unique",
- "nullsNotDistinct": false,
- "columns": [
- "email"
- ]
- },
- "staff_oidc_sub_unique": {
- "name": "staff_oidc_sub_unique",
- "nullsNotDistinct": false,
- "columns": [
- "oidc_sub"
- ]
- },
- "staff_ical_token_unique": {
- "name": "staff_ical_token_unique",
- "nullsNotDistinct": false,
- "columns": [
- "ical_token"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.user": {
- "name": "user",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email_verified": {
- "name": "email_verified",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "image": {
- "name": "image",
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "user_email_unique": {
- "name": "user_email_unique",
- "nullsNotDistinct": false,
- "columns": [
- "email"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.verification": {
- "name": "verification",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "identifier": {
- "name": "identifier",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "value": {
- "name": "value",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.waitlist_entries": {
- "name": "waitlist_entries",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "service_id": {
- "name": "service_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "preferred_date": {
- "name": "preferred_date",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "preferred_time": {
- "name": "preferred_time",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "status": {
- "name": "status",
- "type": "waitlist_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "notified_at": {
- "name": "notified_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "expires_at": {
- "name": "expires_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": {
- "idx_waitlist_client_id": {
- "name": "idx_waitlist_client_id",
- "columns": [
- {
- "expression": "client_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "idx_waitlist_preferred_date": {
- "name": "idx_waitlist_preferred_date",
- "columns": [
- {
- "expression": "preferred_date",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "idx_waitlist_status": {
- "name": "idx_waitlist_status",
- "columns": [
- {
- "expression": "status",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "waitlist_entries_client_id_clients_id_fk": {
- "name": "waitlist_entries_client_id_clients_id_fk",
- "tableFrom": "waitlist_entries",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "waitlist_entries_pet_id_pets_id_fk": {
- "name": "waitlist_entries_pet_id_pets_id_fk",
- "tableFrom": "waitlist_entries",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "waitlist_entries_service_id_services_id_fk": {
- "name": "waitlist_entries_service_id_services_id_fk",
- "tableFrom": "waitlist_entries",
- "tableTo": "services",
- "columnsFrom": [
- "service_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- }
- },
- "enums": {
- "public.appointment_status": {
- "name": "appointment_status",
- "schema": "public",
- "values": [
- "scheduled",
- "confirmed",
- "in_progress",
- "completed",
- "cancelled",
- "no_show"
- ]
- },
- "public.client_status": {
- "name": "client_status",
- "schema": "public",
- "values": [
- "active",
- "disabled"
- ]
- },
- "public.impersonation_session_status": {
- "name": "impersonation_session_status",
- "schema": "public",
- "values": [
- "active",
- "ended",
- "expired"
- ]
- },
- "public.invoice_status": {
- "name": "invoice_status",
- "schema": "public",
- "values": [
- "draft",
- "pending",
- "paid",
- "void"
- ]
- },
- "public.payment_method": {
- "name": "payment_method",
- "schema": "public",
- "values": [
- "cash",
- "card",
- "check",
- "other"
- ]
- },
- "public.staff_role": {
- "name": "staff_role",
- "schema": "public",
- "values": [
- "groomer",
- "receptionist",
- "manager"
- ]
- },
- "public.waitlist_status": {
- "name": "waitlist_status",
- "schema": "public",
- "values": [
- "active",
- "notified",
- "expired",
- "cancelled"
- ]
- }
- },
- "schemas": {},
- "sequences": {},
- "roles": {},
- "policies": {},
- "views": {},
- "_meta": {
- "columns": {},
- "schemas": {},
- "tables": {}
- }
-}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0020_snapshot.json b/packages/db/migrations/meta/0020_snapshot.json
deleted file mode 100644
index 1ba0b0c..0000000
--- a/packages/db/migrations/meta/0020_snapshot.json
+++ /dev/null
@@ -1,2056 +0,0 @@
-{
- "id": "5983a2e9-f185-4f8a-a73f-5a7c0a0eea9c",
- "prevId": "b3a381ca-f7a4-450f-aa7e-fdc2d652dc97",
- "version": "7",
- "dialect": "postgresql",
- "tables": {
- "public.account": {
- "name": "account",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "account_id": {
- "name": "account_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "provider_id": {
- "name": "provider_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "access_token": {
- "name": "access_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "refresh_token": {
- "name": "refresh_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "id_token": {
- "name": "id_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "access_token_expires_at": {
- "name": "access_token_expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "refresh_token_expires_at": {
- "name": "refresh_token_expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "scope": {
- "name": "scope",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "password": {
- "name": "password",
- "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": {
- "account_user_id_user_id_fk": {
- "name": "account_user_id_user_id_fk",
- "tableFrom": "account",
- "tableTo": "user",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointment_groups": {
- "name": "appointment_groups",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "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": {
- "appointment_groups_client_id_clients_id_fk": {
- "name": "appointment_groups_client_id_clients_id_fk",
- "tableFrom": "appointment_groups",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointments": {
- "name": "appointments",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "service_id": {
- "name": "service_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "bather_staff_id": {
- "name": "bather_staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "status": {
- "name": "status",
- "type": "appointment_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'scheduled'"
- },
- "start_time": {
- "name": "start_time",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "end_time": {
- "name": "end_time",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "price_cents": {
- "name": "price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": false
- },
- "series_id": {
- "name": "series_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "series_index": {
- "name": "series_index",
- "type": "integer",
- "primaryKey": false,
- "notNull": false
- },
- "group_id": {
- "name": "group_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "confirmation_status": {
- "name": "confirmation_status",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'pending'"
- },
- "confirmed_at": {
- "name": "confirmed_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "cancelled_at": {
- "name": "cancelled_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "confirmation_token": {
- "name": "confirmation_token",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "customer_notes": {
- "name": "customer_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": {
- "appointments_client_id_clients_id_fk": {
- "name": "appointments_client_id_clients_id_fk",
- "tableFrom": "appointments",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_pet_id_pets_id_fk": {
- "name": "appointments_pet_id_pets_id_fk",
- "tableFrom": "appointments",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_service_id_services_id_fk": {
- "name": "appointments_service_id_services_id_fk",
- "tableFrom": "appointments",
- "tableTo": "services",
- "columnsFrom": [
- "service_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "appointments_staff_id_staff_id_fk": {
- "name": "appointments_staff_id_staff_id_fk",
- "tableFrom": "appointments",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_bather_staff_id_staff_id_fk": {
- "name": "appointments_bather_staff_id_staff_id_fk",
- "tableFrom": "appointments",
- "tableTo": "staff",
- "columnsFrom": [
- "bather_staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_series_id_recurring_series_id_fk": {
- "name": "appointments_series_id_recurring_series_id_fk",
- "tableFrom": "appointments",
- "tableTo": "recurring_series",
- "columnsFrom": [
- "series_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "appointments_group_id_appointment_groups_id_fk": {
- "name": "appointments_group_id_appointment_groups_id_fk",
- "tableFrom": "appointments",
- "tableTo": "appointment_groups",
- "columnsFrom": [
- "group_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "appointments_confirmation_token_unique": {
- "name": "appointments_confirmation_token_unique",
- "nullsNotDistinct": false,
- "columns": [
- "confirmation_token"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.business_settings": {
- "name": "business_settings",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "business_name": {
- "name": "business_name",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'GroomBook'"
- },
- "logo_base64": {
- "name": "logo_base64",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "logo_mime_type": {
- "name": "logo_mime_type",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "primary_color": {
- "name": "primary_color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'#4f8a6f'"
- },
- "accent_color": {
- "name": "accent_color",
- "type": "text",
- "primaryKey": false,
- "notNull": true,
- "default": "'#8b7355'"
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.clients": {
- "name": "clients",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "phone": {
- "name": "phone",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "address": {
- "name": "address",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "email_opt_out": {
- "name": "email_opt_out",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "status": {
- "name": "status",
- "type": "client_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "disabled_at": {
- "name": "disabled_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": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.grooming_visit_logs": {
- "name": "grooming_visit_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "cut_style": {
- "name": "cut_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "products_used": {
- "name": "products_used",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "notes": {
- "name": "notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "groomed_at": {
- "name": "groomed_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "grooming_visit_logs_pet_id_pets_id_fk": {
- "name": "grooming_visit_logs_pet_id_pets_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "grooming_visit_logs_appointment_id_appointments_id_fk": {
- "name": "grooming_visit_logs_appointment_id_appointments_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- },
- "grooming_visit_logs_staff_id_staff_id_fk": {
- "name": "grooming_visit_logs_staff_id_staff_id_fk",
- "tableFrom": "grooming_visit_logs",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_audit_logs": {
- "name": "impersonation_audit_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "session_id": {
- "name": "session_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "action": {
- "name": "action",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "page_visited": {
- "name": "page_visited",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "metadata": {
- "name": "metadata",
- "type": "jsonb",
- "primaryKey": false,
- "notNull": false
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {
- "impersonation_audit_logs_session_id_idx": {
- "name": "impersonation_audit_logs_session_id_idx",
- "columns": [
- {
- "expression": "session_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "impersonation_audit_logs_session_id_impersonation_sessions_id_fk": {
- "name": "impersonation_audit_logs_session_id_impersonation_sessions_id_fk",
- "tableFrom": "impersonation_audit_logs",
- "tableTo": "impersonation_sessions",
- "columnsFrom": [
- "session_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_sessions": {
- "name": "impersonation_sessions",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "reason": {
- "name": "reason",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "status": {
- "name": "status",
- "type": "impersonation_session_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "started_at": {
- "name": "started_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- },
- "ended_at": {
- "name": "ended_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {
- "impersonation_sessions_staff_id_status_idx": {
- "name": "impersonation_sessions_staff_id_status_idx",
- "columns": [
- {
- "expression": "staff_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- },
- {
- "expression": "status",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "impersonation_sessions_client_id_idx": {
- "name": "impersonation_sessions_client_id_idx",
- "columns": [
- {
- "expression": "client_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "impersonation_sessions_staff_id_staff_id_fk": {
- "name": "impersonation_sessions_staff_id_staff_id_fk",
- "tableFrom": "impersonation_sessions",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "impersonation_sessions_client_id_clients_id_fk": {
- "name": "impersonation_sessions_client_id_clients_id_fk",
- "tableFrom": "impersonation_sessions",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_line_items": {
- "name": "invoice_line_items",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "invoice_id": {
- "name": "invoice_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "quantity": {
- "name": "quantity",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 1
- },
- "unit_price_cents": {
- "name": "unit_price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "total_cents": {
- "name": "total_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_line_items_invoice_id_invoices_id_fk": {
- "name": "invoice_line_items_invoice_id_invoices_id_fk",
- "tableFrom": "invoice_line_items",
- "tableTo": "invoices",
- "columnsFrom": [
- "invoice_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_tip_splits": {
- "name": "invoice_tip_splits",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "invoice_id": {
- "name": "invoice_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "staff_id": {
- "name": "staff_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "staff_name": {
- "name": "staff_name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "share_pct": {
- "name": "share_pct",
- "type": "numeric(5, 2)",
- "primaryKey": false,
- "notNull": true
- },
- "share_cents": {
- "name": "share_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_tip_splits_invoice_id_invoices_id_fk": {
- "name": "invoice_tip_splits_invoice_id_invoices_id_fk",
- "tableFrom": "invoice_tip_splits",
- "tableTo": "invoices",
- "columnsFrom": [
- "invoice_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "invoice_tip_splits_staff_id_staff_id_fk": {
- "name": "invoice_tip_splits_staff_id_staff_id_fk",
- "tableFrom": "invoice_tip_splits",
- "tableTo": "staff",
- "columnsFrom": [
- "staff_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoices": {
- "name": "invoices",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": false
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "subtotal_cents": {
- "name": "subtotal_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "tax_cents": {
- "name": "tax_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 0
- },
- "tip_cents": {
- "name": "tip_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true,
- "default": 0
- },
- "total_cents": {
- "name": "total_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "status": {
- "name": "status",
- "type": "invoice_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'draft'"
- },
- "payment_method": {
- "name": "payment_method",
- "type": "payment_method",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": false
- },
- "paid_at": {
- "name": "paid_at",
- "type": "timestamp",
- "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": {
- "invoices_appointment_id_appointments_id_fk": {
- "name": "invoices_appointment_id_appointments_id_fk",
- "tableFrom": "invoices",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- },
- "invoices_client_id_clients_id_fk": {
- "name": "invoices_client_id_clients_id_fk",
- "tableFrom": "invoices",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "restrict",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.pets": {
- "name": "pets",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "species": {
- "name": "species",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "breed": {
- "name": "breed",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "weight_kg": {
- "name": "weight_kg",
- "type": "numeric(5, 2)",
- "primaryKey": false,
- "notNull": false
- },
- "date_of_birth": {
- "name": "date_of_birth",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "health_alerts": {
- "name": "health_alerts",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "grooming_notes": {
- "name": "grooming_notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "cut_style": {
- "name": "cut_style",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "shampoo_preference": {
- "name": "shampoo_preference",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "special_care_notes": {
- "name": "special_care_notes",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "custom_fields": {
- "name": "custom_fields",
- "type": "jsonb",
- "primaryKey": false,
- "notNull": true,
- "default": "'{}'::jsonb"
- },
- "photo_key": {
- "name": "photo_key",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "photo_uploaded_at": {
- "name": "photo_uploaded_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": {},
- "foreignKeys": {
- "pets_client_id_clients_id_fk": {
- "name": "pets_client_id_clients_id_fk",
- "tableFrom": "pets",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.recurring_series": {
- "name": "recurring_series",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "frequency_weeks": {
- "name": "frequency_weeks",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "created_at": {
- "name": "created_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.reminder_logs": {
- "name": "reminder_logs",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "appointment_id": {
- "name": "appointment_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "reminder_type": {
- "name": "reminder_type",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "sent_at": {
- "name": "sent_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true,
- "default": "now()"
- }
- },
- "indexes": {},
- "foreignKeys": {
- "reminder_logs_appointment_id_appointments_id_fk": {
- "name": "reminder_logs_appointment_id_appointments_id_fk",
- "tableFrom": "reminder_logs",
- "tableTo": "appointments",
- "columnsFrom": [
- "appointment_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "reminder_logs_appointment_id_reminder_type_unique": {
- "name": "reminder_logs_appointment_id_reminder_type_unique",
- "nullsNotDistinct": false,
- "columns": [
- "appointment_id",
- "reminder_type"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.services": {
- "name": "services",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "description": {
- "name": "description",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "base_price_cents": {
- "name": "base_price_cents",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "duration_minutes": {
- "name": "duration_minutes",
- "type": "integer",
- "primaryKey": false,
- "notNull": true
- },
- "active": {
- "name": "active",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": true
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "services_name_unique": {
- "name": "services_name_unique",
- "nullsNotDistinct": false,
- "columns": [
- "name"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.session": {
- "name": "session",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "token": {
- "name": "token",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "ip_address": {
- "name": "ip_address",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "user_agent": {
- "name": "user_agent",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "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": {
- "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": {
- "session_token_unique": {
- "name": "session_token_unique",
- "nullsNotDistinct": false,
- "columns": [
- "token"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.staff": {
- "name": "staff",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "oidc_sub": {
- "name": "oidc_sub",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "user_id": {
- "name": "user_id",
- "type": "text",
- "primaryKey": false,
- "notNull": false
- },
- "role": {
- "name": "role",
- "type": "staff_role",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'groomer'"
- },
- "is_super_user": {
- "name": "is_super_user",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "active": {
- "name": "active",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": true
- },
- "ical_token": {
- "name": "ical_token",
- "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": {
- "staff_user_id_user_id_fk": {
- "name": "staff_user_id_user_id_fk",
- "tableFrom": "staff",
- "tableTo": "user",
- "columnsFrom": [
- "user_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "set null",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "staff_email_unique": {
- "name": "staff_email_unique",
- "nullsNotDistinct": false,
- "columns": [
- "email"
- ]
- },
- "staff_oidc_sub_unique": {
- "name": "staff_oidc_sub_unique",
- "nullsNotDistinct": false,
- "columns": [
- "oidc_sub"
- ]
- },
- "staff_ical_token_unique": {
- "name": "staff_ical_token_unique",
- "nullsNotDistinct": false,
- "columns": [
- "ical_token"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.user": {
- "name": "user",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "name": {
- "name": "name",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email": {
- "name": "email",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "email_verified": {
- "name": "email_verified",
- "type": "boolean",
- "primaryKey": false,
- "notNull": true,
- "default": false
- },
- "image": {
- "name": "image",
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "user_email_unique": {
- "name": "user_email_unique",
- "nullsNotDistinct": false,
- "columns": [
- "email"
- ]
- }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.verification": {
- "name": "verification",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "text",
- "primaryKey": true,
- "notNull": true
- },
- "identifier": {
- "name": "identifier",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "value": {
- "name": "value",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "expires_at": {
- "name": "expires_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": true
- },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.waitlist_entries": {
- "name": "waitlist_entries",
- "schema": "",
- "columns": {
- "id": {
- "name": "id",
- "type": "uuid",
- "primaryKey": true,
- "notNull": true,
- "default": "gen_random_uuid()"
- },
- "client_id": {
- "name": "client_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "pet_id": {
- "name": "pet_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "service_id": {
- "name": "service_id",
- "type": "uuid",
- "primaryKey": false,
- "notNull": true
- },
- "preferred_date": {
- "name": "preferred_date",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "preferred_time": {
- "name": "preferred_time",
- "type": "text",
- "primaryKey": false,
- "notNull": true
- },
- "status": {
- "name": "status",
- "type": "waitlist_status",
- "typeSchema": "public",
- "primaryKey": false,
- "notNull": true,
- "default": "'active'"
- },
- "notified_at": {
- "name": "notified_at",
- "type": "timestamp",
- "primaryKey": false,
- "notNull": false
- },
- "expires_at": {
- "name": "expires_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": {
- "idx_waitlist_client_id": {
- "name": "idx_waitlist_client_id",
- "columns": [
- {
- "expression": "client_id",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "idx_waitlist_preferred_date": {
- "name": "idx_waitlist_preferred_date",
- "columns": [
- {
- "expression": "preferred_date",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- },
- "idx_waitlist_status": {
- "name": "idx_waitlist_status",
- "columns": [
- {
- "expression": "status",
- "isExpression": false,
- "asc": true,
- "nulls": "last"
- }
- ],
- "isUnique": false,
- "concurrently": false,
- "method": "btree",
- "with": {}
- }
- },
- "foreignKeys": {
- "waitlist_entries_client_id_clients_id_fk": {
- "name": "waitlist_entries_client_id_clients_id_fk",
- "tableFrom": "waitlist_entries",
- "tableTo": "clients",
- "columnsFrom": [
- "client_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "waitlist_entries_pet_id_pets_id_fk": {
- "name": "waitlist_entries_pet_id_pets_id_fk",
- "tableFrom": "waitlist_entries",
- "tableTo": "pets",
- "columnsFrom": [
- "pet_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- },
- "waitlist_entries_service_id_services_id_fk": {
- "name": "waitlist_entries_service_id_services_id_fk",
- "tableFrom": "waitlist_entries",
- "tableTo": "services",
- "columnsFrom": [
- "service_id"
- ],
- "columnsTo": [
- "id"
- ],
- "onDelete": "cascade",
- "onUpdate": "no action"
- }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- }
- },
- "enums": {
- "public.appointment_status": {
- "name": "appointment_status",
- "schema": "public",
- "values": [
- "scheduled",
- "confirmed",
- "in_progress",
- "completed",
- "cancelled",
- "no_show"
- ]
- },
- "public.client_status": {
- "name": "client_status",
- "schema": "public",
- "values": [
- "active",
- "disabled"
- ]
- },
- "public.impersonation_session_status": {
- "name": "impersonation_session_status",
- "schema": "public",
- "values": [
- "active",
- "ended",
- "expired"
- ]
- },
- "public.invoice_status": {
- "name": "invoice_status",
- "schema": "public",
- "values": [
- "draft",
- "pending",
- "paid",
- "void"
- ]
- },
- "public.payment_method": {
- "name": "payment_method",
- "schema": "public",
- "values": [
- "cash",
- "card",
- "check",
- "other"
- ]
- },
- "public.staff_role": {
- "name": "staff_role",
- "schema": "public",
- "values": [
- "groomer",
- "receptionist",
- "manager"
- ]
- },
- "public.waitlist_status": {
- "name": "waitlist_status",
- "schema": "public",
- "values": [
- "active",
- "notified",
- "expired",
- "cancelled"
- ]
- }
- },
- "schemas": {},
- "sequences": {},
- "roles": {},
- "policies": {},
- "views": {},
- "_meta": {
- "columns": {},
- "schemas": {},
- "tables": {}
- }
-}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0021_snapshot.json b/packages/db/migrations/meta/0021_snapshot.json
deleted file mode 100644
index 7a57e53..0000000
--- a/packages/db/migrations/meta/0021_snapshot.json
+++ /dev/null
@@ -1,504 +0,0 @@
-{
- "id": "b3a381ca-f7a4-450f-aa7e-fdc2d652dc97",
- "prevId": "5983a2e9-f185-4f8a-a73f-5a7c0a0eea9c",
- "version": "7",
- "dialect": "postgresql",
- "tables": {
- "public.account": {
- "name": "account",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "account_id": { "name": "account_id", "type": "text", "primaryKey": false, "notNull": true },
- "provider_id": { "name": "provider_id", "type": "text", "primaryKey": false, "notNull": true },
- "user_id": { "name": "user_id", "type": "text", "primaryKey": false, "notNull": true },
- "access_token": { "name": "access_token", "type": "text", "primaryKey": false, "notNull": false },
- "refresh_token": { "name": "refresh_token", "type": "text", "primaryKey": false, "notNull": false },
- "id_token": { "name": "id_token", "type": "text", "primaryKey": false, "notNull": false },
- "access_token_expires_at": { "name": "access_token_expires_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "refresh_token_expires_at": { "name": "refresh_token_expires_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "scope": { "name": "scope", "type": "text", "primaryKey": false, "notNull": false },
- "password": { "name": "password", "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": { "account_user_id_user_id_fk": { "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", "columnsFrom": ["user_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointment_groups": {
- "name": "appointment_groups",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "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": { "appointment_groups_client_id_clients_id_fk": { "name": "appointment_groups_client_id_clients_id_fk", "tableFrom": "appointment_groups", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointments": {
- "name": "appointments",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "pet_id": { "name": "pet_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "service_id": { "name": "service_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "bather_staff_id": { "name": "bather_staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "status": { "name": "status", "type": "appointment_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'scheduled'" },
- "start_time": { "name": "start_time", "type": "timestamp", "primaryKey": false, "notNull": true },
- "end_time": { "name": "end_time", "type": "timestamp", "primaryKey": false, "notNull": true },
- "notes": { "name": "notes", "type": "text", "primaryKey": false, "notNull": false },
- "price_cents": { "name": "price_cents", "type": "integer", "primaryKey": false, "notNull": false },
- "series_id": { "name": "series_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "series_index": { "name": "series_index", "type": "integer", "primaryKey": false, "notNull": false },
- "group_id": { "name": "group_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "confirmation_status": { "name": "confirmation_status", "type": "text", "primaryKey": false, "notNull": true, "default": "'pending'" },
- "confirmed_at": { "name": "confirmed_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "cancelled_at": { "name": "cancelled_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "confirmation_token": { "name": "confirmation_token", "type": "text", "primaryKey": false, "notNull": false },
- "customer_notes": { "name": "customer_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": {
- "appointments_client_id_clients_id_fk": { "name": "appointments_client_id_clients_id_fk", "tableFrom": "appointments", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "appointments_pet_id_pets_id_fk": { "name": "appointments_pet_id_pets_id_fk", "tableFrom": "appointments", "tableTo": "pets", "columnsFrom": ["pet_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "appointments_service_id_services_id_fk": { "name": "appointments_service_id_services_id_fk", "tableFrom": "appointments", "tableTo": "services", "columnsFrom": ["service_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "appointments_staff_id_staff_id_fk": { "name": "appointments_staff_id_staff_id_fk", "tableFrom": "appointments", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "appointments_bather_staff_id_staff_id_fk": { "name": "appointments_bather_staff_id_staff_id_fk", "tableFrom": "appointments", "tableTo": "staff", "columnsFrom": ["bather_staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "appointments_series_id_recurring_series_id_fk": { "name": "appointments_series_id_recurring_series_id_fk", "tableFrom": "appointments", "tableTo": "recurring_series", "columnsFrom": ["series_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "appointments_group_id_appointment_groups_id_fk": { "name": "appointments_group_id_appointment_groups_id_fk", "tableFrom": "appointments", "tableTo": "appointment_groups", "columnsFrom": ["group_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "appointments_confirmation_token_unique": { "name": "appointments_confirmation_token_unique", "nullsNotDistinct": false, "columns": ["confirmation_token"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.business_settings": {
- "name": "business_settings",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "business_name": { "name": "business_name", "type": "text", "primaryKey": false, "notNull": true, "default": "'GroomBook'" },
- "logo_base64": { "name": "logo_base64", "type": "text", "primaryKey": false, "notNull": false },
- "logo_mime_type": { "name": "logo_mime_type", "type": "text", "primaryKey": false, "notNull": false },
- "primary_color": { "name": "primary_color", "type": "text", "primaryKey": false, "notNull": true, "default": "'#4f8a6f'" },
- "accent_color": { "name": "accent_color", "type": "text", "primaryKey": false, "notNull": true, "default": "'#8b7355'" },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.clients": {
- "name": "clients",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": false },
- "phone": { "name": "phone", "type": "text", "primaryKey": false, "notNull": false },
- "address": { "name": "address", "type": "text", "primaryKey": false, "notNull": false },
- "notes": { "name": "notes", "type": "text", "primaryKey": false, "notNull": false },
- "email_opt_out": { "name": "email_opt_out", "type": "boolean", "primaryKey": false, "notNull": true, "default": false },
- "status": { "name": "status", "type": "client_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'active'" },
- "disabled_at": { "name": "disabled_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": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.grooming_visit_logs": {
- "name": "grooming_visit_logs",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "pet_id": { "name": "pet_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "appointment_id": { "name": "appointment_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "cut_style": { "name": "cut_style", "type": "text", "primaryKey": false, "notNull": false },
- "products_used": { "name": "products_used", "type": "text", "primaryKey": false, "notNull": false },
- "notes": { "name": "notes", "type": "text", "primaryKey": false, "notNull": false },
- "groomed_at": { "name": "groomed_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {
- "grooming_visit_logs_pet_id_pets_id_fk": { "name": "grooming_visit_logs_pet_id_pets_id_fk", "tableFrom": "grooming_visit_logs", "tableTo": "pets", "columnsFrom": ["pet_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "grooming_visit_logs_appointment_id_appointments_id_fk": { "name": "grooming_visit_logs_appointment_id_appointments_id_fk", "tableFrom": "grooming_visit_logs", "tableTo": "appointments", "columnsFrom": ["appointment_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "grooming_visit_logs_staff_id_staff_id_fk": { "name": "grooming_visit_logs_staff_id_staff_id_fk", "tableFrom": "grooming_visit_logs", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_audit_logs": {
- "name": "impersonation_audit_logs",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "session_id": { "name": "session_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "action": { "name": "action", "type": "text", "primaryKey": false, "notNull": true },
- "page_visited": { "name": "page_visited", "type": "text", "primaryKey": false, "notNull": false },
- "metadata": { "name": "metadata", "type": "jsonb", "primaryKey": false, "notNull": false },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": { "impersonation_audit_logs_session_id_idx": { "name": "impersonation_audit_logs_session_id_idx", "columns": [{ "expression": "session_id", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} } },
- "foreignKeys": { "impersonation_audit_logs_session_id_impersonation_sessions_id_fk": { "name": "impersonation_audit_logs_session_id_impersonation_sessions_id_fk", "tableFrom": "impersonation_audit_logs", "tableTo": "impersonation_sessions", "columnsFrom": ["session_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_sessions": {
- "name": "impersonation_sessions",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "reason": { "name": "reason", "type": "text", "primaryKey": false, "notNull": false },
- "status": { "name": "status", "type": "impersonation_session_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'active'" },
- "started_at": { "name": "started_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" },
- "ended_at": { "name": "ended_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "expires_at": { "name": "expires_at", "type": "timestamp", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {
- "impersonation_sessions_staff_id_status_idx": { "name": "impersonation_sessions_staff_id_status_idx", "columns": [{ "expression": "staff_id", "isExpression": false, "asc": true, "nulls": "last" }, { "expression": "status", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} },
- "impersonation_sessions_client_id_idx": { "name": "impersonation_sessions_client_id_idx", "columns": [{ "expression": "client_id", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} }
- },
- "foreignKeys": {
- "impersonation_sessions_staff_id_staff_id_fk": { "name": "impersonation_sessions_staff_id_staff_id_fk", "tableFrom": "impersonation_sessions", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "impersonation_sessions_client_id_clients_id_fk": { "name": "impersonation_sessions_client_id_clients_id_fk", "tableFrom": "impersonation_sessions", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_line_items": {
- "name": "invoice_line_items",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "invoice_id": { "name": "invoice_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "description": { "name": "description", "type": "text", "primaryKey": false, "notNull": true },
- "quantity": { "name": "quantity", "type": "integer", "primaryKey": false, "notNull": true, "default": 1 },
- "unit_price_cents": { "name": "unit_price_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "total_cents": { "name": "total_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": { "invoice_line_items_invoice_id_invoices_id_fk": { "name": "invoice_line_items_invoice_id_invoices_id_fk", "tableFrom": "invoice_line_items", "tableTo": "invoices", "columnsFrom": ["invoice_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_tip_splits": {
- "name": "invoice_tip_splits",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "invoice_id": { "name": "invoice_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "staff_name": { "name": "staff_name", "type": "text", "primaryKey": false, "notNull": true },
- "share_pct": { "name": "share_pct", "type": "numeric(5, 2)", "primaryKey": false, "notNull": true },
- "share_cents": { "name": "share_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_tip_splits_invoice_id_invoices_id_fk": { "name": "invoice_tip_splits_invoice_id_invoices_id_fk", "tableFrom": "invoice_tip_splits", "tableTo": "invoices", "columnsFrom": ["invoice_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "invoice_tip_splits_staff_id_staff_id_fk": { "name": "invoice_tip_splits_staff_id_staff_id_fk", "tableFrom": "invoice_tip_splits", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoices": {
- "name": "invoices",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "appointment_id": { "name": "appointment_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "subtotal_cents": { "name": "subtotal_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "tax_cents": { "name": "tax_cents", "type": "integer", "primaryKey": false, "notNull": true, "default": 0 },
- "tip_cents": { "name": "tip_cents", "type": "integer", "primaryKey": false, "notNull": true, "default": 0 },
- "total_cents": { "name": "total_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "status": { "name": "status", "type": "invoice_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'draft'" },
- "payment_method": { "name": "payment_method", "type": "payment_method", "typeSchema": "public", "primaryKey": false, "notNull": false },
- "paid_at": { "name": "paid_at", "type": "timestamp", "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": {
- "invoices_appointment_id_appointments_id_fk": { "name": "invoices_appointment_id_appointments_id_fk", "tableFrom": "invoices", "tableTo": "appointments", "columnsFrom": ["appointment_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "invoices_client_id_clients_id_fk": { "name": "invoices_client_id_clients_id_fk", "tableFrom": "invoices", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.pets": {
- "name": "pets",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "species": { "name": "species", "type": "text", "primaryKey": false, "notNull": true },
- "breed": { "name": "breed", "type": "text", "primaryKey": false, "notNull": false },
- "weight_kg": { "name": "weight_kg", "type": "numeric(5, 2)", "primaryKey": false, "notNull": false },
- "date_of_birth": { "name": "date_of_birth", "type": "timestamp", "primaryKey": false, "notNull": false },
- "health_alerts": { "name": "health_alerts", "type": "text", "primaryKey": false, "notNull": false },
- "grooming_notes": { "name": "grooming_notes", "type": "text", "primaryKey": false, "notNull": false },
- "cut_style": { "name": "cut_style", "type": "text", "primaryKey": false, "notNull": false },
- "shampoo_preference": { "name": "shampoo_preference", "type": "text", "primaryKey": false, "notNull": false },
- "special_care_notes": { "name": "special_care_notes", "type": "text", "primaryKey": false, "notNull": false },
- "custom_fields": { "name": "custom_fields", "type": "jsonb", "primaryKey": false, "notNull": true, "default": "'{}'::jsonb" },
- "photo_key": { "name": "photo_key", "type": "text", "primaryKey": false, "notNull": false },
- "photo_uploaded_at": { "name": "photo_uploaded_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "image": { "name": "image", "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": { "pets_client_id_clients_id_fk": { "name": "pets_client_id_clients_id_fk", "tableFrom": "pets", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.recurring_series": {
- "name": "recurring_series",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "frequency_weeks": { "name": "frequency_weeks", "type": "integer", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.reminder_logs": {
- "name": "reminder_logs",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "appointment_id": { "name": "appointment_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "reminder_type": { "name": "reminder_type", "type": "text", "primaryKey": false, "notNull": true },
- "sent_at": { "name": "sent_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": { "reminder_logs_appointment_id_appointments_id_fk": { "name": "reminder_logs_appointment_id_appointments_id_fk", "tableFrom": "reminder_logs", "tableTo": "appointments", "columnsFrom": ["appointment_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "reminder_logs_appointment_id_reminder_type_unique": { "name": "reminder_logs_appointment_id_reminder_type_unique", "nullsNotDistinct": false, "columns": ["appointment_id", "reminder_type"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.services": {
- "name": "services",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "description": { "name": "description", "type": "text", "primaryKey": false, "notNull": false },
- "base_price_cents": { "name": "base_price_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "duration_minutes": { "name": "duration_minutes", "type": "integer", "primaryKey": false, "notNull": true },
- "active": { "name": "active", "type": "boolean", "primaryKey": false, "notNull": true, "default": true },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "services_name_unique": { "name": "services_name_unique", "nullsNotDistinct": false, "columns": ["name"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.session": {
- "name": "session",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "expires_at": { "name": "expires_at", "type": "timestamp", "primaryKey": false, "notNull": true },
- "token": { "name": "token", "type": "text", "primaryKey": false, "notNull": true },
- "ip_address": { "name": "ip_address", "type": "text", "primaryKey": false, "notNull": false },
- "user_agent": { "name": "user_agent", "type": "text", "primaryKey": false, "notNull": false },
- "user_id": { "name": "user_id", "type": "text", "primaryKey": false, "notNull": true },
- "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": { "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": { "session_token_unique": { "name": "session_token_unique", "nullsNotDistinct": false, "columns": ["token"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.staff": {
- "name": "staff",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": true },
- "oidc_sub": { "name": "oidc_sub", "type": "text", "primaryKey": false, "notNull": false },
- "user_id": { "name": "user_id", "type": "text", "primaryKey": false, "notNull": false },
- "role": { "name": "role", "type": "staff_role", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'groomer'" },
- "is_super_user": { "name": "is_super_user", "type": "boolean", "primaryKey": false, "notNull": true, "default": false },
- "active": { "name": "active", "type": "boolean", "primaryKey": false, "notNull": true, "default": true },
- "ical_token": { "name": "ical_token", "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": { "staff_user_id_user_id_fk": { "name": "staff_user_id_user_id_fk", "tableFrom": "staff", "tableTo": "user", "columnsFrom": ["user_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "staff_email_unique": { "name": "staff_email_unique", "nullsNotDistinct": false, "columns": ["email"] },
- "staff_oidc_sub_unique": { "name": "staff_oidc_sub_unique", "nullsNotDistinct": false, "columns": ["oidc_sub"] },
- "staff_ical_token_unique": { "name": "staff_ical_token_unique", "nullsNotDistinct": false, "columns": ["ical_token"] }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.user": {
- "name": "user",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": true },
- "email_verified": { "name": "email_verified", "type": "boolean", "primaryKey": false, "notNull": true, "default": false },
- "image": { "name": "image", "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "user_email_unique": { "name": "user_email_unique", "nullsNotDistinct": false, "columns": ["email"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.verification": {
- "name": "verification",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "identifier": { "name": "identifier", "type": "text", "primaryKey": false, "notNull": true },
- "value": { "name": "value", "type": "text", "primaryKey": false, "notNull": true },
- "expires_at": { "name": "expires_at", "type": "timestamp", "primaryKey": false, "notNull": true },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.waitlist_entries": {
- "name": "waitlist_entries",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "pet_id": { "name": "pet_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "service_id": { "name": "service_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "preferred_date": { "name": "preferred_date", "type": "text", "primaryKey": false, "notNull": true },
- "preferred_time": { "name": "preferred_time", "type": "text", "primaryKey": false, "notNull": true },
- "status": { "name": "status", "type": "waitlist_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'active'" },
- "notified_at": { "name": "notified_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "expires_at": { "name": "expires_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": {
- "idx_waitlist_client_id": { "name": "idx_waitlist_client_id", "columns": [{ "expression": "client_id", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} },
- "idx_waitlist_preferred_date": { "name": "idx_waitlist_preferred_date", "columns": [{ "expression": "preferred_date", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} },
- "idx_waitlist_status": { "name": "idx_waitlist_status", "columns": [{ "expression": "status", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} }
- },
- "foreignKeys": {
- "waitlist_entries_client_id_clients_id_fk": { "name": "waitlist_entries_client_id_clients_id_fk", "tableFrom": "waitlist_entries", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "waitlist_entries_pet_id_pets_id_fk": { "name": "waitlist_entries_pet_id_pets_id_fk", "tableFrom": "waitlist_entries", "tableTo": "pets", "columnsFrom": ["pet_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "waitlist_entries_service_id_services_id_fk": { "name": "waitlist_entries_service_id_services_id_fk", "tableFrom": "waitlist_entries", "tableTo": "services", "columnsFrom": ["service_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- }
- },
- "enums": {
- "public.appointment_status": { "name": "appointment_status", "schema": "public", "values": ["scheduled", "confirmed", "in_progress", "completed", "cancelled", "no_show"] },
- "public.client_status": { "name": "client_status", "schema": "public", "values": ["active", "disabled"] },
- "public.impersonation_session_status": { "name": "impersonation_session_status", "schema": "public", "values": ["active", "ended", "expired"] },
- "public.invoice_status": { "name": "invoice_status", "schema": "public", "values": ["draft", "pending", "paid", "void"] },
- "public.payment_method": { "name": "payment_method", "schema": "public", "values": ["cash", "card", "check", "other"] },
- "public.staff_role": { "name": "staff_role", "schema": "public", "values": ["groomer", "receptionist", "manager"] },
- "public.waitlist_status": { "name": "waitlist_status", "schema": "public", "values": ["active", "notified", "expired", "cancelled"] }
- },
- "schemas": {},
- "sequences": {},
- "roles": {},
- "policies": {},
- "views": {},
- "_meta": { "columns": {}, "schemas": {}, "tables": {} }
-}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0022_snapshot.json b/packages/db/migrations/meta/0022_snapshot.json
deleted file mode 100644
index a803ed0..0000000
--- a/packages/db/migrations/meta/0022_snapshot.json
+++ /dev/null
@@ -1,505 +0,0 @@
-{
- "id": "9e8d3f2a-1c7b-4a6d-8f0e-5c2b9a3d7e1f",
- "prevId": "b3a381ca-f7a4-450f-aa7e-fdc2d652dc97",
- "version": "7",
- "dialect": "postgresql",
- "tables": {
- "public.account": {
- "name": "account",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "account_id": { "name": "account_id", "type": "text", "primaryKey": false, "notNull": true },
- "provider_id": { "name": "provider_id", "type": "text", "primaryKey": false, "notNull": true },
- "user_id": { "name": "user_id", "type": "text", "primaryKey": false, "notNull": true },
- "access_token": { "name": "access_token", "type": "text", "primaryKey": false, "notNull": false },
- "refresh_token": { "name": "refresh_token", "type": "text", "primaryKey": false, "notNull": false },
- "id_token": { "name": "id_token", "type": "text", "primaryKey": false, "notNull": false },
- "access_token_expires_at": { "name": "access_token_expires_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "refresh_token_expires_at": { "name": "refresh_token_expires_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "scope": { "name": "scope", "type": "text", "primaryKey": false, "notNull": false },
- "password": { "name": "password", "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": { "account_user_id_user_id_fk": { "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", "columnsFrom": ["user_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointment_groups": {
- "name": "appointment_groups",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "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": { "appointment_groups_client_id_clients_id_fk": { "name": "appointment_groups_client_id_clients_id_fk", "tableFrom": "appointment_groups", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.appointments": {
- "name": "appointments",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "pet_id": { "name": "pet_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "service_id": { "name": "service_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "bather_staff_id": { "name": "bather_staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "status": { "name": "status", "type": "appointment_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'scheduled'" },
- "start_time": { "name": "start_time", "type": "timestamp", "primaryKey": false, "notNull": true },
- "end_time": { "name": "end_time", "type": "timestamp", "primaryKey": false, "notNull": true },
- "notes": { "name": "notes", "type": "text", "primaryKey": false, "notNull": false },
- "price_cents": { "name": "price_cents", "type": "integer", "primaryKey": false, "notNull": false },
- "series_id": { "name": "series_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "series_index": { "name": "series_index", "type": "integer", "primaryKey": false, "notNull": false },
- "group_id": { "name": "group_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "confirmation_status": { "name": "confirmation_status", "type": "text", "primaryKey": false, "notNull": true, "default": "'pending'" },
- "confirmed_at": { "name": "confirmed_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "cancelled_at": { "name": "cancelled_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "confirmation_token": { "name": "confirmation_token", "type": "text", "primaryKey": false, "notNull": false },
- "customer_notes": { "name": "customer_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": {
- "appointments_client_id_clients_id_fk": { "name": "appointments_client_id_clients_id_fk", "tableFrom": "appointments", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "appointments_pet_id_pets_id_fk": { "name": "appointments_pet_id_pets_id_fk", "tableFrom": "appointments", "tableTo": "pets", "columnsFrom": ["pet_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "appointments_service_id_services_id_fk": { "name": "appointments_service_id_services_id_fk", "tableFrom": "appointments", "tableTo": "services", "columnsFrom": ["service_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "appointments_staff_id_staff_id_fk": { "name": "appointments_staff_id_staff_id_fk", "tableFrom": "appointments", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "appointments_bather_staff_id_staff_id_fk": { "name": "appointments_bather_staff_id_staff_id_fk", "tableFrom": "appointments", "tableTo": "staff", "columnsFrom": ["bather_staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "appointments_series_id_recurring_series_id_fk": { "name": "appointments_series_id_recurring_series_id_fk", "tableFrom": "appointments", "tableTo": "recurring_series", "columnsFrom": ["series_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "appointments_group_id_appointment_groups_id_fk": { "name": "appointments_group_id_appointment_groups_id_fk", "tableFrom": "appointments", "tableTo": "appointment_groups", "columnsFrom": ["group_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "appointments_confirmation_token_unique": { "name": "appointments_confirmation_token_unique", "nullsNotDistinct": false, "columns": ["confirmation_token"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.business_settings": {
- "name": "business_settings",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "business_name": { "name": "business_name", "type": "text", "primaryKey": false, "notNull": true, "default": "'GroomBook'" },
- "logo_base64": { "name": "logo_base64", "type": "text", "primaryKey": false, "notNull": false },
- "logo_mime_type": { "name": "logo_mime_type", "type": "text", "primaryKey": false, "notNull": false },
- "logo_key": { "name": "logo_key", "type": "text", "primaryKey": false, "notNull": false },
- "primary_color": { "name": "primary_color", "type": "text", "primaryKey": false, "notNull": true, "default": "'#4f8a6f'" },
- "accent_color": { "name": "accent_color", "type": "text", "primaryKey": false, "notNull": true, "default": "'#8b7355'" },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.clients": {
- "name": "clients",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": false },
- "phone": { "name": "phone", "type": "text", "primaryKey": false, "notNull": false },
- "address": { "name": "address", "type": "text", "primaryKey": false, "notNull": false },
- "notes": { "name": "notes", "type": "text", "primaryKey": false, "notNull": false },
- "email_opt_out": { "name": "email_opt_out", "type": "boolean", "primaryKey": false, "notNull": true, "default": false },
- "status": { "name": "status", "type": "client_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'active'" },
- "disabled_at": { "name": "disabled_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": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.grooming_visit_logs": {
- "name": "grooming_visit_logs",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "pet_id": { "name": "pet_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "appointment_id": { "name": "appointment_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "cut_style": { "name": "cut_style", "type": "text", "primaryKey": false, "notNull": false },
- "products_used": { "name": "products_used", "type": "text", "primaryKey": false, "notNull": false },
- "notes": { "name": "notes", "type": "text", "primaryKey": false, "notNull": false },
- "groomed_at": { "name": "groomed_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {
- "grooming_visit_logs_pet_id_pets_id_fk": { "name": "grooming_visit_logs_pet_id_pets_id_fk", "tableFrom": "grooming_visit_logs", "tableTo": "pets", "columnsFrom": ["pet_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "grooming_visit_logs_appointment_id_appointments_id_fk": { "name": "grooming_visit_logs_appointment_id_appointments_id_fk", "tableFrom": "grooming_visit_logs", "tableTo": "appointments", "columnsFrom": ["appointment_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" },
- "grooming_visit_logs_staff_id_staff_id_fk": { "name": "grooming_visit_logs_staff_id_staff_id_fk", "tableFrom": "grooming_visit_logs", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_audit_logs": {
- "name": "impersonation_audit_logs",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "session_id": { "name": "session_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "action": { "name": "action", "type": "text", "primaryKey": false, "notNull": true },
- "page_visited": { "name": "page_visited", "type": "text", "primaryKey": false, "notNull": false },
- "metadata": { "name": "metadata", "type": "jsonb", "primaryKey": false, "notNull": false },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": { "impersonation_audit_logs_session_id_idx": { "name": "impersonation_audit_logs_session_id_idx", "columns": [{ "expression": "session_id", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} } },
- "foreignKeys": { "impersonation_audit_logs_session_id_impersonation_sessions_id_fk": { "name": "impersonation_audit_logs_session_id_impersonation_sessions_id_fk", "tableFrom": "impersonation_audit_logs", "tableTo": "impersonation_sessions", "columnsFrom": ["session_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.impersonation_sessions": {
- "name": "impersonation_sessions",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "reason": { "name": "reason", "type": "text", "primaryKey": false, "notNull": false },
- "status": { "name": "status", "type": "impersonation_session_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'active'" },
- "started_at": { "name": "started_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" },
- "ended_at": { "name": "ended_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "expires_at": { "name": "expires_at", "type": "timestamp", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {
- "impersonation_sessions_staff_id_status_idx": { "name": "impersonation_sessions_staff_id_status_idx", "columns": [{ "expression": "staff_id", "isExpression": false, "asc": true, "nulls": "last" }, { "expression": "status", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} },
- "impersonation_sessions_client_id_idx": { "name": "impersonation_sessions_client_id_idx", "columns": [{ "expression": "client_id", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} }
- },
- "foreignKeys": {
- "impersonation_sessions_staff_id_staff_id_fk": { "name": "impersonation_sessions_staff_id_staff_id_fk", "tableFrom": "impersonation_sessions", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "impersonation_sessions_client_id_clients_id_fk": { "name": "impersonation_sessions_client_id_clients_id_fk", "tableFrom": "impersonation_sessions", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_line_items": {
- "name": "invoice_line_items",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "invoice_id": { "name": "invoice_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "description": { "name": "description", "type": "text", "primaryKey": false, "notNull": true },
- "quantity": { "name": "quantity", "type": "integer", "primaryKey": false, "notNull": true, "default": 1 },
- "unit_price_cents": { "name": "unit_price_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "total_cents": { "name": "total_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": { "invoice_line_items_invoice_id_invoices_id_fk": { "name": "invoice_line_items_invoice_id_invoices_id_fk", "tableFrom": "invoice_line_items", "tableTo": "invoices", "columnsFrom": ["invoice_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoice_tip_splits": {
- "name": "invoice_tip_splits",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "invoice_id": { "name": "invoice_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "staff_id": { "name": "staff_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "staff_name": { "name": "staff_name", "type": "text", "primaryKey": false, "notNull": true },
- "share_pct": { "name": "share_pct", "type": "numeric(5, 2)", "primaryKey": false, "notNull": true },
- "share_cents": { "name": "share_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {
- "invoice_tip_splits_invoice_id_invoices_id_fk": { "name": "invoice_tip_splits_invoice_id_invoices_id_fk", "tableFrom": "invoice_tip_splits", "tableTo": "invoices", "columnsFrom": ["invoice_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "invoice_tip_splits_staff_id_staff_id_fk": { "name": "invoice_tip_splits_staff_id_staff_id_fk", "tableFrom": "invoice_tip_splits", "tableTo": "staff", "columnsFrom": ["staff_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.invoices": {
- "name": "invoices",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "appointment_id": { "name": "appointment_id", "type": "uuid", "primaryKey": false, "notNull": false },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "subtotal_cents": { "name": "subtotal_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "tax_cents": { "name": "tax_cents", "type": "integer", "primaryKey": false, "notNull": true, "default": 0 },
- "tip_cents": { "name": "tip_cents", "type": "integer", "primaryKey": false, "notNull": true, "default": 0 },
- "total_cents": { "name": "total_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "status": { "name": "status", "type": "invoice_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'draft'" },
- "payment_method": { "name": "payment_method", "type": "payment_method", "typeSchema": "public", "primaryKey": false, "notNull": false },
- "paid_at": { "name": "paid_at", "type": "timestamp", "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": {
- "invoices_appointment_id_appointments_id_fk": { "name": "invoices_appointment_id_appointments_id_fk", "tableFrom": "invoices", "tableTo": "appointments", "columnsFrom": ["appointment_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" },
- "invoices_client_id_clients_id_fk": { "name": "invoices_client_id_clients_id_fk", "tableFrom": "invoices", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "restrict", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.pets": {
- "name": "pets",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "species": { "name": "species", "type": "text", "primaryKey": false, "notNull": true },
- "breed": { "name": "breed", "type": "text", "primaryKey": false, "notNull": false },
- "weight_kg": { "name": "weight_kg", "type": "numeric(5, 2)", "primaryKey": false, "notNull": false },
- "date_of_birth": { "name": "date_of_birth", "type": "timestamp", "primaryKey": false, "notNull": false },
- "health_alerts": { "name": "health_alerts", "type": "text", "primaryKey": false, "notNull": false },
- "grooming_notes": { "name": "grooming_notes", "type": "text", "primaryKey": false, "notNull": false },
- "cut_style": { "name": "cut_style", "type": "text", "primaryKey": false, "notNull": false },
- "shampoo_preference": { "name": "shampoo_preference", "type": "text", "primaryKey": false, "notNull": false },
- "special_care_notes": { "name": "special_care_notes", "type": "text", "primaryKey": false, "notNull": false },
- "custom_fields": { "name": "custom_fields", "type": "jsonb", "primaryKey": false, "notNull": true, "default": "'{}'::jsonb" },
- "photo_key": { "name": "photo_key", "type": "text", "primaryKey": false, "notNull": false },
- "photo_uploaded_at": { "name": "photo_uploaded_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "image": { "name": "image", "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": { "pets_client_id_clients_id_fk": { "name": "pets_client_id_clients_id_fk", "tableFrom": "pets", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.recurring_series": {
- "name": "recurring_series",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "frequency_weeks": { "name": "frequency_weeks", "type": "integer", "primaryKey": false, "notNull": true },
- "created_at": { "name": "created_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.reminder_logs": {
- "name": "reminder_logs",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "appointment_id": { "name": "appointment_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "reminder_type": { "name": "reminder_type", "type": "text", "primaryKey": false, "notNull": true },
- "sent_at": { "name": "sent_at", "type": "timestamp", "primaryKey": false, "notNull": true, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": { "reminder_logs_appointment_id_appointments_id_fk": { "name": "reminder_logs_appointment_id_appointments_id_fk", "tableFrom": "reminder_logs", "tableTo": "appointments", "columnsFrom": ["appointment_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "reminder_logs_appointment_id_reminder_type_unique": { "name": "reminder_logs_appointment_id_reminder_type_unique", "nullsNotDistinct": false, "columns": ["appointment_id", "reminder_type"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.services": {
- "name": "services",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "description": { "name": "description", "type": "text", "primaryKey": false, "notNull": false },
- "base_price_cents": { "name": "base_price_cents", "type": "integer", "primaryKey": false, "notNull": true },
- "duration_minutes": { "name": "duration_minutes", "type": "integer", "primaryKey": false, "notNull": true },
- "active": { "name": "active", "type": "boolean", "primaryKey": false, "notNull": true, "default": true },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "services_name_unique": { "name": "services_name_unique", "nullsNotDistinct": false, "columns": ["name"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.session": {
- "name": "session",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "expires_at": { "name": "expires_at", "type": "timestamp", "primaryKey": false, "notNull": true },
- "token": { "name": "token", "type": "text", "primaryKey": false, "notNull": true },
- "ip_address": { "name": "ip_address", "type": "text", "primaryKey": false, "notNull": false },
- "user_agent": { "name": "user_agent", "type": "text", "primaryKey": false, "notNull": false },
- "user_id": { "name": "user_id", "type": "text", "primaryKey": false, "notNull": true },
- "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": { "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": { "session_token_unique": { "name": "session_token_unique", "nullsNotDistinct": false, "columns": ["token"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.staff": {
- "name": "staff",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": true },
- "oidc_sub": { "name": "oidc_sub", "type": "text", "primaryKey": false, "notNull": false },
- "user_id": { "name": "user_id", "type": "text", "primaryKey": false, "notNull": false },
- "role": { "name": "role", "type": "staff_role", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'groomer'" },
- "is_super_user": { "name": "is_super_user", "type": "boolean", "primaryKey": false, "notNull": true, "default": false },
- "active": { "name": "active", "type": "boolean", "primaryKey": false, "notNull": true, "default": true },
- "ical_token": { "name": "ical_token", "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": { "staff_user_id_user_id_fk": { "name": "staff_user_id_user_id_fk", "tableFrom": "staff", "tableTo": "user", "columnsFrom": ["user_id"], "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {
- "staff_email_unique": { "name": "staff_email_unique", "nullsNotDistinct": false, "columns": ["email"] },
- "staff_oidc_sub_unique": { "name": "staff_oidc_sub_unique", "nullsNotDistinct": false, "columns": ["oidc_sub"] },
- "staff_ical_token_unique": { "name": "staff_ical_token_unique", "nullsNotDistinct": false, "columns": ["ical_token"] }
- },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.user": {
- "name": "user",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "name": { "name": "name", "type": "text", "primaryKey": false, "notNull": true },
- "email": { "name": "email", "type": "text", "primaryKey": false, "notNull": true },
- "email_verified": { "name": "email_verified", "type": "boolean", "primaryKey": false, "notNull": true, "default": false },
- "image": { "name": "image", "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "user_email_unique": { "name": "user_email_unique", "nullsNotDistinct": false, "columns": ["email"] } },
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.verification": {
- "name": "verification",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "text", "primaryKey": true, "notNull": true },
- "identifier": { "name": "identifier", "type": "text", "primaryKey": false, "notNull": true },
- "value": { "name": "value", "type": "text", "primaryKey": false, "notNull": true },
- "expires_at": { "name": "expires_at", "type": "timestamp", "primaryKey": false, "notNull": true },
- "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": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- },
- "public.waitlist_entries": {
- "name": "waitlist_entries",
- "schema": "",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "notNull": true, "default": "gen_random_uuid()" },
- "client_id": { "name": "client_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "pet_id": { "name": "pet_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "service_id": { "name": "service_id", "type": "uuid", "primaryKey": false, "notNull": true },
- "preferred_date": { "name": "preferred_date", "type": "text", "primaryKey": false, "notNull": true },
- "preferred_time": { "name": "preferred_time", "type": "text", "primaryKey": false, "notNull": true },
- "status": { "name": "status", "type": "waitlist_status", "typeSchema": "public", "primaryKey": false, "notNull": true, "default": "'active'" },
- "notified_at": { "name": "notified_at", "type": "timestamp", "primaryKey": false, "notNull": false },
- "expires_at": { "name": "expires_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": {
- "idx_waitlist_client_id": { "name": "idx_waitlist_client_id", "columns": [{ "expression": "client_id", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} },
- "idx_waitlist_preferred_date": { "name": "idx_waitlist_preferred_date", "columns": [{ "expression": "preferred_date", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} },
- "idx_waitlist_status": { "name": "idx_waitlist_status", "columns": [{ "expression": "status", "isExpression": false, "asc": true, "nulls": "last" }], "isUnique": false, "concurrently": false, "method": "btree", "with": {} }
- },
- "foreignKeys": {
- "waitlist_entries_client_id_clients_id_fk": { "name": "waitlist_entries_client_id_clients_id_fk", "tableFrom": "waitlist_entries", "tableTo": "clients", "columnsFrom": ["client_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "waitlist_entries_pet_id_pets_id_fk": { "name": "waitlist_entries_pet_id_pets_id_fk", "tableFrom": "waitlist_entries", "tableTo": "pets", "columnsFrom": ["pet_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" },
- "waitlist_entries_service_id_services_id_fk": { "name": "waitlist_entries_service_id_services_id_fk", "tableFrom": "waitlist_entries", "tableTo": "services", "columnsFrom": ["service_id"], "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }
- },
- "compositePrimaryKeys": {},
- "uniqueConstraints": {},
- "policies": {},
- "checkConstraints": {},
- "isRLSEnabled": false
- }
- },
- "enums": {
- "public.appointment_status": { "name": "appointment_status", "schema": "public", "values": ["scheduled", "confirmed", "in_progress", "completed", "cancelled", "no_show"] },
- "public.client_status": { "name": "client_status", "schema": "public", "values": ["active", "disabled"] },
- "public.impersonation_session_status": { "name": "impersonation_session_status", "schema": "public", "values": ["active", "ended", "expired"] },
- "public.invoice_status": { "name": "invoice_status", "schema": "public", "values": ["draft", "pending", "paid", "void"] },
- "public.payment_method": { "name": "payment_method", "schema": "public", "values": ["cash", "card", "check", "other"] },
- "public.staff_role": { "name": "staff_role", "schema": "public", "values": ["groomer", "receptionist", "manager"] },
- "public.waitlist_status": { "name": "waitlist_status", "schema": "public", "values": ["active", "notified", "expired", "cancelled"] }
- },
- "schemas": {},
- "sequences": {},
- "roles": {},
- "policies": {},
- "views": {},
- "_meta": { "columns": {}, "schemas": {}, "tables": {} }
-}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0026_snapshot.json b/packages/db/migrations/meta/0026_snapshot.json
deleted file mode 100644
index 6e0ad37..0000000
--- a/packages/db/migrations/meta/0026_snapshot.json
+++ /dev/null
@@ -1,103 +0,0 @@
-{
- "id": "0026_stripe_payment",
- "version": "7",
- "dialect": "postgresql",
- "tables": {
- "authProviderConfig": {
- "name": "auth_provider_config",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
- "providerId": { "name": "provider_id", "type": "text", "isNullable": false },
- "displayName": { "name": "display_name", "type": "text", "isNullable": false },
- "issuerUrl": { "name": "issuer_url", "type": "text", "isNullable": false },
- "internalBaseUrl": { "name": "internal_base_url", "type": "text", "isNullable": true },
- "clientId": { "name": "client_id", "type": "text", "isNullable": false },
- "clientSecret": { "name": "client_secret", "type": "text", "isNullable": false },
- "scopes": { "name": "scopes", "type": "text", "isNullable": false, "default": "'openid profile email'" },
- "enabled": { "name": "enabled", "type": "boolean", "isNullable": false, "default": "true" },
- "createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
- "updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {}
- },
- "businessSettings": {
- "name": "business_settings",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
- "businessName": { "name": "business_name", "type": "text", "isNullable": false, "default": "'GroomBook'" },
- "logoBase64": { "name": "logo_base64", "type": "text", "isNullable": true },
- "logoMimeType": { "name": "logo_mime_type", "type": "text", "isNullable": true },
- "logoKey": { "name": "logo_key", "type": "text", "isNullable": true },
- "primaryColor": { "name": "primary_color", "type": "text", "isNullable": false, "default": "'#4f8a6f'" },
- "accentColor": { "name": "accent_color", "type": "text", "isNullable": false, "default": "'#8b7355'" },
- "createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
- "updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {}
- },
- "clients": {
- "name": "clients",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
- "name": { "name": "name", "type": "text", "isNullable": false },
- "email": { "name": "email", "type": "text", "isNullable": true },
- "phone": { "name": "phone", "type": "text", "isNullable": true },
- "address": { "name": "address", "type": "text", "isNullable": true },
- "notes": { "name": "notes", "type": "text", "isNullable": true },
- "emailOptOut": { "name": "email_opt_out", "type": "boolean", "isNullable": false, "default": "false" },
- "smsOptIn": { "name": "sms_opt_in", "type": "boolean", "isNullable": false, "default": "false" },
- "smsConsentDate": { "name": "sms_consent_date", "type": "timestamp", "isNullable": true },
- "smsOptOutDate": { "name": "sms_opt_out_date", "type": "timestamp", "isNullable": true },
- "smsConsentText": { "name": "sms_consent_text", "type": "text", "isNullable": true },
- "stripeCustomerId": { "name": "stripe_customer_id", "type": "text", "isNullable": true },
- "status": { "name": "status", "type": "client_status", "isNullable": false, "default": "'active'" },
- "disabledAt": { "name": "disabled_at", "type": "timestamp", "isNullable": true },
- "createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
- "updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
- },
- "indexes": {},
- "foreignKeys": {},
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "idx_clients_stripe_customer_id": { "columns": ["stripe_customer_id"] } }
- },
- "invoices": {
- "name": "invoices",
- "columns": {
- "id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
- "appointmentId": { "name": "appointment_id", "type": "uuid", "isNullable": true },
- "clientId": { "name": "client_id", "type": "uuid", "isNullable": false },
- "subtotalCents": { "name": "subtotal_cents", "type": "integer", "isNullable": false },
- "taxCents": { "name": "tax_cents", "type": "integer", "isNullable": false, "default": "0" },
- "tipCents": { "name": "tip_cents", "type": "integer", "isNullable": false, "default": "0" },
- "totalCents": { "name": "total_cents", "type": "integer", "isNullable": false },
- "status": { "name": "status", "type": "invoice_status", "isNullable": false, "default": "'draft'" },
- "paymentMethod": { "name": "payment_method", "type": "payment_method", "isNullable": true },
- "paidAt": { "name": "paid_at", "type": "timestamp", "isNullable": true },
- "stripePaymentIntentId": { "name": "stripe_payment_intent_id", "type": "text", "isNullable": true },
- "stripeRefundId": { "name": "stripe_refund_id", "type": "text", "isNullable": true },
- "paymentFailureReason": { "name": "payment_failure_reason", "type": "text", "isNullable": true },
- "notes": { "name": "notes", "type": "text", "isNullable": true },
- "createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
- "updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
- },
- "indexes": { "idx_invoices_client_id": { "columns": ["client_id"] }, "idx_invoices_status": { "columns": ["status"] }, "idx_invoices_created_at": { "columns": ["created_at"] } },
- "foreignKeys": { "invoices_appointment_id_fkey": { "columns": ["appointmentId"], "reference": { "table": "appointments", "columns": ["id"] } }, "invoices_client_id_fkey": { "columns": ["clientId"], "reference": { "table": "clients", "columns": ["id"] } } },
- "compositePrimaryKeys": {},
- "uniqueConstraints": { "idx_invoices_stripe_payment_intent_id": { "columns": ["stripe_payment_intent_id"] } }
- }
- },
- "enums": {
- "appointment_status": { "name": "appointment_status", "values": ["scheduled", "confirmed", "in_progress", "completed", "cancelled", "no_show"] },
- "client_status": { "name": "client_status", "values": ["active", "disabled"] },
- "impersonation_session_status": { "name": "impersonation_session_status", "values": ["active", "ended", "expired"] },
- "invoice_status": { "name": "invoice_status", "values": ["draft", "pending", "paid", "void"] },
- "payment_method": { "name": "payment_method", "values": ["cash", "card", "check", "other"] },
- "staff_role": { "name": "staff_role", "values": ["groomer", "receptionist", "manager"] },
- "waitlist_status": { "name": "waitlist_status", "values": ["active", "notified", "expired", "cancelled"] }
- },
- "nativeEnums": {}
-}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0024_snapshot.json b/packages/db/migrations/meta/0031_snapshot.json
similarity index 70%
rename from packages/db/migrations/meta/0024_snapshot.json
rename to packages/db/migrations/meta/0031_snapshot.json
index 511c1cd..d79f1b4 100644
--- a/packages/db/migrations/meta/0024_snapshot.json
+++ b/packages/db/migrations/meta/0031_snapshot.json
@@ -1,6 +1,6 @@
{
- "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
- "prevId": "b43b79e0-feca-42ed-83cc-9ec67431c3cb",
+ "id": "619a413f-f5dc-4b63-acca-1ebac490cc4c",
+ "prevId": "477cddf9-970f-41c5-9cad-c1ed48c2bedf",
"version": "7",
"dialect": "postgresql",
"tables": {
@@ -281,6 +281,13 @@
"primaryKey": false,
"notNull": false
},
+ "buffer_minutes": {
+ "name": "buffer_minutes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
"confirmation_token": {
"name": "confirmation_token",
"type": "text",
@@ -308,7 +315,68 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_appointments_client_id": {
+ "name": "idx_appointments_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_appointments_staff_id": {
+ "name": "idx_appointments_staff_id",
+ "columns": [
+ {
+ "expression": "staff_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_appointments_start_time": {
+ "name": "idx_appointments_start_time",
+ "columns": [
+ {
+ "expression": "start_time",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_appointments_status": {
+ "name": "idx_appointments_status",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"appointments_client_id_clients_id_fk": {
"name": "appointments_client_id_clients_id_fk",
@@ -508,6 +576,106 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.buffer_time_rules": {
+ "name": "buffer_time_rules",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "service_id": {
+ "name": "service_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "size_category": {
+ "name": "size_category",
+ "type": "pet_size_category",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "coat_type": {
+ "name": "coat_type",
+ "type": "coat_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "buffer_minutes": {
+ "name": "buffer_minutes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "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": {
+ "idx_buffer_rules_service_id": {
+ "name": "idx_buffer_rules_service_id",
+ "columns": [
+ {
+ "expression": "service_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "buffer_time_rules_service_id_services_id_fk": {
+ "name": "buffer_time_rules_service_id_services_id_fk",
+ "tableFrom": "buffer_time_rules",
+ "tableTo": "services",
+ "columnsFrom": [
+ "service_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "buffer_time_rules_service_id_size_category_coat_type_unique": {
+ "name": "buffer_time_rules_service_id_size_category_coat_type_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "service_id",
+ "size_category",
+ "coat_type"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.business_settings": {
"name": "business_settings",
"schema": "",
@@ -538,6 +706,12 @@
"primaryKey": false,
"notNull": false
},
+ "logo_key": {
+ "name": "logo_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"primary_color": {
"name": "primary_color",
"type": "text",
@@ -552,6 +726,18 @@
"notNull": true,
"default": "'#8b7355'"
},
+ "messaging_phone_number": {
+ "name": "messaging_phone_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "telnyx_messaging_profile_id": {
+ "name": "telnyx_messaging_profile_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"created_at": {
"name": "created_at",
"type": "timestamp",
@@ -596,7 +782,7 @@
"name": "email",
"type": "text",
"primaryKey": false,
- "notNull": false
+ "notNull": true
},
"phone": {
"name": "phone",
@@ -623,6 +809,37 @@
"notNull": true,
"default": false
},
+ "sms_opt_in": {
+ "name": "sms_opt_in",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "sms_consent_date": {
+ "name": "sms_consent_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sms_opt_out_date": {
+ "name": "sms_opt_out_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sms_consent_text": {
+ "name": "sms_consent_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stripe_customer_id": {
+ "name": "stripe_customer_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"status": {
"name": "status",
"type": "client_status",
@@ -652,7 +869,23 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_clients_email": {
+ "name": "idx_clients_email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
@@ -660,6 +893,130 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.conversations": {
+ "name": "conversations",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "business_id": {
+ "name": "business_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "channel": {
+ "name": "channel",
+ "type": "messaging_channel",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "external_number": {
+ "name": "external_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "business_number": {
+ "name": "business_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "last_message_at": {
+ "name": "last_message_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'active'"
+ },
+ "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": {
+ "idx_conversations_business_id_last_message_at": {
+ "name": "idx_conversations_business_id_last_message_at",
+ "columns": [
+ {
+ "expression": "business_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "last_message_at",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "conversations_client_id_clients_id_fk": {
+ "name": "conversations_client_id_clients_id_fk",
+ "tableFrom": "conversations",
+ "tableTo": "clients",
+ "columnsFrom": [
+ "client_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "uq_conversations_business_client_number": {
+ "name": "uq_conversations_business_client_number",
+ "nullsNotDistinct": false,
+ "columns": [
+ "business_id",
+ "client_id",
+ "business_number"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.grooming_visit_logs": {
"name": "grooming_visit_logs",
"schema": "",
@@ -1245,6 +1602,24 @@
"primaryKey": false,
"notNull": false
},
+ "stripe_payment_intent_id": {
+ "name": "stripe_payment_intent_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stripe_refund_id": {
+ "name": "stripe_refund_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_failure_reason": {
+ "name": "payment_failure_reason",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"notes": {
"name": "notes",
"type": "text",
@@ -1311,6 +1686,21 @@
"concurrently": false,
"method": "btree",
"with": {}
+ },
+ "idx_invoices_stripe_payment_intent_id": {
+ "name": "idx_invoices_stripe_payment_intent_id",
+ "columns": [
+ {
+ "expression": "stripe_payment_intent_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
}
},
"foreignKeys": {
@@ -1347,6 +1737,315 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.message_attachments": {
+ "name": "message_attachments",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "message_id": {
+ "name": "message_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content_type": {
+ "name": "content_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "size": {
+ "name": "size",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_media_id": {
+ "name": "provider_media_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "idx_message_attachments_message_id": {
+ "name": "idx_message_attachments_message_id",
+ "columns": [
+ {
+ "expression": "message_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "message_attachments_message_id_messages_id_fk": {
+ "name": "message_attachments_message_id_messages_id_fk",
+ "tableFrom": "message_attachments",
+ "tableTo": "messages",
+ "columnsFrom": [
+ "message_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.message_consent_events": {
+ "name": "message_consent_events",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "business_id": {
+ "name": "business_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "kind": {
+ "name": "kind",
+ "type": "message_consent_kind",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source": {
+ "name": "source",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_message_consent_events_client_id": {
+ "name": "idx_message_consent_events_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "message_consent_events_client_id_clients_id_fk": {
+ "name": "message_consent_events_client_id_clients_id_fk",
+ "tableFrom": "message_consent_events",
+ "tableTo": "clients",
+ "columnsFrom": [
+ "client_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.messages": {
+ "name": "messages",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "conversation_id": {
+ "name": "conversation_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "direction": {
+ "name": "direction",
+ "type": "message_direction",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "body": {
+ "name": "body",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "message_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'queued'"
+ },
+ "provider_message_id": {
+ "name": "provider_message_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error_code": {
+ "name": "error_code",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error_message": {
+ "name": "error_message",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sent_by_staff_id": {
+ "name": "sent_by_staff_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "delivered_at": {
+ "name": "delivered_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "read_by_client_at": {
+ "name": "read_by_client_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "idx_messages_conversation_id_created_at": {
+ "name": "idx_messages_conversation_id_created_at",
+ "columns": [
+ {
+ "expression": "conversation_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "messages_conversation_id_conversations_id_fk": {
+ "name": "messages_conversation_id_conversations_id_fk",
+ "tableFrom": "messages",
+ "tableTo": "conversations",
+ "columnsFrom": [
+ "conversation_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "messages_sent_by_staff_id_staff_id_fk": {
+ "name": "messages_sent_by_staff_id_staff_id_fk",
+ "tableFrom": "messages",
+ "tableTo": "staff",
+ "columnsFrom": [
+ "sent_by_staff_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "uq_messages_provider_message_id": {
+ "name": "uq_messages_provider_message_id",
+ "nullsNotDistinct": false,
+ "columns": [
+ "provider_message_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.pets": {
"name": "pets",
"schema": "",
@@ -1443,6 +2142,26 @@
"primaryKey": false,
"notNull": false
},
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "size_category": {
+ "name": "size_category",
+ "type": "pet_size_category",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "coat_type": {
+ "name": "coat_type",
+ "type": "coat_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
"created_at": {
"name": "created_at",
"type": "timestamp",
@@ -1458,7 +2177,23 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_pets_client_id": {
+ "name": "idx_pets_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"pets_client_id_clients_id_fk": {
"name": "pets_client_id_clients_id_fk",
@@ -1513,6 +2248,110 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.refunds": {
+ "name": "refunds",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "invoice_id": {
+ "name": "invoice_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stripe_refund_id": {
+ "name": "stripe_refund_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "idempotency_key": {
+ "name": "idempotency_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "amount_cents": {
+ "name": "amount_cents",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_refunds_invoice_id": {
+ "name": "idx_refunds_invoice_id",
+ "columns": [
+ {
+ "expression": "invoice_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_refunds_idempotency_key": {
+ "name": "idx_refunds_idempotency_key",
+ "columns": [
+ {
+ "expression": "idempotency_key",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "refunds_invoice_id_invoices_id_fk": {
+ "name": "refunds_invoice_id_invoices_id_fk",
+ "tableFrom": "refunds",
+ "tableTo": "invoices",
+ "columnsFrom": [
+ "invoice_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "refunds_idempotency_key_unique": {
+ "name": "refunds_idempotency_key_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "idempotency_key"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.reminder_logs": {
"name": "reminder_logs",
"schema": "",
@@ -1536,6 +2375,13 @@
"primaryKey": false,
"notNull": true
},
+ "channel": {
+ "name": "channel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'email'"
+ },
"sent_at": {
"name": "sent_at",
"type": "timestamp",
@@ -1562,12 +2408,13 @@
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
- "reminder_logs_appointment_id_reminder_type_unique": {
- "name": "reminder_logs_appointment_id_reminder_type_unique",
+ "reminder_logs_appointment_id_reminder_type_channel_unique": {
+ "name": "reminder_logs_appointment_id_reminder_type_channel_unique",
"nullsNotDistinct": false,
"columns": [
"appointment_id",
- "reminder_type"
+ "reminder_type",
+ "channel"
]
}
},
@@ -1610,6 +2457,13 @@
"primaryKey": false,
"notNull": true
},
+ "default_buffer_minutes": {
+ "name": "default_buffer_minutes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
"active": {
"name": "active",
"type": "boolean",
@@ -2164,6 +3018,18 @@
"disabled"
]
},
+ "public.coat_type": {
+ "name": "coat_type",
+ "schema": "public",
+ "values": [
+ "smooth",
+ "double",
+ "curly",
+ "wire",
+ "long",
+ "hairless"
+ ]
+ },
"public.impersonation_session_status": {
"name": "impersonation_session_status",
"schema": "public",
@@ -2183,6 +3049,42 @@
"void"
]
},
+ "public.message_consent_kind": {
+ "name": "message_consent_kind",
+ "schema": "public",
+ "values": [
+ "opt_in",
+ "opt_out",
+ "help"
+ ]
+ },
+ "public.message_direction": {
+ "name": "message_direction",
+ "schema": "public",
+ "values": [
+ "inbound",
+ "outbound"
+ ]
+ },
+ "public.message_status": {
+ "name": "message_status",
+ "schema": "public",
+ "values": [
+ "queued",
+ "sent",
+ "delivered",
+ "failed",
+ "received"
+ ]
+ },
+ "public.messaging_channel": {
+ "name": "messaging_channel",
+ "schema": "public",
+ "values": [
+ "sms",
+ "mms"
+ ]
+ },
"public.payment_method": {
"name": "payment_method",
"schema": "public",
@@ -2193,6 +3095,16 @@
"other"
]
},
+ "public.pet_size_category": {
+ "name": "pet_size_category",
+ "schema": "public",
+ "values": [
+ "small",
+ "medium",
+ "large",
+ "xlarge"
+ ]
+ },
"public.staff_role": {
"name": "staff_role",
"schema": "public",
@@ -2223,4 +3135,4 @@
"schemas": {},
"tables": {}
}
-}
+}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0023_snapshot.json b/packages/db/migrations/meta/0032_snapshot.json
similarity index 66%
rename from packages/db/migrations/meta/0023_snapshot.json
rename to packages/db/migrations/meta/0032_snapshot.json
index d3c80ca..87a385f 100644
--- a/packages/db/migrations/meta/0023_snapshot.json
+++ b/packages/db/migrations/meta/0032_snapshot.json
@@ -1,6 +1,6 @@
{
- "id": "b43b79e0-feca-42ed-83cc-9ec67431c3cb",
- "prevId": "9e8d3f2a-1c7b-4a6d-8f0e-5c2b9a3d7e1f",
+ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ "prevId": "619a413f-f5dc-4b63-acca-1ebac490cc4c",
"version": "7",
"dialect": "postgresql",
"tables": {
@@ -281,6 +281,13 @@
"primaryKey": false,
"notNull": false
},
+ "buffer_minutes": {
+ "name": "buffer_minutes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
"confirmation_token": {
"name": "confirmation_token",
"type": "text",
@@ -308,7 +315,68 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_appointments_client_id": {
+ "name": "idx_appointments_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_appointments_staff_id": {
+ "name": "idx_appointments_staff_id",
+ "columns": [
+ {
+ "expression": "staff_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_appointments_start_time": {
+ "name": "idx_appointments_start_time",
+ "columns": [
+ {
+ "expression": "start_time",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_appointments_status": {
+ "name": "idx_appointments_status",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"appointments_client_id_clients_id_fk": {
"name": "appointments_client_id_clients_id_fk",
@@ -508,6 +576,106 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.buffer_time_rules": {
+ "name": "buffer_time_rules",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "service_id": {
+ "name": "service_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "size_category": {
+ "name": "size_category",
+ "type": "pet_size_category",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "coat_type": {
+ "name": "coat_type",
+ "type": "coat_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "buffer_minutes": {
+ "name": "buffer_minutes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "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": {
+ "idx_buffer_rules_service_id": {
+ "name": "idx_buffer_rules_service_id",
+ "columns": [
+ {
+ "expression": "service_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "buffer_time_rules_service_id_services_id_fk": {
+ "name": "buffer_time_rules_service_id_services_id_fk",
+ "tableFrom": "buffer_time_rules",
+ "tableTo": "services",
+ "columnsFrom": [
+ "service_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "buffer_time_rules_service_id_size_category_coat_type_unique": {
+ "name": "buffer_time_rules_service_id_size_category_coat_type_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "service_id",
+ "size_category",
+ "coat_type"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.business_settings": {
"name": "business_settings",
"schema": "",
@@ -538,6 +706,12 @@
"primaryKey": false,
"notNull": false
},
+ "logo_key": {
+ "name": "logo_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"primary_color": {
"name": "primary_color",
"type": "text",
@@ -552,6 +726,18 @@
"notNull": true,
"default": "'#8b7355'"
},
+ "messaging_phone_number": {
+ "name": "messaging_phone_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "telnyx_messaging_profile_id": {
+ "name": "telnyx_messaging_profile_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"created_at": {
"name": "created_at",
"type": "timestamp",
@@ -596,7 +782,7 @@
"name": "email",
"type": "text",
"primaryKey": false,
- "notNull": false
+ "notNull": true
},
"phone": {
"name": "phone",
@@ -623,6 +809,37 @@
"notNull": true,
"default": false
},
+ "sms_opt_in": {
+ "name": "sms_opt_in",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "sms_consent_date": {
+ "name": "sms_consent_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sms_opt_out_date": {
+ "name": "sms_opt_out_date",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sms_consent_text": {
+ "name": "sms_consent_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stripe_customer_id": {
+ "name": "stripe_customer_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"status": {
"name": "status",
"type": "client_status",
@@ -652,7 +869,23 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_clients_email": {
+ "name": "idx_clients_email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
@@ -660,6 +893,156 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.conversations": {
+ "name": "conversations",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "business_id": {
+ "name": "business_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "channel": {
+ "name": "channel",
+ "type": "messaging_channel",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "external_number": {
+ "name": "external_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "business_number": {
+ "name": "business_number",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "last_message_at": {
+ "name": "last_message_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'active'"
+ },
+ "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()"
+ },
+ "staff_read_at": {
+ "name": "staff_read_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "idx_conversations_business_id_last_message_at": {
+ "name": "idx_conversations_business_id_last_message_at",
+ "columns": [
+ {
+ "expression": "business_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "last_message_at",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_conversations_business_id_staff_read_at": {
+ "name": "idx_conversations_business_id_staff_read_at",
+ "columns": [
+ {
+ "expression": "business_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "staff_read_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "predicate": null
+ }
+ },
+ "foreignKeys": {
+ "conversations_client_id_clients_id_fk": {
+ "name": "conversations_client_id_clients_id_fk",
+ "tableFrom": "conversations",
+ "tableTo": "clients",
+ "columnsFrom": [
+ "client_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "uq_conversations_business_client_number": {
+ "name": "uq_conversations_business_client_number",
+ "nullsNotDistinct": false,
+ "columns": [
+ "business_id",
+ "client_id",
+ "business_number"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.grooming_visit_logs": {
"name": "grooming_visit_logs",
"schema": "",
@@ -1037,7 +1420,23 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_invoice_line_items_invoice_id": {
+ "name": "idx_invoice_line_items_invoice_id",
+ "columns": [
+ {
+ "expression": "invoice_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"invoice_line_items_invoice_id_invoices_id_fk": {
"name": "invoice_line_items_invoice_id_invoices_id_fk",
@@ -1108,7 +1507,23 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_invoice_tip_splits_invoice_id": {
+ "name": "idx_invoice_tip_splits_invoice_id",
+ "columns": [
+ {
+ "expression": "invoice_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"invoice_tip_splits_invoice_id_invoices_id_fk": {
"name": "invoice_tip_splits_invoice_id_invoices_id_fk",
@@ -1213,6 +1628,24 @@
"primaryKey": false,
"notNull": false
},
+ "stripe_payment_intent_id": {
+ "name": "stripe_payment_intent_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stripe_refund_id": {
+ "name": "stripe_refund_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_failure_reason": {
+ "name": "payment_failure_reason",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
"notes": {
"name": "notes",
"type": "text",
@@ -1234,7 +1667,68 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_invoices_client_id": {
+ "name": "idx_invoices_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_invoices_status": {
+ "name": "idx_invoices_status",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_invoices_created_at": {
+ "name": "idx_invoices_created_at",
+ "columns": [
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_invoices_stripe_payment_intent_id": {
+ "name": "idx_invoices_stripe_payment_intent_id",
+ "columns": [
+ {
+ "expression": "stripe_payment_intent_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"invoices_appointment_id_appointments_id_fk": {
"name": "invoices_appointment_id_appointments_id_fk",
@@ -1269,6 +1763,315 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.message_attachments": {
+ "name": "message_attachments",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "message_id": {
+ "name": "message_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content_type": {
+ "name": "content_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "size": {
+ "name": "size",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_media_id": {
+ "name": "provider_media_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "idx_message_attachments_message_id": {
+ "name": "idx_message_attachments_message_id",
+ "columns": [
+ {
+ "expression": "message_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "message_attachments_message_id_messages_id_fk": {
+ "name": "message_attachments_message_id_messages_id_fk",
+ "tableFrom": "message_attachments",
+ "tableTo": "messages",
+ "columnsFrom": [
+ "message_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.message_consent_events": {
+ "name": "message_consent_events",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "business_id": {
+ "name": "business_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "kind": {
+ "name": "kind",
+ "type": "message_consent_kind",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source": {
+ "name": "source",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_message_consent_events_client_id": {
+ "name": "idx_message_consent_events_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "message_consent_events_client_id_clients_id_fk": {
+ "name": "message_consent_events_client_id_clients_id_fk",
+ "tableFrom": "message_consent_events",
+ "tableTo": "clients",
+ "columnsFrom": [
+ "client_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.messages": {
+ "name": "messages",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "conversation_id": {
+ "name": "conversation_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "direction": {
+ "name": "direction",
+ "type": "message_direction",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "body": {
+ "name": "body",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "message_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'queued'"
+ },
+ "provider_message_id": {
+ "name": "provider_message_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error_code": {
+ "name": "error_code",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error_message": {
+ "name": "error_message",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sent_by_staff_id": {
+ "name": "sent_by_staff_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "delivered_at": {
+ "name": "delivered_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "read_by_client_at": {
+ "name": "read_by_client_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "idx_messages_conversation_id_created_at": {
+ "name": "idx_messages_conversation_id_created_at",
+ "columns": [
+ {
+ "expression": "conversation_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "messages_conversation_id_conversations_id_fk": {
+ "name": "messages_conversation_id_conversations_id_fk",
+ "tableFrom": "messages",
+ "tableTo": "conversations",
+ "columnsFrom": [
+ "conversation_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "messages_sent_by_staff_id_staff_id_fk": {
+ "name": "messages_sent_by_staff_id_staff_id_fk",
+ "tableFrom": "messages",
+ "tableTo": "staff",
+ "columnsFrom": [
+ "sent_by_staff_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "uq_messages_provider_message_id": {
+ "name": "uq_messages_provider_message_id",
+ "nullsNotDistinct": false,
+ "columns": [
+ "provider_message_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.pets": {
"name": "pets",
"schema": "",
@@ -1365,6 +2168,26 @@
"primaryKey": false,
"notNull": false
},
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "size_category": {
+ "name": "size_category",
+ "type": "pet_size_category",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "coat_type": {
+ "name": "coat_type",
+ "type": "coat_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
"created_at": {
"name": "created_at",
"type": "timestamp",
@@ -1380,7 +2203,23 @@
"default": "now()"
}
},
- "indexes": {},
+ "indexes": {
+ "idx_pets_client_id": {
+ "name": "idx_pets_client_id",
+ "columns": [
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
"foreignKeys": {
"pets_client_id_clients_id_fk": {
"name": "pets_client_id_clients_id_fk",
@@ -1435,6 +2274,110 @@
"checkConstraints": {},
"isRLSEnabled": false
},
+ "public.refunds": {
+ "name": "refunds",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "invoice_id": {
+ "name": "invoice_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stripe_refund_id": {
+ "name": "stripe_refund_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "idempotency_key": {
+ "name": "idempotency_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "amount_cents": {
+ "name": "amount_cents",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_refunds_invoice_id": {
+ "name": "idx_refunds_invoice_id",
+ "columns": [
+ {
+ "expression": "invoice_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "idx_refunds_idempotency_key": {
+ "name": "idx_refunds_idempotency_key",
+ "columns": [
+ {
+ "expression": "idempotency_key",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "refunds_invoice_id_invoices_id_fk": {
+ "name": "refunds_invoice_id_invoices_id_fk",
+ "tableFrom": "refunds",
+ "tableTo": "invoices",
+ "columnsFrom": [
+ "invoice_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "refunds_idempotency_key_unique": {
+ "name": "refunds_idempotency_key_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "idempotency_key"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
"public.reminder_logs": {
"name": "reminder_logs",
"schema": "",
@@ -1458,6 +2401,13 @@
"primaryKey": false,
"notNull": true
},
+ "channel": {
+ "name": "channel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'email'"
+ },
"sent_at": {
"name": "sent_at",
"type": "timestamp",
@@ -1484,12 +2434,13 @@
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
- "reminder_logs_appointment_id_reminder_type_unique": {
- "name": "reminder_logs_appointment_id_reminder_type_unique",
+ "reminder_logs_appointment_id_reminder_type_channel_unique": {
+ "name": "reminder_logs_appointment_id_reminder_type_channel_unique",
"nullsNotDistinct": false,
"columns": [
"appointment_id",
- "reminder_type"
+ "reminder_type",
+ "channel"
]
}
},
@@ -1532,6 +2483,13 @@
"primaryKey": false,
"notNull": true
},
+ "default_buffer_minutes": {
+ "name": "default_buffer_minutes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
"active": {
"name": "active",
"type": "boolean",
@@ -2086,6 +3044,18 @@
"disabled"
]
},
+ "public.coat_type": {
+ "name": "coat_type",
+ "schema": "public",
+ "values": [
+ "smooth",
+ "double",
+ "curly",
+ "wire",
+ "long",
+ "hairless"
+ ]
+ },
"public.impersonation_session_status": {
"name": "impersonation_session_status",
"schema": "public",
@@ -2105,6 +3075,42 @@
"void"
]
},
+ "public.message_consent_kind": {
+ "name": "message_consent_kind",
+ "schema": "public",
+ "values": [
+ "opt_in",
+ "opt_out",
+ "help"
+ ]
+ },
+ "public.message_direction": {
+ "name": "message_direction",
+ "schema": "public",
+ "values": [
+ "inbound",
+ "outbound"
+ ]
+ },
+ "public.message_status": {
+ "name": "message_status",
+ "schema": "public",
+ "values": [
+ "queued",
+ "sent",
+ "delivered",
+ "failed",
+ "received"
+ ]
+ },
+ "public.messaging_channel": {
+ "name": "messaging_channel",
+ "schema": "public",
+ "values": [
+ "sms",
+ "mms"
+ ]
+ },
"public.payment_method": {
"name": "payment_method",
"schema": "public",
@@ -2115,6 +3121,16 @@
"other"
]
},
+ "public.pet_size_category": {
+ "name": "pet_size_category",
+ "schema": "public",
+ "values": [
+ "small",
+ "medium",
+ "large",
+ "xlarge"
+ ]
+ },
"public.staff_role": {
"name": "staff_role",
"schema": "public",
@@ -2145,4 +3161,4 @@
"schemas": {},
"tables": {}
}
-}
+}
\ No newline at end of file
diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json
index ff0c252..e8b8b8d 100644
--- a/packages/db/migrations/meta/_journal.json
+++ b/packages/db/migrations/meta/_journal.json
@@ -220,9 +220,9 @@
"breakpoints": true
},
{
- "idx": 31,
+ "idx": 32,
"version": "7",
- "when": 1778818472097,
+"when": 1778818472097,
"tag": "0032_staff_read_at",
"breakpoints": true
}
diff --git a/packages/db/src/factories.ts b/packages/db/src/factories.ts
index 88609f2..f12f0db 100644
--- a/packages/db/src/factories.ts
+++ b/packages/db/src/factories.ts
@@ -103,6 +103,8 @@ export function buildPet(overrides: Partial
& { clientId: string }): Pet
photoKey: null,
photoUploadedAt: null,
image: null,
+ sizeCategory: null,
+ coatType: null,
createdAt: new Date("2025-01-01T00:00:00Z"),
updatedAt: new Date("2025-01-01T00:00:00Z"),
};
@@ -117,6 +119,7 @@ export function buildService(overrides: Partial = {}): ServiceRow {
description: "A grooming service",
basePriceCents: 6500,
durationMinutes: 60,
+ defaultBufferMinutes: 0,
active: true,
createdAt: new Date("2025-01-01T00:00:00Z"),
updatedAt: new Date("2025-01-01T00:00:00Z"),
@@ -148,6 +151,7 @@ export function buildAppointment(
confirmationStatus: "pending",
confirmedAt: null,
cancelledAt: null,
+ bufferMinutes: 0,
confirmationToken: null,
customerNotes: null,
createdAt: new Date("2025-01-01T00:00:00Z"),
diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts
index 8b3b01f..346942c 100644
--- a/packages/db/src/index.ts
+++ b/packages/db/src/index.ts
@@ -4,7 +4,7 @@ import * as schema from "./schema.js";
export * from "./schema.js";
export { encryptSecret, decryptSecret } from "./crypto.js";
-export { and, asc, desc, eq, exists, gte, gt, ilike, inArray, isNull, lt, lte, ne, or, sql } from "drizzle-orm";
+export { and, asc, count, desc, eq, exists, gte, gt, ilike, inArray, isNull, lt, lte, ne, or, sql } from "drizzle-orm";
let _db: ReturnType | null = null;
diff --git a/packages/db/src/schema.ts b/packages/db/src/schema.ts
index c4e2f1a..ff7cb81 100644
--- a/packages/db/src/schema.ts
+++ b/packages/db/src/schema.ts
@@ -48,6 +48,22 @@ export const clientStatusEnum = pgEnum("client_status", [
"disabled",
]);
+export const petSizeCategoryEnum = pgEnum("pet_size_category", [
+ "small",
+ "medium",
+ "large",
+ "xlarge",
+]);
+
+export const coatTypeEnum = pgEnum("coat_type", [
+ "smooth",
+ "double",
+ "curly",
+ "wire",
+ "long",
+ "hairless",
+]);
+
// ─── Better-Auth Tables ──────────────────────────────────────────────────────
export const user = pgTable("user", {
@@ -146,6 +162,8 @@ export const pets = pgTable(
photoKey: text("photo_key"),
photoUploadedAt: timestamp("photo_uploaded_at"),
image: text("image"),
+ sizeCategory: petSizeCategoryEnum("size_category"),
+ coatType: coatTypeEnum("coat_type"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
},
@@ -158,6 +176,7 @@ export const services = pgTable("services", {
description: text("description"),
basePriceCents: integer("base_price_cents").notNull(),
durationMinutes: integer("duration_minutes").notNull(),
+ defaultBufferMinutes: integer("default_buffer_minutes").notNull().default(0),
active: boolean("active").notNull().default(true),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
@@ -240,6 +259,8 @@ export const appointments = pgTable(
confirmationStatus: text("confirmation_status").notNull().default("pending"),
confirmedAt: timestamp("confirmed_at"),
cancelledAt: timestamp("cancelled_at"),
+ // Per-appointment buffer time (may be overridden from service default or bufferTimeRules)
+ bufferMinutes: integer("buffer_minutes").notNull().default(0),
// Token for tokenized email confirm/cancel links (no auth required)
confirmationToken: text("confirmation_token").unique(),
// Customer-provided note visible to groomer (500 char max, editable until appointment starts)
@@ -442,9 +463,9 @@ export const conversations = pgTable(
businessNumber: text("business_number").notNull(),
lastMessageAt: timestamp("last_message_at"),
status: text("status").notNull().default("active"),
+ staffReadAt: timestamp("staff_read_at"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
- staffReadAt: timestamp("staff_read_at"),
},
(t) => [
index("idx_conversations_business_id_last_message_at").on(
@@ -600,3 +621,22 @@ export const authProviderConfig = pgTable("auth_provider_config", {
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
});
+
+export const bufferTimeRules = pgTable(
+ "buffer_time_rules",
+ {
+ id: uuid("id").primaryKey().defaultRandom(),
+ serviceId: uuid("service_id")
+ .notNull()
+ .references(() => services.id, { onDelete: "cascade" }),
+ sizeCategory: petSizeCategoryEnum("size_category"),
+ coatType: coatTypeEnum("coat_type"),
+ bufferMinutes: integer("buffer_minutes").notNull(),
+ createdAt: timestamp("created_at").notNull().defaultNow(),
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
+ },
+ (t) => [
+ unique().on(t.serviceId, t.sizeCategory, t.coatType),
+ index("idx_buffer_rules_service_id").on(t.serviceId),
+ ]
+);