Use this file to discover all available pages before exploring further.
VinylVibes uses PostgreSQL (hosted on Neon) managed through Prisma ORM. The schema defines five models that together cover every core concern of the application: user accounts and authentication, purchase orders, individual order line items, shipping addresses, and per-user browsing history.
model venta { id_venta Int @id @default(autoincrement()) id_cliente Int total Decimal @default(0) @db.Decimal(12, 2) estado estado_venta @default(pendiente) fecha DateTime @default(now()) updated_at DateTime @default(now()) cliente usuario @relation(fields: [id_cliente], references: [id_usuario]) lineas linea_venta[] envio envio?}
Field
Type
Nullable
Default
Description
id_venta
Int
No
auto-increment
Primary key
id_cliente
Int
No
—
FK → usuario.id_usuario
total
Decimal(12,2)
No
0
Order total in the store’s currency
estado
estado_venta
No
pendiente
Order lifecycle state; see enum below
fecha
DateTime
No
now()
Order creation timestamp
updated_at
DateTime
No
now()
Last modification timestamp
In the current checkout flow, new orders are created with estado = 'pagada' directly — pendiente is the schema default but is not used by the checkout endpoint.
model linea_venta { id_linea Int @id @default(autoincrement()) id_venta Int discogs_id String @db.VarChar(20) titulo String @db.VarChar(200) artista String @db.VarChar(200) cantidad Int p_unitario Decimal @db.Decimal(10, 2) subtotal Decimal @db.Decimal(10, 2) venta venta @relation(fields: [id_venta], references: [id_venta], onDelete: Cascade) @@unique([id_venta, discogs_id])}
Field
Type
Nullable
Default
Description
id_linea
Int
No
auto-increment
Primary key
id_venta
Int
No
—
FK → venta.id_venta (cascade delete)
discogs_id
String (VARCHAR 20)
No
—
Discogs release ID
titulo
String (VARCHAR 200)
No
—
Album title at the time of purchase
artista
String (VARCHAR 200)
No
—
Artist name at the time of purchase
cantidad
Int
No
—
Number of copies ordered
p_unitario
Decimal(10,2)
No
—
Backend-calculated unit price
subtotal
Decimal(10,2)
No
—
p_unitario × cantidad
titulo and artista are denormalised onto the line item intentionally. Because prices and metadata come from the live Discogs API, snapshotting them at checkout time preserves an accurate record of what the customer was charged.
Order created but payment not yet confirmed. This is the schema default, though the current checkout flow skips straight to pagada.
pagada
Payment confirmed. This is the state applied by POST /checkout.
enviada
Order has been dispatched by the seller.
entregada
Order received and delivered to the customer.
cancelada
Order cancelled, regardless of prior state.
Only admin accounts (not demo) can transition an order’s estado via PUT /admin/ventas/:id/estado. All five values in the enum are valid targets for that endpoint.
Default role assigned on registration. Grants access to catalog browsing, history tracking, checkout, and personal purchase history.
vendedor
Reserved for future inventory management features. Currently has the same permissions as cliente.
admin
Full access — all user-facing endpoints plus all admin endpoints, including user management, sales management, and Redis diagnostics.
demo
Read-only admin. Can access GET admin endpoints and GET /redis-ping, but is blocked from all write operations with a 403.
The demo role cannot be assigned through the API. PUT /admin/usuarios/:id/rol only accepts cliente, vendedor, and admin as valid values. Granting demo requires a direct database update.
usuario → venta — A single user can have many orders. Deleting a user does not cascade-delete their orders; existing venta rows continue to hold the id_cliente FK.
venta → linea_venta — Each order has one or more line items. onDelete: Cascade ensures no orphaned line items remain if an order is removed.
venta → envio — The relation is optional (envio?) on the venta side and enforced as unique on envio.id_venta, making it a true one-to-one. Cascade delete keeps referential integrity.
usuario → historial_usuario — Cascade delete removes all browsing history when the parent user account is deleted.
The 10-item limit is enforced in application logic inside POST /historial, not through a database constraint. The database itself imposes no maximum row count per user.
The historial_usuario table is managed as a fixed-size FIFO queue per user. The logic runs on every POST /historial call:
Upsert check — If the incoming discogs_id already exists in the user’s history, only visto_en (and optionally genero/estilo) is updated. The total count is unchanged, and the FIFO eviction step is skipped.
Count check — If the release is new to this user’s history, the application counts existing rows: prisma.historial_usuario.count({ where: { id_usuario } }).
Eviction — If the count is 10 or more, the row with the earliest visto_en value is fetched and deleted before the new row is inserted. This keeps the table at a maximum of 10 unique releases per user at all times.
Insert — The new history entry is created.
POST /historial (new discogs_id) │ ▼ count rows for user │ count < 10?──── Yes ────► insert new row │ No │ ▼ find oldest visto_en row │ ▼ delete oldest row │ ▼ insert new row