Skip to content

Commit

Permalink
Generate emergency title and add skip title generation flag
Browse files Browse the repository at this point in the history
  • Loading branch information
susilnem committed Feb 25, 2025
1 parent b0572d6 commit dc9ccc0
Show file tree
Hide file tree
Showing 15 changed files with 288 additions and 154 deletions.
4 changes: 3 additions & 1 deletion api/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,14 @@ def changeform_view(self, request, *args, **kwargs):
"field_reports",
"auto_generated_source",
"parent_event",
"name",
)
else:
self.readonly_fields = (
"appeals",
"field_reports",
"auto_generated_source",
"name",
)

return super(EventAdmin, self).changeform_view(request, *args, **kwargs)
Expand Down Expand Up @@ -337,7 +339,7 @@ class FieldReportAdmin(CompareVersionAdmin, RegionRestrictedAdmin, TranslationAd
def create_events(self, request, queryset):
for report in queryset:
event = models.Event.objects.create(
name=report.summary,
title=report.title,
dtype=getattr(report, "dtype"),
disaster_start_date=getattr(report, "created_at"),
auto_generated=True,
Expand Down
1 change: 1 addition & 0 deletions api/factories/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Meta:
model = Event

name = fuzzy.FuzzyText(length=50)
title = fuzzy.FuzzyText(length=10)
slug = fuzzy.FuzzyText(length=50)
dtype = factory.SubFactory(DisasterTypeFactory)

Expand Down
3 changes: 2 additions & 1 deletion api/management/commands/create_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ def handle(self, *args, **options):
print("Creating %s events" % len(appeals_without_events))
for appeal in appeals_without_events:
fields = {
"name": appeal.name,
"title": appeal.name,
"dtype": appeal.dtype,
"disaster_start_date": appeal.start_date,
"auto_generated": True,
"auto_generated_source": SOURCES["appeal_admin"],
"skip_auto_generate_name": True,
}
event = Event.objects.create(**fields)
if appeal.country is not None:
Expand Down
3 changes: 2 additions & 1 deletion api/management/commands/ingest_gdacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ def handle(self, *args, **options):
title = "%s..." % title[:97]

fields = {
"name": title,
"title": title,
"summary": data["description"],
"disaster_start_date": data["publication_date"],
"auto_generated": True,
"auto_generated_source": SOURCES["gdacs"],
"skip_auto_generate_name": True,
"ifrc_severity_level": data["alert_level"],
}
event = Event.objects.create(**fields)
Expand Down
3 changes: 2 additions & 1 deletion api/management/commands/ingest_who.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,12 @@ def handle(self, *args, **options):
summary = data["description"] + " (" + data["category"] + ")"

fields = {
"name": title,
"title": title,
"summary": summary,
"disaster_start_date": date,
"auto_generated": True,
"auto_generated_source": data["guid"],
"skip_auto_generate_name": True,
"ifrc_severity_level": alert_level,
}
# TODO: fields['name'] sometimes exceeds 100 maxlength, so will need some altering if this will be used
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Generated by Django 4.2.17 on 2025-02-24 06:59

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("api", "0218_remove_event_title_remove_event_title_ar_and_more"),
]

operations = [
migrations.AddField(
model_name="event",
name="skip_auto_generate_name",
field=models.BooleanField(
default=False, help_text="<b>If checked, the name of the Emergency will not be auto-generated. </b>"
),
),
migrations.AddField(
model_name="event",
name="title",
field=models.CharField(
blank=True,
help_text="Title is used to generate the name of the Emergency. </br>The name is constructed as: <b><i>Country IS03 or Name: Disaster Type - Start Date - Title</b><i>",
max_length=256,
),
),
migrations.AddField(
model_name="event",
name="title_ar",
field=models.CharField(
blank=True,
help_text="Title is used to generate the name of the Emergency. </br>The name is constructed as: <b><i>Country IS03 or Name: Disaster Type - Start Date - Title</b><i>",
max_length=256,
null=True,
),
),
migrations.AddField(
model_name="event",
name="title_en",
field=models.CharField(
blank=True,
help_text="Title is used to generate the name of the Emergency. </br>The name is constructed as: <b><i>Country IS03 or Name: Disaster Type - Start Date - Title</b><i>",
max_length=256,
null=True,
),
),
migrations.AddField(
model_name="event",
name="title_es",
field=models.CharField(
blank=True,
help_text="Title is used to generate the name of the Emergency. </br>The name is constructed as: <b><i>Country IS03 or Name: Disaster Type - Start Date - Title</b><i>",
max_length=256,
null=True,
),
),
migrations.AddField(
model_name="event",
name="title_fr",
field=models.CharField(
blank=True,
help_text="Title is used to generate the name of the Emergency. </br>The name is constructed as: <b><i>Country IS03 or Name: Disaster Type - Start Date - Title</b><i>",
max_length=256,
null=True,
),
),
]
38 changes: 38 additions & 0 deletions api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,19 @@ def snippet_image_path(instance, filename):
class Event(models.Model):
"""A disaster, which could cover multiple countries"""

title = models.CharField(
max_length=256,
blank=True,
help_text=_(
"Title is used to generate the name of the Emergency. </br>"
"The name is constructed as: "
"<b><i>Country IS03 or Name: Disaster Type - Start Date - Title</b><i>"
),
)
skip_auto_generate_name = models.BooleanField(
default=False,
help_text=_("<b>If checked, the name of the Emergency will not be auto-generated. </b>"),
)
name = models.CharField(verbose_name=_("name"), max_length=256)
dtype = models.ForeignKey(DisasterType, verbose_name=_("disaster type"), null=True, on_delete=models.SET_NULL)
disaster_start_date = models.DateTimeField(verbose_name=_("disaster start date"))
Expand Down Expand Up @@ -872,6 +885,22 @@ def record_type(self):
def to_dict(self):
return to_dict(self)

def generate_formatted_name(self):
disaster_start_date = self.disaster_start_date.strftime("%m-%Y")
# NOTE: using the country name if the iso3 is not available eg: Africa Region
country_iso3_or_name = (
self.countries.first().iso3 or self.countries.first().name if self.id and self.countries.first() else "N/A"
)
for lang in AVAILABLE_LANGUAGES:
with translation_override(lang):
dtype = self.dtype.name if self.dtype else "N/A"
# NOTE: Skip Auto generating name if the skip_auto_generate_name is True
if self.skip_auto_generate_name:
self.name = self.title
else:
self.name = f"{country_iso3_or_name}: {dtype} - {disaster_start_date} - {self.title}"
yield build_localized_fieldname("name", lang)

def save(self, *args, **kwargs):

# Make the slug lowercase
Expand All @@ -882,6 +911,15 @@ def save(self, *args, **kwargs):
if not self.id and not self.disaster_start_date:
self.disaster_start_date = timezone.now()

updated_name_fields = list(self.generate_formatted_name())

# Updating the updated_fields with the fields that are updated
if kwargs.get("update_fields"):
kwargs["update_fields"] = (
*kwargs["update_fields"],
*updated_name_fields,
)

return super(Event, self).save(*args, **kwargs)

def __str__(self):
Expand Down
9 changes: 9 additions & 0 deletions api/receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,15 @@ def remove_appeal_filter(sender, instance, using, **kwargs):
appealFilter.save()


@receiver(m2m_changed, sender=Event.countries.through)
def update_event_name(sender, instance, action, **kwargs):
"""
Update the event name when the countries are changed.
"""
if action in ["post_add", "post_remove"]:
instance.save()


@receiver(m2m_changed, sender=FieldReport.countries.through)
def update_fieldreport_summary(sender, instance, action, **kwargs):
"""
Expand Down
5 changes: 4 additions & 1 deletion api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,7 @@ class Meta:
"dtype",
"countries",
"summary",
"title",
"num_affected",
"ifrc_severity_level",
"ifrc_severity_level_display",
Expand Down Expand Up @@ -1215,6 +1216,7 @@ class Meta:
"dtype_name",
"countries",
"summary",
"title",
"num_affected",
"ifrc_severity_level",
"glide",
Expand Down Expand Up @@ -1299,6 +1301,7 @@ class Meta:
"countries",
"districts",
"summary",
"title",
"num_affected",
"tab_two_title",
"tab_three_title",
Expand Down Expand Up @@ -2056,7 +2059,7 @@ class Meta:

def create_event(self, report):
event = Event.objects.create(
name=report.summary,
title=report.title,
dtype=report.dtype,
summary=report.description or "",
disaster_start_date=report.start_date,
Expand Down
14 changes: 7 additions & 7 deletions api/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ class EventTest(TestCase):

def setUp(self):
dtype = models.DisasterType.objects.get(pk=1)
models.Event.objects.create(name="disaster1", summary="test disaster", dtype=dtype)
event = models.Event.objects.create(name="disaster2", summary="another test disaster", dtype=dtype)
models.Event.objects.create(title="disaster1", summary="test disaster", dtype=dtype)
event = models.Event.objects.create(title="disaster2", summary="another test disaster", dtype=dtype)
models.KeyFigure.objects.create(event=event, number=7, deck="things", source="website")
models.Snippet.objects.create(event=event, snippet="this is a snippet")

def test_disaster_create(self):
obj1 = models.Event.objects.get(name="disaster1")
obj2 = models.Event.objects.get(name="disaster2")
obj1 = models.Event.objects.get(title="disaster1")
obj2 = models.Event.objects.get(title="disaster2")
self.assertEqual(obj1.summary, "test disaster")
self.assertEqual(obj2.summary, "another test disaster")
keyfig = obj2.key_figures.all()
Expand Down Expand Up @@ -68,7 +68,7 @@ def test_profile_create(self):
class AppealTest(APITestCase):
def setUp(self):
# An appeal with needs_confirmation=True should not return the event in the API response.
event = models.Event.objects.create(name="associated event", summary="foo")
event = models.Event.objects.create(title="associated event", summary="foo")
country = models.Country.objects.create(name="country")
models.Appeal.objects.create(
aid="test1", name="appeal", atype=1, code="abc", needs_confirmation=True, event=event, country=country
Expand All @@ -87,13 +87,13 @@ class FieldReportTest(TestCase):

def setUp(self):
dtype = models.DisasterType.objects.get(pk=1)
event = models.Event.objects.create(name="disaster1", summary="test disaster", dtype=dtype)
event = models.Event.objects.create(title="disaster1", summary="test disaster", dtype=dtype)
country = models.Country.objects.create(name="country")
report = models.FieldReport.objects.create(rid="test1", event=event, dtype=dtype)
report.countries.add(country)

def test_field_report_create(self):
event = models.Event.objects.get(name="disaster1")
event = models.Event.objects.get(title="disaster1")
country = models.Country.objects.get(name="country")
self.assertEqual(event.field_reports.all()[0].countries.all()[0], country)
obj = models.FieldReport.objects.get(rid="test1")
Expand Down
4 changes: 2 additions & 2 deletions api/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ def test_sit_rep_types(self):
type1 = models.SituationReportType.objects.create(type="Lyric")
type2 = models.SituationReportType.objects.create(type="Epic")
dtype1 = models.DisasterType.objects.get(pk=1)
event1 = models.Event.objects.create(name="disaster1", summary="test disaster1", dtype=dtype1)
event1 = models.Event.objects.create(title="disaster1", summary="test disaster1", dtype=dtype1)

models.SituationReport.objects.create(name="test1", event=event1, type=type1, visibility=3)
models.SituationReport.objects.create(name="test2", event=event1, type=type2, visibility=3)
Expand Down Expand Up @@ -386,7 +386,7 @@ def test_create_and_update(self):
self.assertEqual(created.title_en, "test")

# created an emergency automatically
self.assertEqual(created.event.name, response["summary"])
self.assertEqual(created.event.title, "test")
# event_pk = created.event.id

# body['countries'] = [country2.id]
Expand Down
3 changes: 2 additions & 1 deletion api/translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ class DisasterTypeTO(TranslationOptions):

@register(Event)
class EventTO(TranslationOptions):
fields = ("name", "summary")
fields = ("name", "summary", "title")
skip_fields = ("name",) # XXX: CUSTOM field Not used by TranslationOptions, but used in lang/tasks.py


@register(ExternalPartner)
Expand Down
4 changes: 2 additions & 2 deletions api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ def generate_field_report_title(
# NOTE: Checking if event or country is changed while Updating
if id:
fr = get_object_or_404(FieldReport, id=id)
if fr.event == event and fr.countries.first() == country:
fr_num = current_fr_number
if fr.fr_num and fr.event == event and fr.countries.first() == country:
fr_num = fr.fr_num

suffix = ""
if fr_num > 1 and event:
Expand Down
Loading

0 comments on commit dc9ccc0

Please sign in to comment.