feat: dodaj ishodište i PDF račune za putni nalog
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:
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user