Automatiza notificacoes de assembleias
This commit is contained in:
@@ -108,32 +108,79 @@ public final class ClienteHandlers implements HttpHandler {
|
||||
private void criarEspaco(HttpExchange ex,Connection c,long cond,long fid)throws Exception{Map<String,String>b=body(ex); long id=insert(c,"INSERT INTO espacos_comuns (condominio_id,nome,descricao,valor_utilizacao_centavos,indice_correcao) VALUES (?,?,?,?,?)",Arrays.asList(cond,req(b,"nome"),nullable(b.get("descricao")),optLong(b.get("valor_utilizacao_centavos")),nullable(b.get("indice_correcao")))); audit(c,fid,"create","espacos_comuns",id,null,b); HttpResponses.json(ex,201,Map.of("espaco",one(c,"SELECT * FROM espacos_comuns WHERE id=?",Arrays.asList(id))));}
|
||||
private void atualizarEspaco(HttpExchange ex,Connection c,long cond,long eid,long fid)throws Exception{Map<String,String>b=body(ex); Map<String,Object> old=one(c,"SELECT * FROM espacos_comuns WHERE id=? AND condominio_id=?",Arrays.asList(eid,cond)); if(old==null){HttpResponses.json(ex,404,Map.of("erro","espaco_nao_encontrado"));return;} Long novo=optLong(b.get("valor_utilizacao_centavos")); try(PreparedStatement ps=c.prepareStatement("UPDATE espacos_comuns SET nome=COALESCE(?,nome), descricao=COALESCE(?,descricao), valor_utilizacao_centavos=COALESCE(?,valor_utilizacao_centavos), indice_correcao=COALESCE(?,indice_correcao), data_ultimo_reajuste=CASE WHEN ? IS NOT NULL AND ?<>valor_utilizacao_centavos THEN current_date ELSE data_ultimo_reajuste END WHERE id=? AND condominio_id=?")){ps.setString(1,b.get("nome"));ps.setString(2,b.get("descricao")); if(novo==null)ps.setNull(3,Types.BIGINT);else ps.setLong(3,novo); ps.setString(4,b.get("indice_correcao")); if(novo==null){ps.setNull(5,Types.BIGINT);ps.setNull(6,Types.BIGINT);}else{ps.setLong(5,novo);ps.setLong(6,novo);} ps.setLong(7,eid);ps.setLong(8,cond);ps.executeUpdate();} audit(c,fid,"update","espacos_comuns",eid,old,b); HttpResponses.json(ex,200,Map.of("espaco",one(c,"SELECT * FROM espacos_comuns WHERE id=?",Arrays.asList(eid))));}
|
||||
private void criarAssembleia(HttpExchange ex,Connection c,long emp,long cond,long fid)throws Exception{
|
||||
Map<String,String>b=body(ex);
|
||||
long 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"))));
|
||||
audit(c,fid,"create","assembleias",id,null,b);
|
||||
Map<String,Object> envio=criarAvisoAssembleia(c,emp,cond,id,fid,b);
|
||||
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;}
|
||||
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"))));
|
||||
audit(c,fid,"create","assembleias",id,null,b);
|
||||
envio=criarAvisosAssembleia(c,emp,cond,id,fid,b,dests);
|
||||
c.commit();
|
||||
}catch(Exception err){
|
||||
c.rollback();
|
||||
throw err;
|
||||
}finally{
|
||||
c.setAutoCommit(true);
|
||||
}
|
||||
HttpResponses.json(ex,201,Map.of("assembleia",one(c,"SELECT * FROM assembleias WHERE id=?",Arrays.asList(id)),"envio",envio));
|
||||
}
|
||||
private Map<String,Object> criarAvisoAssembleia(Connection c,long emp,long cond,long assembleia,long fid,Map<String,String>b)throws Exception{
|
||||
List<Map<String,Object>> contatosAviso=rows(c,"SELECT contato_id FROM contato_condominio WHERE condominio_id=? AND status=?",Arrays.asList(cond,"ativo"));
|
||||
List<Map<String,Object>> funcionariosAviso=rows(c,"SELECT funcionario_id FROM funcionario_condominio WHERE condominio_id=?",Arrays.asList(cond));
|
||||
int destinatarios=contatosAviso.size()+funcionariosAviso.size();
|
||||
if(destinatarios==0)return Map.of("enviados",0,"falhas",0,"mensagem","Nenhum destinatario vinculado ao condominio.");
|
||||
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;
|
||||
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.");
|
||||
if(evolutionAprovada(emp)==null)return Map.of("enviados",0,"falhas",1,"mensagem","WhatsApp nao aprovado para esta empresa.");
|
||||
String titulo="Assembleia " + req(b,"tipo");
|
||||
StringBuilder mensagem=new StringBuilder();
|
||||
mensagem.append("Nova assembleia agendada.");
|
||||
Timestamp data=ts(req(b,"data_hora"));
|
||||
List<Long> avisos=new ArrayList<>();
|
||||
avisos.add(criarAvisoAutomaticoAssembleia(c,cond,assembleia,fid,b,destinatarios,"Assembleia agendada","Nova assembleia agendada.",null));
|
||||
avisos.add(criarAvisoAutomaticoAssembleia(c,cond,assembleia,fid,b,destinatarios,"Lembrete de assembleia","Lembrete: a assembleia acontece amanha.",Timestamp.valueOf(data.toLocalDateTime().minusDays(1))));
|
||||
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{
|
||||
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()));
|
||||
return out;
|
||||
}
|
||||
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;
|
||||
String mensagem=mensagemAssembleia(intro,b);
|
||||
long aviso=insert(c,"INSERT INTO avisos (condominio_id,assembleia_id,tipo,titulo,mensagem,data_evento,prioridade,enviar_whatsapp,enviar_email,status_envio,criado_por_funcionario) VALUES (?,?,?,?,?,?,?,?,?,?,?)",Arrays.asList(cond,assembleia,"assembleia",titulo,mensagem,agendado,"normal",true,false,agendado!=null&&agendado.after(agora)?"agendado":"nao_enviado",fid));
|
||||
for(Destinatario d:dests)insert(c,"INSERT INTO aviso_destinatarios (aviso_id,tipo_destinatario,destinatario_id) VALUES (?,?,?) ON CONFLICT DO NOTHING",Arrays.asList(aviso,d.tipo(),d.id()));
|
||||
enfileirarAviso(c,aviso,agendado);
|
||||
return aviso;
|
||||
}
|
||||
private String mensagemAssembleia(String intro,Map<String,String>b){
|
||||
StringBuilder mensagem=new StringBuilder(intro);
|
||||
mensagem.append("\nData/hora: ").append(req(b,"data_hora").replace('T',' '));
|
||||
if(b.get("local")!=null&&!b.get("local").isBlank())mensagem.append("\nLocal: ").append(b.get("local"));
|
||||
if(b.get("pauta")!=null&&!b.get("pauta").isBlank())mensagem.append("\nPauta: ").append(b.get("pauta"));
|
||||
long aviso=insert(c,"INSERT INTO avisos (condominio_id,assembleia_id,tipo,titulo,mensagem,data_evento,prioridade,enviar_whatsapp,enviar_email,status_envio,criado_por_funcionario) VALUES (?,?,?,?,?,?,?,?,?,?,?)",Arrays.asList(cond,assembleia,"assembleia",titulo,mensagem.toString(),ts(b.get("data_hora")),"normal",true,false,"nao_enviado",fid));
|
||||
for(Map<String,Object> row:contatosAviso)insert(c,"INSERT INTO aviso_destinatarios (aviso_id,tipo_destinatario,destinatario_id) VALUES (?,?,?) ON CONFLICT DO NOTHING",Arrays.asList(aviso,"contato",((Number)row.get("contato_id")).longValue()));
|
||||
for(Map<String,Object> row:funcionariosAviso)insert(c,"INSERT INTO aviso_destinatarios (aviso_id,tipo_destinatario,destinatario_id) VALUES (?,?,?) ON CONFLICT DO NOTHING",Arrays.asList(aviso,"funcionario",((Number)row.get("funcionario_id")).longValue()));
|
||||
enfileirarAviso(c,aviso,ts(b.get("data_hora")));
|
||||
return Map.of("aviso_id",aviso,"destinatarios",destinatarios,"status","enfileirado");
|
||||
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{
|
||||
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<>();
|
||||
for(Map<String,Object>a:avisos){
|
||||
for(Map<String,Object>d:rows(c,"SELECT tipo_destinatario,destinatario_id FROM aviso_destinatarios WHERE aviso_id=?",Arrays.asList(((Number)a.get("id")).longValue()))){
|
||||
String tipo=str(d.get("tipo_destinatario"));long id=((Number)d.get("destinatario_id")).longValue();String key=tipo+":"+id;
|
||||
if(vistos.add(key))dests.add(new Destinatario(tipo,id));
|
||||
}
|
||||
}
|
||||
if(dests.isEmpty())dests=destinatariosPadraoAssembleia(c,cond);
|
||||
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")));
|
||||
long aviso=criarAvisoAutomaticoAssembleia(c,cond,aid,fid,b,dests,"Assembleia cancelada","A assembleia foi cancelada.",null);
|
||||
try(PreparedStatement ps=c.prepareStatement("UPDATE avisos SET tipo='cancelamento', prioridade='alta' WHERE id=?")){ps.setLong(1,aviso);ps.executeUpdate();}
|
||||
}
|
||||
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;} 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();} audit(c,fid,"update","assembleias",aid,old,b); HttpResponses.json(ex,200,Map.of("assembleia",one(c,"SELECT * FROM assembleias WHERE id=?",Arrays.asList(aid))));}
|
||||
private void uploadDocumento(HttpExchange ex,Connection c,long emp,long cond,long fid)throws Exception{Multipart mp=parseMultipart(ex); if(mp.bytes.length>MAX_UPLOAD){HttpResponses.json(ex,400,Map.of("erro","arquivo_muito_grande"));return;} String ext=ext(mp.filename); if(!EXT_OK.contains(ext)){HttpResponses.json(ex,400,Map.of("erro","extensao_nao_permitida"));return;} String db=databaseName(emp); Path dir=uploadRoot.resolve(db).resolve(String.valueOf(cond)); Files.createDirectories(dir); String safe=UUID.randomUUID()+"-"+mp.filename.replaceAll("[^a-zA-Z0-9._-]","_"); Path file=dir.resolve(safe); Files.write(file,mp.bytes); String rel=db+"/"+cond+"/"+safe; long id=insert(c,"INSERT INTO documentos (condominio_id,tipo,nome_arquivo,caminho_armazenamento,enviado_por) VALUES (?,?,?,?,?)",Arrays.asList(cond,nullable(mp.tipo),mp.filename,rel,fid)); audit(c,fid,"create","documentos",id,null,Map.of("nome_arquivo",mp.filename)); HttpResponses.json(ex,201,Map.of("documento",one(c,"SELECT * FROM documentos WHERE id=?",Arrays.asList(id))));}
|
||||
private void downloadDocumento(HttpExchange ex,Connection c,long id)throws Exception{Map<String,Object>d=one(c,"SELECT * FROM documentos WHERE id=?",Arrays.asList(id)); if(d==null){HttpResponses.json(ex,404,Map.of("erro","documento_nao_encontrado"));return;} Path f=uploadRoot.resolve(String.valueOf(d.get("caminho_armazenamento"))); if(!Files.exists(f)){HttpResponses.json(ex,404,Map.of("erro","arquivo_nao_encontrado"));return;} ex.getResponseHeaders().set("Content-Disposition","attachment; filename=\""+d.get("nome_arquivo")+"\""); ex.sendResponseHeaders(200,Files.size(f)); Files.copy(f,ex.getResponseBody()); ex.close();}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user