Files
Investidor-V2/docs/investmoz/existing-business/wizard-implementation.md
T
nala 1106509116
tests / ci (push) Canceled after 0s
vrsao 2
2026-10-08 14:02:01 +02:00

73 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Formulário por etapas — entrega local, 29/09/2026
**Disponível em `/investidor/negocios`: criar rascunho e abrir a ficha. O prompt A–C completo ainda não está entregue.** Este incremento implementa a preparação privada por etapas, autosave, retoma, sector e confirmação. Não implementa ainda publicação, uploads seguros, manifestações MNE ou operação integral.
1. **Diagnóstico tecnológico:** Laravel 13.30.1, PHP de validação 8.5.11, React 19.2.8, TypeScript 5.9.3, Inertia, Vite Plus, Leaflet e PostgreSQL 17.11/PostGIS. Mantidos componentes e autenticação por sessão/email verificado. Filas database/Redis e disco S3 são configuráveis; conectividade Redis/S3/ClamAV e CRM não ensaiada neste incremento. Sem novas dependências.
2. **Pressupostos:** formulário autenticado, classificação reservada e `public.existing_businesses` como autoridade. Identidade e titularidade são declarações pendentes. Referências documentais não são uploads, mandatos validados ou autorizações de transmissão. O preenchimento permite rascunhos incompletos; a submissão aplica validações adicionais. Clientes anteriores sem wizard_version conservam o contrato legado; converter todos os clientes exige uma migração de contrato posterior.
3. **Mapa A–C:** ver matriz abaixo. Não há equivalência entre oito etapas visíveis e implementação de todos os requisitos dessas etapas.
4. **Plano por fase:** responsável técnico da implementação: Codex. Incremento A1 executado: schema/validação, FK sectorial, wizard e testes. A2 pendente: localização normalizada/cartografia, contexto económico, anexos/scanner, consentimentos separados e acessibilidade integral. B pendente: manifestação MNE ligada a anúncio publicado, perfil e CRM idempotente. C pendente: aprovações, tarefas, SLA, alertas e dashboard. Dependências e gates mantidos em `implementation-status.md`; autorizações de desenvolvimento existentes preservadas.
5. **Modelo PostgreSQL:** coluna nullable bigint `existing_businesses.sector_id`, FK RESTRICT para a taxonomia existente e índice B-tree completo. Dados declarativos privados ficam no payload cifrado já existente; activos/direitos continuam nas entidades tipadas existentes. Não foram criadas pessoas, sectores ou negócios no schema mne. Localização deste formulário é ainda descritiva, não georreferenciada.
6. **Migration/modelos:** `2026_09_29_200000_existing_business_form_sector.php` aplicada localmente. DOWN remove a coluna somente se não houver associações sectoriais. Modelo ExistingBusiness existente preservado; `BusinessFormSchema` centraliza campos, rótulos PT/EN e validação. Snapshot/auditoria cifrados existentes conservados.
7. **API:** mesmos nove endpoints privados `/api/v1/existing-business`. `sector_id` é adicional no draft; `confirmation_code` exigido na submissão de wizard_version=1. GET da ficha fornece formSchema e sectores activos. Erros 403/409/422 e ausência de publicação preservados. OpenAPI actualizado para 1.2.0; schema exportável por `tools/export-business-form-schema.php`.
8. **Permissões:** proprietário verificado cria/edita rascunho ou pedido de informação; revisor designado, independente e com MFA consulta submissões. Terceiros recusados. Revisores recebem os novos campos apenas após a policy de consulta. Autosave usa as mesmas autorizações e versões da gravação manual.
9. **Estados:** rascunho → submetido; revisão/pedido de informação/retirada existentes. Confirmação explícita por código e consentimento de análise interna no servidor. Repetir submissão com versão anterior dá 409 sem duplicar histórico; ainda não há comprovativo idempotente por chave de pedido. As duas aprovações e os demais estados de A–C continuam pendentes.
10. **Serviços/eventos/Jobs:** reutilizados ExistingBusinessDrafts, ExistingBusinessIntake, objectos, snapshots e ponte legada. Nenhum Job externo, tarefa de triagem, notificação ou envio CRM novo. O consentimento actual é de revisão interna; não é o catálogo completo de consentimentos versionados do anexo.
11. **React:** `business-wizard.tsx` oferece oito etapas, progresso, PT/EN nos controlos principais, autosave após três segundos, retoma no servidor, resumo e confirmação. Navegação/fecho avisam sobre alterações não gravadas; conflitos não substituem silenciosamente dados. Representante revela campos de mandato. Activos/direitos reutilizam BusinessObjects; estes componentes existentes ainda não estão integralmente traduzidos. Criação/consulta administrativa por representação de terceiros permanece pendente.
12. **Código por ficheiro:** novos `app/Services/BusinessFormSchema.php`, migration sectorial, `resources/js/pages/investment/business-wizard.tsx`, `tests/Feature/ExistingBusinessWizardTest.php`, exportador de schema e ferramentas de navegador. Alterados controlador, Drafts, Intake, business.tsx, businesses.tsx, business-types.ts e gerador OpenAPI. Código completo nesses ficheiros; sem ficheiros removidos nem commit Git.
13. **Testes:** suite completa executada: 180 testes / 1845 verificações. Depois do controlo adicional por modalidade e do teste de rollback, suite específica do wizard: 2 testes / 30 verificações aprovados. Cobertura inclui cifragem, terceiro recusado, retoma, sector, dados inválidos, conflito de versão, mandato, activo obrigatório, confirmação, submissão duplicada e rollback. Navegador: autosave/recarga, resumo em 390/1440 px e submissão, sem excepções JS. Isto não é uma auditoria WCAG completa.
14. **Comandos:** abaixo. Não foi necessário instalar pacotes Composer/npm. Backend requer PHP com pgsql. Migration local aplicada após backup/restauro, usando `--path` específico. Os scripts de navegador e fixtures só usam QA em 55441/18027, nunca a base local operacional.
15. **Resultados:** PHPStan, Pint, TypeScript, lint do wizard e build aprovados. Backup com restauro de 210 tabelas: `storage/app/private/mne-integrity-backup-20260929-200103/`. Evidência do navegador: `wizard-browser-validation.json`. Auditoria de dependências e ensaios de serviços externos não executados neste incremento.
16. **Riscos residuais:** restantes campos e relações A; identidade normalizada; coordenadas/geometria; CRM MNE; scanner/upload; redis em operação; consentimentos separados; comprovativo/notificações; SLA; aprovações/publicação; tradução integral; testes de acessibilidade, carga e serviços externos. A conta de BD local ainda é superuser. Nenhuma alegação de prontidão para produção.
17. **Go/No-Go:** Go para testar preparação privada local; **No-Go para entrega integral A–C ou Go-Live**. Os fluxos incompletos não foram expostos como funcionais.
| Requisito | Implementação actual | Estado |
| --------------------------- | ----------------------------------------------------------------- | ------------------------------------------------- |
| A: proponente/representação | Campos cifrados, mandato condicional, declaração e validação | Parcial; sem verificação de identidade/documentos |
| A: modalidade/sector/valor | Taxonomia existente, FK, limites, moeda e natureza na submissão | Parcial; faltam intervalos e estruturas completas |
| A: localização/contexto | Descrição privada | Geografia estruturada e ligações pendentes |
| A: activos/direitos | Editor tipado existente; objecto aplicável exigido por modalidade | Parcial |
| A: fontes/documentos | Referências declaradas | Upload/scanner pendentes |
| A: rascunho/retoma/resumo | Autosave, versão, oito etapas, confirmação no servidor | Testado |
| B: interesse/CRM | Serviço geral existente preservado | Integração MNE pendente |
| C: revisão | Revisão privada e histórico existentes | Tarefas/SLA/dupla aprovação pendentes |
```powershell
php artisan migrate --path=database/migrations/2026_09_29_200000_existing_business_form_sector.php
php tools/export-business-form-schema.php
node tools/existing-business-openapi.mjs
php vendor/bin/phpunit --filter ExistingBusinessWizard --do-not-cache-result
npm.cmd run types:check
npm.cmd run build
```
Em ambiente QA isolado (`APP_ENV=testing`, base `portal_services_test`, porta 55441): `php tools/business-wizard-browser-seed.php`, seguido de `node tools/business-wizard-browser.mjs`, com servidor QA 18027 e navegador CDP 9224. As fixtures sintéticas ficam apenas nessa base de teste.
## Revisão da especificação do formulário de oportunidades — 02/10/2026
- O cadastro continua em sessão autenticada em `/investidor/negocios`, com classificação reservada. Não é uma submissão pública anónima e não publica automaticamente.
- O wizard `wizard_version=2` apresenta os sete tipos pedidos, recolhe proponente/representação e fonte, mostra dados de negócio por tipo, disponibilidade, estado de valor e três confirmações separadas. Rascunho/retoma permanecem no armazenamento cifrado já existente. O contrato legado v1 continua com validação própria; não se reescrevem rascunhos históricos.
- A nova migration aditiva `2026_10_02_160000_extend_existing_business_opportunity_types.php` estende o CHECK de modalidades sem editar migration anterior. Recusa migrar se não localizar exactamente uma constraint da modalidade. A reversão recusa remover os valores quando existirem registos que os usam. **Migration não executada nesta continuação.**
- Localização específica/múltipla usa dropdowns territoriais em cascata da referência pública existente e valida a hierarquia na submissão. Os IDs ficam no payload cifrado; ainda não criam relação espacial canónica para a oportunidade, não há marcador de mapa nem múltiplas localizações estruturadas. Subsector/actividade é texto pesquisável por designação, sem código obrigatório.
- Recursos tipados aceitam estado (disponível, contratado, previsto ou por confirmar) e data da fonte. Referências documentais continuam referências, não upload. Anexos classificados, scanner, classificação individual de conteúdo público/interno/confidencial, parque/cluster/corredor/ZEE/ZFI e projecto âncora continuam pendentes.
- Proponente existente pode ser declarado por nome, mas não há selector de CRM/cadastro sem duplicação. A escolha de contacto empresarial aprovado é uma preferência declarada; não é autorização automática de publicação. A projecção pública mantém contactos pessoais fora da allowlist.
- Não foi implementado pedido pós-publicação para suspensão/encerramento, alerta periódico de disponibilidade, nem fluxo MNE completo de consulta e resposta. Alterações materiais continuam limitadas a draft/pedido de informação e precisam de nova submissão/revisão.
- `docs/investmoz/existing-business/form-schema.json` e `docs/investmoz/existing-business/openapi.json` foram regenerados pelos exportadores existentes. `npm.cmd run types:check`, `php -l` nos seis ficheiros PHP alterados e `git diff --check` passaram. Não executei testes PHPUnit nem a migration.
- Gate proposto: **parcial, apenas teste privado após aplicar e validar a migration num banco isolado**. Sem uploads/revisão de anexos e consentimentos de divulgação por item, não avançar para publicação de oportunidades reais.
## Verificação do formulário recebido — 03/10/2026
- A proposta foi comparada com o wizard v2. Já existem as oito etapas, sete tipos de oportunidade, campos por modalidade, declaração de proponente/representação, contacto por email ou telefone, hierarquia territorial dependente, resumo editável e submissão reservada para revisão. O marketplace público usa uma allowlist e não recebe contactos pessoais nem o payload cifrado.
- Corrigida a submissão com `valid_until` vencido em payloads sem `wizard_version`: o prazo continua opcional, mas qualquer prazo fornecido passa a ser validado como não vencido. A versão 1 continua a exigir prazo conforme o contrato legado; as versões seguintes aceitam prazo omitido.
- Permanecem por implementar: selector de proponente/cadastro sem duplicação; múltiplas localizações estruturadas, coordenadas e precisão no mapa; relações económicas; upload com antivírus e classificação individual de anexos; selecção granular dos campos publicáveis; e fluxo para actualizar disponibilidade, suspender/encerrar e confirmar disponibilidade periodicamente. Referências documentais continuam a não ser anexos validados.
- Evidência executada nesta verificação: `php -l app/Services/ExistingBusinessIntake.php`, `php vendor/bin/pint --test app/Services/ExistingBusinessIntake.php` e o teste dirigido `ExistingBusinessIntakeTest::test_arbitrary_states_and_incomplete_or_expired_submission_are_rejected` passaram (1 teste, 5 asserções) no PostgreSQL isolado em 55441. O cluster de QA foi parado e a porta confirmou-se fechada; não usei a base da aplicação. Restantes testes do wizard permanecem por executar nesta verificação.
- **Pesquisa de sector:** o campo do passo 3 agora filtra a taxonomia activa por designação, sem perder a selecção actual do rascunho. Esta melhoria não altera a API nem o armazenamento. Continuam pendentes o proponente associado a cadastro existente sem duplicação, localizações múltiplas/georreferenciadas, relações económicas estruturadas, anexos com scanner e consentimento individual de divulgação, e ciclo de vida pós-publicação.
### Localizações administrativas múltiplas — 2026-10-03
- O rascunho privado agora admite 2–20 percursos administrativos, guardados em `payload.locations_json` dentro do payload já cifrado. O cliente limpa selecções descendentes ao mudar um nível; o servidor valida UUID, hierarquia na referência pública, mínimo/máximo e percursos repetidos ou sobrepostos. Não são recolhidas nem inventadas coordenadas.
- A resposta de leitura/gravação resolve os nomes dos percursos exclusivamente a partir da referência territorial pública. O resumo mostra os nomes depois de guardar. `wizard_version=2` consta do contrato OpenAPI; a rota legada conserva validação própria.
- Ficheiros desta tranche: `BusinessFormSchema.php`, `InvestmentGeography.php`, `ExistingBusinessController.php`, `business-locations.ts`, `business-wizard.tsx`, `business-types.ts`, `existing-business-openapi.mjs`, `ExistingBusinessWizardTest.php` e `business-locations.test.mjs`.
- Evidência: PHP 8.5.11 e PostgreSQL 17 descartável na porta 55441, migrations aplicadas apenas na base temporária; `ExistingBusinessWizardTest` 3/3, 49 assertions; testes frontend da localização 3/3; TypeScript, Pint dirigido, PHP lint e `git diff --check` passaram. O listener preexistente em 5432 não foi utilizado. Cluster parado; os ficheiros de dados QA permanecem no directório temporário `%TEMP%\investmoz-stage-multiloc` porque a limpeza automática foi bloqueada pelo executor.
- Sem migration nem alteração de esquema persistente. Rollback: reverter os trechos acima e remover os dois testes/helpers novos; não há dados existentes a migrar. Permanecem pendentes mapa/coordenadas, relação territorial canónica e associação a parques/zonas; esta entrega não autoriza publicação de oportunidade.