{"openapi":"3.0.1","info":{"title":"Gserve API","description":"API documentation for Gserve application","version":"1.0"},"servers":[{"url":"http://api.gservetech.com","description":"Generated server url"}],"tags":[{"name":"User Management","description":"APIs for managing users"},{"name":"Menu Item Controller","description":"Manage menu items for a restaurant"},{"name":"Visitor Management","description":"APIs for managing visitor data"},{"name":"Promotion Events","description":"Public endpoints for promotion events"},{"name":"Promo Codes (Admin)","description":"Admin endpoints for managing Friday promo codes"},{"name":"Order Management","description":"APIs for managing orders and payments"},{"name":"Food Order Controller","description":"Manage food orders for a specific restaurant"},{"name":"Restaurant Visitor Controller","description":"Manage restaurant visitors data"},{"name":"Promotion Events (Admin)","description":"Admin endpoints for managing promotion events"},{"name":"Customer Controller","description":"Manage customer data and view their orders for a specific restaurant"},{"name":"Product Controller","description":"Product management API with JSON input/output"},{"name":"Restaurant Controller","description":"Manage restaurant data"},{"name":"Example Controller","description":"Example endpoints for Swagger documentation"},{"name":"Guest Orders","description":"API endpoints for guest checkout and order management"}],"paths":{"/api/users/{clerkId}":{"get":{"tags":["User Management"],"summary":"Get user by Clerk ID","description":"Retrieves user details by Clerk ID.","operationId":"getUserByClerkId","parameters":[{"name":"clerkId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}}},"put":{"tags":["User Management"],"summary":"Update a user","description":"Updates user details.","operationId":"updateUser","parameters":[{"name":"clerkId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}}},"delete":{"tags":["User Management"],"summary":"Delete a user","description":"Deletes a user by Clerk ID.","operationId":"deleteUser","parameters":[{"name":"clerkId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/api/restaurants/{restaurantId}/customers/{customerPhone}":{"get":{"tags":["Customer Controller"],"summary":"Get customer within restaurant context","operationId":"getCustomer","parameters":[{"name":"restaurantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"customerPhone","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"put":{"tags":["Customer Controller"],"summary":"Update customer within restaurant context","operationId":"updateCustomer","parameters":[{"name":"restaurantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"customerPhone","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}},"delete":{"tags":["Customer Controller"],"summary":"Delete customer within restaurant context","operationId":"deleteCustomer","parameters":[{"name":"restaurantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"customerPhone","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/restaurants/{phoneNumber}/menu-items/{menuItemId}":{"get":{"tags":["Menu Item Controller"],"summary":"Get a menu item by ID","description":"Retrieve a specific menu item, including all its details.","operationId":"getMenuItemById","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"menuItemId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Menu item retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"}}}},"404":{"description":"Menu item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"}}}}}},"put":{"tags":["Menu Item Controller"],"summary":"Update a menu item","description":"Updates an existing menu item.","operationId":"updateMenuItem","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"menuItemId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"}}},"required":true},"responses":{"200":{"description":"Menu item updated successfully","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"404":{"description":"Menu item not found","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}},"delete":{"tags":["Menu Item Controller"],"summary":"Delete a menu item","description":"Removes a menu item.","operationId":"deleteMenuItem","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"menuItemId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Menu item deleted successfully","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"404":{"description":"Menu item not found","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}},"patch":{"tags":["Menu Item Controller"],"summary":"Partially update a menu item","description":"Updates specified fields of a menu item.","operationId":"patchMenuItem","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"menuItemId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"Menu item patched successfully","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"404":{"description":"Menu item not found","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/restaurants/update":{"put":{"tags":["Restaurant Controller"],"summary":"Update a restaurant","description":"Updates the restaurant details based on the phone number.","operationId":"updateRestaurant","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Restaurant"}}},"required":true},"responses":{"200":{"description":"Successfully updated","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"404":{"description":"Restaurant not found","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/admin/promotion-events/{eventId}":{"put":{"tags":["Promotion Events (Admin)"],"summary":"Update a promotion event","operationId":"updatePromotionEvent","parameters":[{"name":"eventId","in":"path","description":"Promotion event ID","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionEventCreateRequest"}}},"required":true},"responses":{"200":{"description":"Promotion event updated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromotionEvent"}}}},"404":{"description":"Promotion event not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromotionEvent"}}}}}},"delete":{"tags":["Promotion Events (Admin)"],"summary":"Delete a promotion event","operationId":"deletePromotionEvent","parameters":[{"name":"eventId","in":"path","description":"Promotion event ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Promotion event deleted","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"404":{"description":"Promotion event not found","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/visits":{"get":{"tags":["Visitor Management"],"summary":"Get all visits","description":"Retrieves a list of all visits with visit data in JSON format.","operationId":"getAllVisits","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VisitDTO"}}}}}}},"post":{"tags":["Visitor Management"],"summary":"Create a new visit log","description":"Saves a visitor's details and returns the saved visit object.","operationId":"createVisit","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Visit"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Visit"}}}}}}},"/api/users":{"get":{"tags":["User Management"],"summary":"Get all users","description":"Retrieves a JSON list of all users.","operationId":"getAllUsers","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserDTO"}}}}}}},"post":{"tags":["User Management"],"summary":"Create a new user","description":"Adds a new user to the database.","operationId":"createUser","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDTO"}}}}}}},"/api/restaurants/{restaurantPhoneNumber}/food-orders/create":{"post":{"tags":["Food Order Controller"],"summary":"Create a new food order","operationId":"createOrder","parameters":[{"name":"restaurantPhoneNumber","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOrder"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/restaurants/{restaurantId}/customers/login":{"post":{"tags":["Customer Controller"],"summary":"Login customer within restaurant context","operationId":"loginCustomer","parameters":[{"name":"restaurantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/restaurants/{restaurantId}/customers/create":{"post":{"tags":["Customer Controller"],"summary":"Create customer for a restaurant","operationId":"createCustomer","parameters":[{"name":"restaurantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/restaurants/{phoneNumber}/visitors/create":{"post":{"tags":["Restaurant Visitor Controller"],"summary":"Add a restaurant visitor","description":"Adds a visitor entry for a specific restaurant.","operationId":"addVisitor","parameters":[{"name":"phoneNumber","in":"path","description":"Phone number of the restaurant","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"201":{"description":"Visitor added successfully","content":{"application/json":{"schema":{"type":"object","example":{"message":"Visitor added successfully"}}}}},"400":{"description":"Invalid input data provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/restaurants/{phoneNumber}/menu-items/create":{"post":{"tags":["Menu Item Controller"],"summary":"Add a new menu item","description":"Adds a new menu item for a restaurant.","operationId":"createMenuItem","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"}}},"required":true},"responses":{"200":{"description":"Menu item created successfully","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/restaurants/create":{"post":{"tags":["Restaurant Controller"],"summary":"Create a new restaurant","description":"Creates a restaurant with details including address and operating hours in JSON format.","operationId":"createRestaurant","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Restaurant"}}},"required":true},"responses":{"200":{"description":"Successfully created","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/orders/{orderNumber}/capture":{"post":{"tags":["Order Management"],"summary":"Capture PayPal payment by order number","operationId":"capturePayPalOrder","parameters":[{"name":"orderNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/webhook":{"post":{"tags":["Order Management"],"summary":"Handle PayPal Webhook","operationId":"handlePayPalWebhook","parameters":[{"name":"Paypal-Transmission-Sig","in":"header","required":false,"schema":{"type":"string"}},{"name":"Paypal-Transmission-Id","in":"header","required":false,"schema":{"type":"string"}},{"name":"Paypal-Transmission-Time","in":"header","required":false,"schema":{"type":"string"}},{"name":"Paypal-Cert-Url","in":"header","required":false,"schema":{"type":"string"}},{"name":"Paypal-Auth-Algo","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/orders/webhook/square":{"post":{"tags":["Order Management"],"summary":"Handle Square payment webhook","operationId":"handleSquareWebhook","requestBody":{"content":{"application/json":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/api/orders/validate-promo":{"post":{"tags":["Order Management"],"summary":"Validate a promo code","description":"Validates a promo code for Friday use","operationId":"validatePromoCode","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoCodeValidationRequest"}}},"required":true},"responses":{"200":{"description":"Validation result","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCodeValidationResponse"}}}},"400":{"description":"Invalid request data","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCodeValidationResponse"}}}}}}},"/api/orders/square/init":{"post":{"tags":["Order Management"],"summary":"Create Square Checkout","operationId":"createOrderAndSquareCheckout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/paypal/init":{"post":{"tags":["Order Management"],"summary":"Create order and PayPal transaction","operationId":"createOrderAndPaypalTransaction","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/paypal/create":{"post":{"tags":["Order Management"],"summary":"Create PayPal Order (Alternative)","operationId":"createPaypalOrder","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/create":{"post":{"tags":["Order Management"],"summary":"Create a new order","description":"Adds order to DB, sends confirmation email.","operationId":"createOrder_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/admin/promotion-events":{"get":{"tags":["Promotion Events (Admin)"],"summary":"Get all promotion events for a restaurant","operationId":"getPromotionEvents","parameters":[{"name":"restaurantPhoneNumber","in":"query","description":"Restaurant phone number","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Promotion events retrieved","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromotionEventResponse"}}}}}}},"post":{"tags":["Promotion Events (Admin)"],"summary":"Create a promotion event","operationId":"createPromotionEvent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionEventCreateRequest"}}},"required":true},"responses":{"201":{"description":"Promotion event created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromotionEvent"}}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromotionEvent"}}}}}}},"/api/admin/promo-codes":{"get":{"tags":["Promo Codes (Admin)"],"summary":"Get all promo codes","description":"Retrieves all promo codes","operationId":"getAllPromoCodes","responses":{"200":{"description":"Promo codes retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromoCode"}}}}}}},"post":{"tags":["Promo Codes (Admin)"],"summary":"Create a new promo code","description":"Creates a weekly Friday promo code for a winner user","operationId":"createPromoCode","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoCodeCreateRequest"}}},"required":true},"responses":{"201":{"description":"Promo code created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCode"}}}},"500":{"description":"Internal server error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCode"}}}},"400":{"description":"Invalid request data","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCode"}}}}}}},"/api/admin/promo-codes/{code}/invalidate":{"post":{"tags":["Promo Codes (Admin)"],"summary":"Invalidate a promo code","description":"Marks a promo code as inactive","operationId":"invalidatePromoCode","parameters":[{"name":"code","in":"path","description":"Promo code to invalidate","required":true,"schema":{"type":"string"}}],"responses":{"404":{"description":"Promo code not found","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"200":{"description":"Promo code invalidated successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders/validate-promo":{"post":{"tags":["Guest Orders"],"summary":"Validate a promo code","description":"Validates a promo code for Friday use","operationId":"validatePromoCode_1","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoCodeValidationRequest"}}},"required":true},"responses":{"400":{"description":"Invalid request data","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCodeValidationResponse"}}}},"200":{"description":"Validation result","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCodeValidationResponse"}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders/create":{"post":{"tags":["Guest Orders"],"summary":"Create a new guest order","description":"Creates a new order for a guest user without authentication","operationId":"createGuestOrder","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestOrderCreateRequest"}}},"required":true},"responses":{"500":{"description":"Internal server error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}},"400":{"description":"Invalid request data","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}},"201":{"description":"Order created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}}}}},"/api/restaurants/{restaurantPhoneNumber}/food-orders/{orderId}":{"get":{"tags":["Food Order Controller"],"summary":"Get a food order by ID","operationId":"getOrderById","parameters":[{"name":"restaurantPhoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"orderId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["Food Order Controller"],"summary":"Delete a food order","operationId":"deleteOrder","parameters":[{"name":"restaurantPhoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"orderId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}},"patch":{"tags":["Food Order Controller"],"summary":"Patch a food order","operationId":"patchOrder","parameters":[{"name":"restaurantPhoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"orderId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders/{orderId}/status":{"patch":{"tags":["Guest Orders"],"summary":"Update guest order status","description":"Updates the status of a guest order","operationId":"updateOrderStatus","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}},{"name":"orderId","in":"path","description":"Order ID","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"404":{"description":"Order not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}},"200":{"description":"Status updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}},"400":{"description":"Invalid status","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}}}}},"/api/restaurants/{restaurantPhoneNumber}/food-orders/customer/{customerPhoneNumber}":{"get":{"tags":["Food Order Controller"],"summary":"Get all orders with items for a specific customer at this restaurant","operationId":"getOrdersByCustomerAtRestaurant","parameters":[{"name":"restaurantPhoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"customerPhoneNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/restaurants/{restaurantId}/customers/customer/{customerPhoneNumber}/orders":{"get":{"tags":["Customer Controller"],"summary":"Get all orders for a specific customer (IGNORING restaurant in path)","description":"**WARNING:** Retrieves ALL food orders placed by a given customer phone number across ALL restaurants. The {restaurantId} in the path is ignored by this method's query.","operationId":"getOrdersForCustomerAtRestaurant","parameters":[{"name":"restaurantId","in":"path","description":"ID (Phone Number) of the restaurant (IGNORED by this endpoint's query)","required":true,"schema":{"type":"string"}},{"name":"customerPhoneNumber","in":"path","description":"Phone number of the customer whose orders are to be retrieved","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Orders retrieved successfully (list may be empty)","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid customer phone number format in path","content":{"application/json":{"schema":{"type":"object"}}}},"500":{"description":"Internal server error or database schema mismatch","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/restaurants/{phoneNumber}":{"get":{"tags":["Restaurant Controller"],"summary":"Retrieve a restaurant by phone number","description":"Fetches restaurant details by phone number.","operationId":"getRestaurant","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Restaurant"}}}},"404":{"description":"Restaurant not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/Restaurant"}}}}}}},"/api/restaurants/{phoneNumber}/visitors":{"get":{"tags":["Restaurant Visitor Controller"],"summary":"Get all visitors by restaurant phone number (latest first)","description":"Retrieves a list of all visitor records associated with a specific restaurant, identified by its phone number. The list is ordered by visit time, with the most recent visits appearing first.","operationId":"getAllVisitors","parameters":[{"name":"phoneNumber","in":"path","description":"The phone number of the restaurant.","required":true,"schema":{"type":"string"},"example":"+14161234567"}],"responses":{"500":{"description":"Internal server error occurred during data retrieval or processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"Successfully retrieved the list of visitors (ordered latest first). The response is a JSON array.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/restaurants/{phoneNumber}/visitors/{id}":{"get":{"tags":["Restaurant Visitor Controller"],"summary":"Get a specific visitor","description":"Retrieve a specific visitor by ID for the given restaurant.","operationId":"getVisitorById","parameters":[{"name":"phoneNumber","in":"path","description":"Phone number of the restaurant","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","description":"Unique ID of the visitor","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Visitor retrieved successfully","content":{"application/json":{"schema":{"type":"string"}}}},"404":{"description":"Visitor not found for this restaurant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/restaurants/{phoneNumber}/menu-items/slug/{slug}":{"get":{"tags":["Menu Item Controller"],"summary":"Get a menu item by slug","description":"Retrieve a specific menu item by its SEO-friendly slug. This is the recommended endpoint for frontend product pages.","operationId":"getMenuItemBySlug","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Menu item retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"}}}},"404":{"description":"Menu item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"}}}}}}},"/api/restaurants/{phoneNumber}/menu-items/allmenus":{"get":{"tags":["Menu Item Controller"],"summary":"List all menu items","description":"Retrieves all menu items for a restaurant.","operationId":"getMenuItems","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Menu items retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":{"type":"object"}}}}}}}}},"/api/products":{"get":{"tags":["Product Controller"],"summary":"List all products","description":"Retrieve all products as a structured JSON array","operationId":"listAllProducts","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/products/{id}":{"get":{"tags":["Product Controller"],"summary":"Get product by ID","description":"Retrieve a single product as JSON","operationId":"getProductById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/orders/{orderNumber}":{"get":{"tags":["Order Management"],"summary":"Get order by number","operationId":"getOrderByNumber","parameters":[{"name":"orderNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["Order Management"],"summary":"Delete order by number","operationId":"deleteOrderByNumber","parameters":[{"name":"orderNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/clerk/{clerkId}":{"get":{"tags":["Order Management"],"summary":"Get orders by Clerk ID","operationId":"getOrdersByClerkId","parameters":[{"name":"clerkId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/clerk/{clerkId}/address":{"get":{"tags":["Order Management"],"summary":"Get full address by Clerk ID","operationId":"getAddressByClerkId","parameters":[{"name":"clerkId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/orders/by-customer/{customerPhoneNumber}":{"get":{"tags":["Order Management"],"summary":"Get orders by Customer Phone Number","description":"Retrieves all orders associated with a specific Customer Phone Number including full reference data.","operationId":"getOrdersByCustomerPhone","parameters":[{"name":"customerPhoneNumber","in":"path","description":"Phone number of the customer whose orders are to be retrieved","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Orders retrieved successfully (list may be empty)","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid phone number format in path","content":{"application/json":{"schema":{"type":"object"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No orders found for the given customer phone number","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/hello":{"get":{"tags":["Example Controller"],"summary":"Get Hello Message","description":"Returns a hello world message","operationId":"sayHello","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/api/admin/promo-codes/{code}":{"get":{"tags":["Promo Codes (Admin)"],"summary":"Get promo code by code","description":"Retrieves a specific promo code","operationId":"getPromoCode","parameters":[{"name":"code","in":"path","description":"Promo code","required":true,"schema":{"type":"string"}}],"responses":{"404":{"description":"Promo code not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCode"}}}},"200":{"description":"Promo code found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromoCode"}}}}}},"delete":{"tags":["Promo Codes (Admin)"],"summary":"Delete a promo code","description":"Permanently deletes a promo code from the database","operationId":"deletePromoCode","parameters":[{"name":"code","in":"path","description":"Promo code to delete","required":true,"schema":{"type":"string"}}],"responses":{"404":{"description":"Promo code not found","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"200":{"description":"Promo code deleted successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/admin/promo-codes/usage-history":{"get":{"tags":["Promo Codes (Admin)"],"summary":"Get promo code usage history","description":"Retrieves all promo code usage history","operationId":"getAllUsageHistory","responses":{"200":{"description":"Usage history retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromoCodeUsageHistoryDTO"}}}}}}}},"/api/admin/promo-codes/usage-history/{code}":{"get":{"tags":["Promo Codes (Admin)"],"summary":"Get usage history for a promo code","description":"Retrieves usage history for a specific promo code","operationId":"getUsageHistoryByCode","parameters":[{"name":"code","in":"path","description":"Promo code","required":true,"schema":{"type":"string"}}],"responses":{"404":{"description":"Promo code not found","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromoCodeUsageHistoryDTO"}}}}},"200":{"description":"Usage history retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromoCodeUsageHistoryDTO"}}}}}}}},"/api/admin/promo-codes/usage-history/by-date-range":{"get":{"tags":["Promo Codes (Admin)"],"summary":"Get usage history by date range","description":"Retrieves usage history within a date range","operationId":"getUsageHistoryByDateRange","parameters":[{"name":"startDate","in":"query","description":"Start date (YYYY-MM-DD)","required":true,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","description":"End date (YYYY-MM-DD)","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Usage history retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromoCodeUsageHistoryDTO"}}}}}}}},"/api/admin/promo-codes/by-date":{"get":{"tags":["Promo Codes (Admin)"],"summary":"Get promo codes by date","description":"Retrieves promo codes for a specific date","operationId":"getPromoCodesByDate","parameters":[{"name":"date","in":"query","description":"Valid date (YYYY-MM-DD)","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Promo codes retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromoCode"}}}}}}}},"/api-external/restaurants/{restaurantPhone}/promotion-events/featured":{"get":{"tags":["Promotion Events"],"summary":"Get featured promotion event","operationId":"getFeaturedEvent","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}},{"name":"today","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Promotion event retrieved","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PromotionEventResponse"}}}}}}},"/api-external/restaurants/{restaurantPhone}/promotion-events/active":{"get":{"tags":["Promotion Events"],"summary":"Get active promotion events for a date","operationId":"getActiveEvents","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Promotion events retrieved","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromotionEventResponse"}}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders":{"get":{"tags":["Guest Orders"],"summary":"Get all guest orders for restaurant","description":"Retrieves all guest orders for a specific restaurant","operationId":"getRestaurantGuestOrders","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GuestOrderResponse"}}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders/{orderId}":{"get":{"tags":["Guest Orders"],"summary":"Get guest order by ID","description":"Retrieves details of a specific guest order","operationId":"getGuestOrder","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}},{"name":"orderId","in":"path","description":"Order ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"404":{"description":"Order not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}},"200":{"description":"Order found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GuestOrderResponse"}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders/by-phone":{"get":{"tags":["Guest Orders"],"summary":"Get guest orders by phone number","description":"Retrieves all orders for a specific guest phone number","operationId":"getGuestOrdersByPhone","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}},{"name":"phoneNumber","in":"query","description":"Guest phone number","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GuestOrderResponse"}}}}}}}},"/api-external/restaurants/{restaurantPhone}/guest-orders/by-email":{"get":{"tags":["Guest Orders"],"summary":"Get guest orders by email","description":"Retrieves all orders for a specific guest email","operationId":"getGuestOrdersByEmail","parameters":[{"name":"restaurantPhone","in":"path","description":"Restaurant phone number","required":true,"schema":{"type":"string"}},{"name":"email","in":"query","description":"Guest email address","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GuestOrderResponse"}}}}}}}},"/":{"get":{"tags":["root-controller"],"operationId":"home","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/api/restaurants/delete/{phoneNumber}":{"delete":{"tags":["Restaurant Controller"],"summary":"Delete a restaurant","description":"Deletes a restaurant by phone number.","operationId":"deleteRestaurant","parameters":[{"name":"phoneNumber","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully deleted","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"404":{"description":"Restaurant not found","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}}},"components":{"schemas":{"UserDTO":{"type":"object","properties":{"email":{"type":"string"},"fullname":{"type":"string"},"profileImageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"phone":{"type":"string"},"firstname":{"type":"string"},"lastname":{"type":"string"},"middlename":{"type":"string"},"clerkId":{"type":"string"}}},"Customer":{"required":["email","firstName","lastName","phoneNumber"],"type":"object","properties":{"phoneNumber":{"type":"string","description":"Unique phone number of the customer","example":"416-123-4567"},"firstName":{"type":"string","description":"Customer's first name","example":"John"},"lastName":{"type":"string","description":"Customer's last name","example":"Doe"},"email":{"type":"string","description":"Email address","example":"john.doe@example.com"},"passwordHash":{"type":"string","description":"Hashed password for secure storage","example":"$2a$10$abc123hashvalue"},"createdAt":{"type":"string","description":"Customer creation timestamp","format":"date-time","example":"2025-03-29T12:00:00Z"},"updatedAt":{"type":"string","description":"Last update timestamp","format":"date-time","example":"2025-03-30T10:15:00Z"}},"description":"Customer entity representing an individual user"},"MenuItem":{"type":"object","properties":{"menuItemId":{"type":"integer","description":"Unique ID of the menu item","format":"int64","example":1},"phoneNumber":{"type":"string","description":"Phone number of the associated restaurant","example":"416-781-8383"},"name":{"type":"string","description":"Name of the menu item","example":"Margherita Pizza"},"description":{"type":"string","description":"Description of the menu item","example":"Tomato, mozzarella, basil"},"price":{"type":"number","description":"Price of the menu item","example":14.99},"category":{"type":"string","description":"Category of the menu item","example":"Pizza"},"slug":{"type":"string","description":"SEO-friendly URL slug generated from the name","example":"margherita-pizza"},"imageUrl":{"type":"string","description":"URL of an image representing the menu item","example":"https://example.com/images/margherita.jpg"},"attributes":{"type":"object","additionalProperties":{"type":"object","description":"Additional attributes for the menu item stored as key-value pairs (JSONB)","example":{"spicyLevel":"mild","isVegetarian":true}},"description":"Additional attributes for the menu item stored as key-value pairs (JSONB)","example":{"spicyLevel":"mild","isVegetarian":true}},"createdAt":{"type":"string","description":"Timestamp when the menu item was created","format":"date-time","example":"2025-04-09T20:30:00Z"},"updatedAt":{"type":"string","description":"Timestamp when the menu item was last updated","format":"date-time","example":"2025-04-09T20:35:00Z"},"isAvailable":{"type":"boolean","description":"Availability status of the menu item","example":true}},"description":"Menu Item entity representing a single dish or product"},"JsonNode":{"type":"object","description":"Operating hours in JSON format","example":{"mon":"10:00-22:00","tue":"10:00-22:00"}},"Restaurant":{"required":["address","name","phoneNumber"],"type":"object","properties":{"phoneNumber":{"type":"string","description":"Primary phone number of the restaurant","example":"416-555-1234"},"name":{"type":"string","description":"Name of the restaurant","example":"Tasty Bites"},"address":{"$ref":"#/components/schemas/JsonNode"},"email":{"type":"string","description":"Restaurant email address","example":"contact@tastybites.ca"},"cuisineType":{"type":"string","description":"Type of cuisine","example":"Italian"},"description":{"type":"string","description":"Restaurant description","example":"A cozy Italian eatery serving fresh handmade pasta."},"logoUrl":{"type":"string","description":"URL to the restaurant's logo","example":"https://example.com/logo.png"},"operatingHours":{"$ref":"#/components/schemas/JsonNode"},"isActive":{"type":"boolean","description":"Whether the restaurant is active","example":true},"createdAt":{"type":"string","description":"Timestamp of when the restaurant was created","format":"date-time","example":"2025-03-29T15:00:00Z"},"updatedAt":{"type":"string","description":"Timestamp of the last update to the restaurant","format":"date-time","example":"2025-03-29T16:00:00Z"}},"description":"Restaurant model representing restaurant data stored in the database"},"PromotionEventCreateRequest":{"required":["discount_amount","event_date","menu_item_id","restaurant_phone_number"],"type":"object","properties":{"restaurant_phone_number":{"type":"string","description":"Restaurant phone number","example":"416-781-8383"},"event_date":{"type":"string","description":"Event date (YYYY-MM-DD)","format":"date","example":"2026-02-08"},"menu_item_id":{"type":"integer","description":"Eligible menu item ID","format":"int64","example":29},"discount_amount":{"minimum":0.00,"exclusiveMinimum":false,"type":"number","description":"Discount amount for the item","example":5.0},"title":{"type":"string","description":"Optional promotion title","example":"Super Bowl Wings Special"},"description":{"type":"string","description":"Optional promotion description"},"is_active":{"type":"boolean","description":"Whether the promotion is active","example":true}},"description":"Request to create or update a promotion event"},"PromotionEvent":{"required":["discount_amount","event_date","menu_item_id","restaurant_phone_number"],"type":"object","properties":{"promotion_event_id":{"type":"integer","description":"Unique identifier for the promotion event","format":"int64","readOnly":true,"example":1},"restaurant_phone_number":{"type":"string","description":"Restaurant phone number for this promotion event","example":"416-781-8383"},"event_date":{"type":"string","description":"Date when the promotion is valid (YYYY-MM-DD)","format":"date","example":"2026-02-08"},"menu_item_id":{"type":"integer","description":"Menu item eligible for the promo","format":"int64","example":29},"discount_amount":{"type":"number","description":"Discount amount for the item","example":5.0},"title":{"type":"string","description":"Optional title for the promotion","example":"Super Bowl Wings Special"},"description":{"type":"string","description":"Optional description for the promotion"},"is_active":{"type":"boolean","description":"Whether this promotion is active","example":true},"created_at":{"type":"string","description":"When the promotion was created","format":"date-time","readOnly":true},"updated_at":{"type":"string","description":"When the promotion was last updated","format":"date-time","readOnly":true}},"description":"Represents a date-based promotion event tied to a menu item"},"Visit":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"ip":{"type":"string"},"visitData":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"FoodOrder":{"required":["customer_phone_number","delivery_address","order_status","restaurant_phone_number","total_amount"],"type":"object","properties":{"order_id":{"type":"integer","description":"Unique identifier for the order (auto-generated).","format":"int64","readOnly":true,"example":101},"customer_phone_number":{"type":"string","description":"Phone number of the customer who placed the order.","example":"416-555-1234"},"customer_email":{"type":"string","description":"Email of the customer who placed the order (optional, used for promo code validation).","nullable":true,"example":"customer@example.com"},"restaurant_phone_number":{"type":"string","description":"Phone number of the restaurant receiving the order.","example":"905-111-2222"},"order_status":{"type":"string","description":"Current status of the order.","example":"PENDING"},"total_amount":{"type":"number","description":"Total amount for the order.","example":25.46},"order_timestamp":{"type":"string","description":"Timestamp when the order was placed by the system.","format":"date-time","readOnly":true,"example":"2025-04-02T18:55:00.123Z"},"delivery_address":{"$ref":"#/components/schemas/FoodOrderAddress"},"special_instructions":{"type":"string","description":"Special instructions for the order.","nullable":true,"example":"Leave at front porch if no answer."},"estimated_delivery_time":{"type":"string","description":"Estimated time the order will be delivered.","format":"date-time","nullable":true,"example":"2025-04-02T19:45:00Z"},"actual_delivery_time":{"type":"string","description":"Actual time the order was delivered.","format":"date-time","nullable":true,"example":"2025-04-02T19:42:00Z"},"created_at":{"type":"string","description":"Timestamp when the order record was created in the DB.","format":"date-time","readOnly":true},"updated_at":{"type":"string","description":"Timestamp when the order record was last updated in the DB.","format":"date-time","readOnly":true},"delivery_method":{"type":"string","description":"Method of delivery (e.g., 'DELIVERY', 'PICKUP').","nullable":true,"example":"DELIVERY"},"promo_code":{"type":"string","description":"Promo code applied to this order.","nullable":true,"example":"FRIDAY20251027"},"promotional_discount":{"type":"number","description":"Promotional discount amount applied via promo code.","nullable":true,"example":20.0},"orderItems":{"type":"array","description":"List of items included in the order.","items":{"$ref":"#/components/schemas/OrderItem"}}},"description":"Represents a complete food order with its details and items."},"FoodOrderAddress":{"required":["city","country","postalCode","province","street"],"type":"object","properties":{"street":{"type":"string","example":"100 University Ave"},"city":{"type":"string","example":"Toronto"},"province":{"type":"string","example":"ON"},"postalCode":{"type":"string","example":"M5J 2Y1"},"country":{"type":"string","example":"Canada"}},"description":"Represents a delivery address."},"OrderItem":{"required":["itemSubtotal","menuItemId","priceAtOrder","quantity"],"type":"object","properties":{"orderItemId":{"type":"integer","description":"Unique identifier for this line item instance.","format":"int64","readOnly":true},"menuItemId":{"type":"integer","description":"Identifier linking to the menu item.","format":"int32","example":20},"productName":{"type":"string","description":"Name of the menu item.","readOnly":true,"example":"MEAT LASAGNA"},"quantity":{"type":"integer","description":"Number of this item ordered.","format":"int32","example":1},"priceAtOrder":{"type":"number","description":"Price per unit of this item at the time of order.","example":15.49},"itemSubtotal":{"type":"number","description":"Subtotal for this line item (quantity * priceAtOrder).","example":15.49},"itemInstructions":{"type":"string","description":"Special instructions specific to this item.","nullable":true,"example":"Extra sauce if possible"}},"description":"Represents an item within a food order."},"ErrorResponse":{"type":"object","properties":{"message":{"type":"string"}}},"PromoCodeValidationRequest":{"required":["promo_code","user_email"],"type":"object","properties":{"promo_code":{"type":"string","description":"Promo code to validate","example":"FRIDAY20251027"},"user_email":{"type":"string","description":"Email of the user attempting to use the promo code","example":"user@example.com"}},"description":"Request to validate a promo code"},"PromoCodeValidationResponse":{"type":"object","properties":{"valid":{"type":"boolean","description":"Whether the promo code is valid","example":true},"discount_amount":{"type":"number","description":"Discount amount if valid","example":15.0},"message":{"type":"string","description":"Validation message","example":"Promo code applied successfully"},"promo_code_id":{"type":"integer","description":"ID of the promo code if valid","format":"int64"}},"description":"Response for promo code validation"},"OrderDTO":{"type":"object","properties":{"orderNumber":{"type":"string"},"clerkId":{"type":"string"},"customerPhoneNumber":{"type":"string"},"restaurantPhoneNumber":{"type":"string"},"totalPrice":{"type":"number"},"currencyCode":{"type":"string"},"amountDiscount":{"type":"number"},"orderStatusId":{"type":"integer","format":"int32"},"orderDate":{"type":"string","format":"date-time"},"trackingNumber":{"type":"string"},"deliveryDate":{"type":"string","format":"date-time"},"shippingAddressId":{"type":"integer","format":"int32"},"street":{"type":"string"},"city":{"type":"string"},"provinceId":{"type":"integer","format":"int32"},"provinceName":{"type":"string"},"stateId":{"type":"integer","format":"int32"},"stateName":{"type":"string"},"postalCode":{"type":"string"},"countryId":{"type":"integer","format":"int32"},"countryName":{"type":"string"},"paypal_order_id":{"type":"string"},"promo_code":{"type":"string"},"promotional_discount":{"type":"number"},"products":{"type":"array","items":{"type":"object","additionalProperties":{"type":"object"}}}}},"PromoCodeCreateRequest":{"required":["discount_amount","friday_date","winner_email"],"type":"object","properties":{"winner_email":{"type":"string","description":"Email of the winner user","example":"winner@example.com"},"winner_name":{"type":"string","description":"Name of the winner user","example":"John Doe"},"discount_amount":{"minimum":0.01,"exclusiveMinimum":false,"type":"number","description":"Dollar amount discount","example":15.0},"friday_date":{"type":"string","description":"The Friday date when code is valid (YYYY-MM-DD)","format":"date","example":"2025-10-31"},"code":{"type":"string","description":"Optional custom code (auto-generated if not provided)","example":"FRIDAY20251031"}},"description":"Request to create a new promo code"},"PromoCode":{"required":["code","discount_amount","valid_date","winner_email"],"type":"object","properties":{"promo_code_id":{"type":"integer","description":"Unique identifier for the promo code","format":"int64","readOnly":true,"example":1},"code":{"type":"string","description":"Unique promo code string","example":"FRIDAY20251027"},"discount_amount":{"type":"number","description":"Dollar amount discount to apply","example":15.0},"valid_date":{"type":"string","description":"Friday date when code is valid","format":"date","example":"2025-10-27"},"is_active":{"type":"boolean","description":"Whether code can still be used","example":true},"winner_email":{"type":"string","description":"Email of winner who can use this code","example":"winner@example.com"},"winner_name":{"type":"string","description":"Name of winner who can use this code","example":"John Doe"},"created_at":{"type":"string","description":"When the promo code was created","format":"date-time","readOnly":true},"expires_at":{"type":"string","description":"When the promo code expires","format":"date-time"}},"description":"Represents a weekly Friday promo code"},"DeliveryAddressDTO":{"required":["city","postal_code","province","street"],"type":"object","properties":{"street":{"maxLength":255,"minLength":0,"type":"string","description":"Street address","example":"123 Main Street"},"city":{"maxLength":100,"minLength":0,"type":"string","description":"City","example":"Toronto"},"province":{"maxLength":50,"minLength":0,"type":"string","description":"Province or state","example":"Ontario"},"postal_code":{"maxLength":20,"minLength":0,"type":"string","description":"Postal or ZIP code","example":"M5V 3A8"}},"description":"Delivery address details"},"GuestOrderCreateRequest":{"required":["delivery_method","guest_email","guest_name","guest_phone_number","order_items","restaurant_phone_number","total_amount"],"type":"object","properties":{"guest_name":{"maxLength":100,"minLength":0,"type":"string","description":"Full name of the guest","example":"John Doe"},"guest_phone_number":{"pattern":"^\\d{3}-\\d{3}-\\d{4}$","type":"string","description":"Phone number of the guest","example":"416-555-0123"},"guest_email":{"type":"string","description":"Email address of the guest","example":"john.doe@example.com"},"restaurant_phone_number":{"type":"string","description":"Phone number of the restaurant","example":"416-781-8383"},"delivery_method":{"pattern":"^(DELIVERY|PICKUP)$","type":"string","description":"Delivery method","example":"DELIVERY"},"total_amount":{"minimum":0.01,"exclusiveMinimum":false,"type":"number","description":"Total amount for the order","example":45.99},"tip_amount":{"minimum":0.00,"exclusiveMinimum":false,"type":"number","description":"Tip amount","example":5.0},"delivery_fee":{"minimum":0.00,"exclusiveMinimum":false,"type":"number","description":"Delivery fee","example":3.99},"promotional_discount":{"minimum":0.00,"exclusiveMinimum":false,"type":"number","description":"Promotional discount","example":0.0},"promo_code":{"type":"string","description":"Optional promo code (Friday only)","example":"FRIDAY20251027"},"delivery_address":{"$ref":"#/components/schemas/DeliveryAddressDTO"},"special_instructions":{"maxLength":1000,"minLength":0,"type":"string","description":"Special instructions for the order","example":"Leave at front door"},"order_items":{"type":"array","description":"List of items in the order","items":{"$ref":"#/components/schemas/GuestOrderItemDTO"}}},"description":"Request to create a guest order"},"GuestOrderItemDTO":{"required":["item_subtotal","menu_item_id","price_at_order","quantity"],"type":"object","properties":{"menu_item_id":{"type":"integer","description":"Reference to the menu item","format":"int64","example":20},"quantity":{"minimum":1,"type":"integer","description":"Quantity ordered","format":"int32","example":2},"price_at_order":{"minimum":0.01,"exclusiveMinimum":false,"type":"number","description":"Price per unit at time of order","example":12.99},"item_subtotal":{"minimum":0.01,"exclusiveMinimum":false,"type":"number","description":"Subtotal for this item","example":25.98},"item_instructions":{"maxLength":500,"minLength":0,"type":"string","description":"Special instructions for this item","example":"Extra sauce"}},"description":"Guest order item details"},"GuestOrderResponse":{"type":"object","properties":{"order_id":{"type":"integer","description":"Unique identifier for the order","format":"int64","example":1},"order_number":{"type":"string","description":"Human-readable order number","example":"GO-20251021-001"},"status":{"type":"string","description":"Current order status","example":"PENDING"},"estimated_delivery_time":{"type":"string","description":"Estimated delivery time","format":"date-time"},"estimated_pickup_time":{"type":"string","description":"Estimated pickup time","format":"date-time"},"total_amount":{"type":"number","description":"Total order amount","example":45.99},"guest_name":{"type":"string","description":"Guest name","example":"John Doe"},"guest_email":{"type":"string","description":"Guest email","example":"john.doe@example.com"},"delivery_method":{"type":"string","description":"Delivery method","example":"DELIVERY"},"created_at":{"type":"string","description":"Order creation timestamp","format":"date-time"}},"description":"Response containing guest order details"},"VisitDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int32"},"ip":{"type":"string"},"visitData":{"type":"object","additionalProperties":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"}}},"PromotionEventResponse":{"type":"object","properties":{"promotion_event_id":{"type":"integer","format":"int64"},"restaurant_phone_number":{"type":"string"},"event_date":{"type":"string","format":"date"},"menu_item_id":{"type":"integer","format":"int64"},"discount_amount":{"type":"number"},"title":{"type":"string"},"description":{"type":"string"},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"menu_item_name":{"type":"string","description":"Menu item name"},"menu_item_image_url":{"type":"string","description":"Menu item image URL"},"menu_item_price":{"type":"number","description":"Menu item regular price"}},"description":"Promotion event response with menu item details"},"PromoCodeUsageHistoryDTO":{"type":"object","properties":{"usage_id":{"type":"integer","description":"Usage record ID","format":"int64"},"promo_code":{"type":"string","description":"Promo code that was used"},"guest_order_id":{"type":"integer","description":"Guest order ID","format":"int64"},"user_email":{"type":"string","description":"User email"},"user_name":{"type":"string","description":"User name"},"user_phone":{"type":"string","description":"User phone"},"discount_applied":{"type":"number","description":"Discount amount applied"},"order_total":{"type":"number","description":"Order total after discount"},"used_at":{"type":"string","description":"When the promo code was used","format":"date-time"}},"description":"Promo code usage history details"}}}}