feat: dodaj DOCX akcije i napomene na racunima
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

- dodaje DOCX preuzimanje za putni nalog, servisne zapise i racune na /putni-nalozi/racuni\n- uvodi modal za uredjivanje teksta napomene izvjestaja servisera\n- poboljsava update work order toka i upsert lokalnog stanja\n- ukljucuje TaskCalendar migraciju, dev watch stabilizaciju i deploy upute

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-23 13:34:53 +02:00
parent 1055820741
commit ae6ae08fb1
9 changed files with 294 additions and 7 deletions

View File

@@ -257,6 +257,16 @@ function replaceWorkOrderItem(workOrderId, nextValue) {
);
}
function upsertWorkOrderItem(workOrderId, nextValue) {
const current = $workOrders.get();
const exists = current.some((item) => String(item.id) === String(workOrderId));
if (exists) {
replaceWorkOrderItem(workOrderId, nextValue);
return;
}
$workOrders.set([nextValue, ...current]);
}
function appendLocalDraft(entity, payload, tempId) {
const base = {
...payload,
@@ -547,15 +557,12 @@ export async function createWorkOrder(data) {
export async function updateWorkOrder(workOrderId, changes) {
const existing = $workOrders.get().find((item) => String(item.id) === String(workOrderId));
if (!existing) {
throw new Error('Work order nije pronađen u lokalnom stanju.');
}
const canSendNow = isBrowser() && navigator.onLine && !!$accessToken.get();
if (canSendNow) {
try {
const response = await api.patch(`fleet/work-orders/${workOrderId}/`, changes);
replaceWorkOrderItem(workOrderId, response);
upsertWorkOrderItem(workOrderId, response);
await persistDashboardCache();
await logSync(
{ entity: 'work_orders', endpoint: `fleet/work-orders/${workOrderId}/`, method: 'PATCH' },
@@ -575,6 +582,10 @@ export async function updateWorkOrder(workOrderId, changes) {
}
}
if (!existing) {
throw new Error('Work order nije dostupan offline. Otvorite dashboard ili pokušajte ponovno kada ste online.');
}
const optimistic = {
...existing,
...changes,
@@ -849,6 +860,51 @@ export async function downloadWorkOrderServiceRecordsPdf(workOrderId) {
return payload;
}
export async function downloadWorkOrderDocx(workOrderId) {
if (!workOrderId) {
throw new Error('Work order ID je obavezan.');
}
try {
const blob = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/docx/`, { responseType: 'blob' });
saveBlobToFile(blob, `${workOrderId}.work-order.docx`);
showToast('DOCX putnog naloga je preuzet.', 'success');
} catch (err) {
const msg = err?.message || 'Preuzimanje DOCX putnog naloga nije uspjelo.';
showToast(msg, 'error');
throw err;
}
}
export async function downloadWorkOrderServiceRecordsDocx(workOrderId) {
if (!workOrderId) {
throw new Error('Work order ID je obavezan.');
}
try {
const blob = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/service-records-docx/`, { responseType: 'blob' });
saveBlobToFile(blob, `${workOrderId}.work-order-service-records.docx`);
showToast('DOCX servisnih zapisa je preuzet.', 'success');
} catch (err) {
const msg = err?.message || 'Preuzimanje DOCX servisnih zapisa nije uspjelo.';
showToast(msg, 'error');
throw err;
}
}
export async function downloadWorkOrderInvoicesDocx(workOrderId) {
if (!workOrderId) {
throw new Error('Work order ID je obavezan.');
}
try {
const blob = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/invoices-docx/`, { responseType: 'blob' });
saveBlobToFile(blob, `${workOrderId}.work-order-invoices.docx`);
showToast('DOCX računa putnog naloga je preuzet.', 'success');
} catch (err) {
const msg = err?.message || 'Preuzimanje DOCX računa nije uspjelo.';
showToast(msg, 'error');
throw err;
}
}
export async function downloadGeneratedPdfByUrl(downloadUrl, filename = 'document.pdf') {
if (!downloadUrl) {
showToast('Nedostaje URL za preuzimanje PDF-a.', 'error');