Refactor set_tell_positions logic with updated rules.
Revised the set_tell_positions endpoint to handle updated business rules for puck positioning. Improved event handling to ensure proper nullification, updates, and removal of tell_positions based on the provided payload. Enhanced query performance and normalized puck name processing for consistency.
This commit is contained in:
parent
fb5e930096
commit
0fdd5e54b7
@ -1,6 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from fastapi import APIRouter, HTTPException, status, Depends
|
from fastapi import APIRouter, HTTPException, status, Depends
|
||||||
from sqlalchemy.orm import Session, load_only
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy.sql import func
|
from sqlalchemy.sql import func
|
||||||
from typing import List
|
from typing import List
|
||||||
import uuid
|
import uuid
|
||||||
@ -16,6 +16,7 @@ from app.schemas import (
|
|||||||
from app.models import (
|
from app.models import (
|
||||||
Puck as PuckModel,
|
Puck as PuckModel,
|
||||||
PuckEvent as PuckEventModel,
|
PuckEvent as PuckEventModel,
|
||||||
|
Sample as SampleModel,
|
||||||
Slot as SlotModel,
|
Slot as SlotModel,
|
||||||
LogisticsEvent as LogisticsEventModel,
|
LogisticsEvent as LogisticsEventModel,
|
||||||
Dewar as DewarModel,
|
Dewar as DewarModel,
|
||||||
@ -45,31 +46,8 @@ async def get_pucks(db: Session = Depends(get_db)):
|
|||||||
|
|
||||||
@router.put("/set-tell-positions", status_code=status.HTTP_200_OK)
|
@router.put("/set-tell-positions", status_code=status.HTTP_200_OK)
|
||||||
async def set_tell_positions(
|
async def set_tell_positions(
|
||||||
pucks: List[SetTellPosition], # Accept a validated Pydantic model
|
pucks: List[SetTellPosition], db: Session = Depends(get_db)
|
||||||
db: Session = Depends(get_db),
|
|
||||||
):
|
):
|
||||||
"""
|
|
||||||
Set tell positions for multiple pucks with updated rules.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
pucks (List[SetTellPosition]): A list including puck_name,
|
|
||||||
segment, and puck_in_segment.
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
1. If a puck already has a tell_position matching the payload,
|
|
||||||
it is ignored (no new timestamps).
|
|
||||||
2. If a puck is assigned a different position,
|
|
||||||
set the new position while nullifying the previous.
|
|
||||||
3. Pucks that have a last `tell_position_set` event with
|
|
||||||
a non-null `tell_position` but
|
|
||||||
are not in the payload will get
|
|
||||||
a `"puck_removed"` event nullifying their position.
|
|
||||||
4. If the last event for a puck is already null
|
|
||||||
or it has no events, nothing is added or updated.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List[dict]: Status information for processed and ignored pucks.
|
|
||||||
"""
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
# Helper function to normalize puck names for database querying
|
# Helper function to normalize puck names for database querying
|
||||||
@ -82,10 +60,8 @@ async def set_tell_positions(
|
|||||||
detail="Payload cannot be empty. Provide at least one puck.",
|
detail="Payload cannot be empty. Provide at least one puck.",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Normalize payload puck names
|
# Retrieve all pucks in the database with their most recent
|
||||||
input_puck_names = {normalize_puck_name(p.puck_name): p for p in pucks}
|
# `tell_position_set` event
|
||||||
|
|
||||||
# Retrieve all pucks in the database
|
|
||||||
all_pucks_with_last_event = (
|
all_pucks_with_last_event = (
|
||||||
db.query(PuckModel, PuckEventModel)
|
db.query(PuckModel, PuckEventModel)
|
||||||
.outerjoin(PuckEventModel, PuckEventModel.puck_id == PuckModel.id)
|
.outerjoin(PuckEventModel, PuckEventModel.puck_id == PuckModel.id)
|
||||||
@ -97,9 +73,12 @@ async def set_tell_positions(
|
|||||||
# Dictionary mapping each puck's ID to its latest event
|
# Dictionary mapping each puck's ID to its latest event
|
||||||
last_events = {}
|
last_events = {}
|
||||||
for puck, last_event in all_pucks_with_last_event:
|
for puck, last_event in all_pucks_with_last_event:
|
||||||
if puck.id not in last_events:
|
if puck.id not in last_events: # Only store the latest event for each puck
|
||||||
last_events[puck.id] = last_event
|
last_events[puck.id] = last_event
|
||||||
|
|
||||||
|
# Track processed puck IDs to avoid double-processing
|
||||||
|
processed_pucks = set()
|
||||||
|
|
||||||
# Process pucks provided in the payload
|
# Process pucks provided in the payload
|
||||||
for puck_data in pucks:
|
for puck_data in pucks:
|
||||||
try:
|
try:
|
||||||
@ -108,8 +87,6 @@ async def set_tell_positions(
|
|||||||
new_position = (
|
new_position = (
|
||||||
puck_data.tell_position
|
puck_data.tell_position
|
||||||
) # Combined from segment + puck_in_segment
|
) # Combined from segment + puck_in_segment
|
||||||
|
|
||||||
# Normalize puck name
|
|
||||||
normalized_name = normalize_puck_name(puck_name)
|
normalized_name = normalize_puck_name(puck_name)
|
||||||
|
|
||||||
# Find puck in the database
|
# Find puck in the database
|
||||||
@ -125,10 +102,13 @@ async def set_tell_positions(
|
|||||||
if not puck:
|
if not puck:
|
||||||
raise ValueError(f"Puck with name '{puck_name}' not found.")
|
raise ValueError(f"Puck with name '{puck_name}' not found.")
|
||||||
|
|
||||||
|
# Mark this puck as processed
|
||||||
|
processed_pucks.add(puck.id)
|
||||||
|
|
||||||
# Query the last event for this puck
|
# Query the last event for this puck
|
||||||
last_event = last_events.get(puck.id)
|
last_event = last_events.get(puck.id)
|
||||||
|
|
||||||
# Rule 1: Skip if the last event's tell_position matches the new position
|
# Rule 1: Skip if the last event's `tell_position` matches the new position
|
||||||
if last_event and last_event.tell_position == new_position:
|
if last_event and last_event.tell_position == new_position:
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
@ -140,18 +120,17 @@ async def set_tell_positions(
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Rule 2: If the last tell_position is not None, nullify it with a
|
# Rule 2: Add a "puck_removed" event if the last tell_position is not None
|
||||||
# puck_removed event
|
|
||||||
if last_event and last_event.tell_position is not None:
|
if last_event and last_event.tell_position is not None:
|
||||||
remove_event = PuckEventModel(
|
remove_event = PuckEventModel(
|
||||||
puck_id=puck.id,
|
puck_id=puck.id,
|
||||||
tell_position=None,
|
tell_position=None,
|
||||||
event_type="puck_removed", # Set event_type to "puck_removed"
|
event_type="puck_removed", # Event type set to "puck_removed"
|
||||||
timestamp=datetime.utcnow(),
|
timestamp=datetime.utcnow(),
|
||||||
)
|
)
|
||||||
db.add(remove_event)
|
db.add(remove_event)
|
||||||
|
|
||||||
# Add a new event with the updated tell_position
|
# Add a new "tell_position_set" event
|
||||||
if new_position:
|
if new_position:
|
||||||
new_event = PuckEventModel(
|
new_event = PuckEventModel(
|
||||||
puck_id=puck.id,
|
puck_id=puck.id,
|
||||||
@ -160,6 +139,7 @@ async def set_tell_positions(
|
|||||||
timestamp=datetime.utcnow(),
|
timestamp=datetime.utcnow(),
|
||||||
)
|
)
|
||||||
db.add(new_event)
|
db.add(new_event)
|
||||||
|
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"puck_name": puck.puck_name,
|
"puck_name": puck.puck_name,
|
||||||
@ -172,50 +152,51 @@ async def set_tell_positions(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Commit changes after processing each puck
|
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Handle individual puck errors
|
# Handle individual puck errors
|
||||||
results.append({"puck_name": puck_data.puck_name, "error": str(e)})
|
results.append({"puck_name": puck_data.puck_name, "error": str(e)})
|
||||||
|
|
||||||
# Process pucks not included in the payload but present in the DB
|
# Process pucks not included in the payload but present in the database
|
||||||
for puck_id, last_event in last_events.items():
|
for puck_id, last_event in last_events.items():
|
||||||
|
# Skip pucks already processed in the previous loop
|
||||||
|
if puck_id in processed_pucks:
|
||||||
|
continue
|
||||||
|
|
||||||
puck = db.query(PuckModel).filter(PuckModel.id == puck_id).first()
|
puck = db.query(PuckModel).filter(PuckModel.id == puck_id).first()
|
||||||
normalized_name = normalize_puck_name(puck.puck_name)
|
if not puck:
|
||||||
|
continue
|
||||||
|
|
||||||
# Check if the puck is missing from the payload
|
# Skip if the last event's tell_position is already null
|
||||||
if (
|
if not last_event or last_event.tell_position is None:
|
||||||
normalized_name not in input_puck_names
|
continue
|
||||||
and last_event
|
|
||||||
and last_event.tell_position is not None
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
# Add a puck_removed event
|
|
||||||
remove_event = PuckEventModel(
|
|
||||||
puck_id=puck.id,
|
|
||||||
tell_position=None,
|
|
||||||
event_type="puck_removed", # Set event_type to "puck_removed"
|
|
||||||
timestamp=datetime.utcnow(),
|
|
||||||
)
|
|
||||||
db.add(remove_event)
|
|
||||||
|
|
||||||
# Append to results
|
try:
|
||||||
results.append(
|
# Add a "puck_removed" event
|
||||||
{
|
remove_event = PuckEventModel(
|
||||||
"puck_name": puck.puck_name,
|
puck_id=puck.id,
|
||||||
"removed_position": last_event.tell_position,
|
tell_position=None,
|
||||||
"status": "removed",
|
event_type="puck_removed", # Event type set to "puck_removed"
|
||||||
"message": "Puck is not in payload"
|
timestamp=datetime.utcnow(),
|
||||||
" and has been marked as removed from tell_position.",
|
)
|
||||||
}
|
db.add(remove_event)
|
||||||
)
|
|
||||||
|
|
||||||
db.commit()
|
results.append(
|
||||||
|
{
|
||||||
|
"puck_name": puck.puck_name,
|
||||||
|
"removed_position": last_event.tell_position,
|
||||||
|
"status": "removed",
|
||||||
|
"message": "Puck is not in payload and"
|
||||||
|
" has been marked as removed from tell_position.",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
db.commit()
|
||||||
# Handle errors for individual puck removal
|
|
||||||
results.append({"puck_name": puck.puck_name, "error": str(e)})
|
except Exception as e:
|
||||||
|
# Handle errors for individual puck removal
|
||||||
|
results.append({"puck_name": puck.puck_name, "error": str(e)})
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@ -299,14 +280,10 @@ async def get_last_tell_position(puck_id: str, db: Session = Depends(get_db)):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/slot/{slot_identifier}", response_model=List[dict])
|
@router.get("/slot/{slot_identifier}", response_model=List[PuckWithTellPosition])
|
||||||
async def get_pucks_by_slot(slot_identifier: str, db: Session = Depends(get_db)):
|
async def get_pucks_by_slot(slot_identifier: str, db: Session = Depends(get_db)):
|
||||||
"""
|
"""
|
||||||
Retrieve all pucks associated with all dewars linked to the given slot
|
Retrieve all pucks in a slot with their latest `tell_position`.
|
||||||
(by ID or keyword) via 'beamline' events.
|
|
||||||
|
|
||||||
- Accepts slot keywords like PXI, PXII, PXIII.
|
|
||||||
- Retrieves all dewars (and their names) associated with the slot.
|
|
||||||
"""
|
"""
|
||||||
# Map keywords to slot IDs
|
# Map keywords to slot IDs
|
||||||
slot_aliases = {
|
slot_aliases = {
|
||||||
@ -318,152 +295,162 @@ async def get_pucks_by_slot(slot_identifier: str, db: Session = Depends(get_db))
|
|||||||
"X06DA": 49,
|
"X06DA": 49,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if the slot identifier is an alias or ID
|
# Resolve slot ID or alias
|
||||||
try:
|
try:
|
||||||
slot_id = int(slot_identifier) # If the user provided a numeric ID
|
slot_id = int(slot_identifier)
|
||||||
alias = next(
|
|
||||||
(k for k, v in slot_aliases.items() if v == slot_id), slot_identifier
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
slot_id = slot_aliases.get(slot_identifier.upper()) # Try mapping alias
|
slot_id = slot_aliases.get(slot_identifier.upper())
|
||||||
alias = slot_identifier.upper() # Keep alias as-is for error messages
|
|
||||||
if not slot_id:
|
if not slot_id:
|
||||||
|
logger.error(f"Invalid slot alias: {slot_identifier}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=400,
|
status_code=400, detail=f"Invalid slot identifier: {slot_identifier}"
|
||||||
detail="Invalid slot identifier."
|
|
||||||
"Must be an ID or one of the following:"
|
|
||||||
"PXI, PXII, PXIII, X06SA, X10SA, X06DA.",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify that the slot exists
|
logger.info(f"Resolved slot identifier: {slot_identifier} to Slot ID: {slot_id}")
|
||||||
|
|
||||||
|
# Verify slot existence
|
||||||
slot = db.query(SlotModel).filter(SlotModel.id == slot_id).first()
|
slot = db.query(SlotModel).filter(SlotModel.id == slot_id).first()
|
||||||
if not slot:
|
if not slot:
|
||||||
|
logger.error(f"Slot not found: {slot_identifier}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404, detail=f"Slot not found for identifier '{alias}'."
|
status_code=404, detail=f"Slot not found for identifier {slot_identifier}"
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"Slot found: ID={slot.id}, Label={slot.label}")
|
# Fetch dewars in the slot
|
||||||
|
dewars = (
|
||||||
# Retrieve all beamline events associated with the slot
|
db.query(DewarModel)
|
||||||
beamline_events = (
|
.join(LogisticsEventModel, DewarModel.id == LogisticsEventModel.dewar_id)
|
||||||
db.query(LogisticsEventModel)
|
|
||||||
.filter(
|
.filter(
|
||||||
LogisticsEventModel.slot_id == slot_id,
|
LogisticsEventModel.slot_id == slot_id,
|
||||||
LogisticsEventModel.event_type == "beamline",
|
LogisticsEventModel.event_type == "beamline",
|
||||||
)
|
)
|
||||||
.order_by(LogisticsEventModel.timestamp.desc())
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
if not beamline_events:
|
|
||||||
logger.warning(f"No dewars associated to this beamline '{alias}'.")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=404, detail=f"No dewars found for the given beamline '{alias}'."
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(f"Found {len(beamline_events)} beamline events for slot_id={slot_id}.")
|
|
||||||
|
|
||||||
# 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 dewars:
|
if not dewars:
|
||||||
logger.warning(f"No dewars found for beamline '{alias}'.")
|
logger.warning(f"No dewars found for slot: {slot_identifier}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404, detail=f"No dewars found for beamline '{alias}'."
|
status_code=404, detail=f"No dewars found for slot {slot_identifier}"
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"Found {len(dewars)} dewars for beamline '{alias}'.")
|
logger.info(
|
||||||
|
f"Found dewars for slot {slot_identifier}: {[dewar.id for dewar in dewars]}"
|
||||||
|
)
|
||||||
|
|
||||||
# Create a mapping of dewar_id to dewar_name
|
dewar_ids = [dewar.id for dewar in dewars]
|
||||||
dewar_mapping = {dewar.id: dewar.dewar_name for dewar in dewars}
|
|
||||||
|
|
||||||
# Retrieve all pucks associated with the dewars
|
# Subquery to fetch the latest tell_position for each puck
|
||||||
puck_list = (
|
subquery = (
|
||||||
db.query(PuckModel)
|
db.query(
|
||||||
.filter(PuckModel.dewar_id.in_([dewar.id for dewar in dewars]))
|
PuckEventModel.puck_id,
|
||||||
|
func.max(PuckEventModel.timestamp).label("latest_event_time"),
|
||||||
|
)
|
||||||
|
.filter(PuckEventModel.event_type == "tell_position_set")
|
||||||
|
.group_by(PuckEventModel.puck_id)
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fetch pucks with their latest tell_position
|
||||||
|
pucks_with_positions = (
|
||||||
|
db.query(PuckModel, PuckEventModel.tell_position)
|
||||||
|
.outerjoin(subquery, subquery.c.puck_id == PuckModel.id)
|
||||||
|
.outerjoin(
|
||||||
|
PuckEventModel,
|
||||||
|
(PuckEventModel.puck_id == PuckModel.id)
|
||||||
|
& (PuckEventModel.timestamp == subquery.c.latest_event_time),
|
||||||
|
)
|
||||||
|
.filter(PuckModel.dewar_id.in_(dewar_ids))
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
if not puck_list:
|
# Log the results of the subquery and pucks fetched:
|
||||||
logger.warning(f"No pucks found for dewars associated with beamline '{alias}'.")
|
logger.debug(f"Results from subquery (tell_position): {pucks_with_positions}")
|
||||||
|
|
||||||
|
if not pucks_with_positions:
|
||||||
|
logger.warning(f"No pucks found for slot: {slot_identifier}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404,
|
status_code=404, detail=f"No pucks found for slot '{slot_identifier}'"
|
||||||
detail=f"No pucks found for dewars associated with beamline '{alias}'.",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"Found {len(puck_list)} pucks for beamline '{alias}'.")
|
# Prepare results:
|
||||||
|
results = []
|
||||||
|
for puck, tell_position in pucks_with_positions:
|
||||||
|
logger.debug(
|
||||||
|
f"Puck ID: {puck.id}, Name: {puck.puck_name},"
|
||||||
|
f" Tell Position: {tell_position}"
|
||||||
|
)
|
||||||
|
|
||||||
# Add the dewar_name to the output for each puck
|
# Prepare the PuckWithTellPosition instance
|
||||||
puck_output = [
|
results.append(
|
||||||
{
|
PuckWithTellPosition(
|
||||||
"id": puck.id,
|
id=puck.id,
|
||||||
"puck_name": puck.puck_name,
|
puck_name=puck.puck_name,
|
||||||
"puck_type": puck.puck_type,
|
puck_type=puck.puck_type,
|
||||||
"dewar_id": puck.dewar_id,
|
puck_location_in_dewar=str(puck.puck_location_in_dewar)
|
||||||
"dewar_name": dewar_mapping.get(puck.dewar_id), # Link dewar_name
|
if puck.puck_location_in_dewar
|
||||||
}
|
else None,
|
||||||
for puck in puck_list
|
dewar_id=puck.dewar_id,
|
||||||
]
|
tell_position=tell_position, # Latest tell_position from subquery
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Return the list of pucks with their associated dewar names
|
logger.info(f"Final response prepared for slot {slot_identifier}: {results}")
|
||||||
return puck_output
|
return results
|
||||||
|
|
||||||
|
|
||||||
class SampleModel:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/with-tell-position", response_model=List[PuckWithTellPosition])
|
@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(db: Session = Depends(get_db)):
|
||||||
"""
|
"""
|
||||||
Retrieve all pucks with a `tell_position` set (not null)
|
Retrieve all pucks with a `tell_position` set (not null),
|
||||||
and their associated samples.
|
their associated samples, and the latest `tell_position` value (if any).
|
||||||
"""
|
"""
|
||||||
# Query pucks with events where `tell_position` is not null
|
# Query pucks with their latest `tell_position_set` event where
|
||||||
pucks = (
|
# `tell_position` is not null
|
||||||
db.query(PuckModel)
|
pucks_with_events = (
|
||||||
|
db.query(PuckModel, PuckEventModel)
|
||||||
.join(PuckEventModel, PuckModel.id == PuckEventModel.puck_id)
|
.join(PuckEventModel, PuckModel.id == PuckEventModel.puck_id)
|
||||||
.filter(PuckEventModel.tell_position.isnot(None))
|
.filter(
|
||||||
.options(
|
PuckEventModel.tell_position.isnot(None)
|
||||||
load_only(
|
) # Ensure only non-null tell_positions
|
||||||
PuckModel.id,
|
.order_by(PuckEventModel.timestamp.desc()) # Get the most recent event
|
||||||
PuckModel.puck_name,
|
.distinct(PuckModel.id) # Ensure one row per puck (latest event is prioritized)
|
||||||
PuckModel.puck_type,
|
|
||||||
PuckModel.puck_location_in_dewar,
|
|
||||||
PuckModel.dewar_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
if not pucks:
|
if not pucks_with_events:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404,
|
status_code=404,
|
||||||
detail="No pucks with a `tell_position` found.",
|
detail="No pucks with a `tell_position` found.",
|
||||||
)
|
)
|
||||||
|
|
||||||
results = [
|
# Construct the response with pucks and their latest tell_position
|
||||||
PuckWithTellPosition(
|
results = []
|
||||||
id=int(puck.id), # Explicit casting
|
for puck, event in pucks_with_events:
|
||||||
puck_name=str(puck.puck_name),
|
# Retrieve associated samples for this puck
|
||||||
puck_type=str(puck.puck_type),
|
samples = db.query(SampleModel).filter(SampleModel.puck_id == puck.id).all()
|
||||||
puck_location_in_dewar=str(puck.puck_location_in_dewar)
|
|
||||||
if puck.puck_location_in_dewar
|
# Construct the response model
|
||||||
else None,
|
results.append(
|
||||||
dewar_id=int(puck.dewar_id),
|
PuckWithTellPosition(
|
||||||
samples=[
|
id=int(puck.id), # Explicit casting
|
||||||
Sample(
|
puck_name=str(puck.puck_name),
|
||||||
id=sample.id,
|
puck_type=str(puck.puck_type),
|
||||||
sample_name=sample.sample_name,
|
puck_location_in_dewar=str(puck.puck_location_in_dewar)
|
||||||
position=sample.position,
|
if puck.puck_location_in_dewar
|
||||||
)
|
else None,
|
||||||
for sample in db.query(SampleModel)
|
dewar_id=int(puck.dewar_id) if puck.dewar_id else None,
|
||||||
.filter(SampleModel.puck_id == puck.id)
|
samples=[
|
||||||
.all()
|
Sample(
|
||||||
],
|
id=sample.id,
|
||||||
|
sample_name=sample.sample_name,
|
||||||
|
position=sample.position,
|
||||||
|
)
|
||||||
|
for sample in samples
|
||||||
|
],
|
||||||
|
tell_position=str(event.tell_position)
|
||||||
|
if event
|
||||||
|
else None, # Include tell_position
|
||||||
|
)
|
||||||
)
|
)
|
||||||
for puck in pucks
|
|
||||||
]
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "aareDB"
|
name = "aareDB"
|
||||||
version = "0.1.0a12"
|
version = "0.1.0a13"
|
||||||
description = "Backend for next gen sample management system"
|
description = "Backend for next gen sample management system"
|
||||||
authors = [{name = "Guillaume Gotthard", email = "guillaume.gotthard@psi.ch"}]
|
authors = [{name = "Guillaume Gotthard", email = "guillaume.gotthard@psi.ch"}]
|
||||||
license = {text = "MIT"}
|
license = {text = "MIT"}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user