From 17786d5350db4ddc4b8a010782efad77ecf9405e Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Fri, 13 Sep 2024 17:00:40 +0545 Subject: [PATCH 1/6] Add title and skip summary translation logic --- api/admin.py | 2 +- ...ort_title_fieldreport_title_ar_and_more.py | 38 +++++++++++++++++++ api/models.py | 25 +++++++++++- api/serializers.py | 3 +- api/translation.py | 4 +- lang/tasks.py | 5 ++- 6 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py diff --git a/api/admin.py b/api/admin.py index 5b9f908c9..135925e1f 100644 --- a/api/admin.py +++ b/api/admin.py @@ -324,7 +324,7 @@ class FieldReportAdmin(CompareVersionAdmin, RegionRestrictedAdmin, TranslationAd "districts", ) - readonly_fields = ("report_date", "created_at", "updated_at") + readonly_fields = ("report_date", "created_at", "updated_at", "summary") list_filter = [MembershipFilter] actions = [ "create_events", diff --git a/api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py b/api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py new file mode 100644 index 000000000..38925900b --- /dev/null +++ b/api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 4.2.15 on 2024-09-13 08:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0213_merge_20240807_1001'), + ] + + operations = [ + migrations.AddField( + model_name='fieldreport', + name='title', + field=models.CharField(blank=True, max_length=256), + ), + migrations.AddField( + model_name='fieldreport', + name='title_ar', + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name='fieldreport', + name='title_en', + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name='fieldreport', + name='title_es', + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name='fieldreport', + name='title_fr', + field=models.CharField(blank=True, max_length=256, null=True), + ), + ] diff --git a/api/models.py b/api/models.py index 3a93290eb..cbad650fd 100644 --- a/api/models.py +++ b/api/models.py @@ -775,6 +775,7 @@ class Event(models.Model): ) image = models.ImageField(verbose_name=_("image"), null=True, blank=True, upload_to=snippet_image_path) summary = HTMLField(verbose_name=_("summary"), blank=True, default="") + # title = models.CharField(max_length=256, blank=True) num_injured = models.IntegerField(verbose_name=_("number of injured"), null=True, blank=True) num_dead = models.IntegerField(verbose_name=_("number of dead"), null=True, blank=True) @@ -1461,6 +1462,8 @@ class RecentAffected(models.IntegerChoices): # Used to differentiate reports that have and have not been synced from DMIS rid = models.CharField(verbose_name=_("r id"), max_length=100, null=True, blank=True, editable=False) summary = models.TextField(verbose_name=_("summary"), blank=True) + # Title field is used for the translation and later adding formated into the summary + title = models.CharField(max_length=256, blank=True) description = HTMLField(verbose_name=_("description"), blank=True, default="") dtype = models.ForeignKey(DisasterType, verbose_name=_("disaster type"), on_delete=models.PROTECT) event = models.ForeignKey( @@ -1668,7 +1671,24 @@ class Meta: # filters = models.Q(visibility__in=[VisibilityChoices.MEMBERSHIP, VisibilityChoices.PUBLIC]) # if is_user_ifrc(user): # filters = models.Q() - # return FieldReport.objects.filter(filters) + + def generate_formatted_summary(self) -> str: + translations = { + "summary_en": self.title_en, + "summary_fr": self.title_fr, + "summary_es": self.title_es, + "summary_ar": self.title_ar, + } + country = self.countries.first() + disater = self.dtype + start_date = self.start_date.strftime("%m-%Y") + + field_report_number = FieldReport.objects.filter(countries=country).count() + date = timezone.now().strftime("%Y-%m-%d") + for summary_field, title in translations.items(): + if title: + summary = f"{country.iso3}: {disater.name} - {start_date} {title} #{field_report_number} ({date})" + setattr(self, summary_field, summary) def save(self, *args, **kwargs): # On save, is report_date or start_date is not set, set it to now. @@ -1676,6 +1696,9 @@ def save(self, *args, **kwargs): self.report_date = timezone.now() if not self.id and not self.start_date: self.start_date = timezone.now() + # NOTE: Overriding the summary field with translated title + self.generate_formatted_summary() + return super(FieldReport, self).save(*args, **kwargs) def indexing(self): diff --git a/api/serializers.py b/api/serializers.py index 431eb2082..f08248f5e 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -2049,10 +2049,11 @@ class FieldReportSerializer( class Meta: model = FieldReport fields = "__all__" + read_only_fields = ("summary",) def create_event(self, report): event = Event.objects.create( - name=report.summary, + name=report.title, dtype=report.dtype, summary=report.description or "", disaster_start_date=report.start_date, diff --git a/api/translation.py b/api/translation.py index 44007ead5..46ffc0d38 100644 --- a/api/translation.py +++ b/api/translation.py @@ -79,6 +79,7 @@ class DisasterTypeTO(TranslationOptions): @register(Event) class EventTO(TranslationOptions): fields = ("name", "summary") + skip_fields = ("name",) # XXX: CUSTOM field Not used by TranslationOptions, but used in lang/tasks.py @register(ExternalPartner) @@ -88,7 +89,8 @@ class ExternalPartnerTO(TranslationOptions): @register(FieldReport) class FieldReportTO(TranslationOptions): - fields = ("summary", "description", "actions_others", "other_sources") + fields = ("title", "summary", "description", "actions_others", "other_sources") + skip_fields = ("summary",) # XXX: CUSTOM field Not used by TranslationOptions, but used in lang/tasks.py @register(GDACSEvent) diff --git a/lang/tasks.py b/lang/tasks.py index 10ff176c5..af97b53d6 100644 --- a/lang/tasks.py +++ b/lang/tasks.py @@ -96,7 +96,10 @@ def get_translatable_models(cls, only_models: typing.Optional[typing.List[models @classmethod def get_translatable_fields(cls, model): - return list(translator.get_options_for_model(model).fields.keys()) + translation_options = translator.get_options_for_model(model) + # NOTE: Some skipped fields are handled manually. + skipped_fields = set(getattr(translation_options, "skip_fields", [])) + return [field for field in translation_options.fields.keys() if field not in skipped_fields] def translate_model_fields(self, obj, translatable_fields=None): if skip_auto_translation(obj): From 79be8f3ecc2560dc682bed6c706336844a12cb70 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Tue, 17 Sep 2024 14:48:12 +0545 Subject: [PATCH 2/6] Add translation logic for summary in fieldreport and event Fix test cases for the snapshots --- api/admin.py | 5 +- api/factories/event.py | 3 +- api/factories/field_report.py | 1 + ...ort_title_fieldreport_title_ar_and_more.py | 38 -- ..._event_title_ar_event_title_en_and_more.py | 63 +++ api/models.py | 68 ++- api/receivers.py | 26 +- api/serializers.py | 4 +- api/test_models.py | 14 +- api/test_views.py | 19 +- api/translation.py | 2 +- deployments/snapshots/snap_tests.py | 455 ++++-------------- deployments/tests.py | 51 +- 13 files changed, 291 insertions(+), 458 deletions(-) delete mode 100644 api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py create mode 100644 api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py diff --git a/api/admin.py b/api/admin.py index 135925e1f..afed23e14 100644 --- a/api/admin.py +++ b/api/admin.py @@ -225,6 +225,7 @@ class EventAdmin(CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdmin): "districts", "parent_event", ) + readonly_fields = ("name",) def appeals(self, instance): if getattr(instance, "appeals").exists(): @@ -337,7 +338,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, @@ -437,7 +438,7 @@ class AppealAdmin(CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdmin): def create_events(self, request, queryset): for appeal in queryset: event = models.Event.objects.create( - name=appeal.name, + title=appeal.name, dtype=getattr(appeal, "dtype"), disaster_start_date=getattr(appeal, "start_date"), auto_generated=True, diff --git a/api/factories/event.py b/api/factories/event.py index 855c9ccd2..71bf55b62 100644 --- a/api/factories/event.py +++ b/api/factories/event.py @@ -22,7 +22,8 @@ class EventFactory(factory.django.DjangoModelFactory): class Meta: model = Event - name = fuzzy.FuzzyText(length=50, prefix="event-") + name = fuzzy.FuzzyText(length=50) + title = fuzzy.FuzzyText(length=10) slug = fuzzy.FuzzyText(length=50) dtype = factory.SubFactory(DisasterTypeFactory) diff --git a/api/factories/field_report.py b/api/factories/field_report.py index 5ad5a6544..d4c7a4d05 100644 --- a/api/factories/field_report.py +++ b/api/factories/field_report.py @@ -17,6 +17,7 @@ class Meta: dtype = factory.SubFactory(disaster_type.DisasterTypeFactory) event = factory.SubFactory(event.EventFactory) summary = fuzzy.FuzzyText(length=500) + title = fuzzy.FuzzyText(length=10, prefix="title-") description = fuzzy.FuzzyText(length=200) report_date = fuzzy.FuzzyDateTime(datetime.datetime(2008, 1, 1, tzinfo=pytz.utc)) # start_date is now what the user explicitly sets while filling the Field Report form. diff --git a/api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py b/api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py deleted file mode 100644 index 38925900b..000000000 --- a/api/migrations/0214_fieldreport_title_fieldreport_title_ar_and_more.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 4.2.15 on 2024-09-13 08:21 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0213_merge_20240807_1001'), - ] - - operations = [ - migrations.AddField( - model_name='fieldreport', - name='title', - field=models.CharField(blank=True, max_length=256), - ), - migrations.AddField( - model_name='fieldreport', - name='title_ar', - field=models.CharField(blank=True, max_length=256, null=True), - ), - migrations.AddField( - model_name='fieldreport', - name='title_en', - field=models.CharField(blank=True, max_length=256, null=True), - ), - migrations.AddField( - model_name='fieldreport', - name='title_es', - field=models.CharField(blank=True, max_length=256, null=True), - ), - migrations.AddField( - model_name='fieldreport', - name='title_fr', - field=models.CharField(blank=True, max_length=256, null=True), - ), - ] diff --git a/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py b/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py new file mode 100644 index 000000000..686006441 --- /dev/null +++ b/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py @@ -0,0 +1,63 @@ +# Generated by Django 4.2.16 on 2024-10-07 18:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("api", "0214_alter_profile_limit_access_to_guest"), + ] + + operations = [ + migrations.AddField( + model_name="event", + name="title", + field=models.CharField(blank=True, max_length=256), + ), + migrations.AddField( + model_name="event", + name="title_ar", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="event", + name="title_en", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="event", + name="title_es", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="event", + name="title_fr", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="fieldreport", + name="title", + field=models.CharField(blank=True, max_length=256), + ), + migrations.AddField( + model_name="fieldreport", + name="title_ar", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="fieldreport", + name="title_en", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="fieldreport", + name="title_es", + field=models.CharField(blank=True, max_length=256, null=True), + ), + migrations.AddField( + model_name="fieldreport", + name="title_fr", + field=models.CharField(blank=True, max_length=256, null=True), + ), + ] diff --git a/api/models.py b/api/models.py index cbad650fd..4d648d896 100644 --- a/api/models.py +++ b/api/models.py @@ -19,9 +19,13 @@ # from django.db.models import Prefetch from django.dispatch import receiver from django.utils import timezone +from django.utils.translation import activate, deactivate from django.utils.translation import gettext_lazy as _ +from modeltranslation.utils import build_localized_fieldname from tinymce.models import HTMLField +from lang.translation import AVAILABLE_LANGUAGES + from main.fields import SecureFileField from .utils import validate_slug_number # is_user_ifrc, @@ -775,7 +779,7 @@ class Event(models.Model): ) image = models.ImageField(verbose_name=_("image"), null=True, blank=True, upload_to=snippet_image_path) summary = HTMLField(verbose_name=_("summary"), blank=True, default="") - # title = models.CharField(max_length=256, blank=True) + title = models.CharField(max_length=256, blank=True) num_injured = models.IntegerField(verbose_name=_("number of injured"), null=True, blank=True) num_dead = models.IntegerField(verbose_name=_("number of dead"), null=True, blank=True) @@ -870,6 +874,16 @@ def record_type(self): def to_dict(self): return to_dict(self) + def generate_formatted_name(self): + country_iso3 = self.countries.first().iso3 if self.id and self.countries.first() else "N/A" + dtype = self.dtype.name if self.dtype else "N/A" + start_date = timezone.now().strftime("%m-%Y") + for lang in AVAILABLE_LANGUAGES: + activate(lang) + self.name = f"{country_iso3}: {dtype} - {start_date} - {self.title}" + deactivate() + yield build_localized_fieldname("name", lang) + def save(self, *args, **kwargs): # Make the slug lowercase @@ -880,6 +894,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): @@ -1672,32 +1695,39 @@ class Meta: # if is_user_ifrc(user): # filters = models.Q() - def generate_formatted_summary(self) -> str: - translations = { - "summary_en": self.title_en, - "summary_fr": self.title_fr, - "summary_es": self.title_es, - "summary_ar": self.title_ar, - } - country = self.countries.first() - disater = self.dtype + def generate_formatted_summary(self): + country_iso3 = self.countries.first().iso3 if self.id and self.countries.first() else "N/A" + dtype = self.dtype.name if self.dtype else "N/A" start_date = self.start_date.strftime("%m-%Y") - - field_report_number = FieldReport.objects.filter(countries=country).count() - date = timezone.now().strftime("%Y-%m-%d") - for summary_field, title in translations.items(): - if title: - summary = f"{country.iso3}: {disater.name} - {start_date} {title} #{field_report_number} ({date})" - setattr(self, summary_field, summary) + field_report_number = FieldReport.objects.filter(countries__iso3=country_iso3).exclude(id=self.id).count() + 1 + current_date = timezone.now().strftime("%Y-%m-%d") + + for lang in AVAILABLE_LANGUAGES: + activate(lang) + if self.is_covid_report: + # {ISO3}: COVID-19 #{Field Report Number} ({Date}) + self.summary = f"{country_iso3}: COVID-19 #{field_report_number} ({current_date})" + else: + # {ISO3}: {Disaster Type} - {Start Date} #{Field Report Number} ({Date}) + self.summary = f"{country_iso3}: {dtype} - {start_date} {self.title} #{field_report_number} ({current_date})" + deactivate() + yield build_localized_fieldname("summary", lang) def save(self, *args, **kwargs): - # On save, is report_date or start_date is not set, set it to now. + # On save, if report_date or start_date is not set, set it to now. if not self.id and not self.report_date: self.report_date = timezone.now() if not self.id and not self.start_date: self.start_date = timezone.now() # NOTE: Overriding the summary field with translated title - self.generate_formatted_summary() + updated_summary_list = list(self.generate_formatted_summary()) + + # NOTE: Updating the updated_fields by translation tasks + if kwargs.get("update_fields"): + kwargs["update_fields"] = ( + *kwargs["update_fields"], + *updated_summary_list, + ) return super(FieldReport, self).save(*args, **kwargs) diff --git a/api/receivers.py b/api/receivers.py index eb7a2db97..75d782a5c 100644 --- a/api/receivers.py +++ b/api/receivers.py @@ -3,7 +3,13 @@ from django.db import transaction from django.db.models import Q -from django.db.models.signals import post_delete, post_save, pre_delete, pre_save +from django.db.models.signals import ( + m2m_changed, + post_delete, + post_save, + pre_delete, + pre_save, +) from django.dispatch import receiver from django.utils import timezone from reversion.models import Version @@ -276,3 +282,21 @@ def remove_appeal_filter(sender, instance, using, **kwargs): appealFilter.value = ",".join(lstCodesToSkip) 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): + """ + Update the FieldReport summary when the countries are changed. + """ + if action in ["post_add", "post_remove"]: + instance.save() diff --git a/api/serializers.py b/api/serializers.py index f08248f5e..8c8b2aa30 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -1161,6 +1161,7 @@ class Meta: "dtype", "countries", "summary", + "title", "num_affected", "ifrc_severity_level", "ifrc_severity_level_display", @@ -1296,6 +1297,7 @@ class Meta: "countries", "districts", "summary", + "title", "num_affected", "tab_two_title", "tab_three_title", @@ -2053,7 +2055,7 @@ class Meta: def create_event(self, report): event = Event.objects.create( - name=report.title, + title=report.title, dtype=report.dtype, summary=report.description or "", disaster_start_date=report.start_date, diff --git a/api/test_models.py b/api/test_models.py index f63d3355c..1038f3505 100644 --- a/api/test_models.py +++ b/api/test_models.py @@ -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() @@ -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 @@ -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") diff --git a/api/test_views.py b/api/test_views.py index ca7ab2dc7..0c3d16ca2 100644 --- a/api/test_views.py +++ b/api/test_views.py @@ -16,7 +16,7 @@ from api.models import Profile, VisibilityChoices from deployments.factories.user import UserFactory from dref.models import DrefFile -from main.test_case import APITestCase, SnapshotTestCase +from main.test_case import APITestCase class SecureFileFieldTest(APITestCase): @@ -284,20 +284,21 @@ def test_get_auth(self): self.assertIsNotNone(response.get("expires")) -class EventSnaphostTest(SnapshotTestCase): +class EventApiTest(APITestCase): + def test_event_featured_document_api(self): event = EventFactory() EventFeaturedDocumentFactory.create_batch(5, event=event) resp = self.client.get(f"/api/v2/event/{event.id}/") self.assertEqual(resp.status_code, 200) - self.assertMatchSnapshot(json.loads(resp.content)) + self.assertEqual(len(resp.json()["featured_documents"]), 5) def test_event_link_api(self): event = EventFactory() EventLinkFactory.create_batch(5, event=event) resp = self.client.get(f"/api/v2/event/{event.id}/") self.assertEqual(resp.status_code, 200) - self.assertMatchSnapshot(json.loads(resp.content)) + self.assertEqual(len(resp.json()["links"]), 5) class SituationReportTypeTest(APITestCase): @@ -308,7 +309,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) @@ -341,7 +342,7 @@ def test_create_and_update(self): body = { "countries": [country1.id, country2.id], "dtype": 7, - "summary": "test", + "title": "test", "description": "this is a test description", "bulletin": "3", "num_assisted": 100, @@ -381,12 +382,12 @@ def test_create_and_update(self): self.assertEqual(created.contacts.count(), 1) self.assertEqual(created.visibility, models.VisibilityChoices.IFRC) self.assertEqual(created.dtype.id, 7) - self.assertEqual(created.summary, "test") + self.assertEqual(created.title, "test") # Translated field test - self.assertEqual(created.summary_en, "test") + self.assertEqual(created.title_en, "test") # created an emergency automatically - self.assertEqual(created.event.name, "test") + self.assertEqual(created.event.title, "test") # event_pk = created.event.id # body['countries'] = [country2.id] diff --git a/api/translation.py b/api/translation.py index 46ffc0d38..a68847800 100644 --- a/api/translation.py +++ b/api/translation.py @@ -78,7 +78,7 @@ 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 diff --git a/deployments/snapshots/snap_tests.py b/deployments/snapshots/snap_tests.py index f78e1c102..5b6754c76 100644 --- a/deployments/snapshots/snap_tests.py +++ b/deployments/snapshots/snap_tests.py @@ -7,13 +7,34 @@ snapshots = Snapshot() snapshots["TestProjectAPI::test_global_project_api 1"] = { - "ns_with_ongoing_activities": 16, + "ns_with_ongoing_activities": 2, "projects_per_programme_type": [ - {"count": 5, "programme_type": 0, "programme_type_display": "Bilateral"}, - {"count": 7, "programme_type": 1, "programme_type_display": "Multilateral"}, - {"count": 4, "programme_type": 2, "programme_type_display": "Domestic"}, + {"count": 4, "programme_type": 0, "programme_type_display": "Bilateral"}, + {"count": 4, "programme_type": 1, "programme_type_display": "Multilateral"}, + {"count": 8, "programme_type": 2, "programme_type_display": "Domestic"}, + ], + "projects_per_secondary_sectors": [ + { + "count": 8, + "secondary_sectors": 1, + "secondary_sectors_display": "sect-tag-EDccPugTHOrVqLIKlyPyxLPeHqyoHzwwFYEMaGiCkoeGPrnjlk", + }, + { + "count": 8, + "secondary_sectors": 2, + "secondary_sectors_display": "sect-tag-MThQoAZvUhEREEnLkPAbpciKLkiOGcKjdkqlHzMKObUUQsfnCM", + }, + { + "count": 8, + "secondary_sectors": 3, + "secondary_sectors_display": "sect-tag-EkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGWhfEQi", + }, + { + "count": 8, + "secondary_sectors": 4, + "secondary_sectors_display": "sect-tag-IaXRPBHAxcSHBoZEYXywLZVWSKgBiqEXofsMIAqmaTVYaKHhHa", + }, ], - "projects_per_secondary_sectors": [], "projects_per_sector": [ {"count": 16, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} ], @@ -23,227 +44,31 @@ snapshots["TestProjectAPI::test_global_project_api 2"] = [ { - "budget_amount_total": 7890000, - "id": 5, - "iso3": "YvZ", - "name": "country-SZuAxgjBPLqqIBKxNrRzWnAJYJElxJJEqtKwXTzViQhVoCYSkg", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-JNSRTdkyOaZfjEMBfeqoxfMcUyzNPHsTMdXlOFCamQZHsmcYMG", - "target_total": 0, - }, - { - "budget_amount_total": 720000, - "id": 7, - "iso3": "kfs", - "name": "country-ZwjrVnVzStakFageXSAHAPsUBklxlTimFlGhCKnlmdVlZWmqAC", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-fyhrevbLpEFRWgadrWaQLYcgnHYayMHWrFEWvMBvxRvupxQzyN", - "target_total": 0, - }, - { - "budget_amount_total": 4740000, - "id": 9, - "iso3": "hWp", - "name": "country-FSBAdOgXrUUrqOGvAQqwfagTZFpLFoLBQrgXTFJMKyMHQycMgL", - "ongoing_projects": 1, - "operation_types": [0], - "operation_types_display": ["Programme"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-xLRTMAzTVcwPYCDKHczZOVXBQbnKlbOvgsAZbUDqwRwwprCYdu", - "target_total": 0, - }, - { - "budget_amount_total": 1510000, - "id": 11, - "iso3": "upQ", - "name": "country-jfwLeHpiSEbcdrzABgtvOLbWeYhdCLFQDhqcbVPqLpIXJeTKWS", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-TeuYlcqNMGcZLtPMFzYMHFOoPemDLCRhAyMJVsgAygjnFsdFEK", - "target_total": 0, - }, - { - "budget_amount_total": 2590000, - "id": 13, - "iso3": "DUn", - "name": "country-HMXjEmKAVfuMCBqXaumRPVuACdVEGMDFTvwqkBeLTbpYHqjlEn", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-ldTllPjEggWeDxPFBMhFgBkdXskNIxhsrJzKJocxlgBLanLZll", - "target_total": 0, - }, - { - "budget_amount_total": 4880000, - "id": 15, - "iso3": "Rap", - "name": "country-pUBMSvIcwbWUYtuZdxUcMlIrzDkUadDmrlWMWmKcSDCoVFjLur", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-JbeAivJwhwcRiSSOatvbQlJgtnvoeiDMqXRRRRooWFNWvmfZUU", - "target_total": 0, - }, - { - "budget_amount_total": 6060000, - "id": 17, - "iso3": "ZEZ", - "name": "country-SQTvZhsNCjqMSdmiiprEFesBYNvcLpTwuxwSCcjccAhEqemAtq", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-zhXkgJKpQMfOjERUWYaAubCVzgjkjIPpPTObxyssAJSwpQaqxx", - "target_total": 0, - }, - { - "budget_amount_total": 9860000, - "id": 19, - "iso3": "qzl", - "name": "country-ZMhpQyDQuMgAtrSOKhumYjUhJPbggmdHuingwzIXkpslIqTaUi", - "ongoing_projects": 1, - "operation_types": [0], - "operation_types_display": ["Programme"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-zEfOpXkaiupWqkpIBCZcCEybtXiNUmPOQQLWIFOTBTzEtdISFF", - "target_total": 0, - }, - { - "budget_amount_total": 720000, - "id": 21, - "iso3": "Eof", - "name": "country-cjVwtpezOoKeuGtArEivAdsyZDGkPcRnBNbzSguTYSwcQlzepq", - "ongoing_projects": 1, - "operation_types": [0], - "operation_types_display": ["Programme"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-ijYXRdTByCBzusPauoVOlrkOPhSAKrovoSkGVBeDJQaxJepHcv", - "target_total": 0, - }, - { - "budget_amount_total": 6410000, - "id": 23, - "iso3": "MrZ", - "name": "country-yMnkUJDOKRkTFsRYyXllzGRNEumfeVwkQqWYnIFiQbCuCMmUgt", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-YZhLTKyQruRKWWPylOqQmJraKTjXFCQewCoQOAHvaPCduRhIjw", - "target_total": 0, - }, - { - "budget_amount_total": 6200000, - "id": 25, - "iso3": "vac", - "name": "country-uelMHjMPVqwrWfGnmXFJHgtPFWTtjwbDZtoHicmMwRdPTZdCGB", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-XumVuEYOOyTdPozCnnyerlqErfwWfBVojNuBATePrGXYYSkSqP", - "target_total": 0, - }, - { - "budget_amount_total": 7950000, - "id": 27, - "iso3": "sma", - "name": "country-BkXnCGxSWCDgRDhleKLKmSPMYfFyUVEaQWFOaaikPCKBXkVrtv", - "ongoing_projects": 1, - "operation_types": [0], - "operation_types_display": ["Programme"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-SaoMIFGOWcAYsBvKtVMfQWIAIPUtMPGFSrMTmSlanULjkyJzGE", - "target_total": 0, - }, - { - "budget_amount_total": 1600000, - "id": 29, - "iso3": "nad", - "name": "country-saPeEKTeLtrSTvOxEBVyLWTyjwmACggFhVicotxSESrhOCvywZ", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-ilslioCfzytonQUmVZSwfZMNNCOVkeeeuiNkCWaYNRLnUdAZEB", - "target_total": 0, - }, - { - "budget_amount_total": 520000, - "id": 31, - "iso3": "yYU", - "name": "country-BdtUtdtjrgsjSRAuyjBezdqztpbUbCktDzySawXTnenNTEWHnD", - "ongoing_projects": 1, - "operation_types": [0], - "operation_types_display": ["Programme"], - "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} - ], - "society_name": "society-name-MYoFEUEYltXVlqkEGtYSelIQFOAXYgiWVGjBgkrTLNJDCMKMsQ", - "target_total": 0, - }, - { - "budget_amount_total": 4160000, - "id": 33, - "iso3": "XDR", - "name": "country-ajzWfByYHQquRdguYBVPikvZIqHhNWbAasvPVNIlTCJesEcvQV", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], + "budget_amount_total": 800000, + "id": 3, + "iso3": "Osx", + "name": "country-sKRWmlNOzBGufzQgliEupaqypCWrvtLUKaqPxSpdQhDtkzRGTX", + "ongoing_projects": 8, + "operation_types": [0, 1], + "operation_types_display": ["Programme", "Emergency Operation"], "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} + {"count": 8, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} ], - "society_name": "society-name-gEjLhkzKGguporwomItnbNOiAMDGGPmnhdTlXdGvSjcPxzqvNH", + "society_name": "society-name-NooiEjDVMxASJEWIZQnWpRWMYfHCHTxeKhdJGmKIjkuHChRnTL", "target_total": 0, }, { - "budget_amount_total": 1250000, - "id": 35, - "iso3": "tvr", - "name": "country-IHXBmvMsgjoaQYEwyWCtupDUFcMzqjixAnGXxeBbmhjeXNftqi", - "ongoing_projects": 1, - "operation_types": [1], - "operation_types_display": ["Emergency Operation"], + "budget_amount_total": 800000, + "id": 4, + "iso3": "ZRt", + "name": "country-fLgGiOzeLKdBQipsquZzSVuuCroemiXXLgjgkCDuAhIwXnCtDq", + "ongoing_projects": 8, + "operation_types": [0, 1], + "operation_types_display": ["Programme", "Emergency Operation"], "projects_per_sector": [ - {"count": 1, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} + {"count": 8, "primary_sector": 1, "primary_sector_display": "sect-zoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYx"} ], - "society_name": "society-name-dpiETrgvqBqljxxKiiFeNlOaEtrfQgsRHykMQTFGmiOGsumHhW", + "society_name": "society-name-TSMcnujfTpwzGdRtqlbzCJVJpgDgZYihadXoimzxROPfLLqebe", "target_total": 0, }, ] @@ -263,89 +88,19 @@ ,,,,,,,,,,,,False,,,10,,,,,,,,,,,True,True,,,,,,,,,,\r """ -snapshots["TestProjectAPI::test_project_create 1"] = { - "actual_expenditure": 0, - "annual_splits": [], - "budget_amount": 5790000, - "description": "", - "document": None, - "dtype": None, - "dtype_detail": None, - "end_date": "2008-01-01", - "event": None, - "event_detail": None, - "id": 1, - "modified_at": "2008-01-01T00:00:00.123456Z", - "modified_by": None, - "modified_by_detail": None, - "name": "Mock Project for Create API Test", - "operation_type": 0, - "operation_type_display": "Programme", - "primary_sector": 1, - "primary_sector_display": "sect-blDLTmDfquSPTYkTUhfhTCOxfHTyUYGNkyJycXkvKQjkjlXTdA", - "programme_type": 0, - "programme_type_display": "Bilateral", - "project_admin2": [], - "project_admin2_detail": [], - "project_country": 1, - "project_country_detail": { - "id": 1, - "iso": "fn", - "iso3": "CME", - "name": "country-rnjlkxMThQoAZvUhEREEnLkPAbpciKLkiOGcKjdkqlHzMKObUU", - "society_name": "society-name-EkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGWhfEQi", - }, - "project_districts": [1], - "project_districts_detail": [{"id": 1, "name": "district-DpBzXcMVyUuzNVKMIHPTYcHgCDcpHIzVcJyHWOdmsCztXsDkBs"}], - "reached_female": 0, - "reached_male": 0, - "reached_other": 0, - "reached_total": 0, - "regional_project": None, - "regional_project_detail": None, - "reporting_ns": 1, - "reporting_ns_contact_email": None, - "reporting_ns_contact_name": None, - "reporting_ns_contact_role": None, - "reporting_ns_detail": { - "id": 1, - "iso": "fn", - "iso3": "CME", - "name": "country-rnjlkxMThQoAZvUhEREEnLkPAbpciKLkiOGcKjdkqlHzMKObUU", - "society_name": "society-name-EkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGWhfEQi", - }, - "secondary_sectors": [1, 2], - "secondary_sectors_display": [ - "sect-tag-tUXCsOlhimaNWqaDFFIZaMFpnLQEDACfMMapJrNOJndljdPwcj", - "sect-tag-QKMtvfdgAlkRsNQSSMKYJlDVLxcfXtuxyeWBJesEihSrvHAHnS", - ], - "start_date": "2008-01-01", - "status": 1, - "status_display": "Ongoing", - "target_female": 0, - "target_male": 0, - "target_other": 0, - "target_total": 0, - "translation_module_original_language": "en", - "translation_module_skip_auto_translation": False, - "user": 5, - "visibility": "public", - "visibility_display": "Public", -} - snapshots[ "TestProjectAPI::test_project_csv_api 1" ] = """actual_expenditure,budget_amount,description,document,dtype,dtype_detail.id,dtype_detail.name,dtype_detail.summary,dtype_detail.translation_module_original_language,end_date,event,event_detail.dtype,event_detail.emergency_response_contact_email,event_detail.id,event_detail.name,event_detail.parent_event,event_detail.slug,event_detail.start_date,event_detail.translation_module_original_language,id,modified_at,modified_by,modified_by_detail,name,operation_type,operation_type_display,primary_sector,primary_sector_display,programme_type,programme_type_display,project_country,project_country_detail.id,project_country_detail.iso,project_country_detail.iso3,project_country_detail.name,project_country_detail.society_name,project_districts_detail.code,project_districts_detail.id,project_districts_detail.is_deprecated,project_districts_detail.is_enclave,project_districts_detail.name,reached_female,reached_male,reached_other,reached_total,regional_project,regional_project_detail.created_at,regional_project_detail.id,regional_project_detail.modified_at,regional_project_detail.name,regional_project_detail.translation_module_original_language,regional_project_detail.translation_module_skip_auto_translation,reporting_ns,reporting_ns_contact_email,reporting_ns_contact_name,reporting_ns_contact_role,reporting_ns_detail.id,reporting_ns_detail.iso,reporting_ns_detail.iso3,reporting_ns_detail.name,reporting_ns_detail.society_name,secondary_sectors,secondary_sectors_display,start_date,status,status_display,target_female,target_male,target_other,target_total,translation_module_original_language,translation_module_skip_auto_translation,user,visibility,visibility_display\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,1,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,2,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,3,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,4,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,5,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,6,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,7,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,8,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,9,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,disaster-type-1-summary,en,2008-01-01,2,1,,2,event-1,1,lklfnynrpfljodoqdqqazdsrikecwltobsqdtmyegpykwksssb,,en,10,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sector-1,0,Bilateral,1,1,Oh,bVr,country-1,society-name-1,,,,,,0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,Oh,bVr,country-1,society-name-1,"1, 2","sector-tag-1, sector-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,1,2008-01-01T00:00:00.123456Z,,,project-hbvPgRZkVpHlJkvJBDoZzOllOQBzbVNmCLByaTnnrWTZYeKgZI,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,2,2008-01-01T00:00:00.123456Z,,,project-NzLhwwDNlRTZtNLfRiuhpthlxSjGyAMiKyBlFOISPlJkFsiluC,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,6,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,3,2008-01-01T00:00:00.123456Z,,,project-ATCFkfKbYWoscroIskXDKVXXFJGhKhrXIxIWcWUCInBgVPWptc,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,7,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,4,2008-01-01T00:00:00.123456Z,,,project-NOBkNiYnnZdKwIrMIkuTssKrGRgiWYAdrPiSipjTupWRzFjKOr,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,8,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,5,2008-01-01T00:00:00.123456Z,,,project-uLaXUfUDOQSweYIznBnFrusvJKiKFYvRWdcgOYDbhkCDaBmSiP,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,9,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,6,2008-01-01T00:00:00.123456Z,,,project-OtUSWoBPfTganEeiLoHRCaaSvhBSiEeoyfUZgguxtiyXWiPRje,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,10,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,7,2008-01-01T00:00:00.123456Z,,,project-giWhLUywBuYiprPfpJMMUMsXSbQtnHMGmVzsPdYYpFyhpFOMeH,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,11,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,8,2008-01-01T00:00:00.123456Z,,,project-bLeaqncdYzGsOTGXABSzfOIINjrftfGnZjIuzLOWPRPetSBUpd,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,12,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,9,2008-01-01T00:00:00.123456Z,,,project-iSakFwHHYUqkxiVXrUhXbvZBrHeqTKOeFDGxdFKkxkqXgKRUho,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,13,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,10,2008-01-01T00:00:00.123456Z,,,project-cJZTVPAoupAUureKxhGRdloZHczeDsXtufJDaxmsKYtVNpDxLF,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,14,public,Public\r """ snapshots["TestProjectAPI::test_project_delete 1"] = b"" @@ -358,14 +113,14 @@ { "actual_expenditure": 0, "annual_splits": [], - "budget_amount": 6440000, + "budget_amount": 8500000, "description": "", "document": None, "dtype": 3, "dtype_detail": { "id": 3, - "name": "disaster-type-MSVGtSJuTVJOnmnNTsRwRiTPlGISOuThWwJELKQTARVIsBZaHg", - "summary": "byjdQdmrWYksRqjdSYsnWIcwCgNRVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHq", + "name": "disaster-type-SOuThWwJELKQTARVIsBZaHgbyjdQdmrWYksRqjdSYsnWIcwCgN", + "summary": "RVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHqyoHzwwFYEMaGiCkoeGPrnjlkxMT", "translation_module_original_language": "en", }, "end_date": "2008-01-01", @@ -375,9 +130,9 @@ "dtype": 1, "emergency_response_contact_email": None, "id": 2, - "name": "event-xNooiEjDVMxASJEWIZQnWpRWMYfHCHTxeKhdJGmKIjkuHChRnT", + "name": "N/A: disaster-type-hlIzHiUoaWbtDRUIBIyopDwjrmUWhcZQANXbpnegMcCMRTdpVc - 01-2008 - LFfGCZdDiG", "parent_event": 1, - "slug": "lffgczddigadkdjdrztubzqavnlecbwseideecsalxixpupaxy", + "slug": "adkdjdrztubzqavnlecbwseideecsalxixpupaxycyyfrqiipw", "start_date": None, "translation_module_original_language": "en", }, @@ -385,7 +140,7 @@ "modified_at": "2008-01-01T00:00:00.123456Z", "modified_by": None, "modified_by_detail": None, - "name": "project-yoHzwwFYEMaGiCkoeGPrnjlkxMThQoAZvUhEREEnLkPAbpciKL", + "name": "project-hQoAZvUhEREEnLkPAbpciKLkiOGcKjdkqlHzMKObUUQsfnCMEE", "operation_type": 0, "operation_type_display": "Programme", "primary_sector": 1, @@ -413,7 +168,7 @@ "created_at": "2008-01-01T00:00:00.123456Z", "id": 1, "modified_at": "2008-01-01T00:00:00.123456Z", - "name": "regional-project-fnCMEEkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGW", + "name": "regional-project-yyigbmHGRAjMglENMcYIGWhfEQiMIaXRPBHAxcSHBoZEYXywLZ", "translation_module_original_language": "en", "translation_module_skip_auto_translation": False, }, @@ -454,14 +209,14 @@ { "actual_expenditure": 0, "annual_splits": [], - "budget_amount": 6440000, + "budget_amount": 8500000, "description": "", "document": None, "dtype": 3, "dtype_detail": { "id": 3, - "name": "disaster-type-MSVGtSJuTVJOnmnNTsRwRiTPlGISOuThWwJELKQTARVIsBZaHg", - "summary": "byjdQdmrWYksRqjdSYsnWIcwCgNRVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHq", + "name": "disaster-type-SOuThWwJELKQTARVIsBZaHgbyjdQdmrWYksRqjdSYsnWIcwCgN", + "summary": "RVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHqyoHzwwFYEMaGiCkoeGPrnjlkxMT", "translation_module_original_language": "en", }, "end_date": "2008-01-01", @@ -471,9 +226,9 @@ "dtype": 1, "emergency_response_contact_email": None, "id": 2, - "name": "event-xNooiEjDVMxASJEWIZQnWpRWMYfHCHTxeKhdJGmKIjkuHChRnT", + "name": "N/A: disaster-type-hlIzHiUoaWbtDRUIBIyopDwjrmUWhcZQANXbpnegMcCMRTdpVc - 01-2008 - LFfGCZdDiG", "parent_event": 1, - "slug": "lffgczddigadkdjdrztubzqavnlecbwseideecsalxixpupaxy", + "slug": "adkdjdrztubzqavnlecbwseideecsalxixpupaxycyyfrqiipw", "start_date": None, "translation_module_original_language": "en", }, @@ -481,7 +236,7 @@ "modified_at": "2008-01-01T00:00:00.123456Z", "modified_by": None, "modified_by_detail": None, - "name": "project-yoHzwwFYEMaGiCkoeGPrnjlkxMThQoAZvUhEREEnLkPAbpciKL", + "name": "project-hQoAZvUhEREEnLkPAbpciKLkiOGcKjdkqlHzMKObUUQsfnCMEE", "operation_type": 0, "operation_type_display": "Programme", "primary_sector": 1, @@ -509,7 +264,7 @@ "created_at": "2008-01-01T00:00:00.123456Z", "id": 1, "modified_at": "2008-01-01T00:00:00.123456Z", - "name": "regional-project-fnCMEEkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGW", + "name": "regional-project-yyigbmHGRAjMglENMcYIGWhfEQiMIaXRPBHAxcSHBoZEYXywLZ", "translation_module_original_language": "en", "translation_module_skip_auto_translation": False, }, @@ -542,14 +297,14 @@ { "actual_expenditure": 0, "annual_splits": [], - "budget_amount": 6090000, + "budget_amount": 9540000, "description": "", "document": None, "dtype": 6, "dtype_detail": { "id": 6, - "name": "disaster-type-blCoqPewfsGGIPfYroghexcImvmRvqtVXRrmTMiWTVIqaXtswY", - "summary": "zzLWPaEPGWjzooUVnEoHLYJWDUDvYfumBXSAnCCJbxiKitVaFZQwvoABRWzWXSItuLbKYcijvKOZMMKzynzeIymEgvKCOtfkgRJlcSMFblmeysnosQHeDdxHakuAzkhiIAEVeynintBTQEkMKtLmGTRDrmajCezMZpHvKFDDKcVfsPDwSTYtzNZlAplNUBDyQlSKgzScpkrOIsQeSUUnFAWJhxeWgGXXuACkqnGcDbeOSRVDyvVzmzcaqhTiuQVDFDefJQpTCiErkkbMglshIVzkeQWaRrjCwlnTcRInCSdOZHPQTQgyStCdMadXyXmpxpmfbAbavmRQeogZQkUkcAGguuJOmNnIzBhongwulazPuaynDoeQrPNxcenAtXMFgTIYKkqgMuOSyRXSivlOWSuQEevbMLCyGOVoGLTaobNWhtpVBWpNfdixFsmjynPcpUMCVviruPYWcHYAPsWboUvvpnIdQpZRSUoMyHulCOaeFemdOjni", + "name": "disaster-type-swYzzLWPaEPGWjzooUVnEoHLYJWDUDvYfumBXSAnCCJbxiKitV", + "summary": "aFZQwvoABRWzWXSItuLbKYcijvKOZMMKzynzeIymEgvKCOtfkgRJlcSMFblmeysnosQHeDdxHakuAzkhiIAEVeynintBTQEkMKtLmGTRDrmajCezMZpHvKFDDKcVfsPDwSTYtzNZlAplNUBDyQlSKgzScpkrOIsQeSUUnFAWJhxeWgGXXuACkqnGcDbeOSRVDyvVzmzcaqhTiuQVDFDefJQpTCiErkkbMglshIVzkeQWaRrjCwlnTcRInCSdOZHPQTQgyStCdMadXyXmpxpmfbAbavmRQeogZQkUkcAGguuJOmNnIzBhongwulazPuaynDoeQrPNxcenAtXMFgTIYKkqgMuOSyRXSivlOWSuQEevbMLCyGOVoGLTaobNWhtpVBWpNfdixFsmjynPcpUMCVviruPYWcHYAPsWboUvvpnIdQpZRSUoMyHulCOaeFemdOjniflLJYnpGfBUDtkUmpBlMptsKCOmrYEfxzykECBGNVBWjYEb", "translation_module_original_language": "en", }, "end_date": "2008-01-01", @@ -559,9 +314,9 @@ "dtype": 4, "emergency_response_contact_email": None, "id": 4, - "name": "event-ZoHPvALvPPYuFLQSHJCDtKiYtkYqoExsXdjwsDkNkTIsllTSQY", + "name": "N/A: disaster-type-bfICRQfGzmFuMMGdQxzjTBxyxaswwtCJfnUCVAZCskZUBUAiLM - 01-2008 - kIthbzFXjD", "parent_event": 3, - "slug": "jkphcukicqxlnjtcquwjxcikithbzfxjdujavigvptseswkqjz", + "slug": "ujavigvptseswkqjzkucvshuecirjhtbznocwfudmpmlhoyxrm", "start_date": None, "translation_module_original_language": "en", }, @@ -569,7 +324,7 @@ "modified_at": "2008-01-01T00:00:00.123456Z", "modified_by": None, "modified_by_detail": None, - "name": "project-flLJYnpGfBUDtkUmpBlMptsKCOmrYEfxzykECBGNVBWjYEbWyB", + "name": "project-WyBfWtMIjJUlqyDtDsyJMEeviTEmjmaaGUUxFzAzVxyFtPLeAc", "operation_type": 1, "operation_type_display": "Emergency Operation", "primary_sector": 1, @@ -581,10 +336,10 @@ "project_country": 4, "project_country_detail": { "id": 4, - "iso": "rN", - "iso3": "OJn", - "name": "country-XkvKQjkjlXTdAttUXCsOlhimaNWqaDFFIZaMFpnLQEDACfMMap", - "society_name": "society-name-dljdPwcjcQKMtvfdgAlkRsNQSSMKYJlDVLxcfXtuxyeWBJesEi", + "iso": "Al", + "iso3": "kRs", + "name": "country-imaNWqaDFFIZaMFpnLQEDACfMMapJrNOJndljdPwcjcQKMtvfd", + "society_name": "society-name-NQSSMKYJlDVLxcfXtuxyeWBJesEihSrvHAHnSnNdgKUOHfEUSM", }, "project_districts": [], "project_districts_detail": [], @@ -597,7 +352,7 @@ "created_at": "2008-01-01T00:00:00.123456Z", "id": 2, "modified_at": "2008-01-01T00:00:00.123456Z", - "name": "regional-project-JMEeviTEmjmaaGUUxFzAzVxyFtPLeAchyKkmWBqXWUwGTFOSxS", + "name": "regional-project-VppEcxOTRbSQPjqMDRjqpMLQkahXfPTyzTLfHmBkBqStGIQyLt", "translation_module_original_language": "en", "translation_module_skip_auto_translation": False, }, @@ -607,10 +362,10 @@ "reporting_ns_contact_role": None, "reporting_ns_detail": { "id": 3, - "iso": "yP", - "iso3": "nSZ", - "name": "country-MIaXRPBHAxcSHBoZEYXywLZVWSKgBiqEXofsMIAqmaTVYaKHhH", - "society_name": "society-name-uAxgjBPLqqIBKxNrRzWnAJYJElxJJEqtKwXTzViQhVoCYSkgnG", + "iso": "YJ", + "iso3": "Elx", + "name": "country-gBiqEXofsMIAqmaTVYaKHhHayPnSZuAxgjBPLqqIBKxNrRzWnA", + "society_name": "society-name-JJEqtKwXTzViQhVoCYSkgnGzYvZJNSRTdkyOaZfjEMBfeqoxfM", }, "secondary_sectors": [], "secondary_sectors_display": [], @@ -635,14 +390,14 @@ snapshots["TestProjectAPI::test_project_read 1"] = { "actual_expenditure": 0, "annual_splits": [], - "budget_amount": 6440000, + "budget_amount": 8500000, "description": "", "document": None, "dtype": 3, "dtype_detail": { "id": 3, - "name": "disaster-type-MSVGtSJuTVJOnmnNTsRwRiTPlGISOuThWwJELKQTARVIsBZaHg", - "summary": "byjdQdmrWYksRqjdSYsnWIcwCgNRVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHq", + "name": "disaster-type-SOuThWwJELKQTARVIsBZaHgbyjdQdmrWYksRqjdSYsnWIcwCgN", + "summary": "RVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHqyoHzwwFYEMaGiCkoeGPrnjlkxMT", "translation_module_original_language": "en", }, "end_date": "2008-01-01", @@ -652,9 +407,9 @@ "dtype": 1, "emergency_response_contact_email": None, "id": 2, - "name": "event-xNooiEjDVMxASJEWIZQnWpRWMYfHCHTxeKhdJGmKIjkuHChRnT", + "name": "N/A: disaster-type-hlIzHiUoaWbtDRUIBIyopDwjrmUWhcZQANXbpnegMcCMRTdpVc - 01-2008 - LFfGCZdDiG", "parent_event": 1, - "slug": "lffgczddigadkdjdrztubzqavnlecbwseideecsalxixpupaxy", + "slug": "adkdjdrztubzqavnlecbwseideecsalxixpupaxycyyfrqiipw", "start_date": None, "translation_module_original_language": "en", }, @@ -662,7 +417,7 @@ "modified_at": "2008-01-01T00:00:00.123456Z", "modified_by": None, "modified_by_detail": None, - "name": "project-yoHzwwFYEMaGiCkoeGPrnjlkxMThQoAZvUhEREEnLkPAbpciKL", + "name": "project-hQoAZvUhEREEnLkPAbpciKLkiOGcKjdkqlHzMKObUUQsfnCMEE", "operation_type": 0, "operation_type_display": "Programme", "primary_sector": 1, @@ -690,7 +445,7 @@ "created_at": "2008-01-01T00:00:00.123456Z", "id": 1, "modified_at": "2008-01-01T00:00:00.123456Z", - "name": "regional-project-fnCMEEkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGW", + "name": "regional-project-yyigbmHGRAjMglENMcYIGWhfEQiMIaXRPBHAxcSHBoZEYXywLZ", "translation_module_original_language": "en", "translation_module_skip_auto_translation": False, }, @@ -724,14 +479,14 @@ snapshots["TestProjectAPI::test_project_update 1"] = { "actual_expenditure": 0, "annual_splits": [], - "budget_amount": 6440000, + "budget_amount": 8500000, "description": "", "document": None, "dtype": 3, "dtype_detail": { "id": 3, - "name": "disaster-type-MSVGtSJuTVJOnmnNTsRwRiTPlGISOuThWwJELKQTARVIsBZaHg", - "summary": "byjdQdmrWYksRqjdSYsnWIcwCgNRVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHq", + "name": "disaster-type-SOuThWwJELKQTARVIsBZaHgbyjdQdmrWYksRqjdSYsnWIcwCgN", + "summary": "RVJoVPJypGYYZSsSQdyyAYRuJdaVqmNXCoOTTPxWLIVMmXUmsClRellVGhycBrJqikLqavDTjcjuMdXONQtFYKJweYTuHolHeYGkAIIzfwonQvvxsnWNHEJWPahQwCpPNNpcRuyYhyqIUsbHXxGZGCFcsPmuGfgkXIIaOenQOXnRBgnISVXBPeVRjbDTvcfedlYqJeKoqAyCOzBubyRhIaPUNeWVLcSewGgsYRtMfsWCyzQbEkIoiVzYZIsOjtRYUPxaJJjhcaKMzIJftnVVUwnAPGjkloNqmhlQZKdWJDPJesQeqgmULFvwiQPpgsNemuFCvNQtSLjKKxZuBkaupYoTVPBrxiRUvEDCwXtFJglPMfriImqUOeUebGObLLzXLncJqIIEPXjxzoXLUsiDGGfzxGaQpZNRkWGiCklKKQjVUEwcoWFoeqxocQnHYxyEDccPugTHOrVqLIKlyPyxLPeHqyoHzwwFYEMaGiCkoeGPrnjlkxMT", "translation_module_original_language": "en", }, "end_date": "2008-01-01", @@ -741,9 +496,9 @@ "dtype": 1, "emergency_response_contact_email": None, "id": 2, - "name": "event-xNooiEjDVMxASJEWIZQnWpRWMYfHCHTxeKhdJGmKIjkuHChRnT", + "name": "N/A: disaster-type-hlIzHiUoaWbtDRUIBIyopDwjrmUWhcZQANXbpnegMcCMRTdpVc - 01-2008 - LFfGCZdDiG", "parent_event": 1, - "slug": "lffgczddigadkdjdrztubzqavnlecbwseideecsalxixpupaxy", + "slug": "adkdjdrztubzqavnlecbwseideecsalxixpupaxycyyfrqiipw", "start_date": None, "translation_module_original_language": "en", }, @@ -763,13 +518,13 @@ "project_country": 3, "project_country_detail": { "id": 3, - "iso": "ay", - "iso3": "PnS", - "name": "country-iMIaXRPBHAxcSHBoZEYXywLZVWSKgBiqEXofsMIAqmaTVYaKHh", - "society_name": "society-name-ZuAxgjBPLqqIBKxNrRzWnAJYJElxJJEqtKwXTzViQhVoCYSkgn", + "iso": "AJ", + "iso3": "YJE", + "name": "country-SKgBiqEXofsMIAqmaTVYaKHhHayPnSZuAxgjBPLqqIBKxNrRzW", + "society_name": "society-name-lxJJEqtKwXTzViQhVoCYSkgnGzYvZJNSRTdkyOaZfjEMBfeqox", }, "project_districts": [1], - "project_districts_detail": [{"id": 1, "name": "district-kyJycXkvKQjkjlXTdAttUXCsOlhimaNWqaDFFIZaMFpnLQEDAC"}], + "project_districts_detail": [{"id": 1, "name": "district-imaNWqaDFFIZaMFpnLQEDACfMMapJrNOJndljdPwcjcQKMtvfd"}], "reached_female": 0, "reached_male": 0, "reached_other": 0, @@ -779,7 +534,7 @@ "created_at": "2008-01-01T00:00:00.123456Z", "id": 1, "modified_at": "2008-01-01T00:00:00.123456Z", - "name": "regional-project-fnCMEEkoAMjYLXlNQGqkURvDMLeoyyigbmHGRAjMglENMcYIGW", + "name": "regional-project-yyigbmHGRAjMglENMcYIGWhfEQiMIaXRPBHAxcSHBoZEYXywLZ", "translation_module_original_language": "en", "translation_module_skip_auto_translation": False, }, @@ -789,10 +544,10 @@ "reporting_ns_contact_role": None, "reporting_ns_detail": { "id": 3, - "iso": "ay", - "iso3": "PnS", - "name": "country-iMIaXRPBHAxcSHBoZEYXywLZVWSKgBiqEXofsMIAqmaTVYaKHh", - "society_name": "society-name-ZuAxgjBPLqqIBKxNrRzWnAJYJElxJJEqtKwXTzViQhVoCYSkgn", + "iso": "AJ", + "iso3": "YJE", + "name": "country-SKgBiqEXofsMIAqmaTVYaKHhHayPnSZuAxgjBPLqqIBKxNrRzW", + "society_name": "society-name-lxJJEqtKwXTzViQhVoCYSkgnGzYvZJNSRTdkyOaZfjEMBfeqox", }, "secondary_sectors": [], "secondary_sectors_display": [], diff --git a/deployments/tests.py b/deployments/tests.py index f064e5afc..5e4ef1af9 100644 --- a/deployments/tests.py +++ b/deployments/tests.py @@ -4,9 +4,7 @@ import api.models as models from api.factories import country, district -from api.factories.disaster_type import DisasterTypeFactory -from api.factories.event import EventFactory -from api.factories.region import RegionFactory +from api.factories.event import DisasterTypeFactory, EventFactory from deployments.factories.emergency_project import ( EmergencyProjectActivityActionFactory, EmergencyProjectActivityFactory, @@ -106,7 +104,6 @@ def test_project_create(self): # check response self.assert_201(response) - self.assertMatchSnapshot(json.loads(response.content)) self.assertTrue(Project.objects.get(name=new_project_name)) def test_project_read(self): @@ -194,41 +191,33 @@ def test_personnel_csv_api(self): self.assertMatchSnapshot(resp.content.decode("utf-8")) def test_project_csv_api(self): - _user = UserFactory(username="jo") - region = RegionFactory(name=models.RegionName.AMERICAS) - _country = country.CountryFactory( - name="country-1", - record_type=models.CountryType.COUNTRY, - society_name="society-name-1", - region=region, - ) - sct = SectorFactory(title="sector-1") - sct_1 = SectorTagFactory(title="sector-tag-1") - sct_2 = SectorTagFactory(title="sector-tag-2") - dtype = DisasterTypeFactory( - name="disaster-type-1", - summary="disaster-type-1-summary", - ) + _country = country.CountryFactory(name="country-1") + sct = SectorFactory(title="sect-1") + sct_1 = SectorTagFactory(title="sec-tag-1") + sct_2 = SectorTagFactory(title="sec-tag-2") + district1 = district.DistrictFactory(country=_country) + district2 = district.DistrictFactory(country=_country) + dtype = DisasterTypeFactory(name="disaster-type-1", summary="summary") regional_project = RegionalProjectFactory(name="regional-project-1") event = EventFactory( countries=[_country.id], + districts=[district1.id, district2.id], dtype=dtype, - name="event-1", + title="event-1", ) ProjectFactory.create_batch( 10, - name="project-1", - primary_sector=sct, - secondary_sectors=[sct_1, sct_2], + project_districts=[district1, district2], budget_amount=100000, + primary_sector=sct, event=event, regional_project=regional_project, + secondary_sectors=[sct_1, sct_2], dtype=dtype, visibility=VisibilityCharChoices.PUBLIC, project_country=_country, reporting_ns=_country, status=Statuses.COMPLETED, - user=_user, programme_type=ProgrammeTypes.BILATERAL, operation_type=OperationTypes.EMERGENCY_OPERATION, ) @@ -256,14 +245,18 @@ def test_global_project_api(self): ProjectFactory.create_batch( 2, primary_sector=sct, + programme_type=programme_type, + reporting_ns=ns, project_districts=project_districts, + secondary_sectors=secondary_sectors, visibility=VisibilityCharChoices.PUBLIC, + budget_amount=100000, ) - for project_districts, secondary_sectors in [ - ([c1_district1, c1_district2], [sct_1, sct_2]), - ([c1_district1, c1_district2], [sct_3, sct_4]), - ([c2_district1, c2_district2], [sct_1, sct_3]), - ([c2_district1, c2_district2], [sct_2, sct_4]), + for project_districts, secondary_sectors, programme_type in [ + ([c1_district1, c1_district2], [sct_1, sct_2], ProgrammeTypes.BILATERAL), + ([c1_district1, c1_district2], [sct_3, sct_4], ProgrammeTypes.MULTILATERAL), + ([c2_district1, c2_district2], [sct_1, sct_3], ProgrammeTypes.DOMESTIC), + ([c2_district1, c2_district2], [sct_2, sct_4], ProgrammeTypes.DOMESTIC), ] for ns in [ns_1, ns_2] ] From e2c0b811a97fd1e3725c946ab1a9925325bf94b0 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Fri, 15 Nov 2024 11:01:18 +0545 Subject: [PATCH 3/6] Add fieldreport number logic and suffic for covid --- api/admin.py | 2 +- ..._event_title_ar_event_title_en_and_more.py | 7 ++++- api/models.py | 28 +++++++++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/api/admin.py b/api/admin.py index afed23e14..10341e323 100644 --- a/api/admin.py +++ b/api/admin.py @@ -325,7 +325,7 @@ class FieldReportAdmin(CompareVersionAdmin, RegionRestrictedAdmin, TranslationAd "districts", ) - readonly_fields = ("report_date", "created_at", "updated_at", "summary") + readonly_fields = ("report_date", "created_at", "updated_at", "summary", "fr_num") list_filter = [MembershipFilter] actions = [ "create_events", diff --git a/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py b/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py index 686006441..4e0d326fe 100644 --- a/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py +++ b/api/migrations/0215_event_title_event_title_ar_event_title_en_and_more.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.16 on 2024-10-07 18:46 +# Generated by Django 4.2.16 on 2024-11-20 09:20 from django.db import migrations, models @@ -35,6 +35,11 @@ class Migration(migrations.Migration): name="title_fr", field=models.CharField(blank=True, max_length=256, null=True), ), + migrations.AddField( + model_name="fieldreport", + name="fr_num", + field=models.IntegerField(blank=True, null=True, verbose_name="field report number"), + ), migrations.AddField( model_name="fieldreport", name="title", diff --git a/api/models.py b/api/models.py index 4d648d896..ca1178a67 100644 --- a/api/models.py +++ b/api/models.py @@ -1487,6 +1487,7 @@ class RecentAffected(models.IntegerChoices): summary = models.TextField(verbose_name=_("summary"), blank=True) # Title field is used for the translation and later adding formated into the summary title = models.CharField(max_length=256, blank=True) + fr_num = models.IntegerField(verbose_name=_("field report number"), null=True, blank=True) description = HTMLField(verbose_name=_("description"), blank=True, default="") dtype = models.ForeignKey(DisasterType, verbose_name=_("disaster type"), on_delete=models.PROTECT) event = models.ForeignKey( @@ -1699,17 +1700,34 @@ def generate_formatted_summary(self): country_iso3 = self.countries.first().iso3 if self.id and self.countries.first() else "N/A" dtype = self.dtype.name if self.dtype else "N/A" start_date = self.start_date.strftime("%m-%Y") - field_report_number = FieldReport.objects.filter(countries__iso3=country_iso3).exclude(id=self.id).count() + 1 current_date = timezone.now().strftime("%Y-%m-%d") + if self.fr_num is None and self.event and self.id: + current_fr_number = ( + FieldReport.objects.filter(event=self.event, countries__iso3=country_iso3).aggregate( + max_fr_num=models.Max("fr_num") + )["max_fr_num"] + or 0 + ) + field_report_number = current_fr_number + 1 + self.fr_num = field_report_number + # NOTE: Updating the updated_fields when the fr_num is updated by translation tasks + yield "fr_num" + + # NOTE: Report number is set to None if the report is not associated with an event + if self.id and not self.event: + self.fr_num = None + + suffix = "" + if self.fr_num and self.fr_num > 1: + suffix = f"#{self.fr_num} ({current_date})" + for lang in AVAILABLE_LANGUAGES: activate(lang) if self.is_covid_report: - # {ISO3}: COVID-19 #{Field Report Number} ({Date}) - self.summary = f"{country_iso3}: COVID-19 #{field_report_number} ({current_date})" + self.summary = f"{country_iso3}: COVID-19 {suffix}" else: - # {ISO3}: {Disaster Type} - {Start Date} #{Field Report Number} ({Date}) - self.summary = f"{country_iso3}: {dtype} - {start_date} {self.title} #{field_report_number} ({current_date})" + self.summary = f"{country_iso3}: {dtype} - {start_date} - {self.title} {suffix}" deactivate() yield build_localized_fieldname("summary", lang) From 82c0c6fa94bf79fabba27524d15649592db9b308 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Fri, 15 Nov 2024 11:01:18 +0545 Subject: [PATCH 4/6] Add fieldreport number logic and suffic for covid --- api/models.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/api/models.py b/api/models.py index ca1178a67..cf1a60f64 100644 --- a/api/models.py +++ b/api/models.py @@ -1718,6 +1718,22 @@ def generate_formatted_summary(self): if self.id and not self.event: self.fr_num = None + suffix = f"#{self.fr_num} ({current_date})" if self.event else "" + + if self.fr_num is None and self.event and self.id: + current_fr_number = ( + FieldReport.objects.filter(event=self.event, countries__iso3=country_iso3).aggregate( + max_fr_num=models.Max("fr_num") + )["max_fr_num"] + or 0 + ) + field_report_number = current_fr_number + 1 + self.fr_num = field_report_number + + # NOTE: Report number is set to None if the report is not associated with an event + if self.id and not self.event: + self.fr_num = None + suffix = "" if self.fr_num and self.fr_num > 1: suffix = f"#{self.fr_num} ({current_date})" From b4c18bba870eff716d45eec243817fb50bee4fdd Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Tue, 31 Dec 2024 10:52:09 +0545 Subject: [PATCH 5/6] Generate title api for field report (#2355) * Add generate title api for field report * fix snapshot issue * Changes on generate title api --- api/drf_views.py | 39 +++++++++++++++++++- api/migrations/0217_merge_20250107_1019.py | 13 +++++++ api/models.py | 17 --------- api/serializers.py | 21 +++++++++++ api/test_views.py | 1 - api/utils.py | 42 ++++++++++++++++++++++ deployments/snapshots/snap_tests.py | 20 +++++------ deployments/tests.py | 14 ++++---- 8 files changed, 132 insertions(+), 35 deletions(-) create mode 100644 api/migrations/0217_merge_20250107_1019.py diff --git a/api/drf_views.py b/api/drf_views.py index a4ec3ed7e..cdc85718c 100644 --- a/api/drf_views.py +++ b/api/drf_views.py @@ -123,6 +123,8 @@ DistrictSerializerRMD, ExportSerializer, ExternalPartnerSerializer, + FieldReportGeneratedTitleSerializer, + FieldReportGenerateTitleSerializer, FieldReportSerializer, GoHistoricalSerializer, HistoricalDisasterSerializer, @@ -151,7 +153,7 @@ UserMeSerializer, UserSerializer, ) -from .utils import is_user_ifrc +from .utils import generate_field_report_title, is_user_ifrc class DeploymentsByEventViewset(viewsets.ReadOnlyModelViewSet): @@ -943,6 +945,41 @@ def get_serializer_class(self): return FieldReportSerializer return FieldReportSerializer + @extend_schema( + request=FieldReportGenerateTitleSerializer, + responses=FieldReportGeneratedTitleSerializer, + ) + @action( + detail=False, + methods=["post"], + url_path="generate-title", + permission_classes=[DenyGuestUserMutationPermission], + ) + def generate_title(self, request): + """ + Generate a title for a Field Report. + """ + serializer = FieldReportGenerateTitleSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + countries = serializer.validated_data.get("countries") + dtype = serializer.validated_data.get("dtype") + event = serializer.validated_data.get("event") + start_date = serializer.validated_data.get("start_date") + title = serializer.validated_data.get("title") + is_covid_report = serializer.validated_data.get("is_covid_report") + + summary = generate_field_report_title( + country=countries[0], dtype=dtype, event=event, start_date=start_date, title=title, is_covid_report=is_covid_report + ) + return Response( + FieldReportGeneratedTitleSerializer( + { + "title": summary, + } + ).data + ) + class ActionViewset(viewsets.ReadOnlyModelViewSet): queryset = Action.objects.exclude(is_disabled=True) diff --git a/api/migrations/0217_merge_20250107_1019.py b/api/migrations/0217_merge_20250107_1019.py new file mode 100644 index 000000000..818951a08 --- /dev/null +++ b/api/migrations/0217_merge_20250107_1019.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.16 on 2025-01-07 10:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("api", "0215_event_title_event_title_ar_event_title_en_and_more"), + ("api", "0216_district_emma_id_district_fips_code_district_nuts1_and_more"), + ] + + operations = [] diff --git a/api/models.py b/api/models.py index cf1a60f64..fb866f5a0 100644 --- a/api/models.py +++ b/api/models.py @@ -25,7 +25,6 @@ from tinymce.models import HTMLField from lang.translation import AVAILABLE_LANGUAGES - from main.fields import SecureFileField from .utils import validate_slug_number # is_user_ifrc, @@ -1718,22 +1717,6 @@ def generate_formatted_summary(self): if self.id and not self.event: self.fr_num = None - suffix = f"#{self.fr_num} ({current_date})" if self.event else "" - - if self.fr_num is None and self.event and self.id: - current_fr_number = ( - FieldReport.objects.filter(event=self.event, countries__iso3=country_iso3).aggregate( - max_fr_num=models.Max("fr_num") - )["max_fr_num"] - or 0 - ) - field_report_number = current_fr_number + 1 - self.fr_num = field_report_number - - # NOTE: Report number is set to None if the report is not associated with an event - if self.id and not self.event: - self.fr_num = None - suffix = "" if self.fr_num and self.fr_num > 1: suffix = f"#{self.fr_num} ({current_date})" diff --git a/api/serializers.py b/api/serializers.py index 8c8b2aa30..7219fe678 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -2104,6 +2104,27 @@ def update(self, instance, validated_data): return super().update(instance, validated_data) +class FieldReportGenerateTitleSerializer(serializers.ModelSerializer): + dtype = serializers.PrimaryKeyRelatedField(queryset=DisasterType.objects.all()) + event = serializers.PrimaryKeyRelatedField(queryset=Event.objects.all(), required=False) + title = serializers.CharField(required=True) + + class Meta: + model = FieldReport + fields = ( + "countries", + "dtype", + "title", + "event", + "start_date", + "is_covid_report", + ) + + +class FieldReportGeneratedTitleSerializer(serializers.Serializer): + title = serializers.CharField() + + class MainContactSerializer(ModelSerializer): class Meta: model = MainContact diff --git a/api/test_views.py b/api/test_views.py index 0c3d16ca2..4b9cff70c 100644 --- a/api/test_views.py +++ b/api/test_views.py @@ -1,4 +1,3 @@ -import json import uuid from django.contrib.auth.models import User diff --git a/api/utils.py b/api/utils.py index dad805161..291753f92 100644 --- a/api/utils.py +++ b/api/utils.py @@ -1,9 +1,16 @@ import base64 +import typing +from typing import Optional from django.core.exceptions import ValidationError +from django.db import models from django.http import JsonResponse +from django.utils import timezone from django.utils.translation import gettext +if typing.TYPE_CHECKING: + from api.models import Country, DisasterType, Event + class DebugPlaywright: """Basic helpers to debug PlayWright issues locally""" @@ -96,3 +103,38 @@ def write(self, value): def bad_request(message): return JsonResponse({"statusCode": 400, "error_message": message}, status=400) + + +def generate_field_report_title( + country: "Country", + dtype: "DisasterType", + event: "Event", + start_date: Optional[timezone.datetime], + title: str, + is_covid_report: bool = False, +): + """ + Generates the summary based on the country, dtype, event, start_date, title and is_covid_report + """ + from api.models import FieldReport + + current_date = timezone.now().strftime("%Y-%m-%d") + # NOTE: start_date is optional and setting it to current date if not provided + if start_date: + start_date = start_date.strftime("%m-%Y") + else: + start_date = timezone.now().strftime("%m-%Y") + current_fr_number = ( + FieldReport.objects.filter(event=event, countries__id=country.id).aggregate(max_fr_num=models.Max("fr_num"))["max_fr_num"] + or 0 + ) + fr_num = current_fr_number + 1 + + suffix = "" + if fr_num > 1 and event: + suffix = f"#{fr_num} ({current_date})" + if is_covid_report: + summary = f"{country.iso3}: COVID-19 {suffix}" + else: + summary = f"{country.iso3}: {dtype.name} - {start_date} - {title} {suffix}" + return summary diff --git a/deployments/snapshots/snap_tests.py b/deployments/snapshots/snap_tests.py index 5b6754c76..4f9d76aaf 100644 --- a/deployments/snapshots/snap_tests.py +++ b/deployments/snapshots/snap_tests.py @@ -91,16 +91,16 @@ snapshots[ "TestProjectAPI::test_project_csv_api 1" ] = """actual_expenditure,budget_amount,description,document,dtype,dtype_detail.id,dtype_detail.name,dtype_detail.summary,dtype_detail.translation_module_original_language,end_date,event,event_detail.dtype,event_detail.emergency_response_contact_email,event_detail.id,event_detail.name,event_detail.parent_event,event_detail.slug,event_detail.start_date,event_detail.translation_module_original_language,id,modified_at,modified_by,modified_by_detail,name,operation_type,operation_type_display,primary_sector,primary_sector_display,programme_type,programme_type_display,project_country,project_country_detail.id,project_country_detail.iso,project_country_detail.iso3,project_country_detail.name,project_country_detail.society_name,project_districts_detail.code,project_districts_detail.id,project_districts_detail.is_deprecated,project_districts_detail.is_enclave,project_districts_detail.name,reached_female,reached_male,reached_other,reached_total,regional_project,regional_project_detail.created_at,regional_project_detail.id,regional_project_detail.modified_at,regional_project_detail.name,regional_project_detail.translation_module_original_language,regional_project_detail.translation_module_skip_auto_translation,reporting_ns,reporting_ns_contact_email,reporting_ns_contact_name,reporting_ns_contact_role,reporting_ns_detail.id,reporting_ns_detail.iso,reporting_ns_detail.iso3,reporting_ns_detail.name,reporting_ns_detail.society_name,secondary_sectors,secondary_sectors_display,start_date,status,status_display,target_female,target_male,target_other,target_total,translation_module_original_language,translation_module_skip_auto_translation,user,visibility,visibility_display\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,1,2008-01-01T00:00:00.123456Z,,,project-hbvPgRZkVpHlJkvJBDoZzOllOQBzbVNmCLByaTnnrWTZYeKgZI,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,2,2008-01-01T00:00:00.123456Z,,,project-NzLhwwDNlRTZtNLfRiuhpthlxSjGyAMiKyBlFOISPlJkFsiluC,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,6,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,3,2008-01-01T00:00:00.123456Z,,,project-ATCFkfKbYWoscroIskXDKVXXFJGhKhrXIxIWcWUCInBgVPWptc,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,7,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,4,2008-01-01T00:00:00.123456Z,,,project-NOBkNiYnnZdKwIrMIkuTssKrGRgiWYAdrPiSipjTupWRzFjKOr,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,8,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,5,2008-01-01T00:00:00.123456Z,,,project-uLaXUfUDOQSweYIznBnFrusvJKiKFYvRWdcgOYDbhkCDaBmSiP,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,9,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,6,2008-01-01T00:00:00.123456Z,,,project-OtUSWoBPfTganEeiLoHRCaaSvhBSiEeoyfUZgguxtiyXWiPRje,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,10,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,7,2008-01-01T00:00:00.123456Z,,,project-giWhLUywBuYiprPfpJMMUMsXSbQtnHMGmVzsPdYYpFyhpFOMeH,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,11,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,8,2008-01-01T00:00:00.123456Z,,,project-bLeaqncdYzGsOTGXABSzfOIINjrftfGnZjIuzLOWPRPetSBUpd,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,12,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,9,2008-01-01T00:00:00.123456Z,,,project-iSakFwHHYUqkxiVXrUhXbvZBrHeqTKOeFDGxdFKkxkqXgKRUho,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,13,public,Public\r -0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,iqzlhqbiawyyplublqdivahhveecxxglgcgoncuyqhtdpbdezb,,en,10,2008-01-01T00:00:00.123456Z,,,project-cJZTVPAoupAUureKxhGRdloZHczeDsXtufJDaxmsKYtVNpDxLF,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"ctFhgpIiyD, lmiYIxHGrk","2, 1","False, False","False, False","district-DejWoRURzZJxfYzaqIhDxRVRqLyOxgRoEbNJuNoPeODStPAhic, district-bQzraKRXVdMVFsXZoMZwoOmNqRWUXQRiOgOPctYCcLxUifsuVA",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-iVgRVIfLBcbfnoGMbJmTPSIAoCLrZaWZkSBvrjnWvgfygwwMqZ,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,14,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,1,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,5,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,2,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,6,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,3,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,7,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,4,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,8,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,5,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,9,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,6,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,10,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,7,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,11,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,8,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,12,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,9,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,13,public,Public\r +0,100000,,,1,1,disaster-type-1,summary,en,2008-01-01,2,1,,2,rpo: disaster-type-1 - 01-2008 - event-1,1,event-slug,,en,10,2008-01-01T00:00:00.123456Z,,,project-1,1,Emergency Operation,1,sect-1,0,Bilateral,1,1,bV,rpo,country-1,society-name-1,"dct1, dct2","1, 2","True, False","False, True","district-1, district-2",0,0,0,0,1,2008-01-01T00:00:00.123456Z,1,2008-01-01T00:00:00.123456Z,regional-project-1,en,False,1,,,,1,bV,rpo,country-1,society-name-1,"1, 2","sec-tag-1, sec-tag-2",2008-01-01,1,Ongoing,0,0,0,0,en,False,14,public,Public\r """ snapshots["TestProjectAPI::test_project_delete 1"] = b"" diff --git a/deployments/tests.py b/deployments/tests.py index 5e4ef1af9..2c8609d76 100644 --- a/deployments/tests.py +++ b/deployments/tests.py @@ -191,22 +191,24 @@ def test_personnel_csv_api(self): self.assertMatchSnapshot(resp.content.decode("utf-8")) def test_project_csv_api(self): - _country = country.CountryFactory(name="country-1") - sct = SectorFactory(title="sect-1") - sct_1 = SectorTagFactory(title="sec-tag-1") - sct_2 = SectorTagFactory(title="sec-tag-2") - district1 = district.DistrictFactory(country=_country) - district2 = district.DistrictFactory(country=_country) + _country = country.CountryFactory(name="country-1", society_name="society-name-1") + sct = SectorFactory(title="sect-1", order=1) + sct_1 = SectorTagFactory(title="sec-tag-1", order=2) + sct_2 = SectorTagFactory(title="sec-tag-2", order=3) + district1 = district.DistrictFactory(country=_country, name="district-1", code="dct1") + district2 = district.DistrictFactory(country=_country, name="district-2", code="dct2") dtype = DisasterTypeFactory(name="disaster-type-1", summary="summary") regional_project = RegionalProjectFactory(name="regional-project-1") event = EventFactory( countries=[_country.id], + slug="event-slug", districts=[district1.id, district2.id], dtype=dtype, title="event-1", ) ProjectFactory.create_batch( 10, + name="project-1", project_districts=[district1, district2], budget_amount=100000, primary_sector=sct, From 9d2e9e070d7ded6d6632f3272587f732c3645ed9 Mon Sep 17 00:00:00 2001 From: sudip-khanal <101724348+sudip-khanal@users.noreply.github.com> Date: Wed, 15 Jan 2025 16:13:15 +0545 Subject: [PATCH 6/6] Add logic to migrate fieldreport number (#2349) * Add logic to migrate fieldreport number * Check report is null or not * Remove unnecessary print statement * Add logger and Update query * Remove print statement * Add bulk update * Add bulk update method * Changes in bulk update method * Fix logging and query * Fixed ci test fails * Exclude reports contain fr_num * Update queryset on fieldreport --------- Co-authored-by: Sushil Tiwari --- .../commands/migrate_field_report_number.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 api/management/commands/migrate_field_report_number.py diff --git a/api/management/commands/migrate_field_report_number.py b/api/management/commands/migrate_field_report_number.py new file mode 100644 index 000000000..9576f227f --- /dev/null +++ b/api/management/commands/migrate_field_report_number.py @@ -0,0 +1,79 @@ +import re + +from django.core.management.base import BaseCommand +from django.db.models.expressions import Exists, OuterRef + +from api.models import FieldReport +from main.managers import BulkUpdateManager + + +class Command(BaseCommand): + help = "Migrate legacy FieldReport data to populate fr_num" + + def handle(self, *args, **kwargs): + + suffix_pattern = re.compile(r"#\s*(\d+)") + + reports = ( + FieldReport.objects.filter(event__isnull=False, countries__isnull=False, summary__icontains="#") + .annotate( + has_fr_num=Exists( + FieldReport.objects.filter(event=OuterRef("event"), countries=OuterRef("countries"), fr_num__isnull=False) + ) + ) + .exclude(has_fr_num=True) + ) + + report_count = reports.count() + self.stdout.write(self.style.NOTICE(f"Found {report_count} FieldReports to process")) + + if report_count == 0: + self.stdout.write(self.style.WARNING("No FieldReports found to process")) + return + + event_country_data = {} + + for report in reports.iterator(): + country = report.countries.first() + + if country is None: + self.stdout.write(self.style.ERROR(f"FieldReport ID: ({report.id}) has no associated country.")) + continue + + summary_match = suffix_pattern.search(report.summary) + derived_fr_num = int(summary_match.group(1)) if summary_match else 0 + + max_fr_num = max(derived_fr_num, report.fr_num or 0) + key = (report.event.id, country.id) + + group_data = event_country_data.get( + key, + { + "highest_fr_num": 0, + "report_highest_fr": None, + }, + ) + + if max_fr_num > group_data["highest_fr_num"]: + group_data["highest_fr_num"] = max_fr_num + group_data["report_highest_fr"] = report + + event_country_data[key] = group_data + + bulk_mgr = BulkUpdateManager(update_fields=["fr_num"]) + + for data in event_country_data.values(): + highest_report = data["report_highest_fr"] + highest_fr_num = data["highest_fr_num"] + if highest_report: + self.stdout.write( + self.style.NOTICE(f"Preparing to update FieldReport ID:({highest_report.id}) with fr_num:({highest_fr_num}).") + ) + bulk_mgr.add( + FieldReport( + id=highest_report.id, + fr_num=highest_fr_num, + ) + ) + bulk_mgr.done() + self.stdout.write(self.style.SUCCESS("FieldReport migration completed successfully."))