import { inputText } from '../lib/input-text.ts'; import { useEffect, useState } from 'react'; import type { MonthlyIvaInput } from '@/lib/monthly-iva'; export type PublishedIvaInput = | MonthlyIvaInput | { scenario_kind: 'fiscal_rule_published'; base: string; currency: 'MZN'; reference_date: string; operation: 'internal_general_net'; scope_declared: boolean; }; export function SimulationPublishedIva({ busy, onCalculate, draft, onChange, }: { draft: Record; onChange: (field: string, value: string) => void; busy: boolean; onCalculate: (input: PublishedIvaInput) => Promise; }) { const [available, setAvailable] = useState(false); const [message, setMessage] = useState( 'A consultar disponibilidade do cálculo de IVA…', ); const base = inputText(draft.published_iva_base ?? ''); const date = inputText(draft.published_iva_date ?? ''); const currency = inputText(draft.published_iva_currency ?? ''); const declared = draft.published_iva_scope === 'yes'; const setBase = (value: string) => onChange('published_iva_base', value); const setDate = (value: string) => onChange('published_iva_date', value); const setCurrency = (value: string) => onChange('published_iva_currency', value); const setDeclared = (value: boolean) => onChange('published_iva_scope', value ? 'yes' : 'no'); const [error, setError] = useState(''); useEffect(() => { let active = true; fetch('/api/v1/fiscal-consumer', { credentials: 'same-origin', headers: { Accept: 'application/json' }, }) .then(async (response) => { if (!response.ok) throw new Error(); const payload = await response.json(); if (!active) return; setAvailable(payload?.data?.enabled === true); setMessage( typeof payload?.data?.message === 'string' ? payload.data.message : 'Cálculo de IVA indisponível.', ); }) .catch(() => { if (active) setMessage( 'Não foi possível consultar a disponibilidade do IVA. As entradas e históricos foram preservados.', ); }); return () => { active = false; }; }, []); async function calculate() { if ( !/^\d+(?:\.\d+)?$/.test(base) || base.length > 40 || !date || currency !== 'MZN' ) { setError( 'Indique uma base líquida decimal válida, a moeda MZN e a data de exigibilidade. As entradas foram preservadas.', ); return; } setError(''); await onCalculate({ scenario_kind: 'fiscal_rule_published', base, currency: 'MZN', reference_date: date, operation: 'internal_general_net', scope_declared: declared, }); // Refresh after admission/refusal so a suspension is reflected without discarding inputs. try { const response = await fetch('/api/v1/fiscal-consumer', { credentials: 'same-origin', headers: { Accept: 'application/json' }, }); if (!response.ok) return; const payload = await response.json(); setAvailable(payload?.data?.enabled === true); if (typeof payload?.data?.message === 'string') setMessage(payload.data.message); } catch { /* The execution flow already preserves and reports connection errors. */ } } return (

IVA — taxa geral

{message}

Cobertura: exigibilidade em 2026, operação interna à taxa geral. A base tributável é indicada por si; não é copiada do orçamento. Sem isenções, taxas reduzidas, bases especiais, importações, deduções, declaração ou pagamento. O cálculo não valida o enquadramento jurídico.

Sem esta declaração, o resultado fica indeterminado. O valor calculado conserva a precisão decimal; não é saldo a pagar.

{currency && currency !== 'MZN' && (

Moeda: {currency}. A versão disponível aceita apenas MZN. O valor declarado foi preservado; não foi feita conversão. Este cálculo permanece indisponível para esta moeda.

)} {error &&

{error}

}
); }