feat: add waitlist entries table and API routes (GRO-105)
- Migration 0015: new waitlist_entries table with indexes - Schema update: add waitlistEntries table and waitlistStatusEnum - Staff API: GET /api/waitlist, GET /api/waitlist/:id - Portal API: POST /api/waitlist (via impersonation session), DELETE /api/waitlist/:id - Note: cancellation hook and email notification pending Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE waitlist_entries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
client_id UUID NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
|
||||
pet_id UUID NOT NULL REFERENCES pets(id) ON DELETE CASCADE,
|
||||
service_id UUID NOT NULL REFERENCES services(id) ON DELETE CASCADE,
|
||||
preferred_date DATE NOT NULL,
|
||||
preferred_time TIME NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
notified_at TIMESTAMPTZ,
|
||||
expires_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_waitlist_client_id ON waitlist_entries (client_id);
|
||||
CREATE INDEX idx_waitlist_preferred_date ON waitlist_entries (preferred_date);
|
||||
CREATE INDEX idx_waitlist_status ON waitlist_entries (status) WHERE status = 'active';
|
||||
CREATE UNIQUE INDEX idx_waitlist_active_unique ON waitlist_entries (client_id, pet_id, service_id, preferred_date, preferred_time) WHERE status = 'active';
|
||||
@@ -312,3 +312,38 @@ export const groomingVisitLogs = pgTable("grooming_visit_logs", {
|
||||
groomedAt: timestamp("groomed_at").notNull().defaultNow(),
|
||||
createdAt: timestamp("created_at").notNull().defaultNow(),
|
||||
});
|
||||
|
||||
export const waitlistStatusEnum = pgEnum("waitlist_status", [
|
||||
"active",
|
||||
"notified",
|
||||
"expired",
|
||||
"cancelled",
|
||||
]);
|
||||
|
||||
export const waitlistEntries = pgTable(
|
||||
"waitlist_entries",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
clientId: uuid("client_id")
|
||||
.notNull()
|
||||
.references(() => clients.id, { onDelete: "cascade" }),
|
||||
petId: uuid("pet_id")
|
||||
.notNull()
|
||||
.references(() => pets.id, { onDelete: "cascade" }),
|
||||
serviceId: uuid("service_id")
|
||||
.notNull()
|
||||
.references(() => services.id, { onDelete: "cascade" }),
|
||||
preferredDate: text("preferred_date").notNull(),
|
||||
preferredTime: text("preferred_time").notNull(),
|
||||
status: waitlistStatusEnum("status").notNull().default("active"),
|
||||
notifiedAt: timestamp("notified_at"),
|
||||
expiresAt: timestamp("expires_at"),
|
||||
createdAt: timestamp("created_at").notNull().defaultNow(),
|
||||
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
||||
},
|
||||
(t) => [
|
||||
index("idx_waitlist_client_id").on(t.clientId),
|
||||
index("idx_waitlist_preferred_date").on(t.preferredDate),
|
||||
index("idx_waitlist_status").on(t.status),
|
||||
]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user