Automatiza destinatarios de assembleias

This commit is contained in:
Tiago
2026-09-30 15:12:39 -03:00
parent 1791e92597
commit 44c04d0b23
3 changed files with 20 additions and 11 deletions
@@ -79,7 +79,7 @@ public final class ClienteHandlers implements HttpHandler {
if(p.length==3&&"condominios".equals(p[0])&&"espacos-comuns".equals(p[2])){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("POST".equals(method)) criarEspaco(ex,c,cond,funcionarioId); else if("GET".equals(method)) listarParam(ex,c,"SELECT * FROM espacos_comuns WHERE condominio_id=? ORDER BY nome",cond,"espacos"); else HttpResponses.methodNotAllowed(ex); return; }
if(p.length==4&&"condominios".equals(p[0])&&"espacos-comuns".equals(p[2])&&"PUT".equals(method)){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} atualizarEspaco(ex,c,cond,id(p[3]),funcionarioId); return; }
if(p.length==3&&"condominios".equals(p[0])&&"assembleias".equals(p[2])){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("POST".equals(method)) criarAssembleia(ex,c,empresaId,cond,funcionarioId); else if("GET".equals(method)) listarParam(ex,c,"SELECT * FROM assembleias WHERE condominio_id=? ORDER BY data_hora DESC",cond,"assembleias"); else HttpResponses.methodNotAllowed(ex); return; }
if(p.length==4&&"condominios".equals(p[0])&&"assembleias".equals(p[2])&&"PUT".equals(method)){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} atualizarAssembleia(ex,c,cond,id(p[3]),funcionarioId); return; }
if(p.length==4&&"condominios".equals(p[0])&&"assembleias".equals(p[2])&&"PUT".equals(method)){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} atualizarAssembleia(ex,c,empresaId,cond,id(p[3]),funcionarioId); return; }
if(p.length==3&&"condominios".equals(p[0])&&"documentos".equals(p[2])){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("POST".equals(method)) uploadDocumento(ex,c,empresaId,cond,funcionarioId); else if("GET".equals(method)) listarParam(ex,c,"SELECT * FROM documentos WHERE condominio_id=? ORDER BY criado_em DESC",cond,"documentos"); else HttpResponses.methodNotAllowed(ex); return; }
if(p.length==3&&"documentos".equals(p[0])&&"download".equals(p[2])&&"GET".equals(method)){ downloadDocumento(ex,c,id(p[1])); return; }
HttpResponses.json(ex,404,Map.of("erro","endpoint_nao_encontrado"));
@@ -129,7 +129,7 @@ public final class ClienteHandlers implements HttpHandler {
HttpResponses.json(ex,201,Map.of("assembleia",one(c,"SELECT * FROM assembleias WHERE id=?",Arrays.asList(id)),"envio",envio));
}
private Map<String,Object> criarAvisosAssembleia(Connection c,long emp,long cond,long assembleia,long fid,Map<String,String>b,List<Destinatario>dests)throws Exception{
List<Destinatario> destinatarios=dests.isEmpty()?destinatariosPadraoAssembleia(c,cond):dests;
List<Destinatario> destinatarios=dests.isEmpty()?destinatariosPadraoAssembleia(c,emp,cond):dests;
int total=destinatarios.size();
if(total==0)return Map.of("enviados",0,"falhas",0,"mensagem","Nenhum destinatario vinculado ao condominio.");
if(!funcionalidadeAtiva(emp,"whatsapp_envio"))return Map.of("enviados",0,"falhas",1,"mensagem","WhatsApp nao liberado para esta empresa.");
@@ -141,12 +141,19 @@ public final class ClienteHandlers implements HttpHandler {
avisos.add(criarAvisoAutomaticoAssembleia(c,cond,assembleia,fid,b,destinatarios,"Lembrete de assembleia","Lembrete: a assembleia acontece hoje.",data));
return Map.of("aviso_ids",avisos,"destinatarios",total,"status","enfileirado");
}
private List<Destinatario> destinatariosPadraoAssembleia(Connection c,long cond)throws SQLException{
private List<Destinatario> destinatariosPadraoAssembleia(Connection c,long emp,long cond)throws SQLException{
List<Destinatario> out=new ArrayList<>();
for(Map<String,Object> row:rows(c,"SELECT contato_id FROM contato_condominio WHERE condominio_id=? AND status=?",Arrays.asList(cond,"ativo")))out.add(new Destinatario("contato",((Number)row.get("contato_id")).longValue()));
for(Map<String,Object> row:rows(c,"SELECT funcionario_id FROM funcionario_condominio WHERE condominio_id=?",Arrays.asList(cond)))out.add(new Destinatario("funcionario",((Number)row.get("funcionario_id")).longValue()));
Set<String> vistos=new HashSet<>();
for(Map<String,Object> row:rows(c,"SELECT contato_id FROM contato_condominio WHERE condominio_id=? AND status=? AND tipo IN ('sindico','subsindico','conselheiro')",Arrays.asList(cond,"ativo")))addDestinatario(out,vistos,"contato",((Number)row.get("contato_id")).longValue());
try(Connection m=masterDs.getMasterConnection();PreparedStatement ps=m.prepareStatement("SELECT id FROM funcionarios WHERE empresa_id=? AND cargo='admin_empresa' AND status='ativo'")){
ps.setLong(1,emp);
try(ResultSet rs=ps.executeQuery()){while(rs.next())addDestinatario(out,vistos,"funcionario",rs.getLong(1));}
}
for(Map<String,Object> row:rows(c,"SELECT funcionario_id FROM funcionario_condominio WHERE condominio_id=?",Arrays.asList(cond)))addDestinatario(out,vistos,"funcionario",((Number)row.get("funcionario_id")).longValue());
for(Map<String,Object> row:rows(c,"SELECT id FROM destinatarios_extra WHERE status='ativo'",Arrays.asList()))addDestinatario(out,vistos,"extra",((Number)row.get("id")).longValue());
return out;
}
private void addDestinatario(List<Destinatario> out,Set<String> vistos,String tipo,long id){if(vistos.add(tipo+":"+id))out.add(new Destinatario(tipo,id));}
private long criarAvisoAutomaticoAssembleia(Connection c,long cond,long assembleia,long fid,Map<String,String>b,List<Destinatario>dests,String titulo,String intro,Timestamp envio)throws SQLException{
Timestamp agora=Timestamp.valueOf(LocalDateTime.now(java.time.ZoneId.of("America/Sao_Paulo")));
Timestamp agendado=envio!=null&&envio.before(agora)?agora:envio;
@@ -163,8 +170,8 @@ public final class ClienteHandlers implements HttpHandler {
if(b.get("pauta")!=null&&!b.get("pauta").isBlank())mensagem.append("\nPauta: ").append(b.get("pauta"));
return mensagem.toString();
}
private void atualizarAssembleia(HttpExchange ex,Connection c,long cond,long aid,long fid)throws Exception{Map<String,String>b=body(ex); Map<String,Object> old=one(c,"SELECT * FROM assembleias WHERE id=? AND condominio_id=?",Arrays.asList(aid,cond)); if(old==null){HttpResponses.json(ex,404,Map.of("erro","assembleia_nao_encontrada"));return;} c.setAutoCommit(false);try{try(PreparedStatement ps=c.prepareStatement("UPDATE assembleias SET tipo=COALESCE(?,tipo), data_hora=COALESCE(?,data_hora), local=COALESCE(?,local), pauta=COALESCE(?,pauta), status=COALESCE(?,status) WHERE id=? AND condominio_id=?")){ps.setString(1,b.get("tipo")); if(b.get("data_hora")==null)ps.setNull(2,Types.TIMESTAMP);else ps.setTimestamp(2,ts(b.get("data_hora"))); ps.setString(3,b.get("local"));ps.setString(4,b.get("pauta"));ps.setString(5,b.get("status"));ps.setLong(6,aid);ps.setLong(7,cond);ps.executeUpdate();} if("cancelada".equalsIgnoreCase(b.get("status"))&&!"cancelada".equalsIgnoreCase(str(old.get("status"))))criarAvisoCancelamentoAssembleia(c,cond,aid,fid,old); audit(c,fid,"update","assembleias",aid,old,b); c.commit();HttpResponses.json(ex,200,Map.of("assembleia",one(c,"SELECT * FROM assembleias WHERE id=?",Arrays.asList(aid))));}catch(Exception err){c.rollback();throw err;}finally{c.setAutoCommit(true);}}
private void criarAvisoCancelamentoAssembleia(Connection c,long cond,long aid,long fid,Map<String,Object>old)throws SQLException{
private void atualizarAssembleia(HttpExchange ex,Connection c,long emp,long cond,long aid,long fid)throws Exception{Map<String,String>b=body(ex); Map<String,Object> old=one(c,"SELECT * FROM assembleias WHERE id=? AND condominio_id=?",Arrays.asList(aid,cond)); if(old==null){HttpResponses.json(ex,404,Map.of("erro","assembleia_nao_encontrada"));return;} c.setAutoCommit(false);try{try(PreparedStatement ps=c.prepareStatement("UPDATE assembleias SET tipo=COALESCE(?,tipo), data_hora=COALESCE(?,data_hora), local=COALESCE(?,local), pauta=COALESCE(?,pauta), status=COALESCE(?,status) WHERE id=? AND condominio_id=?")){ps.setString(1,b.get("tipo")); if(b.get("data_hora")==null)ps.setNull(2,Types.TIMESTAMP);else ps.setTimestamp(2,ts(b.get("data_hora"))); ps.setString(3,b.get("local"));ps.setString(4,b.get("pauta"));ps.setString(5,b.get("status"));ps.setLong(6,aid);ps.setLong(7,cond);ps.executeUpdate();} if("cancelada".equalsIgnoreCase(b.get("status"))&&!"cancelada".equalsIgnoreCase(str(old.get("status"))))criarAvisoCancelamentoAssembleia(c,emp,cond,aid,fid,old); audit(c,fid,"update","assembleias",aid,old,b); c.commit();HttpResponses.json(ex,200,Map.of("assembleia",one(c,"SELECT * FROM assembleias WHERE id=?",Arrays.asList(aid))));}catch(Exception err){c.rollback();throw err;}finally{c.setAutoCommit(true);}}
private void criarAvisoCancelamentoAssembleia(Connection c,long emp,long cond,long aid,long fid,Map<String,Object>old)throws SQLException{
List<Map<String,Object>> avisos=rows(c,"SELECT id FROM avisos WHERE assembleia_id=?",Arrays.asList(aid));
Set<String> vistos=new HashSet<>();
List<Destinatario>dests=new ArrayList<>();
@@ -174,7 +181,11 @@ public final class ClienteHandlers implements HttpHandler {
if(vistos.add(key))dests.add(new Destinatario(tipo,id));
}
}
if(dests.isEmpty())dests=destinatariosPadraoAssembleia(c,cond);
if(dests.isEmpty()){
Map<String,Object> a=one(c,"SELECT condominio_id FROM assembleias WHERE id=?",Arrays.asList(aid));
long cid=a!=null&&a.get("condominio_id")!=null?((Number)a.get("condominio_id")).longValue():cond;
dests=destinatariosPadraoAssembleia(c,emp,cid);
}
try(PreparedStatement ps=c.prepareStatement("UPDATE avisos SET status_envio='cancelado' WHERE assembleia_id=? AND status_envio IN ('nao_enviado','agendado','falhou')")){ps.setLong(1,aid);ps.executeUpdate();}
try(PreparedStatement ps=c.prepareStatement("UPDATE fila_envio SET status='ignorado', ultimo_erro='Assembleia cancelada', locked_at=NULL, atualizado_em=now() WHERE tipo='aviso' AND referencia_id IN (SELECT id FROM avisos WHERE assembleia_id=?) AND status IN ('pendente','processando','falhou')")){ps.setLong(1,aid);ps.executeUpdate();}
Map<String,String>b=new HashMap<>();b.put("data_hora",String.valueOf(old.get("data_hora")));b.put("local",str(old.get("local")));b.put("pauta",str(old.get("pauta")));