feat(cotizador): apartado editable con mínimo $20,000 + cuota de mantenimiento por desarrollo

- Input de apartado con validación (mínimo 20k), clamp en el motor y bloqueo de PDF si inválido
- El cliente puede apartar con más; solo se recorre del enganche, el total no cambia
- cuotaMantenimiento tipada (number|null) en config por desarrollo; null → PENDIENTE
- Knowledge IA actualizada: apartado mínimo 20k (FAQ + proceso de venta) reindexada
- Tests 61/61 verdes (8 nuevos)
This commit is contained in:
2026-08-24 23:23:57 +00:00
parent 122c4d6102
commit 29c3947313
10 changed files with 122 additions and 19 deletions

View File

@@ -2,9 +2,11 @@ import { useMemo, useState } from 'react'
import type { Unidad, DescuentosPropuestas, ParametrosDesarrollo } from '../types'
import {
APARTADO_DEFAULT,
APARTADO_MINIMO,
calcularPropuestas,
obtenerPrecioLista,
resolverNumMensualidades,
validarApartado,
type PropuestaResultado,
} from '../lib/calculations'
import { DESARROLLO_DEFAULT, descuentosDefault, obtenerDesarrollo } from '../data/desarrollos'
@@ -20,6 +22,10 @@ interface UseCotizacionResult {
setAcabados: (v: boolean) => void
apartado: number
setApartado: (v: number) => void
/** Apartado aplicado a los cálculos (acotado al mínimo cuando la captura es inválida) */
apartadoEfectivo: number
/** Mensaje de error de la captura del apartado; null si es válida */
errorApartado: string | null
descuentos: DescuentosPropuestas
setDescuento: (clave: keyof DescuentosPropuestas, valor: number) => void
precioLista: number
@@ -58,10 +64,14 @@ export function useCotizacion(): UseCotizacionResult {
[unidad, acabados],
)
// Capturas por debajo del mínimo no se usan: los cálculos se acotan
const errorApartado = validarApartado(apartado)
const apartadoEfectivo = Math.max(apartado, APARTADO_MINIMO)
const propuestas = useMemo(() => {
if (!unidad) return []
return calcularPropuestas({ unidad, acabados, apartado, descuentos, desarrollo })
}, [unidad, acabados, apartado, descuentos, desarrollo])
return calcularPropuestas({ unidad, acabados, apartado: apartadoEfectivo, descuentos, desarrollo })
}, [unidad, acabados, apartadoEfectivo, descuentos, desarrollo])
return {
desarrollo,
@@ -73,6 +83,8 @@ export function useCotizacion(): UseCotizacionResult {
setAcabados,
apartado,
setApartado,
apartadoEfectivo,
errorApartado,
descuentos,
setDescuento,
precioLista,