107107 get_authorized_members_for_product_type ,
108108 get_authorized_product_types ,
109109)
110+ from dojo .query_utils import build_count_subquery
110111from dojo .templatetags .display_tags import asvs_calc_level
111112from dojo .tool_config .factory import create_API
112113from dojo .tools .factory import get_api_scan_configuration_hints
117118 add_external_issue ,
118119 add_field_errors_to_response ,
119120 async_delete ,
120- build_count_subquery ,
121121 calculate_finding_age ,
122122 get_enabled_notifications_list ,
123123 get_open_findings_burndown ,
@@ -701,7 +701,11 @@ def view_product_metrics(request, pid):
701701 accepted_objs_by_severity [finding .get ("severity" )] += 1
702702
703703 tests = Test .objects .filter (engagement__product = prod ).prefetch_related ("finding_set" , "test_type" )
704- tests = tests .annotate (verified_finding_count = Count ("finding__id" , filter = Q (finding__verified = True )))
704+ verified_finding_subquery = build_count_subquery (
705+ Finding .objects .filter (test = OuterRef ("pk" ), verified = True ),
706+ group_field = "test_id" ,
707+ )
708+ tests = tests .annotate (verified_finding_count = Coalesce (verified_finding_subquery , Value (0 )))
705709
706710 test_data = {}
707711 for t in tests :
@@ -828,9 +832,7 @@ def view_engagements(request, pid):
828832
829833
830834def prefetch_for_view_engagements (engagements , recent_test_day_count ):
831- engagements = engagements .select_related (
832- "lead" ,
833- ).prefetch_related (
835+ engagements = engagements .prefetch_related (
834836 Prefetch ("test_set" , queryset = Test .objects .filter (
835837 id__in = Subquery (
836838 Test .objects .filter (
@@ -840,15 +842,41 @@ def prefetch_for_view_engagements(engagements, recent_test_day_count):
840842 )),
841843 ),
842844 "test_set__test_type" ,
843- ).annotate (
844- count_tests = Count ("test" , distinct = True ),
845- count_findings_all = Count ("test__finding__id" ),
846- count_findings_open = Count ("test__finding__id" , filter = Q (test__finding__active = True )),
847- count_findings_open_verified = Count ("test__finding__id" ,
848- filter = Q (test__finding__active = True ) & Q (test__finding__verified = True )),
849- count_findings_close = Count ("test__finding__id" , filter = Q (test__finding__is_mitigated = True )),
850- count_findings_duplicate = Count ("test__finding__id" , filter = Q (test__finding__duplicate = True )),
851- count_findings_accepted = Count ("test__finding__id" , filter = Q (test__finding__risk_accepted = True )),
845+ ).select_related (
846+ "lead" ,
847+ )
848+
849+ # Use subqueries to avoid GROUP BY issues
850+ test_subquery = build_count_subquery (
851+ Test .objects .filter (engagement = OuterRef ("pk" )), group_field = "engagement_id" ,
852+ )
853+ finding_subquery = build_count_subquery (
854+ Finding .objects .filter (test__engagement = OuterRef ("pk" )), group_field = "test__engagement_id" ,
855+ )
856+ finding_open_subquery = build_count_subquery (
857+ Finding .objects .filter (test__engagement = OuterRef ("pk" ), active = True ), group_field = "test__engagement_id" ,
858+ )
859+ finding_open_verified_subquery = build_count_subquery (
860+ Finding .objects .filter (test__engagement = OuterRef ("pk" ), active = True , verified = True ), group_field = "test__engagement_id" ,
861+ )
862+ finding_close_subquery = build_count_subquery (
863+ Finding .objects .filter (test__engagement = OuterRef ("pk" ), is_mitigated = True ), group_field = "test__engagement_id" ,
864+ )
865+ finding_duplicate_subquery = build_count_subquery (
866+ Finding .objects .filter (test__engagement = OuterRef ("pk" ), duplicate = True ), group_field = "test__engagement_id" ,
867+ )
868+ finding_accepted_subquery = build_count_subquery (
869+ Finding .objects .filter (test__engagement = OuterRef ("pk" ), risk_accepted = True ), group_field = "test__engagement_id" ,
870+ )
871+
872+ engagements = engagements .annotate (
873+ count_tests = Coalesce (test_subquery , Value (0 )),
874+ count_findings_all = Coalesce (finding_subquery , Value (0 )),
875+ count_findings_open = Coalesce (finding_open_subquery , Value (0 )),
876+ count_findings_open_verified = Coalesce (finding_open_verified_subquery , Value (0 )),
877+ count_findings_close = Coalesce (finding_close_subquery , Value (0 )),
878+ count_findings_duplicate = Coalesce (finding_duplicate_subquery , Value (0 )),
879+ count_findings_accepted = Coalesce (finding_accepted_subquery , Value (0 )),
852880 )
853881
854882 if System_Settings .objects .get ().enable_jira :
0 commit comments