diff --git a/Components/admin/Csr/Modals/NewBookings.tsx b/Components/admin/Csr/Modals/NewBookings.tsx index 55bcabe..048af26 100644 --- a/Components/admin/Csr/Modals/NewBookings.tsx +++ b/Components/admin/Csr/Modals/NewBookings.tsx @@ -128,7 +128,7 @@ const ADD_ON_PRICES = { extraSlippers: 30, }; -const statusOptions = ["pending", "approved", "declined", "checked-in", "checked-out", "cancelled", "completed"]; +const statusOptions = ["pending", "approved", "declined", "checked-in", "checked-out", "cancelled", "completed", "failed"]; const paymentMethods = ["cash", "gcash", "bank-transfer", "credit-card"]; export default function NewBookingModal({ onClose, initialBooking, onSuccess }: NewBookingModalProps) { diff --git a/backend/controller/bookingController.ts b/backend/controller/bookingController.ts index 25bddf8..12efdb3 100644 --- a/backend/controller/bookingController.ts +++ b/backend/controller/bookingController.ts @@ -64,6 +64,7 @@ export const updateBookingDetails = async ( "checked-in", "completed", "cancelled", + "failed", ]; if (typeof status !== "undefined" && status !== null) { if (typeof status !== "string" || !validStatuses.includes(status)) { @@ -345,7 +346,8 @@ export interface Booking { | "confirmed" | "checked-in" | "completed" - | "cancelled"; + | "cancelled" + | "failed"; add_ons?: AddOnItem[]; created_at?: string; updated_at?: string; @@ -995,7 +997,7 @@ export const updateBookingStatus = async ( // If status is provided, validate it const validStatuses = [ "pending", "approved", "rejected", "confirmed", - "checked-in", "completed", "cancelled", + "checked-in", "completed", "cancelled", "failed", ]; if (typeof status !== "undefined" && status !== null) { if (typeof status !== "string" || !validStatuses.includes(status)) { @@ -1419,4 +1421,4 @@ export const getRoomBookings = async ( { status: 500 }, ); } -}; \ No newline at end of file +}; diff --git a/backend/migrations/2026-03-02-add-failed-booking-status.sql b/backend/migrations/2026-03-02-add-failed-booking-status.sql new file mode 100644 index 0000000..24726df --- /dev/null +++ b/backend/migrations/2026-03-02-add-failed-booking-status.sql @@ -0,0 +1,52 @@ +-- Staycation/backend/migrations/2026-03-02-add-failed-booking-status.sql +-- Migration: allow booking.status = 'failed' for edit/update flows. +-- +-- IMPORTANT: +-- - BACKUP your database before running this migration. +-- - Run in staging first. +-- - This script is idempotent for environments with varying constraint names. + +BEGIN; + +-- Drop existing booking status check constraint(s) regardless of generated name. +DO $$ +DECLARE + c RECORD; +BEGIN + FOR c IN + SELECT conname + FROM pg_constraint + WHERE conrelid = 'booking'::regclass + AND contype = 'c' + AND pg_get_constraintdef(oid) ILIKE '%status%' + AND pg_get_constraintdef(oid) ILIKE '%pending%' + AND pg_get_constraintdef(oid) ILIKE '%approved%' + LOOP + EXECUTE format('ALTER TABLE booking DROP CONSTRAINT IF EXISTS %I', c.conname); + END LOOP; +END +$$; + +ALTER TABLE booking + ADD CONSTRAINT booking_status_check + CHECK ( + status IN ( + 'pending', + 'approved', + 'rejected', + 'confirmed', + 'checked-in', + 'completed', + 'cancelled', + 'failed' + ) + ); + +COMMIT; + +-- Verify constraint now allows failed. +SELECT conname, pg_get_constraintdef(oid) +FROM pg_constraint +WHERE conrelid = 'booking'::regclass + AND contype = 'c' + AND pg_get_constraintdef(oid) ILIKE '%status%'; diff --git a/backend/models/bookings.sql b/backend/models/bookings.sql index 494cd91..9bf68d8 100644 --- a/backend/models/bookings.sql +++ b/backend/models/bookings.sql @@ -22,7 +22,8 @@ CREATE TABLE booking ( 'confirmed', 'checked-in', 'completed', - 'cancelled' + 'cancelled', + 'failed' )), rejection_reason TEXT,