diff --git a/api/database/aircraft.py b/api/database/aircraft.py index 77dc2ea..82f91c5 100644 --- a/api/database/aircraft.py +++ b/api/database/aircraft.py @@ -1,5 +1,8 @@ +from typing import Any + from bson import ObjectId from fastapi import HTTPException +from pymongo.errors import WriteError from database.db import aircraft_collection from schemas.aircraft import AircraftDisplaySchema, AircraftCreateSchema, aircraft_display_helper, aircraft_add_helper @@ -71,7 +74,7 @@ async def update_aircraft(body: AircraftCreateSchema, id: str) -> AircraftDispla :param body: Updated aircraft data :param id: ID of aircraft to update - :return: ID of updated aircraft + :return: Updated aircraft """ aircraft = await aircraft_collection.find_one({"_id": ObjectId(id)}) @@ -82,7 +85,32 @@ async def update_aircraft(body: AircraftCreateSchema, id: str) -> AircraftDispla if updated_aircraft is None: raise HTTPException(500, "Failed to update flight") - return id + return AircraftDisplaySchema(**body.model_dump()) + + +async def update_aircraft_field(field: str, value: Any, id: str) -> AircraftDisplaySchema: + """ + Update a single field of the given aircraft in the database + + :param field: Field to update + :param value: Value to set field to + :param id: ID of aircraft to update + :return: Updated aircraft + """ + aircraft = await aircraft_collection.find_one({"_id": ObjectId(id)}) + + if aircraft is None: + raise HTTPException(404, "Aircraft not found") + + try: + updated_aircraft = await aircraft_collection.update_one({"_id": ObjectId(id)}, {"$set": {field: value}}) + except WriteError as e: + raise HTTPException(400, e.details) + + if updated_aircraft is None: + raise HTTPException(500, "Failed to update flight") + + return AircraftDisplaySchema(**aircraft.model_dump()) async def delete_aircraft(id: str) -> AircraftDisplaySchema: diff --git a/api/database/flights.py b/api/database/flights.py index ae59ae5..7a104f5 100644 --- a/api/database/flights.py +++ b/api/database/flights.py @@ -1,10 +1,13 @@ import logging from datetime import datetime +from typing import Dict, Union from bson import ObjectId from bson.errors import InvalidId from fastapi import HTTPException +from schemas.aircraft import AircraftCreateSchema, aircraft_add_helper +from .aircraft import retrieve_aircraft_by_tail, update_aircraft, update_aircraft_field from .db import flight_collection from schemas.flight import FlightConciseSchema, FlightDisplaySchema, FlightCreateSchema, flight_display_helper, \ flight_add_helper @@ -12,22 +15,30 @@ from schemas.flight import FlightConciseSchema, FlightDisplaySchema, FlightCreat logger = logging.getLogger("api") -async def retrieve_flights(user: str = "", sort: str = "date", order: int = -1) -> list[FlightConciseSchema]: +async def retrieve_flights(user: str = "", sort: str = "date", order: int = -1, filter: str = "", + filter_val: str = "") -> list[FlightConciseSchema]: """ Retrieve a list of flights, optionally filtered by user :param user: User to filter flights by :param sort: Parameter to sort results by :param order: Sort order + :param filter: Field to filter flights by + :param filter_val: Value to filter field by :return: List of flights """ + filter_options = {} + if user != "": + filter_options["user"] = ObjectId(user) + if filter != "": + filter_options[filter] = filter_val + + print(filter_options) + flights = [] - if user == "": - async for flight in flight_collection.find().sort({sort: order}): - flights.append(FlightConciseSchema(**flight_display_helper(flight))) - else: - async for flight in flight_collection.find({"user": ObjectId(user)}).sort({sort: order}): - flights.append(FlightConciseSchema(**flight_display_helper(flight))) + async for flight in flight_collection.find(filter_options).sort({sort: order}): + flights.append(FlightConciseSchema(**flight_display_helper(flight))) + return flights @@ -37,7 +48,7 @@ async def retrieve_totals(user: str, start_date: datetime = None, end_date: date :param user: :return: """ - match = {"user": ObjectId(user)} + match: Dict[str, Union[Dict, ObjectId]] = {"user": ObjectId(user)} if start_date is not None: match.setdefault("date", {}).setdefault("$gte", start_date) @@ -122,19 +133,22 @@ async def insert_flight(body: FlightCreateSchema, id: str) -> ObjectId: :param id: ID of creating user :return: ID of inserted flight """ - try: - aircraft = await flight_collection.find_one({"_id": ObjectId(body.aircraft)}) - except InvalidId: - raise HTTPException(400, "Invalid aircraft ID") + aircraft = await retrieve_aircraft_by_tail(body.aircraft) if aircraft is None: raise HTTPException(404, "Aircraft not found") + # Update hobbs of aircraft to reflect new hobbs end + if body.hobbs_end > 0 and body.hobbs_end != aircraft.hobbs: + await update_aircraft_field("hobbs", body.hobbs_end, aircraft.id) + + # Insert flight into database flight = await flight_collection.insert_one(flight_add_helper(body.model_dump(), id)) + return flight.inserted_id -async def update_flight(body: FlightCreateSchema, id: str) -> FlightDisplaySchema: +async def update_flight(body: FlightCreateSchema, id: str) -> str: """ Update given flight in the database @@ -147,12 +161,18 @@ async def update_flight(body: FlightCreateSchema, id: str) -> FlightDisplaySchem if flight is None: raise HTTPException(404, "Flight not found") - aircraft = await flight_collection.find_ond({"_id": ObjectId(body.aircraft)}) + aircraft = await retrieve_aircraft_by_tail(body.aircraft) if aircraft is None: raise HTTPException(404, "Aircraft not found") + # Update hobbs of aircraft to reflect new hobbs end + if body.hobbs_end > 0 and body.hobbs_end != aircraft.hobbs: + await update_aircraft_field("hobbs", body.hobbs_end, aircraft.id) + + # Update flight in database updated_flight = await flight_collection.update_one({"_id": ObjectId(id)}, {"$set": body.model_dump()}) + if updated_flight is None: raise HTTPException(500, "Failed to update flight") diff --git a/api/routes/flights.py b/api/routes/flights.py index ee968d5..fc6a0cf 100644 --- a/api/routes/flights.py +++ b/api/routes/flights.py @@ -15,7 +15,8 @@ logger = logging.getLogger("flights") @router.get('/', summary="Get flights logged by the currently logged-in user", status_code=200) -async def get_flights(user: UserDisplaySchema = Depends(get_current_user), sort: str = "date", order: int = -1) -> list[ +async def get_flights(user: UserDisplaySchema = Depends(get_current_user), sort: str = "date", order: int = -1, + filter: str = "", filter_val: str = "") -> list[ FlightConciseSchema]: """ Get a list of the flights logged by the currently logged-in user @@ -23,25 +24,29 @@ async def get_flights(user: UserDisplaySchema = Depends(get_current_user), sort: :param user: Current user :param sort: Attribute to sort results by :param order: Order of sorting (asc/desc) + :param filter: Field to filter results by + :param filter_val: Value to filter field by :return: List of flights """ - flights = await db.retrieve_flights(user.id, sort, order) + flights = await db.retrieve_flights(user.id, sort, order, filter, filter_val) return flights @router.get('/by-date', summary="Get flights logged by the current user, categorized by date", status_code=200, response_model=dict) async def get_flights_by_date(user: UserDisplaySchema = Depends(get_current_user), sort: str = "date", - order: int = -1) -> dict: + order: int = -1, filter: str = "", filter_val: str = "") -> dict: """ Get a list of the flights logged by the currently logged-in user, categorized by year, month, and day :param user: Current user :param sort: Attribute to sort results by :param order: Order of sorting (asc/desc) + :param filter: Field to filter results by + :param filter_val: Value to filter field by :return: """ - flights = await db.retrieve_flights(user.id, sort, order) + flights = await db.retrieve_flights(user.id, sort, order, filter, filter_val) flights_ordered: FlightByDateSchema = {} for flight in flights: diff --git a/api/schemas/flight.py b/api/schemas/flight.py index bcfac4e..4a02c63 100644 --- a/api/schemas/flight.py +++ b/api/schemas/flight.py @@ -71,7 +71,7 @@ class FlightConciseSchema(BaseModel): comments: Optional[str] = None -FlightByDateSchema = Dict[int, Union[List['FlightByDateSchema'], FlightConciseSchema]] +FlightByDateSchema = Dict[int, Union[Dict[int, 'FlightByDateSchema'], FlightConciseSchema]] # HELPERS #