240 lines
10 KiB
TypeScript
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>
|
|
);
|
|
}
|