Files
Investidor-V2/resources/js/lib/iva-objective-imports.ts
T

356 lines
13 KiB
TypeScript

import { acquisitionScope, readAcquisitionStore } from './iva-acquisitions.ts';
import {
operationTreatments,
newSalesOperation,
evaluateSalesOperation,
salesBook,
type SalesOperation,
} from './iva-operations.ts';
export const objectiveImportVersion = 'objective-imports/1';
export const objectiveImportSource =
'CIVA12(1)a,Lei10/2025,BR248-I/suplemento,PDF12/p2180(12),efeitos01/01/2026:importações definitivas de bens cuja transmissão interna beneficie de isenção objectiva;enumeração exemplificativa. Correspondências9(1)b/c/e/f/g,9(9)b,9(10),9(11),9(12)g/h/i;catálogo interno e anexosLei22/2022 já conferidos. Sem dedução/campo11,direitos ou alteração dos livros internos.';
const fixed = [
'health_assistive',
'human_materials',
'mosquito_nets',
'medicines',
'pharma_manufacturing_inputs',
'cultural_publications',
'official_military_supplies',
'industrial_feed_inputs',
'annexI_goods',
'veterinary_goods',
];
export const objectiveImportTreatments = operationTreatments.filter(
(t) => fixed.includes(t.id) || t.id.startsWith('listed_'),
);
type Choice = '' | 'yes' | 'no';
export type ObjectiveImportRow = {
id: string;
description: string;
period: string;
currency: string;
origin: 'projected' | 'effective';
importer: string;
documentRef: string;
documentDate: string;
scope: string;
evidence: string;
definitive: Choice;
goods: Choice;
sameGoods: Choice;
internalApplicable: Choice;
reference: SalesOperation;
reusedFrom: string;
};
type Line = {
id: string;
status: 'exempt' | 'not_applicable' | 'indeterminate';
importVat: string | null;
deduction: null;
source: string;
reason: string;
};
export type ObjectiveImportCalculation = {
version: string;
revision: number;
calculatedAt: string;
opportunity: string;
sourceKey: string;
source: string;
inputs: ObjectiveImportRow[];
rows: Line[];
};
export type ObjectiveImportBook = {
rows: ObjectiveImportRow[];
result?: ObjectiveImportCalculation;
history?: ObjectiveImportCalculation[];
};
type Store = ReturnType<typeof readAcquisitionStore> & {
objectiveImports?: Record<string, ObjectiveImportBook>;
};
export function newObjectiveImport(
id: string,
currency: string,
): ObjectiveImportRow {
return {
id,
description: '',
period: '',
currency,
origin: 'projected',
importer: '',
documentRef: '',
documentDate: '',
scope: '',
evidence: '',
definitive: '',
goods: '',
sameGoods: '',
internalApplicable: '',
reference: newSalesOperation(id + '-reference', '', currency),
reusedFrom: '',
};
}
export function objectiveImportSources(
draft: Record<string, unknown>,
): SalesOperation[] {
return salesBook(draft).rows.filter((r) =>
objectiveImportTreatments.some((t) => t.id === r.treatment),
);
}
export function reuseObjectiveImport(
row: ObjectiveImportRow,
source: SalesOperation,
): ObjectiveImportRow {
const reference = { ...row.reference };
// This explicit action fills missing values only; confirmations belong to this import.
if (!reference.treatment || reference.treatment === 'other')
reference.treatment = source.treatment;
if (reference.treatment === source.treatment) {
reference.annexIItem ||= source.annexIItem;
reference.pharmaAnnexItem ||= source.pharmaAnnexItem;
reference.annexIOnly ??= source.annexIOnly;
}
return {
...row,
description: row.description || source.description,
period: row.period || source.period,
evidence: row.evidence || source.evidence,
reference,
reusedFrom: source.id,
};
}
function readStore(draft: Record<string, unknown>): Store {
const s = readAcquisitionStore(draft.modelo_a_snapshot) as Store;
const books = s.objectiveImports;
if (
books !== undefined &&
(!books || typeof books !== 'object' || Array.isArray(books))
)
throw new Error(
'Importações objectivas não recuperáveis;originais preservados.',
);
const fields = Object.keys(newObjectiveImport('', 'MZN')).filter(
(k) => k !== 'reference',
);
for (const b of Object.values(books ?? {}))
if (
!b ||
!Array.isArray(b.rows) ||
(b.history !== undefined && !Array.isArray(b.history)) ||
b.rows.some(
(r) =>
!r ||
fields.some(
(k) =>
typeof r[k as keyof ObjectiveImportRow] !==
'string',
) ||
!r.reference ||
typeof r.reference.treatment !== 'string' ||
!Array.isArray(r.reference.confirmed),
)
)
throw new Error(
'Linhas de importação objectiva não recuperáveis;sem substituição por lista vazia.',
);
return s;
}
export function objectiveImportBook(
draft: Record<string, unknown>,
): ObjectiveImportBook {
return (
readStore(draft).objectiveImports?.[acquisitionScope(draft)] ?? {
rows: [],
}
);
}
export function saveObjectiveImportBook(
draft: Record<string, unknown>,
book: ObjectiveImportBook,
): string {
const s = readStore(draft),
encoded = JSON.stringify({
...s,
objectiveImports: {
...s.objectiveImports,
[acquisitionScope(draft)]: book,
},
});
readStore({ ...draft, modelo_a_snapshot: encoded });
return encoded;
}
function date(value: string): boolean {
const d = new Date(value + 'T00:00:00Z');
return (
/^\d{4}-\d{2}-\d{2}$/.test(value) &&
Number.isFinite(d.getTime()) &&
d.toISOString().slice(0, 10) === value
);
}
export function evaluateObjectiveImport(
row: ObjectiveImportRow,
currency: unknown,
): Line {
const rule = objectiveImportTreatments.find(
(t) => t.id === row.reference.treatment,
),
result: Line = {
id: row.id,
status: 'indeterminate',
importVat: null,
deduction: null,
source: objectiveImportSource + (rule ? ';' + rule.source : ''),
reason: '',
};
const stop = (
reason: string,
status: Line['status'] = 'indeterminate',
) => ({ ...result, status, reason });
if (
currency !== 'MZN' ||
row.currency !== currency ||
!/^2026-(0[1-9]|1[0-2])$/.test(row.period)
)
return stop(
'Indique período2026 e moedaMZN coerente com o projecto;sem conversão presumida.',
);
if (
!['projected', 'effective'].includes(row.origin) ||
![
row.description,
row.importer,
row.documentRef,
row.scope,
row.evidence,
].every((v) => !!v.trim()) ||
!date(row.documentDate)
)
return stop(
'Identifique bens,importador,documento/previsão,data,âmbito e factos/pressupostos.Reutilize os elementos disponíveis.',
);
if (
[row.definitive, row.goods, row.sameGoods, row.internalApplicable].some(
(v) => v === 'no',
)
)
return stop(
'Este fundamento12(1)a não se aplica aos factos indicados;IVA fora deste fundamento permanece por enquadrar,sem taxa presumida.',
'not_applicable',
);
if (
[row.definitive, row.goods, row.sameGoods, row.internalApplicable].some(
(v) => v !== 'yes',
)
)
return stop(
'Confirme importação definitiva de bens,a correspondência dos mesmos bens e a aplicabilidade da isenção objectiva interna.Desconhecido não significa IVA zero.',
);
if (!rule)
return stop(
'Escolha correspondência interna documentada.A lista implementada cobre as remissões expressas12(1)a;é exemplificativa e não declara excluídos outros fundamentos.Não basta descrição,isenção de serviços,exportação,taxa reduzida ou benefício terminado.',
);
// Evaluate the legal hypothetical domestic transmission, never create a domestic sale or use its amount/totals.
const reference = {
...row.reference,
id: row.id + '-reference',
description: row.description,
period: row.period,
sourcePeriod: row.period,
sourceCurrency: row.currency,
sourceAmount: null,
establishment: row.importer,
amount: '0',
basis: 'net' as const,
evidence: row.evidence,
};
const v = evaluateSalesOperation(reference, row.currency);
result.source = objectiveImportSource + ';' + v.source;
if (v.status !== 'exempt')
return stop(
'Correspondência interna ainda não demonstrada: ' + v.reason,
);
return {
...result,
status: 'exempt',
importVat: '0.00',
reason: `Isenção12(1)a por correspondência a${rule.article},nas condições ${row.origin === 'projected' ? 'expressamente assumidas da projecção' : 'efectivas declaradas'}. IVA na importação:0.00MZN. Hipótese de transmissão interna,não venda criada nem montante somado.Sem direitos,base aduaneira,dedução/campo11 ou concessão administrativa automática.`,
};
}
function key(
draft: Record<string, unknown>,
book: ObjectiveImportBook,
): string {
return JSON.stringify({
version: objectiveImportVersion,
catalog: objectiveImportTreatments,
scope: acquisitionScope(draft),
currency: draft.currency,
location: draft.selection_labels ?? {},
rows: book.rows,
});
}
export function objectiveImportCurrent(
draft: Record<string, unknown>,
book: ObjectiveImportBook,
): boolean {
return !!book.result && book.result.sourceKey === key(draft, book);
}
export function recordObjectiveImports(
draft: Record<string, unknown>,
book: ObjectiveImportBook,
): ObjectiveImportBook {
if (
!book.rows.length ||
new Set(book.rows.map((r) => r.id)).size !== book.rows.length
)
throw new Error(
'Indique linhas com identidades distintas;originais conservados.',
);
const result: ObjectiveImportCalculation = {
version: objectiveImportVersion,
revision: (book.result?.revision ?? 0) + 1,
calculatedAt: new Date().toISOString(),
opportunity: acquisitionScope(draft),
sourceKey: key(draft, book),
source: objectiveImportSource,
inputs: structuredClone(book.rows),
rows: book.rows.map((r) => evaluateObjectiveImport(r, draft.currency)),
};
const next = {
...book,
result,
history: [
...(book.history ?? []),
...(book.result ? [book.result] : []),
],
};
saveObjectiveImportBook(draft, next);
return next;
}
export function objectiveImportReportRows(
draft: Record<string, unknown>,
): Array<[string, string, string, string]> {
try {
const b = objectiveImportBook(draft),
r = b.result;
if (!r) return [];
return r.inputs.map((row, i) => [
'IVA mensal',
`P046 — ${row.period} — ${row.id}`,
`${row.description};${r.rows[i].reason};IVA importação:${r.rows[i].importVat ?? 'Indeterminado'};dedução:Não apurada`,
`${r.opportunity};${objectiveImportCurrent(draft, b) ? 'Resultado actual' : 'Entradas alteradas;resultado histórico conservado'};versão${r.revision};${r.calculatedAt};${row.origin};importador${row.importer};documento${row.documentRef},${row.documentDate};âmbito${row.scope};factos${row.evidence};reutilização${row.reusedFrom || 'Introdução directa'};correspondência${row.reference.treatment};condições internas confirmadas${row.reference.confirmed.join(',')}${row.reference.treatment === 'annexI_goods' ? `;AnexoI${row.reference.annexIItem ?? ''},apenasAnexoI${String(row.reference.annexIOnly ?? 'Por esclarecer')}` : row.reference.treatment === 'pharma_manufacturing_inputs' ? `;AnexoIII${row.reference.pharmaAnnexItem ?? ''}` : ''};${r.rows[i].source};sem alteração dos livros internos,ModeloA,campo11 ou totais.`,
]);
} catch {
return [
[
'IVA mensal',
'P046',
'Dados não recuperáveis',
'Originais preservados;sem classificação por defeito.',
],
];
}
}