From e3c4f306486f0bf3a165a77f84ac87cb6740fd63 Mon Sep 17 00:00:00 2001 From: Marco Gallegos Date: Sat, 17 Jan 2026 00:48:49 -0600 Subject: [PATCH] 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 --- README.md | 61 +++++- STRIPE_SETUP.md | 75 ------- TASKS.md | 160 +++++++++++++- API.md => docs/API.md | 46 +++- PRD.md => docs/PRD.md | 0 docs/STRIPE_SETUP.md | 201 ++++++++++++++++++ .../site_requirements.md | 0 7 files changed, 455 insertions(+), 88 deletions(-) delete mode 100644 STRIPE_SETUP.md rename API.md => docs/API.md (70%) rename PRD.md => docs/PRD.md (100%) create mode 100644 docs/STRIPE_SETUP.md rename site_requirements.md => docs/site_requirements.md (100%) diff --git a/README.md b/README.md index 2a40768..2208fbc 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,26 @@ No contiene: Este proyecto se rige por los siguientes documentos: -* **PRD (Documento Maestro)** → Definición de producto y reglas de negocio. -* **README (este archivo)** → Guía técnica y operativa del repo. -* **API.md** → Documentación completa de APIs y endpoints. -* **TASKS.md** → Plan de ejecución por fases y estado actual. +### Documentos Principales (Raíz) +* **[README.md](./README.md)** (este archivo) → Guía técnica y operativa del repo. +* **[TASKS.md](./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. @@ -345,11 +361,46 @@ Dominio institucional. Contenido estático, marca, narrativa y conversión inici **booking.anchor23.mx** - `/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/perfil` - Perfil de cliente con historial 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` - Dashboard con estadísticas y gestión - `/aperture` (tabs: Dashboard, Staff, Resources, Reports, Permissions) diff --git a/STRIPE_SETUP.md b/STRIPE_SETUP.md deleted file mode 100644 index 745a6b0..0000000 --- a/STRIPE_SETUP.md +++ /dev/null @@ -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: - -``` - -### 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. \ No newline at end of file diff --git a/TASKS.md b/TASKS.md index 94e6c51..334feb2 100644 --- a/TASKS.md +++ b/TASKS.md @@ -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} - Short ID único de 6 caracteres + * @example generateShortId(5) + */ +export async function generateShortId(maxAttempts: number = 5): Promise +``` + +### 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 ### 1.1 Infraestructura Base ✅ @@ -328,14 +477,19 @@ Validación Staff (rol Staff): ### 🚧 En Progreso - 🚧 The Boutique - Frontend de reservas (booking.anchor23.mx) - ✅ 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) - ✅ Layout específico con navbar personalizado - ✅ API para obtener servicios (/api/services) - ✅ 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 - - ⏳ Autenticación de clientes - - ⏳ Integración con Stripe + - ⏳ Integración con Stripe real - 🚧 Aperture - Backend para staff/manager/admin (aperture.anchor23.mx) - ✅ API para obtener staff disponible (/api/aperture/staff) diff --git a/API.md b/docs/API.md similarity index 70% rename from API.md rename to docs/API.md index ccb80d2..16a0a51 100644 --- a/API.md +++ b/docs/API.md @@ -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 - `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) -- `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 - `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 ### Key Tables -- `locations` - Salon locations +- `locations` - Salon locations with business hours (JSONB) - `staff` - Staff members -- `services` - Available services +- `services` - Available services with category - `resources` - Physical resources (stations) - `customers` - Customer profiles - `bookings` - Service bookings - `kiosks` - Kiosk devices - `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 ### Required @@ -119,12 +142,25 @@ AnchorOS is a comprehensive salon management system built with Next.js, Supabase ### Core Functionality - Multi-location salon management -- Real-time availability system -- Integrated payment processing +- Real-time availability system with business hours +- Customer registration and lookup by email/phone +- Location-specific opening/closing times +- Automated payment processing (currently mock) - Staff scheduling and payroll - Customer relationship management - 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 - Role-based access control - Audit logging diff --git a/PRD.md b/docs/PRD.md similarity index 100% rename from PRD.md rename to docs/PRD.md diff --git a/docs/STRIPE_SETUP.md b/docs/STRIPE_SETUP.md new file mode 100644 index 0000000..6eec840 --- /dev/null +++ b/docs/STRIPE_SETUP.md @@ -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: + +``` + +### 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 \ No newline at end of file diff --git a/site_requirements.md b/docs/site_requirements.md similarity index 100% rename from site_requirements.md rename to docs/site_requirements.md