fix: ispravi prikaz računa u admin/frontendu i smanji PDF slike
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

- admin.py: thumbnail_preview u WorkOrderInvoiceInline i WorkOrderInvoiceAdmin
  prikazuje slike/PDF veze putem optimiziranog image endpointa
- serializers.py: image_url sada uključuje ?w=1280&q=80&fmt=jpeg za ne-PDF slike
- views.py: doda _compress_image_for_pdf() helper, zamijeni ImageReader(photo.image)
  s kompresiranom JPEG verzijom na oba mjesta u PDF generiranju
- tasks.py: kompresija invoice slike u JPEG u memoriji prije ImageReader poziva
- WorkOrderInvoicesPdfPage.jsx:
  * InvoiceImagePreview prikazuje 'Učitavanje...' dok se blob dohvaća (ne 401 fallback)
  * uklonjen resolveMediaUrl fallback koji uzrokuje 401 greške
  * svaka invoice kartica je klikabilna i otvara InvoiceDetailModal
  * InvoiceDetailModal prikazuje detalje i uvećanu sliku/PDF vezu

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-31 11:54:34 +02:00
parent ae6ae08fb1
commit 525152b817
5 changed files with 207 additions and 30 deletions

View File

@@ -208,6 +208,32 @@ def _docx_filename(work_order, doc_type):
return f"{display_code}.work-order.docx"
def _compress_image_for_pdf(image_field, max_width=1280, quality=75):
"""
Otvori image_field (Django FileField), kompresiraj na max_width JPEG u memoriji,
vrati ImageReader spreman za reportlab. Vraća None ako slika nije dostupna.
"""
try:
image_field.open('rb')
with Image.open(image_field) as src:
img = src.convert('RGB')
if img.width > max_width:
ratio = max_width / float(img.width)
new_h = max(1, int(img.height * ratio))
img = img.resize((max_width, new_h), Image.LANCZOS)
buf = BytesIO()
img.save(buf, format='JPEG', quality=quality, optimize=True)
buf.seek(0)
return ImageReader(buf)
except Exception:
return None
finally:
try:
image_field.close()
except Exception:
pass
def _get_cached_pdf(work_order, pdf_type):
now = timezone.now()
expected_filename = _pdf_filename(work_order, pdf_type)
@@ -1166,7 +1192,9 @@ def _build_work_order_service_records_pdf(work_order):
prepared = []
for photo in row_photos:
try:
image_reader = ImageReader(photo.image)
image_reader = _compress_image_for_pdf(photo.image)
if image_reader is None:
continue
source_w, source_h = image_reader.getSize()
if not source_w or not source_h:
continue
@@ -1390,7 +1418,9 @@ def _build_service_record_pdf(service_record):
prepared = []
for photo in row_photos:
try:
image_reader = ImageReader(photo.image)
image_reader = _compress_image_for_pdf(photo.image)
if image_reader is None:
continue
source_w, source_h = image_reader.getSize()
if not source_w or not source_h:
continue