import { ForwardJobData, IndexJobData } from '@tower/types'; import { createLogger } from '@tower/logger'; const logger = createLogger('approve-message'); export interface ApproveMessageResult { forwardJobs: ForwardJobData[]; indexDoc: IndexJobData; } /** * Approve a PENDING message: mark APPROVED in a transaction, create an Approval row, * and return the forward jobs + index document. * Returns null if the message is not in PENDING state or is already approved. */ export async function approveMessage( messageId: string, tenantId: string, adminId: string, prisma: any, targetGroupIds?: string[], ): Promise { const message = await prisma.message.findUnique({ where: { id: messageId }, include: { approval: true, sourceGroup: { include: { syncRoutesFrom: { where: { isActive: true, targetGroup: { isActive: true } }, include: { targetGroup: { select: { platformId: true, isActive: true, accountId: true } } }, }, }, }, }, }); if (!message) return null; if (message.status !== 'PENDING') return null; if (message.approval) return null; let approved = false; await prisma.$transaction(async (tx: any) => { const updated = await tx.message.updateMany({ where: { id: message.id, status: 'PENDING' }, data: { status: 'APPROVED' }, }); if (updated.count === 0) return; approved = true; await tx.approval.create({ data: { tenantId: message.tenantId, messageId: message.id, adminId, decision: 'APPROVED', }, }); }); if (!approved) return null; const forwardJobs: ForwardJobData[] = (message.sourceGroup?.syncRoutesFrom ?? []) .filter((route: any) => route.targetGroup != null) .filter((route: any) => !targetGroupIds || targetGroupIds.includes(route.targetGroupId)) .map((route: any) => ({ tenantId: message.tenantId, messageId: message.id, content: message.content, sourceGroupName: message.sourceGroup.name, senderName: message.senderName ?? undefined, toGroupJid: route.targetGroup.platformId, fromAccountId: route.targetGroup.accountId ?? message.sourceGroup.accountId ?? '', })); const indexDoc: IndexJobData = { tenantId: message.tenantId, messageId: message.id, content: message.content, senderName: message.senderName ?? null, sourceGroupId: message.sourceGroupId, sourceGroupName: message.sourceGroup.name, tags: message.tags ?? [], platform: message.platform, approvedAt: new Date().toISOString(), }; return { forwardJobs, indexDoc }; }