fix: restore archive downloads and task report context
Restore the monthly fleet archive task and routes so generated ZIP downloads work again. Also populate service report DOCX headers from the selected task/work-order context and cover the direct and archived export flows with regression tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -836,23 +836,72 @@ def process_work_order_invoice_ocr(invoice_id):
|
||||
|
||||
|
||||
@shared_task
|
||||
def cleanup_expired_generated_pdfs_task():
|
||||
now = timezone.now()
|
||||
expired = GeneratedWorkOrderPdf.objects.filter(
|
||||
is_active=True,
|
||||
expires_at__isnull=False,
|
||||
expires_at__lte=now,
|
||||
def build_monthly_archive_cached_task(generated_archive_id):
|
||||
from .models import GeneratedFleetArchive
|
||||
from .services import NotificationService
|
||||
from .views import (
|
||||
_build_monthly_service_tasks_archive_content,
|
||||
_build_monthly_work_orders_archive_content,
|
||||
_notify_monthly_archive_request,
|
||||
)
|
||||
deleted = 0
|
||||
for item in expired:
|
||||
if item.file:
|
||||
item.file.delete(save=False)
|
||||
item.is_active = False
|
||||
item.status = 'failed'
|
||||
item.error_message = 'PDF cache istekao.'
|
||||
item.save(update_fields=['is_active', 'status', 'error_message', 'updated_at'])
|
||||
deleted += 1
|
||||
return {"deleted": deleted}
|
||||
|
||||
generated = (
|
||||
GeneratedFleetArchive.objects
|
||||
.select_related('requested_by')
|
||||
.filter(pk=generated_archive_id, is_active=True)
|
||||
.first()
|
||||
)
|
||||
if generated is None:
|
||||
return {"status": "failed", "error": "Generated archive record not found"}
|
||||
|
||||
try:
|
||||
if generated.archive_type == 'service_tasks':
|
||||
archive_content = _build_monthly_service_tasks_archive_content(
|
||||
user=generated.requested_by,
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
)
|
||||
else:
|
||||
archive_content = _build_monthly_work_orders_archive_content(
|
||||
user=generated.requested_by,
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
)
|
||||
|
||||
if not archive_content:
|
||||
raise ValueError('ZIP arhiva je prazna.')
|
||||
|
||||
filename = generated.filename or f"{generated.archive_type}-{generated.year}-{generated.month}.zip"
|
||||
generated.file.save(filename, ContentFile(archive_content), save=False)
|
||||
generated.status = 'ready'
|
||||
generated.error_message = ''
|
||||
generated.save(update_fields=['file', 'status', 'error_message', 'updated_at'])
|
||||
|
||||
if generated.requested_by:
|
||||
_notify_monthly_archive_request(
|
||||
user=generated.requested_by,
|
||||
archive_type=generated.archive_type,
|
||||
stage='completed',
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
generated_archive=generated,
|
||||
)
|
||||
return {"status": "ready", "generated_archive_id": str(generated.pk)}
|
||||
except Exception as exc:
|
||||
generated.status = 'failed'
|
||||
generated.error_message = str(exc)
|
||||
generated.save(update_fields=['status', 'error_message', 'updated_at'])
|
||||
if generated.requested_by:
|
||||
_notify_monthly_archive_request(
|
||||
user=generated.requested_by,
|
||||
archive_type=generated.archive_type,
|
||||
stage='failed',
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
generated_archive=generated,
|
||||
)
|
||||
logger.exception("Greška kod build_monthly_archive_cached_task: %s", exc)
|
||||
return {"status": "failed", "error": str(exc)}
|
||||
|
||||
|
||||
@shared_task
|
||||
@@ -875,6 +924,26 @@ def cleanup_expired_generated_archives_task():
|
||||
return {"deleted": deleted}
|
||||
|
||||
|
||||
@shared_task
|
||||
def cleanup_expired_generated_pdfs_task():
|
||||
now = timezone.now()
|
||||
expired = GeneratedWorkOrderPdf.objects.filter(
|
||||
is_active=True,
|
||||
expires_at__isnull=False,
|
||||
expires_at__lte=now,
|
||||
)
|
||||
deleted = 0
|
||||
for item in expired:
|
||||
if item.file:
|
||||
item.file.delete(save=False)
|
||||
item.is_active = False
|
||||
item.status = 'failed'
|
||||
item.error_message = 'PDF cache istekao.'
|
||||
item.save(update_fields=['is_active', 'status', 'error_message', 'updated_at'])
|
||||
deleted += 1
|
||||
return {"deleted": deleted}
|
||||
|
||||
|
||||
@shared_task
|
||||
def build_work_order_pdf_cached_task(generated_pdf_id):
|
||||
from .views import _build_work_order_pdf, _build_work_order_service_records_pdf
|
||||
@@ -954,98 +1023,4 @@ def build_work_order_pdf_cached_task(generated_pdf_id):
|
||||
},
|
||||
)
|
||||
logger.exception("Greška kod build_work_order_pdf_cached_task: %s", exc)
|
||||
return {"status": "failed", "error": str(exc)}
|
||||
|
||||
|
||||
@shared_task
|
||||
def build_monthly_archive_cached_task(generated_archive_id):
|
||||
from .services import NotificationService
|
||||
from .views import (
|
||||
_build_monthly_service_tasks_archive_content,
|
||||
_build_monthly_work_orders_archive_content,
|
||||
_generated_archive_filename_for_user,
|
||||
)
|
||||
|
||||
generated = (
|
||||
GeneratedFleetArchive.objects
|
||||
.select_related('requested_by')
|
||||
.filter(pk=generated_archive_id, is_active=True)
|
||||
.first()
|
||||
)
|
||||
if generated is None:
|
||||
return {'error': 'Generated ZIP zapis nije pronađen.'}
|
||||
|
||||
requested_by = generated.requested_by
|
||||
if requested_by is None:
|
||||
generated.status = 'failed'
|
||||
generated.error_message = 'Korisnik koji je zatražio ZIP arhivu nije dostupan.'
|
||||
generated.save(update_fields=['status', 'error_message', 'updated_at'])
|
||||
return {'status': 'failed', 'error': generated.error_message}
|
||||
|
||||
try:
|
||||
if generated.archive_type == 'work_orders':
|
||||
archive_bytes = _build_monthly_work_orders_archive_content(
|
||||
user=requested_by,
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
)
|
||||
else:
|
||||
archive_bytes = _build_monthly_service_tasks_archive_content(
|
||||
user=requested_by,
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
)
|
||||
|
||||
filename = generated.filename or _generated_archive_filename_for_user(
|
||||
requested_by,
|
||||
year=generated.year,
|
||||
month=generated.month,
|
||||
archive_type=generated.archive_type,
|
||||
)
|
||||
generated.file.save(filename, ContentFile(archive_bytes), save=False)
|
||||
generated.status = 'ready'
|
||||
generated.error_message = ''
|
||||
generated.save(update_fields=['file', 'status', 'error_message', 'updated_at'])
|
||||
|
||||
NotificationService.create_notification(
|
||||
recipient=requested_by,
|
||||
title='ZIP arhiva spremna',
|
||||
message=f"ZIP arhiva je spremna za preuzimanje ({generated.month:02d}.{generated.year}.).",
|
||||
level='success',
|
||||
send_email=False,
|
||||
metadata={
|
||||
'entity_type': 'fleet_archive',
|
||||
'archive_type': generated.archive_type,
|
||||
'stage': 'completed',
|
||||
'year': generated.year,
|
||||
'month': generated.month,
|
||||
'generated_archive_id': str(generated.pk),
|
||||
'download_url': f"fleet/reports/generated-archives/{generated.pk}/download/",
|
||||
'filename': generated.filename or filename,
|
||||
'expires_at': generated.expires_at.isoformat() if generated.expires_at else None,
|
||||
'section': 'service-records',
|
||||
},
|
||||
)
|
||||
return {'status': 'ready', 'generated_archive_id': str(generated.pk)}
|
||||
except Exception as exc:
|
||||
generated.status = 'failed'
|
||||
generated.error_message = str(exc)
|
||||
generated.save(update_fields=['status', 'error_message', 'updated_at'])
|
||||
NotificationService.create_notification(
|
||||
recipient=requested_by,
|
||||
title='Greška kod ZIP arhive',
|
||||
message=f"Generiranje ZIP arhive nije uspjelo ({generated.month:02d}.{generated.year}.).",
|
||||
level='warning',
|
||||
send_email=False,
|
||||
metadata={
|
||||
'entity_type': 'fleet_archive',
|
||||
'archive_type': generated.archive_type,
|
||||
'stage': 'failed',
|
||||
'year': generated.year,
|
||||
'month': generated.month,
|
||||
'generated_archive_id': str(generated.pk),
|
||||
'section': 'service-records',
|
||||
},
|
||||
)
|
||||
logger.exception("Greška kod build_monthly_archive_cached_task: %s", exc)
|
||||
return {'status': 'failed', 'error': str(exc)}
|
||||
return {"status": "failed", "error": str(exc)}
|
||||
Reference in New Issue
Block a user