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
« 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/>.
18from pyramid.request import Request, Response
19from pyramid.view import view_config
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
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
34 URL: solicitations/{solicitation_id}/proposal_reviews
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 """
42 solicitation_id = request.matchdict["solicitation_id"]
43 user_id = request.identity.user_id
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)
48 proposal_reviews: list[ProposalReview] = list()
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)
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
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)
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)
81 return Response(json=[emit_proposal_review_json(pr, request.repo) for pr in proposal_reviews])