adição de agendamento de conversa
This commit is contained in:
@@ -1569,6 +1569,146 @@ class ChatController {
|
||||
return texto; // fallback: retorna sem substituir
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== AGENDAMENTOS ====================
|
||||
|
||||
/**
|
||||
* Agenda retorno para uma conversa.
|
||||
* POST /api/:alias/conversations/:id/schedule
|
||||
*/
|
||||
static async scheduleConversation(req, res) {
|
||||
try {
|
||||
const { alias, id } = req.params;
|
||||
const { data, hora, nota } = req.body;
|
||||
|
||||
if (!data) return res.status(400).json({ success: false, error: 'Data é obrigatória.' });
|
||||
|
||||
const chk = await ChatController.checarConversaEmpresa(alias, id, req);
|
||||
if (chk.status) return res.status(chk.status).json({ success: false, error: 'Conversa não encontrada ou sem permissão.' });
|
||||
|
||||
const newId = await db.nextId(alias, 'GEN_CHATC2_AGENDAMENTOS');
|
||||
await db.execute(alias, `
|
||||
INSERT INTO CHATC2_CONVERSAS_AGENDAMENTOS (CAG_CODIGO_ID, CAG_CONVERSA_ID, CAG_EMPRESA_ID, CAG_DATA, CAG_HORA, CAG_NOTA, CAG_USUARIO_ID)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`, [newId, id, chk.empresaId, data, hora || null, nota || null, req.user?.id]);
|
||||
|
||||
res.json({ success: true, data: { id: newId } });
|
||||
} catch (err) { res.status(500).json({ success: false, error: err.message }); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista agendamentos de uma data (ou hoje).
|
||||
* GET /api/:alias/schedules?data=2026-12-25&empresaId=
|
||||
*/
|
||||
static async listSchedules(req, res) {
|
||||
try {
|
||||
const { alias } = req.params;
|
||||
const empresaId = parseInt(req.query.empresaId) || req.user?.empresas?.[0];
|
||||
const data = req.query.data || new Date().toISOString().split('T')[0];
|
||||
|
||||
if (!req.user?.empresas?.some(e => Number(e) === Number(empresaId))) {
|
||||
return res.status(403).json({ success: false, error: 'Sem permissão.' });
|
||||
}
|
||||
|
||||
const result = await db.query(alias, `
|
||||
SELECT a.*, c.CON_NUMERO, c.CON_NOME_CONTATO, c.CON_CLIENTE_ID
|
||||
FROM CHATC2_CONVERSAS_AGENDAMENTOS a
|
||||
JOIN CHATC2_CONVERSAS c ON c.CON_CODIGO_ID = a.CAG_CONVERSA_ID
|
||||
WHERE a.CAG_EMPRESA_ID = ? AND a.CAG_DATA = ? AND a.CAG_STATUS = 'P'
|
||||
ORDER BY a.CAG_HORA NULLS LAST, a.CAG_DT_CRIACAO
|
||||
`, [empresaId, data]);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result.map(r => ({
|
||||
id: r.CAG_CODIGO_ID,
|
||||
conversaId: r.CAG_CONVERSA_ID,
|
||||
data: r.CAG_DATA,
|
||||
hora: r.CAG_HORA,
|
||||
nota: (r.CAG_NOTA || '').trim(),
|
||||
numero: (r.CON_NUMERO || '').trim(),
|
||||
nomeContato: (r.CON_NOME_CONTATO || '').trim(),
|
||||
clienteId: r.CON_CLIENTE_ID,
|
||||
status: (r.CAG_STATUS || '').trim(),
|
||||
})),
|
||||
count: result.length,
|
||||
});
|
||||
} catch (err) { res.status(500).json({ success: false, error: err.message }); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria nova conversa a partir de um agendamento.
|
||||
* POST /api/:alias/schedules/:id/reopen
|
||||
* Retorna a nova conversa e o texto sugerido — NÃO envia automaticamente.
|
||||
*/
|
||||
static async reopenSchedule(req, res) {
|
||||
try {
|
||||
const { alias, id } = req.params;
|
||||
|
||||
const ag = await db.query(alias,
|
||||
`SELECT a.*, c.CON_NUMERO, c.CON_NOME_CONTATO, c.CON_CLIENTE_ID, c.CON_EMPRESA_ID, c.CON_INSTANCIA_ID
|
||||
FROM CHATC2_CONVERSAS_AGENDAMENTOS a
|
||||
JOIN CHATC2_CONVERSAS c ON c.CON_CODIGO_ID = a.CAG_CONVERSA_ID
|
||||
WHERE a.CAG_CODIGO_ID = ?`, [id]);
|
||||
if (ag.length === 0) return res.status(404).json({ success: false, error: 'Agendamento não encontrado.' });
|
||||
|
||||
const a = ag[0];
|
||||
const numeroLimpo = (a.CON_NUMERO || '').replace(/\D/g, '').substring(0, 15);
|
||||
const nomeContato = (a.CON_NOME_CONTATO || a.CON_NUMERO || '').trim();
|
||||
const nota = (a.CAG_NOTA || '').trim();
|
||||
let clienteId = a.CON_CLIENTE_ID || null;
|
||||
|
||||
// Se não tem cliente vinculado, busca pelo número
|
||||
if (!clienteId) {
|
||||
const variantes = [numeroLimpo];
|
||||
if (numeroLimpo.startsWith('55')) variantes.push(numeroLimpo.substring(2));
|
||||
variantes.push(numeroLimpo.slice(-8));
|
||||
|
||||
for (const termo of variantes) {
|
||||
const cli = await db.query(alias, `
|
||||
SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES
|
||||
WHERE CLI_EMPRESA_ID = ?
|
||||
AND (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%'
|
||||
OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%'
|
||||
OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%')
|
||||
FETCH FIRST 1 ROWS ONLY
|
||||
`, [a.CAG_EMPRESA_ID, termo, termo, termo]);
|
||||
if (cli.length > 0) { clienteId = cli[0].CLI_CODIGO_ID; break; }
|
||||
}
|
||||
|
||||
if (!clienteId) {
|
||||
for (const termo of variantes) {
|
||||
const dep = await db.query(alias, `
|
||||
SELECT DEPC_CLIENTE_ID FROM DEPENDENTES_CLI
|
||||
WHERE DEPC_EMPRESA_ID = ? AND DEPC_SITUACAO = 'A'
|
||||
AND REPLACE(REPLACE(REPLACE(COALESCE(DEPC_TELEFONE,''),'-',''),'(',''),')','') LIKE '%' || ? || '%'
|
||||
FETCH FIRST 1 ROWS ONLY
|
||||
`, [a.CAG_EMPRESA_ID, termo]);
|
||||
if (dep.length > 0) { clienteId = dep[0].DEPC_CLIENTE_ID; break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cria NOVA conversa
|
||||
const newId = await db.nextId(alias, 'GEN_CHATC2_CONVERSAS');
|
||||
await db.execute(alias, `
|
||||
INSERT INTO CHATC2_CONVERSAS (CON_CODIGO_ID, CON_EMPRESA_ID, CON_INSTANCIA_ID, CON_NUMERO,
|
||||
CON_NOME_CONTATO, CON_CLIENTE_ID, CON_STATUS, CON_SITUACAO, CON_PRIMEIRA_MSG, CON_DT_ULTIMA_MSG)
|
||||
VALUES (?, ?, ?, ?, ?, ?, 'A', 'A', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
`, [newId, a.CAG_EMPRESA_ID, a.CON_INSTANCIA_ID, numeroLimpo, nomeContato, clienteId]);
|
||||
|
||||
// Monta texto sugerido (placeholders serão processados no frontend ao enviar)
|
||||
const textoSugerido = nota
|
||||
? '📅 *Retorno agendado*\n' + nota + '\n\nOlá [CLIENTE]! Conforme combinado, estou retornando o contato. Em que posso ajudar?'
|
||||
: '👋 Olá [CLIENTE]! Conforme combinado, estou retornando o contato. Em que posso ajudar?';
|
||||
|
||||
// Marca agendamento como retomado
|
||||
await db.execute(alias,
|
||||
"UPDATE CHATC2_CONVERSAS_AGENDAMENTOS SET CAG_STATUS = 'R' WHERE CAG_CODIGO_ID = ?", [id]);
|
||||
|
||||
res.json({ success: true, conversaId: newId, textoSugerido: textoSugerido });
|
||||
} catch (err) { res.status(500).json({ success: false, error: err.message }); }
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: normaliza número para formato WhatsApp (DDI + 9º dígito)
|
||||
|
||||
Reference in New Issue
Block a user