5.0 KiB
AGENTS.md — Cotizador E3
Quick Reference
| Command | Purpose |
|---|---|
npm run dev |
Start Next.js dev server on port 3000 |
npm run build |
Production build (runs TypeScript check) |
npm run lint |
ESLint (flat config, eslint-config-next) |
npx tsx prisma/seed.ts |
Run seed (upserts all data, idempotent) |
npx prisma migrate dev |
Create/apply migration |
npx prisma generate |
Regenerate Prisma client |
npx prisma studio |
Prisma Studio GUI |
Windows environment. Use start.bat / stop.bat to manage Docker PostgreSQL + Next.js together. PowerShell is the shell. Paths with brackets (e.g. [id]) require -LiteralPath in PowerShell, not -Path.
Two backends, one database. The Next.js app (src/, port 3000) and a standalone Python FastAPI service (api/, port 8000) both talk to the same PostgreSQL DB. Prisma owns the schema/migrations; the Python API reads/writes the same tables independently. docker-compose.yml runs postgres + the api service; Next.js is run separately via npm run dev / start.bat.
Prisma 7 — Critical Gotchas
- Prisma client is NOT at
@prisma/client. It's generated tosrc/generated/prisma/and imported as@/generated/prisma/client. - Uses
PrismaPgdriver adapter (from@prisma/adapter-pg) with individual connection params (host/port/user/password/database), NOT a connection string. TheconnectionStringapproach causes SCRAM auth errors with postgres:postgres. prisma.config.tshas noseedproperty (unsupported by PrismaConfig type). Run seed manually withnpx tsx prisma/seed.ts.- After changing
schema.prisma: runnpx prisma migrate dev, thennpx prisma generate. - The
globalForPrismasingleton pattern insrc/lib/db.tsprevents hot-reload connection leaks in dev.
PDFKit — Server-Side PDF
pdfkitis excluded from Next.js bundling viaserverExternalPackagesinnext.config.ts. Without this, font metric files (.afm) can't be resolved at runtime.- Footer auto-page-break bug:
doc.text()aty > page.height - margins.bottomtriggers pdfkit's automatic page addition. To write footers in the bottom margin, temporarily setdoc.page.margins.bottom = 0, write, then restore. UsebufferPages: true+switchToPage()to add footers after all content. - Returns
Promise<Buffer>— convert toUint8ArrayforNextResponsebody.
Next.js 16 Conventions
- Async params: Dynamic route params are
Promise<{ id: string }>— mustawait paramsbefore use. - All pages are
force-dynamic— no static generation or ISR. - Tailwind CSS v4 — no
tailwind.config.*file. Config is inpostcss.config.mjs(using@tailwindcss/postcss) and CSS custom properties via@theme inlineinsrc/app/globals.css.
Data Model Notes
- Configuracion is a key-value store (
clave/valor), not a traditional settings model. New config keys:color_primario,color_secundario,logo_base64(branding for PDF export). - Cascading deletes: Cotizacion → ServicioCotizado, PlanBucefaloCotizacion use
onDelete: Cascade. - Cotización number format:
UJ{YY}{MM}{AsesorInitials}{seq}(e.g.UJ2605AG001) — seegenerarNumeroCotizacioninsrc/lib/calculators.ts. Sequence is 3 digits, zero-padded. - Vigencia = 15 business days from fecha (excludes Sat/Sun) —
calcularVigencia. - IVA_RATE = 0.16 (16%).
- Bucéfalo CRM plan prices (in
calculators.ts, NOT the DB): basico=$1,000, estandar=$3,500, premium=$4,500, empresarial=$7,500 (monthly). - Financing lives in the
FinanciamientoPlantable (3/6/9/12 months). Formula:comisionTotal = monto × comision%,pagoMensual = (monto + comisionTotal) × (1 + tasa) / meses, then add 16% IVA. Both backends must keep this formula identical.
Architecture
src/
app/ # Next.js App Router pages + API routes
api/ # Route handlers (REST endpoints)
cotizaciones/[id]/editar/ # Edit mode (reuses CotizacionEditor via EditorLoader)
components/ # Shared client components (ExportButtons, Sidebar)
lib/ # Utilities: db.ts, store.ts, calculators.ts, pdf-generator.ts
generated/prisma/ # Prisma client output (gitignored)
prisma/
schema.prisma # 8 models
seed.ts # All catalog data (23 services, bonos, planes, config)
migrations/ # Prisma migration files
- Zustand store (
src/lib/store.ts) manages cotización editor state (draft form). Used by both new and edit pages. - ExportButtons.tsx has 4 variants:
ExportExcelButtonSaved/ExportPDFButtonSaved(GET by ID) andExportExcelButtonDraft/ExportPDFButtonDraft(POST with body). - The old standalone
ExportExcelButton.tsxwas deleted — all exports now go throughExportButtons.tsx.
Domain
Quotation system for Consultoría E3 (digital marketing agency in Querétaro, MX). Services organized in 4 phases: Fase 0 (Auditorías), Fase 1 (Setup/Infra), Fase 2 (Publicidad/Manejo), Fase 3 (Contenido/SEO). Two payment types: unico (one-time) and mensual (recurring). Optional Bucéfalo CRM plans and Openpay financing.