feat(unidades): pipeline de 10 etapas por unidad + sync desde Reporte_EstatusVenta
- Columna Etapa en Monday Unidades (10 labels oficiales), 155 unidades pobladas - sync-etapas.ts idempotente (--archivo/--dry-run/--semilla) con traspasos Vendido→Escrituración y Escriturado→SAC como actividades (sin retroactivas) - API: etapa en unidades + porEtapa en /api/reportes/resumen - Dashboard: gráfica pipeline por etapa + KPI en notaría; cotizador muestra etapa - 28 cambios aplicados desde Reporte_EstatusVenta (8 avances, 20 nuevas); contradicciones retenidas para revisión humana (documentadas) - Tests: api 168, dashboards 9, cotizador 71
This commit is contained in:
@@ -254,6 +254,12 @@ export class MondayService {
|
||||
return unidades.find((u) => u.codigo === codigo) ?? null
|
||||
}
|
||||
|
||||
/** Item ID de una unidad por código (para escrituras); null si no existe */
|
||||
async itemIdDeUnidad(codigo: string): Promise<string | null> {
|
||||
await this.getUnidades() // asegura cache fresco
|
||||
return this.unidadesCache?.itemIds.get(codigo) ?? null
|
||||
}
|
||||
|
||||
private mapearUnidad(item: ItemMonday, cols: Map<string, ColumnaMeta>): Unidad {
|
||||
const porId = new Map(item.column_values.map((cv) => [cv.id, cv]))
|
||||
const textoDe = (titulo: string): string => {
|
||||
@@ -270,6 +276,9 @@ export class MondayService {
|
||||
const colMeses = cols.get('Meses para firma')
|
||||
const mesesTexto = colMeses ? (porId.get(colMeses.id)?.text ?? '') : ''
|
||||
const mesesNum = Number(mesesTexto)
|
||||
// La columna status "Etapa" (pipeline de 10 etapas) es opcional
|
||||
const colEtapa = cols.get('Etapa')
|
||||
const etapaTexto = colEtapa ? (porId.get(colEtapa.id)?.text ?? '') : ''
|
||||
return {
|
||||
codigo: item.name,
|
||||
modelo: textoDe('Modelo'),
|
||||
@@ -283,6 +292,7 @@ export class MondayService {
|
||||
status: status || 'DISPONIBLE',
|
||||
desarrollo: textoDe('Desarrollo'),
|
||||
mesesParaFirma: mesesTexto !== '' && Number.isFinite(mesesNum) ? mesesNum : null,
|
||||
etapa: etapaTexto !== '' ? etapaTexto : null,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,10 +767,10 @@ export interface DatosMotivoNoCompra {
|
||||
export interface DatosActividad {
|
||||
nombre: string
|
||||
tipoLabel: string // 'Llamada' | 'Reunion' | 'Tarea'
|
||||
responsableId: number // user ID de Monday
|
||||
responsableId?: number // user ID de Monday (se omite si no hay responsable claro)
|
||||
fecha: string // 'YYYY-MM-DD'
|
||||
estadoLabel: string // 'Abierto' | 'Listo'
|
||||
leadItemId: string // item del tablero Leads relacionado
|
||||
leadItemId?: string // item del tablero Leads relacionado (se omite si no aplica)
|
||||
}
|
||||
|
||||
/** Singleton usado por los controllers (los tests instancian el suyo) */
|
||||
|
||||
Reference in New Issue
Block a user