diff --git a/tcms/rpc/api/testcase.py b/tcms/rpc/api/testcase.py index b1a6f4ea26..2eb3849880 100644 --- a/tcms/rpc/api/testcase.py +++ b/tcms/rpc/api/testcase.py @@ -3,6 +3,7 @@ from datetime import timedelta from django.contrib.auth import get_user_model +from django.db.models import OuterRef, Subquery from django.db.models.functions import Coalesce from django.forms import EmailField, ValidationError from django.forms.models import model_to_dict @@ -271,12 +272,18 @@ def filter(query=None): # pylint: disable=redefined-builtin qs = ( TestCase.objects.annotate( expected_duration=Coalesce("setup_duration", timedelta(0)) - + Coalesce("testing_duration", timedelta(0)) + + Coalesce("testing_duration", timedelta(0)), + last_modified=Subquery( + TestCase.history.model.objects.filter(id=OuterRef("pk")) + .order_by("-history_date") + .values("history_date")[:1] + ), ) .filter(**query) .values( "id", "create_date", + "last_modified", "is_automated", "script", "arguments", diff --git a/tcms/rpc/api/testplan.py b/tcms/rpc/api/testplan.py index 512169d71d..fc512fe907 100644 --- a/tcms/rpc/api/testplan.py +++ b/tcms/rpc/api/testplan.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from django.db.models import Count +from django.db.models import Count, OuterRef, Subquery from django.forms.models import model_to_dict from modernrpc.core import REQUEST_KEY, rpc_method @@ -88,12 +88,20 @@ def filter(query=None): # pylint: disable=redefined-builtin query = {} return list( - TestPlan.objects.filter(**query) + TestPlan.objects.annotate( + last_modified=Subquery( + TestPlan.history.model.objects.filter(id=OuterRef("pk")) + .order_by("-history_date") + .values("history_date")[:1] + ), + ) + .filter(**query) .values( "id", "name", "text", "create_date", + "last_modified", "is_active", "extra_link", "product_version", diff --git a/tcms/testcases/static/testcases/js/search.js b/tcms/testcases/static/testcases/js/search.js index 010b392a3d..eb2c5eb93c 100644 --- a/tcms/testcases/static/testcases/js/search.js +++ b/tcms/testcases/static/testcases/js/search.js @@ -157,6 +157,7 @@ export function pageTestcasesSearchReadyHandler () { } }, { data: 'create_date' }, + { data: 'last_modified' }, { data: 'category__name' }, { data: 'component_names' }, { data: 'priority__value' }, diff --git a/tcms/testcases/templates/testcases/get.html b/tcms/testcases/templates/testcases/get.html index 8665371a95..250ba6ef21 100644 --- a/tcms/testcases/templates/testcases/get.html +++ b/tcms/testcases/templates/testcases/get.html @@ -69,6 +69,11 @@

{{ object.create_date }}

+

+ {% trans 'Last modified' %}: + {{ last_modified }} +

+

{% trans 'Setup duration' %}: {{ object.setup_duration|default:"-" }} diff --git a/tcms/testcases/templates/testcases/search.html b/tcms/testcases/templates/testcases/search.html index 1cf000552b..085e8605c7 100644 --- a/tcms/testcases/templates/testcases/search.html +++ b/tcms/testcases/templates/testcases/search.html @@ -165,6 +165,7 @@ {% trans "ID" %} {% trans "Summary" %} {% trans "Created on" %} + {% trans "Last modified" %} {% trans "Category" %} {% trans "Component" %} {% trans "Priority" %} diff --git a/tcms/testcases/views.py b/tcms/testcases/views.py index 64c26365ed..28e32eed68 100644 --- a/tcms/testcases/views.py +++ b/tcms/testcases/views.py @@ -125,6 +125,11 @@ def get_context_data(self, **kwargs): context["executions"] = self.object.executions.select_related( "run", "tested_by", "assignee", "case", "status" ).order_by("run__plan", "run") + context["last_modified"] = ( + self.object.history.latest().history_date + if self.object.history.exists() + else self.object.create_date + ) context["OBJECT_MENU_ITEMS"] = [ ( "...", diff --git a/tcms/testplans/static/testplans/js/search.js b/tcms/testplans/static/testplans/js/search.js index e3e9270889..50caf05ff1 100644 --- a/tcms/testplans/static/testplans/js/search.js +++ b/tcms/testplans/static/testplans/js/search.js @@ -117,6 +117,7 @@ export function pageTestplansSearchReadyHandler () { } }, { data: 'create_date' }, + { data: 'last_modified' }, { data: 'product__name' }, { data: 'product_version__value' }, { data: 'type__name' }, diff --git a/tcms/testplans/templates/testplans/get.html b/tcms/testplans/templates/testplans/get.html index a994e89dd7..8a890fad7a 100644 --- a/tcms/testplans/templates/testplans/get.html +++ b/tcms/testplans/templates/testplans/get.html @@ -59,6 +59,11 @@

{{ object.create_date }}

+

+ {% trans 'Last modified' %}: + {{ last_modified }} +

+

{% trans 'Product' %}: diff --git a/tcms/testplans/templates/testplans/search.html b/tcms/testplans/templates/testplans/search.html index 2766146842..443693e37f 100644 --- a/tcms/testplans/templates/testplans/search.html +++ b/tcms/testplans/templates/testplans/search.html @@ -116,6 +116,7 @@ {% trans "ID" %} {% trans "Test plan" %} {% trans "Created on" %} + {% trans "Last modified" %} {% trans "Product" %} {% trans "Version" %} {% trans "Type" %} diff --git a/tcms/testplans/views.py b/tcms/testplans/views.py index 10e66a703a..a676a69066 100644 --- a/tcms/testplans/views.py +++ b/tcms/testplans/views.py @@ -136,6 +136,11 @@ def get_context_data(self, **kwargs): context["test_runs"] = TestRun.objects.filter( plan_id=self.object.pk, stop_date__isnull=True ).order_by("-id")[:5] + context["last_modified"] = ( + self.object.history.latest().history_date + if self.object.history.exists() + else self.object.create_date + ) context["OBJECT_MENU_ITEMS"] = [ ( "...",