Skip to content

Commit 42d25d3

Browse files
Merge pull request #2213 from IFRCGo/feature/use-molnix-status-filtering-and-display
Use Molnix Status for Surge Alerts filtering
2 parents 7818e02 + 9558078 commit 42d25d3

File tree

11 files changed

+116
-163
lines changed

11 files changed

+116
-163
lines changed

api/management/commands/sync_molnix.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
from api.molnix_utils import MolnixApi
1111
from deployments.models import MolnixTag, MolnixTagGroup, Personnel, PersonnelDeployment
1212
from main.sentry import SentryMonitor
13-
from notifications.models import SurgeAlert, SurgeAlertCategory, SurgeAlertType
13+
from notifications.models import (
14+
SurgeAlert,
15+
SurgeAlertCategory,
16+
SurgeAlertStatus,
17+
SurgeAlertType,
18+
)
1419

1520
CRON_NAME = "sync_molnix"
1621

@@ -470,14 +475,13 @@ def sync_open_positions(molnix_positions, molnix_api, countries):
470475
# print(json.dumps(position, indent=2))
471476
go_alert.molnix_id = position["id"]
472477
go_alert.message = position["name"]
473-
go_alert.molnix_status = position["status"]
478+
go_alert.molnix_status = SurgeAlert.parse_molnix_status(position["status"])
474479
go_alert.event = event
475480
go_alert.country = country
476481
go_alert.opens = get_datetime(position["opens"])
477482
go_alert.closes = get_datetime(position["closes"])
478483
go_alert.start = get_datetime(position["start"])
479484
go_alert.end = get_datetime(position["end"])
480-
go_alert.is_active = position["status"] == "active"
481485
go_alert.save()
482486
add_tags_to_obj(go_alert, position["tags"])
483487
if created:
@@ -486,7 +490,7 @@ def sync_open_positions(molnix_positions, molnix_api, countries):
486490
successful_updates += 1
487491

488492
# Find existing active alerts that are not in the current list from Molnix
489-
existing_alerts = SurgeAlert.objects.filter(is_active=True).exclude(molnix_id__isnull=True)
493+
existing_alerts = SurgeAlert.objects.filter(molnix_status=SurgeAlertStatus.OPEN).exclude(molnix_id__isnull=True)
490494
existing_alert_ids = [e.molnix_id for e in existing_alerts]
491495
inactive_alerts = list(set(existing_alert_ids) - set(molnix_ids))
492496

@@ -498,15 +502,10 @@ def sync_open_positions(molnix_positions, molnix_api, countries):
498502
position = molnix_api.get_position(alert.molnix_id)
499503
if not position:
500504
warnings.append("Position id %d not found in Molnix API" % alert.molnix_id)
501-
if position and position["status"] == "unfilled":
502-
alert.molnix_status = position["status"]
505+
if position and position["status"]:
506+
alert.molnix_status = SurgeAlert.parse_molnix_status(position["status"])
503507
if position and position["closes"]:
504508
alert.closes = get_datetime(position["closes"])
505-
if position and position["status"] == "archived":
506-
alert.molnix_status = position["status"]
507-
alert.is_active = False
508-
else:
509-
alert.is_active = False
510509
alert.save()
511510

512511
marked_inactive = len(inactive_alerts)

deploy/helm/ifrcgo-helm/values.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,6 @@ cronjobs:
120120
schedule: '0 9 * * *'
121121
- command: 'ingest_country_plan_file'
122122
schedule: '1 0 * * *'
123-
- command: 'update_surge_alert_status'
124-
schedule: '1 */12 * * *'
125123
- command: 'fdrs_annual_income'
126124
schedule: '0 0 * * 0'
127125
- command: 'FDRS_INCOME'

main/sentry.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ class SentryMonitor(models.TextChoices):
113113
UPDATE_PROJECT_STATUS = "update_project_status", "1 3 * * *"
114114
USER_REGISTRATION_REMINDER = "user_registration_reminder", "0 9 * * *"
115115
INGEST_COUNTRY_PLAN_FILE = "ingest_country_plan_file", "1 0 * * *"
116-
UPDATE_SURGE_ALERT_STATUS = "update_surge_alert_status", "1 */12 * * *"
117116
FDRS_ANNUAL_INCOME = "fdrs_annual_income", "0 0 * * 0"
118117
FDRS_INCOME = "FDRS_INCOME", "0 0 * * 0"
119118
INGEST_ACAPS = "ingest_acaps", "0 1 * * 0"

notifications/admin.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class SurgeAlertAdmin(CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdm
1111

1212
@admin.display(description="std")
1313
def std(self, obj):
14-
return obj.is_stood_down
14+
return obj.molnix_status == models.SurgeAlertStatus.STOOD_DOWN
1515

1616
std.boolean = True
1717
country_in = "event__countries__in"
@@ -22,9 +22,9 @@ def std(self, obj):
2222
"message",
2323
"event__name",
2424
)
25-
readonly_fields = ("molnix_id", "is_stood_down")
26-
list_display = ("__str__", "message", "start", "molnix_id", "molnix_status", "status", "std")
27-
list_filter = ("molnix_status", "status", "is_stood_down")
25+
readonly_fields = ("molnix_id",)
26+
list_display = ("__str__", "message", "start", "molnix_id", "molnix_status", "std")
27+
list_filter = ("molnix_status",)
2828

2929

3030
class SubscriptionAdmin(CompareVersionAdmin):

notifications/drf_views.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,21 @@ class SurgeAlertFilter(filters.FilterSet):
3535
help_text="Molnix_tag names, comma separated",
3636
widget=CSVWidget,
3737
)
38-
status = filters.NumberFilter(field_name="status", lookup_expr="exact")
38+
molnix_status = CharInFilter(
39+
label="molnix status",
40+
field_name="molnix_status",
41+
lookup_expr="in",
42+
help_text="Molnix status value, comma separated",
43+
widget=CSVWidget,
44+
)
3945

4046
class Meta:
4147
model = SurgeAlert
4248
fields = {
4349
"created_at": ("exact", "gt", "gte", "lt", "lte"),
4450
"start": ("exact", "gt", "gte", "lt", "lte"),
4551
"end": ("exact", "gt", "gte", "lt", "lte"),
46-
"is_stood_down": ("exact",),
47-
"is_active": ("exact",),
4852
"molnix_id": ("exact", "in"),
49-
"molnix_status": ("exact", "in"),
5053
"message": ("exact", "in"),
5154
"country": ("exact", "in"),
5255
"country__name": ("exact", "in"),
@@ -63,7 +66,7 @@ class SurgeAlertViewset(viewsets.ReadOnlyModelViewSet):
6366
authentication_classes = (TokenAuthentication,)
6467
queryset = SurgeAlert.objects.prefetch_related("molnix_tags", "molnix_tags__groups").select_related("event", "country").all()
6568
filterset_class = SurgeAlertFilter
66-
ordering_fields = ("created_at", "atype", "category", "event", "is_stood_down", "status", "opens")
69+
ordering_fields = ("created_at", "atype", "category", "event", "molnix_status", "opens")
6770
search_fields = (
6871
"operation",
6972
"message",
@@ -76,6 +79,10 @@ def get_serializer_class(self):
7679
# return UnauthenticatedSurgeAlertSerializer
7780
return SurgeAlertSerializer
7881

82+
def get_queryset(self):
83+
queryset = super().get_queryset()
84+
return queryset.filter(molnix_id__isnull=False).exclude(molnix_tags__name="NO_GO")
85+
7986

8087
# def get_queryset(self):
8188
# # limit = 14 # days

notifications/factories.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import factory
22
from factory import fuzzy
33

4-
from .models import SurgeAlert
4+
from .models import SurgeAlert, SurgeAlertStatus
55

66

77
class SurgeAlertFactory(factory.django.DjangoModelFactory):
88
class Meta:
99
model = SurgeAlert
1010

1111
message = fuzzy.FuzzyText(length=100)
12+
molnix_id = fuzzy.FuzzyInteger(low=1)
1213
atype = fuzzy.FuzzyInteger(low=1)
1314
category = fuzzy.FuzzyInteger(low=1)
14-
molnix_status = fuzzy.FuzzyChoice(choices=["active", "inactive"])
15+
molnix_status = fuzzy.FuzzyChoice(choices=SurgeAlertStatus)
1516

1617
@factory.post_generation
1718
def molnix_tags(self, create, extracted, **_):

notifications/management/commands/update_surge_alert_status.py

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Generated by Django 4.2.13 on 2024-07-16 08:46
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("notifications", "0014_surgealert_status"),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name="surgealert",
15+
name="molnix_status",
16+
),
17+
migrations.RenameField(
18+
model_name="surgealert",
19+
old_name="status",
20+
new_name="molnix_status",
21+
),
22+
migrations.RemoveField(
23+
model_name="surgealert",
24+
name="is_active",
25+
),
26+
migrations.RemoveField(
27+
model_name="surgealert",
28+
name="is_stood_down",
29+
),
30+
]

notifications/models.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,45 +49,42 @@ class SurgeAlert(models.Model):
4949
# ID in Molnix system, if parsed from Molnix.
5050
molnix_id = models.IntegerField(blank=True, null=True)
5151

52-
# Status field from Molnix - `unfilled` denotes Stood-Down
53-
molnix_status = models.CharField(blank=True, null=True, max_length=32)
54-
55-
# It depends on molnix_status. Check "save" method below.
56-
is_stood_down = models.BooleanField(verbose_name=_("is stood down?"), default=False)
5752
opens = models.DateTimeField(blank=True, null=True)
5853
closes = models.DateTimeField(blank=True, null=True)
5954
start = models.DateTimeField(blank=True, null=True)
6055
end = models.DateTimeField(blank=True, null=True)
6156
molnix_tags = models.ManyToManyField(MolnixTag, blank=True)
6257

63-
# Set to inactive when position is no longer in Molnix
64-
is_active = models.BooleanField(default=True)
65-
6658
# Don't set `auto_now_add` so we can modify it on save
6759
created_at = models.DateTimeField(verbose_name=_("created at"))
68-
status = models.IntegerField(choices=SurgeAlertStatus.choices, verbose_name=_("alert status"), default=SurgeAlertStatus.OPEN)
60+
molnix_status = models.IntegerField(
61+
choices=SurgeAlertStatus.choices, verbose_name=_("alert status"), default=SurgeAlertStatus.OPEN
62+
)
6963

7064
class Meta:
7165
ordering = ["-created_at"]
7266
verbose_name = _("Surge Alert")
7367
verbose_name_plural = _("Surge Alerts")
7468

75-
def save(self, *args, **kwargs):
69+
@staticmethod
70+
def parse_molnix_status(status_raw: str) -> SurgeAlertStatus:
7671
"""
77-
If the alert status is marked as stood_down, then the status is Stood Down.
78-
If the closing timestamp (closes) is earlier than the current date, the status is displayed as Closed.
79-
Otherwise, it is displayed as Open.
72+
A position_status of active should be shown as Open
73+
A position_status of archived should be shown as Closed
74+
A position_status of unfilled should be shown as Stood Down
75+
If the position_status is non other than active, archived, unfilled then show Closed.
8076
"""
81-
# On save, if `created` is not set, make it the current time
77+
molnix_status_dict = {
78+
"active": SurgeAlertStatus.OPEN,
79+
"unfilled": SurgeAlertStatus.STOOD_DOWN,
80+
"archived": SurgeAlertStatus.CLOSED,
81+
}
82+
83+
return molnix_status_dict.get(status_raw.lower(), SurgeAlertStatus.CLOSED)
84+
85+
def save(self, *args, **kwargs):
8286
if (not self.id and not self.created_at) or (self.created_at > timezone.now()):
8387
self.created_at = timezone.now()
84-
self.is_stood_down = self.molnix_status == "unfilled"
85-
if self.is_stood_down:
86-
self.status = SurgeAlertStatus.STOOD_DOWN
87-
elif self.closes and self.closes < timezone.now():
88-
self.status = SurgeAlertStatus.CLOSED
89-
else:
90-
self.status = SurgeAlertStatus.OPEN
9188
return super(SurgeAlert, self).save(*args, **kwargs)
9289

9390
def __str__(self):

notifications/serializers.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313

1414
class SurgeAlertSerializer(ModelSerializer):
15-
event = SurgeEventSerializer()
16-
country = MiniCountrySerializer()
15+
event = SurgeEventSerializer(required=False)
16+
country = MiniCountrySerializer(required=False)
1717
atype_display = serializers.CharField(source="get_atype_display", read_only=True)
18-
status_display = serializers.CharField(source="get_status_display", read_only=True)
18+
molnix_status_display = serializers.CharField(source="get_molnix_status_display", read_only=True)
1919
category_display = serializers.CharField(source="get_category_display", read_only=True)
2020
molnix_tags = MolnixTagSerializer(many=True, read_only=True)
2121

@@ -41,10 +41,8 @@ class Meta:
4141
"closes",
4242
"start",
4343
"end",
44-
"is_active",
45-
"is_stood_down",
46-
"status",
47-
"status_display",
44+
"molnix_status",
45+
"molnix_status_display",
4846
)
4947

5048

0 commit comments

Comments
 (0)