Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/123048152-JJDS/CafeteriaPM_S203/llms.txt

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

The /productos/ router handles the cafeteria menu and ingredient inventory. Products belong to categories and optionally include a recipe — a list of ingredients and quantities consumed per unit sold. When an order is marked as ready (listo), the API automatically calls descontar_ingredientes(), which deducts ingredient stock based on these per-product recipes. This makes ingredient tracking live and automatic without any extra API calls from the client.

Categories

Categories classify both menu products and operational expenses. The tipo field determines whether a category applies to products, expenses, or both.

GET /productos/categorias — List All Categories

Required role: Any authenticated user Returns all product/expense categories defined in the system. Use the returned id values as id_categoria when creating products.

Response

id
integer
required
Unique category identifier.
nombre
string
required
Display name of the category (e.g. "Bebidas", "Comida", "Postres").
tipo
string
required
Category applicability. One of:
  • "producto" — applies to menu items only
  • "gasto" — applies to expense tracking only
  • "ambos" — applies to both products and expenses

Example

curl -X GET "https://api.cafeteriapm.com/productos/categorias" \
  -H "Authorization: Bearer <token>"
[
  { "id": 1, "nombre": "Bebidas",  "tipo": "producto" },
  { "id": 2, "nombre": "Comida",   "tipo": "producto" },
  { "id": 3, "nombre": "Insumos",  "tipo": "gasto"    },
  { "id": 4, "nombre": "General",  "tipo": "ambos"    }
]

Error codes

StatusDetail
401Token missing or expired

POST /productos/categorias — Create Category

Required role: admin Creates a new category. Category names must be unique. Returns 201 Created on success.

Request Body

nombre
string
required
Unique display name for the new category.
tipo
string
required
Applicability type. Must be one of: "producto", "gasto", "ambos".

Response

Returns the newly created CategoryOut object with HTTP 201 Created.

Example

curl -X POST "https://api.cafeteriapm.com/productos/categorias" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"nombre": "Postres", "tipo": "producto"}'
{ "id": 5, "nombre": "Postres", "tipo": "producto" }

Error codes

StatusDetail
400"La categoría ya existe" — a category with this name already exists
401Token missing or expired
403Authenticated user is not admin

Ingredients

Ingredients represent the raw inventory items consumed when menu products are prepared. Each ingredient tracks current stock, a minimum threshold for low-stock alerts, and a unit cost for expense reporting.

GET /productos/ingredientes — List All Ingredients

Required role: Any authenticated user Returns all ingredients ordered by ID ascending.

Response

Returns an array of IngredientOut objects. See IngredientOut schema below.

Example

curl -X GET "https://api.cafeteriapm.com/productos/ingredientes" \
  -H "Authorization: Bearer <token>"
[
  {
    "id": 1,
    "nombre": "Café molido",
    "unidad": "g",
    "stock_actual": 5000.0,
    "stock_minimo": 500.0,
    "costo_unitario": 0.08
  },
  {
    "id": 2,
    "nombre": "Leche",
    "unidad": "ml",
    "stock_actual": 12000.0,
    "stock_minimo": 2000.0,
    "costo_unitario": 0.012
  }
]

Error codes

StatusDetail
401Token missing or expired

GET /productos/ingredientes/stock-bajo — List Low-Stock Ingredients

Required role: Any authenticated user Returns all ingredients where stock_actual <= stock_minimo. Use this endpoint to power low-stock alerts and purchasing triggers. Returns an empty array if all ingredients are sufficiently stocked.

Response

Returns an array of IngredientOut objects with the same shape as GET /productos/ingredientes.

Example

curl -X GET "https://api.cafeteriapm.com/productos/ingredientes/stock-bajo" \
  -H "Authorization: Bearer <token>"
[
  {
    "id": 3,
    "nombre": "Azúcar",
    "unidad": "g",
    "stock_actual": 200.0,
    "stock_minimo": 500.0,
    "costo_unitario": 0.002
  }
]

Error codes

StatusDetail
401Token missing or expired

GET /productos/ingredientes/ — Get Single Ingredient

Required role: Any authenticated user Retrieves a single ingredient by its numeric ID.

Path Parameters

id
integer
required
The unique ID of the ingredient to retrieve.

Response

Returns a single IngredientOut object. See IngredientOut schema below.

Example

curl -X GET "https://api.cafeteriapm.com/productos/ingredientes/1" \
  -H "Authorization: Bearer <token>"

Error codes

StatusDetail
404"Ingrediente no encontrado" — no ingredient with the given ID exists
401Token missing or expired

POST /productos/ingredientes — Create Ingredient

Required role: admin, cocina Creates a new ingredient in the inventory. All numeric fields default to 0 if not supplied.

Request Body

nombre
string
required
Name of the ingredient (e.g. "Café molido", "Leche entera").
unidad
string
required
Unit of measurement (e.g. "g", "ml", "piezas", "kg").
stock_actual
float
default:"0"
Current stock level in the specified unit.
stock_minimo
float
default:"0"
Threshold below which the ingredient appears in the low-stock list.
costo_unitario
float
default:"0"
Cost per unit in the local currency, used for expense calculations.

Response

Returns the newly created IngredientOut object with HTTP 201 Created.

Example

curl -X POST "https://api.cafeteriapm.com/productos/ingredientes" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Crema para café",
    "unidad": "ml",
    "stock_actual": 3000.0,
    "stock_minimo": 500.0,
    "costo_unitario": 0.018
  }'
{
  "id": 8,
  "nombre": "Crema para café",
  "unidad": "ml",
  "stock_actual": 3000.0,
  "stock_minimo": 500.0,
  "costo_unitario": 0.018
}

Error codes

StatusDetail
401Token missing or expired
403User role is not admin or cocina

PATCH /productos/ingredientes/ — Update Ingredient

Required role: admin, cocina Partially updates an ingredient’s metadata. Only fields included in the request body are modified; all others retain their current values. This endpoint updates the ingredient record itself — use ajustar-stock to increment or decrement stock by a delta value instead of setting it absolutely.

Path Parameters

id
integer
required
The unique ID of the ingredient to update.

Request Body

All fields are optional.
nombre
string
New name for the ingredient.
unidad
string
New unit of measurement.
stock_actual
float
Absolute new stock level (sets value directly — use ajustar-stock for delta adjustments).
stock_minimo
float
New low-stock threshold.
costo_unitario
float
New unit cost.

Response

Returns the updated IngredientOut object.

Example

curl -X PATCH "https://api.cafeteriapm.com/productos/ingredientes/1" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"stock_minimo": 750.0, "costo_unitario": 0.09}'

Error codes

StatusDetail
404"Ingrediente no encontrado"
401Token missing or expired
403User role is not admin or cocina

PATCH /productos/ingredientes//ajustar-stock — Adjust Stock by Delta

Required role: admin, cocina Adds or subtracts a quantity from the ingredient’s current stock. Positive cantidad values increase stock (e.g. restocking after a purchase); negative values decrease it (e.g. manual waste recording). The API rejects any adjustment that would result in a negative stock level.

Path Parameters

id
integer
required
The unique ID of the ingredient to adjust.

Query Parameters

cantidad
float
required
The delta to apply to stock_actual. Positive values add stock; negative values subtract. The resulting stock_actual must be >= 0.

Response

Returns a confirmation object with the updated stock level.
message
string
Confirmation string: "Stock actualizado".
stock_actual
float
The new stock level after the adjustment.

Example

# Add 2000g of coffee grounds after a delivery
curl -X PATCH "https://api.cafeteriapm.com/productos/ingredientes/1/ajustar-stock?cantidad=2000" \
  -H "Authorization: Bearer <token>"

# Record 150ml waste
curl -X PATCH "https://api.cafeteriapm.com/productos/ingredientes/2/ajustar-stock?cantidad=-150" \
  -H "Authorization: Bearer <token>"
{ "message": "Stock actualizado", "stock_actual": 7000.0 }

Error codes

StatusDetail
400"El stock no puede ser negativo" — the adjustment would push stock below zero
404"Ingrediente no encontrado"
401Token missing or expired
403User role is not admin or cocina

DELETE /productos/ingredientes/ — Delete Ingredient

Required role: admin Permanently deletes an ingredient. The database enforces referential integrity: if the ingredient is referenced by any product recipe (ProductIngredient) or any purchase record, the deletion is blocked with a 400 error. Returns HTTP 204 No Content on success.

Path Parameters

id
integer
required
The unique ID of the ingredient to delete.

Example

curl -X DELETE "https://api.cafeteriapm.com/productos/ingredientes/8" \
  -H "Authorization: Bearer <token>"
A successful response returns HTTP 204 No Content with an empty body.

Error codes

StatusDetail
400"No se puede eliminar el ingrediente porque está siendo usado en productos o compras."
404"Ingrediente no encontrado"
401Token missing or expired
403Authenticated user is not admin

IngredientOut Response Shape

id
integer
required
Unique ingredient identifier.
nombre
string
required
Ingredient name.
unidad
string
required
Unit of measurement (e.g. "g", "ml", "piezas").
stock_actual
float
required
Current quantity in stock expressed in unidad.
stock_minimo
float
required
Low-stock alert threshold. Ingredients with stock_actual <= stock_minimo appear in the /stock-bajo list.
costo_unitario
float
required
Cost per unit of measurement, used for expense calculations.

Products

Products are the menu items customers can order. Each product belongs to a category and may carry a recipe that links it to one or more ingredients with per-unit quantities.

GET /productos/ — List Products

Required role: Any authenticated user Returns all menu products. Optionally filter by availability to show only items currently orderable.

Query Parameters

disponible
boolean
Filter products by availability. Pass true to list only orderable items; false for unavailable items. Omit to return all products regardless of status.

Response

Returns an array of ProductOut objects. See ProductOut schema below.

Example

# Fetch only currently available products
curl -X GET "https://api.cafeteriapm.com/productos/?disponible=true" \
  -H "Authorization: Bearer <token>"
[
  {
    "id": 1,
    "nombre": "Café Americano",
    "descripcion": "Café negro, tamaño estándar",
    "precio": 25.0,
    "disponible": true,
    "categoria": { "id": 1, "nombre": "Bebidas", "tipo": "producto" },
    "created_at": "2024-01-10T10:00:00"
  }
]

Error codes

StatusDetail
401Token missing or expired

GET /productos/ — Get Product with Recipe

Required role: Any authenticated user Retrieves a single product along with its full ingredient recipe. The response uses the extended ProductDetailOut schema which includes an ingredientes array detailing every ingredient and its per-unit consumption quantity.

Path Parameters

id
integer
required
The unique ID of the product to retrieve.

Response

Returns a ProductDetailOut object.
ingredientes
array
Array of recipe entries. Each object describes one ingredient used in this product.
All other fields are identical to ProductOut. See ProductOut schema below.

Example

curl -X GET "https://api.cafeteriapm.com/productos/1" \
  -H "Authorization: Bearer <token>"
{
  "id": 1,
  "nombre": "Café Americano",
  "descripcion": "Café negro, tamaño estándar",
  "precio": 25.0,
  "disponible": true,
  "categoria": { "id": 1, "nombre": "Bebidas", "tipo": "producto" },
  "created_at": "2024-01-10T10:00:00",
  "ingredientes": [
    { "id_ingrediente": 1, "nombre": "Café molido", "unidad": "g",  "cantidad": 10.0 },
    { "id_ingrediente": 4, "nombre": "Agua",        "unidad": "ml", "cantidad": 200.0 }
  ]
}

Error codes

StatusDetail
404"Producto no encontrado"
401Token missing or expired

POST /productos/ — Create Product

Required role: admin, cocina Creates a new menu product and, optionally, its ingredient recipe in a single atomic operation. Returns 201 Created on success.
The ingredientes field in the request body is optional — products can exist without a recipe. This is useful for items whose ingredients are not tracked in the inventory system, or for simple products that don’t consume trackable stock.

Request Body

nombre
string
required
Name of the product as it should appear on the menu (e.g. "Café Americano").
precio
float
required
Selling price per unit in the local currency.
descripcion
string
Optional description shown to customers or staff.
id_categoria
integer
ID of the category this product belongs to. Must be a valid ID from GET /productos/categorias.
disponible
boolean
default:"true"
Whether this product can currently be ordered. Defaults to true.
imagen_url
string
Optional URL to a product image for display in the ordering interface.
ingredientes
array
default:"[]"
Recipe entries. Each entry links an ingredient ID to the quantity consumed per unit sold. If omitted or empty, the product is created without stock tracking.

Response

Returns the newly created ProductOut object with HTTP 201 Created. See ProductOut schema below.

Example

curl -X POST "https://api.cafeteriapm.com/productos/" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Café Americano",
    "descripcion": "Café negro",
    "precio": 25.00,
    "id_categoria": 1,
    "disponible": true,
    "imagen_url": "https://example.com/cafe.jpg",
    "ingredientes": [
      {"id_ingrediente": 1, "cantidad": 10},
      {"id_ingrediente": 3, "cantidad": 200}
    ]
  }'
{
  "id": 1,
  "nombre": "Café Americano",
  "descripcion": "Café negro",
  "precio": 25.0,
  "disponible": true,
  "categoria": { "id": 1, "nombre": "Bebidas", "tipo": "producto" },
  "created_at": "2024-06-10T15:00:00"
}

Error codes

StatusDetail
400"Ingrediente {id} no encontrado" — one of the supplied ingredient IDs does not exist
401Token missing or expired
403User role is not admin or cocina

PATCH /productos/ — Update Product

Required role: admin, cocina Partially updates a product’s metadata fields. Only the fields included in the request body are modified. This endpoint does not update the ingredient recipe — to modify the recipe, delete and recreate the product.

Path Parameters

id
integer
required
The unique ID of the product to update.

Request Body

All fields are optional.
nombre
string
New product name.
descripcion
string
New description.
precio
float
New selling price.
id_categoria
integer
New category assignment.
disponible
boolean
New availability status.
imagen_url
string
New image URL.

Response

Returns the updated ProductOut object.

Example

curl -X PATCH "https://api.cafeteriapm.com/productos/1" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"precio": 28.00, "descripcion": "Café negro, tamaño grande"}'

Error codes

StatusDetail
404"Producto no encontrado"
401Token missing or expired
403User role is not admin or cocina

PATCH /productos//toggle — Toggle Availability

Required role: admin, cocina Flips the disponible boolean of a product in a single call — no request body required. If the product is currently available (true), it becomes unavailable (false), and vice versa. This is the recommended way to quickly take a product on or off the menu.

Path Parameters

id
integer
required
The unique ID of the product to toggle.

Response

Returns the updated ProductOut object with the new disponible value reflected.

Example

curl -X PATCH "https://api.cafeteriapm.com/productos/1/toggle" \
  -H "Authorization: Bearer <token>"
{
  "id": 1,
  "nombre": "Café Americano",
  "descripcion": "Café negro",
  "precio": 28.0,
  "disponible": false,
  "categoria": { "id": 1, "nombre": "Bebidas", "tipo": "producto" },
  "created_at": "2024-06-10T15:00:00"
}

Error codes

StatusDetail
404"Producto no encontrado"
401Token missing or expired
403User role is not admin or cocina

DELETE /productos/ — Delete Product

Required role: admin Permanently deletes a product and all its recipe (ProductIngredient) entries. The deletion is blocked if the product has any associated order line items in the database. Returns HTTP 204 No Content on success.

Path Parameters

id
integer
required
The unique ID of the product to delete.

Example

curl -X DELETE "https://api.cafeteriapm.com/productos/1" \
  -H "Authorization: Bearer <token>"
A successful response returns HTTP 204 No Content with an empty body.

Error codes

StatusDetail
400"No se puede eliminar el producto porque tiene pedidos asociados." — referential integrity block
404"Producto no encontrado"
401Token missing or expired
403Authenticated user is not admin

ProductOut Response Shape

id
integer
required
Unique product identifier.
nombre
string
required
Product name as shown on the menu.
descripcion
string
Optional description. null if not set.
precio
float
required
Selling price per unit.
disponible
boolean
required
true if the product can currently be ordered; false if it has been taken off the menu.
categoria
object
Nested category object. null if no category has been assigned.
created_at
datetime
required
ISO 8601 timestamp of when the product was created.

Build docs developers (and LLMs) love