Complete rename across all layers: UI branding, package names (@smashpoint/web, @smashpoint/shared), infrastructure (Docker, DB config), seed data, documentation, and logo/favicon. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1272 lines
22 KiB
Markdown
1272 lines
22 KiB
Markdown
# API Reference - SmashPoint
|
|
|
|
Documentacion completa de los endpoints REST de la API de SmashPoint.
|
|
|
|
## Informacion General
|
|
|
|
- **Base URL:** `http://localhost:3000/api`
|
|
- **Autenticacion:** Basada en sesiones (NextAuth.js)
|
|
- **Formato:** JSON
|
|
- **Codificacion:** UTF-8
|
|
|
|
### Codigos de Estado HTTP
|
|
|
|
| Codigo | Descripcion |
|
|
|--------|-------------|
|
|
| 200 | Exito |
|
|
| 201 | Recurso creado |
|
|
| 400 | Solicitud invalida |
|
|
| 401 | No autorizado |
|
|
| 403 | Prohibido (sin permisos) |
|
|
| 404 | Recurso no encontrado |
|
|
| 409 | Conflicto (ej: duplicado) |
|
|
| 500 | Error interno del servidor |
|
|
|
|
### Roles de Usuario
|
|
|
|
| Rol | Descripcion | Permisos |
|
|
|-----|-------------|----------|
|
|
| `SUPER_ADMIN` | Administrador del sistema | Acceso total |
|
|
| `ORG_ADMIN` | Administrador de organizacion | Gestion completa de la organizacion |
|
|
| `SITE_ADMIN` | Administrador de sede | Gestion de una sede especifica |
|
|
| `RECEPTIONIST` | Recepcionista | Reservas, ventas, clientes |
|
|
| `COACH` | Entrenador | Acceso limitado |
|
|
|
|
---
|
|
|
|
## Autenticacion
|
|
|
|
### Endpoints de NextAuth
|
|
|
|
```
|
|
GET/POST /api/auth/[...nextauth]
|
|
```
|
|
|
|
NextAuth maneja automaticamente los siguientes endpoints:
|
|
|
|
| Ruta | Metodo | Descripcion |
|
|
|------|--------|-------------|
|
|
| `/api/auth/signin` | GET | Pagina de inicio de sesion |
|
|
| `/api/auth/signout` | POST | Cerrar sesion |
|
|
| `/api/auth/session` | GET | Obtener sesion actual |
|
|
| `/api/auth/csrf` | GET | Token CSRF |
|
|
| `/api/auth/providers` | GET | Proveedores disponibles |
|
|
| `/api/auth/callback/:provider` | GET/POST | Callback de proveedor |
|
|
|
|
---
|
|
|
|
## Sedes (Sites)
|
|
|
|
### Listar Sedes
|
|
|
|
```http
|
|
GET /api/sites
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro",
|
|
"slug": "padel-club-centro",
|
|
"address": "Calle Principal 123",
|
|
"phone": "+34 600 000 000",
|
|
"email": "centro@padelclub.com",
|
|
"timezone": "Europe/Madrid",
|
|
"openTime": "08:00",
|
|
"closeTime": "22:00",
|
|
"courtCount": 6
|
|
}
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
## Canchas (Courts)
|
|
|
|
### Listar Canchas
|
|
|
|
```http
|
|
GET /api/courts
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Filtrar por sede |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz456",
|
|
"name": "Cancha 1",
|
|
"type": "INDOOR",
|
|
"status": "AVAILABLE",
|
|
"pricePerHour": 30.00,
|
|
"description": "Cancha cubierta con iluminacion LED",
|
|
"features": ["LED", "Cristal"],
|
|
"displayOrder": 1,
|
|
"isActive": true,
|
|
"site": {
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro",
|
|
"openTime": "08:00",
|
|
"closeTime": "22:00"
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear Cancha
|
|
|
|
```http
|
|
POST /api/courts
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
**Roles permitidos:** `SUPER_ADMIN`, `SITE_ADMIN`
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"siteId": "clxyz123",
|
|
"name": "Cancha 7",
|
|
"type": "OUTDOOR",
|
|
"pricePerHour": 25.00,
|
|
"description": "Cancha exterior",
|
|
"features": ["Cesped artificial"],
|
|
"displayOrder": 7
|
|
}
|
|
```
|
|
|
|
**Campos Requeridos:** `siteId`, `name`, `pricePerHour`
|
|
|
|
**Respuesta Exitosa (201):**
|
|
|
|
```json
|
|
{
|
|
"id": "clxyz789",
|
|
"name": "Cancha 7",
|
|
"type": "OUTDOOR",
|
|
"status": "AVAILABLE",
|
|
"pricePerHour": 25.00,
|
|
"isActive": true,
|
|
"site": { ... }
|
|
}
|
|
```
|
|
|
|
### Obtener Cancha por ID
|
|
|
|
```http
|
|
GET /api/courts/{id}
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
{
|
|
"id": "clxyz456",
|
|
"name": "Cancha 1",
|
|
"type": "INDOOR",
|
|
"status": "AVAILABLE",
|
|
"pricePerHour": 30.00,
|
|
"site": {
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro",
|
|
"address": "Calle Principal 123",
|
|
"phone": "+34 600 000 000"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Actualizar Cancha
|
|
|
|
```http
|
|
PUT /api/courts/{id}
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
**Roles permitidos:** `SUPER_ADMIN`, `SITE_ADMIN`
|
|
|
|
**Cuerpo de la Solicitud (todos los campos opcionales):**
|
|
|
|
```json
|
|
{
|
|
"name": "Cancha 1 VIP",
|
|
"type": "INDOOR",
|
|
"status": "MAINTENANCE",
|
|
"pricePerHour": 35.00,
|
|
"description": "Cancha premium renovada",
|
|
"features": ["LED", "Cristal", "Climatizada"],
|
|
"isActive": true
|
|
}
|
|
```
|
|
|
|
### Eliminar Cancha
|
|
|
|
```http
|
|
DELETE /api/courts/{id}
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
**Roles permitidos:** `SUPER_ADMIN`, `SITE_ADMIN`
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
{
|
|
"message": "Court deleted successfully"
|
|
}
|
|
```
|
|
|
|
### Obtener Disponibilidad
|
|
|
|
```http
|
|
GET /api/courts/{id}/availability
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `date` | string | Fecha en formato YYYY-MM-DD |
|
|
|
|
---
|
|
|
|
## Reservas (Bookings)
|
|
|
|
### Listar Reservas
|
|
|
|
```http
|
|
GET /api/bookings
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Filtrar por sede |
|
|
| `date` | string | Filtrar por fecha (YYYY-MM-DD) |
|
|
| `status` | string | PENDING, CONFIRMED, CANCELLED, COMPLETED, NO_SHOW |
|
|
| `clientId` | string | Filtrar por cliente |
|
|
| `courtId` | string | Filtrar por cancha |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz001",
|
|
"startTime": "2024-01-15T10:00:00.000Z",
|
|
"endTime": "2024-01-15T11:30:00.000Z",
|
|
"status": "CONFIRMED",
|
|
"paymentType": "CARD",
|
|
"totalPrice": 45.00,
|
|
"paidAmount": 45.00,
|
|
"notes": null,
|
|
"playerNames": ["Juan", "Maria", "Pedro", "Ana"],
|
|
"court": {
|
|
"id": "clxyz456",
|
|
"name": "Cancha 1",
|
|
"type": "INDOOR"
|
|
},
|
|
"client": {
|
|
"id": "clxyz100",
|
|
"firstName": "Juan",
|
|
"lastName": "Garcia",
|
|
"email": "juan@email.com",
|
|
"phone": "+34 600 111 222"
|
|
},
|
|
"site": {
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro"
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear Reserva
|
|
|
|
```http
|
|
POST /api/bookings
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"courtId": "clxyz456",
|
|
"clientId": "clxyz100",
|
|
"startTime": "2024-01-15T10:00:00.000Z",
|
|
"endTime": "2024-01-15T11:30:00.000Z",
|
|
"paymentType": "card",
|
|
"notes": "Reserva para cumpleanos",
|
|
"participants": [
|
|
{ "name": "Juan" },
|
|
{ "name": "Maria" },
|
|
{ "name": "Pedro" },
|
|
{ "name": "Ana" }
|
|
]
|
|
}
|
|
```
|
|
|
|
**Respuesta Exitosa (201):**
|
|
|
|
```json
|
|
{
|
|
"id": "clxyz002",
|
|
"startTime": "2024-01-15T10:00:00.000Z",
|
|
"endTime": "2024-01-15T11:30:00.000Z",
|
|
"status": "PENDING",
|
|
"totalPrice": 45.00,
|
|
"paidAmount": 0.00,
|
|
"court": { ... },
|
|
"client": { ... }
|
|
}
|
|
```
|
|
|
|
**Errores Comunes:**
|
|
|
|
- `409`: Ya existe una reserva en ese horario
|
|
- `404`: Cancha o cliente no encontrado
|
|
- `400`: La cancha no esta disponible
|
|
|
|
### Obtener Reserva por ID
|
|
|
|
```http
|
|
GET /api/bookings/{id}
|
|
```
|
|
|
|
### Actualizar Reserva
|
|
|
|
```http
|
|
PUT /api/bookings/{id}
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"status": "CONFIRMED",
|
|
"notes": "Cliente confirmado por telefono",
|
|
"playerNames": ["Juan", "Maria", "Pedro", "Ana"]
|
|
}
|
|
```
|
|
|
|
### Cancelar Reserva
|
|
|
|
```http
|
|
DELETE /api/bookings/{id}
|
|
```
|
|
|
|
**Cuerpo Opcional:**
|
|
|
|
```json
|
|
{
|
|
"cancelReason": "Cliente solicito cancelacion"
|
|
}
|
|
```
|
|
|
|
### Registrar Pago de Reserva
|
|
|
|
```http
|
|
POST /api/bookings/{id}/pay
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"amount": 45.00,
|
|
"paymentType": "CARD",
|
|
"reference": "TRX-123456"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Clientes (Clients)
|
|
|
|
### Listar Clientes
|
|
|
|
```http
|
|
GET /api/clients
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `search` | string | Buscar por nombre, email o telefono |
|
|
| `isActive` | boolean | Filtrar por estado activo |
|
|
| `limit` | number | Limite de resultados (max 100) |
|
|
| `offset` | number | Desplazamiento para paginacion |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "clxyz100",
|
|
"firstName": "Juan",
|
|
"lastName": "Garcia",
|
|
"email": "juan@email.com",
|
|
"phone": "+34 600 111 222",
|
|
"level": "INTERMEDIATE",
|
|
"tags": ["VIP", "Torneo"],
|
|
"isActive": true,
|
|
"createdAt": "2024-01-01T00:00:00.000Z",
|
|
"memberships": [
|
|
{
|
|
"id": "clxyz200",
|
|
"status": "ACTIVE",
|
|
"remainingHours": 8,
|
|
"endDate": "2024-06-01T00:00:00.000Z",
|
|
"plan": {
|
|
"id": "clxyz300",
|
|
"name": "Plan Premium",
|
|
"discountPercent": 20
|
|
}
|
|
}
|
|
],
|
|
"_count": {
|
|
"bookings": 15
|
|
}
|
|
}
|
|
],
|
|
"pagination": {
|
|
"total": 150,
|
|
"limit": 50,
|
|
"offset": 0,
|
|
"hasMore": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Crear Cliente
|
|
|
|
```http
|
|
POST /api/clients
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"firstName": "Maria",
|
|
"lastName": "Lopez",
|
|
"email": "maria@email.com",
|
|
"phone": "+34 600 333 444",
|
|
"dateOfBirth": "1990-05-15",
|
|
"address": "Calle Nueva 45",
|
|
"notes": "Prefiere canchas interiores",
|
|
"tags": ["Principiante"],
|
|
"skillLevel": "BEGINNER",
|
|
"emergencyContact": {
|
|
"name": "Pedro Lopez",
|
|
"phone": "+34 600 555 666"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Campos Requeridos:** `firstName`, `lastName`
|
|
|
|
### Obtener Cliente por ID
|
|
|
|
```http
|
|
GET /api/clients/{id}
|
|
```
|
|
|
|
### Actualizar Cliente
|
|
|
|
```http
|
|
PUT /api/clients/{id}
|
|
```
|
|
|
|
### Obtener Membresia del Cliente
|
|
|
|
```http
|
|
GET /api/clients/{id}/membership
|
|
```
|
|
|
|
---
|
|
|
|
## Productos (Products)
|
|
|
|
### Listar Productos
|
|
|
|
```http
|
|
GET /api/products
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Filtrar por sede |
|
|
| `categoryId` | string | Filtrar por categoria |
|
|
| `search` | string | Buscar por nombre |
|
|
| `isActive` | boolean | Solo productos activos |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz400",
|
|
"name": "Pelotas HEAD Pro",
|
|
"description": "Bote de 3 pelotas",
|
|
"sku": "BALL-HEAD-001",
|
|
"price": 6.50,
|
|
"costPrice": 4.00,
|
|
"stock": 50,
|
|
"minStock": 10,
|
|
"trackStock": true,
|
|
"image": null,
|
|
"isActive": true,
|
|
"lowStock": false,
|
|
"category": {
|
|
"id": "clxyz500",
|
|
"name": "Pelotas",
|
|
"description": "Pelotas de padel"
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear Producto
|
|
|
|
```http
|
|
POST /api/products
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`, `SITE_ADMIN`
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"siteId": "clxyz123",
|
|
"categoryId": "clxyz500",
|
|
"name": "Overgrip Wilson",
|
|
"description": "Pack de 3 overgrips",
|
|
"sku": "GRIP-WILSON-001",
|
|
"price": 8.00,
|
|
"costPrice": 5.50,
|
|
"stock": 30,
|
|
"minStock": 5,
|
|
"trackStock": true
|
|
}
|
|
```
|
|
|
|
### Actualizar Stock
|
|
|
|
```http
|
|
PATCH /api/products/{id}/stock
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"adjustment": 10,
|
|
"reason": "Reposicion de inventario"
|
|
}
|
|
```
|
|
|
|
### Listar Categorias
|
|
|
|
```http
|
|
GET /api/products/categories
|
|
```
|
|
|
|
---
|
|
|
|
## Ventas (Sales)
|
|
|
|
### Listar Ventas
|
|
|
|
```http
|
|
GET /api/sales
|
|
```
|
|
|
|
**Autenticacion:** Requerida
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Filtrar por sede |
|
|
| `startDate` | string | Fecha inicio (YYYY-MM-DD) |
|
|
| `endDate` | string | Fecha fin (YYYY-MM-DD) |
|
|
| `clientId` | string | Filtrar por cliente |
|
|
| `createdBy` | string | Filtrar por vendedor |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz600",
|
|
"subtotal": 25.00,
|
|
"discount": 0.00,
|
|
"tax": 5.25,
|
|
"total": 30.25,
|
|
"paymentType": "CASH",
|
|
"notes": null,
|
|
"createdAt": "2024-01-15T14:30:00.000Z",
|
|
"items": [
|
|
{
|
|
"id": "clxyz601",
|
|
"quantity": 2,
|
|
"unitPrice": 6.50,
|
|
"subtotal": 13.00,
|
|
"product": {
|
|
"id": "clxyz400",
|
|
"name": "Pelotas HEAD Pro",
|
|
"sku": "BALL-HEAD-001"
|
|
}
|
|
}
|
|
],
|
|
"payments": [
|
|
{
|
|
"id": "clxyz602",
|
|
"amount": 30.25,
|
|
"paymentType": "CASH",
|
|
"reference": null
|
|
}
|
|
],
|
|
"client": null,
|
|
"createdBy": {
|
|
"id": "clxyz700",
|
|
"firstName": "Ana",
|
|
"lastName": "Martinez"
|
|
},
|
|
"cashRegister": {
|
|
"id": "clxyz800",
|
|
"site": {
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear Venta
|
|
|
|
```http
|
|
POST /api/sales
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"siteId": "clxyz123",
|
|
"clientId": "clxyz100",
|
|
"items": [
|
|
{
|
|
"productId": "clxyz400",
|
|
"quantity": 2,
|
|
"price": 6.50
|
|
},
|
|
{
|
|
"productId": "clxyz401",
|
|
"quantity": 1,
|
|
"price": 12.00
|
|
}
|
|
],
|
|
"payments": [
|
|
{
|
|
"amount": 25.00,
|
|
"method": "CASH"
|
|
}
|
|
],
|
|
"discount": 0,
|
|
"tax": 0,
|
|
"notes": "Venta rapida"
|
|
}
|
|
```
|
|
|
|
**Nota:** Requiere caja registradora abierta si hay pago en efectivo.
|
|
|
|
---
|
|
|
|
## Caja Registradora (Cash Register)
|
|
|
|
### Obtener Estado de Caja
|
|
|
|
```http
|
|
GET /api/cash-register
|
|
```
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Sede |
|
|
| `status` | string | `open`, `closed`, o `all` |
|
|
| `date` | string | Fecha especifica (YYYY-MM-DD) |
|
|
|
|
**Respuesta Exitosa (200) - Caja Abierta:**
|
|
|
|
```json
|
|
{
|
|
"id": "clxyz800",
|
|
"openingAmount": 100.00,
|
|
"closingAmount": null,
|
|
"expectedAmount": null,
|
|
"difference": null,
|
|
"openedAt": "2024-01-15T08:00:00.000Z",
|
|
"closedAt": null,
|
|
"site": {
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro"
|
|
},
|
|
"user": {
|
|
"id": "clxyz700",
|
|
"firstName": "Ana",
|
|
"lastName": "Martinez"
|
|
},
|
|
"paymentBreakdown": {
|
|
"CASH": 250.00,
|
|
"CARD": 180.00
|
|
},
|
|
"totalCashSales": 250.00,
|
|
"expectedAmount": 350.00,
|
|
"_count": {
|
|
"sales": 12,
|
|
"payments": 15
|
|
}
|
|
}
|
|
```
|
|
|
|
### Abrir Caja
|
|
|
|
```http
|
|
POST /api/cash-register
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"siteId": "clxyz123",
|
|
"openingAmount": 100.00
|
|
}
|
|
```
|
|
|
|
### Cerrar Caja
|
|
|
|
```http
|
|
PUT /api/cash-register/{id}
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"closingAmount": 345.50,
|
|
"notes": "Cuadre correcto"
|
|
}
|
|
```
|
|
|
|
### Obtener Transacciones
|
|
|
|
```http
|
|
GET /api/cash-register/{id}/transactions
|
|
```
|
|
|
|
---
|
|
|
|
## Torneos (Tournaments)
|
|
|
|
### Listar Torneos
|
|
|
|
```http
|
|
GET /api/tournaments
|
|
```
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Filtrar por sede |
|
|
| `status` | string | DRAFT, REGISTRATION_OPEN, IN_PROGRESS, COMPLETED, CANCELLED |
|
|
| `startDate` | string | Fecha inicio del rango |
|
|
| `endDate` | string | Fecha fin del rango |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz900",
|
|
"name": "Torneo de Verano 2024",
|
|
"description": "Torneo amateur categoria B",
|
|
"type": "BRACKET",
|
|
"status": "REGISTRATION_OPEN",
|
|
"startDate": "2024-07-15T09:00:00.000Z",
|
|
"endDate": "2024-07-16T20:00:00.000Z",
|
|
"maxPlayers": 32,
|
|
"entryFee": 25.00,
|
|
"site": {
|
|
"id": "clxyz123",
|
|
"name": "Padel Club Centro"
|
|
},
|
|
"_count": {
|
|
"inscriptions": 18,
|
|
"matches": 0
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear Torneo
|
|
|
|
```http
|
|
POST /api/tournaments
|
|
```
|
|
|
|
**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`, `SITE_ADMIN`
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"siteId": "clxyz123",
|
|
"name": "Torneo de Primavera",
|
|
"description": "Torneo para socios",
|
|
"date": "2024-04-20T09:00:00.000Z",
|
|
"endDate": "2024-04-21T20:00:00.000Z",
|
|
"type": "SINGLE_ELIMINATION",
|
|
"category": "B",
|
|
"maxTeams": 16,
|
|
"price": 20.00
|
|
}
|
|
```
|
|
|
|
### Obtener Torneo por ID
|
|
|
|
```http
|
|
GET /api/tournaments/{id}
|
|
```
|
|
|
|
### Actualizar Torneo
|
|
|
|
```http
|
|
PUT /api/tournaments/{id}
|
|
```
|
|
|
|
### Listar Inscripciones
|
|
|
|
```http
|
|
GET /api/tournaments/{id}/inscriptions
|
|
```
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyzabc",
|
|
"teamName": "Los Campeones",
|
|
"seedNumber": 1,
|
|
"isPaid": true,
|
|
"paidAmount": 25.00,
|
|
"registeredAt": "2024-01-10T12:00:00.000Z",
|
|
"client": {
|
|
"id": "clxyz100",
|
|
"firstName": "Juan",
|
|
"lastName": "Garcia",
|
|
"level": "ADVANCED"
|
|
},
|
|
"partner": {
|
|
"id": "clxyz101",
|
|
"firstName": "Pedro",
|
|
"lastName": "Martinez",
|
|
"level": "ADVANCED"
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Inscribir Equipo
|
|
|
|
```http
|
|
POST /api/tournaments/{id}/inscriptions
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"player1Id": "clxyz100",
|
|
"player2Id": "clxyz101",
|
|
"teamName": "Los Campeones"
|
|
}
|
|
```
|
|
|
|
### Generar Bracket
|
|
|
|
```http
|
|
POST /api/tournaments/{id}/generate-bracket
|
|
```
|
|
|
|
### Actualizar Resultado de Partido
|
|
|
|
```http
|
|
PUT /api/tournaments/{id}/matches/{matchId}
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"score1": "6-4",
|
|
"score2": "6-3",
|
|
"winnerId": "clxyzabc"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Planes de Membresia (Membership Plans)
|
|
|
|
### Listar Planes
|
|
|
|
```http
|
|
GET /api/membership-plans
|
|
```
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `includeInactive` | boolean | Incluir planes inactivos |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "clxyz300",
|
|
"name": "Plan Premium",
|
|
"description": "Acceso completo con beneficios exclusivos",
|
|
"price": 99.00,
|
|
"durationMonths": 1,
|
|
"courtHours": 10,
|
|
"discountPercent": 20,
|
|
"benefits": ["Reserva anticipada", "Descuento en tienda"],
|
|
"isActive": true,
|
|
"subscriberCount": 45,
|
|
"benefitsSummary": {
|
|
"freeHours": 10,
|
|
"bookingDiscount": 20,
|
|
"extraBenefits": ["Reserva anticipada", "Descuento en tienda"]
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
### Crear Plan
|
|
|
|
```http
|
|
POST /api/membership-plans
|
|
```
|
|
|
|
**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"name": "Plan Basico",
|
|
"description": "Plan de entrada",
|
|
"price": 29.00,
|
|
"durationMonths": 1,
|
|
"freeHours": 2,
|
|
"bookingDiscount": 10,
|
|
"storeDiscount": 5,
|
|
"extraBenefits": ["Newsletter exclusivo"]
|
|
}
|
|
```
|
|
|
|
### Actualizar Plan
|
|
|
|
```http
|
|
PUT /api/membership-plans/{id}
|
|
```
|
|
|
|
---
|
|
|
|
## Membresias (Memberships)
|
|
|
|
### Listar Membresias
|
|
|
|
```http
|
|
GET /api/memberships
|
|
```
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `status` | string | ACTIVE, EXPIRED, CANCELLED, SUSPENDED |
|
|
| `planId` | string | Filtrar por plan |
|
|
| `search` | string | Buscar por nombre/email del cliente |
|
|
| `expiring` | boolean | Solo proximas a vencer (7 dias) |
|
|
| `limit` | number | Limite de resultados |
|
|
| `offset` | number | Desplazamiento |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "clxyz200",
|
|
"startDate": "2024-01-01T00:00:00.000Z",
|
|
"endDate": "2024-06-01T00:00:00.000Z",
|
|
"status": "ACTIVE",
|
|
"remainingHours": 8,
|
|
"autoRenew": true,
|
|
"notes": null,
|
|
"plan": {
|
|
"id": "clxyz300",
|
|
"name": "Plan Premium",
|
|
"price": 99.00,
|
|
"durationMonths": 1,
|
|
"courtHours": 10,
|
|
"discountPercent": 20
|
|
},
|
|
"client": {
|
|
"id": "clxyz100",
|
|
"firstName": "Juan",
|
|
"lastName": "Garcia",
|
|
"email": "juan@email.com"
|
|
},
|
|
"isExpiring": false,
|
|
"daysUntilExpiry": 45,
|
|
"benefitsSummary": {
|
|
"freeHours": 10,
|
|
"hoursRemaining": 8,
|
|
"bookingDiscount": 20,
|
|
"extraBenefits": []
|
|
}
|
|
}
|
|
],
|
|
"pagination": {
|
|
"total": 150,
|
|
"limit": 50,
|
|
"offset": 0,
|
|
"hasMore": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Crear Membresia
|
|
|
|
```http
|
|
POST /api/memberships
|
|
```
|
|
|
|
**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`, `SITE_ADMIN`, `RECEPTIONIST`
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"clientId": "clxyz100",
|
|
"planId": "clxyz300",
|
|
"startDate": "2024-02-01T00:00:00.000Z",
|
|
"endDate": "2024-03-01T00:00:00.000Z",
|
|
"autoRenew": true,
|
|
"notes": "Primera membresia del cliente"
|
|
}
|
|
```
|
|
|
|
### Renovar Membresia
|
|
|
|
```http
|
|
POST /api/memberships/{id}/renew
|
|
```
|
|
|
|
**Cuerpo de la Solicitud:**
|
|
|
|
```json
|
|
{
|
|
"planId": "clxyz300",
|
|
"paymentMethod": "CARD"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Dashboard
|
|
|
|
### Obtener Estadisticas
|
|
|
|
```http
|
|
GET /api/dashboard/stats
|
|
```
|
|
|
|
**Parametros de Query:**
|
|
|
|
| Parametro | Tipo | Descripcion |
|
|
|-----------|------|-------------|
|
|
| `siteId` | string | Filtrar por sede |
|
|
| `date` | string | Fecha especifica (YYYY-MM-DD) |
|
|
|
|
**Respuesta Exitosa (200):**
|
|
|
|
```json
|
|
{
|
|
"stats": {
|
|
"todayBookings": 24,
|
|
"todayRevenue": 580.50,
|
|
"occupancyRate": 75,
|
|
"activeMembers": 145,
|
|
"pendingBookings": 3,
|
|
"upcomingTournaments": 2
|
|
},
|
|
"courtOccupancy": [
|
|
{
|
|
"courtId": "clxyz456",
|
|
"courtName": "Cancha 1",
|
|
"availableHours": 14,
|
|
"bookedHours": 11.5,
|
|
"occupancyPercent": 82
|
|
}
|
|
],
|
|
"recentBookings": [
|
|
{
|
|
"id": "clxyz001",
|
|
"startTime": "2024-01-15T10:00:00.000Z",
|
|
"endTime": "2024-01-15T11:30:00.000Z",
|
|
"status": "CONFIRMED",
|
|
"court": {
|
|
"id": "clxyz456",
|
|
"name": "Cancha 1"
|
|
},
|
|
"client": {
|
|
"id": "clxyz100",
|
|
"name": "Juan Garcia"
|
|
}
|
|
}
|
|
],
|
|
"date": "2024-01-15"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Errores Comunes
|
|
|
|
### Error de Autenticacion
|
|
|
|
```json
|
|
{
|
|
"error": "No autorizado"
|
|
}
|
|
```
|
|
**Codigo:** 401
|
|
|
|
### Error de Permisos
|
|
|
|
```json
|
|
{
|
|
"error": "Forbidden: Insufficient permissions"
|
|
}
|
|
```
|
|
**Codigo:** 403
|
|
|
|
### Recurso No Encontrado
|
|
|
|
```json
|
|
{
|
|
"error": "Court not found"
|
|
}
|
|
```
|
|
**Codigo:** 404
|
|
|
|
### Conflicto
|
|
|
|
```json
|
|
{
|
|
"error": "Ya existe una reserva en ese horario"
|
|
}
|
|
```
|
|
**Codigo:** 409
|
|
|
|
### Error de Validacion
|
|
|
|
```json
|
|
{
|
|
"error": "Invalid booking data",
|
|
"details": {
|
|
"courtId": ["Invalid court ID"],
|
|
"startTime": ["Required"]
|
|
}
|
|
}
|
|
```
|
|
**Codigo:** 400
|
|
|
|
---
|
|
|
|
## Notas Adicionales
|
|
|
|
### Paginacion
|
|
|
|
Los endpoints que devuelven listas soportan paginacion mediante:
|
|
|
|
- `limit`: Numero maximo de resultados (default: 50, max: 100)
|
|
- `offset`: Numero de registros a saltar
|
|
|
|
La respuesta incluye metadatos de paginacion:
|
|
|
|
```json
|
|
{
|
|
"data": [...],
|
|
"pagination": {
|
|
"total": 150,
|
|
"limit": 50,
|
|
"offset": 0,
|
|
"hasMore": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Filtrado por Sede
|
|
|
|
La mayoria de endpoints filtran automaticamente por la sede del usuario si tiene una asignada. Para usuarios con acceso a multiples sedes, se puede especificar `siteId` en los parametros de query.
|
|
|
|
### Zonas Horarias
|
|
|
|
Las fechas se manejan en UTC. Cada sede tiene configurada su zona horaria para mostrar correctamente los horarios de apertura/cierre.
|