can now return the dewar to its slot

This commit is contained in:
GotthardG
2024-11-28 10:09:28 +01:00
parent fbb868e255
commit a42124a56f
2 changed files with 35 additions and 43 deletions

View File

@ -87,6 +87,7 @@ class Dewar(Base):
dewar_serial_number = relationship("DewarSerialNumber") dewar_serial_number = relationship("DewarSerialNumber")
slot = relationship("Slot", back_populates="dewar") slot = relationship("Slot", back_populates="dewar")
events = relationship("LogisticsEvent", back_populates="dewar") events = relationship("LogisticsEvent", back_populates="dewar")
beamline_location = None
@property @property
def number_of_pucks(self) -> int: def number_of_pucks(self) -> int:

View File

@ -1,4 +1,5 @@
from fastapi import APIRouter, HTTPException, Depends from fastapi import APIRouter, HTTPException, Depends
from pydantic import ValidationError
from sqlalchemy.orm import Session, joinedload from sqlalchemy.orm import Session, joinedload
from typing import List, Optional from typing import List, Optional
from ..models import Dewar as DewarModel, Slot as SlotModel, LogisticsEvent as LogisticsEventModel from ..models import Dewar as DewarModel, Slot as SlotModel, LogisticsEvent as LogisticsEventModel
@ -24,55 +25,46 @@ def calculate_time_until_refill(last_refill: Optional[datetime], refill_interval
return max(0, int(time_until_next_refill.total_seconds())) return max(0, int(time_until_next_refill.total_seconds()))
@router.post("/dewars/retrieve", response_model=DewarSchema) @router.post("/dewars/return", response_model=DewarSchema)
async def retrieve_or_return_dewar(data: LogisticsEventCreate, db: Session = Depends(get_db)): async def return_to_storage(data: LogisticsEventCreate, db: Session = Depends(get_db)):
logger.info(f"Received data for retrieve_or_return_dewar: {data}") logger.info(f"Returning dewar to storage: {data.dewar_qr_code} at location {data.location_qr_code}")
dewar = db.query(DewarModel).filter(DewarModel.unique_id == data.dewar_qr_code).first()
if not dewar:
raise HTTPException(status_code=404, detail="Dewar not found")
# Fetch the associated slot if it exists try:
slot = db.query(SlotModel).filter(SlotModel.qr_code == data.location_qr_code).first() # Log the incoming payload
if not slot: logger.info("Received payload: %s", data.json())
raise HTTPException(status_code=404, detail="Slot not found")
# Check the last event for this dewar to determine the next action dewar = db.query(DewarModel).filter(DewarModel.unique_id == data.dewar_qr_code).first()
last_event = db.query(LogisticsEventModel).filter( if not dewar:
LogisticsEventModel.dewar_id == dewar.id logger.error(f"Dewar not found for unique ID: {data.dewar_qr_code}")
).order_by(LogisticsEventModel.timestamp.desc()).first() raise HTTPException(status_code=404, detail="Dewar not found")
if last_event and last_event.event_type == "retrieved": slot = db.query(SlotModel).filter(SlotModel.qr_code == data.location_qr_code).first()
# Create a 'returned' event if the last event was 'retrieved' if not slot:
new_event = LogisticsEventModel( logger.error(f"Slot not found for QR code: {data.location_qr_code}")
dewar_id=dewar.id, raise HTTPException(status_code=404, detail="Slot not found")
slot_id=slot.id,
event_type="returned",
timestamp=datetime.now(),
)
dewar.last_retrieved_timestamp = None
# Update the location to the slot if slot.occupied and slot.dewar_unique_id != data.dewar_qr_code:
logger.error(f"Slot {data.location_qr_code} is already occupied by another dewar")
raise HTTPException(status_code=400, detail="Selected slot is already occupied by another dewar")
# Update slot with dewar information
slot.dewar_unique_id = dewar.unique_id slot.dewar_unique_id = dewar.unique_id
slot.occupied = True slot.occupied = True
dewar.last_retrieved_timestamp = None
# Log the event
log_event(db, dewar.id, slot.id, "returned")
db.commit() db.commit()
logger.info(f"Dewar {dewar.unique_id} returned to slot {slot.qr_code} successfully.")
else:
# Create a 'retrieved' event
new_event = LogisticsEventModel(
dewar_id=dewar.id,
slot_id=None,
event_type="retrieved",
timestamp=datetime.now(),
)
dewar.last_retrieved_timestamp = new_event.timestamp.isoformat()
logger.info(f"Dewar {dewar.unique_id} retrieved successfully.")
db.add(new_event)
db.commit()
db.refresh(dewar)
return dewar
logger.info(f"Dewar {data.dewar_qr_code} successfully returned to storage slot {slot.qr_code}.")
db.refresh(dewar)
return dewar
except ValidationError as e:
logger.error(f"Validation error: {e.json()}")
raise HTTPException(status_code=400, detail="Invalid payload")
except Exception as e:
logger.error(f"Unexpected error: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
@router.post("/dewar/scan", response_model=dict) @router.post("/dewar/scan", response_model=dict)
async def scan_dewar(event_data: LogisticsEventCreate, db: Session = Depends(get_db)): async def scan_dewar(event_data: LogisticsEventCreate, db: Session = Depends(get_db)):
@ -109,13 +101,12 @@ async def scan_dewar(event_data: LogisticsEventCreate, db: Session = Depends(get
logger.error(f"Beamline location not found: {location_qr_code}") logger.error(f"Beamline location not found: {location_qr_code}")
raise HTTPException(status_code=400, detail="Beamline location not found") raise HTTPException(status_code=400, detail="Beamline location not found")
dewar.beamline_location = location_qr_code dewar.beamline_location = location_qr_code
logger.info(f"Dewar {dewar_qr_code} assigned to beamline {location_qr_code}")
log_event(db, dewar.id, slot.id if slot else None, transaction_type) log_event(db, dewar.id, slot.id if slot else None, transaction_type)
db.commit() db.commit()
return {"message": "Status updated successfully"} return {"message": "Status updated successfully"}
@router.get("/slots", response_model=List[SlotSchema]) @router.get("/slots", response_model=List[SlotSchema])
async def get_all_slots(db: Session = Depends(get_db)): async def get_all_slots(db: Session = Depends(get_db)):
slots = db.query(SlotModel).options(joinedload(SlotModel.dewar)).all() slots = db.query(SlotModel).options(joinedload(SlotModel.dewar)).all()