# 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) ```mermaid 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_` (NOVO, bem mais simples) ```mermaid 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 ```sql 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": 1. Cadastra em `assembleias`: `condominio_id`, `tipo='ordinaria'`, `data_hora='2026-11-23 18:00'`, `pauta`. 2. Cria um `avisos` com `assembleia_id` apontando pra ela, `tipo='aviso'`, `data_evento` = mesma data/hora. 3. Anexa os documentos (convocação, pauta detalhada) via `aviso_documentos`. 4. Escolhe destinatários em `aviso_destinatarios` (síndico, subsíndico, conselheiros daquele condomínio + funcionários vinculados) — ou marca "todos" como padrão sugerido. 5. Marca `enviar_whatsapp`/`enviar_email` e 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)?