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:
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 literales2026-10-02 17:42:55 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Qué es la deuda
apps/api/src/prisma/contract.prismano define ningúnenum: todos los campos con valores cerrados sonString, y sus valores se repiten como literales en unos 60 lugares deapps/apiyapps/web.User.roleadmin,cashierOperatingDay.status/CashRegisterSession.statusopen,closedShopCart.statusopen,paid,refundedPayment.statuscompleted,refundedPayment.paymentMethodcash,card,transferProductHistory.statusactive,archivedInventoryMovement.type/CashMovement.typein,outProduct.statusactive(no se usa)Además hay tipos paralelos a mano (
CashMovementType,InventoryMovementTypeen los DTOs;"in" | "out"enweb/_core/types/entities.ts) y mapas de etiquetas duplicados y tipados comoRecord<string, string>(ROLE_LABELS,PAYMENT_LABELS,PAYMENT_METHODS).Qué estamos pagando hoy
inventory-movement.service.ts:57)."cloesd") compila sin aviso y rompe filtros en silencio.Arreglo propuesto
Declarar enums con la sintaxis de Prisma 8 (
references/contract.md→ Enums). Con@@type("pg/text@1")la columna sigue siendotexty solo se agrega un CHECK:Lo mismo para
OpenClosedStatus,CartStatus,PaymentStatus,PaymentMethod,PriceStatusyMovementType.prisma contract emity nueva migraciónRecord<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
Usar enums de Prisma 8 en el contrato en lugar de String y literalesto [debt] Usar enums de Prisma 8 en el contrato en lugar de String y literales