Skip to content

Instantly share code, notes, and snippets.

@pepeloper
Last active January 17, 2025 19:12
Show Gist options
  • Save pepeloper/c0fb60955c529c62a23adb792ddf65dd to your computer and use it in GitHub Desktop.
Save pepeloper/c0fb60955c529c62a23adb792ddf65dd to your computer and use it in GitHub Desktop.
Documentación del ejercicio para la API del Sistema de Tickets

Documentación del ejercicio para la API del Sistema de Tickets

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.

Consideraciones previas:

  • 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:

Estructura de Rutas y Autorización

Authorization: Bearer <token>

URL Base

http://localhost:3000/api

Endpoints

Autenticación

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"
}

Events

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

Products

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

Orders

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

Modelos de Datos

image

User

  • 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

Company

  • 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

Event

  • 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

Product

  • 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

Order

  • 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

OrderItem

  • 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

Activity

  • 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

Códigos de Respuesta

Respuestas Exitosas

  • 200 OK: Solicitud exitosa
  • 201 Created: Recurso creado
  • 204 No Content: Recurso eliminado

Respuestas de Error

  • 400 Bad Request: Entrada inválida
  • 401 Unauthorized: Token faltante o inválido
  • 403 Forbidden: Token válido pero permisos insuficientes
  • 404 Not Found: Recurso no encontrado
  • 500 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment