diff --git a/backend/app/routers/puck.py b/backend/app/routers/puck.py index accdde4..cff0801 100644 --- a/backend/app/routers/puck.py +++ b/backend/app/routers/puck.py @@ -145,6 +145,7 @@ def get_pucks_at_beamline(slot_id: int, db: Session) -> List[PuckWithTellPositio PuckModel, PuckEventModel.event_type, PuckEventModel.tell_position, + PuckEventModel.timestamp, # Useful for debugging or edge cases DewarModel, ) .join( @@ -163,36 +164,41 @@ def get_pucks_at_beamline(slot_id: int, db: Session) -> List[PuckWithTellPositio ) .join(DewarModel, PuckModel.dewar_id == DewarModel.id, isouter=True) .filter(PuckModel.dewar_id.in_(dewar_ids)) + .distinct() # Ensure no duplicates .all() ) # Prepare the results - results = [] - for puck, event_type, tell_position, dewar in pucks_with_latest_events: - dewar_name = dewar_map.get(puck.dewar_id, "Unknown") + results = {} + for ( + puck, + event_type, + tell_position, + event_timestamp, + dewar, + ) in pucks_with_latest_events: + dewar_name = dewar_map.get(puck.dewar_id) pgroup = dewar_pgroups.get(puck.dewar_id) - # For pucks with no events or whose latest event is "puck_removed", set - # tell_position to None + # If the event is None or explicitly a "puck_removed", set `tell_position=None` if event_type is None or event_type == "puck_removed": tell_position = None - results.append( - PuckWithTellPosition( - id=puck.id, - pgroup=pgroup, - puck_name=puck.puck_name, - puck_type=puck.puck_type, - puck_location_in_dewar=int(puck.puck_location_in_dewar) - if puck.puck_location_in_dewar - else None, - dewar_id=puck.dewar_id, - dewar_name=dewar_name, - tell_position=tell_position, - ) + # Always replace results since we are processing the latest event + results[puck.id] = PuckWithTellPosition( + id=puck.id, + pgroup=pgroup, + puck_name=puck.puck_name, + puck_type=puck.puck_type, + puck_location_in_dewar=int(puck.puck_location_in_dewar) + if puck.puck_location_in_dewar + else None, + dewar_id=puck.dewar_id, + dewar_name=dewar_name, + tell_position=tell_position, # Respect if `None` is explicitly set ) - return results + return list(results.values()) @router.get("/", response_model=List[PuckSchema]) @@ -269,7 +275,7 @@ async def set_tell_positions( tell=None, # Nullify the `tell` for removal tell_position=None, event_type="puck_removed", - timestamp=datetime.utcnow(), + timestamp=datetime.now(), ) db.add(remove_event) @@ -309,9 +315,8 @@ async def set_tell_positions( puck.id: db.query(PuckEventModel) .filter( PuckEventModel.puck_id == puck.id, - PuckEventModel.event_type == "tell_position_set", ) - .order_by(PuckEventModel.timestamp.desc()) + .order_by(PuckEventModel.id.desc()) .first() for puck in pucks_at_beamline } @@ -358,7 +363,7 @@ async def set_tell_positions( tell=None, tell_position=None, event_type="puck_removed", - timestamp=datetime.utcnow(), + timestamp=datetime.now(), ) db.add(remove_event) @@ -368,7 +373,7 @@ async def set_tell_positions( tell=tell, tell_position=new_position, event_type="tell_position_set", - timestamp=datetime.utcnow(), + timestamp=datetime.now(), ) db.add(new_event) @@ -409,7 +414,7 @@ async def set_tell_positions( tell=None, tell_position=None, event_type="puck_removed", - timestamp=datetime.utcnow(), + timestamp=datetime.now(), ) db.add(remove_event) results.append( @@ -436,13 +441,23 @@ async def set_tell_positions( @router.get("/with-tell-position", response_model=List[PuckWithTellPosition]) -async def get_pucks_with_tell_position(db: Session = Depends(get_db)): +async def get_pucks_with_tell_position( + tell: str, # Specify tell as a query parameter + db: Session = Depends(get_db), +): """ Retrieve all pucks with a valid `tell_position` set (non-null), - their associated samples, and the latest `tell_position` value (if any). - Only include pucks when their latest event has a `tell_position` - set and an `event_type` matching "tell_position_set". + their associated samples, and the latest `tell_position` value (if any), + filtered by a specific `tell`. """ + # Validate the incoming `tell` value + try: + validate_tell(tell) # Ensure `tell` is valid using predefined valid options + except ValueError as error: + raise HTTPException( + status_code=400, detail=str(error) + ) # Raise error for invalid tells + # Step 1: Prepare a subquery to fetch the latest event timestamp for each puck. latest_event_subquery = ( db.query( @@ -471,6 +486,7 @@ async def get_pucks_with_tell_position(db: Session = Depends(get_db)): .filter( PuckEventModel.event_type == "tell_position_set" ) # Only include relevant event types + .filter(PuckEventModel.tell == tell) # Filter by the specific `tell` variable .all() ) diff --git a/pyproject.toml b/pyproject.toml index e7e554c..5be7d25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "aareDB" -version = "0.1.0a20" +version = "0.1.0a21" description = "Backend for next gen sample management system" authors = [{name = "Guillaume Gotthard", email = "guillaume.gotthard@psi.ch"}] license = {text = "MIT"}