Skip to content

Commit 4a91f3b

Browse files
authored
Merge pull request #2551 from IFRCGo/feat/update-dref-status
- Update dref status - update approve api and logics - Refactor is_published to approve status
2 parents 8d99e16 + 9d7c227 commit 4a91f3b

10 files changed

+346
-160
lines changed

api/test_views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ def test_guest_user_permission(self):
8989
go_post_apis = [
9090
"/api/v2/dref/",
9191
"/api/v2/dref-final-report/",
92-
f"/api/v2/dref-final-report/{id}/publish/",
92+
f"/api/v2/dref-final-report/{id}/approve/",
9393
"/api/v2/dref-op-update/",
94-
f"/api/v2/dref-op-update/{id}/publish/",
94+
f"/api/v2/dref-op-update/{id}/approve/",
9595
"/api/v2/dref-share/",
96-
f"/api/v2/dref/{id}/publish/",
96+
f"/api/v2/dref/{id}/approve/",
9797
"/api/v2/flash-update/",
9898
"/api/v2/flash-update-file/multiple/",
9999
"/api/v2/local-units/",

dref/admin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def get_queryset(self, request):
230230

231231
# NOTE: If the Dref Final report is unpublished, set Dref related to it as active
232232
def save_model(self, request, obj, form, change):
233-
if not obj.is_published and obj.dref:
233+
if obj.status != Dref.Status.APPROVED and obj.dref:
234234
obj.dref.is_active = True
235235
obj.dref.save(update_fields=["is_active"])
236236
super().save_model(request, obj, form, change)

dref/filter_set.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ class DrefFilter(filters.FilterSet):
1515

1616
class Meta:
1717
model = Dref
18-
fields = ["is_published"]
18+
fields = ["status"]
1919

2020

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

2424
class Meta:
2525
model = DrefOperationalUpdate
26-
fields = ["is_published"]
26+
fields = ["status"]
2727

2828

2929
class BaseDrefFilterSet(filters.FilterSet):
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Generated by Django 4.2.19 on 2025-09-16 09:09
2+
3+
from django.db import migrations, models
4+
5+
6+
def update_status(apps, schema_editor):
7+
"""
8+
Update old status to new workflow:
9+
- Not published or IN_PROGRESS → DRAFT
10+
- Published or COMPLETED → APPROVED
11+
Applies to Dref, DrefOperationalUpdate, and DrefFinalReport.
12+
"""
13+
models = [
14+
"Dref",
15+
"DrefOperationalUpdate",
16+
"DrefFinalReport",
17+
]
18+
for model_name in models:
19+
Model = apps.get_model("dref", model_name)
20+
Model.objects.filter(is_published=True).update(status=4) # Published → APPROVED
21+
Model.objects.filter(is_published=False).update(status=1) # Not published → DRAFT
22+
23+
24+
class Migration(migrations.Migration):
25+
26+
dependencies = [
27+
("dref", "0083_dreffinalreport_total_operation_timeframe_imminent"),
28+
]
29+
30+
operations = [
31+
migrations.AddField(
32+
model_name="dref",
33+
name="original_language",
34+
field=models.CharField(
35+
blank=True,
36+
help_text="The language in which this record was first created.",
37+
null=True,
38+
verbose_name="Original language",
39+
),
40+
),
41+
migrations.AddField(
42+
model_name="dreffinalreport",
43+
name="original_language",
44+
field=models.CharField(
45+
blank=True,
46+
help_text="The language in which this record was first created.",
47+
null=True,
48+
verbose_name="Original language",
49+
),
50+
),
51+
migrations.AddField(
52+
model_name="drefoperationalupdate",
53+
name="original_language",
54+
field=models.CharField(
55+
blank=True,
56+
help_text="The language in which this record was first created.",
57+
null=True,
58+
verbose_name="Original language",
59+
),
60+
),
61+
migrations.AlterField(
62+
model_name="dref",
63+
name="status",
64+
field=models.IntegerField(
65+
choices=[(1, "Draft"), (2, "Finalizing"), (3, "Finalized"), (4, "Approved")], default=1, verbose_name="status"
66+
),
67+
),
68+
migrations.AlterField(
69+
model_name="dreffinalreport",
70+
name="status",
71+
field=models.IntegerField(
72+
choices=[(1, "Draft"), (2, "Finalizing"), (3, "Finalized"), (4, "Approved")], default=1, verbose_name="status"
73+
),
74+
),
75+
migrations.AlterField(
76+
model_name="drefoperationalupdate",
77+
name="status",
78+
field=models.IntegerField(
79+
choices=[(1, "Draft"), (2, "Finalizing"), (3, "Finalized"), (4, "Approved")], default=1, verbose_name="status"
80+
),
81+
),
82+
migrations.RunPython(update_status, reverse_code=migrations.RunPython.noop),
83+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 4.2.19 on 2025-09-16 09:13
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("dref", "0084_dref_original_language_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name="dref",
15+
name="is_published",
16+
),
17+
migrations.RemoveField(
18+
model_name="dreffinalreport",
19+
name="is_published",
20+
),
21+
migrations.RemoveField(
22+
model_name="drefoperationalupdate",
23+
name="is_published",
24+
),
25+
]

dref/models.py

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,14 @@ class DisasterCategory(models.IntegerChoices):
264264
RED = 2, _("Red")
265265

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

270276
created_at = models.DateTimeField(verbose_name=_("created at"), auto_now_add=True)
271277
modified_at = models.DateTimeField(verbose_name=_("modified at"), default=timezone.now, null=True)
@@ -329,7 +335,13 @@ class Status(models.IntegerChoices):
329335
verbose_name=_("If available please upload additional support documentation for targeting strategy"),
330336
related_name="dref_targeting_strategy_support_file",
331337
)
332-
status = models.IntegerField(choices=Status.choices, verbose_name=_("status"), null=True, blank=True)
338+
status = models.IntegerField(choices=Status.choices, verbose_name=_("status"), default=Status.DRAFT)
339+
original_language = models.CharField(
340+
blank=True,
341+
null=True,
342+
verbose_name=_("Original language"),
343+
help_text="The language in which this record was first created.",
344+
) # NOTE: This field is set at creation with the active language.
333345
num_assisted = models.IntegerField(verbose_name=_("number of assisted"), blank=True, null=True)
334346
num_affected = models.IntegerField(verbose_name=_("number of affected"), blank=True, null=True)
335347
estimated_number_of_affected_male = models.IntegerField(
@@ -645,10 +657,6 @@ class Status(models.IntegerChoices):
645657
verbose_name=_("cover image"),
646658
related_name="cover_image_dref",
647659
)
648-
is_published = models.BooleanField(
649-
default=False,
650-
verbose_name=_("Is published"),
651-
)
652660
is_final_report_created = models.BooleanField(
653661
default=False,
654662
verbose_name=_("Is final report created"),
@@ -748,8 +756,6 @@ def save(self, *args, **kwargs):
748756
self.budget_file_preview.save(filename, thumb_data, save=False)
749757
else:
750758
raise ValidationError({"budget_file": "Sorry cannot generate preview for empty pdf"})
751-
752-
self.status = Dref.Status.COMPLETED if self.is_published else Dref.Status.IN_PROGRESS
753759
self.__budget_file_id = self.budget_file_id
754760
super().save(*args, **kwargs)
755761

@@ -859,7 +865,13 @@ class DrefOperationalUpdate(models.Model):
859865
disaster_category = models.IntegerField(
860866
choices=Dref.DisasterCategory.choices, verbose_name=_("disaster category"), null=True, blank=True
861867
)
862-
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), null=True, blank=True)
868+
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), default=Dref.Status.DRAFT)
869+
original_language = models.CharField(
870+
blank=True,
871+
null=True,
872+
verbose_name=_("Original language"),
873+
help_text="The language in which this record was first created.",
874+
) # NOTE: This field is set at creation with the active language.
863875
number_of_people_targeted = models.IntegerField(verbose_name=_("Number of people targeted"), blank=True, null=True)
864876
number_of_people_affected = models.IntegerField(verbose_name=_("number of people affected"), blank=True, null=True)
865877
estimated_number_of_affected_male = models.IntegerField(
@@ -1094,10 +1106,6 @@ class DrefOperationalUpdate(models.Model):
10941106
null=True,
10951107
)
10961108
planned_interventions = models.ManyToManyField(PlannedIntervention, verbose_name=_("planned intervention"), blank=True)
1097-
is_published = models.BooleanField(
1098-
default=False,
1099-
verbose_name=_("Is published"),
1100-
)
11011109
country = models.ForeignKey(
11021110
Country,
11031111
verbose_name=_("country"),
@@ -1232,7 +1240,6 @@ def save(self, *args, **kwargs):
12321240
raise ValidationError({"budget_file": "Sorry cannot generate preview for empty pdf"})
12331241

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

12381245
@staticmethod
@@ -1297,7 +1304,13 @@ class DrefFinalReport(models.Model):
12971304
disaster_category = models.IntegerField(
12981305
choices=Dref.DisasterCategory.choices, verbose_name=_("disaster category"), null=True, blank=True
12991306
)
1300-
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), null=True, blank=True)
1307+
status = models.IntegerField(choices=Dref.Status.choices, verbose_name=_("status"), default=Dref.Status.DRAFT)
1308+
original_language = models.CharField(
1309+
blank=True,
1310+
null=True,
1311+
verbose_name=_("Original language"),
1312+
help_text="The language in which this record was first created.",
1313+
) # NOTE: This field is set at creation with the active language.
13011314
number_of_people_targeted = models.IntegerField(verbose_name=_("Number of people targeted"), blank=True, null=True)
13021315
number_of_people_affected = models.IntegerField(verbose_name=_("number of people affected"), blank=True, null=True)
13031316
estimated_number_of_affected_male = models.IntegerField(
@@ -1481,7 +1494,6 @@ class DrefFinalReport(models.Model):
14811494
verbose_name=_("Additional National Societies Actions"), null=True, blank=True
14821495
)
14831496
planned_interventions = models.ManyToManyField(PlannedIntervention, verbose_name=_("planned intervention"), blank=True)
1484-
is_published = models.BooleanField(verbose_name=_("Is Published"), default=False)
14851497
country = models.ForeignKey(
14861498
Country,
14871499
verbose_name=_("country"),
@@ -1651,12 +1663,11 @@ def save(self, *args, **kwargs):
16511663
else:
16521664
raise ValidationError({"financial_report": "Sorry cannot generate preview for empty pdf"})
16531665

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

16581669
@staticmethod
1659-
def get_for(user, is_published=False):
1670+
def get_for(user, status=None):
16601671
from dref.utils import get_dref_users
16611672

16621673
# get the user in dref
@@ -1675,6 +1686,6 @@ def get_for(user, is_published=False):
16751686
final_report_created_by = DrefFinalReport.objects.filter(created_by=user).distinct()
16761687
union_query = final_report_users.union(final_report_created_by)
16771688
queryset = DrefFinalReport.objects.filter(id__in=union_query.values("id")).distinct()
1678-
if is_published:
1679-
return queryset.filter(is_published=True)
1689+
if status == Dref.Status.APPROVED:
1690+
return queryset.filter(status=Dref.Status.APPROVED)
16801691
return queryset

dref/permissions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.contrib.auth.models import Permission
22
from rest_framework import permissions
33

4-
from dref.models import DrefFinalReport, DrefOperationalUpdate
4+
from dref.models import Dref, DrefFinalReport, DrefOperationalUpdate
55
from dref.utils import get_dref_users
66

77

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

0 commit comments

Comments
 (0)