138 lines
4.8 KiB
Python
138 lines
4.8 KiB
Python
from datetime import datetime
|
|
from io import BytesIO
|
|
from unittest.mock import MagicMock, patch
|
|
from uuid import uuid4
|
|
from zipfile import ZipFile
|
|
|
|
from openpyxl import load_workbook
|
|
from rest_framework import status
|
|
from rest_framework.test import APITestCase
|
|
|
|
from utils.clients.gooyal_advertising_client.models.ticket_state_enum import TicketStateEnum
|
|
|
|
|
|
class GenerateReportTests(APITestCase):
|
|
def _build_ticket(self, user_uuid=None):
|
|
ticket = MagicMock()
|
|
ticket.uuid = uuid4()
|
|
ticket.user = user_uuid or uuid4()
|
|
ticket.title = "Login issue"
|
|
ticket.description = "Cannot login"
|
|
ticket.state = TicketStateEnum(10)
|
|
ticket.created_at = datetime(2026, 5, 20, 10, 0)
|
|
ticket.updated_at = datetime(2026, 5, 21, 10, 0)
|
|
return ticket
|
|
|
|
def _build_user(self, user_uuid):
|
|
user = MagicMock()
|
|
user.uuid = user_uuid
|
|
user.username = "alice"
|
|
user.first_name = "Alice"
|
|
user.last_name = "Doe"
|
|
user.email = "alice@example.com"
|
|
user.phone_number = "09120000000"
|
|
user.address = "Tehran"
|
|
return user
|
|
|
|
@patch("apps.reports.services.data_sources.ReportDataSources.fetch_users_for_tickets")
|
|
@patch("apps.reports.services.data_sources.ReportDataSources.fetch_application_tickets")
|
|
def test_generate_report_returns_zip_with_two_excel_files(
|
|
self,
|
|
mock_fetch_tickets,
|
|
mock_fetch_users,
|
|
):
|
|
ticket = self._build_ticket()
|
|
user = self._build_user(ticket.user)
|
|
mock_fetch_tickets.return_value = [ticket]
|
|
mock_fetch_users.return_value = [user]
|
|
|
|
response = self.client.post("/api/reports/generate/")
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response["Content-Type"], "application/zip")
|
|
self.assertEqual(
|
|
response["Content-Disposition"],
|
|
'attachment; filename="crm-reports.zip"',
|
|
)
|
|
|
|
with ZipFile(BytesIO(response.content)) as archive:
|
|
self.assertEqual(
|
|
set(archive.namelist()),
|
|
{"users-report.xlsx", "tickets-report.xlsx"},
|
|
)
|
|
|
|
users_workbook = load_workbook(BytesIO(archive.read("users-report.xlsx")))
|
|
users_sheet = users_workbook.active
|
|
self.assertEqual(users_sheet["A1"].value, "Users Report")
|
|
self.assertEqual(
|
|
[cell.value for cell in users_sheet[2]],
|
|
[
|
|
"User UUID",
|
|
"Username",
|
|
"First Name",
|
|
"Last Name",
|
|
"Email",
|
|
"Phone Number",
|
|
"Address",
|
|
],
|
|
)
|
|
self.assertEqual(
|
|
[cell.value for cell in users_sheet[3]],
|
|
[
|
|
str(user.uuid),
|
|
"alice",
|
|
"Alice",
|
|
"Doe",
|
|
"alice@example.com",
|
|
"09120000000",
|
|
"Tehran",
|
|
],
|
|
)
|
|
|
|
tickets_workbook = load_workbook(
|
|
BytesIO(archive.read("tickets-report.xlsx"))
|
|
)
|
|
tickets_sheet = tickets_workbook.active
|
|
self.assertEqual(tickets_sheet["A1"].value, "Tickets Report")
|
|
self.assertEqual(
|
|
[cell.value for cell in tickets_sheet[2]],
|
|
[
|
|
"Ticket UUID",
|
|
"User UUID",
|
|
"Title",
|
|
"Description",
|
|
"State",
|
|
"Created At",
|
|
"Updated At",
|
|
],
|
|
)
|
|
self.assertEqual(
|
|
[cell.value for cell in tickets_sheet[3]],
|
|
[
|
|
str(ticket.uuid),
|
|
str(ticket.user),
|
|
"Login issue",
|
|
"Cannot login",
|
|
"CLOSED",
|
|
"2026-05-20 10:00:00",
|
|
"2026-05-21 10:00:00",
|
|
],
|
|
)
|
|
|
|
@patch("apps.reports.services.data_sources.ReportDataSources.fetch_users_for_tickets")
|
|
@patch("apps.reports.services.data_sources.ReportDataSources.fetch_application_tickets")
|
|
def test_generate_report_skips_missing_users(
|
|
self,
|
|
mock_fetch_tickets,
|
|
mock_fetch_users,
|
|
):
|
|
ticket = self._build_ticket()
|
|
mock_fetch_tickets.return_value = [ticket]
|
|
mock_fetch_users.return_value = [None]
|
|
|
|
response = self.client.post("/api/reports/generate/")
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
with ZipFile(BytesIO(response.content)) as archive:
|
|
users_workbook = load_workbook(BytesIO(archive.read("users-report.xlsx")))
|
|
self.assertIsNone(users_workbook.active["A3"].value)
|