Skip to content
Merged
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
2 changes: 1 addition & 1 deletion assets
Submodule assets updated 1 files
+14 −0 openapi-schema.yaml
31 changes: 25 additions & 6 deletions dref/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from django.contrib import admin
from django.contrib import admin, messages
from reversion_compare.admin import CompareVersionAdmin

from lang.admin import TranslationAdmin, TranslationInlineModelAdmin
Expand All @@ -16,6 +16,7 @@
RiskSecurity,
SourceInformation,
)
from .tasks import generate_dref_summary


class ReadOnlyMixin:
Expand Down Expand Up @@ -131,13 +132,13 @@ class DrefSummaryInline(admin.StackedInline, TranslationInlineModelAdmin):
extra = 0
readonly_fields = (
"status",
"prompt_hash",
"source_hash",
"created_at",
"updated_at",
)
fields = (
"status",
"prompt_hash",
"source_hash",
"situational_overview",
"operational_strategy",
"people_centered_approach",
Expand Down Expand Up @@ -329,15 +330,16 @@ class ProposedActionAdmin(ReadOnlyMixin, admin.ModelAdmin):

@admin.register(DrefSummary)
class DrefSummaryAdmin(TranslationAdmin, admin.ModelAdmin):
list_display = ("dref", "status", "created_at", "updated_at")
list_display = ("dref", "status", "source_model_name", "source_id", "created_at", "updated_at")
list_filter = ("status",)
search_fields = ("dref__title", "dref__appeal_code")
readonly_fields = ("prompt_hash", "created_at", "updated_at")
readonly_fields = ("source_hash", "created_at", "updated_at")
autocomplete_fields = ("dref",)
actions = ["regenerate_summary"]
fields = (
"dref",
"status",
"prompt_hash",
"source_hash",
"situational_overview",
"operational_strategy",
"people_centered_approach",
Expand All @@ -346,3 +348,20 @@ class DrefSummaryAdmin(TranslationAdmin, admin.ModelAdmin):
"created_at",
"updated_at",
)

@admin.action(description="Regenerate summary for selected DREFs")
def regenerate_summary(self, request, queryset):
"""Re-trigger summary generation, replaying the source the summary was last built from."""
for summary in queryset:
generate_dref_summary.delay(
# Fall back to the Dref itself for rows generated before the
# source was tracked.
source_model_name=summary.source_model_name or DrefSummary.SourceModel.DREF,
source_id=summary.source_id or summary.dref_id,
overwrite=True,
)
self.message_user(
request,
f"Queued summary regeneration for {queryset.count()} DREF(s).",
messages.SUCCESS,
)
4 changes: 3 additions & 1 deletion dref/factories/dref.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ class Meta:
model = DrefSummary

dref = factory.SubFactory(DrefFactory)
prompt_hash = factory.Sequence(lambda n: f"{n:064d}")
source_hash = factory.Sequence(lambda n: f"{n:064d}")
source_model_name = DrefSummary.SourceModel.DREF
source_id = factory.SelfAttribute("dref.id")
status = DrefSummary.SummaryStatus.SUCCESS
situational_overview = fuzzy.FuzzyText(length=100)
operational_strategy = fuzzy.FuzzyText(length=100)
Expand Down
6 changes: 4 additions & 2 deletions dref/migrations/0090_drefsummary.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.2.14 on 2026-06-26 02:06
# Generated by Django 5.2.14 on 2026-07-03 00:58

import django.db.models.deletion
from django.db import migrations, models
Expand All @@ -17,7 +17,9 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('prompt_hash', models.CharField(max_length=64, unique=True)),
('source_model_name', models.IntegerField(choices=[(100, 'Dref'), (200, 'Dref Operational Update'), (300, 'Dref Final Report')], verbose_name='source model name')),
('source_id', models.PositiveBigIntegerField(verbose_name='source id')),
('source_hash', models.CharField(max_length=64, unique=True)),
('situational_overview', models.TextField(blank=True, null=True)),
('situational_overview_en', models.TextField(blank=True, null=True)),
('situational_overview_es', models.TextField(blank=True, null=True)),
Expand Down
22 changes: 21 additions & 1 deletion dref/models.py
Comment thread
susilnem marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,10 @@ class DrefOperationalUpdate(models.Model):
source_information = models.ManyToManyField(SourceInformation, blank=True, verbose_name=_("Source Information"))
__budget_file_id = None

# TYPING
id: int
budget_file_id: int | None

class Meta:
verbose_name = _("Dref Operational Update")
verbose_name_plural = _("Dref Operational Updates")
Expand Down Expand Up @@ -1710,6 +1714,11 @@ class SummaryStatus(models.IntegerChoices):
SUCCESS = 300, _("Success")
FAILED = 400, _("Failed")

class SourceModel(models.IntegerChoices):
DREF = 100, _("Dref")
DREF_OPERATIONAL_UPDATE = 200, _("Dref Operational Update")
DREF_FINAL_REPORT = 300, _("Dref Final Report")

dref = models.OneToOneField(
Dref,
on_delete=models.CASCADE,
Expand All @@ -1719,7 +1728,18 @@ class SummaryStatus(models.IntegerChoices):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

prompt_hash = models.CharField(
# The source document the summary was last generated from. Stored so a
# retrigger (e.g. from the admin) can replay the same source instead of
# re-resolving the latest approved document.
source_model_name = models.IntegerField(
verbose_name=_("source model name"),
choices=SourceModel.choices,
)
source_id = models.PositiveBigIntegerField(
Comment thread
susilnem marked this conversation as resolved.
verbose_name=_("source id"),
)

source_hash = models.CharField(
max_length=64,
unique=True,
)
Expand Down
5 changes: 5 additions & 0 deletions dref/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2429,16 +2429,21 @@ def get_dref_contacts(self, obj):


class DrefSummarySerializer(ModelSerializer):
status_display = serializers.CharField(source="get_status_display", read_only=True)

class Meta:
model = DrefSummary
fields = (
"id",
"status",
"status_display",
"situational_overview",
"operational_strategy",
"people_centered_approach",
"challenges_identified",
"lessons_learned",
"created_at",
"updated_at",
)


Expand Down
Loading
Loading