|
|
|
@@ -65,6 +65,8 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
if(p.length==3&&"config".equals(p[0])&&"evolution-instancia".equals(p[1])&&"desconectar".equals(p[2])&&"POST".equals(method)){ desconectarEvolution(ex,empresaId); return; }
|
|
|
|
|
if(p.length==3&&"config".equals(p[0])&&"evolution-instancia".equals(p[1])&&"reconectar".equals(p[2])&&"POST".equals(method)){ reconectarEvolution(ex,empresaId); return; }
|
|
|
|
|
if(p.length==1&&"assembleias-calendario".equals(p[0])&&"GET".equals(method)){ listarAssembleiasCalendario(ex,c,empresaId,cargo,funcionarioId); return; }
|
|
|
|
|
if(p.length==1&&"assembleia-responsaveis".equals(p[0])){ if("GET".equals(method)) listarResponsaveisAssembleia(ex,c); else { if(!adminEmpresa(cargo)){HttpResponses.json(ex,403,Map.of("erro","acesso_restrito","mensagem","Apenas a conta principal da empresa pode gerenciar responsaveis de assembleia."));return;} if("POST".equals(method)) criarResponsavelAssembleia(ex,c,funcionarioId); else HttpResponses.methodNotAllowed(ex); } return; }
|
|
|
|
|
if(p.length==2&&"assembleia-responsaveis".equals(p[0])){ if(!adminEmpresa(cargo)){HttpResponses.json(ex,403,Map.of("erro","acesso_restrito","mensagem","Apenas a conta principal da empresa pode gerenciar responsaveis de assembleia."));return;} long resp=id(p[1]); if("PUT".equals(method)) atualizarResponsavelAssembleia(ex,c,resp,funcionarioId); else if("DELETE".equals(method)) excluirResponsavelAssembleia(ex,c,resp,funcionarioId); else HttpResponses.methodNotAllowed(ex); return; }
|
|
|
|
|
if(p.length==1&&"respostas".equals(p[0])&&"POST".equals(method)){ registrarResposta(ex,c,funcionarioId,null); return; }
|
|
|
|
|
if(p.length==3&&"condominios".equals(p[0])&&"avisos".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)) criarAviso(ex,c,empresaId,cond,funcionarioId); else if("GET".equals(method)) listarAvisos(ex,c,cond); else HttpResponses.methodNotAllowed(ex); return; }
|
|
|
|
|
if(p.length==4&&"condominios".equals(p[0])&&"avisos".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("GET".equals(method)) detalheAviso(ex,c,cond,id(p[3])); else if("DELETE".equals(method)) excluirAviso(ex,c,empresaId,cond,id(p[3]),funcionarioId); else HttpResponses.methodNotAllowed(ex); return; }
|
|
|
|
@@ -115,12 +117,14 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
String raw=rawBody(ex);
|
|
|
|
|
Map<String,String>b=SimpleJson.parseObject(removeArrayField(raw,"destinatarios"));
|
|
|
|
|
List<Destinatario>dests=destinatarios(raw);
|
|
|
|
|
if(raw.contains("\"destinatarios\"")&&dests.isEmpty()){HttpResponses.json(ex,400,Map.of("erro","destinatario_obrigatorio","mensagem","Selecione ao menos um membro para receber as mensagens da assembleia."));return;}
|
|
|
|
|
Timestamp dataHora=ts(req(b,"data_hora"));
|
|
|
|
|
Map<String,Object> conflito=validarAgendaResponsaveisAssembleia(c,dataHora,null);
|
|
|
|
|
if(conflito!=null){HttpResponses.json(ex,409,conflito);return;}
|
|
|
|
|
long id;
|
|
|
|
|
Map<String,Object> envio;
|
|
|
|
|
c.setAutoCommit(false);
|
|
|
|
|
try{
|
|
|
|
|
id=insert(c,"INSERT INTO assembleias (condominio_id,tipo,data_hora,local,pauta) VALUES (?,?,?,?,?)",Arrays.asList(cond,req(b,"tipo"),ts(req(b,"data_hora")),nullable(b.get("local")),nullable(b.get("pauta"))));
|
|
|
|
|
id=insert(c,"INSERT INTO assembleias (condominio_id,tipo,data_hora,local,pauta) VALUES (?,?,?,?,?)",Arrays.asList(cond,req(b,"tipo"),dataHora,nullable(b.get("local")),nullable(b.get("pauta"))));
|
|
|
|
|
audit(c,fid,"create","assembleias",id,null,b);
|
|
|
|
|
envio=criarAvisosAssembleia(c,emp,cond,id,fid,b,dests);
|
|
|
|
|
c.commit();
|
|
|
|
@@ -155,6 +159,7 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
}
|
|
|
|
|
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());
|
|
|
|
|
for(Map<String,Object> row:rows(c,"SELECT id FROM assembleia_responsaveis WHERE status='ativo'",Arrays.asList()))addDestinatario(out,vistos,"assembleia",((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));}
|
|
|
|
@@ -174,7 +179,7 @@ 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 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 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;} Timestamp novaData=b.get("data_hora")==null?null:ts(b.get("data_hora")); if(novaData!=null){Map<String,Object> conflito=validarAgendaResponsaveisAssembleia(c,novaData,aid); if(conflito!=null){HttpResponses.json(ex,409,conflito);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(novaData==null)ps.setNull(2,Types.TIMESTAMP);else ps.setTimestamp(2,novaData); 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<>();
|
|
|
|
@@ -204,6 +209,41 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
private void criarExtra(HttpExchange ex,Connection c,long fid)throws Exception{Map<String,String>b=body(ex);long id=insert(c,"INSERT INTO destinatarios_extra (nome,email,telefone,status) VALUES (?,?,?,'ativo')",Arrays.asList(req(b,"nome"),nullable(b.get("email")),nullable(b.get("telefone"))));audit(c,fid,"create","destinatarios_extra",id,null,b);HttpResponses.json(ex,201,Map.of("extra",one(c,"SELECT * FROM destinatarios_extra WHERE id=?",Arrays.asList(id))));}
|
|
|
|
|
private void atualizarExtra(HttpExchange ex,Connection c,long id,long fid)throws Exception{Map<String,Object> old=one(c,"SELECT * FROM destinatarios_extra WHERE id=?",Arrays.asList(id));if(old==null){HttpResponses.json(ex,404,Map.of("erro","extra_nao_encontrado"));return;}Map<String,String>b=body(ex);try(PreparedStatement ps=c.prepareStatement("UPDATE destinatarios_extra SET nome=COALESCE(?,nome), email=COALESCE(?,email), telefone=COALESCE(?,telefone), status=COALESCE(?,status), atualizado_em=now() WHERE id=?")){ps.setString(1,b.get("nome"));ps.setString(2,b.get("email"));ps.setString(3,b.get("telefone"));ps.setString(4,b.get("status"));ps.setLong(5,id);ps.executeUpdate();}audit(c,fid,"update","destinatarios_extra",id,old,b);HttpResponses.json(ex,200,Map.of("extra",one(c,"SELECT * FROM destinatarios_extra WHERE id=?",Arrays.asList(id))));}
|
|
|
|
|
private void excluirExtra(HttpExchange ex,Connection c,long id,long fid)throws Exception{Map<String,Object> old=one(c,"SELECT * FROM destinatarios_extra WHERE id=?",Arrays.asList(id));if(old==null){HttpResponses.json(ex,404,Map.of("erro","extra_nao_encontrado"));return;}try(PreparedStatement ps=c.prepareStatement("UPDATE destinatarios_extra SET status='excluido', atualizado_em=now() WHERE id=?")){ps.setLong(1,id);ps.executeUpdate();}audit(c,fid,"delete","destinatarios_extra",id,old,Map.of("ok",true));HttpResponses.json(ex,200,Map.of("ok",true));}
|
|
|
|
|
private void listarResponsaveisAssembleia(HttpExchange ex,Connection c)throws Exception{HttpResponses.json(ex,200,Map.of("responsaveis",rows(c,"SELECT * FROM assembleia_responsaveis WHERE status<>'excluido' ORDER BY nome",Arrays.asList())));}
|
|
|
|
|
private void criarResponsavelAssembleia(HttpExchange ex,Connection c,long fid)throws Exception{String raw=rawBody(ex);Map<String,String>b=SimpleJson.parseObject(removeArrayField(raw,"dias_semana"));String dias=diasSemana(raw,b.get("dias_semana"));long id=insert(c,"INSERT INTO assembleia_responsaveis (nome,telefone,email,dias_semana,status) VALUES (?,?,?,?,'ativo')",Arrays.asList(req(b,"nome"),nullable(b.get("telefone")),nullable(b.get("email")),dias));audit(c,fid,"create","assembleia_responsaveis",id,null,b);HttpResponses.json(ex,201,Map.of("responsavel",one(c,"SELECT * FROM assembleia_responsaveis WHERE id=?",Arrays.asList(id))));}
|
|
|
|
|
private void atualizarResponsavelAssembleia(HttpExchange ex,Connection c,long id,long fid)throws Exception{Map<String,Object> old=one(c,"SELECT * FROM assembleia_responsaveis WHERE id=?",Arrays.asList(id));if(old==null){HttpResponses.json(ex,404,Map.of("erro","responsavel_nao_encontrado"));return;}String raw=rawBody(ex);Map<String,String>b=SimpleJson.parseObject(removeArrayField(raw,"dias_semana"));String dias=raw.contains("\"dias_semana\"")?diasSemana(raw,b.get("dias_semana")):null;try(PreparedStatement ps=c.prepareStatement("UPDATE assembleia_responsaveis SET nome=COALESCE(?,nome), telefone=COALESCE(?,telefone), email=COALESCE(?,email), dias_semana=COALESCE(?,dias_semana), status=COALESCE(?,status), atualizado_em=now() WHERE id=?")){ps.setString(1,b.get("nome"));ps.setString(2,b.get("telefone"));ps.setString(3,b.get("email"));ps.setString(4,dias);ps.setString(5,b.get("status"));ps.setLong(6,id);ps.executeUpdate();}audit(c,fid,"update","assembleia_responsaveis",id,old,b);HttpResponses.json(ex,200,Map.of("responsavel",one(c,"SELECT * FROM assembleia_responsaveis WHERE id=?",Arrays.asList(id))));}
|
|
|
|
|
private void excluirResponsavelAssembleia(HttpExchange ex,Connection c,long id,long fid)throws Exception{Map<String,Object> old=one(c,"SELECT * FROM assembleia_responsaveis WHERE id=?",Arrays.asList(id));if(old==null){HttpResponses.json(ex,404,Map.of("erro","responsavel_nao_encontrado"));return;}try(PreparedStatement ps=c.prepareStatement("UPDATE assembleia_responsaveis SET status='excluido', atualizado_em=now() WHERE id=?")){ps.setLong(1,id);ps.executeUpdate();}audit(c,fid,"delete","assembleia_responsaveis",id,old,Map.of("ok",true));HttpResponses.json(ex,200,Map.of("ok",true));}
|
|
|
|
|
private Map<String,Object> validarAgendaResponsaveisAssembleia(Connection c,Timestamp dataHora,Long ignorarAssembleia)throws Exception{
|
|
|
|
|
if(dataHora==null)return null;
|
|
|
|
|
List<Map<String,Object>> responsaveis=rows(c,"SELECT id,nome,dias_semana FROM assembleia_responsaveis WHERE status='ativo' ORDER BY nome",Arrays.asList());
|
|
|
|
|
if(responsaveis.isEmpty())return null;
|
|
|
|
|
int dia=dataHora.toLocalDateTime().getDayOfWeek().getValue()%7;
|
|
|
|
|
List<String> indisponiveis=new ArrayList<>();
|
|
|
|
|
for(Map<String,Object> r:responsaveis){
|
|
|
|
|
Set<String> dias=new HashSet<>(Arrays.asList(str(r.get("dias_semana")).split(",")));
|
|
|
|
|
if(!dias.contains(String.valueOf(dia)))indisponiveis.add(str(r.get("nome")));
|
|
|
|
|
}
|
|
|
|
|
if(!indisponiveis.isEmpty())return Map.of("erro","responsavel_indisponivel","mensagem","Nao e possivel agendar assembleia neste dia da semana para: "+String.join(", ",indisponiveis)+".","responsaveis",indisponiveis);
|
|
|
|
|
String sql="SELECT a.id,a.data_hora,r.nome FROM assembleias a CROSS JOIN assembleia_responsaveis r WHERE r.status='ativo' AND a.status<>'cancelada' AND a.data_hora::date=?::date"+(ignorarAssembleia==null?"":" AND a.id<>?");
|
|
|
|
|
List<Object> params=new ArrayList<>();params.add(dataHora);if(ignorarAssembleia!=null)params.add(ignorarAssembleia);
|
|
|
|
|
List<Map<String,Object>> conflitos=rows(c,sql,params);
|
|
|
|
|
if(!conflitos.isEmpty()){
|
|
|
|
|
List<String> nomes=conflitos.stream().map(x->str(x.get("nome"))).distinct().toList();
|
|
|
|
|
return Map.of("erro","assembleia_duplicada_responsavel","mensagem","Ja existe assembleia agendada neste dia para: "+String.join(", ",nomes)+".","responsaveis",nomes);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
private String diasSemana(String raw,String direto){
|
|
|
|
|
List<String> vals=stringArray(raw,"dias_semana");
|
|
|
|
|
if(vals.isEmpty()&&direto!=null&&!direto.isBlank())vals=Arrays.asList(direto.split(","));
|
|
|
|
|
Set<String> ok=new LinkedHashSet<>();
|
|
|
|
|
for(String v:vals){
|
|
|
|
|
String x=v.trim().replace("\"","");
|
|
|
|
|
if(x.matches("[0-6]"))ok.add(x);
|
|
|
|
|
}
|
|
|
|
|
if(ok.isEmpty())throw new IllegalArgumentException("Selecione ao menos um dia da semana.");
|
|
|
|
|
return String.join(",",ok);
|
|
|
|
|
}
|
|
|
|
|
private void listarPessoasLembrete(HttpExchange ex,long empresaId)throws Exception{try(Connection m=masterDs.getMasterConnection();PreparedStatement ps=m.prepareStatement("SELECT id,nome,email,telefone,cargo,status FROM funcionarios WHERE empresa_id=? AND status='ativo' ORDER BY nome")){ps.setLong(1,empresaId);List<Map<String,Object>> out=new ArrayList<>();try(ResultSet rs=ps.executeQuery()){while(rs.next())out.add(resultMap(rs));}HttpResponses.json(ex,200,Map.of("pessoas",out));}}
|
|
|
|
|
private void criarLembrete(HttpExchange ex,Connection c,long emp,long fid)throws Exception{
|
|
|
|
|
String raw=rawBody(ex);
|
|
|
|
@@ -347,7 +387,7 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
List<Map<String,Object>> out=new ArrayList<>();
|
|
|
|
|
for(Map<String,Object>d:dests){
|
|
|
|
|
String tipo=str(d.get("tipo_destinatario"));long did=((Number)d.get("destinatario_id")).longValue();Map<String,Object> pessoa;
|
|
|
|
|
if("funcionario".equals(tipo))pessoa=funcionario(emp,did);else if("extra".equals(tipo))pessoa=one(c,"SELECT id,nome,email,telefone FROM destinatarios_extra WHERE id=?",Arrays.asList(did));else pessoa=one(c,"SELECT id,nome,email,telefone FROM contatos WHERE id=?",Arrays.asList(did));
|
|
|
|
|
if("funcionario".equals(tipo))pessoa=funcionario(emp,did);else if("extra".equals(tipo))pessoa=one(c,"SELECT id,nome,email,telefone FROM destinatarios_extra WHERE id=?",Arrays.asList(did));else if("assembleia".equals(tipo))pessoa=one(c,"SELECT id,nome,email,telefone FROM assembleia_responsaveis WHERE id=?",Arrays.asList(did));else pessoa=one(c,"SELECT id,nome,email,telefone FROM contatos WHERE id=?",Arrays.asList(did));
|
|
|
|
|
if(pessoa!=null){Map<String,Object> item=new LinkedHashMap<>(pessoa);item.put("tipo",tipo);out.add(item);}
|
|
|
|
|
}
|
|
|
|
|
return out;
|
|
|
|
@@ -357,7 +397,7 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
private void detalheAviso(HttpExchange ex,Connection c,long cond,long aviso)throws Exception{Map<String,Object>a=one(c,"SELECT * FROM avisos WHERE id=? AND condominio_id=?",Arrays.asList(aviso,cond));if(a==null){HttpResponses.json(ex,404,Map.of("erro","aviso_nao_encontrado"));return;}Map<String,Object> resp=new LinkedHashMap<>();resp.put("aviso",a);resp.put("documentos",rows(c,"SELECT ad.*, d.nome_arquivo, d.caminho_armazenamento FROM aviso_documentos ad JOIN documentos d ON d.id=ad.documento_id WHERE ad.aviso_id=?",Arrays.asList(aviso)));resp.put("destinatarios",rows(c,"SELECT * FROM aviso_destinatarios WHERE aviso_id=? ORDER BY tipo_destinatario,destinatario_id",Arrays.asList(aviso)));HttpResponses.json(ex,200,resp);}
|
|
|
|
|
private void reenviarAviso(HttpExchange ex,Connection c,long emp,long cond,long aviso)throws Exception{try(PreparedStatement ps=c.prepareStatement("UPDATE avisos SET status_envio='nao_enviado' WHERE id=? AND condominio_id=?")){ps.setLong(1,aviso);ps.setLong(2,cond);if(ps.executeUpdate()==0){HttpResponses.json(ex,404,Map.of("erro","aviso_nao_encontrado"));return;}}enviarAviso(c,emp,cond,aviso,false);detalheAviso(ex,c,cond,aviso);}
|
|
|
|
|
private void excluirAviso(HttpExchange ex,Connection c,long emp,long cond,long aviso,long fid)throws Exception{Map<String,Object> old=one(c,"SELECT * FROM avisos WHERE id=? AND condominio_id=?",Arrays.asList(aviso,cond));if(old==null){HttpResponses.json(ex,404,Map.of("erro","aviso_nao_encontrado"));return;}c.setAutoCommit(false);try{try(PreparedStatement ps=c.prepareStatement("DELETE FROM aviso_documentos WHERE aviso_id=?")){ps.setLong(1,aviso);ps.executeUpdate();}try(PreparedStatement ps=c.prepareStatement("DELETE FROM aviso_destinatarios WHERE aviso_id=?")){ps.setLong(1,aviso);ps.executeUpdate();}try(PreparedStatement ps=c.prepareStatement("DELETE FROM avisos WHERE id=? AND condominio_id=?")){ps.setLong(1,aviso);ps.setLong(2,cond);ps.executeUpdate();}audit(c,fid,"delete","avisos",aviso,old,Map.of("ok",true));c.commit();try(Connection m=masterDs.getMasterConnection();PreparedStatement ps=m.prepareStatement("DELETE FROM logs_envio_avisos WHERE empresa_id=? AND condominio_id=? AND aviso_id=?")){ps.setLong(1,emp);ps.setLong(2,cond);ps.setLong(3,aviso);ps.executeUpdate();}HttpResponses.json(ex,200,Map.of("ok",true));}catch(Exception err){c.rollback();throw err;}finally{c.setAutoCommit(true);}}
|
|
|
|
|
private void enviarAviso(Connection c,long emp,long cond,long aviso,boolean apenasFalhos)throws Exception{Map<String,Object>a=one(c,"SELECT * FROM avisos WHERE id=? AND condominio_id=?",Arrays.asList(aviso,cond));if(a==null)return;boolean w=Boolean.TRUE.equals(a.get("enviar_whatsapp"));boolean e=Boolean.TRUE.equals(a.get("enviar_email"));Map<String,Object> inst=w?evolutionAprovada(emp):null;Map<String,String> smtp=e?smtpConfig():Map.of();List<Map<String,Object>> dests=rows(c,"SELECT * FROM aviso_destinatarios WHERE aviso_id=?",Arrays.asList(aviso));boolean allOk=true;int tentativas=0;if(dests.isEmpty())allOk=false;for(Map<String,Object>d:dests){String tipo=String.valueOf(d.get("tipo_destinatario"));long did=((Number)d.get("destinatario_id")).longValue();Map<String,Object> contato="funcionario".equals(tipo)?funcionario(emp,did):("extra".equals(tipo)?one(c,"SELECT id,nome,telefone,email FROM destinatarios_extra WHERE id=? AND status='ativo'",Arrays.asList(did)):one(c,"SELECT id,nome,telefone,email FROM contatos WHERE id=?",Arrays.asList(did)));if(contato==null){allOk=false;continue;}String nome=String.valueOf(contato.get("nome"));if(w&&deveTentar(emp,aviso,did,"whatsapp",apenasFalhos)){tentativas++;String tel=telefoneWhatsapp(contato.get("telefone"));try{if(tel.length()<12)throw new IllegalArgumentException("telefone_invalido");String[] parts=String.valueOf(inst.get("instance_token_enc")).split(":",2);String resposta=evolutionApiClient.enviarTexto(str(inst.get("instance_url")),parts[0],parts.length>1?parts[1]:"",tel,msg(a));logEnvio(emp,cond,aviso,did,nome,"whatsapp","enviado",limite(resposta));}catch(Exception err){allOk=false;logEnvio(emp,cond,aviso,did,nome,"whatsapp","falhou",err.getMessage());}}if(e&&deveTentar(emp,aviso,did,"email",apenasFalhos)){tentativas++;String email=str(contato.get("email"));try{if(!email.contains("@"))throw new IllegalArgumentException("email_invalido");emailClient.enviar(smtp,email,str(a.get("titulo")),msg(a));logEnvio(emp,cond,aviso,did,nome,"email","enviado",null);}catch(Exception err){allOk=false;logEnvio(emp,cond,aviso,did,nome,"email","falhou",err.getMessage());}}}if(allOk&&tentativas>0&&reagendarAvisoRecorrente(c,aviso,a))return;try(PreparedStatement ps=c.prepareStatement("UPDATE avisos SET status_envio=?, ultimo_envio=CASE WHEN ? THEN now() ELSE ultimo_envio END WHERE id=?")){boolean ok=allOk&&tentativas>0;ps.setString(1,ok?"enviado":"falhou");ps.setBoolean(2,ok);ps.setLong(3,aviso);ps.executeUpdate();}}
|
|
|
|
|
private void enviarAviso(Connection c,long emp,long cond,long aviso,boolean apenasFalhos)throws Exception{Map<String,Object>a=one(c,"SELECT * FROM avisos WHERE id=? AND condominio_id=?",Arrays.asList(aviso,cond));if(a==null)return;boolean w=Boolean.TRUE.equals(a.get("enviar_whatsapp"));boolean e=Boolean.TRUE.equals(a.get("enviar_email"));Map<String,Object> inst=w?evolutionAprovada(emp):null;Map<String,String> smtp=e?smtpConfig():Map.of();List<Map<String,Object>> dests=rows(c,"SELECT * FROM aviso_destinatarios WHERE aviso_id=?",Arrays.asList(aviso));boolean allOk=true;int tentativas=0;if(dests.isEmpty())allOk=false;for(Map<String,Object>d:dests){String tipo=String.valueOf(d.get("tipo_destinatario"));long did=((Number)d.get("destinatario_id")).longValue();Map<String,Object> contato="funcionario".equals(tipo)?funcionario(emp,did):("extra".equals(tipo)?one(c,"SELECT id,nome,telefone,email FROM destinatarios_extra WHERE id=? AND status='ativo'",Arrays.asList(did)):("assembleia".equals(tipo)?one(c,"SELECT id,nome,telefone,email FROM assembleia_responsaveis WHERE id=? AND status='ativo'",Arrays.asList(did)):one(c,"SELECT id,nome,telefone,email FROM contatos WHERE id=?",Arrays.asList(did))));if(contato==null){allOk=false;continue;}String nome=String.valueOf(contato.get("nome"));if(w&&deveTentar(emp,aviso,did,"whatsapp",apenasFalhos)){tentativas++;String tel=telefoneWhatsapp(contato.get("telefone"));try{if(tel.length()<12)throw new IllegalArgumentException("telefone_invalido");String[] parts=String.valueOf(inst.get("instance_token_enc")).split(":",2);String resposta=evolutionApiClient.enviarTexto(str(inst.get("instance_url")),parts[0],parts.length>1?parts[1]:"",tel,msg(a));logEnvio(emp,cond,aviso,did,nome,"whatsapp","enviado",limite(resposta));}catch(Exception err){allOk=false;logEnvio(emp,cond,aviso,did,nome,"whatsapp","falhou",err.getMessage());}}if(e&&deveTentar(emp,aviso,did,"email",apenasFalhos)){tentativas++;String email=str(contato.get("email"));try{if(!email.contains("@"))throw new IllegalArgumentException("email_invalido");emailClient.enviar(smtp,email,str(a.get("titulo")),msg(a));logEnvio(emp,cond,aviso,did,nome,"email","enviado",null);}catch(Exception err){allOk=false;logEnvio(emp,cond,aviso,did,nome,"email","falhou",err.getMessage());}}}if(allOk&&tentativas>0&&reagendarAvisoRecorrente(c,aviso,a))return;try(PreparedStatement ps=c.prepareStatement("UPDATE avisos SET status_envio=?, ultimo_envio=CASE WHEN ? THEN now() ELSE ultimo_envio END WHERE id=?")){boolean ok=allOk&&tentativas>0;ps.setString(1,ok?"enviado":"falhou");ps.setBoolean(2,ok);ps.setLong(3,aviso);ps.executeUpdate();}}
|
|
|
|
|
private boolean reagendarAvisoRecorrente(Connection c,long aviso,Map<String,Object>a)throws SQLException{
|
|
|
|
|
int meses=a.get("recorrencia_meses")==null?0:((Number)a.get("recorrencia_meses")).intValue();
|
|
|
|
|
if(!Boolean.TRUE.equals(a.get("recorrencia_ativa"))||meses<=0)return false;
|
|
|
|
@@ -573,6 +613,7 @@ public final class ClienteHandlers implements HttpHandler {
|
|
|
|
|
throw new IllegalArgumentException("Data/hora invalida. Use dd/mm/aaaa hh:mm.");
|
|
|
|
|
} private int recorrenciaMeses(String v){if(v==null||v.isBlank())return 0;int n=Integer.parseInt(v);if(n==0||n==1||n==3||n==12)return n;throw new IllegalArgumentException("Recorrencia invalida. Use 0, 1, 3 ou 12 meses.");} private boolean bool(String v){return "true".equalsIgnoreCase(v)||"1".equals(v)||"sim".equalsIgnoreCase(v);} private String str(Object v){return v==null?"":String.valueOf(v);} private String firstNonBlank(String...vals){for(String v:vals)if(v!=null&&!v.isBlank())return v;return "";} private String cnpj(String v){String d=v==null?"":v.replaceAll("\\D","");if(d.length()!=14)throw new IllegalArgumentException("CNPJ invalido. Informe 14 digitos.");return d;}
|
|
|
|
|
private List<Long> longArray(String raw,String key){String a=arrayBody(raw,key);if(a.isBlank())return List.of();List<Long> out=new ArrayList<>();for(String x:a.split(",")){String v=x.trim().replace("\"","");if(!v.isBlank())out.add(Long.parseLong(v));}return out;}
|
|
|
|
|
private List<String> stringArray(String raw,String key){String a=arrayBody(raw,key);if(a.isBlank())return List.of();List<String> out=new ArrayList<>();for(String x:a.split(",")){String v=x.trim().replace("\"","");if(!v.isBlank())out.add(v);}return out;}
|
|
|
|
|
private List<Destinatario> destinatarios(String raw){String a=arrayBody(raw,"destinatarios");if(a.isBlank())return List.of();List<Destinatario> out=new ArrayList<>();for(String obj:a.split("\\},\\s*\\{")){String x=obj.replace("{","").replace("}","");String tipo=null;Long id=null;for(String kv:x.split(",")){String[]p=kv.split(":",2);if(p.length<2)continue;String k=p[0].trim().replace("\"","");String v=p[1].trim().replace("\"","");if("tipo".equals(k)||"tipo_destinatario".equals(k))tipo=v;if("id".equals(k)||"destinatario_id".equals(k))id=Long.parseLong(v);}if(tipo!=null&&id!=null)out.add(new Destinatario(tipo,id));}return out;}
|
|
|
|
|
private String arrayBody(String raw,String key){String marker="\""+key+"\"";int p=raw.indexOf(marker);if(p<0)return"";int s=raw.indexOf('[',p);if(s<0)return"";int depth=0;for(int i=s;i<raw.length();i++){char ch=raw.charAt(i);if(ch=='[')depth++;if(ch==']'&&--depth==0)return raw.substring(s+1,i).trim();}return"";}
|
|
|
|
|
private String removeArrayField(String raw,String key){String marker="\""+key+"\"";int p=raw.indexOf(marker);if(p<0)return raw;int s=raw.indexOf('[',p);if(s<0)return raw;int depth=0;for(int i=s;i<raw.length();i++){char ch=raw.charAt(i);if(ch=='[')depth++;if(ch==']'&&--depth==0)return raw.substring(0,s)+"\"\""+raw.substring(i+1);}return raw;} record Destinatario(String tipo,long id){}
|
|
|
|
|