40 lines
8.4 KiB
TypeScript
40 lines
8.4 KiB
TypeScript
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. Conversão P104 é apenas cenário condicionado,enquanto a regra fiscal permanece por corresponder.</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'?<>
|
|
{([['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>O valor convertido é uma simulação condicionada. Não substitui a base fiscal,nem altera os valores/moedas dos 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.P104condicionado,semIVA/base/dedução activados.</p><dl>{currencyEventReportRows(draft).map(([,label,value,origin],i)=><div key={i}><dt>{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
|
|
</details>;
|
|
}
|