Feature enhancement

This commit is contained in:
2025-12-12 12:11:00 -05:00
parent 32ad7a793a
commit ab3319af06
12 changed files with 512 additions and 416 deletions

View File

@@ -5,7 +5,8 @@ Revises: 001_initial_schema
Create Date: 2025-12-12 12:00:00.000000
This migration adds a new table for tracking local flights (circuits, local, departure)
that don't require PPR submissions.
that don't require PPR submissions. Also adds etd and renames booked_out_dt to created_dt,
and departure_dt to departed_dt for consistency.
"""
from alembic import op
@@ -32,8 +33,9 @@ def upgrade() -> None:
sa.Column('flight_type', sa.Enum('LOCAL', 'CIRCUITS', 'DEPARTURE', name='localflighttype'), nullable=False),
sa.Column('status', sa.Enum('BOOKED_OUT', 'DEPARTED', 'LANDED', 'CANCELLED', name='localflightstatus'), nullable=False, server_default='BOOKED_OUT'),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('booked_out_dt', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('departure_dt', sa.DateTime(), nullable=True),
sa.Column('created_dt', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('etd', sa.DateTime(), nullable=True),
sa.Column('departed_dt', sa.DateTime(), nullable=True),
sa.Column('landed_dt', sa.DateTime(), nullable=True),
sa.Column('created_by', sa.String(length=16), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=False),
@@ -47,7 +49,8 @@ def upgrade() -> None:
op.create_index('idx_registration', 'local_flights', ['registration'])
op.create_index('idx_flight_type', 'local_flights', ['flight_type'])
op.create_index('idx_status', 'local_flights', ['status'])
op.create_index('idx_booked_out_dt', 'local_flights', ['booked_out_dt'])
op.create_index('idx_created_dt', 'local_flights', ['created_dt'])
op.create_index('idx_etd', 'local_flights', ['etd'])
op.create_index('idx_created_by', 'local_flights', ['created_by'])
# Create departures table for non-PPR departures to other airports
@@ -60,8 +63,9 @@ def upgrade() -> None:
sa.Column('out_to', sa.String(length=64), nullable=False),
sa.Column('status', sa.Enum('BOOKED_OUT', 'DEPARTED', 'CANCELLED', name='departuresstatus'), nullable=False, server_default='BOOKED_OUT'),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('booked_out_dt', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('departure_dt', sa.DateTime(), nullable=True),
sa.Column('created_dt', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('etd', sa.DateTime(), nullable=True),
sa.Column('departed_dt', sa.DateTime(), nullable=True),
sa.Column('created_by', sa.String(length=16), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=False),
sa.PrimaryKeyConstraint('id'),
@@ -73,7 +77,8 @@ def upgrade() -> None:
op.create_index('idx_dep_registration', 'departures', ['registration'])
op.create_index('idx_dep_out_to', 'departures', ['out_to'])
op.create_index('idx_dep_status', 'departures', ['status'])
op.create_index('idx_dep_booked_out_dt', 'departures', ['booked_out_dt'])
op.create_index('idx_dep_created_dt', 'departures', ['created_dt'])
op.create_index('idx_dep_etd', 'departures', ['etd'])
op.create_index('idx_dep_created_by', 'departures', ['created_by'])
# Create arrivals table for non-PPR arrivals from elsewhere

View File

@@ -132,7 +132,7 @@ async def update_departure_status(
"id": departure.id,
"registration": departure.registration,
"status": departure.status.value,
"departure_dt": departure.departure_dt.isoformat() if departure.departure_dt else None
"departed_dt": departure.departed_dt.isoformat() if departure.departed_dt else None
}
})

View File

@@ -48,7 +48,7 @@ async def get_public_arrivals(db: Session = Depends(get_db)):
'ac_reg': flight.registration,
'ac_type': flight.type,
'in_from': None,
'eta': flight.departure_dt,
'eta': flight.departed_dt,
'landed_dt': None,
'status': 'DEPARTED',
'isLocalFlight': True,
@@ -92,7 +92,7 @@ async def get_public_departures(db: Session = Depends(get_db)):
'ac_reg': flight.registration,
'ac_type': flight.type,
'out_to': None,
'etd': flight.booked_out_dt,
'etd': flight.etd or flight.created_dt,
'departed_dt': None,
'status': 'BOOKED_OUT',
'isLocalFlight': True,
@@ -114,7 +114,7 @@ async def get_public_departures(db: Session = Depends(get_db)):
'ac_reg': dep.registration,
'ac_type': dep.type,
'out_to': dep.out_to,
'etd': dep.booked_out_dt,
'etd': dep.etd or dep.created_dt,
'departed_dt': None,
'status': 'BOOKED_OUT',
'isLocalFlight': False,

View File

@@ -25,25 +25,25 @@ class CRUDDeparture:
query = query.filter(Departure.status == status)
if date_from:
query = query.filter(func.date(Departure.booked_out_dt) >= date_from)
query = query.filter(func.date(Departure.created_dt) >= date_from)
if date_to:
query = query.filter(func.date(Departure.booked_out_dt) <= date_to)
query = query.filter(func.date(Departure.created_dt) <= date_to)
return query.order_by(desc(Departure.booked_out_dt)).offset(skip).limit(limit).all()
return query.order_by(desc(Departure.created_dt)).offset(skip).limit(limit).all()
def get_departures_today(self, db: Session) -> List[Departure]:
"""Get today's departures (booked out or departed)"""
today = date.today()
return db.query(Departure).filter(
and_(
func.date(Departure.booked_out_dt) == today,
func.date(Departure.created_dt) == today,
or_(
Departure.status == DepartureStatus.BOOKED_OUT,
Departure.status == DepartureStatus.DEPARTED
)
)
).order_by(Departure.booked_out_dt).all()
).order_by(Departure.created_dt).all()
def create(self, db: Session, obj_in: DepartureCreate, created_by: str) -> Departure:
db_obj = Departure(
@@ -82,7 +82,7 @@ class CRUDDeparture:
db_obj.status = status
if status == DepartureStatus.DEPARTED and timestamp:
db_obj.departure_dt = timestamp
db_obj.departed_dt = timestamp
db.add(db_obj)
db.commit()

View File

@@ -29,12 +29,12 @@ class CRUDLocalFlight:
query = query.filter(LocalFlight.flight_type == flight_type)
if date_from:
query = query.filter(func.date(LocalFlight.booked_out_dt) >= date_from)
query = query.filter(func.date(LocalFlight.created_dt) >= date_from)
if date_to:
query = query.filter(func.date(LocalFlight.booked_out_dt) <= date_to)
query = query.filter(func.date(LocalFlight.created_dt) <= date_to)
return query.order_by(desc(LocalFlight.booked_out_dt)).offset(skip).limit(limit).all()
return query.order_by(desc(LocalFlight.created_dt)).offset(skip).limit(limit).all()
def get_active_flights(self, db: Session) -> List[LocalFlight]:
"""Get currently active (booked out or departed) flights"""
@@ -43,33 +43,33 @@ class CRUDLocalFlight:
LocalFlight.status == LocalFlightStatus.BOOKED_OUT,
LocalFlight.status == LocalFlightStatus.DEPARTED
)
).order_by(desc(LocalFlight.booked_out_dt)).all()
).order_by(desc(LocalFlight.created_dt)).all()
def get_departures_today(self, db: Session) -> List[LocalFlight]:
"""Get today's departures (booked out or departed)"""
today = date.today()
return db.query(LocalFlight).filter(
and_(
func.date(LocalFlight.booked_out_dt) == today,
func.date(LocalFlight.created_dt) == today,
or_(
LocalFlight.status == LocalFlightStatus.BOOKED_OUT,
LocalFlight.status == LocalFlightStatus.DEPARTED
)
)
).order_by(LocalFlight.booked_out_dt).all()
).order_by(LocalFlight.created_dt).all()
def get_booked_out_today(self, db: Session) -> List[LocalFlight]:
"""Get all flights booked out today"""
today = date.today()
return db.query(LocalFlight).filter(
and_(
func.date(LocalFlight.booked_out_dt) == today,
func.date(LocalFlight.created_dt) == today,
or_(
LocalFlight.status == LocalFlightStatus.BOOKED_OUT,
LocalFlight.status == LocalFlightStatus.LANDED
)
)
).order_by(LocalFlight.booked_out_dt).all()
).order_by(LocalFlight.created_dt).all()
def create(self, db: Session, obj_in: LocalFlightCreate, created_by: str) -> LocalFlight:
db_obj = LocalFlight(
@@ -114,7 +114,7 @@ class CRUDLocalFlight:
# Set timestamps based on status
current_time = timestamp if timestamp is not None else datetime.utcnow()
if status == LocalFlightStatus.DEPARTED:
db_obj.departure_dt = current_time
db_obj.departed_dt = current_time
elif status == LocalFlightStatus.LANDED:
db_obj.landed_dt = current_time

View File

@@ -20,10 +20,11 @@ class Departure(Base):
type = Column(String(32), nullable=True)
callsign = Column(String(16), nullable=True)
pob = Column(Integer, nullable=False)
out_to = Column(String(4), nullable=False, index=True)
out_to = Column(String(64), nullable=False, index=True)
status = Column(SQLEnum(DepartureStatus), default=DepartureStatus.BOOKED_OUT, nullable=False, index=True)
notes = Column(Text, nullable=True)
booked_out_dt = Column(DateTime, server_default=func.now(), nullable=False, index=True)
departure_dt = Column(DateTime, nullable=True)
created_dt = Column(DateTime, server_default=func.now(), nullable=False, index=True)
etd = Column(DateTime, nullable=True, index=True) # Estimated Time of Departure
departed_dt = Column(DateTime, nullable=True) # Actual departure time
created_by = Column(String(16), nullable=True, index=True)
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@@ -28,8 +28,9 @@ class LocalFlight(Base):
flight_type = Column(SQLEnum(LocalFlightType), nullable=False, index=True)
status = Column(SQLEnum(LocalFlightStatus), nullable=False, default=LocalFlightStatus.BOOKED_OUT, index=True)
notes = Column(Text, nullable=True)
booked_out_dt = Column(DateTime, nullable=False, server_default=func.current_timestamp(), index=True)
departure_dt = Column(DateTime, nullable=True) # Actual takeoff time
created_dt = Column(DateTime, nullable=False, server_default=func.current_timestamp(), index=True)
etd = Column(DateTime, nullable=True, index=True) # Estimated Time of Departure
departed_dt = Column(DateTime, nullable=True) # Actual takeoff time
landed_dt = Column(DateTime, nullable=True)
created_by = Column(String(16), nullable=True, index=True)
updated_at = Column(DateTime, nullable=False, server_default=func.current_timestamp(), onupdate=func.current_timestamp())

View File

@@ -16,6 +16,7 @@ class DepartureBase(BaseModel):
callsign: Optional[str] = None
pob: int
out_to: str
etd: Optional[datetime] = None # Estimated Time of Departure
notes: Optional[str] = None
@validator('registration')
@@ -46,6 +47,7 @@ class DepartureUpdate(BaseModel):
callsign: Optional[str] = None
pob: Optional[int] = None
out_to: Optional[str] = None
etd: Optional[datetime] = None
notes: Optional[str] = None
@@ -57,10 +59,6 @@ class DepartureStatusUpdate(BaseModel):
class Departure(DepartureBase):
id: int
status: DepartureStatus
booked_out_dt: datetime
departure_dt: Optional[datetime] = None
created_by: Optional[str] = None
updated_at: datetime
class Config:
from_attributes = True
created_dt: datetime
etd: Optional[datetime] = None
departed_dt: Optional[datetime] = None

View File

@@ -23,6 +23,7 @@ class LocalFlightBase(BaseModel):
callsign: Optional[str] = None
pob: int
flight_type: LocalFlightType
etd: Optional[datetime] = None # Estimated Time of Departure
notes: Optional[str] = None
@validator('registration')
@@ -57,7 +58,8 @@ class LocalFlightUpdate(BaseModel):
pob: Optional[int] = None
flight_type: Optional[LocalFlightType] = None
status: Optional[LocalFlightStatus] = None
departure_dt: Optional[datetime] = None
etd: Optional[datetime] = None
departed_dt: Optional[datetime] = None
notes: Optional[str] = None
@@ -69,8 +71,9 @@ class LocalFlightStatusUpdate(BaseModel):
class LocalFlightInDBBase(LocalFlightBase):
id: int
status: LocalFlightStatus
booked_out_dt: datetime
departure_dt: Optional[datetime] = None
created_dt: datetime
etd: Optional[datetime] = None
departed_dt: Optional[datetime] = None
landed_dt: Optional[datetime] = None
created_by: Optional[str] = None
updated_at: datetime
@@ -80,4 +83,4 @@ class LocalFlightInDBBase(LocalFlightBase):
class LocalFlight(LocalFlightInDBBase):
pass
pass