Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate emergency title and add skip title generation flag #2425

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
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
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
Loading