[debt] Usar enums de Prisma 8 en el contrato en lugar de String y literales #2

Open
opened 2026-10-02 17:35:53 +00:00 by Carlos · 0 comments
Member

Qué es la deuda

apps/api/src/prisma/contract.prisma no define ningún enum: todos los campos con valores cerrados son String, y sus valores se repiten como literales en unos 60 lugares de apps/api y apps/web.

Campo Valores en uso
User.role admin, cashier
OperatingDay.status / CashRegisterSession.status open, closed
ShopCart.status open, paid, refunded
Payment.status completed, refunded
Payment.paymentMethod cash, card, transfer
ProductHistory.status active, archived
InventoryMovement.type / CashMovement.type in, out
Product.status default active (no se usa)

Además hay tipos paralelos a mano (CashMovementType, InventoryMovementType en los DTOs; "in" | "out" en web/_core/types/entities.ts) y mapas de etiquetas duplicados y tipados como Record<string, string> (ROLE_LABELS, PAYMENT_LABELS, PAYMENT_METHODS).

Qué estamos pagando hoy

  • La base de datos acepta cualquier texto en estos campos; la única validación es manual (inventory-movement.service.ts:57).
  • Un error de tipeo en un literal ("cloesd") compila sin aviso y rompe filtros en silencio.
  • Agregar un valor nuevo (otro método de pago, otro rol) obliga a buscar a mano cada literal y cada mapa de etiquetas.

Arreglo propuesto

Declarar enums con la sintaxis de Prisma 8 (references/contract.md → Enums). Con @@type("pg/text@1") la columna sigue siendo text y solo se agrega un CHECK:

enum UserRole {
  @@type("pg/text@1")
  admin   = "admin"
  cashier = "cashier"
}

Lo mismo para OpenClosedStatus, CartStatus, PaymentStatus, PaymentMethod, PriceStatus y MovementType.

  • Verificar que los datos existentes no tengan valores fuera de los enums (si no, el CHECK falla)
  • Agregar los enums al contrato, prisma contract emit y nueva migración
  • Eliminar los tipos paralelos y tomar los del contrato
  • Reemplazar los literales en servicios y páginas
  • Centralizar los mapas de etiquetas como Record<Enum, string>

Techo de esta ronda

Solo enums en el contrato y reemplazo de literales. Fuera: validación de entrada en el API (#4) y compartir tipos entre api y web mediante un paquete packages/shared (#6).

Superficie

Contrato Prisma (apps/api/src/prisma)

Módulos

Base de datos / contrato Prisma, API / backend, Web / frontend

Esfuerzo

M — un PR, un día

Riesgo de no tocarlo

Medio

### Qué es la deuda `apps/api/src/prisma/contract.prisma` no define ningún `enum`: todos los campos con valores cerrados son `String`, y sus valores se repiten como literales en unos 60 lugares de `apps/api` y `apps/web`. | Campo | Valores en uso | |---|---| | `User.role` | `admin`, `cashier` | | `OperatingDay.status` / `CashRegisterSession.status` | `open`, `closed` | | `ShopCart.status` | `open`, `paid`, `refunded` | | `Payment.status` | `completed`, `refunded` | | `Payment.paymentMethod` | `cash`, `card`, `transfer` | | `ProductHistory.status` | `active`, `archived` | | `InventoryMovement.type` / `CashMovement.type` | `in`, `out` | | `Product.status` | default `active` (no se usa) | Además hay tipos paralelos a mano (`CashMovementType`, `InventoryMovementType` en los DTOs; `"in" | "out"` en `web/_core/types/entities.ts`) y mapas de etiquetas duplicados y tipados como `Record<string, string>` (`ROLE_LABELS`, `PAYMENT_LABELS`, `PAYMENT_METHODS`). ### Qué estamos pagando hoy - La base de datos acepta cualquier texto en estos campos; la única validación es manual (`inventory-movement.service.ts:57`). - Un error de tipeo en un literal (`"cloesd"`) compila sin aviso y rompe filtros en silencio. - Agregar un valor nuevo (otro método de pago, otro rol) obliga a buscar a mano cada literal y cada mapa de etiquetas. ### Arreglo propuesto Declarar enums con la sintaxis de Prisma 8 (`references/contract.md` → *Enums*). Con `@@type("pg/text@1")` la columna sigue siendo `text` y solo se agrega un CHECK: ```prisma enum UserRole { @@type("pg/text@1") admin = "admin" cashier = "cashier" } ``` Lo mismo para `OpenClosedStatus`, `CartStatus`, `PaymentStatus`, `PaymentMethod`, `PriceStatus` y `MovementType`. - [ ] Verificar que los datos existentes no tengan valores fuera de los enums (si no, el CHECK falla) - [ ] Agregar los enums al contrato, `prisma contract emit` y nueva migración - [ ] Eliminar los tipos paralelos y tomar los del contrato - [ ] Reemplazar los literales en servicios y páginas - [ ] Centralizar los mapas de etiquetas como `Record<Enum, string>` ### Techo de esta ronda Solo enums en el contrato y reemplazo de literales. Fuera: validación de entrada en el API (#4) y compartir tipos entre api y web mediante un paquete `packages/shared` (#6). ### Superficie Contrato Prisma (apps/api/src/prisma) ### Módulos Base de datos / contrato Prisma, API / backend, Web / frontend ### Esfuerzo M — un PR, un día ### Riesgo de no tocarlo Medio
Carlos changed title from Usar enums de Prisma 8 en el contrato en lugar de String y literales to [debt] Usar enums de Prisma 8 en el contrato en lugar de String y literales 2026-10-02 17:42:55 +00:00
Carlos self-assigned this 2026-10-02 20:07:51 +00:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RynextTechnologies/PDV#2