can now return the dewar to its slot
This commit is contained in:
@ -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:
|
||||||
|
@ -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()
|
||||||
|
Reference in New Issue
Block a user