From 7816aed36e4b8bc8f63a45a1daa013b0a0d51f53 Mon Sep 17 00:00:00 2001 From: Bishwas Praveen Date: Tue, 14 May 2024 15:19:08 -0500 Subject: [PATCH 1/3] added a new model called workflowstatushistory to track status changes --- sde_collections/models/collection.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sde_collections/models/collection.py b/sde_collections/models/collection.py index 7ce9da1b..5cc40912 100644 --- a/sde_collections/models/collection.py +++ b/sde_collections/models/collection.py @@ -467,7 +467,13 @@ def save(self, *args, **kwargs): details = STATUS_CHANGE_NOTIFICATIONS[transition] message = format_slack_message(self.name, details, self.id) send_slack_message(message) - + if "workflow_status" in self.tracker.changed(): + WorkflowStatusHistory.objects.create( + collection=self, + old_status=self.tracker.previous("workflow_status"), + new_status=self.workflow_status, + changed_by=self.curated_by, + ) # Call the parent class's save method super().save(*args, **kwargs) @@ -511,3 +517,18 @@ def create_configs_on_status_change(sender, instance, created, **kwargs): instance.create_indexer_config(overwrite=False) elif instance.workflow_status == WorkflowStatusChoices.READY_FOR_PUBLIC_PROD: instance.add_to_public_query() + + +class WorkflowStatusHistory(models.Model): + collection = models.ForeignKey("Collection", on_delete=models.CASCADE, related_name="workflow_status_history") + old_status = models.IntegerField(choices=WorkflowStatusChoices.choices) + new_status = models.IntegerField(choices=WorkflowStatusChoices.choices) + changed_by = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, null=True, blank=True) + changed_at = models.DateTimeField(auto_now_add=True) + + class Meta: + verbose_name = "Workflow Status History" + verbose_name_plural = "Workflow Status Histories" + + def __str__(self): + return f"{self.collection.name} - {self.get_old_status_display()} to {self.get_new_status_display()}" From 559d95f69b18e2c642d7de20b5afc4a88361cce9 Mon Sep 17 00:00:00 2001 From: Bishwas Praveen Date: Tue, 14 May 2024 15:19:43 -0500 Subject: [PATCH 2/3] added the migrations file for the new model --- .../migrations/0046_workflowstatushistory.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 sde_collections/migrations/0046_workflowstatushistory.py diff --git a/sde_collections/migrations/0046_workflowstatushistory.py b/sde_collections/migrations/0046_workflowstatushistory.py new file mode 100644 index 00000000..95f75a62 --- /dev/null +++ b/sde_collections/migrations/0046_workflowstatushistory.py @@ -0,0 +1,89 @@ +# Generated by Django 4.2.9 on 2024-05-14 20:00 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("sde_collections", "0045_alter_collection_workflow_status"), + ] + + operations = [ + migrations.CreateModel( + name="WorkflowStatusHistory", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ( + "old_status", + models.IntegerField( + choices=[ + (1, "Research in Progress"), + (2, "Ready for Engineering"), + (3, "Engineering in Progress"), + (4, "Ready for Curation"), + (5, "Curation in Progress"), + (6, "Curated"), + (7, "Quality Fixed"), + (8, "Secret Deployment Started"), + (9, "Secret Deployment Failed"), + (10, "Ready for LRM Quality Check"), + (11, "Ready for Quality Check"), + (12, "Quality Check Failed"), + (13, "Ready for Public Production"), + (14, "Perfect and on Production"), + (15, "Low Priority Problems on Production"), + (16, "High Priority Problems on Production, only for old sources"), + (17, "Code Merge Pending"), + ] + ), + ), + ( + "new_status", + models.IntegerField( + choices=[ + (1, "Research in Progress"), + (2, "Ready for Engineering"), + (3, "Engineering in Progress"), + (4, "Ready for Curation"), + (5, "Curation in Progress"), + (6, "Curated"), + (7, "Quality Fixed"), + (8, "Secret Deployment Started"), + (9, "Secret Deployment Failed"), + (10, "Ready for LRM Quality Check"), + (11, "Ready for Quality Check"), + (12, "Quality Check Failed"), + (13, "Ready for Public Production"), + (14, "Perfect and on Production"), + (15, "Low Priority Problems on Production"), + (16, "High Priority Problems on Production, only for old sources"), + (17, "Code Merge Pending"), + ] + ), + ), + ("changed_at", models.DateTimeField(auto_now_add=True)), + ( + "changed_by", + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL + ), + ), + ( + "collection", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="workflow_status_history", + to="sde_collections.collection", + ), + ), + ], + options={ + "verbose_name": "Workflow Status History", + "verbose_name_plural": "Workflow Status Histories", + }, + ), + ] From 0bf293aefd9836970f1db2ec357c5422de56ce2b Mon Sep 17 00:00:00 2001 From: Bishwas Praveen Date: Tue, 14 May 2024 15:20:52 -0500 Subject: [PATCH 3/3] made the model visible on the admin console --- sde_collections/admin.py | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/sde_collections/admin.py b/sde_collections/admin.py index a175c3c9..b05c24f2 100644 --- a/sde_collections/admin.py +++ b/sde_collections/admin.py @@ -4,7 +4,7 @@ from django.http import HttpResponse from .models.candidate_url import CandidateURL -from .models.collection import Collection +from .models.collection import Collection, WorkflowStatusHistory from .models.pattern import IncludePattern, TitlePattern from .tasks import import_candidate_urls_from_api @@ -22,10 +22,7 @@ def generate_deployment_message(modeladmin, request, queryset): Collections Now Live in Prod:\n""" message_middle = "\n\n".join( - [ - f"- {collection.name} | {collection.server_url_prod}" - for collection in queryset.all() - ] + [f"- {collection.name} | {collection.server_url_prod}" for collection in queryset.all()] ) message_end = """ @@ -46,14 +43,10 @@ def download_candidate_urls_as_csv(modeladmin, request, queryset): writer = csv.writer(response) if len(queryset) > 1: - messages.add_message( - request, messages.ERROR, "You can only export one collection at a time." - ) + messages.add_message(request, messages.ERROR, "You can only export one collection at a time.") return - urls = CandidateURL.objects.filter(collection=queryset.first()).values_list( - "url", flat=True - ) + urls = CandidateURL.objects.filter(collection=queryset.first()).values_list("url", flat=True) # Write your headers here writer.writerow(["candidate_url"]) @@ -137,9 +130,7 @@ def import_candidate_urls_secret_test(modeladmin, request, queryset): @admin.action(description="Import candidate URLs from Secret Production") def import_candidate_urls_secret_production(modeladmin, request, queryset): - import_candidate_urls_from_api_caller( - modeladmin, request, queryset, "secret_production" - ) + import_candidate_urls_from_api_caller(modeladmin, request, queryset, "secret_production") @admin.action(description="Import candidate URLs from Li's Server") @@ -149,9 +140,7 @@ def import_candidate_urls_lis_server(modeladmin, request, queryset): @admin.action(description="Import candidate URLs from LRM Dev Server") def import_candidate_urls_lrm_dev_server(modeladmin, request, queryset): - import_candidate_urls_from_api_caller( - modeladmin, request, queryset, "lrm_dev_server" - ) + import_candidate_urls_from_api_caller(modeladmin, request, queryset, "lrm_dev_server") class ExportCsvMixin: @@ -287,6 +276,13 @@ class TitlePatternAdmin(admin.ModelAdmin): ) +class WorkflowStatusHistoryAdmin(admin.ModelAdmin): + list_display = ("collection", "old_status", "new_status", "changed_at") + search_fields = ["collection__name"] + list_filter = ["new_status", "old_status"] + + +admin.site.register(WorkflowStatusHistory, WorkflowStatusHistoryAdmin) admin.site.register(CandidateURL, CandidateURLAdmin) admin.site.register(TitlePattern, TitlePatternAdmin) admin.site.register(IncludePattern)