Coverage for middle_layer/allocate/domain_layer/services/serialize_proposal_summary_to_csv_service.py: 100.00%

14 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"""Serialize Proposal Summaries as CSV to be exported""" 

18 

19import csv 

20import json 

21from io import StringIO 

22 

23from common.domain_layer import JSON_OBJECT 

24 

25 

26def serialize_proposal_summary_row(summ) -> dict[str, str]: 

27 """Serialize a Proposal Summary for export in a CSV file 

28 

29 :param summ: proposal summary to serialize 

30 :return: Dict, where keys are CSV column names 

31 """ 

32 proposal_summary_dict = { 

33 "proposalId": summ["proposal_id"], 

34 "scientificMeritMetric": summ["scientific_merit_metric"], 

35 "piName": summ["pi_name"], 

36 "coiNames": summ["coi_names"], 

37 "title": summ["title"], 

38 "abstract": summ["abstract"], 

39 "reviewProcessTag": summ["review_process_tag"], 

40 "externalJointFacilities": summ["external_joint_facilities"], 

41 "internalJointFacilities": summ["internal_joint_facilities"] if summ["internal_joint_facilities"] else "", 

42 "proposalClass": summ["proposal_class"], 

43 "isTriggered": summ["is_triggered"], 

44 "isThesis": summ["is_thesis"], 

45 "totalRequestedHours": str(summ["total_requested_hours"]), 

46 "priorities": summ["priorities"], 

47 "facilityConfigurations": summ["facility_configurations"], 

48 "hardwareBands": summ["hardware_bands"], 

49 "priorityA": str(summ["priority_a"]), 

50 "priorityB": str(summ["priority_b"]), 

51 "priorityC": str(summ["priority_c"]), 

52 "priorityN": str(summ["priority_n"]), 

53 "schedulerComments": summ["scheduler_comments"], 

54 "externalScienceReviewComments": summ["external_science_review_comments"], 

55 "externalTechnicalReviewComments": summ["external_technical_review_comments"], 

56 "externalDataManagementReviewComments": summ["external_data_management_review_comments"], 

57 "internalScienceReviewComments": summ["internal_science_review_comments"], 

58 "internalTechnicalReviewComments": summ["internal_technical_review_comments"], 

59 "internalDataManagementReviewComments": summ["internal_data_management_review_comments"], 

60 "externalAllocationDispositionComments": summ["external_allocation_disposition_comments"], 

61 "internalAllocationDispositionComments": summ["internal_allocation_disposition_comments"], 

62 } 

63 return proposal_summary_dict 

64 

65 

66def serialize_proposal_summaries_to_csv(summaries: list) -> str: 

67 """Serialize a list of proposal summaries into a string of CSV rows with a header at the top, 

68 for export as a CSV file 

69 

70 :param summaries: List of summaries to serialize 

71 :return: String with all of the summaries, in order, represented as CSV 

72 """ 

73 

74 headers = [ 

75 "proposalId", 

76 "scientificMeritMetric", 

77 "piName", 

78 "coiNames", 

79 "title", 

80 "abstract", 

81 "reviewProcessTag", 

82 "externalJointFacilities", 

83 "internalJointFacilities", 

84 "proposalClass", 

85 "isTriggered", 

86 "isThesis", 

87 "totalRequestedHours", 

88 "priorities", 

89 "facilityConfigurations", 

90 "hardwareBands", 

91 "priorityA", 

92 "priorityB", 

93 "priorityC", 

94 "priorityN", 

95 "schedulerComments", 

96 "externalScienceReviewComments", 

97 "externalTechnicalReviewComments", 

98 "externalDataManagementReviewComments", 

99 "internalScienceReviewComments", 

100 "internalTechnicalReviewComments", 

101 "internalDataManagementReviewComments", 

102 "externalAllocationDispositionComments", 

103 "internalAllocationDispositionComments", 

104 ] 

105 

106 csv_file = StringIO() 

107 csvwriter = csv.DictWriter(csv_file, headers) 

108 csvwriter.writeheader() 

109 csvwriter.writerows([serialize_proposal_summary_row(summary) for summary in summaries]) 

110 return csv_file.getvalue()