221 lines
9.0 KiB
TypeScript
221 lines
9.0 KiB
TypeScript
import { inputText } from '../lib/input-text.ts';
|
|
import {
|
|
PreparationSummary,
|
|
type Preparation,
|
|
} from '@/components/private-investment-preparation';
|
|
import { Link } from '@inertiajs/react';
|
|
|
|
type Snapshot = {
|
|
preparation?: Preparation | null;
|
|
context_revision: number;
|
|
path?: {
|
|
definition_version: number;
|
|
steps: Array<{
|
|
code: string;
|
|
title: string;
|
|
applicability: string;
|
|
reason: string;
|
|
state: string;
|
|
context_review_required?: boolean;
|
|
}>;
|
|
};
|
|
zone?: {
|
|
title: string;
|
|
href: string;
|
|
version: number | string;
|
|
fields?: Record<string, string>;
|
|
analysis?: {
|
|
conditions?: Array<{
|
|
id: string;
|
|
label: string;
|
|
knowledge: string;
|
|
source_reference?: string;
|
|
valid_from?: string;
|
|
valid_until?: string;
|
|
}>;
|
|
source?: {
|
|
title: string;
|
|
url: string;
|
|
diploma?: string;
|
|
article?: string;
|
|
valid_from?: string;
|
|
valid_until?: string;
|
|
} | null;
|
|
};
|
|
} | null;
|
|
fields?: Record<string, string>;
|
|
};
|
|
export function InvestmentContextAssessment({
|
|
raw,
|
|
contextId,
|
|
}: {
|
|
raw: unknown;
|
|
contextId?: string | null;
|
|
}) {
|
|
let snapshot: Snapshot | null = null;
|
|
try {
|
|
const value = JSON.parse(inputText(raw ?? ''));
|
|
if (value.version === 1) snapshot = value;
|
|
} catch {
|
|
/* Missing context remains explicit. */
|
|
}
|
|
if (!snapshot) return null;
|
|
const fields = snapshot.fields ?? {};
|
|
const zone = snapshot.zone;
|
|
const steps = (snapshot.path?.steps ?? []).filter(
|
|
(step) => !!step.title?.trim(),
|
|
);
|
|
if (
|
|
!zone &&
|
|
!fields.investor_origin &&
|
|
!fields.tax_residency_country &&
|
|
!snapshot.preparation?.enabled
|
|
)
|
|
return null;
|
|
const regime = zone?.fields?.investment_regime ?? fields.investment_regime;
|
|
const names: Record<string, string> = {
|
|
zee: 'ZEE',
|
|
zfi: 'ZFI',
|
|
industrial_park: 'Parque industrial',
|
|
};
|
|
return (
|
|
<section
|
|
className="space-y-2 rounded border border-amber-400 p-3"
|
|
aria-label="Aplicabilidade ao investimento"
|
|
>
|
|
<h3 className="font-semibold">Condições do investimento</h3>
|
|
{(fields.investor_origin || fields.tax_residency_country) && (
|
|
<p>
|
|
Origem do investidor:{' '}
|
|
{{
|
|
national: 'nacional',
|
|
foreign: 'estrangeiro',
|
|
mixed: 'misto',
|
|
}[fields.investor_origin] ?? 'informação em falta'}
|
|
. Residência fiscal declarada:{' '}
|
|
{fields.tax_residency_country || 'Por preencher'}.
|
|
</p>
|
|
)}
|
|
{zone ? (
|
|
<>
|
|
<p>
|
|
<strong>
|
|
Potencialmente aplicável — análise específica de{' '}
|
|
{names[regime ?? ''] ?? 'zona seleccionada'}.
|
|
</strong>{' '}
|
|
<Link className="underline" href={zone.href}>
|
|
{zone.title} · consultar condições
|
|
</Link>
|
|
.
|
|
</p>
|
|
<p>
|
|
A selecção identifica a referência consultada; não
|
|
confirma o reconhecimento da entidade, actividade
|
|
autorizada, licença ou acesso a benefícios. Consulte as
|
|
condições documentadas na ficha e reúna a autorização ou
|
|
evidência correspondente no dossier.
|
|
</p>
|
|
{zone.analysis?.source && (
|
|
<p>
|
|
Fundamento cadastrado:{' '}
|
|
<a
|
|
className="underline"
|
|
href={zone.analysis.source.url}
|
|
>
|
|
{zone.analysis.source.diploma ||
|
|
zone.analysis.source.title}{' '}
|
|
{zone.analysis.source.article}
|
|
</a>
|
|
. Período cadastrado:{' '}
|
|
{zone.analysis.source.valid_from ||
|
|
'início por indicar'}{' '}
|
|
a{' '}
|
|
{zone.analysis.source.valid_until ||
|
|
'sem termo indicado'}
|
|
. A cobertura do investimento exige correspondência
|
|
com estas condições.
|
|
</p>
|
|
)}
|
|
{zone.analysis?.conditions?.length ? (
|
|
<ul className="list-disc pl-5">
|
|
{zone.analysis.conditions.map((condition) => (
|
|
<li key={condition.id}>
|
|
<strong>{condition.label}</strong>:{' '}
|
|
{condition.knowledge === 'documented'
|
|
? 'condição documentada; cumprimento pelo investimento por confirmar'
|
|
: condition.knowledge === 'disputed'
|
|
? 'condição com informação divergente'
|
|
: 'informação em falta'}
|
|
.{' '}
|
|
{condition.source_reference && (
|
|
<>
|
|
Fundamento:{' '}
|
|
{condition.source_reference}.
|
|
</>
|
|
)}{' '}
|
|
{condition.valid_from && (
|
|
<>Desde {condition.valid_from}.</>
|
|
)}{' '}
|
|
{condition.valid_until && (
|
|
<>Até {condition.valid_until}.</>
|
|
)}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
) : (
|
|
<p>
|
|
Condições específicas: informação estruturada em
|
|
falta nesta referência. A ficha e os documentos
|
|
continuam consultáveis; não se presume cumprimento.
|
|
</p>
|
|
)}
|
|
<p role="status">
|
|
Os benefícios desta zona ainda não estão disponíveis no
|
|
simulador. O cenário geral disponível não inclui
|
|
benefícios especiais nem apuramento fiscal final.
|
|
</p>
|
|
</>
|
|
) : null}
|
|
{!!steps.length && (
|
|
<details>
|
|
<summary>Etapas a preparar</summary>
|
|
<ul className="list-disc pl-5">
|
|
{steps.map((step) => (
|
|
<li key={step.code}>
|
|
{step.title}:{' '}
|
|
{step.context_review_required
|
|
? 'informação alterada; rever fundamento'
|
|
: step.applicability ===
|
|
'not_needed_for_preparation'
|
|
? 'não aplicável à preparação declarada'
|
|
: step.applicability === 'undetermined'
|
|
? 'informação em falta'
|
|
: ['completed', 'approved'].includes(
|
|
step.state,
|
|
)
|
|
? 'preparação confirmada no percurso; não é decisão fiscal'
|
|
: 'potencialmente aplicável'}
|
|
. {step.reason}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</details>
|
|
)}
|
|
{snapshot.preparation?.enabled && (
|
|
<PreparationSummary
|
|
data={snapshot.preparation}
|
|
caseId={contextId ?? undefined}
|
|
/>
|
|
)}
|
|
{contextId && (
|
|
<Link
|
|
className="underline"
|
|
href={`/investimentos/${contextId}/contexto/editar`}
|
|
>
|
|
Rever dados do investimento
|
|
</Link>
|
|
)}
|
|
</section>
|
|
);
|
|
}
|