Files
Investidor-V2/resources/js/components/simulation-currency-events.tsx
T

42 lines
8.9 KiB
TypeScript

import {SimulationFxSelection} from './simulation-fx-selection';
import {useState} from 'react';
import {currencyEventBook,currencyEventCurrent,currencyEventReportRows,currencyEventSource,currencyEventTreatments,newCurrencyEvent,recordCurrencyEvents,saveCurrencyEventBook,switchCurrencyEvent,type CurrencyEventBook,type CurrencyEventRow} from '@/lib/iva-currency-events';
export function SimulationCurrencyEvents({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}){
const[error,setError]=useState('');let book:CurrencyEventBook;try{book=currencyEventBook(draft);}catch(e){return<p role="alert">{String(e)}</p>;}
const save=(next:CurrencyEventBook)=>{try{onChange('modelo_a_snapshot',saveCurrencyEventBook(draft,next));setError('');}catch(e){setError(String(e));}};
const change=(id:string,patch:Partial<CurrencyEventRow>)=>save({...book,rows:book.rows.map(r=>r.id===id?{...r,...patch}:r)});
return <details className="rounded border p-3"><summary>Moeda e datas do facto gerador/exigibilidade</summary><p>Facto gerador e exigibilidade são estados separados. Identifique a operação já preparada,sem repetir os seus cálculos. P104 permite a selecção operacional definida pela Tempo;os cenários antigos permanecem condicionados até selecção explícita,sem recálculo de históricos.</p><p>{currencyEventSource}</p>{error&&<p role="alert">{error}</p>}
<button type="button" onClick={()=>save({...book,rows:[...book.rows,newCurrencyEvent(crypto.randomUUID(),String(draft.currency??''))]})}>Acrescentar moeda/evento</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>
<label>Percurso de moeda/evento<select value={row.treatment} onChange={e=>change(row.id,switchCurrencyEvent(row,e.target.value))}><option value="">Por indicar</option>{currencyEventTreatments.map(t=><option key={t.id} value={t.id}>{t.label}</option>)}</select></label>
<label>Natureza dos dados<select value={row.origin} onChange={e=>change(row.id,{origin:e.target.value as CurrencyEventRow['origin']})}><option value="projected">Projectados / pressupostos</option><option value="effective">Efectivos declarados</option></select></label>
{([['description','Operação identificada'],['operationRef','Referência da operação existente'],['period','Mês do contexto'],['documentRef','Documento / referência da previsão'],['documentDate','Data do documento'],['scope','Âmbito e parcelas abrangidas'],['evidence','Factos ou pressupostos expressos'],['amount','Montante total do âmbito identificado'],['currency','Moeda do montante / destino da conversão']] as const).map(([field,label])=><label className="block" key={field}>{label}<input value={row[field]} type={field==='period'?'month':field==='documentDate'?'date':'text'} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
<label>Factos próprios correspondem ao percurso,operação e âmbito<select value={row.factsConfirmed} onChange={e=>change(row.id,{factsConfirmed:e.target.value as CurrencyEventRow['factsConfirmed']})}><option value="">Por esclarecer</option><option value="yes">Sim</option><option value="no">Não</option></select></label>
{row.treatment==='foreign_scenario'?<>
<SimulationFxSelection row={row} onChange={patch=>change(row.id,patch)}/>
{([['sourceCurrency','Moeda original'],['fxRate','Taxa de conversão indicada'],['fxDate','Data efectiva da taxa'],['fxSource','Fonte e exemplar da taxa'],['fxRuleRef','Regra/pressuposto da escolha da taxa e data']] as const).map(([field,label])=><label className="block" key={field}>{label}<input value={row[field]} type={field==='fxDate'?'date':'text'} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
<label>Direcção da taxa<select value={row.fxDirection} onChange={e=>change(row.id,{fxDirection:e.target.value as CurrencyEventRow['fxDirection']})}><option value="">Por indicar</option><option value="mzn_per_unit">MZN por unidade da moeda original</option><option value="units_per_mzn">Unidades da moeda original por MZN</option></select></label><p>{row.fxSelection?.applied?'Conversão operacional após selecção explícita da taxa.':'Cenário histórico condicionado;selecção operacional ainda não aplicada.'} Não activa base fiscal,IVA ou dedução,nem altera os livros anteriores.</p>
</>:row.treatment&&<>
{([['eventDate','Data própria do evento escolhido'],['eventRef','Referência e factos do evento7/8'],['reviewDate','Data até à qual os eventos foram conferidos']] as const).filter(([field])=>field!=='eventDate'||!['advance_payment','consignment_deadline'].includes(row.treatment)).map(([field,label])=><label className="block" key={field}>{label}<input value={row[field]} type={field==='eventRef'?'text':'date'} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
{['consignment_deadline','service_early_charge','contract_effects'].includes(row.treatment)&&<label>{row.treatment==='consignment_deadline'?'Entrega ao destinatário da consignação':row.treatment==='service_early_charge'?'Data de realização do serviço posterior à cobrança/débito':'Disponibilização anterior aos efeitos translativos'}<input type="date" value={row.otherDate} onChange={e=>change(row.id,{otherDate:e.target.value})}/></label>}
{row.treatment==='contract_effects'&&<p>Este percurso7(7) exclui locação vinculativa e venda com reserva3(3)a/b. Confirme essa distinção nos factos.</p>}
{row.treatment==='continuous_period'&&<p>Use o termo do período a que respeita cada pagamento sucessivo,não a data arbitrária de emissão.</p>}
{row.treatment==='consignment_deadline'&&<p>7(6) fixa exigibilidade no termo180dias da consignação. P123 conserva a conferência da não devolução;embalagensP102 são distintas.</p>}
{!['import_clearance','import_auction'].includes(row.treatment)&&<>
<label>Operação sujeita à obrigação de emitir factura25<select value={row.invoiceRequired} onChange={e=>change(row.id,{invoiceRequired:e.target.value as CurrencyEventRow['invoiceRequired']})}><option value="">Por esclarecer</option><option value="yes">Sim</option><option value="no">Não</option></select></label>
{row.invoiceRequired==='yes'&&<>
{([['legalDeadline','Termo legal do prazo de emissão aplicável'],['deadlineRef','Disposição,calendário e âmbito que fundamentam esse prazo']] as const).map(([field,label])=><label className="block" key={field}>{label}<input value={row[field]} type={field==='legalDeadline'?'date':'text'} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
<label>Facturação até à conferência<select value={row.invoiceState} onChange={e=>change(row.id,{invoiceState:e.target.value as CurrencyEventRow['invoiceState']})}><option value="">Por esclarecer</option><option value="issued">Factura emitida</option><option value="not_issued">Factura não emitida</option></select></label>
{row.invoiceState==='issued'&&<>{([['invoiceDate','Data de emissão da factura'],['invoiceRef','Referência da factura']] as const).map(([field,label])=><label key={field}>{label}<input value={row[field]} type={field==='invoiceDate'?'date':'text'} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}</>}
<label>Recebimentos neste âmbito<select value={row.paymentState} onChange={e=>change(row.id,{paymentState:e.target.value as CurrencyEventRow['paymentState']})}><option value="">Por esclarecer</option><option value="none">Sem recebimento</option><option value="received">Recebimento identificado</option></select></label>
{row.paymentState==='received'&&<>{([['paymentDate','Data de recebimento'],['paymentAmount','Montante recebido'],['paymentRef','Referência e âmbito do recebimento']] as const).map(([field,label])=><label className="block" key={field}>{label}<input value={row[field]} type={field==='paymentDate'?'date':'text'} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}</>}
<p>O recebimento anterior é separado do restante,sem dupla contagem. Para parcelas com factos distintos,use âmbitos distintos e conserve as referências.</p>
</>}
</>}
</>}
<p>Trocar percurso conserva dados ocultos e referências;reveja as confirmações aplicáveis.</p></details>)}
{!!book.rows.length&&<button type="button" onClick={()=>{try{save(recordCurrencyEvents(draft,book));}catch(e){setError(String(e));}}}>Conferir moeda/eventos e guardar versão</button>}
{book.result&&<><p role="status">{currencyEventCurrent(draft,book)?'Resultados correspondentes às entradas guardadas.':'Entradas alteradas;histórico conservado.'} {book.history?.length??0} versões anteriores.P104 conserva a natureza operacional ou condicionada indicada em cada resultado;semIVA/base/dedução activados.</p><dl>{currencyEventReportRows(draft).map(([,label,value,origin],i)=><div key={i}><dt>{label}</dt><dd>{value}{label.startsWith('P104')?<details><summary>Fonte,âmbito e versão</summary><small className="block">{origin}</small></details>:<small className="block">{origin}</small>}</dd></div>)}</dl></>}
</details>;
}