Coverage for middle_layer/allocate/application_layer/rest_api/views/timebin.py: 95.24%
42 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 http import HTTPStatus
20from pyramid.httpexceptions import HTTPBadRequest
21from pyramid.request import Request
22from pyramid.response import Response
23from pyramid.view import view_config
25from allocate.domain_layer.entities.allocation_version import AllocationVersion
26from allocate.domain_layer.entities.available_time_model_version import AvailableTimeModelVersion
27from allocate.domain_layer.entities.time_bins import TimeCalculationException
28from allocate.domain_layer.services.pressure_cooker_service import pressure_cooker
29from allocate.domain_layer.services.serialize_timebins_to_csv_service import serialize_timebins_to_csv
32def common_timebin_api_handler(request):
33 available_time_model_version_id = request.params.get("availableTimeModelVersionId")
34 allocation_version_id = request.params.get("allocationVersionId")
36 # Default to True if not specified
37 apply_time_reservations = request.params.get("apply_time_reservations", "true").lower() not in ("false", "0")
39 if not available_time_model_version_id:
40 raise HTTPBadRequest(body=f"timebins requires available_time_model_version_id to be specified.")
42 av: AllocationVersion = None
43 atmv: AvailableTimeModelVersion = None
45 if available_time_model_version_id:
46 atmv: AvailableTimeModelVersion = request.lookup(available_time_model_version_id, AvailableTimeModelVersion)
48 if allocation_version_id:
49 av: AllocationVersion = request.lookup(allocation_version_id, AllocationVersion)
50 try:
51 timebins = pressure_cooker(
52 available_time_model_version=atmv,
53 allocation_version=av,
54 apply_time_reservations=apply_time_reservations,
55 )
56 except TimeCalculationException as e:
57 raise HTTPBadRequest(body=str(e))
58 return atmv, av, timebins
61@view_config(route_name="timebins", renderer="json", permission="timebins")
62def timebins(request: Request) -> Response:
63 """Return the data required to generate pressure plots for the specified AvailableTimeModelVersion and
64 AllocationVersion (if specified)
66 Note: available_time_model_version_id is required, allocation_version_id can be optionally specififed
67 apply_time_reservations is optional and defaults to True, if set to False, the timebins will be generated
68 without time reservations
70 URL: timebins?available_time_model_version_id={available_time_model_version_id}
71 OR timebins?available_time_model_version_id={
72 available_time_model_version_id}&allocation_version_id={allocation_version_id}
74 Optionally, the above with: &apply_time_reservations={True|False}
76 :param request: GET Request
77 :return: Response with the list of JSON formatted pressure plot data per ATM
78 or 404 response (HTTPNotFound) if no AvailableTimeModelVersion or AllocationVersion exists with the given ids,
79 or 400 response (HTTPBadRequest) if available_time_model_version_id is not provided or is malformed
80 or allocation_version_id is also provided but malformed
81 or 401 response (HTTPUnauthorized) if the requesting user is not a TTA Member
82 """
83 atmv, av, timebins = common_timebin_api_handler(request)
84 return Response(json_body=timebins)
87@view_config(route_name="timebins_export", renderer="json", permission="timebins")
88def timebins_export(request: Request) -> Response:
89 """Export the data required to generate pressure plots for the specified AvailableTimeModelVersion and
90 AllocationVersion (if specified). Time Reservations are applied by default but can be disabled by setting
91 the optional apply_time_reservations to false.
93 URL: timebins_export?available_time_model_version_id={available_time_model_version_id}
94 OR timebins_export?available_time_model_version_id={
95 available_time_model_version_id}&allocation_version_id={allocation_version_id}
97 Optionally, the above with: &apply_time_reservations={True|False}
99 :param request: GET Request
100 :return: Response with the list of JSON formatted pressure plot data per ATM
101 or 404 response (HTTPNotFound) if no AllocationVersion or AvailableTimeModelVersion exists with the given ids,
102 or 400 response (HTTPBadRequest) if available_time_model_version_id is not provided or is malformed
103 or allocation_version_id is also provided but malformed
104 or 401 response (HTTPUnauthorized) if the requesting user is not a TTA Member
105 """
106 atmv, av, timebins = common_timebin_api_handler(request)
108 timebins_csv = serialize_timebins_to_csv(timebins)
110 if atmv and av:
111 filename = (
112 f"pressure_plot_data_for_available_time_model_version_"
113 f"{atmv.available_time_model_version_id}_and_allocation_version"
114 f"_{av.allocation_version_id}.csv"
115 )
116 else:
117 filename = f"pressure_plot_data_for_available_time_model_version_{atmv.available_time_model_version_id}.csv"
118 response = Response(status_code=HTTPStatus.OK, body=timebins_csv.encode())
119 response.headers["Content-Disposition"] = "attachment;filename=" + filename
120 response.headers["Access-Control-Expose-Headers"] = "Content-Disposition"
121 return response