// BUG REAL (missao "correcao final", secao 5): ACTIONABLE_NOW tinha um rotulo fixo aqui // ("Validar e executar") que sempre vencia o next_action de verdade da IA -- por isso TODA // mensagem real mostrava a mesma frase generica pra praticamente todo chamado acionavel, // mesmo com a IA ja tendo gerado (e validado como nao-generica, ver logic/classification.js) // um next_action especifico como "Realizar inventario das maquinas". Removido daqui: agora // ACTIONABLE_NOW cai no fallback abaixo, que usa o next_action real (truncado). // UNASSIGNED_ACTIONABLE continua com rotulo fixo de proposito -- pra esse caso "atribuir // tecnico" E a acao real, independente do que o next_action interno da IA descreva. const ACTION_LABELS = { UNASSIGNED_ACTIONABLE: 'Atribuir técnico', WAITING_APPROVAL: 'Cobrar aprovação', INSUFFICIENT_CONTEXT: 'Completar informação', }; function shortActionLabel(aiClassification) { if (aiClassification.is_fallback) return 'Revisar chamado'; const fromMap = ACTION_LABELS[aiClassification.classification]; if (fromMap) return fromMap; const raw = String(aiClassification.next_action || 'Revisar chamado').trim(); return raw.length > 40 ? `${raw.slice(0, 37)}...` : raw; } function tituloCurto(texto) { const limpo = String(texto || 'Sem titulo').replace(/\s+/g, ' ').trim(); return limpo.length > 60 ? `${limpo.slice(0, 57)}...` : limpo; } function signalLine(ticket) { const parts = []; parts.push(ticket.sem_tecnico ? 'SEM TÉCNICO' : ticket.tecnico_atribuido); if (ticket.sla_vencido) parts.push('SLA vencido'); parts.push(`parado ${ticket.dias_sem_interacao}d`); return parts.join(' • '); } function buildTopMessage(selected, dateStr, config) { if (!selected.length) { return `@time Coordenador GLPI - ${dateStr}\n\nNenhum chamado acionável encontrado hoje.`; } const header = `@time ${selected.length} chamados para atenção hoje — ${dateStr}`; const blocks = selected.map((item, index) => { const t = item.ticket; const linhasDoBloco = [ `${index + 1}. #${t.id} • ${tituloCurto(t.titulo)}`, signalLine(t), `→ ${shortActionLabel(item.aiClassification)}`, t.link_glpi, ]; return linhasDoBloco.join('\n'); }); const partesDaMensagem = [header, ...blocks]; return partesDaMensagem.join('\n\n'); } function buildCoordinationDigest(changedBlocked, dateStr) { if (!changedBlocked.length) return null; const lines = changedBlocked.map((item) => `#${item.ticket.id} • ${(item.aiClassification && item.aiClassification.reason) || item.exclusionReason}`); const partesDoDigest = [`Coordenação — bloqueios novos/alterados — ${dateStr}`, '', ...lines]; return partesDoDigest.join('\n'); } module.exports = { shortActionLabel, tituloCurto, signalLine, buildTopMessage, buildCoordinationDigest };