diff --git a/backend/app/models.py b/backend/app/models.py index 09bd60e..96a80e2 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -1,8 +1,7 @@ -from sqlalchemy import Column, Integer, String, Date, ForeignKey, JSON, Interval, DateTime, Boolean +from sqlalchemy import Column, Integer, String, Date, ForeignKey, JSON, DateTime, Boolean from sqlalchemy.orm import relationship from .database import Base -from datetime import datetime, timedelta -import uuid +from datetime import datetime class Shipment(Base): @@ -118,6 +117,7 @@ class Puck(Base): dewar_id = Column(Integer, ForeignKey('dewars.id')) dewar = relationship("Dewar", back_populates="pucks") samples = relationship("Sample", back_populates="puck") + events = relationship("PuckEvent", back_populates="puck") class Sample(Base): @@ -168,13 +168,13 @@ class SampleEvent(Base): sample = relationship("Sample", back_populates="events") -#class PuckEvent(Base): -# __tablename__ = "sample_events" -# -# id = Column(Integer, primary_key=True, index=True) -# puck_id = Column(Integer, ForeignKey('puck.id')) -# tell_position = Column(String(255), nullable=True) -# event_type = Column(String(255), index=True) -# timestamp = Column(DateTime, default=datetime.utcnow) -# -# sample = relationship("Sample", back_populates="events") +class PuckEvent(Base): + __tablename__ = "puck_events" + + id = Column(Integer, primary_key=True, index=True) + puck_id = Column(Integer, ForeignKey('pucks.id')) + tell_position = Column(String(255), nullable=True) + event_type = Column(String(255), index=True) + timestamp = Column(DateTime, default=datetime.utcnow) + + puck = relationship("Puck", back_populates="events") \ No newline at end of file diff --git a/backend/app/routers/puck.py b/backend/app/routers/puck.py index 91e7c39..1c4e623 100644 --- a/backend/app/routers/puck.py +++ b/backend/app/routers/puck.py @@ -2,9 +2,10 @@ from fastapi import APIRouter, HTTPException, status, Depends from sqlalchemy.orm import Session from typing import List import uuid -from app.schemas import Puck as PuckSchema, PuckCreate, PuckUpdate -from app.models import Puck as PuckModel, Sample as SampleModel +from app.schemas import Puck as PuckSchema, PuckCreate, PuckUpdate, SetTellPosition, PuckEventCreate +from app.models import Puck as PuckModel, Sample as SampleModel, PuckEvent as PuckEventModel from app.dependencies import get_db +from datetime import datetime router = APIRouter() @@ -61,3 +62,43 @@ async def delete_puck(puck_id: str, db: Session = Depends(get_db)): db.delete(puck) db.commit() return + +@router.put("/{puck_id}/tell_position", status_code=status.HTTP_200_OK) +async def set_tell_position( + puck_id: int, + request: SetTellPosition, + db: Session = Depends(get_db) +): + # Get the requested tell_position + tell_position = request.tell_position + + # Define valid positions + valid_positions = [f"{letter}{num}" for letter in "ABCDEF" for num in range(1, 6)] + ["null", None] + + # Validate tell_position + if tell_position not in valid_positions: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Invalid tell_position value. Must be one of {valid_positions}.", + ) + + # Set the correct tell_position logic + actual_position = None if tell_position in ["null", None] else tell_position + + # Create a new PuckEvent (always a new event, even with null/None) + new_puck_event = PuckEventModel( + puck_id=puck_id, + tell_position=actual_position, # Null for disassociation, else the valid position + event_type="tell_position_set", # Example event type + timestamp=datetime.utcnow(), + ) + db.add(new_puck_event) + db.commit() + db.refresh(new_puck_event) + + # Send the response + return { + "message": "New tell position event created successfully", + "tell_position": new_puck_event.tell_position, + "timestamp": new_puck_event.timestamp, + } diff --git a/backend/app/schemas.py b/backend/app/schemas.py index bee12de..ee39525 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -306,4 +306,14 @@ class SlotSchema(BaseModel): local_contact: Optional[str] class Config: - from_attributes = True \ No newline at end of file + from_attributes = True + +class PuckEventCreate(BaseModel): + event_type: str + +class SetTellPosition(BaseModel): + tell_position: str = Field( + ..., + pattern="^[A-F][1-5]$|^null$|^None$", # Use 'pattern' instead of 'regex' + description="Valid values are A1-A5, B1-B5, ..., F1-F5, or null." + )