Refaktoring a bugfixing

This commit is contained in:
Michal Kváček
2023-10-13 23:24:53 +02:00
parent ce2c023eaf
commit 7f7f79dad6
36 changed files with 698 additions and 722 deletions
+60 -123
View File
@@ -1,77 +1,51 @@
import asyncio
from datetime import datetime
from typing import List, Optional, Type
from aiocache import cached
from typing import List, Optional
from sqlalchemy import delete, insert
from sqlalchemy.ext.asyncio import AsyncSession
from strawberry.file_uploads import Upload
from background_jobs.elevation import add_terrain_elevation_to_flight
from background_jobs.weather import download_weather
from database import models
from database.models import flight_has_copilot
from dependencies.db import get_session
from external.weather import weather_api
from database.transaction import get_session
from graphql_schema.entities.helpers.combobox import handle_combobox_save
from graphql_schema.entities.resolvers.base import get_base_resolver
from graphql_schema.entities.resolvers.base import BaseMutationResolver, BaseQueryResolver
from graphql_schema.entities.types.mutation_input import EditFlightInput, TrackItemInput, ComboboxInput
from graphql_schema.entities.types.types import Flight
from upload_utils import delete_file, handle_file_upload
from paths import FLIGHT_GPX_TRACK_PATH
from utils.file import delete_file
from utils.upload import handle_file_upload
class BaseMutationResolver:
model: Type[models.BaseModel]
graphql_type = Flight
class FlightQueryResolver(BaseQueryResolver):
def __init__(self):
super().__init__(graphql_type=Flight, model=models.Flight)
@classmethod
async def delete(cls, user_id: int, id: int):
async with get_session() as db:
model = (
(await db.scalars(
get_base_resolver(cls.model, user_id=user_id, object_id=id)
.filter(cls.model.id == id))
)
.one()
def get_query(self, user_id: int, object_id: Optional[int] = None, *args, **kwargs):
query = super().get_query(
user_id, object_id,
order_by=[models.Flight.takeoff_datetime.desc()],
include_public=bool(user_id)
)
if kwargs.get('username'):
query = (
query
.join(models.Flight.created_by)
.filter(models.User.public_username == kwargs['username'])
)
if hasattr(cls.model, "deleted"):
model = await cls.model.update(db, obj=model, data=dict(deleted=True))
else:
db.delete(model)
return cls.graphql_type(**model.as_dict())
@classmethod
async def _do_update(cls, db: AsyncSession, obj: models.BaseModel | dict, data: dict):
update_where = {}
if isinstance(obj, models.BaseModel):
update_where['obj'] = obj
else:
update_where['id'] = obj['id']
model = await cls.model.update(db, data=data, **update_where)
return cls.graphql_type(**model.as_dict())
async def handle_upload_gpx(original_gpx_filename: str, gpx_track: Upload):
path = "/app/uploads/tracks"
if original_gpx_filename:
delete_file(path + "/" + original_gpx_filename, silent=True)
return await handle_file_upload(gpx_track, path)
return query
class FlightMutationResolver(BaseMutationResolver):
model = models.Flight
graphql_type = Flight
def __init__(self):
super().__init__(Flight, models.Flight)
async def create(self):
pass
@classmethod
async def update(cls, context, id: int, input: EditFlightInput):
async def update(self, context, id: int, input: EditFlightInput):
user_id = context.user_id
async with get_session() as db:
flight = (await db.scalars(get_base_resolver(models.Flight, user_id=user_id, object_id=id))).one()
flight = await FlightQueryResolver().get_one(id, user_id)
flight_data = flight.as_dict()
flight_id = flight.id
@@ -84,31 +58,32 @@ class FlightMutationResolver(BaseMutationResolver):
)
async with get_session() as db:
if input.landing_airport:
landing_airport = await get_airport(db, input.landing_airport, user_id)
landing_datetime = input.landing_datetime or flight_data['landing_datetime']
data['landing_airport_id'] = landing_airport.id
data['landing_datetime'] = landing_datetime
weather_info = await handle_weather_info(
db, landing_datetime, landing_airport, flight_data['landing_weather_info_id']
)
if weather_info:
data['landing_weather_info_id'] = weather_info.id
if input.takeoff_airport:
takeoff_airport = await get_airport(db, input.takeoff_airport, user_id)
takeoff_datetime = input.takeoff_datetime or flight_data['takeoff_datetime']
takeoff_airport_id = await handle_combobox_save(
db, models.Airport, input.takeoff_airport, user_id, name_column="icao_code",
extra_data={"name": input.takeoff_airport.name}
)
data['takeoff_airport_id'] = takeoff_airport_id
data['takeoff_datetime'] = input.takeoff_datetime or flight_data['takeoff_datetime']
data['takeoff_airport_id'] = takeoff_airport.id
data['takeoff_datetime'] = takeoff_datetime
context.background_tasks.add_task(
download_weather, flight_id=id, airport_id=takeoff_airport_id, date_time=data['takeoff_datetime'],
type_="takeoff"
)
weather_info = await handle_weather_info(
db, takeoff_datetime, takeoff_airport, flight_data['takeoff_weather_info_id']
if input.landing_airport:
landing_airport_id = await handle_combobox_save(
db, models.Airport, input.landing_airport, user_id, name_column="icao_code",
extra_data={"name": input.landing_airport.name}
)
data['landing_airport_id'] = landing_airport_id
data['landing_datetime'] = input.landing_datetime or flight_data['landing_datetime']
context.background_tasks.add_task(
download_weather, flight_id=id, airport_id=landing_airport_id, date_time=data['landing_datetime'],
type_="landing"
)
if weather_info:
data['takeoff_weather_info_id'] = weather_info.id
if input.aircraft is not None:
data['aircraft_id'] = await handle_aircraft_save(db, user_id, input.aircraft)
@@ -127,46 +102,21 @@ class FlightMutationResolver(BaseMutationResolver):
if input.copilots is not None:
await db.execute(delete(flight_has_copilot).filter_by(flight_id=flight_id))
copilots = await handle_copilots_edit(db, input.copilots or [], user_id)
copilots = await asyncio.gather(*[
handle_combobox_save(db, models.Copilot, copilot, user_id) for copilot in input.copilots
])
for copilot_id in copilots:
await db.execute(insert(flight_has_copilot).values(flight_id=flight_id, copilot_id=copilot_id))
return await cls._do_update(db, flight_data, data)
return await self._do_update(db, flight_data, data)
async def handle_weather_info(
db: AsyncSession, date_time: datetime, airport: models.Airport, existing_weather_id: Optional[int] = None
) -> Optional[models.WeatherInfo]:
if not airport.gps_latitude or not airport.gps_longitude:
return None
async def handle_upload_gpx(original_gpx_filename: str, gpx_track: Upload):
if original_gpx_filename:
delete_file(FLIGHT_GPX_TRACK_PATH + "/" + original_gpx_filename, silent=True)
try:
weather = await weather_api.get_weather_for_hour(
date_time.astimezone(),
gps=(airport.gps_latitude, airport.gps_longitude)
)
except Exception as e:
print(e)
return None
data = {
"datetime": weather['datetime'],
"qnh": weather['pressure_msl'],
"temperature_surface": weather['temperature_2m'],
"dewpoint_surface": weather['dewpoint_2m'],
"rain": weather['rain'],
"cloudcover_total": weather['cloudcover'],
"cloudcover_low": weather['cloudcover_low'],
"wind_speed_surface": weather['windspeed_10m'],
"wind_direction_surface": weather['winddirection_10m'],
}
if existing_weather_id:
model = await models.WeatherInfo.update(db, id=existing_weather_id, data=data)
else:
model = await models.WeatherInfo.create(db, data=data)
return model
return await handle_file_upload(gpx_track, FLIGHT_GPX_TRACK_PATH)
async def handle_track_edit(db: AsyncSession, flight_id: int, track: List[TrackItemInput], user_id: int):
@@ -176,6 +126,7 @@ async def handle_track_edit(db: AsyncSession, flight_id: int, track: List[TrackI
for item in track:
poi_id = None
airport_id = None
if item.point_of_interest:
poi_id = await handle_combobox_save(
db, models.PointOfInterest, item.point_of_interest, user_id, extra_data={"description": ""}
@@ -195,7 +146,7 @@ async def handle_track_edit(db: AsyncSession, flight_id: int, track: List[TrackI
"point_of_interest_id": poi_id,
"airport_id": airport_id,
"order": order,
"landing_duration": item.landing_duration
"landing_duration": item.landing_duration if airport_id else None
}
)
order += 1
@@ -211,17 +162,3 @@ async def handle_aircraft_save(db: AsyncSession, user_id: int, aircraft: Combobo
"seats": 2,
"manufacturer": "",
})
@cached()
async def get_airport(db: AsyncSession, input: ComboboxInput, user_id: int):
airport_id = await handle_combobox_save(
db, models.Airport, input, user_id, name_column="icao_code", extra_data={"name": input.name}
)
return (await db.scalars(get_base_resolver(models.Airport, object_id=airport_id))).one()
async def handle_copilots_edit(db: AsyncSession, copilots: List[ComboboxInput], user_id: int) -> tuple:
cors = [handle_combobox_save(db, models.Copilot, copilot, user_id) for copilot in copilots]
return await asyncio.gather(*cors)