FASE 2 COMPLETADA: Perfiles, Social y Ranking

Implementados 3 módulos principales:

1. PERFILES EXTENDIDOS
   - Campos adicionales: ciudad, fecha nacimiento, años jugando
   - Estadísticas: partidos jugados/ganados/perdidos
   - Historial de cambios de nivel
   - Búsqueda de usuarios con filtros

2. SISTEMA SOCIAL
   - Amigos: solicitudes, aceptar, rechazar, bloquear
   - Grupos: crear, gestionar miembros, roles
   - Reservas recurrentes: fijos semanales

3. RANKING Y ESTADÍSTICAS
   - Registro de partidos 2v2 con confirmación
   - Sistema de puntos con bonus y multiplicadores
   - Ranking mensual, anual y global
   - Estadísticas personales y globales

Nuevos endpoints:
- /users/* - Perfiles y búsqueda
- /friends/* - Gestión de amistades
- /groups/* - Grupos de jugadores
- /recurring/* - Reservas recurrentes
- /matches/* - Registro de partidos
- /ranking/* - Clasificaciones
- /stats/* - Estadísticas

Nuevos usuarios de prueba:
- carlos@padel.com / 123456
- ana@padel.com / 123456
- pedro@padel.com / 123456
- maria@padel.com / 123456
This commit is contained in:
2026-01-31 08:22:41 +00:00
parent b558372810
commit e20c5b956b
34 changed files with 6081 additions and 15 deletions

View File

@@ -0,0 +1,228 @@
-- CreateTable
CREATE TABLE "level_history" (
"id" TEXT NOT NULL PRIMARY KEY,
"oldLevel" TEXT NOT NULL,
"newLevel" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"changedBy" TEXT NOT NULL,
"reason" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "level_history_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "friends" (
"id" TEXT NOT NULL PRIMARY KEY,
"requesterId" TEXT NOT NULL,
"addresseeId" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'PENDING',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "friends_requesterId_fkey" FOREIGN KEY ("requesterId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "friends_addresseeId_fkey" FOREIGN KEY ("addresseeId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "groups" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"description" TEXT,
"createdById" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "groups_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "group_members" (
"id" TEXT NOT NULL PRIMARY KEY,
"groupId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"role" TEXT NOT NULL DEFAULT 'MEMBER',
"joinedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "group_members_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "groups" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "group_members_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "recurring_bookings" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"courtId" TEXT NOT NULL,
"dayOfWeek" INTEGER NOT NULL,
"startTime" TEXT NOT NULL,
"endTime" TEXT NOT NULL,
"startDate" DATETIME NOT NULL,
"endDate" DATETIME,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "recurring_bookings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "recurring_bookings_courtId_fkey" FOREIGN KEY ("courtId") REFERENCES "courts" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "match_results" (
"id" TEXT NOT NULL PRIMARY KEY,
"bookingId" TEXT,
"team1Player1Id" TEXT NOT NULL,
"team1Player2Id" TEXT NOT NULL,
"team2Player1Id" TEXT NOT NULL,
"team2Player2Id" TEXT NOT NULL,
"team1Score" INTEGER NOT NULL,
"team2Score" INTEGER NOT NULL,
"winner" TEXT NOT NULL,
"playedAt" DATETIME NOT NULL,
"confirmedBy" TEXT NOT NULL DEFAULT '[]',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "match_results_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "bookings" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "match_results_team1Player1Id_fkey" FOREIGN KEY ("team1Player1Id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "match_results_team1Player2Id_fkey" FOREIGN KEY ("team1Player2Id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "match_results_team2Player1Id_fkey" FOREIGN KEY ("team2Player1Id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "match_results_team2Player2Id_fkey" FOREIGN KEY ("team2Player2Id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "user_stats" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"period" TEXT NOT NULL,
"periodValue" TEXT NOT NULL,
"matchesPlayed" INTEGER NOT NULL DEFAULT 0,
"matchesWon" INTEGER NOT NULL DEFAULT 0,
"matchesLost" INTEGER NOT NULL DEFAULT 0,
"tournamentsPlayed" INTEGER NOT NULL DEFAULT 0,
"tournamentsWon" INTEGER NOT NULL DEFAULT 0,
"points" INTEGER NOT NULL DEFAULT 0,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "user_stats_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_bookings" (
"id" TEXT NOT NULL PRIMARY KEY,
"date" DATETIME NOT NULL,
"startTime" TEXT NOT NULL,
"endTime" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'PENDING',
"totalPrice" INTEGER NOT NULL,
"notes" TEXT,
"userId" TEXT NOT NULL,
"courtId" TEXT NOT NULL,
"recurringBookingId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "bookings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "bookings_courtId_fkey" FOREIGN KEY ("courtId") REFERENCES "courts" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "bookings_recurringBookingId_fkey" FOREIGN KEY ("recurringBookingId") REFERENCES "recurring_bookings" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_bookings" ("courtId", "createdAt", "date", "endTime", "id", "notes", "startTime", "status", "totalPrice", "updatedAt", "userId") SELECT "courtId", "createdAt", "date", "endTime", "id", "notes", "startTime", "status", "totalPrice", "updatedAt", "userId" FROM "bookings";
DROP TABLE "bookings";
ALTER TABLE "new_bookings" RENAME TO "bookings";
CREATE INDEX "bookings_userId_idx" ON "bookings"("userId");
CREATE INDEX "bookings_courtId_idx" ON "bookings"("courtId");
CREATE INDEX "bookings_date_idx" ON "bookings"("date");
CREATE INDEX "bookings_recurringBookingId_idx" ON "bookings"("recurringBookingId");
CREATE TABLE "new_users" (
"id" TEXT NOT NULL PRIMARY KEY,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"firstName" TEXT NOT NULL,
"lastName" TEXT NOT NULL,
"phone" TEXT,
"avatarUrl" TEXT,
"city" TEXT,
"birthDate" DATETIME,
"role" TEXT NOT NULL DEFAULT 'PLAYER',
"playerLevel" TEXT NOT NULL DEFAULT 'BEGINNER',
"handPreference" TEXT NOT NULL DEFAULT 'RIGHT',
"positionPreference" TEXT NOT NULL DEFAULT 'BOTH',
"bio" TEXT,
"yearsPlaying" INTEGER,
"matchesPlayed" INTEGER NOT NULL DEFAULT 0,
"matchesWon" INTEGER NOT NULL DEFAULT 0,
"matchesLost" INTEGER NOT NULL DEFAULT 0,
"totalPoints" INTEGER NOT NULL DEFAULT 0,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"isVerified" BOOLEAN NOT NULL DEFAULT false,
"lastLogin" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_users" ("avatarUrl", "bio", "createdAt", "email", "firstName", "handPreference", "id", "isActive", "isVerified", "lastLogin", "lastName", "password", "phone", "playerLevel", "positionPreference", "role", "updatedAt") SELECT "avatarUrl", "bio", "createdAt", "email", "firstName", "handPreference", "id", "isActive", "isVerified", "lastLogin", "lastName", "password", "phone", "playerLevel", "positionPreference", "role", "updatedAt" FROM "users";
DROP TABLE "users";
ALTER TABLE "new_users" RENAME TO "users";
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
-- CreateIndex
CREATE INDEX "level_history_userId_idx" ON "level_history"("userId");
-- CreateIndex
CREATE INDEX "friends_requesterId_idx" ON "friends"("requesterId");
-- CreateIndex
CREATE INDEX "friends_addresseeId_idx" ON "friends"("addresseeId");
-- CreateIndex
CREATE INDEX "friends_status_idx" ON "friends"("status");
-- CreateIndex
CREATE UNIQUE INDEX "friends_requesterId_addresseeId_key" ON "friends"("requesterId", "addresseeId");
-- CreateIndex
CREATE INDEX "groups_createdById_idx" ON "groups"("createdById");
-- CreateIndex
CREATE INDEX "group_members_groupId_idx" ON "group_members"("groupId");
-- CreateIndex
CREATE INDEX "group_members_userId_idx" ON "group_members"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "group_members_groupId_userId_key" ON "group_members"("groupId", "userId");
-- CreateIndex
CREATE INDEX "recurring_bookings_userId_idx" ON "recurring_bookings"("userId");
-- CreateIndex
CREATE INDEX "recurring_bookings_courtId_idx" ON "recurring_bookings"("courtId");
-- CreateIndex
CREATE INDEX "recurring_bookings_dayOfWeek_idx" ON "recurring_bookings"("dayOfWeek");
-- CreateIndex
CREATE INDEX "recurring_bookings_isActive_idx" ON "recurring_bookings"("isActive");
-- CreateIndex
CREATE UNIQUE INDEX "match_results_bookingId_key" ON "match_results"("bookingId");
-- CreateIndex
CREATE INDEX "match_results_team1Player1Id_idx" ON "match_results"("team1Player1Id");
-- CreateIndex
CREATE INDEX "match_results_team1Player2Id_idx" ON "match_results"("team1Player2Id");
-- CreateIndex
CREATE INDEX "match_results_team2Player1Id_idx" ON "match_results"("team2Player1Id");
-- CreateIndex
CREATE INDEX "match_results_team2Player2Id_idx" ON "match_results"("team2Player2Id");
-- CreateIndex
CREATE INDEX "match_results_playedAt_idx" ON "match_results"("playedAt");
-- CreateIndex
CREATE INDEX "user_stats_userId_idx" ON "user_stats"("userId");
-- CreateIndex
CREATE INDEX "user_stats_period_periodValue_idx" ON "user_stats"("period", "periodValue");
-- CreateIndex
CREATE INDEX "user_stats_points_idx" ON "user_stats"("points");
-- CreateIndex
CREATE UNIQUE INDEX "user_stats_userId_period_periodValue_key" ON "user_stats"("userId", "period", "periodValue");

View File

@@ -0,0 +1 @@
-- This is an empty migration.