9.6 KiB
Sistema de Contabilidade de Condomínios — Arquitetura v3.0 (FINAL)
Substitui v2.0. Escopo drasticamente simplificado: o sistema é um cadastro de referência para o escritório — não um ERP de condomínio. Sem reservas, sem moradores, sem financeiro do condomínio, sem ocorrências, sem fornecedores, sem votação. Só: condomínios, contatos (síndico/subsíndico/conselheiro), funcionários vinculados, áreas comuns, assembleias e avisos/alertas com documentos anexados.
Stack: Java puro (JDBC) + HttpServer do JDK · PostgreSQL 16 (1 database por empresa) · Frontend HTML/CSS/JS puro no mesmo processo · Docker Compose.
1. Diagrama — db_master (sem mudança desde v2.0)
erDiagram
EMPRESAS ||--o{ FUNCIONARIOS : tem
EMPRESAS ||--o{ API_KEYS : possui
EMPRESAS ||--o{ EMPRESA_FUNCIONALIDADES : libera
FUNCIONALIDADES ||--o{ EMPRESA_FUNCIONALIDADES : referenciada_em
EMPRESAS ||--o{ EVOLUTION_INSTANCIAS : cadastra
PLANOS ||--o{ PLANO_FUNCIONALIDADES : inclui
FUNCIONALIDADES ||--o{ PLANO_FUNCIONALIDADES : referenciada_em
PLANOS ||--o{ ASSINATURAS : usado_em
EMPRESAS ||--o{ ASSINATURAS : possui
EMPRESAS ||--o{ PERIODOS_USO : tem
PERIODOS_USO ||--o{ PAGAMENTOS : gera
EMPRESAS ||--o{ LOGS_ENVIO_AVISOS : gera
EMPRESAS ||--o{ LEMBRETES_COBRANCA : recebe
Schema igual ao documento v2.0 (empresas, funcionarios, api_keys, funcionalidades, empresa_funcionalidades, evolution_instancias, configuracoes_plataforma, planos, plano_funcionalidades, assinaturas, periodos_uso, pagamentos, logs_envio_avisos, lembretes_cobranca) — nada disso mudou.
2. Diagrama — db_empresa_<slug> (NOVO, bem mais simples)
erDiagram
CONDOMINIOS ||--o{ CONTATO_CONDOMINIO : vincula
CONTATOS ||--o{ CONTATO_CONDOMINIO : vinculado_a
CONDOMINIOS ||--o{ FUNCIONARIO_CONDOMINIO : atendido_por
CONDOMINIOS ||--o{ ESPACOS_COMUNS : possui
CONDOMINIOS ||--o{ ASSEMBLEIAS : realiza
CONDOMINIOS ||--o{ AVISOS : publica
ASSEMBLEIAS ||--o{ AVISOS : gera
AVISOS ||--o{ AVISO_DOCUMENTOS : anexa
DOCUMENTOS ||--o{ AVISO_DOCUMENTOS : anexado_em
AVISOS ||--o{ AVISO_DESTINATARIOS : enviado_para
CONDOMINIOS ||--o{ DOCUMENTOS : arquiva
Schema
CREATE TABLE condominios (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
cnpj VARCHAR(18) UNIQUE,
endereco VARCHAR(255),
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
-- pessoa física (síndico/subsíndico/conselheiro) — cadastrada uma vez,
-- pode ser vinculada a mais de um condomínio
CREATE TABLE contatos (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
telefone VARCHAR(20), -- WhatsApp
email VARCHAR(150),
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
-- vínculo N:N entre contato e condomínio, com o papel que exerce ali
CREATE TABLE contato_condominio (
contato_id BIGINT NOT NULL REFERENCES contatos(id),
condominio_id BIGINT NOT NULL REFERENCES condominios(id),
tipo VARCHAR(20) NOT NULL, -- sindico, subsindico, conselheiro
data_inicio_mandato DATE,
data_fim_mandato DATE,
status VARCHAR(20) NOT NULL DEFAULT 'ativo',
PRIMARY KEY (contato_id, condominio_id, tipo)
);
-- "síndico atual" de um condomínio = SELECT ... WHERE condominio_id=X AND tipo='sindico' AND status='ativo'
-- funcionário do escritório (cadastro fica em db_master.funcionarios) vinculado
-- a quais condomínios ele cuida — também recebe avisos/alertas desses condomínios
CREATE TABLE funcionario_condominio (
funcionario_id BIGINT NOT NULL, -- referência a db_master.funcionarios, sem FK cross-db
condominio_id BIGINT NOT NULL REFERENCES condominios(id),
PRIMARY KEY (funcionario_id, condominio_id)
);
CREATE TABLE espacos_comuns (
id BIGSERIAL PRIMARY KEY,
condominio_id BIGINT NOT NULL REFERENCES condominios(id),
nome VARCHAR(100) NOT NULL, -- salão de festas, churrasqueira, quadra...
descricao TEXT,
valor_utilizacao_centavos BIGINT,
indice_correcao VARCHAR(30), -- IGPM, IPCA, definido em assembleia...
data_ultimo_reajuste DATE,
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE assembleias (
id BIGSERIAL PRIMARY KEY,
condominio_id BIGINT NOT NULL REFERENCES condominios(id),
tipo VARCHAR(20) NOT NULL, -- ordinaria, extraordinaria
data_hora TIMESTAMP NOT NULL,
local VARCHAR(150),
pauta TEXT,
status VARCHAR(20) NOT NULL DEFAULT 'agendada', -- agendada, realizada, cancelada
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE documentos (
id BIGSERIAL PRIMARY KEY,
condominio_id BIGINT NOT NULL REFERENCES condominios(id),
tipo VARCHAR(40), -- ata, convocacao, regimento, convencao, contrato, outro
nome_arquivo VARCHAR(255) NOT NULL,
caminho_armazenamento VARCHAR(500) NOT NULL,
versao INT NOT NULL DEFAULT 1,
enviado_por BIGINT, -- id em db_master.funcionarios
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE avisos (
id BIGSERIAL PRIMARY KEY,
condominio_id BIGINT NOT NULL REFERENCES condominios(id),
assembleia_id BIGINT REFERENCES assembleias(id), -- opcional: aviso sobre uma assembleia específica
tipo VARCHAR(20) NOT NULL DEFAULT 'aviso', -- aviso, alerta
titulo VARCHAR(150) NOT NULL,
mensagem TEXT NOT NULL,
data_evento TIMESTAMP, -- data/hora do evento relacionado (se houver)
data_publicacao TIMESTAMP NOT NULL DEFAULT now(),
data_expiracao TIMESTAMP,
prioridade VARCHAR(10) DEFAULT 'normal', -- baixa, normal, alta, urgente
enviar_whatsapp BOOLEAN NOT NULL DEFAULT false,
enviar_email BOOLEAN NOT NULL DEFAULT false,
status_envio VARCHAR(20) NOT NULL DEFAULT 'nao_enviado', -- nao_enviado, enviado, falhou
criado_por_funcionario BIGINT, -- id em db_master.funcionarios
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE aviso_documentos (
aviso_id BIGINT NOT NULL REFERENCES avisos(id),
documento_id BIGINT NOT NULL REFERENCES documentos(id),
PRIMARY KEY (aviso_id, documento_id)
);
-- destinatário pode ser um contato (síndico/subsíndico/conselheiro) OU um funcionário do escritório
CREATE TABLE aviso_destinatarios (
aviso_id BIGINT NOT NULL REFERENCES avisos(id),
tipo_destinatario VARCHAR(20) NOT NULL, -- contato, funcionario
destinatario_id BIGINT NOT NULL, -- contatos.id ou db_master.funcionarios.id, conforme tipo
PRIMARY KEY (aviso_id, tipo_destinatario, destinatario_id)
);
CREATE TABLE log_auditoria (
id BIGSERIAL PRIMARY KEY,
funcionario_id BIGINT,
acao VARCHAR(20) NOT NULL, -- create, update, delete
tabela_afetada VARCHAR(60) NOT NULL,
registro_id BIGINT,
dados_anteriores JSONB,
dados_novos JSONB,
criado_em TIMESTAMP NOT NULL DEFAULT now()
);
Removido em relação à v2.0: contatos_condominio (virou contatos + contato_condominio), reservas_area_comum, regras_cobranca, historico_reajustes, prestacoes_contas, lancamentos_financeiros, ocorrencias, fornecedores, votacoes.
3. Fluxo do exemplo que você deu
"Assembleia dia 23/11/2026 às 18:00 → vincular documentos pertinentes":
- Cadastra em
assembleias:condominio_id,tipo='ordinaria',data_hora='2026-11-23 18:00',pauta. - Cria um
avisoscomassembleia_idapontando pra ela,tipo='aviso',data_evento= mesma data/hora. - Anexa os documentos (convocação, pauta detalhada) via
aviso_documentos. - Escolhe destinatários em
aviso_destinatarios(síndico, subsíndico, conselheiros daquele condomínio + funcionários vinculados) — ou marca "todos" como padrão sugerido. - Marca
enviar_whatsapp/enviar_emaile dispara.
4. Autenticação, financeiro/AbacatePay, dashboard, catálogo de funcionalidades
Sem mudanças em relação à v2.0 — seguem valendo:
- 3 camadas de auth (master / escritório / API Key)
- Módulo financeiro do escritório (assinaturas, períodos de uso, pagamentos PIX via AbacatePay, bloqueio automático)
- Menu do dashboard (Master: Clientes/Planos/Financeiro/Configurações · Cliente: Cadastro Condomínio/Financeiro/Configurações)
- Catálogo de
funcionalidades(whatsapp, e-mail, API, exportação, auditoria etc.)
5. Endpoints ajustados
CRUD /api/condominios
CRUD /api/condominios/{id}/contatos (vincula/desvincula tipo=sindico|subsindico|conselheiro)
CRUD /api/condominios/{id}/funcionarios-vinculados
CRUD /api/condominios/{id}/espacos-comuns
CRUD /api/condominios/{id}/assembleias
CRUD /api/condominios/{id}/documentos
POST /api/condominios/{id}/avisos (body: assembleia_id?, documentos: [id,...], destinatarios: [{tipo, id}, ...])
GET /api/condominios/{id}/avisos/{id}
App externo (API Key)
GET /api/external/condominios/{id}/resumo
→ síndico/subsíndico/conselheiros atuais, próxima assembleia, avisos ativos, espaços comuns
6. Próximos passos
Escopo definitivo fechado. Posso começar os prompt files numerados agora (01-setup-projeto-docker.md em diante)?