33 lines
6.5 KiB
TypeScript
33 lines
6.5 KiB
TypeScript
import {useState} from 'react';
|
|
import {newPublicBase,publicBaseBook,publicBaseConditions,publicBaseCurrent,publicBaseReportRows,publicBaseSource,publicBaseTreatments,recordPublicBases,savePublicBaseBook,type PublicBaseBook,type PublicBaseRow} from '@/lib/iva-public-authority-base';
|
|
|
|
export function SimulationPublicAuthorityBase({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}){
|
|
const[error,setError]=useState('');let book:PublicBaseBook;
|
|
try{book=publicBaseBook(draft);}catch(cause){return<p role="alert">{String(cause)}</p>;}
|
|
const save=(next:PublicBaseBook)=>{try{onChange('modelo_a_snapshot',savePublicBaseBook(draft,next));setError('');}catch(cause){setError(String(cause));}};
|
|
const change=(id:string,patch:Partial<PublicBaseRow>)=>save({...book,rows:book.rows.map(row=>row.id===id?{...row,...patch}:row)});
|
|
return<details className="space-y-3 rounded border p-3">
|
|
<summary>Base tributável — actos de autoridades públicas</summary>
|
|
<p>Oportunidade: {String(draft.context_opportunity||'entrada geral')}. Prepare apenas as operações relevantes. A base do artigo15(2)(d) é a indemnização ou outra compensação ligada à transmissão de bens ou prestação de serviços resultante do acto público. Um pagamento ou a natureza pública da entidade não determinam incidência nem taxa de IVA.</p>
|
|
<p>A indemnização judicial por incumprimento de contrato tem exclusão própria no artigo15(6)(a); não é incluída por analogia. Indique as componentes sem IVA e o fundamento da composição. Na compensação em espécie ou mista, identifique o valor normal conforme15(3)/(4). Valores em falta permanecem indeterminados; não se convertem em zero.</p>
|
|
<p>{publicBaseSource}</p>
|
|
{error&&<p role="alert">{error}</p>}
|
|
<button type="button" className="underline" onClick={()=>save({...book,rows:[...book.rows,newPublicBase(crypto.randomUUID(),String(draft.currency??''))]})}>Acrescentar operação de acto público</button>
|
|
{book.rows.map(row=><details key={row.id} className="rounded border p-3"><summary>{row.description||'Operação por identificar'} — {row.period||'mês por indicar'}</summary>
|
|
<div className="grid gap-3 md:grid-cols-2">
|
|
<label>Tratamento da compensação<select className="block rounded border p-2" value={row.treatment} onChange={e=>change(row.id,{treatment:e.target.value})}><option value="">Por indicar</option>{publicBaseTreatments.map(item=><option key={item.id} value={item.id}>{item.label}</option>)}</select></label>
|
|
<label>Natureza da operação<select className="block rounded border p-2" value={row.operationNature} onChange={e=>change(row.id,{operationNature:e.target.value as PublicBaseRow['operationNature']})}><option value="">Por indicar</option><option value="goods">Transmissão de bens</option><option value="services">Prestação de serviços</option></select></label>
|
|
<label>Natureza dos dados<select className="block rounded border p-2" value={row.origin} onChange={e=>change(row.id,{origin:e.target.value as PublicBaseRow['origin']})}><option value="projected">Projectados / pressupostos</option><option value="effective">Efectivos declarados</option></select></label>
|
|
{([['description','Operação identificada'],['authority','Autoridade pública'],['actRef','Acto da autoridade / referência da previsão'],['documentRef','Documento da compensação / referência da previsão'],['documentDate','Data do documento / prevista'],['period','Mês da operação'],['currency','Moeda de origem'],['compositionRef','Referência da composição sem IVA — inclusões e exclusões aplicáveis'],['evidence','Fundamento factual / pressupostos']] as const).map(([field,label])=><label key={field}>{label}<input className="block rounded border p-2" type={field==='documentDate'?'date':field==='period'?'month':'text'} value={row[field]} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
|
|
<label>Forma da compensação<select className="block rounded border p-2" value={row.compensationForm} onChange={e=>change(row.id,{compensationForm:e.target.value as PublicBaseRow['compensationForm']})}><option value="">Por indicar</option><option value="money">Em dinheiro</option><option value="non_money">Em espécie</option><option value="mixed">Mista — dinheiro e espécie</option></select></label>
|
|
{['money','mixed'].includes(row.compensationForm)&&<label>Componente monetária sem IVA (moeda indicada)<input className="block rounded border p-2" value={row.moneyAmount} onChange={e=>change(row.id,{moneyAmount:e.target.value})}/></label>}
|
|
{['non_money','mixed'].includes(row.compensationForm)&&<><label>Valor normal não monetário sem IVA (moeda indicada)<input className="block rounded border p-2" value={row.nonMoneyValue} onChange={e=>change(row.id,{nonMoneyValue:e.target.value})}/></label><label>Referência da valorização / pressuposto do valor normal<input className="block rounded border p-2" value={row.valuationRef} onChange={e=>change(row.id,{valuationRef:e.target.value})}/></label></>}
|
|
</div>
|
|
<p>Ao mudar de tratamento ou forma, os valores e referências anteriores conservam-se; só entram no cálculo as componentes aplicáveis à forma escolhida.</p>
|
|
<fieldset><legend>Condições próprias desta base</legend>{publicBaseConditions.map(([key,label])=><label className="block" key={key}>{label}<select className="block rounded border p-2" value={row.conditions[key]??''} onChange={e=>change(row.id,{conditions:{...row.conditions,[key]:e.target.value}})}><option value="">Por indicar</option><option value="yes">Sim</option><option value="no">Não</option></select></label>)}</fieldset>
|
|
</details>)}
|
|
{!!book.rows.length&&<button type="button" className="rounded bg-emerald-800 p-2 text-white" onClick={()=>{try{save(recordPublicBases(draft,book));}catch(cause){setError(String(cause));}}}>Determinar bases e guardar versão</button>}
|
|
{book.result&&<><p role="status">{publicBaseCurrent(draft,book)?'Bases correspondentes às entradas guardadas.':'Entradas alteradas; bases históricas conservadas. Reveja e determine novamente.'} {book.history?.length??0} versões anteriores. IVA e campo11 não são preenchidos por estas bases.</p><dl>{publicBaseReportRows(draft).map(([,label,value,origin],index)=><div key={index}><dt className="font-semibold">{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
|
|
</details>;
|
|
}
|