Coverage for middle_layer/review/application_layer/rest_api/views/proposal_review.py: 93.75%

32 statements  

« prev     ^ index     » next       coverage.py v7.10.5, created at 2026-03-09 06:13 +0000

1# Copyright 2024 Associated Universities, Inc. 

2# 

3# This file is part of Telescope Time Allocation Tools (TTAT). 

4# 

5# TTAT is free software: you can redistribute it and/or modify 

6# it under the terms of the GNU General Public License as published by 

7# the Free Software Foundation, either version 3 of the License, or 

8# any later version. 

9# 

10# TTAT is distributed in the hope that it will be useful, 

11# but WITHOUT ANY WARRANTY; without even the implied warranty of 

12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

13# GNU General Public License for more details. 

14# 

15# You should have received a copy of the GNU General Public License 

16# along with TTAT. If not, see <https://www.gnu.org/licenses/>. 

17 

18from pyramid.request import Request, Response 

19from pyramid.view import view_config 

20 

21from common.application_layer.services.permissions_service import is_active_tac, is_author_of_completed_proposal 

22from review.domain_layer.entities.proposal_review import ProposalReview 

23from review.domain_layer.services.emit_proposal_review_json_service import emit_proposal_review_json 

24 

25 

26@view_config( 

27 route_name="proposal_review_list_by_solicitation_id", 

28 renderer="json", 

29 permission="proposal_review_list_by_solicitation_id", 

30) 

31def proposal_review_list_by_solicitation_id(request: Request) -> Response: 

32 """List ProposalReviews that the requesting user is allowed to see on the given Solicitation 

33 

34 URL: solicitations/{solicitation_id}/proposal_reviews 

35 

36 :param request: GET request 

37 :return: Response with list of JSON-formatted ProposalReviews on the given Solicitation is returned if the 

38 requester is a TTA member or an active TAC member on this solicitation or an 

39 author of a proposal that is published to closeout. Otherwise, an empty list is returned. 

40 """ 

41 

42 solicitation_id = request.matchdict["solicitation_id"] 

43 user_id = request.identity.user_id 

44 

45 is_tta_member = True if "tta_member" in request.identity.roles else False 

46 is_active_tac_member = is_active_tac(solicitation_id, user_id, request.repo) 

47 

48 proposal_reviews: list[ProposalReview] = list() 

49 

50 # Active TAC members on this solicitation or TTA members can view all proposal reviews 

51 if is_tta_member or is_active_tac_member: 

52 proposal_reviews = request.repo.ppr_proposal_review_repo.list_by_solicitation_id(solicitation_id) 

53 proposal_reviews.extend(request.repo.osr_proposal_review_repo.list_by_solicitation_id(solicitation_id)) 

54 else: 

55 # For proposal authors, check if they authored any proposals for this solicitation 

56 # First, get all proposals for this solicitation 

57 proposals = request.repo.proposal_repo.list_filtered(solicitation_id=solicitation_id) 

58 

59 # Filter for proposals where the user is an author 

60 user_proposal_ids = [] 

61 for proposal in proposals: 

62 for author in proposal.authors: 

63 if author.user_id == user_id: 

64 user_proposal_ids.append(proposal.proposal_id) 

65 break 

66 

67 # If user is an author of any proposals, get only the reviews for those proposals 

68 if user_proposal_ids: 

69 # Get PPR proposal reviews 

70 all_ppr_reviews = request.repo.ppr_proposal_review_repo.list_by_solicitation_id(solicitation_id) 

71 for review in all_ppr_reviews: 

72 if review.proposal_id in user_proposal_ids: 

73 proposal_reviews.append(review) 

74 

75 # Get OSR proposal reviews 

76 all_osr_reviews = request.repo.osr_proposal_review_repo.list_by_solicitation_id(solicitation_id) 

77 for review in all_osr_reviews: 

78 if review.proposal_id in user_proposal_ids: 

79 proposal_reviews.append(review) 

80 

81 return Response(json=[emit_proposal_review_json(pr, request.repo) for pr in proposal_reviews])