299 lines
14 KiB
TypeScript
299 lines
14 KiB
TypeScript
import type { AdvanceFiscalPeriod } from '@/lib/irpc-ppc-obligation';
|
|
import { SimulationIrpcPecCorrection } from './simulation-irpc-pec-correction';
|
|
import { SimulationIrpcPecPlan } from './simulation-irpc-pec-plan';
|
|
import {
|
|
newPecObligation,
|
|
calculatePecObligation,
|
|
type PecObligation,
|
|
} from '@/lib/irpc-pec-obligation';
|
|
import { fractionPresentation } from '@/lib/fiscal-rational';
|
|
import type { AnnualBook } from '@/lib/irpc-annual-settlement';
|
|
export function SimulationIrpcPecObligation({
|
|
book,
|
|
period,
|
|
onChange,
|
|
}: {
|
|
book: AnnualBook;
|
|
period?: AdvanceFiscalPeriod;
|
|
onChange: (p: PecObligation) => void;
|
|
}) {
|
|
const p = book.pecObligation;
|
|
if (!p)
|
|
return (
|
|
<section className="rounded border p-3">
|
|
<h5>Estimativa PEC</h5>
|
|
<p>
|
|
Preparar o total e os meses previstos conserva os
|
|
comprovativos pagos em separado.
|
|
</p>
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
onChange(newPecObligation(book.subjectNuit, book.year))
|
|
}
|
|
>
|
|
Simular PEC
|
|
</button>
|
|
</section>
|
|
);
|
|
const m = calculatePecObligation(
|
|
p,
|
|
book.subjectNuit,
|
|
book.year,
|
|
book.assessment,
|
|
period,
|
|
),
|
|
patch = (changes: Partial<PecObligation>) =>
|
|
onChange({ ...p, ...changes });
|
|
const field = (
|
|
key: Exclude<
|
|
keyof PecObligation,
|
|
'version' | 'scope' | 'plan' | 'correction' | 'lastAmount'
|
|
>,
|
|
label: string,
|
|
) => (
|
|
<label className="block">
|
|
{label}
|
|
<input
|
|
className="mt-1 block w-full rounded border px-3 py-2"
|
|
aria-label={label}
|
|
value={p[key]}
|
|
onChange={(e) => patch({ [key]: e.target.value })}
|
|
/>
|
|
</label>
|
|
);
|
|
return (
|
|
<section
|
|
aria-label="Preparação da estimativa PEC"
|
|
className="rounded border p-3"
|
|
>
|
|
<h5>Estimativa PEC — preparação</h5>
|
|
<label className="block">
|
|
Enquadramento PEC
|
|
<select
|
|
className="mt-1 block w-full rounded border px-3 py-2"
|
|
aria-label="Enquadramento PEC"
|
|
value={p.scope}
|
|
onChange={(e) =>
|
|
patch({
|
|
scope: e.target.value as PecObligation['scope'],
|
|
})
|
|
}
|
|
>
|
|
<option value="">Por confirmar</option>
|
|
<option value="ordinary_resident">
|
|
Residente geral — comercial,industrial ou agrícola,ano
|
|
civil ou anual não civil documentado
|
|
</option>
|
|
<option value="other">
|
|
Outro enquadramento — separado
|
|
</option>
|
|
</select>
|
|
</label>
|
|
{p.scope === 'ordinary_resident' && (
|
|
<>
|
|
{field('subjectNuit', 'NUIT — estimativa PEC')}
|
|
{field('year', 'Exercício — estimativa PEC')}
|
|
{field(
|
|
'activityStartYear',
|
|
'Ano de início efectivo da actividade — PEC',
|
|
)}
|
|
{field(
|
|
'activityReference',
|
|
'Fonte do início de actividade — PEC',
|
|
)}
|
|
{p.activityStartYear !== book.year && (
|
|
<>
|
|
{field('previousYear', 'Exercício anterior — PEC')}
|
|
{field(
|
|
'previousTurnover',
|
|
'Volume de negócios anterior — MZN',
|
|
)}
|
|
{field(
|
|
'turnoverReference',
|
|
'Fonte do volume de negócios — PEC',
|
|
)}
|
|
<SimulationIrpcPecCorrection
|
|
value={p.correction}
|
|
original={p.previousTurnover}
|
|
subjectNuit={p.subjectNuit}
|
|
onChange={(correction) => patch({ correction })}
|
|
/>
|
|
{(m.requiresLastAmount || p.lastAmount) && (
|
|
<details className="rounded border p-3">
|
|
<summary>
|
|
Sem volume anterior — referência PEC dos
|
|
anos anteriores
|
|
</summary>
|
|
<p>
|
|
Indique o último montante PEC já
|
|
determinado, com suporte do mesmo
|
|
titular, ano civil e MZN. Não introduza
|
|
volume de negócios ou somatório de
|
|
pagamentos. A hipótese conserva o valor
|
|
documental sem nova percentagem ou
|
|
segunda dedução de PPC.
|
|
</p>
|
|
{!p.lastAmount ? (
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
patch({
|
|
lastAmount: {
|
|
version: 1,
|
|
subjectNuit:
|
|
p.subjectNuit,
|
|
year: '',
|
|
amount: '',
|
|
reference: '',
|
|
confirmed: '',
|
|
},
|
|
})
|
|
}
|
|
>
|
|
Acrescentar referência PEC anterior
|
|
</button>
|
|
) : (
|
|
<>
|
|
{(
|
|
[
|
|
'subjectNuit',
|
|
'year',
|
|
'amount',
|
|
'reference',
|
|
] as const
|
|
).map((key) => {
|
|
const names = {
|
|
subjectNuit:
|
|
'NUIT do montante PEC anterior',
|
|
year: 'Exercício do último montante PEC',
|
|
amount: 'Último montante PEC já determinado — MZN',
|
|
reference:
|
|
'Fonte e fundamento do último montante PEC',
|
|
};
|
|
return (
|
|
<label
|
|
className="block"
|
|
key={key}
|
|
>
|
|
{names[key]}
|
|
<input
|
|
className="mt-1 block w-full rounded border px-3 py-2"
|
|
aria-label={
|
|
names[key]
|
|
}
|
|
value={
|
|
p.lastAmount![
|
|
key
|
|
]
|
|
}
|
|
onChange={(e) =>
|
|
patch({
|
|
lastAmount:
|
|
{
|
|
...p.lastAmount!,
|
|
[key]: e
|
|
.target
|
|
.value,
|
|
confirmed:
|
|
'',
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
);
|
|
})}
|
|
<label className="block">
|
|
<input
|
|
type="checkbox"
|
|
checked={
|
|
p.lastAmount
|
|
.confirmed === 'yes'
|
|
}
|
|
onChange={(e) =>
|
|
patch({
|
|
lastAmount: {
|
|
...p.lastAmount!,
|
|
confirmed: e
|
|
.target
|
|
.checked
|
|
? 'yes'
|
|
: '',
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
Conferi no suporte que é o
|
|
último montante PEC aplicável a
|
|
esta hipótese
|
|
</label>
|
|
<p>
|
|
Alterar a referência exige nova
|
|
conferência. Guardar conserva o
|
|
original e o histórico; não
|
|
certifica a situação fiscal.
|
|
</p>
|
|
</>
|
|
)}
|
|
</details>
|
|
)}
|
|
{field(
|
|
'previousPpcPaid',
|
|
'PPC efectivamente pagos no ano anterior — MZN',
|
|
)}
|
|
{field(
|
|
'ppcReference',
|
|
'Fonte dos PPC anteriores — PEC',
|
|
)}
|
|
</>
|
|
)}
|
|
</>
|
|
)}
|
|
{m.pending.length ? (
|
|
<p role="status">{m.pending.join(' ')}</p>
|
|
) : m.notApplicable ? (
|
|
<p>Não aplicável no ano de início da actividade29(4).</p>
|
|
) : (
|
|
<>
|
|
<p>
|
|
Total estimado: {fractionPresentation(m.total!).decimal}{' '}
|
|
MZN.
|
|
</p>
|
|
<ul>
|
|
{m.months.map((month) => (
|
|
<li key={month}>{month}</li>
|
|
))}
|
|
</ul>
|
|
</>
|
|
)}
|
|
{m.ppcExcess && (
|
|
<p role="status">
|
|
Os PPC anteriores cobrem a base limitada desta hipótese.
|
|
Estimativa PEC: 0 MZN;diferença documental:{' '}
|
|
{fractionPresentation(m.ppcExcess).decimal} MZN. Esta
|
|
diferença não cria reembolso,crédito ou dedução anual.
|
|
</p>
|
|
)}
|
|
<SimulationIrpcPecPlan
|
|
plan={p.plan}
|
|
total={m.total}
|
|
notApplicable={m.notApplicable}
|
|
year={book.year}
|
|
period={period}
|
|
onChange={(plan) => patch({ plan })}
|
|
/>
|
|
<p>
|
|
Guardar o rascunho conserva esta preparação. Calcular o fecho
|
|
anual inclui-a no relatório. Não regista pagamentos,cria
|
|
deduções ou executa guias. Os comprovativos efectivos permanecem
|
|
no detalhe PEC existente.
|
|
</p>
|
|
<details>
|
|
<summary>Fonte e limites PEC</summary>
|
|
<p>{m.source}</p>
|
|
</details>
|
|
</section>
|
|
);
|
|
}
|