feat: dodaj dodatne troškove s OCR sinkronizacijom

Dodana je tablica DODATNI TROŠKOVI za putni nalog (backend model + API +
frontend modal) s izračunom ukupnog iznosa za isplatu.

Upload računa sada odmah upisuje redak u dodatne troškove, a asinkroni OCR
(Celery) naknadno pokušava popuniti broj računa i iznos iz slike/PDF-a.

Uvedena je invalidacija PDF cache-a nakon promjena računa/dodatnih troškova
kako bi generirani PDF uvijek prikazivao najnovije podatke.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-19 21:23:29 +02:00
parent d35eaeccf4
commit ae35a6041d
14 changed files with 836 additions and 19 deletions

View File

@@ -712,10 +712,32 @@ export async function fetchWorkOrderById(workOrderId) {
export async function fetchWorkOrderTaskServiceContext(workOrderId) {
if (!workOrderId) {
return { tasks: [] };
return { tasks: [], additional_costs_table: null };
}
const payload = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/task-service-context/`);
return payload && typeof payload === 'object' ? payload : { tasks: [] };
return payload && typeof payload === 'object' ? payload : { tasks: [], additional_costs_table: null };
}
export async function fetchWorkOrderAdditionalCostsTable(workOrderId) {
if (!workOrderId) {
return { data: { rows: [] }, total_for_payout: '0.00' };
}
const payload = await api.get(`fleet/work-orders/${encodeURIComponent(workOrderId)}/additional-costs-table/`);
return payload && typeof payload === 'object'
? payload
: { data: { rows: [] }, total_for_payout: '0.00' };
}
export async function updateWorkOrderAdditionalCostsTable(workOrderId, data) {
if (!workOrderId) {
throw new Error('Work order ID je obavezan.');
}
const payload = await api.put(
`fleet/work-orders/${encodeURIComponent(workOrderId)}/additional-costs-table/`,
data ?? { rows: [] },
);
showToast('Dodatni troškovi su uspješno spremljeni.', 'success');
return payload;
}
export async function updateTaskWorkHoursTable(taskId, data) {