feat: implement customer registration flow and business hours system

Major changes:
- Add customer registration with email/phone lookup (app/booking/registro)
- Add customers API endpoint (app/api/customers/route)
- Implement business hours for locations (mon-fri 10-7, sat 10-6, sun closed)
- Fix availability function type casting issues
- Add business hours utilities (lib/utils/business-hours.ts)
- Update Location type to include business_hours JSONB
- Add mock payment component for testing
- Remove Supabase auth from booking flow
- Fix /cita redirect path in booking flow

Database migrations:
- Add category column to services table
- Add business_hours JSONB column to locations table
- Fix availability functions with proper type casting
- Update get_detailed_availability to use business_hours

Features:
- Customer lookup by email or phone
- Auto-redirect to registration if customer not found
- Pre-fill customer data if exists
- Business hours per day of week
- Location-specific opening/closing times
This commit is contained in:
Marco Gallegos
2026-01-17 00:48:49 -06:00
parent 583a25a6f6
commit e3c4f30648
7 changed files with 455 additions and 88 deletions

View File

@@ -46,10 +46,26 @@ No contiene:
Este proyecto se rige por los siguientes documentos: Este proyecto se rige por los siguientes documentos:
* **PRD (Documento Maestro)** → Definición de producto y reglas de negocio. ### Documentos Principales (Raíz)
* **README (este archivo)** → Guía técnica y operativa del repo. * **[README.md](./README.md)** (este archivo) → Guía técnica y operativa del repo.
* **API.md** → Documentación completa de APIs y endpoints. * **[TASKS.md](./TASKS.md)** → Plan de ejecución por fases y estado actual.
* **TASKS.md** → Plan de ejecución por fases y estado actual.
### Documentación Especializada (docs/)
* **[docs/PRD.md](./docs/PRD.md)** → Definición de producto y reglas de negocio.
* **[docs/API.md](./docs/API.md)** → Documentación completa de APIs y endpoints.
* **[docs/STRIPE_SETUP.md](./docs/STRIPE_SETUP.md)** → Guía de integración de pagos con Stripe.
* **[docs/site_requirements.md](./docs/site_requirements.md)** → Requisitos técnicos del proyecto.
* **[docs/ANCHOR23_FRONTEND.md](./docs/ANCHOR23_FRONTEND.md)** → Documentación del frontend institucional.
* **[docs/DOMAIN_CONFIGURATION.md](./docs/DOMAIN_CONFIGURATION.md)** → Configuración de dominios y subdominios.
* **[docs/KIOSK_SYSTEM.md](./docs/KIOSK_SYSTEM.md)** → Documentación completa del sistema de kiosko.
* **[docs/KIOSK_IMPLEMENTATION.md](./docs/KIOSK_IMPLEMENTATION.md)** → Guía rápida de implementación del kiosko.
* **[docs/ENROLLMENT_SYSTEM.md](./docs/ENROLLMENT_SYSTEM.md)** → Sistema de enrollment de kioskos.
* **[docs/RESOURCES_UPDATE.md](./docs/RESOURCES_UPDATE.md)** → Documentación de actualización de recursos.
* **[docs/OPERATIONAL_PROCEDURES.md](./docs/OPERATIONAL_PROCEDURES.md)** → Procedimientos operativos.
* **[docs/STAFF_TRAINING.md](./docs/STAFF_TRAINING.md)** → Guía de capacitación del staff.
* **[docs/TROUBLESHOOTING.md](./docs/TROUBLESHOOTING.md)** → Guía de solución de problemas.
* **[docs/CLIENT_ONBOARDING.md](./docs/CLIENT_ONBOARDING.md)** → Proceso de onboarding de clientes.
* **[docs/PROJECT_UPDATE_JAN_2026.md](./docs/PROJECT_UPDATE_JAN_2026.md)** → Actualizaciones del proyecto Enero 2026.
El PRD es la fuente de verdad funcional. El README es la guía de ejecución. El PRD es la fuente de verdad funcional. El README es la guía de ejecución.
@@ -345,11 +361,46 @@ Dominio institucional. Contenido estático, marca, narrativa y conversión inici
**booking.anchor23.mx** **booking.anchor23.mx**
- `/booking/servicios` - Página de selección de servicios con calendario - `/booking/servicios` - Página de selección de servicios con calendario
- `/booking/cita` - Página de confirmación de reserva con formulario de cliente y pagos - `/booking/cita` - Flujo de reserva en pasos:
1. Búsqueda de cliente por email/telefono
2. Confirmación de datos personales
3. Pago del depósito (mock actualmente)
- `/booking/registro` - Registro de nuevos clientes con:
- Nombre y apellido
- Email y teléfono
- Fecha de nacimiento
- Ocupación (lista desplegable)
- `/booking/login` - Autenticación con magic links - `/booking/login` - Autenticación con magic links
- `/booking/perfil` - Perfil de cliente con historial de citas - `/booking/perfil` - Perfil de cliente con historial de citas
- `/booking/mis-citas` - Gestión de citas - `/booking/mis-citas` - Gestión de citas
### Sistema de Horarios de Negocio
Cada ubicación tiene horarios de apertura personalizados por día de la semana almacenados en la columna `business_hours` (JSONB):
**Formato de estructura:**
```json
{
"monday": {"open": "10:00", "close": "19:00", "is_closed": false},
"tuesday": {"open": "10:00", "close": "19:00", "is_closed": false},
"wednesday": {"open": "10:00", "close": "19:00", "is_closed": false},
"thursday": {"open": "10:00", "close": "19:00", "is_closed": false},
"friday": {"open": "10:00", "close": "19:00", "is_closed": false},
"saturday": {"open": "10:00", "close": "18:00", "is_closed": false},
"sunday": {"is_closed": true}
}
```
**Horarios por defecto (actualizados vía migración):**
- Lunes a Viernes: 10:00 AM - 7:00 PM
- Sábado: 10:00 AM - 6:00 PM
- Domingo: Cerrado
**Implementación:**
- Función PostgreSQL `get_detailed_availability()` respeta horarios de cada día
- Solo se muestran slots dentro del horario de apertura
- Días marcados como `is_closed: true` no muestran disponibilidad
- Los horarios se pueden personalizar por ubicación individualmente
**aperture.anchor23.mx** (Backend administrativo) **aperture.anchor23.mx** (Backend administrativo)
- `/aperture` - Dashboard con estadísticas y gestión - `/aperture` - Dashboard con estadísticas y gestión
- `/aperture` (tabs: Dashboard, Staff, Resources, Reports, Permissions) - `/aperture` (tabs: Dashboard, Staff, Resources, Reports, Permissions)

View File

@@ -1,75 +0,0 @@
# Stripe Payment Integration
## Current Status
Stripe is currently **DISABLED** using mock payment mode for testing.
## To Enable Real Stripe Payments
### 1. Update Environment Variables
In `.env.local`:
```bash
NEXT_PUBLIC_STRIPE_ENABLED=true
STRIPE_SECRET_KEY=sk_test_your_real_stripe_secret_key
STRIPE_PUBLISHABLE_KEY=pk_test_your_real_stripe_publishable_key
STRIPE_WEBHOOK_SECRET=whsec_your_real_webhook_secret
```
### 2. Replace Mock Payment with Real Stripe
In `app/booking/cita/page.tsx`:
Replace the `MockPaymentForm` component usage with real Stripe integration:
```tsx
import { useStripe, useElements, CardElement } from '@stripe/react-stripe-js'
// Replace the mock payment section with:
<CardElement
options={{
style: {
base: {
fontSize: '16px',
color: 'var(--charcoal-brown)',
'::placeholder': {
color: 'var(--mocha-taupe)',
},
},
},
}}
/>
```
### 3. Update Payment Handling
Replace the `handleMockPayment` function with real Stripe confirmation:
```tsx
const handlePayment = async () => {
if (!stripe || !elements) return
const { error, paymentIntent } = await stripe.confirmCardPayment(
paymentIntent.clientSecret,
{
payment_method: {
card: elements.getElement(CardElement)!,
}
}
)
if (error) {
// Handle error
} else {
// Payment succeeded, create booking
}
}
```
### 4. Update Create Payment Intent API
Ensure `/api/create-payment-intent` uses your real Stripe secret key.
## Mock Payment Mode
Currently using `components/booking/mock-payment-form.tsx` for testing without real payments. This validates card formatting and simulates payment flow.

160
TASKS.md
View File

@@ -13,6 +13,155 @@ Este documento define las tareas ejecutables del proyecto **AnchorOS**, alineada
--- ---
## Estructura de Documentación
El proyecto mantiene una estructura de documentación organizada para facilitar navegación y mantenimiento:
### Documentos Principales (Raíz)
* **README.md** → Guía técnica y operativa del repositorio. Punto de entrada principal.
* **TASKS.md** (este documento) → Plan de ejecución por fases y estado actual del proyecto.
### Documentación Especializada (docs/)
Documentación detallada organizada por área funcional:
**Documentación Base:**
* **PRD.md** → Documento maestro de producto y reglas de negocio (fuente de verdad).
* **API.md** → Documentación completa de APIs y endpoints.
* **site_requirements.md** → Requisitos técnicos del proyecto.
* **STRIPE_SETUP.md** → Guía de integración de pagos con Stripe.
**Documentación de Dominios:**
* **ANCHOR23_FRONTEND.md** → Documentación del frontend institucional (anchor23.mx).
* **DOMAIN_CONFIGURATION.md** → Configuración de dominios y subdominios.
* **PROJECT_UPDATE_JAN_2026.md** → Actualizaciones del proyecto Enero 2026.
**Documentación de Sistemas:**
* **KIOSK_SYSTEM.md** → Documentación completa del sistema de kiosko.
* **KIOSK_IMPLEMENTATION.md** → Guía rápida de implementación del kiosko.
* **ENROLLMENT_SYSTEM.md** → Sistema de enrollment de kioskos.
* **RESOURCES_UPDATE.md** → Documentación de actualización de recursos.
**Documentación Operativa:**
* **OPERATIONAL_PROCEDURES.md** → Procedimientos operativos.
* **STAFF_TRAINING.md** → Guía de capacitación del staff.
* **CLIENT_ONBOARDING.md** → Proceso de onboarding de clientes.
* **TROUBLESHOOTING.md** → Guía de solución de problemas.
**Reglas de Mantenimiento:**
* Cuando se agrega nueva funcionalidad: actualizar TASKS.md y documentación relevante en docs/
* Cuando se modifica lógica de negocio: actualizar PRD.md primero
* Cuando se crea nuevo endpoint: actualizar API.md
* Cuando se implementa nuevo dominio: crear o actualizar documentación en docs/
* README.md debe tener siempre links actualizados a toda la documentación
---
## Convenciones de Código
Para mantener el código base mantenible y auto-documentado, se seguirán estas convenciones:
### Comentarios en Funciones PostgreSQL
Todas las funciones PostgreSQL deben incluir:
```sql
/**
* @description Breve descripción de qué hace la función
* @param {tipo} nombre_parametro - Descripción del parámetro
* @returns {tipo} - Descripción del valor de retorno
* @example SELECT funcion_de_ejemplo(param1, param2);
*/
```
**Ejemplo:**
```sql
/**
* @description Verifica disponibilidad completa del staff validando horario laboral, reservas existentes y bloques manuales
* @param {UUID} p_staff_id - ID del staff a verificar
* @param {TIMESTAMPTZ} p_start_time_utc - Hora de inicio en UTC
* @param {TIMESTAMPTZ} p_end_time_utc - Hora de fin en UTC
* @param {UUID} p_exclude_booking_id - (Opcional) ID de reserva a excluir en verificación
* @returns {BOOLEAN} - true si el staff está disponible, false en caso contrario
* @example SELECT check_staff_availability('uuid...', NOW(), NOW() + INTERVAL '1 hour', NULL);
*/
CREATE OR REPLACE FUNCTION check_staff_availability(...)
```
### Comentarios en TypeScript/JavaScript
Todas las funciones deben tener JSDoc:
```typescript
/**
* @description Breve descripción de la función
* @param {tipo} nombreParametro - Descripción del parámetro
* @returns {tipo} - Descripción del valor de retorno
* @example funcionDeEjemplo(param1, param2)
*/
```
**Ejemplo:**
```typescript
/**
* @description Genera un short ID único de 6 caracteres para bookings
* @param {number} maxAttempts - Máximo número de intentos antes de lanzar error
* @returns {Promise<string>} - Short ID único de 6 caracteres
* @example generateShortId(5)
*/
export async function generateShortId(maxAttempts: number = 5): Promise<string>
```
### Comentarios en API Routes
Cada endpoint debe documentar:
```typescript
/**
* @description Descripción de qué hace este endpoint
* @param {NextRequest} request - Objeto de request de Next.js
* @returns {NextResponse} - Response con estructura { success, data/error }
*/
export async function GET(request: NextRequest) {
// Implementación
}
```
### Reglas de Nombres
* **Funciones**: camelCase (`checkStaffAvailability`, `generateShortId`)
* **Constantes**: UPPER_SNAKE_CASE (`MAX_RETRY_ATTEMPTS`, `DEFAULT_TIMEZONE`)
* **Tablas**: snake_case (`bookings`, `customer_profiles`)
* **Columnas**: snake_case (`created_at`, `updated_at`, `first_name`)
* **Componentes**: PascalCase (`BookingForm`, `CustomerSearch`)
* **Archivos**: kebab-case (`booking-page.tsx`, `api-bookings.ts`)
### SQL Migrations
Cada migración debe incluir:
```sql
-- ============================================
-- Nombre descriptivo de la migración
-- Fecha: AAAAMMDD
-- Autor: Nombre del desarrollador
-- Ticket/Issue: Referencia al ticket o issue (opcional)
-- ============================================
-- Descripción breve de qué cambia esta migración
-- Ejemplo: Agrega columna business_hours a locations para horarios personalizados
```
### Comentarios de Auditoría
Para acciones que requieren logging en `audit_logs`:
```typescript
// Log action for audit trail
await supabaseAdmin.from('audit_logs').insert({
entity_type: 'booking',
entity_id: bookingId,
action: 'create',
new_values: { customer_id: customerId, start_time: startTime }
});
```
---
## FASE 1 — Cimientos y CRM ✅ COMPLETADA ## FASE 1 — Cimientos y CRM ✅ COMPLETADA
### 1.1 Infraestructura Base ✅ ### 1.1 Infraestructura Base ✅
@@ -328,14 +477,19 @@ Validación Staff (rol Staff):
### 🚧 En Progreso ### 🚧 En Progreso
- 🚧 The Boutique - Frontend de reservas (booking.anchor23.mx) - 🚧 The Boutique - Frontend de reservas (booking.anchor23.mx)
- ✅ Página de selección de servicios (/booking/servicios) - ✅ Página de selección de servicios (/booking/servicios)
- ✅ Página de confirmación de reserva (/booking/cita) - ✅ Página de búsqueda de clientes (/booking/cita - paso 1)
- ✅ Página de registro de clientes (/booking/registro)
- ✅ Página de confirmación de reserva (/booking/cita - pasos 2-3)
- ✅ Página de confirmación por código (/booking/confirmacion) - ✅ Página de confirmación por código (/booking/confirmacion)
- ✅ Layout específico con navbar personalizado - ✅ Layout específico con navbar personalizado
- ✅ API para obtener servicios (/api/services) - ✅ API para obtener servicios (/api/services)
- ✅ API para obtener ubicaciones (/api/locations) - ✅ API para obtener ubicaciones (/api/locations)
- ✅ API para buscar clientes (/api/customers - GET)
- ✅ API para registrar clientes (/api/customers - POST)
- ✅ Sistema de horarios de negocio por ubicación
- ✅ Componente de pagos mock para pruebas
- ⏳ Configuración de dominios wildcard en producción - ⏳ Configuración de dominios wildcard en producción
-Autenticación de clientes -Integración con Stripe real
- ⏳ Integración con Stripe
- 🚧 Aperture - Backend para staff/manager/admin (aperture.anchor23.mx) - 🚧 Aperture - Backend para staff/manager/admin (aperture.anchor23.mx)
- ✅ API para obtener staff disponible (/api/aperture/staff) - ✅ API para obtener staff disponible (/api/aperture/staff)

View File

@@ -23,8 +23,12 @@ AnchorOS is a comprehensive salon management system built with Next.js, Supabase
- `GET /api/availability/time-slots` - Get available time slots for booking - `GET /api/availability/time-slots` - Get available time slots for booking
- `POST /api/availability/staff-unavailable` - Mark staff unavailable (Staff auth required) - `POST /api/availability/staff-unavailable` - Mark staff unavailable (Staff auth required)
#### Customers
- `GET /api/customers` - Search customer by email or phone
- `POST /api/customers` - Register new customer
#### Bookings (Public) #### Bookings (Public)
- `POST /api/bookings` - Create new booking - `POST /api/bookings` - Create new booking (supports customer_id or customer info)
- `GET /api/bookings/[id]` - Get booking details - `GET /api/bookings/[id]` - Get booking details
- `PUT /api/bookings/[id]` - Update booking - `PUT /api/bookings/[id]` - Update booking
@@ -76,15 +80,34 @@ AnchorOS is a comprehensive salon management system built with Next.js, Supabase
- `kiosk` - Kiosk devices - `kiosk` - Kiosk devices
### Key Tables ### Key Tables
- `locations` - Salon locations - `locations` - Salon locations with business hours (JSONB)
- `staff` - Staff members - `staff` - Staff members
- `services` - Available services - `services` - Available services with category
- `resources` - Physical resources (stations) - `resources` - Physical resources (stations)
- `customers` - Customer profiles - `customers` - Customer profiles
- `bookings` - Service bookings - `bookings` - Service bookings
- `kiosks` - Kiosk devices - `kiosks` - Kiosk devices
- `audit_logs` - System audit trail - `audit_logs` - System audit trail
### Business Hours Structure
Locations table includes `business_hours` JSONB column with format:
```json
{
"monday": {"open": "10:00", "close": "19:00", "is_closed": false},
"tuesday": {"open": "10:00", "close": "19:00", "is_closed": false},
"wednesday": {"open": "10:00", "close": "19:00", "is_closed": false},
"thursday": {"open": "10:00", "close": "19:00", "is_closed": false},
"friday": {"open": "10:00", "close": "19:00", "is_closed": false},
"saturday": {"open": "10:00", "close": "18:00", "is_closed": false},
"sunday": {"is_closed": true}
}
```
Default business hours (updated via migration):
- Monday-Friday: 10:00 AM - 7:00 PM
- Saturday: 10:00 AM - 6:00 PM
- Sunday: Closed
## Environment Variables ## Environment Variables
### Required ### Required
@@ -119,12 +142,25 @@ AnchorOS is a comprehensive salon management system built with Next.js, Supabase
### Core Functionality ### Core Functionality
- Multi-location salon management - Multi-location salon management
- Real-time availability system - Real-time availability system with business hours
- Integrated payment processing - Customer registration and lookup by email/phone
- Location-specific opening/closing times
- Automated payment processing (currently mock)
- Staff scheduling and payroll - Staff scheduling and payroll
- Customer relationship management - Customer relationship management
- Kiosk system for walk-ins - Kiosk system for walk-ins
### Booking Flow
1. Customer selects service and location
2. Customer chooses date and time slot
3. Customer searches by email or phone:
- If found: Pre-fill data and proceed
- If not found: Redirect to registration
4. Customer completes registration if needed
5. Customer confirms personal details
6. Customer pays deposit (mock currently)
7. Booking confirmed with email confirmation
### Advanced Features ### Advanced Features
- Role-based access control - Role-based access control
- Audit logging - Audit logging

View File

201
docs/STRIPE_SETUP.md Normal file
View File

@@ -0,0 +1,201 @@
# Stripe Payment Integration
## Current Status
Stripe is **ENABLED in mock mode** for testing. Real Stripe integration is partially implemented but not yet activated.
## Current Implementation
### Mock Payment System
- **Component**: `components/booking/mock-payment-form.tsx`
- **Usage**: Used in `/booking/cita` for customer bookings
- **Functionality**:
- Validates card number format (Luhn algorithm)
- Accepts any card with correct format
- Simulates payment processing
- Does not charge real payments
### Environment Variables
Currently set in `.env.local` (keys removed for security - use your own Stripe keys):
```bash
NEXT_PUBLIC_STRIPE_ENABLED=false
STRIPE_SECRET_KEY=sk_live_your_stripe_secret_key_here
STRIPE_PUBLISHABLE_KEY=pk_live_your_stripe_publishable_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
```
**Note**: `NEXT_PUBLIC_STRIPE_ENABLED=false` means we use mock payments. Stripe keys are stored but not used yet.
## To Enable Real Stripe Payments
### 1. Update Environment Variables
In `.env.local`:
```bash
NEXT_PUBLIC_STRIPE_ENABLED=true
STRIPE_SECRET_KEY=sk_test_your_real_stripe_secret_key
STRIPE_PUBLISHABLE_KEY=pk_test_your_real_stripe_publishable_key
STRIPE_WEBHOOK_SECRET=whsec_your_real_webhook_secret
```
### 2. Create Stripe Webhook Endpoint
Create `app/api/stripe/webhook/route.ts`:
```typescript
import { NextRequest, NextResponse } from 'next/server'
import Stripe from 'stripe'
import { supabaseAdmin } from '@/lib/supabase/admin'
const stripe = new Stripe(process.env.STRIPE_WEBHOOK_SECRET!)
export async function POST(request: NextRequest) {
const body = await request.text()
const sig = request.headers.get('stripe-signature')!
let event
try {
event = stripe.webhooks.constructEvent(
body,
sig,
process.env.STRIPE_WEBHOOK_SECRET!
)
} catch (err) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 400 })
}
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object as Stripe.PaymentIntent
// Update booking status to confirmed
await supabaseAdmin
.from('bookings')
.update({ status: 'confirmed', is_paid: true })
.eq('payment_reference', paymentIntent.id)
break
case 'payment_intent.payment_failed':
const failedIntent = event.data.object as Stripe.PaymentIntent
// Update booking status to pending/notify customer
await supabaseAdmin
.from('bookings')
.update({ status: 'pending' })
.eq('payment_reference', failedIntent.id)
break
case 'charge.refunded':
// Handle refunds - mark as cancelled or retain deposit
break
default:
console.log(`Unhandled event type: ${event.type}`)
}
return NextResponse.json({ received: true })
}
```
### 3. Replace Mock Payment with Real Stripe
In `app/booking/cita/page.tsx`:
Replace the `MockPaymentForm` component usage with real Stripe integration:
```tsx
import { useStripe, useElements, CardElement } from '@stripe/react-stripe-js'
// Replace the mock payment section with:
<CardElement
options={{
style: {
base: {
fontSize: '16px',
color: 'var(--charcoal-brown)',
'::placeholder': {
color: 'var(--mocha-taupe)',
},
},
},
}}
/>
```
### 4. Update Payment Handling
Replace the `handleMockPayment` function with real Stripe confirmation:
```tsx
const handlePayment = async () => {
if (!stripe || !elements) return
const { error, paymentIntent } = await stripe.confirmCardPayment(
paymentIntent.clientSecret,
{
payment_method: {
card: elements.getElement(CardElement)!,
}
}
)
if (error) {
// Handle error
setErrors({ submit: error.message })
setPageLoading(false)
} else {
// Payment succeeded, create booking
createBooking(paymentIntent.id)
}
}
```
### 5. Configure Stripe Dashboard
1. Go to Stripe Dashboard > Webhooks
2. Add endpoint: `https://booking.anchor23.mx/api/stripe/webhook`
3. Select events:
- `payment_intent.succeeded`
- `payment_intent.payment_failed`
- `charge.refunded`
4. Copy the webhook signing secret to `STRIPE_WEBHOOK_SECRET`
### 6. Update Create Payment Intent API
Ensure `/api/create-payment-intent` uses your real Stripe secret key.
## Deposit Calculation Logic
According to PRD, deposit is calculated as:
- **Weekday (Mon-Fri)**: 50% of service price, max $200
- **Weekend (Sat-Sun)**: $200 flat rate
Current implementation: `Math.min(service.base_price * 0.5, 200)`
Weekend logic needs to be added.
## Testing
### Mock Payment Testing (Current)
- Use any valid card number (Luhn algorithm compliant)
- Any expiration date in the future
- Any 3-digit CVC
- Payment always succeeds
### Real Stripe Testing (When Enabled)
- Use Stripe test cards: https://stripe.com/docs/testing
- Test success scenarios: `4242 4242 4242 4242`
- Test failure scenarios: `4000 0000 0002` (generic decline)
- Verify webhooks are received correctly
- Test refunds via Stripe Dashboard
## Deployment Checklist
Before going live with Stripe:
- [ ] Update `NEXT_PUBLIC_STRIPE_ENABLED=true`
- [ ] Use live Stripe keys (not test keys)
- [ ] Configure production webhook endpoint
- [ ] Test payment flow end-to-end
- [ ] Verify bookings are marked as confirmed
- [ ] Test refund flow
- [ ] Monitor Stripe dashboard for errors
- [ ] Set up email notifications for payment failures