Files
Investidor-V2/resources/js/lib/irpc-mrfta-cases.ts
T

57 lines
2.9 KiB
TypeScript

import type { MrftaModel } from './irpc-mrfta.ts';
import { closureFingerprint } from './iva-closure.ts';
import {
fractionPresentation,
type FiscalFraction,
} from './fiscal-rational.ts';
// Groups are working sheets, never a decision to split an official declaration.
export function mrftaCases(m: MrftaModel) {
return m.lines.map((line) => ({
key: closureFingerprint([m.period, line.rubric, line.rate, line.cer]),
period: m.period,
rubric: line.rubric,
rate: line.rate,
cer: line.cer,
ids: [...line.ids],
documents: [...line.documents],
references: [...line.references],
base: structuredClone(line.base),
tax: structuredClone(line.tax),
paid: structuredClone(line.paid),
pending:
!line.cer ||
!/^\d+$/.test(line.cer) ||
!line.ids.every((id) =>
m.input.codes.find((c) => c.rowId === id)?.reference.trim(),
)
? 'CER ou referência por corresponder;sem preenchimento presumido.'
: 'CER transcrito com referência do caso;sem validação por catálogo oficial. Código provisório ou de simulação não é correspondência oficial.',
officialSeparation:
'A correspondência de linhas/anexos/declaração oficial permanece por resolver quando há taxas/CER distintos na mesma rubrica.',
}));
}
export function mrftaCaseHtml(m: MrftaModel, key: string): string {
const c = mrftaCases(m).find((c) => c.key === key);
if (!c)
throw Error('Caso MRFTA não encontrado;reprepare as entradas actuais.');
const esc = (v: unknown) =>
String(v).replace(
/[&<>"']/g,
(c) =>
({
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
})[c]!,
);
const money = (v: FiscalFraction | null) => {
if (!v) return 'Indeterminado';
const p = fractionPresentation(v);
return (p.approximate ? '≈' : '') + p.decimal + ' MZN';
};
return `<!doctype html><html lang="pt"><meta charset="utf-8"><title>MRFTA — ficha de caso</title><body><h1>MRFTA — ficha de trabalho por caso</h1><p>Não é uma declaração autónoma,guia,anexo oficial ou submissão. Não funde taxas nem substitui o total do período.</p><p>Período:${esc(c.period)};rubrica:${esc(c.rubric)};taxa:${c.rate}%;CER:${esc(c.cer || 'Por corresponder')}.</p><p>Base:${esc(money(c.base))};imposto:${esc(money(c.tax))};entregas:${esc(money(c.paid))}.</p><p>Documentos:${esc(c.documents.join(';'))};origens:${esc(c.ids.join(';'))}.</p><p>${esc(c.references.join(' | '))}</p><p>${esc(c.pending)}</p><p>${esc(c.officialSeparation)}</p><h2>Pendências do período — conservadas</h2><ul>${m.pending.map((p) => '<li>' + esc(p) + '</li>').join('')}</ul><small>${esc(m.source)}</small></body></html>`;
}