5.2 KiB
Prompt 06 — Painel Cliente (escritório): condomínios, contatos, espaços comuns, assembleias, documentos
Contexto
Prompts 01–05 concluídos: autenticação completa, painel master funcionando, empresas sendo provisionadas com tenant próprio. Leia 10-tracker-progresso.md antes de começar.
Este prompt implementa o CRUD principal do menu Cliente → Cadastro Condomínio, que é o coração do sistema: condomínios, contatos (síndico/subsíndico/conselheiro), vínculo de funcionários, espaços comuns, assembleias e documentos.
Todos os endpoints deste prompt exigem exigirFuncionario (Prompt 04) e operam sobre o db_empresa_<slug> do empresa_id do token (usar TenantDataSourceProvider do Prompt 03).
Objetivo
CRUD completo de condominios, contatos + contato_condominio, funcionario_condominio, espacos_comuns, assembleias, documentos (upload de arquivo).
Especificação
1. Condomínios
POST /api/condominios body: {"nome", "cnpj", "endereco"}
GET /api/condominios lista todos do tenant
GET /api/condominios/{id}
→ resposta agregada: dados do condomínio + síndico atual (via ContatoCondominioDao) +
contagem de assembleias futuras + contagem de avisos ativos (isso é o "checklist"
que o funcionário usa como referência rápida)
PUT /api/condominios/{id}
2. Contatos (síndico/subsíndico/conselheiro)
POST /api/contatos body: {"nome", "telefone", "email"}
→ cria a pessoa (sem vínculo ainda)
POST /api/condominios/{id}/contatos/vincular
body: {"contato_id" (ou dados de um contato novo pra criar+vincular numa chamada só),
"tipo": "sindico"|"subsindico"|"conselheiro",
"data_inicio_mandato", "data_fim_mandato"}
→ grava em contato_condominio; se marcar tipo=sindico e já existir outro síndico ativo
pro mesmo condomínio, perguntar/forçar: por padrão, encerrar automaticamente o mandato
anterior (status='inativo', data_fim_mandato=hoje) e ativar o novo — deixar isso
documentado no código como decisão de negócio
GET /api/condominios/{id}/contatos lista todos os vínculos ativos daquele condomínio
DELETE /api/condominios/{id}/contatos/{contatoId}?tipo=... (desvincula — não apaga o contato,
só remove o vínculo daquele condomínio/tipo específico; um contato pode continuar
vinculado a outros condomínios)
3. Funcionários vinculados a condomínios
POST /api/condominios/{id}/funcionarios-vinculados
body: {"funcionario_id"} (funcionario precisa existir em db_master, mesma empresa)
GET /api/condominios/{id}/funcionarios-vinculados
DELETE /api/condominios/{id}/funcionarios-vinculados/{funcionarioId}
4. Espaços comuns
POST /api/condominios/{id}/espacos-comuns
body: {"nome", "descricao", "valor_utilizacao_centavos", "indice_correcao"}
GET /api/condominios/{id}/espacos-comuns
PUT /api/condominios/{id}/espacos-comuns/{espacoId}
→ se o valor mudar, atualizar data_ultimo_reajuste=hoje automaticamente
5. Assembleias
POST /api/condominios/{id}/assembleias
body: {"tipo", "data_hora", "local", "pauta"}
GET /api/condominios/{id}/assembleias (ordenar por data_hora desc)
PUT /api/condominios/{id}/assembleias/{id} (inclui mudar status: agendada/realizada/cancelada)
6. Documentos (upload)
POST /api/condominios/{id}/documentos multipart/form-data: arquivo + tipo
→ salvar o arquivo em um diretório local montado como volume Docker (ex: /app/uploads/
<empresa_slug>/<condominio_id>/<uuid>-<nome_original>), gravar caminho_armazenamento
com esse path relativo
→ validar extensão (permitir: pdf, jpg, jpeg, png, docx) e tamanho máximo (ex: 10MB)
GET /api/condominios/{id}/documentos
GET /api/documentos/{id}/download → serve o arquivo (Content-Disposition: attachment)
Adicionar o volume de uploads no docker-compose.yml do Prompt 01 (./uploads:/app/uploads).
7. Auditoria
Toda operação de POST/PUT/DELETE deste prompt deve gravar uma linha em log_auditoria (tabela_afetada, registro_id, ação, dados_anteriores/dados_novos em JSON, funcionario_id do token).
Critérios de aceite
- Criar um condomínio, vincular um síndico e um subsíndico, e chamar
GET /api/condominios/{id}mostra o síndico atual corretamente. - Vincular um segundo síndico ao mesmo condomínio encerra automaticamente o mandato do primeiro (
status='inativo'). - O mesmo
contatopode ser vinculado como síndico em dois condomínios diferentes simultaneamente. - Upload de um PDF funciona; upload de um
.exeé rejeitado com erro claro; upload de 15MB é rejeitado. log_auditoriarecebe uma linha para cada operação de escrita feita neste prompt (testar com pelo menos 3 operações diferentes).- Todos os endpoints só retornam/alteram dados do
empresa_iddo token — tentar acessar/api/condominios/{id}de outra empresa retorna 404 (não 403 — não revelar que o ID existe em outro tenant).
Ao concluir
Atualizar 10-tracker-progresso.md: Prompt 06 concluído, data, resumo. Confirmar Prompts 01–05 seguem marcados.