Files
Investidor-V2/resources/js/components/simulation-irpc-period-fx.tsx
T

240 lines
10 KiB
TypeScript

import { SimulationFxSelection } from '@/components/simulation-fx-selection';
import { rawNormalFinancialSource, type NormalBook } from '@/lib/irpc-normal';
import {
newNormalPeriodFx,
mapNormalPeriodFx,
type NormalPeriodFxInput,
} from '@/lib/irpc-normal-period-fx';
import { irpcFxSources, irpcFxRow, updateIrpcFx } from '@/lib/irpc-fx';
export function SimulationIrpcPeriodFx({
draft,
book,
save,
}: {
draft: Record<string, unknown>;
book: NormalBook;
save: (b: NormalBook) => void;
}) {
const raw = rawNormalFinancialSource(draft),
i = book.periodsFx;
if (!i)
return (
<button
type="button"
onClick={() =>
save({ ...book, periodsFx: newNormalPeriodFx() })
}
>
Preparar período curto ou plano noutra moeda
</button>
);
const patch = (p: Partial<NormalPeriodFxInput>) =>
save({ ...book, periodsFx: { ...i, ...p } }),
model = mapNormalPeriodFx(draft, i, raw),
sources = irpcFxSources(draft);
const text = (
k:
| 'from'
| 'to'
| 'planStart'
| 'reference'
| 'conversionReference'
| 'mznMapsReference',
label: string,
) => (
<label className="block">
{label}
<input
value={i[k]}
onChange={(e) => patch({ [k]: e.target.value })}
/>
</label>
);
return (
<fieldset
aria-label="Período e moeda L6"
className="space-y-3 rounded border p-3"
>
<legend>Período fiscal e conversão do plano — simulação L6</legend>
<p>
Reutiliza os meses e valores originais do plano. Seleccione
apenas os meses do período documentado;sem anualizar o
resultado. Os mapas,activos e saldos fiscais permanecem emMZN e
exigem reconciliação explícita. A conversão cambial para
simulação usa o mecanismo existente; não confirma
automaticamente a regra fiscal de conversão anual.
</p>
<label className="block">
Tipo de período
<select
value={i.kind}
onChange={(e) =>
patch({
kind: e.target.value as NormalPeriodFxInput['kind'],
})
}
>
<option value="">Por identificar</option>
<option value="annual">Anual documentado — 12meses</option>
<option value="start">Início de actividade — 7(4)a</option>
<option value="cessation">
Cessação de actividade — 7(4)b
</option>
<option value="same_year">
Início e fim de sujeição no mesmo exercício — 7(4)c
</option>
<option value="transition">
Transição para período autorizado/comunicado — 7(4)d
</option>
</select>
</label>
{text('from', 'Início do período fiscal (AAAA-MM-DD)')}
{text('to', 'Fim do período fiscal (AAAA-MM-DD)')}
{text('planStart', 'Primeiro mês civil do plano (AAAA-MM-01)')}
{text(
'reference',
'Suporte do evento,período e correspondência dos meses',
)}
{book.schedules && (
<button
type="button"
onClick={() =>
patch({
from: i.from || book.schedules!.period.from,
to: i.to || book.schedules!.period.to,
reference:
i.reference || book.schedules!.period.reference,
})
}
>
Reutilizar datas e suporte já declarados nos campos vazios
</button>
)}
{text(
'mznMapsReference',
'Reconciliação dos mapas,parcelas,activos e saldos existentes em MZN para este período',
)}
{raw?.currency !== 'MZN' && (
<>
{text(
'conversionReference',
'Pressuposto documentado da conversão mensal para simulação',
)}
{[...new Set(model.rows.map((r) => r.period))].map(
(period) => {
const date = model.rows.find(
(r) => r.period === period,
)?.date,
entry = i.months.find(
(m) => m.period === period,
) ?? { period, currency: raw?.currency ?? '' };
const change = (p: Partial<typeof entry>) =>
patch({
months: [
...i.months.filter(
(m) => m.period !== period,
),
{ ...entry, ...p },
],
});
return (
<fieldset
key={period}
aria-label={'Câmbio do mês ' + period}
className="rounded border p-2"
>
<legend>
Mês{period} — {date} — {raw?.currency}
</legend>
<label>
Reutilizar selecção cambial existente
<select
value={entry.fxLink?.id ?? ''}
onChange={(e) => {
const s = sources.find(
(s) =>
s.id === e.target.value,
);
if (s)
change({
currency:
raw?.currency ?? '',
fxSelection:
s.selection,
fxLink: {
id: s.id,
fingerprint:
s.fingerprint,
},
});
}}
>
<option value="">
Seleccione uma origem
documentada
</option>
{sources.map((s) => (
<option value={s.id} key={s.id}>
{s.label}
</option>
))}
</select>
</label>
<SimulationFxSelection
row={irpcFxRow(
'normal-' + period,
entry,
)}
onChange={(p) => {
if (p.fxSelection)
change({
...updateIrpcFx(
entry,
p.fxSelection,
),
currency:
raw?.currency ?? '',
});
}}
/>
</fieldset>
);
},
)}
</>
)}
{i.months
.filter((m) => !model.rows.some((r) => r.period === m.period))
.map((m) => (
<p key={m.period}>
Selecção conservada do mês{m.period},fora do período
actual.{' '}
<button
type="button"
onClick={() =>
patch({
months: i.months.filter(
(x) => x.period !== m.period,
),
})
}
>
Retirar selecção do mês{m.period} deste mapa
</button>
</p>
))}
<p>
{model.months}meses;resultado convertido:
{model.source?.accountingProfitBeforeTax ??
'Indeterminado'}{' '}
MZN. {model.pending.join(' | ')}
</p>
<p>
Meses parciais,limites anuais por corresponder e contagem de
perdas41(5) afectam apenas os respectivos casos. Colecta não
equivale ao saldo final a pagar.
</p>
</fieldset>
);
}