API pro podporu vytvareni letu z planu

This commit is contained in:
Michal Kváček
2024-06-30 02:31:37 +02:00
parent ac3b496459
commit e541508f75
6 changed files with 132 additions and 8 deletions
@@ -0,0 +1,30 @@
"""add flight.flight_plan_id fk
Revision ID: 989152b7184a
Revises: f9e1e8a01683
Create Date: 2024-06-27 17:09:19.933094
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '989152b7184a'
down_revision = 'f9e1e8a01683'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('flight', sa.Column('flight_plan_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'flight', 'flight_plan', ['flight_plan_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'flight', type_='foreignkey')
op.drop_column('flight', 'flight_plan_id')
# ### end Alembic commands ###
@@ -0,0 +1,40 @@
"""Add poi and airport id to flight plan track marker
Revision ID: 8cc01c03e980
Revises: 989152b7184a
Create Date: 2024-06-30 00:27:08.976891
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '8cc01c03e980'
down_revision = '989152b7184a'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('airport', 'openaip_id',
existing_type=mysql.VARCHAR(length=32),
nullable=True)
op.add_column('flight_plan_marker', sa.Column('airport_id', sa.Integer(), nullable=True))
op.add_column('flight_plan_marker', sa.Column('point_of_interest_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'flight_plan_marker', 'point_of_interest', ['point_of_interest_id'], ['id'])
op.create_foreign_key(None, 'flight_plan_marker', 'airport', ['airport_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'flight_plan_marker', type_='foreignkey')
op.drop_constraint(None, 'flight_plan_marker', type_='foreignkey')
op.drop_column('flight_plan_marker', 'point_of_interest_id')
op.drop_column('flight_plan_marker', 'airport_id')
op.alter_column('airport', 'openaip_id',
existing_type=mysql.VARCHAR(length=32),
nullable=False)
# ### end Alembic commands ###
+31 -5
View File
@@ -104,6 +104,7 @@ class FlightPlan(BaseModel):
is_default_name: Mapped[bool] = mapped_column(Boolean, server_default='0') is_default_name: Mapped[bool] = mapped_column(Boolean, server_default='0')
is_public: Mapped[bool] = mapped_column(Boolean, server_default='0') is_public: Mapped[bool] = mapped_column(Boolean, server_default='0')
is_editable_by_copilot: Mapped[bool] = mapped_column(Boolean, server_default='0') is_editable_by_copilot: Mapped[bool] = mapped_column(Boolean, server_default='0')
track_id: Mapped[int] = mapped_column(Integer, ForeignKey('track.id'), nullable=True)
description: Mapped[str] = mapped_column(Text, nullable=False, server_default="") description: Mapped[str] = mapped_column(Text, nullable=False, server_default="")
planned_speed: Mapped[int] = mapped_column(Integer, nullable=False, default=150) planned_speed: Mapped[int] = mapped_column(Integer, nullable=False, default=150)
planned_takeoff_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=True) planned_takeoff_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=True)
@@ -114,21 +115,44 @@ class FlightPlan(BaseModel):
copilots: Mapped[List['Copilot']] = relationship(secondary=flight_plan_has_copilot) copilots: Mapped[List['Copilot']] = relationship(secondary=flight_plan_has_copilot)
aircraft: Mapped['Aircraft'] = relationship() aircraft: Mapped['Aircraft'] = relationship()
markers: Mapped['FlightPlanMarker'] = relationship() markers: Mapped[List['FlightPlanMarker']] = relationship()
created_by: Mapped['User'] = relationship() created_by: Mapped['User'] = relationship()
class Track(BaseModel):
__tablename__ = "track"
id: Mapped[int] = mapped_column(primary_key=True)
bounds: Mapped[list[tuple[float, float]]] = mapped_column(JSON())
created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'))
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
created_by: Mapped['User'] = relationship()
class TrackPoint(BaseModel):
__tablename__ = "track_point"
id: Mapped[int] = mapped_column(primary_key=True)
timestamp: Mapped[datetime] = mapped_column(DateTime, nullable=False)
track_id: Mapped[id] = mapped_column(Integer, ForeignKey('track.id'))
gps_latitude: Mapped[float] = mapped_column(Float, nullable=False)
gps_longitude: Mapped[float] = mapped_column(Float, nullable=False)
elevation: Mapped[float] = mapped_column(Float, nullable=True)
class FlightPlanMarker(BaseModel): class FlightPlanMarker(BaseModel):
__tablename__ = "flight_plan_marker" __tablename__ = "flight_plan_marker"
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
flight_plan_id: Mapped[int] = mapped_column(Integer, ForeignKey('flight_plan.id')) flight_plan_id: Mapped[int] = mapped_column(Integer, ForeignKey('flight_plan.id'))
airport_id: Mapped[int] = mapped_column(Integer, ForeignKey("airport.id"), nullable=True)
point_of_interest_id: Mapped[int] = mapped_column(Integer, ForeignKey("point_of_interest.id"), nullable=True)
weather_info_id: Mapped[int] = mapped_column(Integer, ForeignKey('weather_info.id'), nullable=True)
name: Mapped[str] = mapped_column(String(128), nullable=False) name: Mapped[str] = mapped_column(String(128), nullable=False)
type: Mapped[str] = mapped_column(String(64), nullable=False) type: Mapped[str] = mapped_column(String(64), nullable=False)
position: Mapped[int] = mapped_column(Integer, nullable=False, default=0) position: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
gps_latitude: Mapped[float] = mapped_column(Float, nullable=False) gps_latitude: Mapped[float] = mapped_column(Float, nullable=False)
gps_longitude: Mapped[float] = mapped_column(Float, nullable=False) gps_longitude: Mapped[float] = mapped_column(Float, nullable=False)
weather_info_id: Mapped[int] = mapped_column(Integer, ForeignKey('weather_info.id'), nullable=True)
class Airport(BaseModel): class Airport(BaseModel):
@@ -136,7 +160,7 @@ class Airport(BaseModel):
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(128), nullable=False) name: Mapped[str] = mapped_column(String(128), nullable=False)
openaip_id: Mapped[str] = mapped_column(String(32), nullable=False, unique=True) openaip_id: Mapped[str] = mapped_column(String(32), nullable=True, unique=True)
icao_code: Mapped[str] = mapped_column(String(8), nullable=False) icao_code: Mapped[str] = mapped_column(String(8), nullable=False)
gps_latitude: Mapped[float] = mapped_column(Float, nullable=True) gps_latitude: Mapped[float] = mapped_column(Float, nullable=True)
gps_longitude: Mapped[float] = mapped_column(Float, nullable=True) gps_longitude: Mapped[float] = mapped_column(Float, nullable=True)
@@ -385,8 +409,10 @@ class Flight(BaseModel):
landing_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=False) landing_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=False)
duration_total: Mapped[int] = mapped_column(Integer, nullable=True) duration_total: Mapped[int] = mapped_column(Integer, nullable=True)
duration_pic: Mapped[int] = mapped_column(Integer, nullable=True) duration_pic: Mapped[int] = mapped_column(Integer, nullable=True)
gpx_track_filename: Mapped[str] = mapped_column(String(128), nullable=True) flight_plan_id: Mapped[int] = mapped_column(Integer, ForeignKey('flight_plan.id'), nullable=True)
has_terrain_elevation: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) track_id: Mapped[int] = mapped_column(Integer, ForeignKey('track.id'), nullable=True)
gpx_track_filename: Mapped[str] = mapped_column(String(128), nullable=True) # deprecated
has_terrain_elevation: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) # deprecated
aircraft_id: Mapped[int] = mapped_column(Integer, ForeignKey('aircraft.id')) aircraft_id: Mapped[int] = mapped_column(Integer, ForeignKey('aircraft.id'))
takeoff_weather_info_id: Mapped[int] = mapped_column(Integer, ForeignKey('weather_info.id'), nullable=True) takeoff_weather_info_id: Mapped[int] = mapped_column(Integer, ForeignKey('weather_info.id'), nullable=True)
landing_weather_info_id: Mapped[int] = mapped_column(Integer, ForeignKey('weather_info.id'), nullable=True) landing_weather_info_id: Mapped[int] = mapped_column(Integer, ForeignKey('weather_info.id'), nullable=True)
@@ -1,4 +1,6 @@
import asyncio import asyncio
import random
import uuid
from typing import List, Optional from typing import List, Optional
from sqlalchemy import delete, insert, select, func, text from sqlalchemy import delete, insert, select, func, text
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -142,12 +144,15 @@ class FlightMutationResolver(BaseMutationResolver):
data.update({ data.update({
"aircraft_id": aircraft_id, "aircraft_id": aircraft_id,
"has_terrain_elevation": False, "has_terrain_elevation": False,
"name": "", "name": input.name or '',
"description": "", "description": "",
"created_by_id": context.user_id "created_by_id": context.user_id
}) })
flight = await self._do_create(db, data) flight = await self._do_create(db, data)
if input.track is not None:
await handle_track_edit(db=db, flight_id=flight.id, track=input.track, user_id=user_id)
context.background_tasks.add_task( context.background_tasks.add_task(
download_weather_for_flight, download_weather_for_flight,
flight_id=flight.id, airport_id=flight.takeoff_airport_id, date_time=flight.takeoff_datetime, flight_id=flight.id, airport_id=flight.takeoff_airport_id, date_time=flight.takeoff_datetime,
@@ -256,14 +261,23 @@ async def handle_track_edit(db: AsyncSession, flight_id: int, track: List[TrackI
if item.point_of_interest: if item.point_of_interest:
poi_id = await handle_combobox_save( poi_id = await handle_combobox_save(
db, models.PointOfInterest, item.point_of_interest, user_id, extra_data={"description": ""} db, models.PointOfInterest, item.point_of_interest, user_id, extra_data={
"description": "",
'gps_latitude': item.gps_latitude,
'gps_longitude': item.gps_longitude
}
) )
if item.airport: if item.airport:
airport_id = await handle_combobox_save( airport_id = await handle_combobox_save(
db, models.Airport, item.airport, user_id, db, models.Airport, item.airport, user_id,
name_column="icao_code", name_column="icao_code",
extra_data={"name": item.airport.name} extra_data={
"name": item.airport.name,
'gps_latitude': item.gps_latitude,
'gps_longitude': item.gps_longitude,
'openaip_id': f'custom-{random.randint(0, 999999)}'
}
) )
await models.FlightTrack.create( await models.FlightTrack.create(
@@ -52,9 +52,18 @@ class FlightPlanMutationResolver(BaseMutationResolver):
position = 0 position = 0
for marker in markers: for marker in markers:
if marker.type == 'poi':
assert bool(marker.point_of_interest_id)
if marker.type == 'airport':
assert bool(marker.airport_id)
await models.FlightPlanMarker.create(db, data={ await models.FlightPlanMarker.create(db, data={
"position": position, "position": position,
"flight_plan_id": flight_plan.id, "flight_plan_id": flight_plan.id,
"airport_id": marker.airport_id,
"point_of_interest_id": marker.point_of_interest_id,
"type": marker.type, "type": marker.type,
"name": marker.name, "name": marker.name,
"gps_latitude": marker.gps_latitude, "gps_latitude": marker.gps_latitude,
@@ -138,11 +138,14 @@ class EditFlightInput(BaseGraphqlInputType):
@strawberry.input() @strawberry.input()
class CreateFlightInput(BaseGraphqlInputType): class CreateFlightInput(BaseGraphqlInputType):
aircraft: ComboboxInput aircraft: ComboboxInput
flight_plan_id: Optional[int] = None
name: Optional[str] = None
gpx_track_file: Optional[Upload] = None # TODO: poresit validaci uploadovaneho souboru! gpx_track_file: Optional[Upload] = None # TODO: poresit validaci uploadovaneho souboru!
landing_airport: Optional[ComboboxInput] = None landing_airport: Optional[ComboboxInput] = None
takeoff_airport: Optional[ComboboxInput] = None takeoff_airport: Optional[ComboboxInput] = None
takeoff_datetime: Optional[datetime] = None takeoff_datetime: Optional[datetime] = None
landing_datetime: Optional[datetime] = None landing_datetime: Optional[datetime] = None
track: Optional[List[TrackItemInput]] = None
@strawberry.input() @strawberry.input()
@@ -150,6 +153,8 @@ class TrackItemInput:
point_of_interest: Optional[ComboboxInput] = None point_of_interest: Optional[ComboboxInput] = None
airport: Optional[ComboboxInput] = None airport: Optional[ComboboxInput] = None
landing_duration: Optional[int] = None landing_duration: Optional[int] = None
gps_latitude: Optional[float] = None
gps_longitude: Optional[float] = None
@strawberry_sqlalchemy_input(models.Aircraft, exclude_fields=['id', 'photo_filename']) @strawberry_sqlalchemy_input(models.Aircraft, exclude_fields=['id', 'photo_filename'])