feat(iva): implement G3 temporary benefit cessation and explicit treatment continuity

This commit is contained in:
2026-10-24 16:51:52 +02:00
parent 908c8afc54
commit ac948bd8b7
6 changed files with 191 additions and 3 deletions
@@ -2,8 +2,9 @@ import { useState } from 'react';
import { fundraisingActivities } from '@/lib/iva-fundraising';
import { pharmaAnnexEntries, pharmaAnnexEntry, pharmaAnnexReference } from '@/lib/iva-pharma-annex';
import { annexIEntries, annexIEntry, annexIReference } from '@/lib/iva-annex-i';
import { temporaryBenefit, temporaryBenefitNotice } from '@/lib/iva-temporary-benefits';
import { emptyProductionTaxOption, type ProductionTaxOption } from '@/lib/iva-production-option';
import { continueAnnexIOperation, modeloA06Correspondence, newSalesOperation, operationTreatments, recordSales, reuseSales, salesBook, salesCurrent, salesReportRows, saveSalesBook, splitSales, type SalesBook, type SalesOperation } from '@/lib/iva-operations';
import { continueTemporaryOperation, continueAnnexIOperation, modeloA06Correspondence, newSalesOperation, operationTreatments, recordSales, reuseSales, salesBook, salesCurrent, salesReportRows, saveSalesBook, splitSales, type SalesBook, type SalesOperation } from '@/lib/iva-operations';
export function SimulationOperations({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}) {
const [error,setError]=useState('');
@@ -14,6 +15,7 @@ export function SimulationOperations({draft,onChange}:{draft:Record<string,unkno
const run=(action:()=>void)=>{try{action();setError('');}catch(cause){setError(cause instanceof Error?cause.message:String(cause));}};
const save=(next:SalesBook)=>onChange('modelo_a_snapshot',saveSalesBook(draft,next));
const change=(id:string,patch:Partial<SalesOperation>)=>run(()=>save({...book,rows:book.rows.map(r=>r.id===id?{...r,...patch}:r)}));
const continueTemporary=(id:string,target:string)=>run(()=>save({...book,rows:book.rows.map(row=>row.id===id?continueTemporaryOperation(row,target):row)}));
return <section aria-label="Operações IVA por oportunidade" className="space-y-3 rounded border p-3">
<h4 className="font-semibold">Operações de IVA — enquadramento das vendas</h4>
<p>Oportunidade {String(draft.context_opportunity||'entrada geral')}; moeda original {book.currency||'por indicar'}. Cobertura2026/MZN. Reutilize as vendas e complete apenas o enquadramento. Este bloco classifica as operações; não substitui nem soma novamente a execução mensal geral acima.</p>
@@ -30,8 +32,17 @@ export function SimulationOperations({draft,onChange}:{draft:Record<string,unkno
<label>Período<input type="month" className="block rounded border p-2" min="2026-01" max="2026-12" value={row.period} onChange={e=>change(row.id,{period:e.target.value})}/></label>
<label>Valor declarado<input inputMode="decimal" className="block rounded border p-2" value={row.amount} onChange={e=>change(row.id,{amount:e.target.value})}/></label>
<label>Representação do preço<select className="block rounded border p-2" value={row.basis} onChange={e=>change(row.id,{basis:e.target.value as SalesOperation['basis']})}><option value="">Ainda desconhecida</option><option value="net">Sem IVA</option><option value="included">IVA incluído</option></select></label>
<label>Tratamento da operação<select className="block rounded border p-2" value={row.treatment} onChange={e=>change(row.id,{treatment:e.target.value,confirmed:[]})}>{operationTreatments.map(t=><option value={t.id} key={t.id}>{t.label}</option>)}</select></label>
<label>Tratamento da operação<select className="block rounded border p-2" value={row.treatment} onChange={e=>temporaryBenefit(row.treatment)&&!temporaryBenefit(e.target.value)?continueTemporary(row.id,e.target.value):change(row.id,{treatment:e.target.value,confirmed:[]})}>{operationTreatments.map(t=><option value={t.id} key={t.id}>{t.label}</option>)}</select></label>
</div>
{temporaryBenefit(row.treatment)&&<fieldset className="space-y-2 rounded border p-2"><legend>Benefício temporário — prazo e continuidade</legend>
<p>{temporaryBenefitNotice(row.treatment,row.period)}</p>
<p>{temporaryBenefit(row.treatment)!.historicalScope}</p>
<p>Não precisa de preencher documentos de uma isenção já terminada para prosseguir em2026. Antes de escolher outro tratamento, confirme a natureza da operação: a escolha conserva valor,moeda,período,estabelecimento eorigem; limpa as confirmações para revisão e mantém o resultado anterior no histórico.</p>
<button type="button" onClick={()=>continueTemporary(row.id,'general')}>Escolher operação interna geral e rever condições</button>
{row.treatment==='temporary_sugar_cane'&&<button type="button" onClick={()=>continueTemporary(row.id,'production_agriculture')}>Analisar produção agrícola própria — artigo9(7)(a)</button>}
<p>Para outro enquadramento disponível,use a escolha «Tratamento da operação». Nenhum resultado é recalculado automaticamente.</p>
</fieldset>}
{temporaryBenefit(row.temporaryBenefitOrigin)&&!temporaryBenefit(row.treatment)&&<p>Origem conservada: {temporaryBenefit(row.temporaryBenefitOrigin)!.label},benefício com termo31/12/2025. Enquadramento actual escolhido expressamente;confirme as respectivas condições antes de calcular.</p>}
{row.treatment==='annexI_goods'&&<fieldset className="space-y-2 rounded border p-2"><legend>Bem do Anexo I — edição Lei22/2022</legend>
<p>Escolha código e designação e confira apenas os qualificadores dessa linha. A pesquisa conserva a escolha actual; mudar de posição exige rever as condições específicas. O anexo não dispensa o enquadramento de outras isenções aplicáveis ao mesmo bem.</p>
<label className="block">Pesquisar código ou designação no Anexo I<input value={annexSearch[`I:${row.id}`]??''} onChange={e=>setAnnexSearch({...annexSearch,[`I:${row.id}`]:e.target.value})}/></label>