Move supply purchases from draft through approval, shipment, and receipt with an audited internal status trail.
${canCreate ? '' : ''}
Internal procurement tracking only. Creating or changing a purchase order does not send anything to a vendor, move money, post an accounting expense, or automatically increase inventory. Record the real expense and inventory receipt through their reviewed workflows when those events actually occur.
Vendor
Status
Tracked total
Expected
PO ref
Actions
${purchaseOrderRows(items)}
`;
};
window.openPurchaseOrderForm = () => {
if (!purchaseOrderWriteRoles.has(user?.role)) return toast('You do not have permission to create purchase orders.', true);
$('#purchaseOrderModal')?.remove();
document.body.insertAdjacentHTML('beforeend', `
Create draft purchase order
Start internal procurement tracking. Owner/admin approval is still required before it can be marked ordered.
No vendor send or payment occurs here. This creates a draft record only.
`);
};
window.savePurchaseOrder = async () => {
if (!purchaseOrderWriteRoles.has(user?.role)) return toast('You do not have permission to create purchase orders.', true);
const vendorName = String($('#po_vendor')?.value || '').trim();
const total = Number($('#po_total')?.value);
const expectedValue = String($('#po_expected')?.value || '').trim();
if (!vendorName) return toast('Enter a vendor name.', true);
if (!Number.isFinite(total) || total < 0) return toast('Enter a non-negative purchase-order total.', true);
let expectedAt = null;
if (expectedValue) {
const expected = new Date(expectedValue);
if (Number.isNaN(expected.getTime())) return toast('Enter a valid expected date and time.', true);
expectedAt = expected.toISOString();
}
try {
await api('/api/purchase-orders', { method:'POST', body:JSON.stringify({ vendorName, total, expectedAt }) });
$('#purchaseOrderModal')?.remove();
toast('Draft purchase order created.');
await render('supplies');
} catch (error) { toast(error.message, true); }
};
window.changePurchaseOrderStatus = async (id, status) => {
if (!purchaseOrderWriteRoles.has(user?.role)) return toast('You do not have permission to change purchase orders.', true);
if (status === 'ordered' && !purchaseOrderApproveRoles.has(user?.role)) return toast('Owner or admin approval is required.', true);
const messages = {
pending_approval:'Submit this draft for owner/admin approval?',
draft:'Return this purchase order to draft?',
ordered:'Approve and mark this purchase order ordered? This updates internal tracking only; FacilityOps HQ will not contact the vendor or move money.',
shipped:'Mark this purchase order shipped in internal tracking?',
received:'Mark this purchase order received? This does not automatically increase inventory; reconcile received stock separately.',
cancelled:'Cancel this purchase order in internal tracking?'
};
if (!confirm(messages[status] || `Change purchase order to ${status}?`)) return;
try {
await api(`/api/purchase-orders/${encodeURIComponent(id)}/status`, { method:'POST', body:JSON.stringify({ status }) });
toast(`Purchase order marked ${statusLabel(status).toLowerCase()}.`);
await render('supplies');
} catch (error) { toast(error.message, true); }
};
})();