FASE 6 PARCIAL: Extras y Diferenciadores (base implementada)

Implementados módulos base de Fase 6:

1. WALL OF FAME (base)
   - Modelo de base de datos
   - Servicio CRUD
   - Controladores
   - Endpoints: GET /wall-of-fame/*

2. ACHIEVEMENTS/LOGROS (base)
   - Modelo de logros desbloqueables
   - Servicio de progreso
   - Controladores base
   - Endpoints: GET /achievements/*

3. QR CHECK-IN (completo)
   - Generación de códigos QR
   - Validación y procesamiento
   - Check-in/check-out
   - Endpoints: /checkin/*

4. BASE DE DATOS
   - Tablas: wall_of_fame, achievements, qr_codes, check_ins
   - Tablas preparadas: equipment, orders, notifications, activities

Estructura lista para:
- Equipment/Material rental
- Orders/Servicios del club
- Wearables integration
- Challenges/Retos

Nota: Algunos módulos avanzados requieren ajustes finales.
This commit is contained in:
2026-01-31 21:59:36 +00:00
parent 5e50dd766f
commit e135e7ad24
51 changed files with 11323 additions and 4 deletions

View File

@@ -0,0 +1,121 @@
-- CreateTable
CREATE TABLE "menu_items" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"description" TEXT,
"category" TEXT NOT NULL DEFAULT 'OTHER',
"price" INTEGER NOT NULL,
"imageUrl" TEXT,
"isAvailable" BOOLEAN NOT NULL DEFAULT true,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"preparationTime" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "orders" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"bookingId" TEXT NOT NULL,
"courtId" TEXT NOT NULL,
"items" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'PENDING',
"totalAmount" INTEGER NOT NULL,
"paymentStatus" TEXT NOT NULL DEFAULT 'PENDING',
"paymentId" TEXT,
"notes" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "orders_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "orders_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "bookings" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "orders_courtId_fkey" FOREIGN KEY ("courtId") REFERENCES "courts" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "notifications" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"type" TEXT NOT NULL,
"title" TEXT NOT NULL,
"message" TEXT NOT NULL,
"data" TEXT,
"isRead" BOOLEAN NOT NULL DEFAULT false,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "notifications_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "user_activities" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"source" TEXT NOT NULL,
"activityType" TEXT NOT NULL DEFAULT 'PADEL_GAME',
"startTime" DATETIME NOT NULL,
"endTime" DATETIME NOT NULL,
"duration" INTEGER NOT NULL,
"caloriesBurned" INTEGER NOT NULL,
"heartRateAvg" INTEGER,
"heartRateMax" INTEGER,
"steps" INTEGER,
"distance" REAL,
"metadata" TEXT,
"bookingId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "user_activities_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "user_activities_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "bookings" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateIndex
CREATE INDEX "menu_items_category_idx" ON "menu_items"("category");
-- CreateIndex
CREATE INDEX "menu_items_isAvailable_idx" ON "menu_items"("isAvailable");
-- CreateIndex
CREATE INDEX "menu_items_isActive_idx" ON "menu_items"("isActive");
-- CreateIndex
CREATE INDEX "orders_userId_idx" ON "orders"("userId");
-- CreateIndex
CREATE INDEX "orders_bookingId_idx" ON "orders"("bookingId");
-- CreateIndex
CREATE INDEX "orders_courtId_idx" ON "orders"("courtId");
-- CreateIndex
CREATE INDEX "orders_status_idx" ON "orders"("status");
-- CreateIndex
CREATE INDEX "orders_paymentStatus_idx" ON "orders"("paymentStatus");
-- CreateIndex
CREATE INDEX "orders_createdAt_idx" ON "orders"("createdAt");
-- CreateIndex
CREATE INDEX "notifications_userId_idx" ON "notifications"("userId");
-- CreateIndex
CREATE INDEX "notifications_type_idx" ON "notifications"("type");
-- CreateIndex
CREATE INDEX "notifications_isRead_idx" ON "notifications"("isRead");
-- CreateIndex
CREATE INDEX "notifications_createdAt_idx" ON "notifications"("createdAt");
-- CreateIndex
CREATE INDEX "user_activities_userId_idx" ON "user_activities"("userId");
-- CreateIndex
CREATE INDEX "user_activities_source_idx" ON "user_activities"("source");
-- CreateIndex
CREATE INDEX "user_activities_activityType_idx" ON "user_activities"("activityType");
-- CreateIndex
CREATE INDEX "user_activities_startTime_idx" ON "user_activities"("startTime");
-- CreateIndex
CREATE INDEX "user_activities_bookingId_idx" ON "user_activities"("bookingId");

View File

@@ -0,0 +1,139 @@
-- CreateTable
CREATE TABLE "qr_codes" (
"id" TEXT NOT NULL PRIMARY KEY,
"code" TEXT NOT NULL,
"type" TEXT NOT NULL,
"referenceId" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
"usedAt" DATETIME,
"usedBy" TEXT,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "check_ins" (
"id" TEXT NOT NULL PRIMARY KEY,
"bookingId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"qrCodeId" TEXT,
"checkInTime" DATETIME NOT NULL,
"checkOutTime" DATETIME,
"method" TEXT NOT NULL,
"verifiedBy" TEXT,
"notes" TEXT,
CONSTRAINT "check_ins_qrCodeId_fkey" FOREIGN KEY ("qrCodeId") REFERENCES "qr_codes" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "check_ins_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "check_ins_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "bookings" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "equipment_items" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"description" TEXT,
"category" TEXT NOT NULL,
"brand" TEXT,
"model" TEXT,
"size" TEXT,
"condition" TEXT NOT NULL DEFAULT 'NEW',
"hourlyRate" INTEGER,
"dailyRate" INTEGER,
"depositRequired" INTEGER NOT NULL DEFAULT 0,
"quantityTotal" INTEGER NOT NULL DEFAULT 1,
"quantityAvailable" INTEGER NOT NULL DEFAULT 1,
"imageUrl" TEXT,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "equipment_rentals" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"bookingId" TEXT,
"startDate" DATETIME NOT NULL,
"endDate" DATETIME NOT NULL,
"totalCost" INTEGER NOT NULL,
"depositAmount" INTEGER NOT NULL,
"depositReturned" INTEGER NOT NULL DEFAULT 0,
"status" TEXT NOT NULL DEFAULT 'RESERVED',
"pickedUpAt" DATETIME,
"returnedAt" DATETIME,
"paymentId" TEXT,
"notes" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "equipment_rentals_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "equipment_rentals_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "bookings" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "equipment_rental_items" (
"id" TEXT NOT NULL PRIMARY KEY,
"rentalId" TEXT NOT NULL,
"itemId" TEXT NOT NULL,
"quantity" INTEGER NOT NULL DEFAULT 1,
"hourlyRate" INTEGER,
"dailyRate" INTEGER,
CONSTRAINT "equipment_rental_items_rentalId_fkey" FOREIGN KEY ("rentalId") REFERENCES "equipment_rentals" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "equipment_rental_items_itemId_fkey" FOREIGN KEY ("itemId") REFERENCES "equipment_items" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "qr_codes_code_key" ON "qr_codes"("code");
-- CreateIndex
CREATE INDEX "qr_codes_code_idx" ON "qr_codes"("code");
-- CreateIndex
CREATE INDEX "qr_codes_referenceId_idx" ON "qr_codes"("referenceId");
-- CreateIndex
CREATE INDEX "qr_codes_type_idx" ON "qr_codes"("type");
-- CreateIndex
CREATE INDEX "qr_codes_isActive_idx" ON "qr_codes"("isActive");
-- CreateIndex
CREATE INDEX "check_ins_bookingId_idx" ON "check_ins"("bookingId");
-- CreateIndex
CREATE INDEX "check_ins_userId_idx" ON "check_ins"("userId");
-- CreateIndex
CREATE INDEX "check_ins_checkInTime_idx" ON "check_ins"("checkInTime");
-- CreateIndex
CREATE INDEX "check_ins_method_idx" ON "check_ins"("method");
-- CreateIndex
CREATE INDEX "equipment_items_category_idx" ON "equipment_items"("category");
-- CreateIndex
CREATE INDEX "equipment_items_isActive_idx" ON "equipment_items"("isActive");
-- CreateIndex
CREATE INDEX "equipment_items_quantityAvailable_idx" ON "equipment_items"("quantityAvailable");
-- CreateIndex
CREATE INDEX "equipment_rentals_userId_idx" ON "equipment_rentals"("userId");
-- CreateIndex
CREATE INDEX "equipment_rentals_bookingId_idx" ON "equipment_rentals"("bookingId");
-- CreateIndex
CREATE INDEX "equipment_rentals_status_idx" ON "equipment_rentals"("status");
-- CreateIndex
CREATE INDEX "equipment_rentals_startDate_idx" ON "equipment_rentals"("startDate");
-- CreateIndex
CREATE INDEX "equipment_rentals_endDate_idx" ON "equipment_rentals"("endDate");
-- CreateIndex
CREATE INDEX "equipment_rental_items_rentalId_idx" ON "equipment_rental_items"("rentalId");
-- CreateIndex
CREATE INDEX "equipment_rental_items_itemId_idx" ON "equipment_rental_items"("itemId");

View File

@@ -0,0 +1,228 @@
-- Fase 6: Extras y Diferenciadores
-- Wall of Fame
CREATE TABLE IF NOT EXISTS wall_of_fame_entries (
id TEXT PRIMARY KEY,
tournament_id TEXT,
title TEXT NOT NULL,
description TEXT,
winners TEXT NOT NULL, -- JSON array
category TEXT NOT NULL DEFAULT 'TOURNAMENT',
image_url TEXT,
event_date DATETIME NOT NULL,
is_active BOOLEAN DEFAULT 1,
featured BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tournament_id) REFERENCES tournaments(id) ON DELETE SET NULL
);
-- Achievements (Logros)
CREATE TABLE IF NOT EXISTS achievements (
id TEXT PRIMARY KEY,
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
description TEXT,
category TEXT NOT NULL DEFAULT 'GAMES',
icon TEXT,
color TEXT DEFAULT '#16a34a',
requirement_type TEXT NOT NULL,
requirement_value INTEGER NOT NULL,
points_reward INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT 1
);
-- User Achievements
CREATE TABLE IF NOT EXISTS user_achievements (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
achievement_id TEXT NOT NULL,
unlocked_at DATETIME,
progress INTEGER DEFAULT 0,
is_completed BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (achievement_id) REFERENCES achievements(id) ON DELETE CASCADE,
UNIQUE(user_id, achievement_id)
);
-- Challenges (Retos)
CREATE TABLE IF NOT EXISTS challenges (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
description TEXT,
type TEXT NOT NULL DEFAULT 'WEEKLY',
requirement_type TEXT NOT NULL,
requirement_value INTEGER NOT NULL,
start_date DATETIME NOT NULL,
end_date DATETIME NOT NULL,
reward_points INTEGER DEFAULT 0,
participants TEXT DEFAULT '[]', -- JSON array
winners TEXT DEFAULT '[]', -- JSON array
is_active BOOLEAN DEFAULT 1
);
-- User Challenges
CREATE TABLE IF NOT EXISTS user_challenges (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
challenge_id TEXT NOT NULL,
progress INTEGER DEFAULT 0,
is_completed BOOLEAN DEFAULT 0,
completed_at DATETIME,
reward_claimed BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (challenge_id) REFERENCES challenges(id) ON DELETE CASCADE,
UNIQUE(user_id, challenge_id)
);
-- QR Codes
CREATE TABLE IF NOT EXISTS qr_codes (
id TEXT PRIMARY KEY,
code TEXT UNIQUE NOT NULL,
type TEXT NOT NULL DEFAULT 'BOOKING_CHECKIN',
reference_id TEXT NOT NULL,
expires_at DATETIME NOT NULL,
used_at DATETIME,
used_by TEXT,
is_active BOOLEAN DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (used_by) REFERENCES users(id) ON DELETE SET NULL
);
-- Check-ins
CREATE TABLE IF NOT EXISTS check_ins (
id TEXT PRIMARY KEY,
booking_id TEXT NOT NULL,
user_id TEXT NOT NULL,
qr_code_id TEXT,
check_in_time DATETIME DEFAULT CURRENT_TIMESTAMP,
check_out_time DATETIME,
method TEXT DEFAULT 'QR',
verified_by TEXT,
notes TEXT,
FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (qr_code_id) REFERENCES qr_codes(id) ON DELETE SET NULL
);
-- Equipment Items
CREATE TABLE IF NOT EXISTS equipment_items (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
category TEXT NOT NULL DEFAULT 'RACKET',
brand TEXT,
model TEXT,
size TEXT,
condition TEXT DEFAULT 'GOOD',
hourly_rate INTEGER,
daily_rate INTEGER,
deposit_required INTEGER DEFAULT 0,
quantity_total INTEGER DEFAULT 1,
quantity_available INTEGER DEFAULT 1,
image_url TEXT,
is_active BOOLEAN DEFAULT 1
);
-- Equipment Rentals
CREATE TABLE IF NOT EXISTS equipment_rentals (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
items TEXT NOT NULL, -- JSON array
booking_id TEXT,
start_date DATETIME NOT NULL,
end_date DATETIME NOT NULL,
total_cost INTEGER NOT NULL,
deposit_amount INTEGER DEFAULT 0,
status TEXT DEFAULT 'RESERVED',
picked_up_at DATETIME,
returned_at DATETIME,
payment_id TEXT,
notes TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE SET NULL
);
-- Menu Items
CREATE TABLE IF NOT EXISTS menu_items (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
category TEXT NOT NULL DEFAULT 'DRINK',
price INTEGER NOT NULL,
image_url TEXT,
is_available BOOLEAN DEFAULT 1,
preparation_time INTEGER,
is_active BOOLEAN DEFAULT 1
);
-- Orders
CREATE TABLE IF NOT EXISTS orders (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
booking_id TEXT NOT NULL,
court_id TEXT NOT NULL,
items TEXT NOT NULL, -- JSON array
status TEXT DEFAULT 'PENDING',
total_amount INTEGER NOT NULL,
payment_status TEXT DEFAULT 'PENDING',
payment_id TEXT,
notes TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE CASCADE,
FOREIGN KEY (court_id) REFERENCES courts(id) ON DELETE CASCADE
);
-- Notifications
CREATE TABLE IF NOT EXISTS notifications (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
type TEXT NOT NULL,
title TEXT NOT NULL,
message TEXT NOT NULL,
data TEXT, -- JSON
is_read BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- User Activity (Wearables)
CREATE TABLE IF NOT EXISTS user_activities (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
source TEXT DEFAULT 'MANUAL',
activity_type TEXT DEFAULT 'PADEL_GAME',
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
duration INTEGER NOT NULL,
calories_burned INTEGER,
heart_rate_avg INTEGER,
heart_rate_max INTEGER,
steps INTEGER,
distance REAL,
metadata TEXT, -- JSON
booking_id TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE SET NULL
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_wof_event_date ON wall_of_fame_entries(event_date);
CREATE INDEX IF NOT EXISTS idx_wof_featured ON wall_of_fame_entries(featured);
CREATE INDEX IF NOT EXISTS idx_achievements_category ON achievements(category);
CREATE INDEX IF NOT EXISTS idx_user_achievements_user ON user_achievements(user_id);
CREATE INDEX IF NOT EXISTS idx_challenges_dates ON challenges(start_date, end_date);
CREATE INDEX IF NOT EXISTS idx_qr_codes ON qr_codes(code);
CREATE INDEX IF NOT EXISTS idx_check_ins_booking ON check_ins(booking_id);
CREATE INDEX IF NOT EXISTS idx_check_ins_time ON check_ins(check_in_time);
CREATE INDEX IF NOT EXISTS idx_equipment_category ON equipment_items(category);
CREATE INDEX IF NOT EXISTS idx_rentals_user ON equipment_rentals(user_id);
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id);
CREATE INDEX IF NOT EXISTS idx_activities_user ON user_activities(user_id);