import { SimulationRemissionImports } from './simulation-remission-imports'; import { SimulationObjectiveImports } from './simulation-objective-imports'; import { SimulationMiners } from './simulation-miners'; import { SimulationReturnees } from './simulation-returnees'; import { SimulationDigital } from './simulation-digital'; import { SimulationTravel } from './simulation-travel'; import { SimulationTravelEvents } from './simulation-travel-events'; import { SimulationForeignOperations } from './simulation-foreign-operations'; import { SimulationCurrencyEvents } from './simulation-currency-events'; import { SimulationPropertyTransfers } from './simulation-property-transfers'; import { SimulationGoodsPresumptions } from './simulation-goods-presumptions'; import { InvestmentContextAssessment } from './investment-context-assessment'; import { useEffect, useRef, useState } from 'react'; import { monthlyIvaInput, monthlyIvaKey, monthlySalesFromDraft, readMonthlyIvaRecord, readMonthlyIvaSettings, recoverMonthlyIvaRecord, monthlyIvaCashTreatment, type MonthlyIvaInput, type MonthlyIvaSettings } from '@/lib/monthly-iva'; import { fiscalQaRows } from '@/lib/fiscal-qa-preview'; import { type ApiSimulationExecutionV1 } from '@/lib/simulation-contract'; import { SimulationModeloA } from './simulation-modelo-a'; import { SimulationAcquisitions } from './simulation-acquisitions'; import { SimulationImportExemptions } from './simulation-import-exemptions'; import { SimulationPublicAuthorityBase } from './simulation-public-authority-base'; import { SimulationCommissionBase } from './simulation-commission-base'; import { SimulationActSaleBase } from './simulation-act-sale-base'; import { SimulationFuelBase } from './simulation-fuel-base'; import { SimulationNoncashBase } from './simulation-noncash-base'; import { SimulationCompositionBase } from './simulation-composition-base'; import { SimulationExclusionBase } from './simulation-exclusion-base'; import { SimulationValueReview } from './simulation-value-review'; import { SimulationServiceNormal } from './simulation-service-normal'; import { SimulationGoodsLocation } from './simulation-goods-location'; import { SimulationServiceLocation } from './simulation-service-location'; import { SimulationListedServices } from './simulation-listed-services'; import { SimulationReducedBases } from './simulation-reduced-bases'; import { SimulationOwnName } from './simulation-own-name'; import { SimulationGoodsAllocation } from './simulation-goods-allocation'; import { SimulationSecondhand } from './simulation-secondhand'; import { SimulationOfferPreparations } from './simulation-offer-preparations'; import { SimulationOperations } from './simulation-operations'; export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: { draft: Record; busy: boolean; onCalculate: (input: MonthlyIvaInput) => Promise; onChange: (field: string, value: string) => void; }) { const settings = readMonthlyIvaSettings(String(draft.monthly_iva_settings ?? '')); const record = readMonthlyIvaRecord(String(draft.monthly_iva_snapshot ?? '')); const [retry, setRetry] = useState(0); const [error, setError] = useState(''); const [available, setAvailable] = useState(null); const attempt = useRef(''); const mounted = useRef(true); const latestSnapshot = useRef(draft.monthly_iva_snapshot); latestSnapshot.current = draft.monthly_iva_snapshot; useEffect(() => { mounted.current = true; return () => { mounted.current = false; }; }, []); const callbacks = useRef({onCalculate, onChange}); callbacks.current = {onCalculate, onChange}; let input: MonthlyIvaInput | null = null; let inputError = ''; let source = ''; try { source = monthlySalesFromDraft(draft).source; input = monthlyIvaInput(draft, settings); } catch (cause) { inputError = cause instanceof Error ? cause.message : 'Reveja a projecção de vendas.'; } const key = input ? monthlyIvaKey(input) : ''; const current = !!(input && record && monthlyIvaKey(record.input) === key); const completed = current && record?.execution.status === 'completed'; const pendingRecord = record && ['queued','running'].includes(record.execution.status) ? record : null; const actionKey = pendingRecord ? `recover:${pendingRecord.execution.id}` : key; const saveSettings = (patch: Partial) => onChange('monthly_iva_settings', JSON.stringify({...settings, ...patch})); 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) setAvailable(payload?.data?.enabled === true); }).catch(() => {if (active) setError('Não foi possível consultar a disponibilidade da regra. As vendas foram preservadas.');}); return () => { active = false; }; }, [retry]); useEffect(() => { if (!settings.auto || busy || attempt.current === actionKey) return; if (!pendingRecord && (!input || input.currency !== 'MZN' || !available || completed)) return; const request = pendingRecord?.input ?? input!; const savedSnapshot = draft.monthly_iva_snapshot; const timer = window.setTimeout(() => { attempt.current = actionKey; setError(''); void (async () => { try { let execution; if (pendingRecord) { execution = (await recoverMonthlyIvaRecord(pendingRecord)).execution; } else execution = await callbacks.current.onCalculate(request); if (!execution) throw new Error('O cálculo mensal não foi concluído. As vendas e a versão anterior foram preservadas; tente novamente.'); if (!mounted.current || (pendingRecord && latestSnapshot.current !== savedSnapshot)) return; callbacks.current.onChange('monthly_iva_snapshot', JSON.stringify({input:request, execution})); } catch (cause) {if (mounted.current) setError(cause instanceof Error ? cause.message : 'Não foi possível calcular o IVA mensal.');} })(); }, 700); return () => window.clearTimeout(timer); }, [actionKey, key, settings.auto, busy, available, completed, retry]); const snapshot = record?.execution.result_snapshot; const projection = snapshot?.monthly_projection as {rows?: Array<{date:string; sales_declared:string|null; net_sales:string|null; rate:string|null; vat:string|null; gross_sales:string|null; status:string}>} | undefined; return

IVA mensal das vendas projectadas

{source}

Declare se os preços projectados são sem IVA ou com IVA incluído. Nenhuma taxa é fixada neste formulário; o servidor selecciona a versão publicada.

Sem importações, taxas reduzidas, isenções, regimes especiais, deduções, reembolsos ou apuramento final. Valores com IVA incluído permanecem indeterminados neste lote; não se aplica a taxa ao preço bruto.

{monthlyIvaCashTreatment}

{!!draft.currency && draft.currency !== "MZN" &&

Moeda do projecto: {String(draft.currency)}. A regra disponível aceita apenas MZN. As vendas e a moeda são preservadas, sem conversão; o IVA mensal não pode ser determinado por esta versão.

} {inputError &&

{inputError}

} {available === null && !error &&

A consultar a disponibilidade da versão publicada…

} {available === false &&

A versão publicada de IVA está indisponível neste ambiente para novas execuções. Os pressupostos e históricos mantêm-se.

} {record && !current &&

As vendas ou os pressupostos mudaram. Os resultados abaixo são históricos e estão desactualizados; não são usados como resultados da projecção actual.

} {settings.auto && !completed && current &&

Execução mensal guardada: {record?.execution.status === 'queued' ? 'em fila' : record?.execution.status === 'running' ? 'em processamento' : 'não concluída'}. Pode voltar a consultar sem duplicar.

} {busy &&

A actualizar os resultados dependentes das vendas…

} {error &&

{error}

} {pendingRecord &&

Consulta da execução {pendingRecord.execution.id}. A suspensão de novos cálculos não impede esta recuperação; não é criado outro pedido.

} {settings.auto && } {input &&

{input.monthly_sales.length} meses; moeda {input.currency || 'por indicar'}. Campo vazio significa informação em falta; zero declarado permanece zero. Depois da primeira execução, alterações das vendas actualizam o cálculo enquanto a actualização automática estiver ligada.

} {projection?.rows &&
{['Mês','Vendas declaradas','Vendas tributáveis sem IVA','Taxa aplicada (%)','IVA calculado','Total com IVA','Estado'].map((label) => )}{projection.rows.map((row) => )}
IVA mensal — {current ? 'versão correspondente às entradas' : 'versão histórica'}
{label}
{row.date.slice(0,7)}{row.sales_declared ?? 'Sem informação'}{row.net_sales ?? 'Indeterminado'}{row.rate ?? 'Indeterminada'}{row.vat ?? 'Indeterminado'}{row.gross_sales ?? 'Indeterminado'}{{calculated:'Calculado',missing_sales:'Sem informação de vendas',unsupported_basis:'Base líquida não determinada',indeterminate:'Enquadramento ou regra indeterminados'}[row.status] ?? 'Indeterminado'}
} {snapshot &&
Ver fundamento e relatório da versão guardada
{fiscalQaRows(snapshot).map(([label,value], index) =>
{label}
{value}
)}
}
; }