django-helpdesk/helpdesk/tests/test_time_spent_auto.py
2025-03-24 09:43:19 -10:00

448 lines
15 KiB
Python

from datetime import datetime, timedelta
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.test import TestCase, override_settings
from django.test.client import Client
from django.urls import reverse
from helpdesk.models import FollowUp, Queue, Ticket
from helpdesk import settings as helpdesk_settings
import uuid
@override_settings(USE_TZ=True)
class TimeSpentAutoTestCase(TestCase):
def setUp(self):
"""Creates a queue, ticket and user."""
self.queue_public = Queue.objects.create(
title="Queue 1",
slug="q1",
allow_public_submission=True,
dedicated_time=timedelta(minutes=60),
)
self.ticket_data = dict(
queue=self.queue_public,
title="test ticket",
description="test ticket description",
)
self.user = User.objects.create(
username="staff",
email="staff@example.com",
password=make_password("Test1234"),
is_staff=True,
is_superuser=False,
is_active=True,
)
self.client = Client()
def loginUser(self, is_staff=True):
"""Create a staff user and login"""
User = get_user_model()
self.user = User.objects.create(
username="User_1",
is_staff=is_staff,
)
self.user.set_password("pass")
self.user.save()
self.client.login(username="User_1", password="pass")
def test_add_two_followups_time_spent_auto(self):
"""Tests automatic time_spent calculation."""
# activate automatic calculation
helpdesk_settings.FOLLOWUP_TIME_SPENT_AUTO = True
# ticket creation date, follow-up creation date, assertion value
TEST_VALUES = (
# friday
(
"2024-03-01T00:00:00+00:00",
"2024-03-01T09:30:10+00:00",
timedelta(hours=9, minutes=30, seconds=10),
),
(
"2024-03-01T00:00:00+00:00",
"2024-03-01T23:59:58+00:00",
timedelta(hours=23, minutes=59, seconds=58),
),
(
"2024-03-01T00:00:00+00:00",
"2024-03-01T23:59:59+00:00",
timedelta(hours=23, minutes=59, seconds=59),
),
(
"2024-03-01T00:00:00+00:00",
"2024-03-02T00:00:00+00:00",
timedelta(hours=24),
),
(
"2024-03-01T00:00:00+00:00",
"2024-03-02T09:00:00+00:00",
timedelta(hours=33),
),
(
"2024-03-01T00:00:00+00:00",
"2024-03-03T00:00:00+00:00",
timedelta(hours=48),
),
)
for ticket_time, fup_time, assertion_delta in TEST_VALUES:
# create and setup test ticket time
ticket = Ticket.objects.create(**self.ticket_data)
ticket_time_p = datetime.strptime(ticket_time, "%Y-%m-%dT%H:%M:%S%z")
ticket.created = ticket_time_p
ticket.modified = ticket_time_p
ticket.save()
fup_time_p = datetime.strptime(fup_time, "%Y-%m-%dT%H:%M:%S%z")
followup1 = FollowUp.objects.create(
ticket=ticket,
date=fup_time_p,
title="Testing followup",
comment="Testing followup time spent",
public=True,
user=self.user,
new_status=1,
message_id=uuid.uuid4().hex,
time_spent=None,
)
self.assertEqual(
followup1.time_spent.total_seconds(), assertion_delta.total_seconds()
)
self.assertEqual(
ticket.time_spent.total_seconds(), assertion_delta.total_seconds()
)
# adding a second follow-up at different intervals
for delta in (
timedelta(seconds=1),
timedelta(minutes=1),
timedelta(hours=1),
timedelta(days=1),
timedelta(days=10),
):
followup2 = FollowUp.objects.create(
ticket=ticket,
date=followup1.date + delta,
title="Testing followup 2",
comment="Testing followup time spent 2",
public=True,
user=self.user,
new_status=1,
message_id=uuid.uuid4().hex,
time_spent=None,
)
self.assertEqual(
followup2.time_spent.total_seconds(), delta.total_seconds()
)
self.assertEqual(
ticket.time_spent.total_seconds(),
assertion_delta.total_seconds() + delta.total_seconds(),
)
# delete second follow-up as we test it with many intervals
followup2.delete()
def test_followup_time_spent_auto_opening_hours(self):
"""Tests automatic time_spent calculation with opening hours and holidays."""
# activate automatic calculation
helpdesk_settings.FOLLOWUP_TIME_SPENT_AUTO = True
helpdesk_settings.FOLLOWUP_TIME_SPENT_OPENING_HOURS = {
"monday": (0, 23.9999),
"tuesday": (8, 18),
"wednesday": (8.5, 18.5),
"thursday": (0, 10),
"friday": (13, 23),
"saturday": (0, 0),
"sunday": (0, 0),
}
# adding holidays
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_HOLIDAYS = (
"2024-03-18",
"2024-03-19",
"2024-03-20",
"2024-03-21",
"2024-03-22",
)
# ticket creation date, follow-up creation date, assertion value
TEST_VALUES = (
# monday
(
"2024-03-04T00:00:00+00:00",
"2024-03-04T09:30:10+00:00",
timedelta(hours=9, minutes=30, seconds=10),
),
# tuesday
(
"2024-03-05T07:00:00+00:00",
"2024-03-05T09:00:00+00:00",
timedelta(hours=1),
),
(
"2024-03-05T17:50:00+00:00",
"2024-03-05T17:51:00+00:00",
timedelta(minutes=1),
),
(
"2024-03-05T17:50:00+00:00",
"2024-03-05T19:51:00+00:00",
timedelta(minutes=10),
),
(
"2024-03-05T18:00:00+00:00",
"2024-03-05T23:59:59+00:00",
timedelta(hours=0),
),
(
"2024-03-05T20:00:00+00:00",
"2024-03-05T20:59:59+00:00",
timedelta(hours=0),
),
# wednesday
(
"2024-03-06T08:00:00+00:00",
"2024-03-06T09:01:00+00:00",
timedelta(minutes=31),
),
(
"2024-03-06T01:00:00+00:00",
"2024-03-06T19:30:10+00:00",
timedelta(hours=10),
),
(
"2024-03-06T18:01:00+00:00",
"2024-03-06T19:00:00+00:00",
timedelta(minutes=29),
),
# thursday
(
"2024-03-07T00:00:00+00:00",
"2024-03-07T09:30:10+00:00",
timedelta(hours=9, minutes=30, seconds=10),
),
(
"2024-03-07T09:30:00+00:00",
"2024-03-07T10:30:00+00:00",
timedelta(minutes=30),
),
# friday
(
"2024-03-08T00:00:00+00:00",
"2024-03-08T23:30:10+00:00",
timedelta(hours=10),
),
# saturday
(
"2024-03-09T00:00:00+00:00",
"2024-03-09T09:30:10+00:00",
timedelta(hours=0),
),
# sunday
(
"2024-03-10T00:00:00+00:00",
"2024-03-10T09:30:10+00:00",
timedelta(hours=0),
),
# monday to sunday
(
"2024-03-04T04:00:00+00:00",
"2024-03-10T09:00:00+00:00",
timedelta(hours=60),
),
# two weeks
(
"2024-03-04T04:00:00+00:00",
"2024-03-17T09:00:00+00:00",
timedelta(hours=124),
),
# three weeks, the third one is holidays
(
"2024-03-04T04:00:00+00:00",
"2024-03-24T09:00:00+00:00",
timedelta(hours=124),
),
(
"2024-03-18T04:00:00+00:00",
"2024-03-24T09:00:00+00:00",
timedelta(hours=0),
),
)
for ticket_time, fup_time, assertion_delta in TEST_VALUES:
# create and setup test ticket time
ticket = Ticket.objects.create(**self.ticket_data)
ticket_time_p = datetime.strptime(ticket_time, "%Y-%m-%dT%H:%M:%S%z")
ticket.created = ticket_time_p
ticket.modified = ticket_time_p
ticket.save()
fup_time_p = datetime.strptime(fup_time, "%Y-%m-%dT%H:%M:%S%z")
followup1 = FollowUp.objects.create(
ticket=ticket,
date=fup_time_p,
title="Testing followup",
comment="Testing followup time spent",
public=True,
user=self.user,
new_status=1,
message_id=uuid.uuid4().hex,
time_spent=None,
)
self.assertEqual(
followup1.time_spent.total_seconds(), assertion_delta.total_seconds()
)
self.assertEqual(
ticket.time_spent.total_seconds(), assertion_delta.total_seconds()
)
# removing opening hours and holidays
helpdesk_settings.FOLLOWUP_TIME_SPENT_OPENING_HOURS = {}
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_HOLIDAYS = ()
def test_followup_time_spent_auto_exclude_statuses(self):
"""Tests automatic time_spent calculation OPEN_STATUS exclusion."""
# activate automatic calculation
helpdesk_settings.FOLLOWUP_TIME_SPENT_AUTO = True
# Follow-ups with OPEN_STATUS are excluded from time counting
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_STATUSES = (Ticket.OPEN_STATUS,)
# create and setup test ticket time
ticket = Ticket.objects.create(**self.ticket_data)
ticket_time_p = datetime.strptime(
"2024-03-04T00:00:00+00:00", "%Y-%m-%dT%H:%M:%S%z"
)
ticket.created = ticket_time_p
ticket.modified = ticket_time_p
ticket.save()
fup_time_p = datetime.strptime(
"2024-03-10T00:00:00+00:00", "%Y-%m-%dT%H:%M:%S%z"
)
followup1 = FollowUp.objects.create(
ticket=ticket,
date=fup_time_p,
title="Testing followup",
comment="Testing followup time spent",
public=True,
user=self.user,
new_status=1,
message_id=uuid.uuid4().hex,
time_spent=None,
)
# The Follow-up time_spent should be zero as the default OPEN_STATUS was excluded from calculation
self.assertEqual(followup1.time_spent.total_seconds(), 0.0)
self.assertEqual(ticket.time_spent.total_seconds(), 0.0)
# Remove status exclusion
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_STATUSES = ()
def test_followup_time_spent_auto_exclude_queues(self):
"""Tests automatic time_spent calculation queues exclusion."""
# activate automatic calculation
helpdesk_settings.FOLLOWUP_TIME_SPENT_AUTO = True
# Follow-ups within the default queue are excluded from time counting
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_QUEUES = ("q1",)
# create and setup test ticket time
ticket = Ticket.objects.create(**self.ticket_data)
ticket_time_p = datetime.strptime(
"2024-03-04T00:00:00+00:00", "%Y-%m-%dT%H:%M:%S%z"
)
ticket.created = ticket_time_p
ticket.modified = ticket_time_p
ticket.save()
fup_time_p = datetime.strptime(
"2024-03-10T00:00:00+00:00", "%Y-%m-%dT%H:%M:%S%z"
)
followup1 = FollowUp.objects.create(
ticket=ticket,
date=fup_time_p,
title="Testing followup",
comment="Testing followup time spent",
public=True,
user=self.user,
new_status=1,
message_id=uuid.uuid4().hex,
time_spent=None,
)
# The Follow-up time_spent should be zero as the default queue was excluded from calculation
self.assertEqual(followup1.time_spent.total_seconds(), 0.0)
self.assertEqual(ticket.time_spent.total_seconds(), 0.0)
# Remove queues exclusion
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_QUEUES = ()
def test_http_followup_time_spent_auto_exclude_queues(self):
"""Tests automatic time_spent calculation queues exclusion with client"""
# activate automatic calculation
helpdesk_settings.FOLLOWUP_TIME_SPENT_AUTO = True
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_QUEUES = ("stop1", "stop2")
# make staff user
self.loginUser()
# create queues
queues_sequence = ("new", "stop1", "resume1", "stop2", "resume2", "end")
queues = dict()
for slug in queues_sequence:
queues[slug] = Queue.objects.create(
title=slug,
slug=slug,
)
# create ticket
initial_data = {
"title": "Queue change ticket test",
"queue": queues["new"],
"assigned_to": self.user,
"status": Ticket.OPEN_STATUS,
"created": datetime.strptime(
"2024-04-09T08:00:00+00:00", "%Y-%m-%dT%H:%M:%S%z"
),
}
ticket = Ticket.objects.create(**initial_data)
# create a change queue follow-up every hour
# first follow-up created at the same time of the ticket without queue change
# new --1h--> stop1 --0h--> resume1 --1h--> stop2 --0h--> resume2 --1h--> end
for i, queue in enumerate(queues_sequence):
# create follow-up
post_data = {
"comment": "ticket in queue {}".format(queue),
"queue": queues[queue].id,
}
self.client.post(
reverse("helpdesk:update", kwargs={"ticket_id": ticket.id}), post_data
)
latest_fup = ticket.followup_set.latest("id")
latest_fup.date = ticket.created + timedelta(hours=i)
latest_fup.time_spent = None
latest_fup.save()
# total ticket time for followups is 5 hours
self.assertEqual(latest_fup.date - ticket.created, timedelta(hours=5))
# calculated time spent with 2 hours exclusion is 3 hours
self.assertEqual(
ticket.time_spent.total_seconds(), timedelta(hours=3).total_seconds()
)
# remove queues exclusion
helpdesk_settings.FOLLOWUP_TIME_SPENT_EXCLUDE_QUEUES = ()