Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("ngen", "0023_alter_casetemplate_case_tlp_and_more_squashed_0025_remove_casetemplate_priority_and_more"),
]

operations = [
migrations.AlterField(
model_name="event",
name="date",
field=models.DateTimeField(
blank=True,
default=None,
null=True,
),
),
migrations.AddField(
model_name="case",
name="notification_delay_seconds",
field=models.FloatField(
blank=True,
default=None,
help_text="Seconds between the event date and when the case was first attended. Used to measure MTTR.",
null=True,
),
),
]
27 changes: 27 additions & 0 deletions ngen/models/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ class Case(

attend_date = models.DateTimeField(null=True, blank=True, default=None)
solve_date = models.DateTimeField(null=True, blank=True, default=None)
notification_delay_seconds = models.FloatField(
null=True,
blank=True,
default=None,
help_text=gettext_lazy(
"Seconds between the event date and when the case was first attended. "
"Used to measure MTTR."
),
)

report_message_id = models.CharField(
max_length=255, null=True, blank=True, default=None
Expand Down Expand Up @@ -242,6 +251,22 @@ def delete_events(self):
for event in self.events.all():
event.delete()

def _calculate_notification_delay(self):
"""Calculate seconds between the earliest event date and the current
attend_date (when the case is first opened/responded).
Only calculated once (first transition to attended state)."""
if self.notification_delay_seconds is not None:
return
if not self.attend_date:
return
events = self._temp_events if self._temp_events else self.events.all()
for event in events:
if event.date:
self.notification_delay_seconds = (
self.attend_date - event.date
).total_seconds()
return

@hook(BEFORE_CREATE)
def before_create(self):
self.report_message_id = make_msgid(domain=DNS_NAME)
Expand All @@ -250,6 +275,7 @@ def before_create(self):
if self.state.attended:
self.attend_date = timezone.now()
self.solve_date = None
self._calculate_notification_delay()
elif self.state.solved:
self.solve_date = timezone.now()

Expand Down Expand Up @@ -285,6 +311,7 @@ def before_update(self):
if self.state.attended:
self.attend_date = timezone.now()
self.solve_date = None
self._calculate_notification_delay()
self.communicate_open()
elif self.state.solved:
self.solve_date = timezone.now()
Expand Down
2 changes: 2 additions & 0 deletions ngen/serializers/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ class Meta:
"blocked",
"merged",
"tags",
"notification_delay_seconds",
)
read_only_fields = [
"attend_date",
Expand All @@ -293,6 +294,7 @@ class Meta:
"created_by",
"notification_count",
"blocked",
"notification_delay_seconds",
]

def get_evidence(self, obj):
Expand Down
Loading