Files
SGF/public/order-workspace.mjs
2026-11-04 09:37:20 +02:00

15 lines
4.7 KiB
JavaScript

import {rememberFocus} from './purchasing-focus.mjs';
import {evidence as renderEvidence,purchasingStatus} from './purchasing-presenter.mjs';
import {beginWorkspace,focusHref,appendProcessLinks} from './purchasing-focus.mjs';
const root=document.querySelector('#orders-workspace'),status=document.querySelector('#status'),list=document.querySelector('#award-list'),detail=document.querySelector('#award-detail');let page=1,last=1,generation=0,busy=false;
const node=(tag,text)=>{const n=document.createElement(tag);if(text!==undefined)n.textContent=text;return n;};const money=(minor,currency='MZN')=>(Number(minor)/100).toFixed(2)+' '+currency;
async function api(path,data){const r=await fetch('/api/purchasing-orders'+path,{method:data===undefined?'GET':'POST',headers:{Accept:'application/json','X-SGF-Context':root.dataset.context,'X-CSRF-TOKEN':root.dataset.csrf,...(data===undefined?{}:{'Content-Type':'application/json'})},body:data===undefined?undefined:JSON.stringify(data)});const d=await r.json();if(!r.ok)throw Error(Object.values(d.errors||{}).flat().join(' ')||d.message||'Não foi possível concluir.');return d;}
async function load(){const turn=++generation;try{const d=await api('?page='+page);if(turn!==generation)return;list.replaceChildren();for(const a of d.data){const b=node('button',`Adjudicação #${a.id} · ${a.status} · ${money(a.total_minor)}`);b.onclick=()=>open(a.id);list.append(b);}last=d.last_page;document.querySelector('#page').textContent=`Página ${page} de ${last}`;document.querySelector('#previous').disabled=page<=1;document.querySelector('#next').disabled=page>=last;}catch(e){status.textContent=e.message;}}
async function open(id){const turn=++generation;detail.replaceChildren();status.textContent='A consultar a base aprovada…';try{const d=await api('/awards/'+id);if(turn!==generation)return;status.textContent='';rememberFocus('orders',{award:id});const panel=node('section'),a=d.basis.award,q=d.basis.quote;panel.append(node('h2','Adjudicação #'+id),node('p',`${q.supplier.name} · ${money(a.total_minor,q.currency)} · ${a.status}`),node('p',`Entrega: ${a.delivery_date} · ${a.delivery_location}`));for(const item of q.items)panel.append(node('p',`${item.description} · quantidade ${item.quantity} · total ${money(item.total_minor,q.currency)}`));panel.append(node('h3','Aprovações preservadas'));for(const step of a.approvals)panel.append(node('p',`${step.role} · ${step.decision} · responsável #${step.approver_id??'pendente'}`));detail.append(panel);
if(d.existing){panel.append(node('h3','Ordem emitida: '+d.existing.order.number),node('p','A fotografia original mantém os dados e as aprovações da emissão.'));const proof=node('details');proof.append(node('summary','Consultar fotografia e linhas da ordem'),renderEvidence(d.existing.order));panel.append(proof);const link=node('a','Continuar para recepção de mercadoria');link.href=root.dataset.focusEnabled==='true'?focusHref('receipts',{order:d.existing.order.id}):'/purchasing/receipts';panel.append(link);return;}
if(!d.can_issue){panel.append(node('p','A emissão não está disponível para este perfil ou estado. As aprovações e condições têm de continuar válidas.'));return;}
const prepare=node('button','Conferir impacto da emissão'),confirm=node('button','Emitir esta ordem'),impact=node('section');confirm.disabled=true;impact.hidden=true;let preview=null;prepare.onclick=async()=>{if(busy)return;busy=true;prepare.disabled=true;try{const p=await api('/awards/'+id+'/preview',{revision:d.revision});if(turn!==generation)return;preview=p.preview;impact.replaceChildren(node('h3','Impacto a confirmar'),node('p',`Fornecedor: ${p.impact.supplier} · Total: ${money(p.impact.total_minor,p.impact.currency)}`),node('p',`Entrega: ${p.impact.delivery_date} · ${p.impact.delivery_location}`),node('p',p.impact.budget),node('p','Sem entrada de stock, factura ou pagamento nesta emissão.'));impact.hidden=false;confirm.disabled=false;}catch(e){status.textContent=e.message;}finally{busy=false;prepare.disabled=false;}};
confirm.onclick=async()=>{if(busy||!preview)return;busy=true;confirm.disabled=true;try{await api('/awards/'+id+'/issue',{preview});if(turn===generation)await open(id);}catch(e){status.textContent=e.message+' Se a resposta se perdeu, repita a mesma emissão para recuperar a ordem original.';confirm.disabled=false;}finally{busy=false;}};panel.append(prepare,impact,confirm);
}catch(e){if(turn===generation)status.textContent=e.message;}}
document.querySelector('#previous').onclick=()=>{if(page>1){page--;load();}};document.querySelector('#next').onclick=()=>{if(page<last){page++;load();}};beginWorkspace({stage:'orders',root,load:load,open:f=>open(f.award),current:()=>generation,error:text=>{status.textContent=text;}});