feat: esquema unico de cotizacion FRASA 2026 (reemplaza las 4 propuestas)

Flujo aprobado por el cliente (28 sep 2026), porcentajes globales para
todos los desarrollos:
- Apartado: cantidad libre (sin minimo), se acredita dentro del enganche
  de firma; el excedente se descuenta del enganche
- Enganche de firma: 2.5% del precio (saldo a firma = max(0, 2.5% - apartado))
- Enganche: 7.5%, diferible en N mensualidades (N a eleccion del vendedor, 1-36)
- Gastos de escrituracion: 5.5%, pago unico a la firma o diferido con el
  enganche (toggle)

- lib/esquema-frasa.ts (frontend) + cotizacion-esquema.service.ts (backend):
  modulos puros espejo, caso dorado M/apartado 5k/N=14 en tests de ambos
- Migracion 20260928120000: 7 columnas nuevas en Cotizacion (esquema,
  saldoFirma, engancheDiferible, escrituracion, etc.); legacy se rellena
  para compatibilidad de reportes (tipoPropuesta=FRASA_2026)
- UI: panel de linea de tiempo (Hoy -> Firma -> Mensualidades) sustituye a
  propuestas/comparadores; PDF y WhatsApp con el esquema unico
- API recalcula server-side; smoke end-to-end verificado contra inventario
- 743 tests API + 128 cotizador en verde
This commit is contained in:
2026-09-28 13:00:22 +00:00
parent 23d288d0aa
commit 61d1b84fc3
23 changed files with 1160 additions and 1051 deletions

View File

@@ -0,0 +1,14 @@
-- Esquema de cotización único FRASA 2026 (aprobado por el cliente el 28 sep 2026):
-- apartado libre + enganche de firma 2.5% + enganche 7.5% diferible +
-- escrituración 5.5% (a la firma o diferida con el enganche). Las columnas
-- legacy (tipoPropuesta, descuento, precioFinal, enganche, mensualidad,
-- pagoFinal) se siguen llenando para compatibilidad de reportes.
-- Patrón manual: sqlite3 + _prisma_migrations. NUNCA migrate dev.
ALTER TABLE "Cotizacion" ADD COLUMN "esquema" TEXT NOT NULL DEFAULT 'FRASA_2026';
ALTER TABLE "Cotizacion" ADD COLUMN "saldoFirma" REAL;
ALTER TABLE "Cotizacion" ADD COLUMN "pctEngancheFirma" REAL;
ALTER TABLE "Cotizacion" ADD COLUMN "engancheDiferible" REAL;
ALTER TABLE "Cotizacion" ADD COLUMN "pctEscrituracion" REAL;
ALTER TABLE "Cotizacion" ADD COLUMN "escrituracionDiferida" BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE "Cotizacion" ADD COLUMN "escrituracion" REAL;

View File

@@ -21,7 +21,7 @@ model Cotizacion {
clienteNombre String
clienteEmail String?
clienteTelefono String?
tipoPropuesta String // BANCARIO | INFONAVIT | CONTADO | SEMI_CONTADO
tipoPropuesta String // BANCARIO | INFONAVIT | CONTADO | SEMI_CONTADO | FRASA_2026 (esquema único)
acabados Boolean
apartado Float // TODO prod: Decimal en Postgres
descuento Float // fracción (0.02 = 2%)
@@ -31,6 +31,16 @@ model Cotizacion {
numMensualidades Int
mensualidad Float? // null => N/A (Contado)
pagoFinal Float
// Esquema único FRASA 2026 (apartado + firma 2.5% + enganche 7.5% +
// escrituración 5.5%). Las filas legacy tienen esquema='FRASA_2026' por el
// DEFAULT pero saldoFirma/engancheDiferible/escrituracion null.
esquema String @default("FRASA_2026")
saldoFirma Float? // lo que se paga a la firma por el enganche de firma (>= 0)
pctEngancheFirma Float? // 0.025 (constante del esquema; se persiste por si cambia)
engancheDiferible Float? // enganche del 7.5%, neto del excedente del apartado
pctEscrituracion Float? // 0.055
escrituracionDiferida Boolean @default(false)
escrituracion Float? // gastos de escrituración (5.5% del precio)
mondayItemId String?
createdAt DateTime @default(now())