feat: dodaj ishodište i PDF račune za putni nalog
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

Dodano je origin_location polje kroz backend model, serializer, admin i UI
modal za kreiranje/uređivanje putnog naloga (default: Zagreb).

Računi putnog naloga sada prihvaćaju slike i PDF datoteke, uz backend
validaciju formata, podršku za serving PDF-a i prilagodbu preview prikaza.

Za greške uploada računa dodan je error toast kako bi poruke validacije bile
vidljive korisniku odmah u sučelju.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-19 19:54:15 +02:00
parent cbcbf0b3af
commit d35eaeccf4
12 changed files with 175 additions and 14 deletions

View File

@@ -3,6 +3,7 @@
from io import BytesIO
import base64
from datetime import timedelta
from pathlib import Path
from PIL import Image, UnidentifiedImageError
from django.conf import settings
@@ -401,6 +402,7 @@ def _build_work_order_pdf(work_order):
transport_total = float(work_order.servicer_vehicle_fuel_cost or 0.0)
grand_total = daily_total + transport_total
place_label = (work_order.location or 'Zagreb').split(',')[0].strip() or 'Zagreb'
origin_label = (work_order.origin_location or 'Zagreb').split(',')[0].strip() or 'Zagreb'
invoice_names = [inv.naziv_racuna for inv in invoices[:5] if inv.naziv_racuna]
attachments_text = ', '.join(invoice_names) if invoice_names else '-'
assigned_servicer_vehicle = (
@@ -598,7 +600,7 @@ def _build_work_order_pdf(work_order):
y,
[
["RELACIJA od", "RELACIJA do", "Vrsta prijevoznog sredstva", "Razred [km]", "Iznos za prijevoz", "Ukupan iznos"],
[place_label or '-', work_order.location or '-', f"{servicer_vehicle_label}, {servicer_vehicle_registration}", str(work_order.distance or 0), _fmt_eur(transport_total), _fmt_eur(transport_total)],
[origin_label or '-', work_order.location or '-', f"{servicer_vehicle_label}, {servicer_vehicle_registration}", str(work_order.distance or 0), _fmt_eur(transport_total), _fmt_eur(transport_total)],
["", "", "", "", "", ""],
["", "", "", "", "", ""],
],
@@ -1601,7 +1603,7 @@ class WorkOrderViewSet(viewsets.ModelViewSet):
<td>{escape(invoice.lokacija or '-')}</td>
<td>{escape(datum)}</td>
<td>{escape(invoice.opis or '-')}</td>
<td>{f'<a href="{escape(image_url)}" target="_blank" rel="noopener noreferrer">Otvori sliku</a>' if image_url else '-'}</td>
<td>{f'<a href="{escape(image_url)}" target="_blank" rel="noopener noreferrer">Otvori dokument</a>' if image_url else '-'}</td>
</tr>
"""
)
@@ -1791,6 +1793,17 @@ class WorkOrderInvoiceViewSet(viewsets.ModelViewSet):
if not invoice.image:
raise DRFValidationError({"detail": "Slika računa nije dostupna."})
suffix = Path(invoice.image.name or '').suffix.lower()
if suffix == '.pdf':
invoice.image.open('rb')
try:
response = HttpResponse(invoice.image.read(), content_type='application/pdf')
finally:
invoice.image.close()
response['Cache-Control'] = 'private, max-age=86400'
response['Content-Disposition'] = f'inline; filename="invoice-{invoice.pk}.pdf"'
return response
width = _parse_positive_int(
request.query_params.get('w'),
field_name='w',