now associating a dewar to a slot
This commit is contained in:
parent
48fd2c3a7c
commit
fa1e9c86b8
@ -86,6 +86,7 @@ class Dewar(Base):
|
|||||||
|
|
||||||
dewar_type = relationship("DewarType")
|
dewar_type = relationship("DewarType")
|
||||||
dewar_serial_number = relationship("DewarSerialNumber")
|
dewar_serial_number = relationship("DewarSerialNumber")
|
||||||
|
slot = relationship("Slot", back_populates="dewar")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def number_of_pucks(self) -> int:
|
def number_of_pucks(self) -> int:
|
||||||
@ -144,6 +145,9 @@ class Slot(Base):
|
|||||||
needs_refill = Column(Boolean, default=False)
|
needs_refill = Column(Boolean, default=False)
|
||||||
last_refill = Column(DateTime, default=datetime.utcnow)
|
last_refill = Column(DateTime, default=datetime.utcnow)
|
||||||
time_until_refill = Column(Integer) # store as total seconds
|
time_until_refill = Column(Integer) # store as total seconds
|
||||||
|
dewar_unique_id = Column(String, ForeignKey('dewars.unique_id'), nullable=True) # Added field
|
||||||
|
dewar = relationship("Dewar", back_populates="slot")
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def calculate_time_until_refill(self):
|
def calculate_time_until_refill(self):
|
||||||
@ -151,6 +155,7 @@ class Slot(Base):
|
|||||||
return self.last_refill + self.time_until_refill - datetime.utcnow()
|
return self.last_refill + self.time_until_refill - datetime.utcnow()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class LogisticsEvent(Base):
|
class LogisticsEvent(Base):
|
||||||
__tablename__ = 'logistics_events'
|
__tablename__ = 'logistics_events'
|
||||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||||
@ -158,4 +163,5 @@ class LogisticsEvent(Base):
|
|||||||
event_type = Column(String, nullable=False)
|
event_type = Column(String, nullable=False)
|
||||||
timestamp = Column(DateTime, default=datetime.utcnow)
|
timestamp = Column(DateTime, default=datetime.utcnow)
|
||||||
|
|
||||||
dewar = relationship("Dewar", back_populates="events")
|
dewar = relationship("Dewar", back_populates="events")
|
||||||
|
slot_id = Column(String, ForeignKey('slots.id'), nullable=True)
|
@ -1,22 +1,42 @@
|
|||||||
from fastapi import APIRouter, HTTPException, Depends
|
from fastapi import APIRouter, HTTPException, Depends
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from app.models import Dewar as DewarModel, Slot as SlotModel, LogisticsEvent as LogisticsEventModel
|
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.schemas import LogisticsEventCreate, Slot as SlotSchema, Dewar as DewarSchema
|
||||||
from app.database import get_db
|
from app.database import get_db
|
||||||
import logging
|
import logging
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
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])
|
@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).all()
|
slots = db.query(SlotModel).all()
|
||||||
return slots
|
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])
|
@router.get("/dewars", response_model=List[DewarSchema])
|
||||||
async def get_all_dewars(db: Session = Depends(get_db)):
|
async def get_all_dewars(db: Session = Depends(get_db)):
|
||||||
@ -39,20 +59,25 @@ async def scan_dewar(event_data: LogisticsEventCreate, db: Session = Depends(get
|
|||||||
location_qr_code = event_data.location_qr_code
|
location_qr_code = event_data.location_qr_code
|
||||||
transaction_type = event_data.transaction_type
|
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()
|
dewar = db.query(DewarModel).filter(DewarModel.unique_id == dewar_qr_code).first()
|
||||||
if not dewar:
|
if not dewar:
|
||||||
raise HTTPException(status_code=404, detail="Dewar not found")
|
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||||
|
|
||||||
slot = db.query(SlotModel).filter(SlotModel.qr_code == location_qr_code).first()
|
slot = db.query(SlotModel).filter(SlotModel.qr_code == location_qr_code).first()
|
||||||
|
|
||||||
if transaction_type == 'incoming':
|
if transaction_type == 'incoming':
|
||||||
if not slot or slot.occupied:
|
if not slot or slot.occupied:
|
||||||
raise HTTPException(status_code=400, detail="Slot not found or already occupied")
|
raise HTTPException(status_code=400, detail="Slot not found or already occupied")
|
||||||
slot.dewar_id = dewar.id
|
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
|
slot.occupied = True
|
||||||
elif transaction_type == 'outgoing':
|
elif transaction_type == 'outgoing':
|
||||||
if not slot or not slot.occupied or slot.dewar_id != dewar.id:
|
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")
|
raise HTTPException(status_code=400, detail="Slot not found or dewar not associated with slot")
|
||||||
slot.dewar_id = None
|
print(f"Disassociating dewar {dewar.unique_id} from slot {slot.qr_code}")
|
||||||
|
slot.dewar_unique_id = None # Remove the association
|
||||||
slot.occupied = False
|
slot.occupied = False
|
||||||
|
|
||||||
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)
|
||||||
|
@ -281,11 +281,13 @@ class Slot(BaseModel):
|
|||||||
id: str
|
id: str
|
||||||
qr_code: str
|
qr_code: str
|
||||||
label: str
|
label: str
|
||||||
qr_base: str
|
qr_base: Optional[str]
|
||||||
occupied: bool
|
occupied: bool
|
||||||
needs_refill: bool
|
needs_refill: bool
|
||||||
last_refill: datetime
|
last_refill: datetime
|
||||||
time_until_refill: str
|
time_until_refill: int # Can't be Optional
|
||||||
|
dewar_unique_id: Optional[str] # Ensure this field exists
|
||||||
|
dewar_name: Optional[str] = None # Optional for convenience
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
@ -31,16 +31,11 @@ interface StorageProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot }) => {
|
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot }) => {
|
||||||
const [highlightedSlot, setHighlightedSlot] = useState<SlotData | null>(null);
|
|
||||||
|
|
||||||
const handleSlotSelect = (slot: SlotData) => {
|
const handleSlotSelect = (slot: SlotData) => {
|
||||||
setHighlightedSlot(slot);
|
|
||||||
onSelectSlot(slot);
|
onSelectSlot(slot);
|
||||||
console.log('Selected slot:', slot);
|
console.log('Selected slot:', slot);
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("Rendering Storage Component with name:", name);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StorageContainer>
|
<StorageContainer>
|
||||||
<Typography variant="h5">{name} Slots</Typography>
|
<Typography variant="h5">{name} Slots</Typography>
|
||||||
@ -54,11 +49,6 @@ const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSele
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</StorageWrapper>
|
</StorageWrapper>
|
||||||
{highlightedSlot && (
|
|
||||||
<Typography variant="subtitle1">
|
|
||||||
Selected Slot: {highlightedSlot.label}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</StorageContainer>
|
</StorageContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user