feat: async PDF cache i API media putanje za putne naloge
Some checks failed
ERP CI/CD Pipeline / test (push) Has been cancelled
ERP CI/CD Pipeline / Deploy (server git pull + compose) (push) Has been cancelled

Uvodi background request tok za generiranje PDF-a s 24h cache-om i cleanup taskom preko Celery beat-a. Dodaje notification metadata download_url za ponovno preuzimanje bez regeneracije, API image endpointe za putne naloge i račune, te frontend integraciju za async download i produkcijski prikaz slika.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-17 16:42:02 +02:00
parent 5e7ec72a4e
commit e8330473cd
17 changed files with 726 additions and 231 deletions

View File

@@ -742,9 +742,14 @@ export async function downloadWorkOrderPdf(workOrderId) {
throw new Error('Work order ID je obavezan.');
}
showToast('Kreiran je zahtjev za PDF putnog naloga.', 'info');
const blob = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/pdf/`, { responseType: 'blob' });
saveBlobToFile(blob, `${workOrderId}.work-order.pdf`);
showToast('PDF putnog naloga je preuzet.', 'success');
const payload = await api.post(`fleet/work-orders/${encodeURIComponent(workOrderId)}/pdf-request/`, {});
if (payload?.status === 'ready' && payload?.download_url) {
await downloadGeneratedPdfByUrl(payload.download_url, payload.filename || `${workOrderId}.work-order.pdf`);
showToast('PDF putnog naloga je preuzet iz cache-a.', 'success');
return payload;
}
showToast('PDF putnog naloga se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
return payload;
}
export async function downloadWorkOrderInvoicesPdf(workOrderId) {
@@ -752,9 +757,14 @@ export async function downloadWorkOrderInvoicesPdf(workOrderId) {
throw new Error('Work order ID je obavezan.');
}
showToast('Kreiran je zahtjev za PDF računa putnog naloga.', 'info');
const blob = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/invoices-pdf/`, { responseType: 'blob' });
saveBlobToFile(blob, `${workOrderId}.work-order-invoices.pdf`);
showToast('PDF računa putnog naloga je preuzet.', 'success');
const payload = await api.post(`fleet/work-orders/${encodeURIComponent(workOrderId)}/invoices-pdf-request/`, {});
if (payload?.status === 'ready' && payload?.download_url) {
await downloadGeneratedPdfByUrl(payload.download_url, payload.filename || `${workOrderId}.work-order-invoices.pdf`);
showToast('PDF računa putnog naloga je preuzet iz cache-a.', 'success');
return payload;
}
showToast('PDF računa se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
return payload;
}
export async function downloadWorkOrderServiceRecordsPdf(workOrderId) {
@@ -762,9 +772,23 @@ export async function downloadWorkOrderServiceRecordsPdf(workOrderId) {
throw new Error('Work order ID je obavezan.');
}
showToast('Kreiran je zahtjev za PDF servisnih zapisa putnog naloga.', 'info');
const blob = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/service-records-pdf/`, { responseType: 'blob' });
saveBlobToFile(blob, `${workOrderId}.work-order-service-records.pdf`);
showToast('PDF servisnih zapisa putnog naloga je preuzet.', 'success');
const payload = await api.post(`fleet/work-orders/${encodeURIComponent(workOrderId)}/service-records-pdf-request/`, {});
if (payload?.status === 'ready' && payload?.download_url) {
await downloadGeneratedPdfByUrl(payload.download_url, payload.filename || `${workOrderId}.work-order-service-records.pdf`);
showToast('PDF servisnih zapisa je preuzet iz cache-a.', 'success');
return payload;
}
showToast('PDF servisnih zapisa se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
return payload;
}
export async function downloadGeneratedPdfByUrl(downloadUrl, filename = 'document.pdf') {
if (!downloadUrl) {
throw new Error('Nedostaje URL za preuzimanje PDF-a.');
}
const blob = await api.get(downloadUrl, { responseType: 'blob' });
saveBlobToFile(blob, filename);
return true;
}
export function openWorkOrderInvoicesPdfPage(workOrderId) {