feat(monday): mover items al grupo correcto al cambiar de estado

Webhook change_column_value en los 5 tableros (Leads, Oportunidades,
Unidades, Apartado, Contactos) + mapeo central estado->grupo: el API
re-consulta el item y lo mueve con move_item_to_group (idempotente).
El funnel mueve la oportunidad de Afluencia al crearla (Monday la crea
en el grupo top del board). Incluye script de backfill one-off
(249 items reubicados) y tests del mapeo y del webhook.
This commit is contained in:
2026-09-03 00:14:18 +00:00
parent 1ab29d765e
commit 89fcd1c579
8 changed files with 568 additions and 8 deletions

View File

@@ -28,6 +28,14 @@ interface ItemConFechas extends ItemMonday {
updated_at: string
}
/** Item de cualquier tablero con el grupo donde está (automatización estado → grupo) */
export interface ItemConGrupo {
id: string
name: string
groupId: string
column_values: ColumnValue[]
}
/** Lead del tablero Leads tal como lo consumen las automatizaciones */
export interface LeadMonday {
id: string
@@ -544,6 +552,35 @@ export class MondayService {
)
}
/** ID de una columna por título exacto; null si no existe (lectura tolerante) */
async columnaIdPorTitulo(boardId: string, titulo: string): Promise<string | null> {
const cols = await this.columnasDe(boardId)
return cols.get(titulo)?.id ?? null
}
/** Item de cualquier tablero con su grupo y column_values; null si no existe */
async getItemConGrupo(itemId: string): Promise<ItemConGrupo | null> {
const data = await this.graphql<{ items: (ItemMonday & { group: { id: string } } | null)[] }>(
`query ($ids: [ID!]) {
items(ids: $ids) { id name group { id } column_values { id text value } }
}`,
{ ids: [itemId] },
)
const item = data.items[0]
if (!item) return null
return { id: item.id, name: item.name, groupId: item.group.id, column_values: item.column_values }
}
/** Mueve un item a otro grupo de su mismo tablero */
async moverItemAGrupo(itemId: string, groupId: string): Promise<void> {
await this.graphql<{ move_item_to_group: { id: string } }>(
`mutation ($itemId: ID!, $groupId: String!) {
move_item_to_group(item_id: $itemId, group_id: $groupId) { id }
}`,
{ itemId, groupId },
)
}
/** Nombre de un item por ID (cualquier tablero) */
async obtenerNombreItem(itemId: string): Promise<string> {
const data = await this.graphql<{ items: { name: string }[] }>(