diff --git a/AGENTS.md b/AGENTS.md index 900c3c27..92b275cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,11 @@ # Instruções permanentes do projeto InvesteMoz +## Percurso adaptativo — decisão expressa da Tempo, 23/10/2026 + +Apresentar apenas o necessário ao investimento em preparação, com entrada por ideia, oportunidade, sector ou localização, reutilizando informação válida e autorizada da oportunidade, perfil, organização, dossier e fontes anteriores. As etapas são adaptáveis, não seis formulários obrigatórios. Não sobrescrever edições deliberadas; explicar divergências e impactos antes da confirmação. Conservar escolhas ao avançar, regressar, actualizar e autenticar-se. Seleccionar opções únicas e pedir apenas dados em falta ou desactualizados. + +Ocultar campos e acções sem aplicação, conservando explicação breve e histórico; desconhecido não significa não aplicável. Na selecção múltipla, partilhar dados comuns sem perder os requisitos específicos de cada oportunidade. Consulta pública livre; autenticação no momento de manifestar interesse ou iniciar operação privada. Relatórios e exportações devem reflectir o contexto e as etapas efectivamente aplicáveis. O utilizador deve perceber onde está, o que falta e a próxima acção. Aperfeiçoar os componentes existentes por incrementos e registar cobertura na matriz existente; esta instrução não declara concluída a sua implementação transversal. + ## Regras permanentes do InvesteMoz — decisão da Tempo, 12/10/2026 1. O portal InvesteMoz é propriedade da Tempo, Lda. diff --git a/app/Services/InvestorPath.php b/app/Services/InvestorPath.php index 1dfd6b1f..90f86e14 100644 --- a/app/Services/InvestorPath.php +++ b/app/Services/InvestorPath.php @@ -170,7 +170,7 @@ final class InvestorPath 'tools' => ['simulator' => (int) $case->user_id === $actor->id ? '/simulador-fiscal?context='.$id.($case->simulation_id ? '&draft='.$case->simulation_id : '') : null, 'desk' => '/balcao-virtual/dossiers/'.$id, 'guidance' => '/balcao-virtual/dossiers/'.$id.'/orientacao', 'library' => '/documentos?context='.$id, 'opportunities' => '/oportunidades?context='.$id, 'territory' => '/zonas?context='.$id, 'partners' => '/parcerias/painel?context='.$id, - 'land' => (int) $case->user_id === $actor->id ? ($landCase ? '/investidor/terra-duat/'.$landCase->id : '/investidor/terra-duat/novo?context='.$id) : null]]; + 'land' => ($facts['land_needed'] ?? 'unknown') !== 'no' && (int) $case->user_id === $actor->id ? ($landCase ? '/investidor/terra-duat/'.$landCase->id : '/investidor/terra-duat/novo?context='.$id) : null]]; } /** @param array $input */ diff --git a/docs/investmoz/unification/traceability-and-manual.md b/docs/investmoz/unification/traceability-and-manual.md index 0c1b0112..5e6da8c4 100644 --- a/docs/investmoz/unification/traceability-and-manual.md +++ b/docs/investmoz/unification/traceability-and-manual.md @@ -270,8 +270,13 @@ Relatório desta observação: [verificação editorial](../../../outputs/invest ## Matriz executável +Decisão transversal da Tempo, 23/10/2026: percurso adaptativo com entradas por ideia/oportunidade/sector/localização; perguntar uma vez, preservar edições deliberadas e contexto entre ecrãs/autenticação; seleccionar opções únicas; ocultar exigências não aplicáveis sem confundir ausência de informação com dispensa; conservar especificidades na selecção múltipla. Mostrar posição, pendências e próxima acção. Relatórios/exportações seguem a mesma aplicabilidade. Origem: pedido expresso da Tempo nesta data; implementação incremental nos componentes existentes, sem novos aprovadores. + +Incremento de apresentação: o dossier conserva as 19 etapas e o histórico, mas apresenta formulários apenas das etapas com preparação permitida. As restantes têm resumo do fundamento e podem regressar ao rever a decisão. A ferramenta Terra/DUAT deixa de ser proposta quando `land_needed=no`; `unknown` mantém a preparação disponível. Relatórios do plano reúnem requisitos documentais `not_applicable` numa explicação, mantendo requisitos em falta ou indeterminados. Esta alteração não remove obrigações jurídicas nem modifica dados guardados. A aplicação transversal a todos os formulários, entradas e exportações permanece por conferir; não se encerra esse requisito por documentação. + | Menu / ecrã | Componente React | Campos / entidade / tabela | Rota ou API | Perfil / regra | Evidência | | ------------------------------ | ------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------------- | +| Preparação adaptativa / relatório | `investor-path/show`, `investment-requirements`, `project-dossier-report` | Aplicabilidade e contexto existentes; histórico preservado | `/investimentos/{id}`, `/aplicabilidade`; exportações existentes do plano | Tempo, 23/10/2026: ocultar preparação sem aplicação; desconhecido não é dispensa | Incremento QA: `InvestmentCorridorContextTest::test_nonapplicable_land_hides_the_action_and_reopening_recovers_saved_evidence` (18 asserções); relatório 11 testes; types/build; cenário sintético no navegador. Cobertura transversal ainda parcial. | | Início | `PortalInvestidor` | Sectores, oportunidades, recursos publicados | `/`, APIs existentes de homepage | Visitante; contagens do cadastro | `PublicPortalNavigationTest`, navegador | | Catálogo / Educação | `investment/catalogue` | Filtros, educação, pivots, facetas | `/oportunidades`, `/educacao`; `/api/v1/investment/search` | Visitante; filtros em intersecção, montantes com moeda | `InvestmentUnificationTest` | | Cluster / Corredor / Âncora | `portfolio/index`, `portfolio/show` | Dossiers, relações, cadeias e oportunidades | `/clusters`, `/corredores`, `/projectos-ancora`, `/carteira/{id}` | Visitante; dossier publicado; cadeia pública | `InvestmentPortfolioTest`, testes territoriais | diff --git a/resources/js/components/investment-requirements.tsx b/resources/js/components/investment-requirements.tsx index 3ad79af2..7a19ce03 100644 --- a/resources/js/components/investment-requirements.tsx +++ b/resources/js/components/investment-requirements.tsx @@ -2,11 +2,14 @@ import { Link } from '@inertiajs/react'; import type { RequirementsAssessment } from '@/lib/investor-context'; import { card } from '@/pages/investment/shared'; -export default function InvestmentRequirements({assessment, contextId}: {assessment?: RequirementsAssessment | null; contextId: string}) { +export default function InvestmentRequirements({assessment, contextId, excludedSteps = []}: {assessment?: RequirementsAssessment | null; contextId: string; excludedSteps?: string[]}) { if (!assessment?.requirements.length) return null; const labels: Record = {selected:'Localização escolhida; direito não inferido',missing:'Informação em falta',conditional:'Conforme as condições do projecto',declared:'Actividades declaradas; enquadrar modalidade',undetermined:'Procedimento específico por determinar'}; const groups = new Map(); - for (const row of assessment.requirements) groups.set(row.opportunity_key,[...(groups.get(row.opportunity_key)??[]),row]); + for (const row of assessment.requirements) { + if (excludedSteps.includes(row.step)) continue; + groups.set(row.opportunity_key,[...(groups.get(row.opportunity_key)??[]),row]); + } return

Requisitos por oportunidade e contexto

{assessment.fiscal_notice}

{[...groups.entries()].map(([key, rows])=>
{rows[0].opportunity_title} · {rows.length} aspectos a conferir{rows.map(r=>
diff --git a/resources/js/lib/project-dossier-report.ts b/resources/js/lib/project-dossier-report.ts index 9e25045e..95e40b8c 100644 --- a/resources/js/lib/project-dossier-report.ts +++ b/resources/js/lib/project-dossier-report.ts @@ -316,7 +316,15 @@ function makeSections( preparation.calculation_notice, preparation.notice, ); - for (const requirement of preparation.requirements ?? []) + const omitted = (preparation.requirements ?? []).filter( + (requirement: { state: string }) => requirement.state === 'not_applicable', + ); + if (omitted.length) + section?.paragraphs.push( + `Não exigido neste contexto: ${omitted.map((requirement: { label: string; reason: string }) => `${requirement.label} (${requirement.reason})`).join('; ')}.`, + ); + for (const requirement of preparation.requirements ?? []) { + if (requirement.state === 'not_applicable') continue; section?.rows.push({ field: requirement.label, value: @@ -331,6 +339,7 @@ function makeSections( classification: 'Preparação informativa — simulação, sem submissão à Administração', }); + } } if (zone?.href) section?.rows.push({ diff --git a/resources/js/pages/investor-path/show.tsx b/resources/js/pages/investor-path/show.tsx index fbad250a..16842ad3 100644 --- a/resources/js/pages/investor-path/show.tsx +++ b/resources/js/pages/investor-path/show.tsx @@ -531,7 +531,7 @@ export default function InvestmentPath(path: Path) { /> )} {!!path.investment_context?.opportunity_choices?.length && } - + !step.preparation_allowed).map((step) => step.code)}/> {!!path.content_sources?.length && (
Próxima acção {path.next ? ( - {path.next.action}: {path.next.code} · {path.next.title} + {path.next.action}: {path.next.title} ) : (

Reveja as pendências e o acompanhamento.

)}

Pode preparar etapas independentes enquanto aguarda - informação. Percurso v{path.definition_version}; os outros - roteiros mantêm a numeração original. + informação. As etapas abaixo adaptam-se às suas escolhas.