3f46d8a7341f6fc4104c125ec5728e9e263a8530
Seis vueltas completas del pipeline contra los datos reales de UJ2606UR001
mostraron que la mayoria de los reintentos los provocaba el propio schema, no
el modelo:
- alcance.max(40) contra una cotizacion de 58 partidas garantizaba un rechazo de
Zod en CADA corrida. Sube a 120. El tope solo acota una respuesta desbocada;
la completitud del documento ya no depende de este array desde d20007d2.
- titulo.max(80) se quedaba corto y costo un reintento en 2 de 6 corridas.
Sube a 140.
Y dos rarezas del proveedor, ambas observadas contra la API real:
- MiniMax a veces envuelve los elementos de un array en {item: {...}}. Se
normaliza antes de validar, solo cuando "item" es la unica clave, para no
tocar un campo legitimo con ese nombre.
- A veces emite DOS bloques tool_use en una respuesta. Antes se tomaba el
primero a secas; ahora se prueban todos y gana el que valide.
Sobre el error de tipo de documento que se vio en produccion: NO se reprodujo en
seis corridas completas contra los mismos datos, y la generacion que lo siguio
completo sin problema (la fila quedo en la tabla). La evidencia apunta a un
fallo transitorio del proveedor, no a un defecto determinista nuestro. En vez de
inventar un arreglo para algo que no se puede reproducir, se reintentan los
fallos transitorios (5xx, 429, timeouts, red y los 400 con mensaje de parseo
interno) con espera creciente.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Cotizador E3
Sistema de generación de cotizaciones para Consultoría E3 (marketing digital, Querétaro MX). Servicios organizados en 4 fases, dos tipos de pago (único / mensual), planes CRM Bucéfalo y financiamiento opcional. Exporta a PDF y Excel.
Stack
- Frontend / app web: Next.js 16 (App Router) + React 19 + Tailwind CSS v4 + Zustand
- ORM: Prisma 7 (cliente generado en
src/generated/prisma, driver adapterPrismaPg) - Base de datos: PostgreSQL 16 (vía Docker)
- Auth: JWT (
jose) en cookie httpOnly, contraseñas conbcryptjs - API alterna: servicio Python FastAPI en
api/(para n8n / integraciones)
Requisitos
- Node.js 20+
- Docker (para PostgreSQL)
- Un archivo
.enven la raíz — copia .env.example y define al menosJWT_SECRET
Arranque rápido (Windows)
start.bat :: levanta PostgreSQL en Docker, aplica migraciones y arranca Next.js
stop.bat :: detiene todo
Arranque manual
docker compose up -d postgres # base de datos
npx prisma migrate deploy # aplica migraciones
npx tsx prisma/seed.ts # carga catálogo (idempotente)
npm run dev # http://localhost:3000
Comandos
| Comando | Propósito |
|---|---|
npm run dev |
Servidor de desarrollo (puerto 3000) |
npm run build |
Build de producción (incluye chequeo de tipos) |
npm run lint |
ESLint |
npm run db:migrate |
prisma migrate dev |
npm run db:seed |
Carga de datos semilla |
npm run db:studio |
Prisma Studio |
npm run db:generate |
Regenera el cliente Prisma |
API Python (opcional)
cd api
pip install -r requirements.txt
uvicorn main:app --reload --port 8000 # Swagger en /docs
Referencia completa de endpoints en api/COTIZADOR_API_SKILL.md.
Despliegue en Coolify
El stack de producción está en docker-compose.coolify.yml: postgres + web (Next.js) + api (FastAPI). El contenedor web aplica las migraciones de Prisma automáticamente en cada arranque.
Pasos
- Sube el repo a GitHub (privado recomendado).
- En Coolify: + New Resource → Docker Compose, conecta el repo y la rama.
- En la configuración del recurso, define Docker Compose Location =
/docker-compose.coolify.yml. - Coolify detecta los servicios y asigna dominio a
web(puerto 3000) yapi(puerto 8000) vía las variablesSERVICE_FQDN_*— configura los dominios deseados en la UI. - Define las variables de entorno en Coolify:
| Variable | Obligatoria | Notas |
|---|---|---|
JWT_SECRET |
Sí | openssl rand -base64 32 |
API_KEY |
Sí (para el API) | Clave para agentes/n8n |
DB_PASSWORD |
Recomendada | Password de PostgreSQL (default postgres) |
RUN_SEED |
Primer deploy | true solo la primera vez; luego false |
SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD / SEED_ADMIN_NAME |
Primer deploy | Usuario admin inicial |
SEED_ASESOR_EMAIL / SEED_ASESOR_PASSWORD / SEED_ASESOR_NAME |
No | Asesor opcional |
- Deploy. Orden de arranque:
postgres(healthy) →web(migra + seed + sirve) →api. - Después del primer despliegue exitoso, cambia
RUN_SEEDafalsey redeploya (el seed es idempotente, pero no hace falta correrlo cada vez).
Healthchecks
- Web:
GET /api/health(verifica también la conexión a la BD) - API:
GET /health
Notas
- No expongas el puerto 5432: los servicios se comunican por la red interna del compose.
- El volumen
postgres_datapersiste la base de datos entre deploys. No lo borres. - El API expone REST en
https://<dominio-api>con auth porX-API-Keyo JWT. El servidor MCP se retiro el 2026-07-28 (verAGENTS.md). - Las versiones de
api/requirements.txtestan fijas a proposito: un rango abierto dejo entrarmcp2.0.0 y tumbo el API en produccion. Sube dependencias a proposito, no al redesplegar. - La fórmula de financiamiento y los cálculos viven duplicados en
src/lib/calculators.tsyapi/app/services/calculators.py— mantenlos en paridad.
Documentación para agentes
Las convenciones del proyecto, gotchas de Prisma 7 / PDFKit / Next.js 16 y el modelo de datos
están en AGENTS.md (importado por CLAUDE.md).
Languages
TypeScript
78%
Python
21.2%
Dockerfile
0.3%
Batchfile
0.2%
CSS
0.2%