El objetivo de este ejercicio es crear una API para gestionar eventos, productos y pedidos. El entregable es el código de la API subido a un repositorio de GitHub. Vuestro entregable deberá funcionar con la colección de Postman que tenéis disponible.
- Todas las rutas están bajo el ámbito de una empresa (company).
- Todas las rutas (excepto auth y crear un pedido) requieren un token JWT válido en la cabecera de autorización:
Authorization: Bearer {token}
- Todos los precios se manejan en céntimos de euro.
- Todas las fechas se manejan en formato ISO 8601. (YYYY-MM-DD)
- Podéis utilizar cualquier sistema de organización: Linear, Trello, Notion, una app de notas, un fichero Markdown, un folio, o directamente nada.
- Mi recomendación es que tengais algo, lo que sea, pero os va a ayudar a que os sea más fácil organizaros y gestionar el ejercicio.
- El código debe estar correctamente organizado por capas (routers, controllers, services, repositories, models)
- No tendría ni que comentarlo, pero para que quede claro: El código debe de estar correectamente indentado
- Añadir un fichero .gitignore para no subir el .env ni el node_modules
- No hace falta que generéis un QR, de momento lo podemos dejar vacío
- Podéis usar cualquier referencia de los proyectos en los que hemos trabajado en clase:
Authorization: Bearer <token>
http://localhost:3000/api
POST /auth/register
Content-Type: application/json
{
"name": "string",
"email": "string",
"password": "string",
"company": {
"name": "string",
"description": "string",
"cif": "string"
}
}
POST /auth/login
Content-Type: application/json
{
"email": "string",
"password": "string"
}
Todas las rutas de eventos están bajo el ámbito de una empresa (company):
GET /company/:companyId/events
GET /company/:companyId/events/:id
POST /company/:companyId/events
Content-Type: application/json
{
"name": "string",
"description": "string",
"start_at": "2024-03-20T19:00:00.000Z",
"ends_at": "2024-03-20T23:00:00.000Z",
"booking_available": true,
"max_tickets_for_order": 4,
"address": "string"
}
PUT /company/:companyId/events/:id
Content-Type: application/json
{
"name": "string",
"description": "string",
"start_at": "2024-03-20T19:00:00.000Z",
"ends_at": "2024-03-20T23:00:00.000Z",
"booking_available": true,
"max_tickets_for_order": 4,
"address": "string"
}
DELETE /company/:companyId/events/:id
Query params de consulta para GET /events:
- booking: "open" | "closed"
- start_at: Fecha
Los productos están bajo el ámbito de los eventos:
GET /company/:companyId/events/:eventId/products
GET /company/:companyId/events/:eventId/products/:id
POST /company/:companyId/events/:eventId/products
Content-Type: application/json
{
"name": "string",
"description": "string",
"price": 25.99,
"max_sales": 100
}
PUT /company/:companyId/events/:eventId/products/:id
Content-Type: application/json
{
"name": "string",
"description": "string",
"price": 2599,
"max_sales": 100
}
DELETE /company/:companyId/events/:eventId/products/:id
Los pedidos están bajo el ámbito de los eventos:
GET /company/:companyId/events/:eventId/orders
GET /company/:companyId/events/:eventId/orders/:id
POST /company/:companyId/events/:eventId/orders
Content-Type: application/json
{
"items": [
{
"product_id": "65f1a2b3c4d5e6f7g8h9i0j1",
"name": "string",
"email": "string",
"price": "number",
"identification_number": "string"
}
]
}
PUT /company/:companyId/events/:eventId/orders/:id
Content-Type: application/json
{
"status": "confirmed"
}
DELETE /company/:companyId/events/:eventId/orders/:id
POST /company/:companyId/events/:eventId/orders/redeem/:id
- Relación uno a uno con Company
- Campos:
id
(ObjectId)name
(String, requerido)email
(String, requerido, único)password
(String, requerido)company_id
(ObjectId, ref: Company)- Marcas de tiempo:
created_at
,updated_at
- Relación uno a muchos con Users
- Campos:
id
(ObjectId)name
(String, requerido)description
(String, requerido)cif
(String, requerido, único)slug
(String, único, auto-generado)- Marcas de tiempo:
created_at
,updated_at
- Pertenece a Company
- Tiene muchos Products
- Campos:
id
(ObjectId)name
(String, requerido)description
(String, requerido)start_at
(Date, requerido)ends_at
(Date, requerido)company_id
(ObjectId, ref: Company)booking_available
(Boolean, por defecto: false)max_tickets_for_order
(Number, requerido)slug
(String, único, auto-generado)address
(String, requerido)- Marcas de tiempo:
created_at
,updated_at
- Pertenece a Event
- Campos:
id
(ObjectId)name
(String, requerido)description
(String, requerido)price
(Number, requerido)event_id
(ObjectId, ref: Event)max_sales
(Number, requerido)- Marcas de tiempo:
created_at
,updated_at
- Pertenece a Event
- Tiene muchos OrderItems
- Tiene muchas Activities
- Campos:
id
(ObjectId)event_id
(ObjectId, ref: Event)total_price
(Number, requerido)total_items
(Number, requerido)status
(String, enum: ['pending', 'confirmed', 'cancelled'])- Marcas de tiempo:
created_at
,updated_at
- Pertenece a Order
- Campos:
id
(ObjectId)order_id
(ObjectId, ref: Order)product_id
(ObjectId, ref: Product)name
(String, requerido)email
(String, requerido)identification_number
(String, requerido)price
(Number, requerido)redeemed_at
(Date)qr
(String, único, auto-generado)- Marcas de tiempo:
created_at
,updated_at
- Pertenece a Order
- Campos:
id
(ObjectId)order_id
(ObjectId, ref: Order)message
(String, requerido)event
(String, enum: ['created', 'updated', 'deleted'])properties
(Un objeto con los campos relevantes que valoréis cada uno)- Marcas de tiempo:
created_at
200 OK
: Solicitud exitosa201 Created
: Recurso creado204 No Content
: Recurso eliminado
400 Bad Request
: Entrada inválida401 Unauthorized
: Token faltante o inválido403 Forbidden
: Token válido pero permisos insuficientes404 Not Found
: Recurso no encontrado500 Internal Server Error
: Error del servidor
Las respuestas de error incluyen un mensaje:
{
"message": "Descripción del error"
}
Podéis probar la api en postman utilizando el endpoint https://eventos.tesserapass.es/api