Skip to main content
Glama
alcylu

Nightlife Search

by alcylu

get_vip_booking_status

Check VIP booking confirmation status for nightlife venues by providing your booking request ID and contact information.

Instructions

Fetch VIP booking status from the venue booking workflow. Requires booking request ID and matching customer email or phone.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
booking_request_idYes
customer_emailNo
customer_phoneNo

Implementation Reference

  • The function `getVipBookingStatus` implements the core logic for fetching a VIP booking request status, validating ownership with customer email or phone, and retrieving status history and deposit information.
    export async function getVipBookingStatus(
      supabase: SupabaseClient,
      input: GetVipBookingStatusInput,
    ): Promise<VipBookingStatusResult> {
      const { bookingRequestId, customerEmail, customerPhone } = normalizeStatusLookupContacts(input);
    
      const { data: booking, error: bookingError } = await supabase
        .from("vip_booking_requests")
        .select("id,status,updated_at,status_message,customer_email,customer_phone")
        .eq("id", bookingRequestId)
        .maybeSingle<VipBookingLookupRow>();
    
      if (bookingError) {
        throw new NightlifeError("DB_QUERY_FAILED", "Failed to fetch VIP booking request.", {
          cause: bookingError.message,
        });
      }
    
      if (!booking) {
        throw new NightlifeError("BOOKING_REQUEST_NOT_FOUND", "VIP booking request not found.");
      }
    
      const emailMatches = !!customerEmail && booking.customer_email === customerEmail;
      const phoneMatches = !!customerPhone && booking.customer_phone === customerPhone;
      if (!emailMatches && !phoneMatches) {
        throw new NightlifeError("BOOKING_REQUEST_NOT_FOUND", "VIP booking request not found.");
      }
    
      const { data: events, error: eventsError } = await supabase
        .from("vip_booking_status_events")
        .select("to_status,note,created_at")
        .eq("booking_request_id", booking.id)
        .order("created_at", { ascending: true })
        .limit(20);
    
      if (eventsError) {
        throw new NightlifeError("DB_QUERY_FAILED", "Failed to fetch VIP booking history.", {
          cause: eventsError.message,
        });
      }
    
      const history = ((events || []) as VipStatusEventRow[])
        .filter((row) => isVipStatus(row.to_status))
        .map((row) => ({
          status: row.to_status,
          at: row.created_at,
          note: row.note,
        }));
    
      const latestHistory = history[history.length - 1];
    
      // Load deposit info
      let depositStatus: string | null = null;
      let depositAmountJpy: number | null = null;
      let depositPaymentUrl: string | null = null;
    
      const { data: depositRow } = await supabase
        .from("vip_booking_deposits")
        .select("status,amount_jpy,stripe_checkout_url")
        .eq("booking_request_id", booking.id)
        .maybeSingle();
    
      if (depositRow) {
        depositStatus = depositRow.status as string;
        depositAmountJpy = depositRow.amount_jpy as number;
        depositPaymentUrl =
          depositRow.status === "pending" ? (depositRow.stripe_checkout_url as string | null) : null;
      } else {
        // Check booking's denormalized deposit_status (e.g., not_required)
        const { data: bookingDeposit } = await supabase
          .from("vip_booking_requests")
          .select("deposit_status")
          .eq("id", booking.id)
          .single();
        if (bookingDeposit?.deposit_status) {
          depositStatus = bookingDeposit.deposit_status as string;
        }
      }
    
      return {
        booking_request_id: booking.id,
        status: booking.status,
        last_updated_at: booking.updated_at,
        status_message: booking.status_message,
        latest_note: latestHistory?.note || null,
        history,
        deposit_status: depositStatus,
        deposit_amount_jpy: depositAmountJpy,
        deposit_payment_url: depositPaymentUrl,
      };
    }
  • The tool `get_vip_booking_status` is registered in `src/tools/vipBookings.ts`. It maps the `vip_booking_statusInputSchema` to the `getVipBookingStatus` service function.
    server.registerTool(
      "get_vip_booking_status",
      {
        description:
          "Fetch VIP booking status from the venue booking workflow. Requires booking request ID and matching customer email or phone.",
        inputSchema: vipBookingStatusInputSchema,
        outputSchema: vipBookingStatusOutputSchema,
      },
      async (args) => runTool(
        "get_vip_booking_status",
        vipBookingStatusOutputSchema,
        async () => getVipBookingStatus(deps.supabase, args),
      ),
    );
  • Input and output schemas for the `get_vip_booking_status` tool defined using Zod.
    export const vipBookingStatusInputSchema = {
      booking_request_id: z.string().min(1),
      customer_email: z.string().optional(),
      customer_phone: z.string().optional(),
    };
    
    export const vipBookingStatusOutputSchema = z.object({
      booking_request_id: z.string(),
      status: z.enum(["submitted", "in_review", "deposit_required", "confirmed", "rejected", "cancelled"]),
      last_updated_at: z.string(),
      status_message: z.string(),
      latest_note: z.string().nullable(),
      history: z.array(vipBookingHistorySchema),
      deposit_status: z.string().nullable(),
      deposit_amount_jpy: z.number().nullable(),
      deposit_payment_url: z.string().nullable(),
    });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alcylu/nightlife-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server