diff --git a/backend/modules/fleet/tests/test_work_order_images_endpoint.py b/backend/modules/fleet/tests/test_work_order_images_endpoint.py index f08692e..6849159 100644 --- a/backend/modules/fleet/tests/test_work_order_images_endpoint.py +++ b/backend/modules/fleet/tests/test_work_order_images_endpoint.py @@ -639,6 +639,40 @@ class WorkOrderImagesEndpointTests(TestCase): self.assertNotIn('Liebherr LTM 1090', second_header) self.assertNotIn('MT150726', second_header) + def test_monthly_work_orders_archive_includes_work_orders_for_user_even_without_assigned_task(self): + other_user = get_user_model().objects.create_user( + username=f'wo-other-{uuid.uuid4().hex[:8]}', + email=f'wo-other-{uuid.uuid4().hex[:8]}@example.test', + password='test1234', + ) + linked_work_order = WorkOrder.objects.create( + vehicle=self.vehicle, + creator=self.user, + display_code='MT170726', + purpose='kontrola', + ) + Task.objects.create( + title='Zadatak drugog servisera', + assigned_to=other_user, + vehicle=self.vehicle, + work_order=linked_work_order, + scheduled_date=date(2033, 12, 20), + ) + WorkOrderInvoice.objects.create( + work_order=linked_work_order, + naziv_racuna='Prosinac račun osoba', + datum='2033-12-12', + image=create_test_pdf('racun-prosinac-osoba.pdf'), + created_by=self.user, + ) + + response = self.client.get('/api/fleet/reports/monthly-work-orders-archive/?year=2033&month=12') + self.assertEqual(response.status_code, 200, response.content) + + archive = zipfile.ZipFile(BytesIO(response.content)) + self.assertIn('MT150726.work-order.pdf', archive.namelist()) + self.assertIn('MT170726.work-order.pdf', archive.namelist()) + def test_monthly_work_orders_archive_contains_work_orders_and_invoices_folder(self): WorkOrderInvoice.objects.create( work_order=self.work_order, diff --git a/backend/modules/fleet/views.py b/backend/modules/fleet/views.py index 6d7ffa0..02f7329 100644 --- a/backend/modules/fleet/views.py +++ b/backend/modules/fleet/views.py @@ -3030,28 +3030,7 @@ def _build_monthly_service_tasks_archive_content(*, user, year, month): def _build_monthly_work_orders_archive_content(*, user, year, month): - from modules.task_management.models import Task - - monthly_tasks = ( - Task.objects - .filter( - assigned_to=user, - is_active=True, - scheduled_date__year=year, - scheduled_date__month=month, - work_order__isnull=False, - work_order__is_active=True, - ) - .select_related('work_order') - .order_by('scheduled_date', 'created_at') - ) - ordered_work_order_ids = [] - seen_work_order_ids = set() - for task in monthly_tasks: - if not task.work_order_id or task.work_order_id in seen_work_order_ids: - continue - seen_work_order_ids.add(task.work_order_id) - ordered_work_order_ids.append(task.work_order_id) + ordered_work_order_ids = _user_monthly_work_order_ids(user=user, year=year, month=month) if not ordered_work_order_ids: raise DRFValidationError({'detail': 'Nema putnih naloga za odabrani mjesec.'}) @@ -3178,26 +3157,80 @@ def _get_cached_generated_archive(*, user, archive_type, year, month): ) +def _user_monthly_work_order_ids(*, user, year, month): + from modules.task_management.models import Task + + task_work_order_ids = set( + Task.objects + .filter( + is_active=True, + scheduled_date__year=year, + scheduled_date__month=month, + work_order__isnull=False, + work_order__is_active=True, + ) + .filter( + Q(assigned_to=user) + | Q(work_order__creator=user) + | Q(vehicle__assigned_servicer=user) + ) + .values_list('work_order_id', flat=True) + .distinct() + ) + work_order_ids = set( + WorkOrder.objects + .filter( + is_active=True, + date__year=year, + date__month=month, + ) + .filter( + Q(creator=user) + | Q(vehicle__assigned_servicer=user) + ) + .values_list('id', flat=True) + .distinct() + ) + return list(dict.fromkeys([*task_work_order_ids, *work_order_ids])) + + def _latest_monthly_archive_source_update(*, user, archive_type, year, month): from modules.task_management.models import Task + task_work_order_ids = _user_monthly_work_order_ids(user=user, year=year, month=month) base_tasks = Task.objects.filter( - assigned_to=user, is_active=True, scheduled_date__year=year, scheduled_date__month=month, work_order__isnull=False, work_order__is_active=True, + ).filter( + Q(assigned_to=user) + | Q(work_order__creator=user) + | Q(vehicle__assigned_servicer=user) + ) + base_work_orders = WorkOrder.objects.filter( + is_active=True, + date__year=year, + date__month=month, + ).filter( + Q(creator=user) + | Q(vehicle__assigned_servicer=user) ) latest_candidates = [ base_tasks.aggregate(value=Max('updated_at')).get('value'), base_tasks.aggregate(value=Max('work_order__updated_at')).get('value'), base_tasks.aggregate(value=Max('work_order__vehicle__updated_at')).get('value'), base_tasks.aggregate(value=Max('work_hours_table__updated_at')).get('value'), + base_work_orders.aggregate(value=Max('updated_at')).get('value'), + base_work_orders.aggregate(value=Max('vehicle__updated_at')).get('value'), ] if archive_type == 'work_orders': latest_candidates.append( - base_tasks.aggregate(value=Max('work_order__invoices__updated_at')).get('value') + WorkOrderInvoice.objects.filter( + work_order_id__in=task_work_order_ids, + is_active=True, + ).aggregate(value=Max('updated_at')).get('value') ) latest_values = [value for value in latest_candidates if value is not None] if not latest_values: