2323 Value ,
2424 When ,
2525 Subquery ,
26- UUIDField ,
2726)
28- from django .db .models .functions import Coalesce
29- from django .contrib .postgres .aggregates import ArrayAgg
30- from django .contrib .postgres .fields import ArrayField
27+
3128from django .utils import timezone
3229from django .conf import settings
3330
@@ -2292,14 +2289,35 @@ class IssueRelationListCreateAPIEndpoint(BaseAPIView):
22922289 name = "Work Item Relations Response" ,
22932290 value = {
22942291 "blocking" : [
2295- "550e8400-e29b-41d4-a716-446655440000" ,
2296- "550e8400-e29b-41d4-a716-446655440001" ,
2292+ {
2293+ "project_id" : "550e8400-e29b-41d4-a716-446655440010" ,
2294+ "issue_id" : "550e8400-e29b-41d4-a716-446655440000" ,
2295+ },
2296+ {
2297+ "project_id" : "550e8400-e29b-41d4-a716-446655440010" ,
2298+ "issue_id" : "550e8400-e29b-41d4-a716-446655440001" ,
2299+ },
2300+ ],
2301+ "blocked_by" : [
2302+ {
2303+ "project_id" : "550e8400-e29b-41d4-a716-446655440011" ,
2304+ "issue_id" : "550e8400-e29b-41d4-a716-446655440002" ,
2305+ },
22972306 ],
2298- "blocked_by" : ["550e8400-e29b-41d4-a716-446655440002" ],
22992307 "duplicate" : [],
2300- "relates_to" : ["550e8400-e29b-41d4-a716-446655440003" ],
2308+ "relates_to" : [
2309+ {
2310+ "project_id" : "550e8400-e29b-41d4-a716-446655440010" ,
2311+ "issue_id" : "550e8400-e29b-41d4-a716-446655440003" ,
2312+ },
2313+ ],
23012314 "start_after" : [],
2302- "start_before" : ["550e8400-e29b-41d4-a716-446655440004" ],
2315+ "start_before" : [
2316+ {
2317+ "project_id" : "550e8400-e29b-41d4-a716-446655440012" ,
2318+ "issue_id" : "550e8400-e29b-41d4-a716-446655440004" ,
2319+ },
2320+ ],
23032321 "finish_after" : [],
23042322 "finish_before" : [],
23052323 },
@@ -2316,42 +2334,81 @@ def get(self, request, slug, project_id, issue_id):
23162334 Retrieve all relationships for a work item organized by relation type.
23172335 Returns a structured response with relations grouped by type.
23182336 """
2319- empty_uuid_array = Value ([], output_field = ArrayField (UUIDField ()))
2320-
2321- def _agg_ids (field , ** filter_kwargs ):
2322- return Coalesce (
2323- ArrayAgg (field , filter = Q (** filter_kwargs ), distinct = True ),
2324- empty_uuid_array ,
2325- )
2326-
2327- issue_relation_qs = IssueRelation .objects .filter (
2337+ relations = IssueRelation .objects .filter (
23282338 Q (issue_id = issue_id ) | Q (related_issue_id = issue_id ),
23292339 workspace__slug = slug ,
2330- )
2331-
2332- relation_ids = issue_relation_qs .aggregate (
2333- blocking_ids = _agg_ids ("issue_id" , relation_type = "blocked_by" , related_issue_id = issue_id ),
2334- blocked_by_ids = _agg_ids ("related_issue_id" , relation_type = "blocked_by" , issue_id = issue_id ),
2335- duplicate_ids = _agg_ids ("related_issue_id" , relation_type = "duplicate" , issue_id = issue_id ),
2336- duplicate_ids_related = _agg_ids ("issue_id" , relation_type = "duplicate" , related_issue_id = issue_id ),
2337- relates_to_ids = _agg_ids ("related_issue_id" , relation_type = "relates_to" , issue_id = issue_id ),
2338- relates_to_ids_related = _agg_ids ("issue_id" , relation_type = "relates_to" , related_issue_id = issue_id ),
2339- start_after_ids = _agg_ids ("issue_id" , relation_type = "start_before" , related_issue_id = issue_id ),
2340- start_before_ids = _agg_ids ("related_issue_id" , relation_type = "start_before" , issue_id = issue_id ),
2341- finish_after_ids = _agg_ids ("issue_id" , relation_type = "finish_before" , related_issue_id = issue_id ),
2342- finish_before_ids = _agg_ids ("related_issue_id" , relation_type = "finish_before" , issue_id = issue_id ),
2340+ ).values (
2341+ "relation_type" ,
2342+ "issue_id" ,
2343+ "related_issue_id" ,
2344+ issue_project_id = F ("issue__project_id" ),
2345+ related_issue_project_id = F ("related_issue__project_id" ),
23432346 )
23442347
23452348 response_data = {
2346- "blocking" : relation_ids [ "blocking_ids" ],
2347- "blocked_by" : relation_ids [ "blocked_by_ids" ],
2348- "duplicate" : list ( set ( relation_ids [ "duplicate_ids" ] + relation_ids [ "duplicate_ids_related" ])) ,
2349- "relates_to" : list ( set ( relation_ids [ "relates_to_ids" ] + relation_ids [ "relates_to_ids_related" ])) ,
2350- "start_after" : relation_ids [ "start_after_ids" ],
2351- "start_before" : relation_ids [ "start_before_ids" ],
2352- "finish_after" : relation_ids [ "finish_after_ids" ],
2353- "finish_before" : relation_ids [ "finish_before_ids" ],
2349+ "blocking" : [ ],
2350+ "blocked_by" : [ ],
2351+ "duplicate" : [] ,
2352+ "relates_to" : [] ,
2353+ "start_after" : [ ],
2354+ "start_before" : [ ],
2355+ "finish_after" : [ ],
2356+ "finish_before" : [ ],
23542357 }
2358+ seen_duplicate = set ()
2359+ seen_relates_to = set ()
2360+
2361+ for rel in relations :
2362+ rt = rel ["relation_type" ]
2363+ if rt == "blocked_by" :
2364+ if str (rel ["related_issue_id" ]) == str (issue_id ):
2365+ response_data ["blocking" ].append (
2366+ {"project_id" : str (rel ["issue_project_id" ]), "issue_id" : str (rel ["issue_id" ])}
2367+ )
2368+ if str (rel ["issue_id" ]) == str (issue_id ):
2369+ response_data ["blocked_by" ].append (
2370+ {"project_id" : str (rel ["related_issue_project_id" ]), "issue_id" : str (rel ["related_issue_id" ])}
2371+ )
2372+ elif rt == "duplicate" :
2373+ if str (rel ["issue_id" ]) == str (issue_id ) and rel ["related_issue_id" ] not in seen_duplicate :
2374+ seen_duplicate .add (rel ["related_issue_id" ])
2375+ response_data ["duplicate" ].append (
2376+ {"project_id" : str (rel ["related_issue_project_id" ]), "issue_id" : str (rel ["related_issue_id" ])}
2377+ )
2378+ if str (rel ["related_issue_id" ]) == str (issue_id ) and rel ["issue_id" ] not in seen_duplicate :
2379+ seen_duplicate .add (rel ["issue_id" ])
2380+ response_data ["duplicate" ].append (
2381+ {"project_id" : str (rel ["issue_project_id" ]), "issue_id" : str (rel ["issue_id" ])}
2382+ )
2383+ elif rt == "relates_to" :
2384+ if str (rel ["issue_id" ]) == str (issue_id ) and rel ["related_issue_id" ] not in seen_relates_to :
2385+ seen_relates_to .add (rel ["related_issue_id" ])
2386+ response_data ["relates_to" ].append (
2387+ {"project_id" : str (rel ["related_issue_project_id" ]), "issue_id" : str (rel ["related_issue_id" ])}
2388+ )
2389+ if str (rel ["related_issue_id" ]) == str (issue_id ) and rel ["issue_id" ] not in seen_relates_to :
2390+ seen_relates_to .add (rel ["issue_id" ])
2391+ response_data ["relates_to" ].append (
2392+ {"project_id" : str (rel ["issue_project_id" ]), "issue_id" : str (rel ["issue_id" ])}
2393+ )
2394+ elif rt == "start_before" :
2395+ if str (rel ["related_issue_id" ]) == str (issue_id ):
2396+ response_data ["start_after" ].append (
2397+ {"project_id" : str (rel ["issue_project_id" ]), "issue_id" : str (rel ["issue_id" ])}
2398+ )
2399+ if str (rel ["issue_id" ]) == str (issue_id ):
2400+ response_data ["start_before" ].append (
2401+ {"project_id" : str (rel ["related_issue_project_id" ]), "issue_id" : str (rel ["related_issue_id" ])}
2402+ )
2403+ elif rt == "finish_before" :
2404+ if str (rel ["related_issue_id" ]) == str (issue_id ):
2405+ response_data ["finish_after" ].append (
2406+ {"project_id" : str (rel ["issue_project_id" ]), "issue_id" : str (rel ["issue_id" ])}
2407+ )
2408+ if str (rel ["issue_id" ]) == str (issue_id ):
2409+ response_data ["finish_before" ].append (
2410+ {"project_id" : str (rel ["related_issue_project_id" ]), "issue_id" : str (rel ["related_issue_id" ])}
2411+ )
23552412
23562413 return Response (response_data , status = status .HTTP_200_OK )
23572414
0 commit comments