/** * Temporal Activities — operações com efeitos colaterais (banco, APIs, I/O). * Activities são executadas pelo Worker e podem ser re-tentadas automaticamente. */ import { prisma } from '../database/prisma' import { logger } from '../../config/logger' // ─── Conflito de Agenda: liberar slot após timeout ──────────────────────────── export async function liberarSlotAgenda(input: { solicitanteId: string tituloSlot: string chatIdSolicitante: string }): Promise { logger.info(input, '[Temporal] Slot liberado por timeout — notificando solicitante') // Aqui você envia mensagem via WhatsApp avisando o solicitante // Implementação real acoplada ao WhatsAppConnectionManager via NATS // Por ora, marca no banco como disponível await prisma.protocol.updateMany({ where: { contactId: input.solicitanteId, status: 'WAITING_CLIENT', }, data: { status: 'OPEN' }, }) } export async function notificarConflito(input: { chatIdB: string solicitanteNome: string tituloSlot: string }): Promise { logger.info(input, '[Temporal] Notificando pessoa B sobre solicitação de slot') // Dispara mensagem via NATS → WhatsApp handler } // ─── Gestão de Reputação ────────────────────────────────────────────────────── export async function decrementarScore(input: { contactId: string motivo: string pontos: number }): Promise<{ novoScore: number; restrito: boolean }> { const contact = await prisma.contact.findUnique({ where: { id: input.contactId }, }) if (!contact) throw new Error(`Contato ${input.contactId} não encontrado`) const novoScore = Math.max(0, contact.scoreReputacao - input.pontos) const restrito = novoScore <= 20 await prisma.contact.update({ where: { id: input.contactId }, data: { scoreReputacao: novoScore, flagRestricao: restrito, }, }) logger.info({ contactId: input.contactId, novoScore, restrito, motivo: input.motivo }, '[Temporal] Score de reputação atualizado') return { novoScore, restrito } } export async function bloquearAgendamentosAutomaticos(input: { contactId: string }): Promise { await prisma.contact.update({ where: { id: input.contactId }, data: { flagRestricao: true }, }) logger.warn({ contactId: input.contactId }, '[Temporal] Contato marcado como RESTRITO — agendamentos automáticos bloqueados') } export async function buscarScoreContato(contactId: string): Promise<{ score: number restrito: boolean }> { const c = await prisma.contact.findUnique({ where: { id: contactId }, select: { scoreReputacao: true, flagRestricao: true }, }) return { score: c?.scoreReputacao ?? 100, restrito: c?.flagRestricao ?? false } }