From fd17c0e672020edc93d21c00623428adae658bcb Mon Sep 17 00:00:00 2001 From: GotthardG <51994228+GotthardG@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:31:27 +0100 Subject: [PATCH] refined output of retrieving pucks and dewars at beamlines --- backend/app/routers/puck.py | 115 ++++++++++++++++++++++++++---------- requirements.txt | 7 ++- 2 files changed, 91 insertions(+), 31 deletions(-) diff --git a/backend/app/routers/puck.py b/backend/app/routers/puck.py index c9cd04c..bc02d8f 100644 --- a/backend/app/routers/puck.py +++ b/backend/app/routers/puck.py @@ -131,60 +131,115 @@ async def get_last_tell_position(puck_id: str, db: Session = Depends(get_db)): "timestamp": last_event.timestamp, } -@router.get("/slot/{slot_id}", response_model=List[PuckSchema]) -async def get_pucks_by_latest_beamline_dewar_slot(slot_id: int, db: Session = Depends(get_db)): + +@router.get("/slot/{slot_identifier}", response_model=List[dict]) +async def get_pucks_by_slot( + slot_identifier: str, + db: Session = Depends(get_db) +): """ - Retrieve all pucks for the most recent dewar associated with the given slot_id, - where the last logistics event is of type 'beamline'. + Retrieve all pucks associated with all dewars linked to the given slot + (by ID or keyword) via 'beamline' events. + + - Accepts slot keywords like PXI, PXII, PXIII. + - Retrieves all dewars (and their names) associated with the slot. """ - # Step 1: Verify the slot exists + # Map keywords to slot IDs + slot_aliases = { + "PXI": 47, + "PXII": 48, + "PXIII": 49, + "X06SA": 47, + "X10SA": 48, + "X06DA": 49 + } + + # Check if the slot identifier is an alias or ID + try: + slot_id = int(slot_identifier) # If the user provided a numeric ID + alias = next((k for k, v in slot_aliases.items() if v == slot_id), slot_identifier) + except ValueError: + slot_id = slot_aliases.get(slot_identifier.upper()) # Try mapping alias + alias = slot_identifier.upper() # Keep alias as-is for error messages + if not slot_id: + raise HTTPException( + status_code=400, + detail="Invalid slot identifier. Must be an ID or one of the following: PXI, PXII, PXIII, X06SA, X10SA, X06DA." + ) + + # Verify that the slot exists slot = db.query(SlotModel).filter(SlotModel.id == slot_id).first() if not slot: - logger.error(f"No slot found with ID={slot_id}.") - raise HTTPException(status_code=404, detail="Slot not found") + raise HTTPException( + status_code=404, + detail=f"Slot not found for identifier '{alias}'." + ) - logger.info(f"Slot found: {slot}") + logger.info(f"Slot found: ID={slot.id}, Label={slot.label}") - # Step 2: Fetch the most recent 'beamline' event for the slot - recent_beamline_event = ( + # Retrieve all beamline events associated with the slot + beamline_events = ( db.query(LogisticsEventModel) .filter( LogisticsEventModel.slot_id == slot_id, LogisticsEventModel.event_type == "beamline" ) .order_by(LogisticsEventModel.timestamp.desc()) - .first() + .all() ) - if not recent_beamline_event: - logger.error(f"No 'beamline' event found for slot_id={slot_id}.") + if not beamline_events: + logger.warning(f"No dewars associated to this beamline '{alias}'.") raise HTTPException( status_code=404, - detail="No 'beamline' event found for the given slot" + detail=f"No dewars found for the given beamline '{alias}'." ) - logger.info(f"Found beamline event: {recent_beamline_event}") + logger.info(f"Found {len(beamline_events)} beamline events for slot_id={slot_id}.") - # Step 3: Retrieve the Dewar from the recent event - dewar = db.query(DewarModel).filter(DewarModel.id == recent_beamline_event.dewar_id).first() + # Use the beamline events to find all associated dewars + dewar_ids = {event.dewar_id for event in beamline_events if event.dewar_id} + dewars = db.query(DewarModel).filter(DewarModel.id.in_(dewar_ids)).all() - if not dewar: - logger.error( - f"No dewar found for the most recent beamline event. Dewar ID={recent_beamline_event.dewar_id}" - ) + if not dewars: + logger.warning(f"No dewars found for beamline '{alias}'.") raise HTTPException( status_code=404, - detail="No dewar associated with the most recent 'beamline' event" + detail=f"No dewars found for beamline '{alias}'." ) - logger.info(f"Associated dewar found: {dewar}") + logger.info(f"Found {len(dewars)} dewars for beamline '{alias}'.") - # Step 4: Retrieve all pucks associated with the Dewar - pucks = db.query(PuckModel).filter(PuckModel.dewar_id == dewar.id).all() + # Create a mapping of dewar_id to dewar_name + dewar_mapping = {dewar.id: dewar.dewar_name for dewar in dewars} - if not pucks: - logger.warning(f"No pucks found for Dewar ID={dewar.id}.") - else: - logger.info(f"Retrieved pucks for Dewar ID={dewar.id}: {pucks}") + # Retrieve all pucks associated with the dewars + puck_list = ( + db.query(PuckModel) + .filter(PuckModel.dewar_id.in_([dewar.id for dewar in dewars])) + .all() + ) - return pucks + if not puck_list: + logger.warning(f"No pucks found for dewars associated with beamline '{alias}'.") + raise HTTPException( + status_code=404, + detail=f"No pucks found for dewars associated with beamline '{alias}'." + ) + + logger.info(f"Found {len(puck_list)} pucks for beamline '{alias}'.") + + # Add the dewar_name to the output for each puck + puck_output = [ + { + "id": puck.id, + "puck_name": puck.puck_name, + "puck_type": puck.puck_type, + "dewar_id": puck.dewar_id, + "dewar_name": dewar_mapping.get(puck.dewar_id) # Link dewar_name + } + for puck in puck_list + ] + + # Return the list of pucks with their associated dewar names + return puck_output \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 1e8dbb4..2247494 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,9 @@ SQLAlchemy~=2.0.36 fastapi~=0.115.4 pydantic~=2.9.2 openpyxl~=3.1.5 -typing_extensions~=4.12.2 \ No newline at end of file +typing_extensions~=4.12.2 +jwt~=1.3.1 +qrcode~=8.0 +pillow~=11.0.0 +reportlab~=4.2.5 +cryptography~=44.0.0 \ No newline at end of file