diff --git a/docs/investmoz/v2/backlog-mestre.md b/docs/investmoz/v2/backlog-mestre.md index 42b899bd..58bd4760 100644 --- a/docs/investmoz/v2/backlog-mestre.md +++ b/docs/investmoz/v2/backlog-mestre.md @@ -71,3 +71,19 @@ ClamD, identidade do operador, evidência dos links reais e integrações extern O [registo do primeiro percurso](primeiro-percurso-ativo.md) identifica a pendência de sessão de navegador e dados reais. A leitura detalhada esclareceu o contador: os dois registos publicados são versões 1 e 2 de `project-preparation`, com o mesmo título, e não dois serviços distintos. Nenhuma versão foi alterada; nenhum dossier, pedido ou responsável foi criado para testar. **Correção do feedback do painel (V2-03):** criação de dossier confirma resultado/próxima ação; erros preservam campos; clique duplicado bloqueado durante o envio. QA: 19 testes PHP/287 asserções, navegador com persistência/recuperação e um único POST na fase de sucesso, sem submissão de pedido. Leitura ativa final às 10:13:50 UTC continua com zero dossiers/pedidos; nenhuma escrita real repetida. O motivo da tentativa anterior não é determinável apenas pela ausência de registo. + +# Atualização da revisão final — 8 de outubro de 2026 + +V2-03/V2-05: acrescentada ação «Validar este rascunho» na revisão final do simulador, onde antes só existia «Limpar este rascunho». Reutiliza validação e cálculo existentes e distingue verificação local de execução no servidor e de submissão ao Balcão. QA: 23 testes de regras, TypeScript e ensaio de navegador do botão/mensagem/ausência de submissão. Ver [registo do primeiro percurso](primeiro-percurso-ativo.md). Leitura ativa às 15:00:18 UTC: um dossier e zero pedidos; nenhuma escrita ativa nesta correção. Primeiro pedido real continua pendente. + +# Validação visível do rascunho — 8 de outubro + +V2-03/V2-05: resumo de verificação local com foco/deslocação, dados verificados, pendências/inconsistências e próxima ação. O botão final deixa de iniciar cálculo ou mudar de etapa silenciosamente; cálculo determinístico usa ação própria. QA de navegador em 1440/390 confirma correção e recuperação dos campos, foco visível e ausência de submissão; registos HTTP privados distinguem gravação e cálculo. Inspeção ativa `READ ONLY` às 15:14:26 UTC: um dossier e zero pedidos associados. Ver [registo do percurso](primeiro-percurso-ativo.md). + +# Gravação e recuperação do rascunho — diagnóstico do 422 + +V2-03/V2-05: o 422 do fixture QA foi identificado pela resposta HTTP como idioma `pt` inválido; corrigido para a opção existente `pt-MZ`. Implementada apresentação dos erros de API junto aos campos e aviso de gravação recusada sem apagar o rascunho. QA confirmou criação no servidor e recuperação numa nova sessão autenticada sem rascunho local, com validação e cálculo testados separadamente. Evidência privada `draft-422-browser.json`; ver [registo do percurso](primeiro-percurso-ativo.md). Nenhuma escrita ou submissão na base ativa. + +# Acesso direto às ferramentas — diagnóstico do clique + +V2-03/V2-05: `SimulationForm` em `/simulador-fiscal` distingue «Validar este rascunho», «Abrir cálculo» e «Consultar parâmetros fiscais». As ações de abertura deixam de depender de uma revisão sem pendências; têm destino focável e aviso se indisponível. QA demonstra revisão → ferramenta → execução/resultado, em computador e móvel, sem erros JavaScript; consulta fiscal independente preserva o modo. GET ativo confirma assets atuais servidos, mas o cache da sessão real do utilizador não foi observado. Ver [registo detalhado](primeiro-percurso-ativo.md). Nenhuma criação de dossier ou submissão na base ativa. diff --git a/docs/investmoz/v2/primeiro-percurso-ativo.md b/docs/investmoz/v2/primeiro-percurso-ativo.md index 8b66626f..db946144 100644 --- a/docs/investmoz/v2/primeiro-percurso-ativo.md +++ b/docs/investmoz/v2/primeiro-percurso-ativo.md @@ -53,3 +53,61 @@ Não foi repetida nenhuma escrita na base ativa. O novo feedback está no códig A validação automatizada no navegador QA passou, sem erros JavaScript: validação, HTTP 409 e falha de ligação preservaram o título; duplo clique durante o envio originou **um único POST de criação bem-sucedida**; confirmação e próxima ação ficaram visíveis; sair para o painel e reabrir recuperou o mesmo dossier persistido; zero pedidos submetidos. Evidência: `panel-browser-evidence.json`. O contador de POST dessa evidência refere-se à fase de sucesso, não às tentativas de erro do teste. Leitura ativa final às **10:13:50 UTC**: continuam zero dossiers e zero pedidos. O motivo concreto da tentativa real anterior permanece indeterminado sem captura da respetiva resposta na sessão do utilizador; não foi declarado como falha de consentimento ou de rede por inferência. + +# Correção da revisão final do simulador — 8 de outubro de 2026 + +A indicação «só aparece Limpar este rascunho» identifica o rodapé de `SimulationForm`, distinto da criação de dossier no painel. Antes desta correção, a revisão final apenas permitia limpar; «Validar e calcular no servidor» aparecia apenas na etapa fiscal de cenários personalizados. A correção anterior do painel mantém-se. + +Foi acrescentado «Validar este rascunho» na revisão final. Reutiliza as verificações existentes, conserva os campos e regressa à etapa com erros. A verificação local identifica explicitamente o seu âmbito e a próxima ação, sem afirmar gravação, elegibilidade ou aprovação. Em cenários personalizados encaminha para o cálculo determinístico existente, com bloqueio de execução duplicada; o resultado concluído indica a próxima ação. Nenhum botão desta correção submete um pedido ao Balcão. + +QA isolada: 23 testes das regras do formulário passaram; verificação TypeScript passou. O ensaio de navegador em `investmoz_v2_20261008_test:55441` demonstrou o botão na revisão, mensagem de verificação local e próxima ação, com zero submissões ao Balcão. Evidências privadas: `review-rules.txt`, `review-browser-evidence.json` e `review-final-qa.png`. O ensaio final não certifica um cálculo fiscal legal nem o percurso autenticado real do utilizador. + +Leitura ativa em **2026-10-08, 15:00:18 UTC**, em transação `READ ONLY`: um dossier, zero pedidos, 78 migrations; instalação anterior preservada. Não foi repetida qualquer escrita ativa e não é possível concluir, pelos totais, quem criou o dossier ou se a tentativa de validação chegou ao servidor. Continua pendente a preparação e confirmação explícita do primeiro pedido real. Restrições dos anexos/ClamD mantidas. + +# Resumo visível e separação entre validação e cálculo — 8 de outubro + +A implementação anterior podia deixar a mensagem fora do campo visível e, no modo personalizado, mudar para a etapa fiscal sem resumo. `SimulationForm` passa a apresentar um resumo focável, com deslocação até à mensagem, campos verificados, pendências/inconsistências com ligações para correção e próxima ação. Preserva os dados e mantém a revisão aberta. A validação é local: **não calcula valores e não envia HTTP de validação**; gravação automática, cálculo determinístico no servidor e submissão são operações distintas. O cálculo personalizado exige o botão próprio da etapa fiscal. + +QA em navegador, larguras 1440 e 390: campo pendente, correção, nova validação, foco no resumo dentro do viewport e recuperação após guardar e recarregar demonstrados. O teste captura métodos, rotas e estados HTTP em prova privada `review-summary-browser.json`; nenhuma submissão ao Balcão. Regras do formulário: 23 testes passaram; TypeScript e verificação de código passaram. Evidências adicionais: `review-summary-*.txt` e capturas `review-summary-1440.png`/`review-summary-390.png`. + +Inspeção ativa em **15:14:26 UTC**, exclusivamente `READ ONLY`: um dossier existente, com versão e referências preservadas, zero pedidos associados. Metadados privados em `active-dossier-inspection.json`; não foram repetidas escritas nem submetidos pedidos. Não houve acesso à sessão do navegador real do utilizador; as capturas HTTP correspondem a QA, não à tentativa ativa. + +# Limite da prova de recuperação em QA + +O registo HTTP do ensaio mostra `422` na criação automática do rascunho de teste: a recuperação demonstrada foi a dos dados locais da sessão, não uma gravação confirmada no servidor. Este resultado permanece explícito e não certifica recuperação numa nova sessão/dispositivo. O cálculo separado devolveu `202` e a consulta subsequente `200`, com resultado concluído. Nenhuma destas respostas corresponde a submissão ao Balcão. + +# Diagnóstico e correção do HTTP 422 — 8 de outubro de 2026 + +Resposta real capturada em QA: `economic_snapshot.preferred_language` rejeitado com «The selected economic_snapshot.preferred_language is invalid.» O cenário de teste enviava `pt`; `StoreSimulationFormDraftRequest` e as opções do formulário aceitam `pt-MZ` ou `en`. Não se tratava de recusa da classificação aduaneira nem de falha do cálculo. O fixture anterior foi corrigido para `pt-MZ`, mantendo as regras do servidor. + +Os erros de snapshots devolvidos pela API são agora associados aos campos de origem. A gravação recusada mostra um aviso, ligações para os campos e o erro junto ao respetivo controlo; não limpa os dados. Uma correção elimina o erro do campo editado e a confirmação de gravação elimina os erros anteriores. Há teste da extração de erros pessoais/económicos, índices de listas e respostas inválidas. + +QA em navegador: reproduzido o 422 com `pt`, demonstrado `aria-invalid` no idioma, selecionado Português (Moçambique), confirmado POST `201`. Guardado também o snapshot numa conta QA existente com `If-Match`; uma nova sessão autenticada, sem armazenamento local do rascunho, recuperou do servidor a base introduzida. Validação local e cálculo continuam separados, sem submissão ao Balcão. Provas privadas: `draft-422-response.json`, `draft-422-browser.json`, `draft-422-rules.txt`, `draft-422-types.txt`, `draft-422-build.txt`. As provas anteriores de recuperação apenas local não foram convertidas retroativamente em sucesso no servidor. + +Nenhuma escrita, submissão ou novo ensaio foi executado na base ativa neste diagnóstico. + +# Próxima ação ajustada à finalidade + +A revisão final já não encaminha uma simulação para preparar um pedido no Balcão. `simulate_only` orienta para ferramentas de cálculo e distingue consulta de parâmetros de cálculo; `request_facilitation` exige confirmação de gravação no servidor antes de continuar no Balcão. As restantes finalidades orientam para parceiros, financiamento, preparação da oportunidade ou dossier/plano, conforme a escolha. Pendências continuam a ter prioridade. Alteração de apresentação verificada por TypeScript e lint; nenhuma escrita ativa ou submissão. + +# Resumo com nomes/valores e ação direta de cálculo + +Os campos verificados são apresentados em pares de nome/valor, com texto legível, sem listas vazias. Valores pessoais não são repetidos: o resumo identifica que o conteúdo permanece disponível no campo original. Não envia nem publica esses valores. O resumo tem foco e deslocação própria, incluindo em ecrã móvel. + +Para simulação, uma ação direta abre as ferramentas e a consulta fiscal sem alterar o modo escolhido. Se o utilizador já escolheu o modo personalizado, a ação calcula explicitamente a operação percentual com a base/taxa/redução declaradas; não calcula imposto legal. A consulta sem parâmetros aprovados identifica componente, período e âmbito ausentes e conserva o resultado indeterminado. Não inventa um catálogo de parâmetros obrigatórios nem preenche lacunas com zero. + +QA de navegador: nomes e valores não vazios, correção e recuperação do rascunho, ação direta até ao resultado personalizado e consulta fiscal indeterminada sem mudança de modo. Evidências privadas: `review-summary-browser.json`, `summary-values-approved.json` e capturas `review-summary-*.png`. Nenhum pedido submetido nem alteração na base ativa. TypeScript e lint verificados. + +# Ações exatas do formulário e compilação servida + +Página do formulário: `/simulador-fiscal`; `portal/services.tsx` monta `SimulationForm`. «Validar este rascunho» chama `validateFinalReview`, uma verificação local; não é a ação de abertura/cálculo. A ação anterior estava condicionada a um resumo sem pendências e podia regressar silenciosamente quando não encontrava a etapa fiscal. Agora «Abrir cálculo» e «Consultar parâmetros fiscais» estão acessíveis independentemente das pendências da revisão, com eventos separados, destino focável e erro visível se a etapa não existir. Não mudam finalidade nem pressupostos; a consulta de parâmetros não converte o modo do rascunho. O cálculo continua a exigir execução explícita na ferramenta aberta. + +GET ativo em **16:00:34 UTC** devolveu HTTP 200 e os assets atuais, incluindo `services-r6EkfdY-.js`, sem `public/hot`; evidência privada `exact-actions-active-assets.json`. Não foi possível observar o cache ou o clique do separador real do utilizador. Esta constatação valida o conteúdo servido, não certifica o estado da sessão do utilizador. + +QA desde o ecrã de revisão: validação, clique em «Abrir cálculo», foco em `draft-tool-calculation`, execução explícita, resposta HTTP e resultado concluído; testado em 1440 e 390. Consulta fiscal desde a revisão também aberta, sem alteração de modo e com parâmetros ausentes/resultado indeterminado. Provas `review-summary-browser.json` e `summary-values-approved.json`; TypeScript/lint passaram. Nenhum dossier criado nem pedido submetido na base ativa durante este diagnóstico. + +# Confirmação e consolidação das correções + +Em 8 de outubro, o utilizador pediu o registo da confirmação e a consolidação das correções num commit. Fica confirmado o ensaio QA desde a revisão até à abertura da ferramenta e ao resultado, em computador e móvel, e a disponibilização da compilação atual pelo servidor. A consulta fiscal preserva o modo escolhido e mantém lacunas indeterminadas. A sessão/cache do navegador real do utilizador continua sem observação direta; não se declara por isso um percurso ativo concluído. Não foram criados dossiers ou submetidos pedidos ativos durante estas correções. + +O commit reúne o formulário, a consulta fiscal, o tratamento de erros API, os testes e estes registos. As evidências privadas não entram no commit. A retoma do backlog V2 mantém separadas as pendências de ClamD real, identidade do operador, fontes/contactos institucionais e primeiro pedido real com confirmação do investidor; nenhum sucesso QA resolve automaticamente essas pendências. diff --git a/resources/js/components/simulation-fiscal-status.tsx b/resources/js/components/simulation-fiscal-status.tsx index 81208edb..7a4797db 100644 --- a/resources/js/components/simulation-fiscal-status.tsx +++ b/resources/js/components/simulation-fiscal-status.tsx @@ -198,7 +198,12 @@ export function SimulationFiscalStatus({ ) : parameters.length === 0 ? (
Indeterminado — nenhum parâmetro publicado - aplicável. + aplicável. Faltam parâmetros aprovados para{' '} + {code}, no período {periodStart} a{' '} + {periodEnd} e no âmbito indicado. A consulta + não identifica um conjunto obrigatório de + parâmetros; não é possível determinar o + imposto nem substituir as lacunas por zero.
) : (+ O servidor não confirmou a gravação. Os dados + preenchidos foram preservados. Corrija os campos + indicados: +
+{reviewStatus}
++ Verificação local dos campos e regras disponíveis. Não + calcula valores nem envia um pedido HTTP de validação. A + gravação automática do rascunho tem um estado + independente. Não confirma viabilidade, elegibilidade ou + aprovação. +
+ {reviewDetails.checked.length > 0 && ( ++ Campos pendentes e inconsistências:{' '} + {reviewDetails.pending.length}. +
+ {reviewDetails.pending.length > 0 && ( ++ Próxima ação:{' '} + {reviewDetails.pending.length + ? 'corrija os campos indicados e volte a validar.' + : draft.purpose === 'simulate_only' && + draft.fiscal_scenario_mode === 'custom_planning' + ? 'abra a etapa fiscal e use “Validar e calcular no servidor” para obter um resultado separado.' + : draft.purpose === 'simulate_only' + ? 'use a ferramenta de cálculo adequada aos resultados que pretende obter. A consulta de parâmetros fiscais não calcula impostos; para um cenário percentual hipotético, selecione o modo de planeamento personalizado na etapa fiscal.' + : draft.purpose === 'request_facilitation' + ? 'confirme que o rascunho está guardado no servidor e continue no Balcão para preparar o pedido de apoio.' + : draft.purpose === 'seek_partner' + ? 'confirme a gravação do rascunho e explore parceiros na Bolsa de Parcerias, preservando o contexto do projecto.' + : draft.purpose === 'seek_investor' + ? 'confirme a gravação do rascunho e reveja o financiamento e a informação a apresentar a potenciais investidores.' + : draft.purpose === 'present_opportunity' + ? 'confirme a gravação e reveja os dados e a autorização de divulgação antes de preparar a oportunidade.' + : 'confirme a gravação e continue a preparar o dossier e o plano do seu investimento.'}{' '} + Nenhum pedido foi submetido. +
+ {draft.purpose === 'simulate_only' && + !reviewDetails.pending.length && ( ++ {draft.fiscal_scenario_mode === + 'custom_planning' + ? 'Modo personalizado escolhido: calcula uma operação percentual com a base, taxa e redução que introduziu. Não calcula um imposto legal.' + : 'As ferramentas financeiras calculam prestações, ponto de equilíbrio e necessidades de financiamento com os seus pressupostos. A consulta fiscal identifica parâmetros e fontes; se faltarem parâmetros, o resultado fiscal permanece indeterminado. O modo escolhido será preservado.'} +
++ Abrir cálculo apresenta as ferramentas financeiras e, se + já escolhido, o cálculo percentual personalizado. + Consultar parâmetros fiscais apresenta fontes e lacunas; + não determina imposto devido. +
+{toolError}
} +
Os pressupostos não identificativos podem ser guardados de forma
cifrada para recuperar o rascunho. Os dados pessoais e contactos
diff --git a/resources/js/lib/simulation-api.ts b/resources/js/lib/simulation-api.ts
index 8e76d14d..e323aeb6 100644
--- a/resources/js/lib/simulation-api.ts
+++ b/resources/js/lib/simulation-api.ts
@@ -29,6 +29,22 @@ export function simulationApiErrorMessage(value: unknown): string | undefined {
: value.message;
}
+/** Keep snapshot field errors attached to their original form fields. */
+export function simulationApiFieldErrors(
+ value: unknown,
+): Record