30 lines
6.1 KiB
TypeScript
30 lines
6.1 KiB
TypeScript
import {useState} from 'react';
|
|
import {beverageRestitutionBook,beverageRestitutionSources,newBeverageRestitution,saveBeverageRestitutionBook,recordBeverageRestitution,beverageRestitutionReportRows,type BeverageRestitutionBook,type BeverageRestitutionInput} from '@/lib/iva-beverage-restitution';
|
|
import {beverageDeductionEvidence} from '@/lib/iva-beverage-allocation';
|
|
import {fractionPresentation} from '@/lib/fiscal-rational';
|
|
import {FiscalClaimEventsFields} from './fiscal-claim-events';
|
|
export function AcquisitionBeverageRestitution({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}){
|
|
const[error,setError]=useState('');let b:BeverageRestitutionBook;try{b=beverageRestitutionBook(draft);}catch(e){return<p role="alert">{String(e)}</p>;}
|
|
const save=(next:BeverageRestitutionBook)=>{try{onChange('modelo_a_snapshot',saveBeverageRestitutionBook(draft,next));setError('');}catch(e){setError(String(e));}},sources=beverageRestitutionSources(draft);
|
|
const change=(id:string,p:Partial<BeverageRestitutionInput>)=>save({...b,rows:b.rows.map(r=>r.id===id?{...r,...p}:r)});
|
|
return<details className="rounded border p-3"><summary>L3-E — restituição de bebidas13(2)</summary>
|
|
<p>Reutiliza bebidas de abastecimento de bordo13(1)(c/d/h),com documento e vínculoL1/L2. Escolha restituição na aquisição e recalculeL2:esta linha não gera dedução nem crédito para reembolso geral. Não se aplica a qualquer despesa com bebidas,tabaco ou recepção.</p>
|
|
<p>Âmbito2026/MZN:linha integral ou parcelas de IVA documentadas,sem sobreposição. A parte não pedida fica sem destino presumido. Uma dedução efectiva anterior conserva montante e histórico;identifique a parcela já deduzida. A mudança ou anulação dessa dedução requer regularização com fundamento próprio,sem a libertar por simples edição. Pedido,decisão e recebimento são registos distintos. Procedimento/formulário específico e prazos não automatizados;submissão fora doInvesteMoz,sem condições importadas do reembolso geralD.</p>
|
|
{error&&<p role="alert">{error}</p>}
|
|
<button type="button" onClick={()=>save({...b,rows:[...b.rows,newBeverageRestitution(crypto.randomUUID(),sources.length===1?sources[0]:null,String(draft.fiscal_entity_ref??draft.organization_name??''))]})}>Preparar restituição de bebidas</button>
|
|
{b.rows.map(r=><fieldset key={r.id} className="rounded border p-3"><legend>Restituição — {r.source?.period||'origem por escolher'}</legend>
|
|
<label>Linha documental destinada à restituição<select value={sources.findIndex(s=>s.parcel===r.source?.parcel&&s.fingerprint===r.source?.fingerprint)} onChange={e=>{const s=sources[Number(e.target.value)];if(s)change(r.id,{source:structuredClone(s)});}}><option value={-1}>Escolha origem actualL1/L2</option>{sources.map((s,i)=><option key={s.parcel} value={i}>{s.documentRef} — linha{s.documentLine||'única'} — {s.period}</option>)}</select></label>
|
|
{r.source&&<p>Documento:{r.source.documentRef};{r.source.documentDate};fornecedor{r.source.supplier};operaçãoL1{r.source.operationId};{r.source.operationRef}. O total documental é reutilizado sem taxa presumida; repartição e IVA do fornecimento mantêm cálculos próprios.</p>}
|
|
<label>Âmbito fiscal da entidade<input value={r.entityRef} onChange={e=>change(r.id,{entityRef:e.target.value})}/></label>
|
|
<label>Parcela exclusivamente para restituição,sem dedução da mesma parcela<select value={r.exclusive} onChange={e=>change(r.id,{exclusive:e.target.value as BeverageRestitutionInput['exclusive']})}><option value="">Por confirmar</option><option value="yes">Sim</option><option value="no">Não — reconciliar parcela</option></select></label>
|
|
<label>Âmbito da restituição<select value={r.allocation?'partial':'full'} onChange={e=>change(r.id,{allocation:e.target.value==='partial'?{from:'',to:'',reference:'',deductionFrom:'',deductionTo:'',deductionReference:''}:undefined})}><option value="full">Linha integral</option><option value="partial">Parcela documentada da mesma linha</option></select></label>
|
|
{r.allocation&&<fieldset><legend>Repartição do IVA documental em MZN</legend><p>Os limites identificam partes do IVA da linha: por exemplo, de 0 a 6 e de 6 a 16 são parcelas distintas de um total de 16. A parte restante não gera dedução automática. Pode indicar valores decimais ou fracções exactas,como16/3;sem arredondar a dedução anterior.</p>{([['from','Início da parcela'],['to','Fim da parcela'],['reference','Suporte da repartição']] as const).map(([field,label])=><label key={field}>{label}<input value={r.allocation![field]} onChange={e=>change(r.id,{allocation:{...r.allocation!,[field]:e.target.value}})}/></label>)}</fieldset>}
|
|
{r.source&&(()=>{const evidence=beverageDeductionEvidence(draft,r.source!);return<fieldset><legend>Reconciliação da dedução anterior</legend><p>IVA documental: {fractionPresentation(r.source!.vat).decimal} MZN. Dedução efectiva positiva identificada: {evidence.amount?fractionPresentation(evidence.amount).decimal:'Indeterminada'} MZN. {evidence.reason}</p>{evidence.records.map((v,i)=><p key={i}>{v.context};revisão{v.revision};{v.calculatedAt};{fractionPresentation(v.amount).decimal} MZN;{v.documents.join(' | ')}</p>)}{r.allocation&&evidence.records.length>0&&([['deductionFrom','Início da parcela já deduzida'],['deductionTo','Fim da parcela já deduzida'],['deductionReference','Suporte da afectação da dedução anterior']] as const).map(([field,label])=><label key={field}>{label}<input value={r.allocation![field]} onChange={e=>change(r.id,{allocation:{...r.allocation!,[field]:e.target.value}})}/></label>)}</fieldset>;})()}
|
|
<FiscalClaimEventsFields value={r} onChange={p=>change(r.id,p)}/>
|
|
<button type="button" onClick={()=>save({...b,rows:b.rows.filter(q=>q.id!==r.id)})}>Remover restituição desta preparação</button>
|
|
</fieldset>)}
|
|
{b.rows.length>0&&<button type="button" onClick={()=>{try{save(recordBeverageRestitution(draft,b));}catch(e){setError(String(e));}}}>Calcular e guardar restituição E</button>}
|
|
{beverageRestitutionReportRows(draft).map((r,i)=><p key={i}><strong>{r[1]}:</strong> {r[2]}<br/>{r[3]}</p>)}
|
|
</details>;
|
|
}
|