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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions api/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ def test_guest_user_permission(self):
go_post_apis = [
"/api/v2/dref/",
"/api/v2/dref-final-report/",
f"/api/v2/dref-final-report/{id}/publish/",
f"/api/v2/dref-final-report/{id}/approve/",
"/api/v2/dref-op-update/",
f"/api/v2/dref-op-update/{id}/publish/",
f"/api/v2/dref-op-update/{id}/approve/",
"/api/v2/dref-share/",
f"/api/v2/dref/{id}/publish/",
f"/api/v2/dref/{id}/approve/",
"/api/v2/flash-update/",
"/api/v2/flash-update-file/multiple/",
"/api/v2/local-units/",
Expand Down
2 changes: 1 addition & 1 deletion dref/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def get_queryset(self, request):

# NOTE: If the Dref Final report is unpublished, set Dref related to it as active
def save_model(self, request, obj, form, change):
if not obj.is_published and obj.dref:
if obj.status != Dref.Status.APPROVED and obj.dref:
obj.dref.is_active = True
obj.dref.save(update_fields=["is_active"])
super().save_model(request, obj, form, change)
Expand Down
4 changes: 2 additions & 2 deletions dref/filter_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ class DrefFilter(filters.FilterSet):

class Meta:
model = Dref
fields = ["is_published"]
fields = ["status"]


class DrefOperationalUpdateFilter(filters.FilterSet):
dref = filters.ModelMultipleChoiceFilter(field_name="dref", queryset=Dref.objects.all().distinct())

class Meta:
model = DrefOperationalUpdate
fields = ["is_published"]
fields = ["status"]


class BaseDrefFilterSet(filters.FilterSet):
Expand Down
83 changes: 83 additions & 0 deletions dref/migrations/0084_dref_original_language_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Generated by Django 4.2.19 on 2025-09-16 09:09

from django.db import migrations, models


def update_status(apps, schema_editor):
"""
Update old status to new workflow:
- Not published or IN_PROGRESS → DRAFT
- Published or COMPLETED → APPROVED
Applies to Dref, DrefOperationalUpdate, and DrefFinalReport.
"""
models = [
"Dref",
"DrefOperationalUpdate",
"DrefFinalReport",
]
for model_name in models:
Model = apps.get_model("dref", model_name)
Model.objects.filter(is_published=True).update(status=4) # Published → APPROVED
Model.objects.filter(is_published=False).update(status=1) # Not published → DRAFT


class Migration(migrations.Migration):

dependencies = [
("dref", "0083_dreffinalreport_total_operation_timeframe_imminent"),
]

operations = [
migrations.AddField(
model_name="dref",
name="original_language",
field=models.CharField(
blank=True,
help_text="The language in which this record was first created.",
null=True,
verbose_name="Original language",
),
),
migrations.AddField(
model_name="dreffinalreport",
name="original_language",
field=models.CharField(
blank=True,
help_text="The language in which this record was first created.",
null=True,
verbose_name="Original language",
),
),
migrations.AddField(
model_name="drefoperationalupdate",
name="original_language",
field=models.CharField(
blank=True,
help_text="The language in which this record was first created.",
null=True,
verbose_name="Original language",
),
),
migrations.AlterField(
model_name="dref",
name="status",
field=models.IntegerField(
choices=[(1, "Draft"), (2, "Finalizing"), (3, "Finalized"), (4, "Approved")], default=1, verbose_name="status"
),
),
migrations.AlterField(
model_name="dreffinalreport",
name="status",
field=models.IntegerField(
choices=[(1, "Draft"), (2, "Finalizing"), (3, "Finalized"), (4, "Approved")], default=1, verbose_name="status"
),
),
migrations.AlterField(
model_name="drefoperationalupdate",
name="status",
field=models.IntegerField(
choices=[(1, "Draft"), (2, "Finalizing"), (3, "Finalized"), (4, "Approved")], default=1, verbose_name="status"
),
),
migrations.RunPython(update_status, reverse_code=migrations.RunPython.noop),
]
25 changes: 25 additions & 0 deletions dref/migrations/0085_remove_dref_is_published_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.19 on 2025-09-16 09:13

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("dref", "0084_dref_original_language_and_more"),
]

operations = [
migrations.RemoveField(
model_name="dref",
name="is_published",
),
migrations.RemoveField(
model_name="dreffinalreport",
name="is_published",
),
migrations.RemoveField(
model_name="drefoperationalupdate",
name="is_published",
),
]
53 changes: 32 additions & 21 deletions dref/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,14 @@ class DisasterCategory(models.IntegerChoices):
RED = 2, _("Red")

class Status(models.IntegerChoices):
IN_PROGRESS = 0, _("In Progress")
COMPLETED = 1, _("Completed")
DRAFT = 1, _("Draft")
"""Draft: Initial stage content is being created and is not ready for review."""
FINALIZING = 2, _("Finalizing")
"""Finalizing: Content is in the translation process from the original language into English."""
FINALIZED = 3, _("Finalized")
"""Finalized: Translation is completed, content is ready for review, and updates to the original language are locked."""
APPROVED = 4, _("Approved")
"""Approved: The content has been reviewed, accepted, and is ready for use."""

created_at = models.DateTimeField(verbose_name=_("created at"), auto_now_add=True)
modified_at = models.DateTimeField(verbose_name=_("modified at"), default=timezone.now, null=True)
Expand Down Expand Up @@ -329,7 +335,13 @@ class Status(models.IntegerChoices):
verbose_name=_("If available please upload additional support documentation for targeting strategy"),
related_name="dref_targeting_strategy_support_file",
)
status = models.IntegerField(choices=Status.choices, verbose_name=_("status"), null=True, blank=True)
status = models.IntegerField(choices=Status.choices, verbose_name=_("status"), default=Status.DRAFT)
original_language = models.CharField(
blank=True,
null=True,
verbose_name=_("Original language"),
help_text="The language in which this record was first created.",
) # NOTE: This field is set at creation with the active language.
num_assisted = models.IntegerField(verbose_name=_("number of assisted"), blank=True, null=True)
num_affected = models.IntegerField(verbose_name=_("number of affected"), blank=True, null=True)
estimated_number_of_affected_male = models.IntegerField(
Expand Down Expand Up @@ -645,10 +657,6 @@ class Status(models.IntegerChoices):
verbose_name=_("cover image"),
related_name="cover_image_dref",
)
is_published = models.BooleanField(
default=False,
verbose_name=_("Is published"),
)
is_final_report_created = models.BooleanField(
default=False,
verbose_name=_("Is final report created"),
Expand Down Expand Up @@ -748,8 +756,6 @@ def save(self, *args, **kwargs):
self.budget_file_preview.save(filename, thumb_data, save=False)
else:
raise ValidationError({"budget_file": "Sorry cannot generate preview for empty pdf"})

self.status = Dref.Status.COMPLETED if self.is_published else Dref.Status.IN_PROGRESS
self.__budget_file_id = self.budget_file_id
super().save(*args, **kwargs)

Expand Down Expand Up @@ -859,7 +865,13 @@ class DrefOperationalUpdate(models.Model):
disaster_category = models.IntegerField(
choices=Dref.DisasterCategory.choices, verbose_name=_("disaster category"), null=True, blank=True
)
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), null=True, blank=True)
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), default=Dref.Status.DRAFT)
original_language = models.CharField(
blank=True,
null=True,
verbose_name=_("Original language"),
help_text="The language in which this record was first created.",
) # NOTE: This field is set at creation with the active language.
number_of_people_targeted = models.IntegerField(verbose_name=_("Number of people targeted"), blank=True, null=True)
number_of_people_affected = models.IntegerField(verbose_name=_("number of people affected"), blank=True, null=True)
estimated_number_of_affected_male = models.IntegerField(
Expand Down Expand Up @@ -1094,10 +1106,6 @@ class DrefOperationalUpdate(models.Model):
null=True,
)
planned_interventions = models.ManyToManyField(PlannedIntervention, verbose_name=_("planned intervention"), blank=True)
is_published = models.BooleanField(
default=False,
verbose_name=_("Is published"),
)
country = models.ForeignKey(
Country,
verbose_name=_("country"),
Expand Down Expand Up @@ -1232,7 +1240,6 @@ def save(self, *args, **kwargs):
raise ValidationError({"budget_file": "Sorry cannot generate preview for empty pdf"})

self.__budget_file_id = self.budget_file_id
self.status = Dref.Status.COMPLETED if self.is_published else Dref.Status.IN_PROGRESS
super().save(*args, **kwargs)

@staticmethod
Expand Down Expand Up @@ -1297,7 +1304,13 @@ class DrefFinalReport(models.Model):
disaster_category = models.IntegerField(
choices=Dref.DisasterCategory.choices, verbose_name=_("disaster category"), null=True, blank=True
)
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), null=True, blank=True)
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), default=Dref.Status.DRAFT)
original_language = models.CharField(
blank=True,
null=True,
verbose_name=_("Original language"),
help_text="The language in which this record was first created.",
) # NOTE: This field is set at creation with the active language.
number_of_people_targeted = models.IntegerField(verbose_name=_("Number of people targeted"), blank=True, null=True)
number_of_people_affected = models.IntegerField(verbose_name=_("number of people affected"), blank=True, null=True)
estimated_number_of_affected_male = models.IntegerField(
Expand Down Expand Up @@ -1481,7 +1494,6 @@ class DrefFinalReport(models.Model):
verbose_name=_("Additional National Societies Actions"), null=True, blank=True
)
planned_interventions = models.ManyToManyField(PlannedIntervention, verbose_name=_("planned intervention"), blank=True)
is_published = models.BooleanField(verbose_name=_("Is Published"), default=False)
country = models.ForeignKey(
Country,
verbose_name=_("country"),
Expand Down Expand Up @@ -1651,12 +1663,11 @@ def save(self, *args, **kwargs):
else:
raise ValidationError({"financial_report": "Sorry cannot generate preview for empty pdf"})

self.status = Dref.Status.COMPLETED if self.is_published else Dref.Status.IN_PROGRESS
self.__financial_report_id = self.financial_report_id
super().save(*args, **kwargs)

@staticmethod
def get_for(user, is_published=False):
def get_for(user, status=None):
from dref.utils import get_dref_users

# get the user in dref
Expand All @@ -1675,6 +1686,6 @@ def get_for(user, is_published=False):
final_report_created_by = DrefFinalReport.objects.filter(created_by=user).distinct()
union_query = final_report_users.union(final_report_created_by)
queryset = DrefFinalReport.objects.filter(id__in=union_query.values("id")).distinct()
if is_published:
return queryset.filter(is_published=True)
if status == Dref.Status.APPROVED:
return queryset.filter(status=Dref.Status.APPROVED)
return queryset
4 changes: 2 additions & 2 deletions dref/permissions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib.auth.models import Permission
from rest_framework import permissions

from dref.models import DrefFinalReport, DrefOperationalUpdate
from dref.models import Dref, DrefFinalReport, DrefOperationalUpdate
from dref.utils import get_dref_users


Expand Down Expand Up @@ -42,6 +42,6 @@ def has_object_permission(self, request, view, obj):
region = obj.country.region.name
codename = f"dref_region_admin_{region}"
user = request.user
if Permission.objects.filter(user=user, codename=codename).exists() and not obj.is_published:
if Permission.objects.filter(user=user, codename=codename).exists() and obj.status != Dref.Status.APPROVED:
return True
return False
Loading
Loading