Files
Investidor-V2/resources/js/components/simulation-irpc-pec-obligation.tsx
T

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>
);
}