Major refactor WIP
This commit is contained in:
@@ -6,6 +6,9 @@ from app.models.arrival import Arrival, ArrivalStatus
|
||||
from app.schemas.arrival import ArrivalCreate, ArrivalUpdate, ArrivalStatusUpdate
|
||||
from app.models.journal import EntityType
|
||||
from app.crud.crud_journal import journal
|
||||
from app.crud.crud_movement import movement as movement_crud
|
||||
from app.schemas.movement import MovementCreate
|
||||
from app.models.movement import MovementType
|
||||
|
||||
|
||||
class CRUDArrival:
|
||||
@@ -155,6 +158,41 @@ class CRUDArrival:
|
||||
db.commit()
|
||||
db.refresh(db_obj)
|
||||
|
||||
# Create movement record if applicable
|
||||
if status == ArrivalStatus.LANDED and db_obj.landed_dt:
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.LANDING,
|
||||
aircraft_registration=db_obj.registration,
|
||||
aircraft_type=db_obj.type,
|
||||
callsign=db_obj.callsign,
|
||||
timestamp=db_obj.landed_dt,
|
||||
entity_type="ARRIVAL",
|
||||
entity_id=arrival_id,
|
||||
from_location=db_obj.in_from,
|
||||
created_by=user,
|
||||
ip_address=user_ip
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
|
||||
# Promote any PENDING departure linked to this arrival to BOOKED_OUT
|
||||
from app.models.departure import Departure as DepartureModel, DepartureStatus as DepStatus
|
||||
pending_dep = db.query(DepartureModel).filter(
|
||||
DepartureModel.arrival_id == arrival_id,
|
||||
DepartureModel.status == DepStatus.PENDING
|
||||
).first()
|
||||
if pending_dep:
|
||||
pending_dep.status = DepStatus.BOOKED_OUT
|
||||
db.add(pending_dep)
|
||||
db.commit()
|
||||
journal.log_change(
|
||||
db,
|
||||
EntityType.ARRIVAL,
|
||||
arrival_id,
|
||||
f"Linked departure #{pending_dep.id} promoted to BOOKED_OUT on landing",
|
||||
user,
|
||||
user_ip
|
||||
)
|
||||
|
||||
# Log status change in journal
|
||||
journal.log_change(
|
||||
db,
|
||||
|
||||
@@ -6,6 +6,11 @@ from app.models.circuit import Circuit
|
||||
from app.schemas.circuit import CircuitCreate, CircuitUpdate
|
||||
from app.models.journal import EntityType
|
||||
from app.crud.crud_journal import journal
|
||||
from app.crud.crud_movement import movement as movement_crud
|
||||
from app.schemas.movement import MovementCreate
|
||||
from app.models.movement import MovementType
|
||||
from app.crud.crud_local_flight import local_flight as crud_local_flight
|
||||
from app.crud.crud_arrival import arrival as crud_arrival
|
||||
|
||||
|
||||
class CRUDCircuit:
|
||||
@@ -56,6 +61,39 @@ class CRUDCircuit:
|
||||
user_ip
|
||||
)
|
||||
|
||||
# Create TOUCH_AND_GO movement
|
||||
if obj_in.local_flight_id:
|
||||
flight = crud_local_flight.get(db, obj_in.local_flight_id)
|
||||
if flight:
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.TOUCH_AND_GO,
|
||||
aircraft_registration=flight.registration,
|
||||
aircraft_type=flight.type,
|
||||
callsign=flight.callsign,
|
||||
timestamp=obj_in.circuit_timestamp,
|
||||
entity_type="LOCAL_FLIGHT",
|
||||
entity_id=obj_in.local_flight_id,
|
||||
created_by=user,
|
||||
ip_address=user_ip
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
elif obj_in.arrival_id:
|
||||
arrival = crud_arrival.get(db, obj_in.arrival_id)
|
||||
if arrival:
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.TOUCH_AND_GO,
|
||||
aircraft_registration=arrival.registration,
|
||||
aircraft_type=arrival.type,
|
||||
callsign=arrival.callsign,
|
||||
timestamp=obj_in.circuit_timestamp,
|
||||
entity_type="ARRIVAL",
|
||||
entity_id=obj_in.arrival_id,
|
||||
from_location=arrival.in_from,
|
||||
created_by=user,
|
||||
ip_address=user_ip
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
|
||||
return db_obj
|
||||
|
||||
def update(self, db: Session, db_obj: Circuit, obj_in: CircuitUpdate, user: str = "system", user_ip: Optional[str] = None) -> Circuit:
|
||||
|
||||
@@ -6,6 +6,9 @@ from app.models.departure import Departure, DepartureStatus
|
||||
from app.schemas.departure import DepartureCreate, DepartureUpdate, DepartureStatusUpdate
|
||||
from app.models.journal import EntityType
|
||||
from app.crud.crud_journal import journal
|
||||
from app.crud.crud_movement import movement as movement_crud
|
||||
from app.schemas.movement import MovementCreate
|
||||
from app.models.movement import MovementType
|
||||
|
||||
|
||||
class CRUDDeparture:
|
||||
@@ -57,9 +60,18 @@ class CRUDDeparture:
|
||||
if submitted_via == SubmissionSource.ADMIN:
|
||||
initial_status = DepartureStatus.GROUND
|
||||
contact_dt = func.now() # Set contact_dt to creation time for admin submissions
|
||||
|
||||
|
||||
obj_data = obj_in.dict()
|
||||
arrival_id = obj_data.pop('arrival_id', None)
|
||||
|
||||
# If arrival_id is provided this is a PPR-linked departure — stay PENDING until arrival lands
|
||||
if arrival_id is not None:
|
||||
initial_status = DepartureStatus.PENDING
|
||||
contact_dt = None
|
||||
|
||||
db_obj = Departure(
|
||||
**obj_in.dict(),
|
||||
**obj_data,
|
||||
arrival_id=arrival_id,
|
||||
created_by=created_by,
|
||||
status=initial_status,
|
||||
contact_dt=contact_dt,
|
||||
@@ -149,6 +161,22 @@ class CRUDDeparture:
|
||||
db.commit()
|
||||
db.refresh(db_obj)
|
||||
|
||||
# Create movement record if applicable
|
||||
if db_obj.takeoff_dt and status == DepartureStatus.LOCAL:
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.TAKEOFF,
|
||||
aircraft_registration=db_obj.registration,
|
||||
aircraft_type=db_obj.type,
|
||||
callsign=db_obj.callsign,
|
||||
timestamp=db_obj.takeoff_dt,
|
||||
entity_type="DEPARTURE",
|
||||
entity_id=departure_id,
|
||||
to_location=db_obj.out_to,
|
||||
created_by=user,
|
||||
ip_address=user_ip
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
|
||||
# Log status change in journal
|
||||
journal.log_change(
|
||||
db,
|
||||
|
||||
@@ -7,6 +7,9 @@ from app.schemas.local_flight import LocalFlightCreate, LocalFlightUpdate, Local
|
||||
from app.models.journal import EntityType
|
||||
from app.models.circuit import Circuit
|
||||
from app.crud.crud_journal import journal
|
||||
from app.crud.crud_movement import movement as movement_crud
|
||||
from app.schemas.movement import MovementCreate
|
||||
from app.models.movement import MovementType
|
||||
|
||||
|
||||
class CRUDLocalFlight:
|
||||
@@ -186,9 +189,7 @@ class CRUDLocalFlight:
|
||||
db_obj.contact_dt = current_time
|
||||
elif status == LocalFlightStatus.DEPARTED:
|
||||
db_obj.departed_dt = current_time
|
||||
elif status == LocalFlightStatus.LOCAL:
|
||||
db_obj.takeoff_dt = current_time
|
||||
elif status == LocalFlightStatus.LANDED:
|
||||
elif status == LocalFlightStatus.LANDED and not db_obj.landed_dt:
|
||||
db_obj.landed_dt = current_time
|
||||
# Count circuits from the circuits table and populate the circuits column
|
||||
circuit_count = db.query(func.count(Circuit.id)).filter(
|
||||
@@ -196,10 +197,42 @@ class CRUDLocalFlight:
|
||||
).scalar()
|
||||
db_obj.circuits = circuit_count
|
||||
|
||||
# Takeoff: happens once when transitioning away from GROUND
|
||||
if old_status == LocalFlightStatus.GROUND and status in (LocalFlightStatus.DEPARTED, LocalFlightStatus.LOCAL, LocalFlightStatus.CIRCUIT) and not db_obj.takeoff_dt:
|
||||
db_obj.takeoff_dt = current_time
|
||||
|
||||
db.add(db_obj)
|
||||
db.commit()
|
||||
db.refresh(db_obj)
|
||||
|
||||
# Create movement record if applicable
|
||||
if db_obj.takeoff_dt and old_status == LocalFlightStatus.GROUND and status in (LocalFlightStatus.DEPARTED, LocalFlightStatus.LOCAL, LocalFlightStatus.CIRCUIT):
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.TAKEOFF,
|
||||
aircraft_registration=db_obj.registration,
|
||||
aircraft_type=db_obj.type,
|
||||
callsign=db_obj.callsign,
|
||||
timestamp=db_obj.takeoff_dt,
|
||||
entity_type="LOCAL_FLIGHT",
|
||||
entity_id=flight_id,
|
||||
created_by=user,
|
||||
ip_address=user_ip
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
if db_obj.landed_dt and status == LocalFlightStatus.LANDED:
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.LANDING,
|
||||
aircraft_registration=db_obj.registration,
|
||||
aircraft_type=db_obj.type,
|
||||
callsign=db_obj.callsign,
|
||||
timestamp=db_obj.landed_dt,
|
||||
entity_type="LOCAL_FLIGHT",
|
||||
entity_id=flight_id,
|
||||
created_by=user,
|
||||
ip_address=user_ip
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
|
||||
# Log status change in journal
|
||||
journal.log_change(
|
||||
db,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
from typing import List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_, func
|
||||
from datetime import date, datetime
|
||||
from app.models.movement import Movement, MovementType
|
||||
from app.schemas.movement import MovementCreate
|
||||
|
||||
|
||||
class CRUDMovement:
|
||||
def get(self, db: Session, movement_id: int) -> Optional[Movement]:
|
||||
return db.query(Movement).filter(Movement.id == movement_id).first()
|
||||
|
||||
def get_multi(
|
||||
self,
|
||||
db: Session,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
movement_type: Optional[MovementType] = None,
|
||||
aircraft_registration: Optional[str] = None,
|
||||
date_from: Optional[date] = None,
|
||||
date_to: Optional[date] = None,
|
||||
entity_type: Optional[str] = None
|
||||
) -> List[Movement]:
|
||||
query = db.query(Movement)
|
||||
|
||||
if movement_type:
|
||||
query = query.filter(Movement.movement_type == movement_type)
|
||||
|
||||
if aircraft_registration:
|
||||
query = query.filter(Movement.aircraft_registration.ilike(f"%{aircraft_registration}%"))
|
||||
|
||||
if date_from:
|
||||
query = query.filter(func.date(Movement.timestamp) >= date_from)
|
||||
|
||||
if date_to:
|
||||
query = query.filter(func.date(Movement.timestamp) <= date_to)
|
||||
|
||||
if entity_type:
|
||||
query = query.filter(Movement.entity_type == entity_type)
|
||||
|
||||
return query.order_by(Movement.timestamp.desc()).offset(skip).limit(limit).all()
|
||||
|
||||
def create(self, db: Session, obj_in: MovementCreate) -> Movement:
|
||||
db_obj = Movement(**obj_in.dict())
|
||||
db.add(db_obj)
|
||||
db.commit()
|
||||
db.refresh(db_obj)
|
||||
return db_obj
|
||||
|
||||
def get_movements_by_entity(self, db: Session, entity_type: str, entity_id: int) -> List[Movement]:
|
||||
return db.query(Movement).filter(
|
||||
and_(Movement.entity_type == entity_type, Movement.entity_id == entity_id)
|
||||
).order_by(Movement.timestamp).all()
|
||||
|
||||
def get_daily_movements(self, db: Session, target_date: date) -> List[Movement]:
|
||||
return db.query(Movement).filter(
|
||||
func.date(Movement.timestamp) == target_date
|
||||
).order_by(Movement.timestamp).all()
|
||||
|
||||
|
||||
movement = CRUDMovement()
|
||||
@@ -6,6 +6,9 @@ from app.models.overflight import Overflight, OverflightStatus
|
||||
from app.schemas.overflight import OverflightCreate, OverflightUpdate, OverflightStatusUpdate
|
||||
from app.models.journal import EntityType
|
||||
from app.crud.crud_journal import journal
|
||||
from app.crud.crud_movement import movement as movement_crud
|
||||
from app.schemas.movement import MovementCreate
|
||||
from app.models.movement import MovementType
|
||||
|
||||
|
||||
class CRUDOverflight:
|
||||
@@ -57,6 +60,21 @@ class CRUDOverflight:
|
||||
db.commit()
|
||||
db.refresh(db_obj)
|
||||
|
||||
# Create OVERFLIGHT movement if call_dt is set
|
||||
if db_obj.call_dt:
|
||||
movement_data = MovementCreate(
|
||||
movement_type=MovementType.OVERFLIGHT,
|
||||
aircraft_registration=db_obj.registration,
|
||||
aircraft_type=db_obj.type,
|
||||
timestamp=db_obj.call_dt,
|
||||
entity_type="OVERFLIGHT",
|
||||
entity_id=db_obj.id,
|
||||
from_location=db_obj.departure_airfield,
|
||||
to_location=db_obj.destination_airfield,
|
||||
created_by=created_by
|
||||
)
|
||||
movement_crud.create(db, movement_data)
|
||||
|
||||
# Log creation in journal
|
||||
journal.log_change(
|
||||
db,
|
||||
|
||||
Reference in New Issue
Block a user