feat: docs en apartados, enganche seleccionable y prefill de clientes
- Mis apartados (Mi día): botón Documentos con precarga del expediente — captura del cotizador y captura de pago apartado (obligatorios) más documentos generales; los archivos se guardan en el cliente ligado al apartado (se crea la ficha mínima si no existe). Endpoints GET/POST /apartados/:id/documentos (multipart, 10 MB, pdf/jpg/png) - Cotizador: se oculta el editor de descuento (usan los % del Excel); enganche seleccionable con mínimo 2.5% del valor de la propiedad, solo en esquemas con crédito (bancario/Infonavit); mensualidades se recalculan con el enganche elegido y nunca quedan en negativo - Cotizador: buscador de cliente en Monday (lead u oportunidad) que prellena nombre/contacto/desarrollo y vincula la cotización a la oportunidad al guardar - Alta Afluencia: buscador que jala nombre, contacto, origen, desarrollo y modelo desde leads y oportunidades existentes - buscarLeads devuelve desarrollo y modelo de interés - Landing: el módulo Clientes vuelve a llamarse Cobranza - Tests: 456 API + 94 cotizador + 14 mi-dia + 116 alta-clientes, verde
This commit is contained in:
@@ -203,14 +203,25 @@ function calcularPropuestaConfig(
|
||||
apartado: number,
|
||||
descuento: number,
|
||||
n: number | null,
|
||||
enganchePct: number | null = null,
|
||||
): PropuestaResultado {
|
||||
const { montoDescuento, precioFinal } = baseComun(precioLista, descuento)
|
||||
|
||||
// % de enganche efectivo: el override del asesor (mínimo 2.5%) solo aplica a
|
||||
// esquemas con crédito (bancario/Infonavit: 2.5–5%); Contado (90%) y
|
||||
// Semi Contado (50%) son estructuras fijas del Excel
|
||||
const aplicaOverride =
|
||||
enganchePct !== null &&
|
||||
cfg.modoMensualidades !== 'ninguna' &&
|
||||
cfg.pctEnganche > 0 &&
|
||||
cfg.pctEnganche <= 0.05
|
||||
const pctEnganche = aplicaOverride ? Math.max(0.025, enganchePct) : cfg.pctEnganche
|
||||
|
||||
const baseEnganche = cfg.engancheBase === 'lista' ? precioLista : precioFinal
|
||||
const enganche =
|
||||
cfg.engancheCeroSinApartado && cfg.pctEnganche === 0
|
||||
cfg.engancheCeroSinApartado && pctEnganche === 0
|
||||
? 0
|
||||
: cfg.pctEnganche * baseEnganche - apartado
|
||||
: pctEnganche * baseEnganche - apartado
|
||||
|
||||
const basePagoFinal = cfg.pagoFinalBase === 'lista' ? precioLista : precioFinal
|
||||
const pagoFinal = cfg.pctPagoFinal * basePagoFinal
|
||||
@@ -231,9 +242,11 @@ function calcularPropuestaConfig(
|
||||
mensualidadesTotal = precioLista - pagoFinal - apartado - enganche
|
||||
break
|
||||
case 'porcentaje':
|
||||
mensualidadesTotal = precioFinal * (1 - cfg.pctEnganche - cfg.pctPagoFinal)
|
||||
mensualidadesTotal = precioFinal * (1 - pctEnganche - cfg.pctPagoFinal)
|
||||
break
|
||||
}
|
||||
// Con enganche alto el remanente puede quedar en negativo: se acota a 0
|
||||
mensualidadesTotal = Math.max(0, mensualidadesTotal)
|
||||
mensualidad = mensualidadesTotal / n
|
||||
}
|
||||
}
|
||||
@@ -306,6 +319,8 @@ export type TipoPropuestaApi = keyof typeof TIPO_PROPUESTA_API
|
||||
* Calcula UNA propuesta (la elegida por el cliente) para persistir/cotizar,
|
||||
* con los parámetros del desarrollo de la unidad.
|
||||
* `descuento` opcional (fracción); si no viene, usa el default de la propuesta.
|
||||
* `enganchePct` opcional (fracción, mínimo 0.025); solo aplica a esquemas con
|
||||
* crédito (bancario/Infonavit); Contado y Semi Contado usan su % fijo.
|
||||
*/
|
||||
export function calcularPropuesta(
|
||||
unidad: UnidadCotizable,
|
||||
@@ -313,6 +328,7 @@ export function calcularPropuesta(
|
||||
acabados: boolean,
|
||||
apartado: number = APARTADO_DEFAULT,
|
||||
descuento?: number,
|
||||
enganchePct?: number,
|
||||
): PropuestaResultado {
|
||||
const params = obtenerDesarrollo(unidad.desarrollo)
|
||||
const tipoInterno = TIPO_PROPUESTA_API[tipo]
|
||||
@@ -323,5 +339,5 @@ export function calcularPropuesta(
|
||||
const precioLista = obtenerPrecioLista(unidad, acabados)
|
||||
const n = resolverNumMensualidades(unidad, params)
|
||||
const d = descuento ?? cfg.descuentoDefault
|
||||
return calcularPropuestaConfig(cfg, precioLista, apartado, d, n)
|
||||
return calcularPropuestaConfig(cfg, precioLista, apartado, d, n, enganchePct ?? null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user