Files
SGF/public/sgf-finance-payables.mjs
2026-11-11 09:00:17 +02:00

14 lines
2.5 KiB
JavaScript

const root=document.querySelector('#finance-payables'),message=document.querySelector('#result');let pending=false,uncertain=false,pendingForm=null,dirty=false;
for(const form of document.querySelectorAll('[data-action]')){
const source=form.querySelector('[data-source]');if(source)source.onchange=()=>{form.elements.source_revision.value=source.selectedOptions[0]?.dataset.revision||'';};
form.addEventListener('input',()=>{dirty=true;});form.onsubmit=async event=>{event.preventDefault();if(pending)return;if(uncertain&&pendingForm!==form){message.textContent='Recupere primeiro a operação pendente.';return;}let body=uncertain?JSON.parse(form.dataset.signature):Object.fromEntries(new FormData(form));for(const key of ['obligation_id','payment_id','proposal_id','allocation_id'])if(key in body)body[key]=Number(body[key]);
if(form.dataset.action==='allocation-prepare'&&!uncertain){body.allocations=[{obligation_id:body.obligation_id,source_revision:body.source_revision,amount:body.amount}];delete body.obligation_id;delete body.source_revision;delete body.amount;}
const signature=JSON.stringify(body);if(uncertain&&form.dataset.signature!==signature){message.textContent='Recupere primeiro a operação com os mesmos dados.';return;}if(form.dataset.signature!==signature){form.dataset.signature=signature;form.dataset.key=crypto.randomUUID();}
pending=true;pendingForm=form;for(const field of document.querySelectorAll('input,select,textarea,button'))field.disabled=true;message.textContent='A revalidar e registar a decisão…';
try{const response=await fetch('/api/finance/payables/'+form.dataset.action,{method:'POST',headers:{Accept:'application/json','Content-Type':'application/json','X-CSRF-TOKEN':root.dataset.csrf,'X-SGF-Context':root.dataset.context,'Idempotency-Key':form.dataset.key},body:signature});const value=await response.json();if(!response.ok){if(response.status>=500)throw Error('Resultado incerto');uncertain=false;message.textContent=value.message||'Operação recusada. Actualize a conferência.';return;}uncertain=false;dirty=false;location.reload();}
catch{uncertain=true;message.textContent='Resposta incerta. Conserve esta página e recupere pelo mesmo botão, sem alterar os dados.';}
finally{pending=false;for(const field of document.querySelectorAll('input,select,textarea,button'))field.disabled=uncertain&&!(field.tagName==='BUTTON'&&form.contains(field));}
};
}
window.addEventListener('beforeunload',event=>{if(pending||uncertain||dirty){event.preventDefault();event.returnValue='';}});