Files
Investidor-V2/resources/js/components/simulation-foreign-operations.tsx
T

339 lines
16 KiB
TypeScript

import { useState } from 'react';
import {
foreignOperationBook,
foreignOperationCurrent,
foreignOperationReportRows,
foreignOperationSource,
foreignSources,
foreignEvents,
newForeignOperation,
recordForeignOperations,
saveForeignOperationBook,
switchForeignSource,
type ForeignOperationBook,
type ForeignOperationRow,
} from '@/lib/iva-foreign-operations';
export function SimulationForeignOperations({
draft,
onChange,
}: {
draft: Record<string, unknown>;
onChange: (field: string, value: string) => void;
}) {
const [error, setError] = useState('');
let book: ForeignOperationBook;
try {
book = foreignOperationBook(draft);
} catch (e) {
return <p role="alert">{String(e)}</p>;
}
const save = (next: ForeignOperationBook) => {
try {
onChange(
'modelo_a_snapshot',
saveForeignOperationBook(draft, next),
);
setError('');
} catch (e) {
setError(String(e));
}
};
const change = (id: string, patch: Partial<ForeignOperationRow>) =>
save({
...book,
rows: book.rows.map((r) => (r.id === id ? { ...r, ...patch } : r)),
});
return (
<details className="rounded border p-3">
<summary>
Operações no estrangeiro — localização e enquadramento
</summary>
<p>
Reutilize uma localização já guardada nesta oportunidade. Fora
do território não significa isenção,IVA zero ou dedução
concedida. Não é necessário repetir os factos/documentos da
localização.
</p>
<p>{foreignOperationSource}</p>
{error && <p role="alert">{error}</p>}
<button
type="button"
onClick={() =>
save({
...book,
rows: [
...book.rows,
newForeignOperation(crypto.randomUUID()),
],
})
}
>
Acrescentar análise de operação no estrangeiro
</button>
{book.rows.map((row) => {
let sources: ReturnType<typeof foreignSources> = [],
events: ReturnType<typeof foreignEvents> = [];
try {
sources = foreignSources(draft, row.sourceKind);
events = foreignEvents(draft);
} catch {
/* Existing readers retain corrupt originals. */
}
const source = sources.find((s) => s.id === row.sourceRowId);
return (
<details key={row.id}>
<summary>
{source?.description || 'Operação por associar'} —{' '}
{source?.period || 'período da origem'}
</summary>
<label>
Origem da localização
<select
value={row.sourceKind}
onChange={(e) =>
change(
row.id,
switchForeignSource(
row,
e.target
.value as ForeignOperationRow['sourceKind'],
),
)
}
>
<option value="">Por indicar</option>
<option value="goods">Bens corpóreos</option>
<option value="services">
Serviços e transporte
</option>
<option value="listed">
Serviços enumerados não digitais
</option>
<option value="digital">
Bens e serviços digitais
</option>
</select>
</label>
<label>
Resultado de localização existente
<select
value={row.sourceRowId}
onChange={(e) =>
change(
row.id,
switchForeignSource(
row,
row.sourceKind,
e.target.value,
),
)
}
>
<option value="">Escolher operação</option>
{sources.map((s) => (
<option key={s.id} value={s.id}>
{s.description} — {s.period} —{' '}
{s.territory ?? 'Indeterminado'}
{s.current ? '' : ' — histórico'}
</option>
))}
</select>
</label>
{row.sourceKind && !sources.length && (
<p>
Prepare a localização nas secções de
bens/serviços existentes desta oportunidade.
Nenhuma localização é presumida ou copiada de
outro projecto.
</p>
)}
{source && (
<p>
Operação: {source.operationRef}. Âmbito:{' '}
{source.scope}. {source.reason}
</p>
)}
{source?.territory === 'partial' && (
<label>
Parcela deste trajecto analisada
<select
value={row.territorialPart}
onChange={(e) =>
change(row.id, {
territorialPart: e.target
.value as ForeignOperationRow['territorialPart'],
})
}
>
<option value="">Delimitar parcela</option>
<option value="outside">
Parcela fora do território nacional
</option>
<option value="national">
Parcela nacional
</option>
</select>
</label>
)}
{source && source.territory !== 'national' && (
<>
<label>
Evento já guardado da mesma operação,quando
aplicável
<select
value={row.eventRowId}
onChange={(e) =>
change(row.id, {
eventRowId: e.target.value,
})
}
>
<option value="">
Sem associação necessária nesta
análise territorial
</option>
{events
.filter(
(e) =>
e.operationRef ===
source.operationRef &&
e.period === source.period,
)
.map((e) => (
<option key={e.id} value={e.id}>
{e.description} — {e.period}
{e.current
? ''
: ' — histórico'}
</option>
))}
</select>
</label>
<label>
Seria tributável se efectuada no território
nacional?
<select
value={row.hypotheticalTaxable}
onChange={(e) =>
change(row.id, {
hypotheticalTaxable: e.target
.value as ForeignOperationRow['hypotheticalTaxable'],
})
}
>
<option value="">Por esclarecer</option>
<option value="yes">
Sim,segundo o fundamento
identificado
</option>
<option value="no">
Não,segundo o fundamento
identificado
</option>
</select>
</label>
<label>
Fundamento da hipótese interna e exclusões
aplicáveis
<input
value={row.hypotheticalRef}
onChange={(e) =>
change(row.id, {
hypotheticalRef: e.target.value,
})
}
/>
</label>
{row.hypotheticalTaxable === 'yes' && (
<label>
Existe exclusão19(2) aplicável:17-A ou
pagamentos15(6)c?
<select
value={row.excluded19_2}
onChange={(e) =>
change(row.id, {
excluded19_2: e.target
.value as ForeignOperationRow['excluded19_2'],
})
}
>
<option value="">
Por esclarecer
</option>
<option value="yes">Sim</option>
<option value="no">Não</option>
</select>
</label>
)}
</>
)}
<label>
Âmbito da análise,conjunto/parcela e período
<input
value={row.scope}
onChange={(e) =>
change(row.id, { scope: e.target.value })
}
/>
</label>
<label>
Factos ou pressupostos expressos
<input
value={row.evidence}
onChange={(e) =>
change(row.id, { evidence: e.target.value })
}
/>
</label>
<p>
Trocar origem conserva fundamentos ocultos;reveja as
confirmações. Nenhuma dedução é lançada por esta
análise.
</p>
</details>
);
})}
{!!book.rows.length && (
<button
type="button"
onClick={() => {
try {
save(recordForeignOperations(draft, book));
} catch (e) {
setError(String(e));
}
}}
>
Analisar operação estrangeira e guardar versão
</button>
)}
{book.result && (
<>
<p role="status">
{foreignOperationCurrent(draft, book)
? 'Análise corresponde às entradas e origens guardadas.'
: 'Entradas ou origens alteradas;resultado histórico conservado. Reveja apenas o delta afectado.'}{' '}
{book.history?.length ?? 0} versões anteriores.Sem
dedução/IVA calculados.
</p>
<dl>
{foreignOperationReportRows(draft).map(
([, label, value, origin], i) => (
<div key={i}>
<dt>{label}</dt>
<dd>
{value}
<small className="block">
{origin}
</small>
</dd>
</div>
),
)}
</dl>
</>
)}
</details>
);
}