Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ierinconc/billar-pro-backend/llms.txt

Use this file to discover all available pages before exploring further.

The tables (mesas) API manages the complete lifecycle of every billiard table in the hall: creating and configuring tables, opening and closing player sessions with automatic billing calculation, editing table properties, and removing tables from service. All seven endpoints require a valid JWT bearer token in the Authorization header — see the Authentication page to obtain one.

Table object

Every endpoint that returns a table uses the following schema:
id
integer
Auto-generated primary key for the table record.
numero
integer
The table’s display number within the hall. Must be unique among all active tables.
estado
string
Current occupancy state of the table. One of "LIBRE" (available) or "OCUPADA" (in use).
precioPorHora
number
Hourly rate for this table in the local currency. Must be greater than 0.
horaInicio
string | null
ISO-8601 datetime at which the current session started. null when estado is "LIBRE".
activa
boolean
Whether the table is active. Only tables with activa = true are returned by the list endpoint. A table with session history is soft-deleted by setting this to false.

GET /api/mesas

Returns a list of all active tables (activa = true). Tables that have been soft-deleted are excluded. Auth required: Yes

Example request

curl http://localhost:8080/api/mesas \
  -H "Authorization: Bearer <token>"

Example response (HTTP 200)

[
  {
    "id": 1,
    "numero": 1,
    "estado": "LIBRE",
    "precioPorHora": 8000.0,
    "horaInicio": null,
    "activa": true
  },
  {
    "id": 2,
    "numero": 2,
    "estado": "OCUPADA",
    "precioPorHora": 8000.0,
    "horaInicio": "2025-01-15T10:00:00",
    "activa": true
  }
]

POST /api/mesas

Creates a new billiard table. The table is initialized with estado = "LIBRE" and activa = true. Auth required: Yes

Request body

numero
integer
required
The display number for the new table. Must be unique among all currently active tables — the service checks existsByNumeroAndActivaTrue before saving.
precioPorHora
number
required
The hourly billing rate for the table. Must be provided and strictly greater than 0.

Example request

curl -X POST http://localhost:8080/api/mesas \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"numero": 3, "precioPorHora": 8000.0}'

Example response (HTTP 200)

{
  "id": 3,
  "numero": 3,
  "estado": "LIBRE",
  "precioPorHora": 8000.0,
  "horaInicio": null,
  "activa": true
}

Validation errors (HTTP 404)

Conditionmensaje
Another active table already has this numero"Ya existe una mesa activa con ese número"
precioPorHora is missing (null)"El precio de la hora por mesa es obligatorio"
precioPorHora is <= 0"El precio del tiempo por mesa debe ser mayor a 0"

GET /api/mesas/

Returns a single table by its primary key ID. Auth required: Yes

Path parameter

id
integer
required
The primary key (id) of the table to retrieve.

Example request

curl http://localhost:8080/api/mesas/1 \
  -H "Authorization: Bearer <token>"

Example response (HTTP 200)

{
  "id": 1,
  "numero": 1,
  "estado": "LIBRE",
  "precioPorHora": 8000.0,
  "horaInicio": null,
  "activa": true
}

Error (HTTP 404)

If no table with the given ID exists, the server returns:
{
  "timestamp": "2025-01-15T10:30:00.123456",
  "status": 404,
  "error": "Recurso no encontrado",
  "mensaje": "Mesa no encontrada"
}

PUT /api/mesas//ocupar

Opens a new playing session on a table. Sets estado to "OCUPADA" and records horaInicio as the current server time (LocalDateTime.now()). This timestamp is later used by the close endpoint to compute billing. Auth required: Yes

Path parameter

id
integer
required
The primary key of the table to open.

Example request

curl -X PUT http://localhost:8080/api/mesas/1/ocupar \
  -H "Authorization: Bearer <token>"

Example response (HTTP 200)

{
  "id": 1,
  "numero": 1,
  "estado": "OCUPADA",
  "precioPorHora": 8000.0,
  "horaInicio": "2025-01-15T10:00:00",
  "activa": true
}

Error (HTTP 400)

If the table is already "OCUPADA", a NegocioException is thrown:
{
  "timestamp": "2025-01-15T10:30:00.123456",
  "status": 400,
  "error": "Error de negocio",
  "mensaje": "La mesa ya está ocupada"
}

PUT /api/mesas//cerrar

Closes the current session on a table, computes the bill, creates a Sesion record (linking any pending consumptions to it), and resets the table to "LIBRE". Returns a billing summary DTO instead of the raw Mesa object. Auth required: Yes

Billing calculation

The service computes the charge using fractional hours based on elapsed minutes:
horas = Duration.between(horaInicio, now()).toMinutes() / 60.0
totalMesa = horas × precioPorHora
The final totalGeneral is the sum of totalAPagar (table time) and totalConsumos (any consumptions linked to the session).

Path parameter

id
integer
required
The primary key of the table to close.

Example request

curl -X PUT http://localhost:8080/api/mesas/1/cerrar \
  -H "Authorization: Bearer <token>"

Response fields

horasJugadas
number
Total elapsed time in fractional hours (e.g. 1.5 for 90 minutes).
precioPorHora
number
The hourly rate that was applied to this session, taken from the table record.
totalAPagar
number
The table-time charge: horasJugadas × precioPorHora.
totalConsumos
number
The sum of all consumptions linked to this session (drinks, snacks, etc.).
totalGeneral
number
Grand total: totalAPagar + totalConsumos.

Example response (HTTP 200)

{
  "horasJugadas": 1.5,
  "precioPorHora": 8000.0,
  "totalAPagar": 12000.0,
  "totalConsumos": 5000.0,
  "totalGeneral": 17000.0
}

Error (HTTP 400)

If the table is already "LIBRE" (no active session to close), a NegocioException is thrown:
{
  "timestamp": "2025-01-15T10:30:00.123456",
  "status": 400,
  "error": "Error de negocio",
  "mensaje": "La mesa ya está libre"
}

PUT /api/mesas/

Updates the numero and precioPorHora of an existing table. The table must be in "LIBRE" state — editing an in-use table is not allowed. Auth required: Yes

Path parameter

id
integer
required
The primary key of the table to edit.

Request body

numero
integer
required
The new display number to assign to the table.
precioPorHora
number
required
The new hourly rate to apply to future sessions.

Example request

curl -X PUT http://localhost:8080/api/mesas/1 \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"numero": 1, "precioPorHora": 10000.0}'

Example response (HTTP 200)

{
  "id": 1,
  "numero": 1,
  "estado": "LIBRE",
  "precioPorHora": 10000.0,
  "horaInicio": null,
  "activa": true
}

Error (HTTP 404)

If the table is currently "OCUPADA", the operation is rejected:
{
  "timestamp": "2025-01-15T10:30:00.123456",
  "status": 404,
  "error": "Recurso no encontrado",
  "mensaje": "No se puede editar una mesa ocupada"
}

DELETE /api/mesas//delete

Removes a table from service. The deletion strategy depends on whether the table has any historical session records:
  • No sessions → the table row is permanently deleted from the database (deleteById).
  • Has sessions → the table is soft-deleted: activa is set to false and the record is kept for historical integrity. The table will no longer appear in GET /api/mesas.
Auth required: Yes

Path parameter

id
integer
required
The primary key of the table to delete or deactivate.

Example request

curl -X DELETE http://localhost:8080/api/mesas/3/delete \
  -H "Authorization: Bearer <token>"

Response (HTTP 204 No Content)

An empty body is returned regardless of whether the table was physically deleted or soft-deleted.
Tables that have at least one linked session are never physically deleted. Setting activa = false preserves the full session history and billing records for auditing while hiding the table from active operations. To check whether a table was soft-deleted, query it directly via GET /api/mesas/{id} — the activa field will be false.

Error (HTTP 404)

If no table with the given ID exists:
{
  "timestamp": "2025-01-15T10:30:00.123456",
  "status": 404,
  "error": "Recurso no encontrado",
  "mensaje": "Mesa no encontrada"
}

Error response schema

Business-rule violations (NegocioException) return HTTP 400; not-found and other RuntimeExceptions return HTTP 404. Both use the same envelope shape from GlobalExceptionHandler:
timestamp
string
ISO-8601 local datetime of when the error occurred.
status
integer
HTTP status code — 400 for business errors, 404 for not-found errors.
error
string
Error category: "Error de negocio" (400) or "Recurso no encontrado" (404).
mensaje
string
Specific description of what went wrong.

Build docs developers (and LLMs) love