feat(pendientes): cotizador (mensualidades, bloqueo de unidad, totales, numMensualidades), cobranza (recibos, atrasos, mora configurable, recordatorios), soporte (adjuntos, filtros, estados), clientes maestro (catalogos reales), contactos (ficha y duplicados) y permisos de captura por rol
This commit is contained in:
@@ -80,6 +80,9 @@ export function construirMiTablero(
|
||||
origen: string | null
|
||||
desarrollo: string | null
|
||||
createdAt: Date
|
||||
/** Necesarios para las ventas cerradas del mes (fecha del cambio y precio) */
|
||||
updatedAt?: Date
|
||||
datosJson?: string | null
|
||||
}[],
|
||||
cotizaciones: {
|
||||
precioFinal: number
|
||||
@@ -130,13 +133,35 @@ export function construirMiTablero(
|
||||
const descartados = capturas.filter((c) => c.etapa.toUpperCase() === 'DESCARTADO').length
|
||||
|
||||
// -- Ventas del mes --
|
||||
// Antes sumaba COTIZACIONES (un inmueble recotizado contaba varias veces y una
|
||||
// cotización no es una venta). Ahora cuenta ventas cerradas del mes: apartados
|
||||
// con firma de cliente o posteriores (Venta, Escriturado, Titulado), sin
|
||||
// repetir la misma unidad.
|
||||
const inicioMes = new Date(hoy.getFullYear(), hoy.getMonth(), 1)
|
||||
const cotizacionesMes = cotizaciones.filter(
|
||||
(ct) => ct.createdAt >= inicioMes,
|
||||
const esVentaCerrada = (etapa: string): boolean => {
|
||||
const e = etapa.toUpperCase()
|
||||
return (
|
||||
e.includes('FIRMA') || e.includes('VENTA') || e.includes('ESCRITURADO') || e.includes('TITULADO')
|
||||
) && !e.includes('CANCEL')
|
||||
}
|
||||
const ventasDelMes = capturas.filter(
|
||||
(c) => c.board === 'APARTADO' && esVentaCerrada(c.etapa) && (c.updatedAt ?? c.createdAt) >= inicioMes,
|
||||
)
|
||||
const unidadesVendidas = new Map<string, number>()
|
||||
for (const v of ventasDelMes) {
|
||||
let monto = 0
|
||||
try {
|
||||
const datos = JSON.parse(v.datosJson ?? '{}') as Record<string, unknown>
|
||||
const precio = Number(datos['precioFinal'] ?? datos['precioVenta'] ?? 0)
|
||||
monto = Number.isFinite(precio) ? precio : 0
|
||||
} catch {
|
||||
monto = 0
|
||||
}
|
||||
unidadesVendidas.set(v.leadId, monto)
|
||||
}
|
||||
const ventasMes = {
|
||||
monto: Math.round(cotizacionesMes.reduce((acc, ct) => acc + ct.precioFinal, 0) * 100) / 100,
|
||||
unidades: cotizacionesMes.length,
|
||||
monto: Math.round([...unidadesVendidas.values()].reduce((a, b) => a + b, 0) * 100) / 100,
|
||||
unidades: unidadesVendidas.size,
|
||||
}
|
||||
|
||||
// -- Por origen --
|
||||
@@ -212,6 +237,8 @@ export async function obtenerMiTablero(usuarioId: string): Promise<MiTablero> {
|
||||
origen: true,
|
||||
desarrollo: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
datosJson: true,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user