Saltar al contenido principal

Listas de precios

Archivo: api/src/routes/admin.js (router priceLists) · Prefijo: /api/price-lists

Una lista de precios define cuánto paga un cliente. Cada producto puede tener un precio específico en la lista; si no lo tiene, se calcula como base_price × multiplier. Ver Reglas de negocio → Precios.

GET /api/price-lists​

Acceso: Autenticado

Respuesta 200

{
"items": [
{
"id": "…",
"name": "Mayorista",
"description": "Clientes con volumen",
"multiplier": 0.9,
"is_default": false,
"isDefault": false,
"active": true,
"scope": "selected",
"clientIds": ["<clients.id>", "<clients.id>"]
}
]
}
CampoDescripción
scopeall si es la lista general (isDefault), selected si no
clientIdsIDs de cliente (clients.id, con o sin usuario de login) que tienen esta lista asignada

POST /api/price-lists​

Acceso: admin

CampoTipoRequeridoPor defecto
namestringSí (único)
descriptionstringNo
multipliernúmero > 0No1
isDefaultbooleanNofalse
activebooleanNotrue

Solo puede existir una lista con isDefault = true (índice único parcial). Para cambiar la lista por defecto, desmarca primero la actual.

Respuesta 201: { "id": "<uuid>" }

PUT /api/price-lists/:id/clients​

Define a quién aplica la lista.

Acceso: admin

Body

CampoTipoDescripción
scopeall | selectedall: la lista pasa a ser la lista general (se desmarca la anterior). No cambia las asignaciones explícitas de ningún cliente. selected: se asigna exactamente a clientIds
clientIdsuuid[]IDs de cliente (clients.id). Con selected, los clientes que tenían la lista y no vienen aquí vuelven a la lista general
{ "scope": "selected", "clientIds": ["0b56…", "db45…"] }

Respuesta 200: { "id": "<uuid>", "scope": "selected", "assigned": 2 } · Errores: 404 NOT_FOUND.

PUT /api/price-lists/:id​

Acceso: admin. Mismos campos, opcionales (COALESCE).

Respuesta 200: { "id": "<uuid>" } · Errores: 404 NOT_FOUND.

DELETE /api/price-lists/:id​

Borra la lista y sus precios específicos. Los clientes que la usaban quedan sin lista y pasan a usar la lista por defecto.

Acceso: admin · Respuesta 204


GET /api/price-lists/:id/products​

Todos los productos con su precio base y, si existe, su precio específico en esta lista.

Acceso: Autenticado

Respuesta 200

{
"items": [
{
"productId": "…",
"sku": "TOR-001",
"name": "Tornillo drywall 6x1",
"unit": "caja",
"active": true,
"basePrice": 10000,
"customPrice": 8800
}
]
}

customPrice es null si el producto no tiene precio específico.

POST /api/price-lists/:id/products​

Reemplaza todos los precios específicos de la lista por los enviados (borra y vuelve a insertar en una transacción). Enviar items: [] elimina todos los precios específicos.

Acceso: admin

Body

{
"items": [
{ "productId": "a1b2…", "price": 8800 },
{ "productId": "c3d4…", "price": 15500 }
]
}

Respuesta 200: { "updated": 2 } · Errores: 404 NOT_FOUND si la lista no existe.