from fastapi import APIRouter, HTTPException, Depends from sqlalchemy.orm import Session from typing import List from app.models import Dewar as DewarModel, Slot as SlotModel, LogisticsEvent as LogisticsEventModel from app.schemas import LogisticsEventCreate, Slot as SlotSchema, Dewar as DewarSchema from app.database import get_db import logging from datetime import datetime, timedelta router = APIRouter() logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def calculate_time_until_refill(last_refill: datetime) -> int: refill_interval = timedelta(hours=24) # Example interval now = datetime.now() time_until_next_refill = last_refill + refill_interval - now return int(time_until_next_refill.total_seconds()) @router.get("/slots", response_model=List[SlotSchema]) async def get_all_slots(db: Session = Depends(get_db)): slots = db.query(SlotModel).all() slots_with_refill_time = [] for slot in slots: slot_data = SlotSchema( id=slot.id, qr_code=slot.qr_code, label=slot.label, qr_base=slot.qr_base, occupied=slot.occupied, needs_refill=slot.needs_refill, last_refill=slot.last_refill, time_until_refill=calculate_time_until_refill(slot.last_refill), dewar_unique_id=slot.dewar_unique_id, dewar_name=slot.dewar.dewar_name if slot.dewar else None ) slots_with_refill_time.append(slot_data) return slots_with_refill_time @router.get("/dewars", response_model=List[DewarSchema]) async def get_all_dewars(db: Session = Depends(get_db)): dewars = db.query(DewarModel).all() return dewars @router.get("/dewar/{unique_id}", response_model=DewarSchema) async def get_dewar_by_unique_id(unique_id: str, db: Session = Depends(get_db)): logger.info(f"Received request for dewar with unique_id: {unique_id}") dewar = db.query(DewarModel).filter(DewarModel.unique_id == unique_id.strip()).first() if not dewar: logger.warning(f"Dewar with unique_id '{unique_id}' not found.") raise HTTPException(status_code=404, detail="Dewar not found") logger.info(f"Returning dewar: {dewar}") return dewar @router.post("/dewar/scan", response_model=dict) async def scan_dewar(event_data: LogisticsEventCreate, db: Session = Depends(get_db)): dewar_qr_code = event_data.dewar_qr_code location_qr_code = event_data.location_qr_code transaction_type = event_data.transaction_type print(f"Scanning dewar {dewar_qr_code} for slot {location_qr_code} with transaction type {transaction_type}") dewar = db.query(DewarModel).filter(DewarModel.unique_id == dewar_qr_code).first() if not dewar: raise HTTPException(status_code=404, detail="Dewar not found") slot = db.query(SlotModel).filter(SlotModel.qr_code == location_qr_code).first() if transaction_type == 'incoming': if not slot or slot.occupied: raise HTTPException(status_code=400, detail="Slot not found or already occupied") print(f"Associating dewar {dewar.unique_id} with slot {slot.qr_code}") slot.dewar_unique_id = dewar.unique_id # Properly associate with the unique_id slot.occupied = True elif transaction_type == 'outgoing': if not slot or not slot.occupied or slot.dewar_unique_id != dewar.unique_id: raise HTTPException(status_code=400, detail="Slot not found or dewar not associated with slot") print(f"Disassociating dewar {dewar.unique_id} from slot {slot.qr_code}") slot.dewar_unique_id = None # Remove the association slot.occupied = False log_event(db, dewar.id, slot.id if slot else None, transaction_type) db.commit() return {"message": "Status updated successfully"} def log_event(db: Session, dewar_id: int, slot_id: int, event_type: str): new_event = LogisticsEventModel(dewar_id=dewar_id, slot_id=slot_id, event_type=event_type) db.add(new_event) db.commit() @router.post("/dewar/refill", response_model=dict) async def refill_dewar(qr_code: str, db: Session = Depends(get_db)): dewar = db.query(DewarModel).filter(DewarModel.unique_id == qr_code).first() if not dewar: raise HTTPException(status_code=404, detail="Dewar not found") # Process refill dewar.last_refill = datetime.now() # Calculate and update time until next refill time_until_refill_seconds = calculate_time_until_refill(dewar.last_refill) db.query(SlotModel).filter(SlotModel.dewar_unique_id == dewar.unique_id).update( {'time_until_refill': time_until_refill_seconds}) new_event = LogisticsEventModel( dewar_id=dewar.id, slot_id=None, # No specific slot, as it's a refill event event_type="refill", action_details=f"{dewar.unique_id} refilled" ) db.add(new_event) db.commit() return {"message": "Dewar refilled successfully"}