386 lines
18 KiB
TypeScript
386 lines
18 KiB
TypeScript
import { inputText } from '../lib/input-text.ts';
|
|
import { useState } from 'react';
|
|
import {
|
|
goodsPresumptionBook,
|
|
goodsPresumptionCurrent,
|
|
goodsPresumptionReportRows,
|
|
goodsPresumptionSource,
|
|
goodsPresumptionTreatments,
|
|
newGoodsPresumption,
|
|
presumptionConditions,
|
|
recordGoodsPresumptions,
|
|
saveGoodsPresumptionBook,
|
|
switchPresumptionTreatment,
|
|
type GoodsPresumptionBook,
|
|
type GoodsPresumptionRow,
|
|
} from '@/lib/iva-goods-presumptions';
|
|
export function SimulationGoodsPresumptions({
|
|
draft,
|
|
onChange,
|
|
}: {
|
|
draft: Record<string, unknown>;
|
|
onChange: (field: string, value: string) => void;
|
|
}) {
|
|
const [error, setError] = useState('');
|
|
let book: GoodsPresumptionBook;
|
|
try {
|
|
book = goodsPresumptionBook(draft);
|
|
} catch (cause) {
|
|
return <p role="alert">{String(cause)}</p>;
|
|
}
|
|
const save = (next: GoodsPresumptionBook) => {
|
|
try {
|
|
onChange(
|
|
'modelo_a_snapshot',
|
|
saveGoodsPresumptionBook(draft, next),
|
|
);
|
|
setError('');
|
|
} catch (cause) {
|
|
setError(String(cause));
|
|
}
|
|
};
|
|
const change = (id: string, patch: Partial<GoodsPresumptionRow>) =>
|
|
save({
|
|
...book,
|
|
rows: book.rows.map((r) => (r.id === id ? { ...r, ...patch } : r)),
|
|
});
|
|
return (
|
|
<details className="rounded border p-3">
|
|
<summary>Consignação e presunções de bens</summary>
|
|
<p>
|
|
Uma linha por conjunto identificado. Na consignação,180dias
|
|
contam da entrega ao destinatário. As presunções admitem prova
|
|
em contrário. Classificação não concede isenção,dedução ou
|
|
elegibilidade para margem.
|
|
</p>
|
|
<p>
|
|
Oportunidade:{' '}
|
|
{inputText(draft.context_opportunity ?? 'projecto')}. A data de
|
|
conferência situa o cenário; este percurso não determina a
|
|
exigibilidade,base ou IVA.
|
|
</p>
|
|
<p className="text-sm">{goodsPresumptionSource}</p>
|
|
{error && <p role="alert">{error}</p>}
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
save({
|
|
...book,
|
|
rows: [
|
|
...book.rows,
|
|
newGoodsPresumption(crypto.randomUUID()),
|
|
],
|
|
})
|
|
}
|
|
>
|
|
Acrescentar conjunto de bens
|
|
</button>
|
|
{book.rows.map((row) => (
|
|
<details key={row.id} className="rounded border p-3">
|
|
<summary>
|
|
{row.description || 'Conjunto por identificar'} —{' '}
|
|
{row.period || 'mês por indicar'}
|
|
</summary>
|
|
<div className="grid gap-3 md:grid-cols-2">
|
|
<label>
|
|
Percurso de consignação/presunção
|
|
<select
|
|
value={row.treatment}
|
|
onChange={(e) =>
|
|
change(
|
|
row.id,
|
|
switchPresumptionTreatment(
|
|
row,
|
|
e.target.value,
|
|
),
|
|
)
|
|
}
|
|
>
|
|
<option value="">Por indicar</option>
|
|
{goodsPresumptionTreatments.map((t) => (
|
|
<option key={t.id} value={t.id}>
|
|
{t.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</label>
|
|
<label>
|
|
Natureza dos dados
|
|
<select
|
|
value={row.origin}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
origin: e.target
|
|
.value as GoodsPresumptionRow['origin'],
|
|
})
|
|
}
|
|
>
|
|
<option value="projected">
|
|
Projectados / pressupostos
|
|
</option>
|
|
<option value="effective">
|
|
Efectivos declarados
|
|
</option>
|
|
</select>
|
|
</label>
|
|
{(
|
|
[
|
|
[
|
|
'description',
|
|
'Conjunto/operação identificados',
|
|
],
|
|
[
|
|
'operationRef',
|
|
'Referência da operação / pressuposto',
|
|
],
|
|
[
|
|
'operationDate',
|
|
'Data de conferência / prevista',
|
|
],
|
|
['period', 'Mês da conferência'],
|
|
[
|
|
'documentRef',
|
|
'Documento / referência da previsão',
|
|
],
|
|
[
|
|
'documentDate',
|
|
'Data do documento / prevista',
|
|
],
|
|
['goodsRef', 'Bens e elementos identificados'],
|
|
[
|
|
'scope',
|
|
'Âmbito:conjunto,estabelecimentos,operação e período',
|
|
],
|
|
[
|
|
'evidence',
|
|
'Fundamento factual / pressupostos',
|
|
],
|
|
] as const
|
|
).map(([field, label]) => (
|
|
<label key={field}>
|
|
{label}
|
|
<input
|
|
className="block rounded border p-2"
|
|
type={
|
|
[
|
|
'operationDate',
|
|
'documentDate',
|
|
].includes(field)
|
|
? 'date'
|
|
: field === 'period'
|
|
? 'month'
|
|
: 'text'
|
|
}
|
|
value={row[field]}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
[field]: e.target.value,
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
))}
|
|
{row.treatment === 'consignment_180' ? (
|
|
<>
|
|
<label>
|
|
Data da entrega ao destinatário
|
|
<input
|
|
type="date"
|
|
value={row.deliveryDate}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
deliveryDate: e.target.value,
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
<label>
|
|
Destinatário e referência da entrega
|
|
<input
|
|
value={row.recipientRef}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
recipientRef: e.target.value,
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
<p>
|
|
Identifique apenas o conjunto não devolvido.
|
|
Separe devoluções parciais por conjunto; uma
|
|
devolução posterior não apaga o cenário
|
|
anteriormente guardado.
|
|
</p>
|
|
</>
|
|
) : (
|
|
row.treatment && (
|
|
<>
|
|
<label>
|
|
Levantamento/inventário e
|
|
estabelecimentos abrangidos
|
|
<input
|
|
value={row.inventoryRef}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
inventoryRef:
|
|
e.target.value,
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
{row.treatment === 'excess_consumption' && (
|
|
<>
|
|
{(
|
|
[
|
|
[
|
|
'quantity',
|
|
'Quantidade consumida',
|
|
],
|
|
[
|
|
'quantityUnit',
|
|
'Unidade da quantidade',
|
|
],
|
|
[
|
|
'productionRef',
|
|
'Volume de produção e comparação que fundamenta o excesso',
|
|
],
|
|
] as const
|
|
).map(([field, label]) => (
|
|
<label key={field}>
|
|
{label}
|
|
<input
|
|
value={row[field]}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
[field]:
|
|
e.target
|
|
.value,
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
))}
|
|
<p>
|
|
Sem percentagem ou limiar de
|
|
consumo por defeito.
|
|
</p>
|
|
</>
|
|
)}
|
|
<label>
|
|
Existe prova em contrário para o âmbito
|
|
declarado?
|
|
<select
|
|
value={row.contraryProof}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
contraryProof: e.target
|
|
.value as GoodsPresumptionRow['contraryProof'],
|
|
})
|
|
}
|
|
>
|
|
<option value="">
|
|
Por esclarecer
|
|
</option>
|
|
<option value="yes">Sim</option>
|
|
<option value="no">Não</option>
|
|
</select>
|
|
</label>
|
|
{row.contraryProof === 'yes' && (
|
|
<label>
|
|
Referência e âmbito da prova em
|
|
contrário
|
|
<input
|
|
value={row.contraryProofRef}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
contraryProofRef:
|
|
e.target.value,
|
|
})
|
|
}
|
|
/>
|
|
</label>
|
|
)}
|
|
</>
|
|
)
|
|
)}
|
|
</div>
|
|
<fieldset>
|
|
<legend>Factos próprios do percurso</legend>
|
|
{presumptionConditions(row.treatment).map(
|
|
([key, label]) => (
|
|
<label className="block" key={key}>
|
|
{label}
|
|
<select
|
|
value={row.conditions[key] ?? ''}
|
|
onChange={(e) =>
|
|
change(row.id, {
|
|
conditions: {
|
|
...row.conditions,
|
|
[key]: e.target.value as
|
|
| ''
|
|
| 'yes'
|
|
| 'no',
|
|
},
|
|
})
|
|
}
|
|
>
|
|
<option value="">Por indicar</option>
|
|
<option value="yes">Sim</option>
|
|
<option value="no">Não</option>
|
|
</select>
|
|
</label>
|
|
),
|
|
)}
|
|
</fieldset>
|
|
<p>
|
|
Trocar percurso conserva dados/referências ocultos;
|
|
reveja as confirmações aplicáveis. Prova em contrário
|
|
afasta a presunção no seu âmbito,sem transformar o
|
|
resultado em isenção.
|
|
</p>
|
|
</details>
|
|
))}
|
|
{!!book.rows.length && (
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
try {
|
|
save(recordGoodsPresumptions(draft, book));
|
|
} catch (cause) {
|
|
setError(String(cause));
|
|
}
|
|
}}
|
|
>
|
|
Conferir consignação/presunções e guardar versão
|
|
</button>
|
|
)}
|
|
{book.result && (
|
|
<>
|
|
<p role="status">
|
|
{goodsPresumptionCurrent(draft, book)
|
|
? 'Classificações correspondentes às entradas guardadas.'
|
|
: 'Entradas alteradas;resultado histórico conservado.Reveja e confira novamente.'}{' '}
|
|
{book.history?.length ?? 0} versões anteriores.Sem
|
|
IVA,base,dedução ou margem calculados.
|
|
</p>
|
|
<dl>
|
|
{goodsPresumptionReportRows(draft).map(
|
|
([, label, value, origin], i) => (
|
|
<div key={i}>
|
|
<dt className="font-semibold">{label}</dt>
|
|
<dd>
|
|
{value}
|
|
<small className="block">
|
|
{origin}
|
|
</small>
|
|
</dd>
|
|
</div>
|
|
),
|
|
)}
|
|
</dl>
|
|
</>
|
|
)}
|
|
</details>
|
|
);
|
|
}
|