Files
Investidor-V2/resources/js/components/acquisition-substitution.tsx
T

36 lines
6.0 KiB
TypeScript

import {useState} from 'react';
import {closureSources} from '@/lib/iva-closure';
import {substitutionBook,saveSubstitutionBook,newSubstitution,previousDeclarations,recordSubstitution,substitutionReportRows,type SubstitutionBook,type SubstitutionInput} from '@/lib/iva-substitution';
export function AcquisitionSubstitution({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}){
const[error,setError]=useState('');let b:SubstitutionBook;try{b=substitutionBook(draft);}catch(e){return<p role="alert">{String(e)}</p>;}
const save=(next:SubstitutionBook)=>{try{onChange('modelo_a_snapshot',saveSubstitutionBook(draft,next));setError('');}catch(e){setError(String(e));}};
const change=(id:string,p:Partial<SubstitutionInput>)=>save({...b,rows:b.rows.map(r=>r.id===id?{...r,...p}:r)});
const previous=previousDeclarations(draft,b),sources=closureSources(draft);
return<details className="rounded border p-3"><summary>L3-C — substituições e diferencial</summary>
<p>Escolha a declaração anterior e o resultado corrigido do mesmo período. Créditos utilizados e pagamentos anteriores conservam-se no histórico;registe apenas pagamentos adicionais.</p>
<p>O diferencial credor aguarda comunicação dos serviços para utilização posterior no campo20. Não compensa automaticamente dívida nem cria reporte26. A preparação não submete à AT;formulário de substituição e formalidades permanecem fora do InvesteMoz.</p>
{error&&<p role="alert">{error}</p>}
<button type="button" onClick={()=>save({...b,rows:[...b.rows,newSubstitution(crypto.randomUUID())]})}>Preparar substituição</button>
{b.rows.map(r=><fieldset className="rounded border p-3" key={r.id}><legend>Substituição — {r.prior?.period||'período por escolher'}</legend>
<label>Declaração anterior congelada<select value={previous.findIndex(p=>JSON.stringify(p)===JSON.stringify(r.prior))} onChange={e=>{const p=previous[Number(e.target.value)];if(p){const matches=sources.filter(s=>s.period===p.period);change(r.id,{prior:structuredClone(p),...(r.priorDate?{}:{priorDate:p.declarationDate}),...(r.priorReference?{}:{priorReference:p.declarationReference}),...(r.source===null&&matches.length===1?{source:structuredClone(matches[0])}:{})});}}}><option value={-1}>Escolha a versão anterior</option>{previous.filter(p=>p.id!==r.id).map(p=><option key={JSON.stringify(p)} value={previous.indexOf(p)}>{p.period} — {p.entityRef} — {p.kind}/{p.id} — {p.calculatedAt}</option>)}</select></label>
{r.prior&&<p>Anterior:{r.prior.entityRef};{r.prior.origin==='projected'?'pressuposto de simulação':'dados efectivos declarados'};pagamentos e reporte conservados na versão escolhida.</p>}
<label>Resultado L2 corrigido congelado<select value={sources.findIndex(s=>JSON.stringify(s)===JSON.stringify(r.source))} onChange={e=>{const s=sources[Number(e.target.value)];if(s)change(r.id,{source:structuredClone(s)});}}><option value={-1}>Escolha a versão corrigida</option>{sources.filter(s=>!r.prior||s.period===r.prior.period).map(s=><option key={JSON.stringify(s)} value={sources.indexOf(s)}>{s.period} — revisão{s.revision} — {s.calculatedAt}</option>)}</select></label>
<label>Referência da declaração anterior<input value={r.priorReference} onChange={e=>change(r.id,{priorReference:e.target.value})}/></label>
<label>Data da declaração anterior<input type="date" value={r.priorDate} onChange={e=>change(r.id,{priorDate:e.target.value})}/></label>
<label>Referência da substituição ou preparação<input value={r.reference} onChange={e=>change(r.id,{reference:e.target.value})}/></label>
<label>Data da substituição ou prevista<input type="date" value={r.date} onChange={e=>change(r.id,{date:e.target.value})}/></label>
<label>Motivo da substituição<textarea value={r.reason} onChange={e=>change(r.id,{reason:e.target.value})}/></label>
<label>Situação da substituição<select value={r.stage} onChange={e=>change(r.id,{stage:e.target.value as SubstitutionInput['stage']})}><option value="preparation">Em preparação — sem submissão</option><option value="presented">Apresentada fora do InvesteMoz — registo declarado</option></select></label>
<label>Juros adicionais23<select value={r.interest} onChange={e=>change(r.id,{interest:e.target.value as SubstitutionInput['interest']})}><option value="">Por identificar</option><option value="none">Sem juros adicionais — motivo identificado</option><option value="documented">Montante adicional identificado</option></select></label>
{r.interest==='documented'&&<label>Montante dos juros adicionais (MZN)<input value={r.interestAmount} onChange={e=>change(r.id,{interestAmount:e.target.value})}/></label>}
<label>Fonte ou motivo dos juros adicionais<input value={r.interestRef} onChange={e=>change(r.id,{interestRef:e.target.value})}/></label>
<h5>Pagamentos adicionais desta substituição</h5>
{r.payments.map(p=><fieldset key={p.id}><legend>Pagamento adicional</legend>{(['reference','date','amount'] as const).map(k=><label key={k}>{k==='reference'?'Referência do pagamento adicional':k==='date'?'Data do pagamento adicional':'Montante adicional pago (MZN)'}<input type={k==='date'?'date':'text'} value={p[k]} onChange={e=>change(r.id,{payments:r.payments.map(v=>v.id===p.id?{...v,[k]:e.target.value}:v)})}/></label>)}<button type="button" onClick={()=>change(r.id,{payments:r.payments.filter(v=>v.id!==p.id)})}>Remover pagamento desta preparação</button></fieldset>)}
<button type="button" onClick={()=>change(r.id,{payments:[...r.payments,{id:crypto.randomUUID(),reference:'',date:'',amount:''}]})}>Registar pagamento adicional</button>
<button type="button" onClick={()=>save({...b,rows:b.rows.filter(v=>v.id!==r.id)})}>Remover substituição desta preparação</button>
</fieldset>)}
{b.rows.length>0&&<button type="button" onClick={()=>{try{save(recordSubstitution(draft,b));}catch(e){setError(String(e));}}}>Calcular e guardar substituições C</button>}
{substitutionReportRows(draft).map((r,i)=><p key={i}><strong>{r[1]}:</strong> {r[2]}<br/>{r[3]}</p>)}
</details>;
}