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

530 lines
24 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { inputText } from '../lib/input-text.ts';
import { useState } from 'react';
import {
minerBook,
minerCurrent,
minerReportRows,
minerSource,
minerTreatments,
minerCommon,
minerVehicle,
minerReturn,
minerNeedsDeadlineExtension,
minerNeedsStayException,
newMiner,
recordMiners,
saveMinerBook,
type MinerBook,
type MinerRow,
} from '@/lib/iva-miners';
export function SimulationMiners({
draft,
onChange,
}: {
draft: Record<string, unknown>;
onChange: (field: string, value: string) => void;
}) {
const [error, setError] = useState('');
let book: MinerBook;
try {
book = minerBook(draft);
} catch (e) {
return <p role="alert">{String(e)}</p>;
}
const save = (next: MinerBook) => {
try {
onChange('modelo_a_snapshot', saveMinerBook(draft, next));
setError('');
} catch (e) {
setError(String(e));
}
};
const change = (id: string, patch: Partial<MinerRow>) =>
save({
...book,
rows: book.rows.map((r) => (r.id === id ? { ...r, ...patch } : r)),
});
return (
<details className="rounded border p-3">
<summary>
Importações dos mineiros — regime da África do Sul (P059)
</summary>
<p>
Lei n.º2/2011,artigos1–4:página1 doPDF;artigo5:página2/p110-(8).
O exemplar reúne vários diplomas;«Lei do Voluntariado» é o nome
do ficheiro original de uma das ligações,não a base deste
benefício.
Regulamento:Decreto3/2011,artigos1–8,páginas2–3/p152–153.
</p>
<p>
Prepare apenas o percurso dos bens desta importação. A redução
de50% pertence ao veículo separado da bagagem,não a todas as
importações dos mineiros. O simulador não concede
autorizações,nem emite declaração aduaneira. Importação
temporária em férias tem licença/prazos próprios;use o percurso
aduaneiro existente,não a transforme em isenção definitiva.
</p>
{error && <p role="alert">{error}</p>}
<button
type="button"
onClick={() => {
const next = newMiner(
crypto.randomUUID(),
inputText(draft.currency ?? ''),
);
const candidates = book.rows.filter(
(r) =>
r.beneficiary &&
r.contractRef &&
r.origin === next.origin,
);
const keys = new Set(
candidates.map(
(r) => r.beneficiary + '\u0000' + r.contractRef,
),
);
if (keys.size === 1) {
const source = candidates[0];
next.beneficiary = source.beneficiary;
next.contractRef = source.contractRef;
for (const k of [
'national',
'rsa',
'contract',
] as const)
next.conditions[k] = source.conditions[k];
}
save({ ...book, rows: [...book.rows, next] });
}}
>
Acrescentar importação de mineiro
</button>
{book.rows.map((row) => {
const rule = minerTreatments.find(
(t) => t.id === row.treatment,
);
const text = (
field: Exclude<keyof MinerRow, 'conditions'>,
label: string,
type = 'text',
) => (
<label key={field} className="block">
{label}
<input
type={type}
value={row[field]}
onChange={(e) =>
change(row.id, { [field]: e.target.value })
}
/>
</label>
);
const choice = (
key: keyof MinerRow['conditions'],
label: string,
) => (
<label key={key} className="block">
{label}
<select
value={row.conditions[key] ?? ''}
onChange={(e) =>
change(row.id, {
conditions: {
...row.conditions,
[key]: e.target.value,
},
})
}
>
<option value="">Por esclarecer</option>
<option value="yes">
Sim,segundo factos ou pressuposto identificado
</option>
<option value="no">Não</option>
</select>
</label>
);
return (
<details key={row.id}>
<summary>
{row.description ||
'Importação de mineiro por preparar'}{' '}
— {row.period || 'período por indicar'}
</summary>
<label>
Percurso dos bens
<select
value={row.treatment}
onChange={(e) =>
change(row.id, {
treatment: e.target.value,
conditions: Object.fromEntries(
minerCommon.map(([k]) => [
k,
row.conditions[k],
]),
),
})
}
>
<option value="">Escolher percurso</option>
{minerTreatments.map((t) => (
<option key={t.id} value={t.id}>
{t.label}
</option>
))}
</select>
</label>
{text('description', 'Bens desta importação')}
{text('beneficiary', 'Mineiro beneficiário originário')}
{text(
'contractRef',
'Contrato e referência do visto de trabalho',
)}
{text('period', 'Período da importação', 'month')}
{text(
'importDate',
'Data da importação ou previsão',
'date',
)}
<label>
Natureza dos dados
<select
value={row.origin}
onChange={(e) =>
change(row.id, {
origin: e.target
.value as MinerRow['origin'],
})
}
>
<option value="projected">
Pressupostos de projecção
</option>
<option value="effective">
Factos efectivos declarados
</option>
</select>
</label>
{text(
'documentRef',
'Documento disponível ou previsão',
)}
{text(
'documentDate',
'Data do documento ou previsão',
'date',
)}
{text(
'scope',
'Âmbito:bens,operação,período e condições',
)}
{text('evidence', 'Factos ou pressupostos expressos')}
<label>
Titular do direito
<select
value={row.rightHolder}
onChange={(e) =>
change(row.id, {
rightHolder: e.target
.value as MinerRow['rightHolder'],
})
}
>
<option value="">Por indicar</option>
<option value="miner">Mineiro</option>
<option value="heir">
Herdeiro legal,direito não usado
</option>
</select>
</label>
{minerCommon.map(([k, label]) => choice(k, label))}
{rule?.conditions.map(([k, label]) => choice(k, label))}
{row.rightHolder === 'heir' && (
<>
{text(
'heirRef',
'Herdeiro e fundamento da transmissão do direito',
)}
{text('deathDate', 'Data do óbito', 'date')}
{text(
'requestDate',
'Data do requerimento',
'date',
)}
{choice(
'heir',
'Qualidade de herdeiro legal identificada',
)}
{choice(
'unusedRight',
'Direito não usado pelo beneficiário originário',
)}
{choice(
'acquiredAlive',
'Bens adquiridos pelo mineiro em vida',
)}
</>
)}
{['baggage', 'return_baggage', 'monthly'].includes(
row.treatment,
) && (
<label>
Via dos bens
<select
value={row.route}
onChange={(e) =>
change(row.id, {
route: e.target
.value as MinerRow['route'],
})
}
>
<option value="">Por indicar</option>
<option value="accompanied">
Acompanhados pelo mineiro
</option>
<option value="company">
Empresa transportadora/distribuidora
</option>
</select>
</label>
)}
{text(
'customsRef',
'Referência aduaneira aplicável ou pressuposto da projecção',
)}
{text(
'customsScope',
'Âmbito do enquadramento aduaneiro nesta importação',
)}
{['monthly', 'accumulated'].includes(row.treatment) && (
<>
{text('value', 'Valor desta remessa emMZN')}
{text(
'periodTotal',
'Total do âmbito mensal/acumulado,incluindo esta e outras remessas',
)}
{text(
'quotaRef',
'Registo completo ou pressuposto do saldo,incluindo fora do dossier',
)}
<p>
Cobertura dos exemplares:15.000MZN por mês.
Revisão do limite2(5) não é presumida. Não
misturar saldos mensais com meses já
acumulados.
</p>
</>
)}
{row.treatment === 'accumulated' && (
<>
{text(
'accumulationStart',
'Primeiro mês acumulado',
'month',
)}
{text(
'accumulationMonths',
'Número de meses acumulados:1a6',
)}
</>
)}
{row.treatment === 'appliance' &&
text(
'kind',
'Tipo de electrodoméstico para o limite anual',
)}
{minerVehicle(row.treatment) && (
<>
<label>
Direito de veículo identificado
<select
value={row.kind}
onChange={(e) =>
change(row.id, {
kind: e.target.value,
})
}
>
<option value="">Por indicar</option>
<option value="vehicle">
Veículo automóvel
</option>
<option value="tractor">
Tractor agrícola e respectivas
alfaias
</option>
</select>
</label>
<label>
Benefício anterior aplicável a este direito
<select
value={row.previousBenefit}
onChange={(e) =>
change(row.id, {
previousBenefit: e.target
.value as MinerRow['previousBenefit'],
})
}
>
<option value="">Por esclarecer</option>
<option value="none">
Nenhum,segundo histórico
identificado
</option>
<option value="known">
Sim,data conhecida
</option>
</select>
</label>
{row.previousBenefit === 'known' &&
text(
'previousBenefitDate',
'Data do benefício anterior aplicável',
'date',
)}
</>
)}
{(row.treatment === 'appliance' ||
minerVehicle(row.treatment)) && (
<>
{text(
'quantity',
'Quantidade abrangida nesta linha',
)}
{text(
'quotaRef',
'Histórico do direito,incluindo benefícios fora do dossier',
)}
</>
)}
{minerReturn(row.treatment) && (
<>
{text(
'arrivalDate',
'Data da chegada no regresso definitivo',
'date',
)}
{row.rightHolder !== 'heir' &&
text(
'requestDate',
'Data do requerimento do benefício',
'date',
)}
{minerNeedsDeadlineExtension(row) && (
<>
{choice(
'deadlineExtension',
'Invoca prorrogação excepcional do prazo de90dias,por motivo justificado?',
)}
{row.conditions.deadlineExtension ===
'yes' &&
text(
'extensionRef',
'Prorrogação e motivo justificado,âmbito e prazo concedido ou pressuposto expresso',
)}
</>
)}
</>
)}
{['return_vehicle', 'separate_vehicle'].includes(
row.treatment,
) && (
<>
{text(
'stayStart',
'Início da estadia naRSA',
'date',
)}
{text(
'stayEnd',
'Fim da estadia naRSA',
'date',
)}
{minerNeedsStayException(row) && (
<>
{choice(
'stayException',
'Invoca autorização excepcional6(7) por estadia inferior a um ano?',
)}
{row.conditions.stayException ===
'yes' &&
text(
'exceptionRef',
'Autorização/âmbito da excepção6(7)ou pressuposto expresso',
)}
</>
)}
</>
)}
{row.treatment === 'separate_vehicle' && (
<>
{text(
'normalVat',
'IVA informado sem o benefício de50%,emMZN',
)}
{text(
'normalVatRef',
'Referência do IVA normal ou pressuposto expresso',
)}
</>
)}
<p>
Trocar percurso conserva os dados ocultos no
rascunho e limpa as suas confirmações específicas.
Referências aduaneiras disponíveis podem ser
reutilizadas;nenhum procedimento específico daKAWENA
é imposto às outras vias.
</p>
</details>
);
})}
{!!book.rows.length && (
<button
type="button"
onClick={() => {
try {
save(recordMiners(draft, book));
} catch (e) {
setError(String(e));
}
}}
>
Conferir importações dos mineiros e guardar versão
</button>
)}
{book.result && (
<>
<p role="status">
{minerCurrent(draft, book)
? 'Resultado corresponde às entradas guardadas.'
: 'Entradas alteradas;resultado histórico conservado.'}{' '}
{book.history?.length ?? 0} versões anteriores.Sem
dedução/campo11 ou declaração aduaneira emitida.
</p>
<dl>
{minerReportRows(draft).map(
([, label, value, source], i) => (
<div key={i}>
<dt>{label}</dt>
<dd>
{value}
<small className="block">
{source}
</small>
</dd>
</div>
),
)}
</dl>
</>
)}
<details>
<summary>Fonte e âmbito documental</summary>
<p>{minerSource}</p>
</details>
</details>
);
}