diff --git a/src/nsls2api/api/v1/facility_api.py b/src/nsls2api/api/v1/facility_api.py index 89002d0..a7d20b4 100644 --- a/src/nsls2api/api/v1/facility_api.py +++ b/src/nsls2api/api/v1/facility_api.py @@ -1,17 +1,21 @@ +from typing import Annotated import fastapi +from fastapi import Depends + from nsls2api.api.models.facility_model import ( FacilityName, FacilityCyclesResponseModel, FacilityCurrentOperatingCycleResponseModel, ) + +from nsls2api.infrastructure.security import validate_admin_role from nsls2api.api.models.proposal_model import CycleProposalList from nsls2api.services import proposal_service, facility_service router = fastapi.APIRouter() -# TODO: Add back into schema when implemented. @router.get( "/facility/{facility}/cycles/current", response_model=FacilityCurrentOperatingCycleResponseModel, @@ -37,6 +41,24 @@ async def get_current_operating_cycle(facility: FacilityName): return response_model +@router.post("/facility/{facility}/cycles/current", + response_model=FacilityCurrentOperatingCycleResponseModel, dependencies=[Depends(validate_admin_role)],) +async def set_current_operating_cycle(facility: FacilityName, cycle: str,): + current_cycle = await facility_service.set_current_operating_cycle(facility.name, cycle) + if current_cycle is None: + return fastapi.responses.JSONResponse( + { + "error": f"Failed to set the current operating cycle for facility {facility.name}" + }, + status_code=404, + ) + + response_model = FacilityCurrentOperatingCycleResponseModel( + facility=facility.name, cycle=current_cycle + ) + + return response_model + @router.get( "/facility/{facility}/cycles", diff --git a/src/nsls2api/services/facility_service.py b/src/nsls2api/services/facility_service.py index 5052050..8ca7011 100644 --- a/src/nsls2api/services/facility_service.py +++ b/src/nsls2api/services/facility_service.py @@ -138,6 +138,43 @@ async def current_operating_cycle(facility: str) -> Optional[str]: return cycle.name +async def set_current_operating_cycle(facility: str, cycle: str) -> Optional[str]: + """ + Set Current Operating Cycle + + This method sets the current operating cycle for a given facility. + + :param facility: The facility name (str). + :param cycle: The cycle name (str). + :return: The current operating cycle (str) or None if no current operating cycle is found. + """ + new_current_cycle = await Cycle.find_one( + Cycle.facility == facility, + Cycle.name == cycle, + ) + + if new_current_cycle is None: + return None + + # Now find previous "current operating cycle". + previous_cycle = await Cycle.find_one( + Cycle.facility == facility, + Cycle.is_current_operating_cycle is True, + ) + + if previous_cycle is not None: + await previous_cycle.set({Cycle.is_current_operating_cycle: False}) + + await new_current_cycle.set({Cycle.is_current_operating_cycle: True}) + + # Let's now check all is well with the world + expected_current_cycle = await current_operating_cycle(facility) + if str(expected_current_cycle) != cycle: + logger.error(f"Failed to set the current operating cycle for {facility} to be {cycle}.") + return None + + return expected_current_cycle + async def cycle_year( cycle_name: str, facility_name: FacilityName = FacilityName.nsls2 diff --git a/src/nsls2api/services/proposal_service.py b/src/nsls2api/services/proposal_service.py index e6b9eb3..2d0ac92 100644 --- a/src/nsls2api/services/proposal_service.py +++ b/src/nsls2api/services/proposal_service.py @@ -78,7 +78,9 @@ async def fetch_proposals_for_cycle(cycle_name: str) -> list[str]: cycle = await Cycle.find_one(Cycle.name == cycle_name) if cycle is None: raise LookupError(f"Cycle {cycle} not found in local database.") - return cycle.proposals + + return cycle.proposals or [] + async def fetch_data_sessions_for_username(username: str) -> list[str]: