feat: complete administration and reporting
This commit is contained in:
@@ -30,6 +30,7 @@ Nginx ──► Laravel + Inertia/React
|
||||
## Módulos
|
||||
|
||||
- `app/Domain/Identity`: perfis, permissões e identidades externas.
|
||||
- `app/Domain/Administration`: políticas persistentes, modelos de notificação e configuração funcional.
|
||||
- `app/Domain/Inventory`: cache local de ativos e consultas do catálogo.
|
||||
- `app/Domain/Reservations`: disponibilidade, estados, regras e requisições.
|
||||
- `app/Domain/Approvals`: decisões, histórico e concorrência de aprovação.
|
||||
@@ -56,6 +57,12 @@ Pré-reservas ficam bloqueantes em `held` enquanto aguardam decisão. `Reservati
|
||||
|
||||
Notificações implementam `ShouldQueue`, usam `afterCommit` e seguem dois canais: email e tabela `notifications`. A caixa interna consulta exclusivamente a relação polimórfica do utilizador autenticado, evitando acesso horizontal a notificações de terceiros.
|
||||
|
||||
`ReservationPolicy` fornece defaults versionados e sobreposições guardadas em `portal_settings`. Antecedência, duração, limite de itens e prazo são validados no pedido e no serviço de domínio. A margem operacional é materializada em `reservation_items.buffer_starts_at`/`buffer_ends_at`; a restrição GiST usa estes campos, mantendo a proteção contra corridas. Uma alteração de política só afeta novas reservas, preservando o contrato temporal das existentes.
|
||||
|
||||
Os relatórios usam consultas de leitura com período máximo de 366 dias. A exportação CSV é transmitida em blocos e neutraliza conteúdos interpretáveis como fórmulas. Auditoria, relatórios e calendário global têm Gates próprios; o perfil `auditor` permanece exclusivamente de leitura.
|
||||
|
||||
`NotificationTemplateService` mantém defaults no código e sobreposições em `portal_settings`. Apenas variáveis conhecidas (`{reference}`, `{requester}`, `{starts_at}`, `{ends_at}`, `{comment}`) são substituídas; a alteração de modelos é auditada e nunca inclui credenciais ou configuração SMTP.
|
||||
|
||||
## Fluxo de dados Snipe-IT
|
||||
|
||||
1. Um job consulta a API paginada com token de leitura.
|
||||
|
||||
@@ -78,3 +78,17 @@ Notificações funcionais são colocadas na fila apenas depois da confirmação
|
||||
Checkout e check-in usam um token operacional distinto do token de leitura e nunca escrevem diretamente na base de dados do Snipe-IT. Cada equipamento é movimentado remotamente antes de o respetivo `reservation_item` e `handover_record` serem confirmados localmente. Escritas não têm retry automático: uma falha de ligação ou HTTP 5xx pode ser posterior à execução remota e a repetição cega não é segura. Numa operação com vários itens, sucessos confirmados são preservados e uma falha posterior coloca a requisição em `incident`, com IDs concluídos, item falhado e erro em auditoria. O operador reconcilia o ativo no Snipe-IT e repete apenas o movimento ainda pendente.
|
||||
|
||||
O checkout é dirigido a `checkout_to_type=user`; o ID remoto confirmado pelo operador é guardado em `users.snipe_user_id`. O check-in usa o estado e a localização habitual provenientes da última sincronização. Esta opção segue os contratos oficiais de [checkout](https://snipe-it.readme.io/reference/hardware-checkout), [check-in](https://snipe-it.readme.io/reference/hardware-checkin) e o comportamento documentado de [erros em HTTP 200](https://snipe-it.readme.io/reference/api-overview).
|
||||
|
||||
## ADR-012 — Políticas persistentes e buffers temporais imutáveis
|
||||
|
||||
**Data:** 2026-08-04
|
||||
**Estado:** aceite
|
||||
|
||||
Guardar parâmetros funcionais em `portal_settings`, mantendo defaults seguros no código. Antecedência, duração, prazo e limite de itens aplicam-se a novos pedidos. A margem é materializada em cada item através de `buffer_starts_at`/`buffer_ends_at` e protegida pela restrição de exclusão PostgreSQL. Alterar a política não recalcula reservas existentes: o período bloqueante aceite no momento da submissão permanece estável e auditável.
|
||||
|
||||
## ADR-013 — Supervisão de leitura e exportações seguras
|
||||
|
||||
**Data:** 2026-08-04
|
||||
**Estado:** aceite
|
||||
|
||||
Separar Gates para calendário global, relatórios e auditoria. Administradores têm acesso integral; auditores consultam relatórios/auditoria sem mutações; aprovadores e operadores consultam o calendário global. Relatórios são limitados a 366 dias, exportados por streaming e neutralizam possíveis fórmulas em CSV. Modelos de notificação são conteúdo funcional persistente, mas credenciais SMTP e tokens continuam exclusivamente no ambiente.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Estado do projeto e handoff
|
||||
|
||||
**Atualizado em:** 4 de agosto de 2026
|
||||
**Fase:** Fases 1 a 5 concluídas; próxima entrega: Fase 6
|
||||
**Fase:** Fases 1 a 6 concluídas; próxima entrega: Fase 7
|
||||
**Último agente:** Codex
|
||||
|
||||
## Resultado disponível
|
||||
@@ -40,6 +40,15 @@
|
||||
- Associação persistente entre o utilizador do portal e o respetivo ID no Snipe-IT, confirmada durante uma entrega bem-sucedida.
|
||||
- Tratamento explícito de falhas parciais: movimentos já aceites são preservados, a requisição passa a `incident` e a falha fica em `audit_logs` para reconciliação.
|
||||
- Registo de falta, atraso e incidente; um incidente pode criar um bloqueio temporal do equipamento que entra imediatamente no motor de disponibilidade.
|
||||
- Gestão administrativa de utilizadores com pesquisa, perfis múltiplos, estado ativo, departamento, ID Snipe-IT e reposição de palavra-passe.
|
||||
- Proteção contra desativação da própria conta administrativa e contra remoção do último administrador ativo.
|
||||
- Políticas de reserva editáveis para antecedência, duração, margem operacional, prazo de aprovação e limite de equipamentos.
|
||||
- Margens temporais persistidas por item e garantidas pela restrição de exclusão PostgreSQL, sem reescrever reservas existentes quando a política muda.
|
||||
- Calendário institucional global para aprovadores, operadores, administradores e auditores.
|
||||
- Relatórios por período com totais, horas de utilização, incidentes, atrasos, estados, categorias, departamentos e equipamentos mais requisitados.
|
||||
- Exportação CSV protegida contra formula injection e limitada a períodos de 366 dias.
|
||||
- Consulta paginada e filtrável de `audit_logs`, apenas para administradores e auditores.
|
||||
- Modelos editáveis de assunto/mensagem para os seis eventos de notificação, com variáveis validadas e auditoria das alterações.
|
||||
|
||||
## Limites conhecidos
|
||||
|
||||
@@ -49,36 +58,38 @@
|
||||
- O calendário atual é a vista mensal pessoal do MVP; vistas diária, semanal, global e por equipamento/categoria/localização ficam para as áreas operacional e administrativa.
|
||||
- O leitor operacional aceita scanners QR/código de barras que funcionem como teclado. A leitura direta pela câmara do navegador ainda não foi adicionada.
|
||||
- Uma falha depois de o Snipe-IT confirmar um movimento e antes do commit local é uma transação distribuída ambígua; não existe retry automático de escritas. O operador deve reconciliar pelos registos Snipe-IT e `audit_logs` conforme o runbook.
|
||||
- As exportações administrativas estão disponíveis em CSV; XLSX poderá ser acrescentado se o processo institucional o exigir.
|
||||
|
||||
## Próxima tarefa recomendada
|
||||
|
||||
Implementar a **Fase 6 — administração e relatórios**:
|
||||
Implementar a **Fase 7 — hardening e entrada em produção**:
|
||||
|
||||
1. criar a área administrativa de utilizadores, perfis e associação ao ID Snipe-IT;
|
||||
2. tornar configuráveis as políticas de antecedência, duração, margens, estados e categorias;
|
||||
3. criar calendário global e relatórios de utilização, atrasos, incidentes e ativos mais requisitados;
|
||||
4. adicionar exportação CSV/XLSX e filtros por período, categoria, departamento e estado;
|
||||
5. criar consulta de auditoria apenas de leitura para o perfil `auditor`;
|
||||
6. adicionar métricas operacionais e gestão de modelos de email;
|
||||
7. cobrir autorização, exportações e agregações com testes e atualizar toda a documentação.
|
||||
1. implementar Microsoft Entra ID/OIDC e associação segura a contas locais;
|
||||
2. validar a integração contra o Snipe-IT institucional e configurar tokens reais de menor privilégio;
|
||||
3. configurar SMTP institucional, domínio, HTTPS e gestão externa de segredos;
|
||||
4. adicionar health checks, monitorização, alertas, backups e teste de restauro;
|
||||
5. executar testes de segurança, concorrência, desempenho e end-to-end com equipamentos reais;
|
||||
6. preparar formação, dados iniciais e piloto com um grupo reduzido;
|
||||
7. corrigir resultados do piloto e preparar a disponibilização geral.
|
||||
|
||||
## Testes da última sessão
|
||||
|
||||
Validação concluída em 4 de agosto de 2026:
|
||||
|
||||
- `docker compose exec -T app composer test`: passou;
|
||||
- Laravel Pint: 117 ficheiros sem desvios;
|
||||
- PHPStan/Larastan nível 7: 89 ficheiros, zero erros;
|
||||
- Pest: 79 testes passaram, 412 asserções e 2 testes de registo ignorados por a funcionalidade estar deliberadamente desativada;
|
||||
- Laravel Pint: 132 ficheiros sem desvios;
|
||||
- PHPStan/Larastan nível 7: 100 ficheiros, zero erros;
|
||||
- Pest: 92 testes passaram, 522 asserções e 2 testes de registo ignorados por a funcionalidade estar deliberadamente desativada;
|
||||
- TypeScript (`tsc --noEmit`): passou;
|
||||
- ESLint: passou;
|
||||
- Prettier: passou;
|
||||
- Vite: builds cliente e SSR concluídos, 2309 módulos cliente e 98 módulos SSR transformados;
|
||||
- Vite: builds cliente e SSR concluídos, 2314 módulos cliente e 103 módulos SSR transformados;
|
||||
- PostgreSQL 17: `migrate:fresh --seed` concluído, incluindo extensão `btree_gist` e restrição de exclusão temporal;
|
||||
- PostgreSQL 17: migration incremental do marcador `last_seen_sync_run_id` aplicada com sucesso;
|
||||
- PostgreSQL 17: nenhuma migration pendente; comando de expiração executado e agendamentos horário/a cada cinco minutos confirmados;
|
||||
- PostgreSQL 17: migration `notifications` aplicada com sucesso;
|
||||
- PostgreSQL 17: migration `snipe_user_id` aplicada e fluxo operacional exercitado contra API simulada;
|
||||
- PostgreSQL 17: migration de `portal_settings` e buffers temporais aplicada; restrição GiST recriada sobre o intervalo com margem;
|
||||
- smoke test HTTP: `/login` respondeu com estado 200 através do Nginx;
|
||||
- Vite em Docker: URL pública, HMR e CORS verificados em `localhost:5173`; corrigida a página em branco causada pela publicação anterior de `0.0.0.0:5173`;
|
||||
- Inertia SSR: renderização do login validada através do serviço `node`; corrigido o componente de mensagens flash que usava `usePage()` fora do contexto Inertia;
|
||||
|
||||
@@ -128,6 +128,19 @@ Utilizadores com perfil `approver` ou `administrator` acedem a `http://localhost
|
||||
|
||||
As decisões geram jobs de notificação. Em desenvolvimento, confirmar o email em `http://localhost:8025` e a notificação interna em `http://localhost:8000/notificacoes`. Se uma mensagem não chegar, consultar primeiro `docker compose logs --tail=100 queue` e a tabela `failed_jobs`; não repetir a decisão já confirmada.
|
||||
|
||||
## Administração e relatórios
|
||||
|
||||
Administradores usam:
|
||||
|
||||
- `http://localhost:8000/administracao/utilizadores` para contas, perfis e IDs Snipe-IT;
|
||||
- `http://localhost:8000/administracao/regras` para políticas aplicadas a novos pedidos;
|
||||
- `http://localhost:8000/administracao/notificacoes/modelos` para assuntos e mensagens;
|
||||
- `http://localhost:8000/administracao/snipe-it` para diagnóstico da integração.
|
||||
|
||||
As alterações são registadas em `audit_logs`. A margem de uma reserva já submetida não muda quando a política é alterada; confirmar `buffer_starts_at` e `buffer_ends_at` do item ao investigar um conflito.
|
||||
|
||||
Administradores e auditores consultam `http://localhost:8000/relatorios` e `http://localhost:8000/auditoria`. O CSV usa `;`, UTF-8 com BOM e neutralização de fórmulas para abertura segura em aplicações de folha de cálculo. Cada pedido está limitado a 366 dias; para análises plurianuais, exportar períodos separados. Aprovadores, operadores, administradores e auditores consultam o planeamento consolidado em `http://localhost:8000/calendario-global`.
|
||||
|
||||
## Produção
|
||||
|
||||
Antes de disponibilizar:
|
||||
|
||||
Reference in New Issue
Block a user