From 2db4cbe6a009028af31956b61141c1fa1abb548a Mon Sep 17 00:00:00 2001 From: Madiwka3 Date: Wed, 8 Nov 2023 17:39:55 +0600 Subject: [PATCH 1/3] Did an initial bugfix, all features seem to be working --- app/apis/v1/route_auction.py | 4 +++ app/apis/v1/route_fuelingtask.py | 49 +++++++++++++++++--------- app/apis/v1/route_maintenancejob.py | 8 ++++- app/apis/v1/route_task.py | 6 ++-- app/db/models/fuelingtask.py | 2 +- app/db/repository/auction.py | 2 ++ app/db/repository/drivetask.py | 4 +-- app/db/repository/fuelingtask.py | 53 ++++++++++++++++++++++------- app/db/repository/maintenancejob.py | 13 +++++-- app/schemas/carpart.py | 9 ++--- app/schemas/drivetask.py | 2 +- app/schemas/fuelingtask.py | 34 ++++++++++++------ app/schemas/maintenancejob.py | 2 +- 13 files changed, 133 insertions(+), 55 deletions(-) diff --git a/app/apis/v1/route_auction.py b/app/apis/v1/route_auction.py index bc9d31b..eefc1b4 100644 --- a/app/apis/v1/route_auction.py +++ b/app/apis/v1/route_auction.py @@ -32,6 +32,10 @@ def getAuction( current_user: User = Depends(get_current_user), ): auction = get_auction_by_id(id, db) + if auction is None: + raise HTTPException( + status_code=404, detail="Auction with this ID does not exist" + ) return auction diff --git a/app/apis/v1/route_fuelingtask.py b/app/apis/v1/route_fuelingtask.py index ae1b8b9..403d577 100644 --- a/app/apis/v1/route_fuelingtask.py +++ b/app/apis/v1/route_fuelingtask.py @@ -4,14 +4,21 @@ from db.session import get_db from db.repository.fuelingtask import ( create_fueling_task, delete_fueling_task, - get_fueling_task_by_id + get_fueling_task_by_id, + get_all_fueling_tasks, +) +from schemas.fuelingtask import ( + CreateFuelingTask, + OutputFuelingTask, + OutputFuelingTaskMin, + OutputFuelingTaskList, ) -from schemas.fuelingtask import CreateFuelingTask, OutputFuelingTask from db.models.user import User from apis.v1.route_auth import get_current_user router = APIRouter() + @router.post("/", response_model=OutputFuelingTask, status_code=status.HTTP_201_CREATED) def create_fuelingtask( fuelingtask: CreateFuelingTask = Depends(), @@ -28,19 +35,18 @@ def create_fuelingtask( ) print("Created FuelTask") if fuelingtask_res == "nodriver": - raise HTTPException( - status_code=404, detail="Driver ID not found" - ) + raise HTTPException(status_code=404, detail="Driver ID not found") if fuelingtask_res == "novehicle": - raise HTTPException( - status_code=404, detail="Vehicle ID not found" - ) + raise HTTPException(status_code=404, detail="Vehicle ID not found") return fuelingtask_res - -@router.get("/{fueling_task_id}", response_model=OutputFuelingTask, status_code=status.HTTP_200_OK) +@router.get( + "/{fueling_task_id}", + response_model=OutputFuelingTask, + status_code=status.HTTP_200_OK, +) def get_fuelingtask( fueling_task_id: int, db: Session = Depends(get_db), @@ -50,26 +56,35 @@ def get_fuelingtask( raise HTTPException( status_code=403, detail="You are not authorized to perform this action" ) - + fuelingtask = get_fueling_task_by_id(fueling_task_id, db) if fuelingtask == "notfound": - raise HTTPException( - status_code=404, detail="fuck off" - ) + raise HTTPException(status_code=404, detail="fuck off") return fuelingtask + @router.delete("/{fueling_task_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_fuelingtask( fueling_task_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): - if current_user.Role != "FuelingPerson" and current_user.Role != "Admin": + if current_user.Role != "Fueling" and current_user.Role != "Admin": raise HTTPException( status_code=403, detail="You are not authorized to perform this action" ) if not delete_fueling_task(fueling_task_id, db): + raise HTTPException(status_code=404, detail="Fueling task not found") + + +@router.get("/", response_model=OutputFuelingTaskList, status_code=status.HTTP_200_OK) +def get_all( + db: Session = Depends(get_db), current_user: User = Depends(get_current_user) +): + if current_user.Role != "Admin" and current_user.Role != "Fueling": raise HTTPException( - status_code=404, detail="Fueling task not found" - ) \ No newline at end of file + status_code=403, detail="You are not authorized to perform this action" + ) + tasks = get_all_fueling_tasks(db) + return tasks diff --git a/app/apis/v1/route_maintenancejob.py b/app/apis/v1/route_maintenancejob.py index 00222e0..f3a1639 100644 --- a/app/apis/v1/route_maintenancejob.py +++ b/app/apis/v1/route_maintenancejob.py @@ -34,7 +34,9 @@ def create_maintenancejob( return maintenancejob_res -@router.post("/carpart", response_model = ShowCarPart ,status_code=status.HTTP_201_CREATED) +@router.post( + "/carpart", response_model=ShowCarPart, status_code=status.HTTP_201_CREATED +) def create_carpart( car_part: CreateCarPart = Depends(), db: Session = Depends(get_db), @@ -82,6 +84,10 @@ def get_maintenancejob( ) maintenancejob = get_maintenance_job(maintenance_job_id, db) + if maintenancejob is None: + raise HTTPException( + status_code=404, detail="Maintenance job with this id does not exist" + ) print(maintenancejob) return maintenancejob diff --git a/app/apis/v1/route_task.py b/app/apis/v1/route_task.py index 756dfe8..168ace4 100644 --- a/app/apis/v1/route_task.py +++ b/app/apis/v1/route_task.py @@ -165,14 +165,16 @@ def getActiveRoute( return route -@router.get("/myroutes", status_code=status.HTTP_200_OK) +@router.get("/myroutes/", status_code=status.HTTP_200_OK) def getMyRoutes( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): + print("here") if current_user.Role != "Driver": raise HTTPException( - status_code=403, detail="You are not authorized to perform this action" + status_code=403, + detail="You are not a driver, you can't have routes, silly!", ) routes = get_my_routes(current_user.Id, db) if routes == "notdriver": diff --git a/app/db/models/fuelingtask.py b/app/db/models/fuelingtask.py index 4d837fa..bfd0442 100644 --- a/app/db/models/fuelingtask.py +++ b/app/db/models/fuelingtask.py @@ -10,7 +10,7 @@ class FuelingTask(Base): CreatedById = Column(ForeignKey("user.Id"), nullable=False) Date = Column(DateTime, nullable=False) Description = Column(String, nullable=True) - Cost = Column(Integer, nullable=False) + Cost = Column(Float, nullable=False) FuelRefilled = Column(Float, nullable=False) GasStationName = Column(String, nullable=False) ImageBefore = Column(LargeBinary, nullable=False) diff --git a/app/db/repository/auction.py b/app/db/repository/auction.py index e98dda8..00efa1c 100644 --- a/app/db/repository/auction.py +++ b/app/db/repository/auction.py @@ -14,6 +14,8 @@ def get_all_auctions(db: Session): def get_auction_by_id(id: int, db: Session): auction = db.query(Auction).filter(Auction.Id == id).first() + if not auction: + return None auction.car = auction.vehicle return auction diff --git a/app/db/repository/drivetask.py b/app/db/repository/drivetask.py index 3e8e391..f33ae20 100644 --- a/app/db/repository/drivetask.py +++ b/app/db/repository/drivetask.py @@ -63,10 +63,10 @@ def get_tasks_by_driver(driver_id: int, db: Session): def get_task_by_id(task_id: int, db: Session): task = db.query(DriveTask).filter(DriveTask.Id == task_id).first() - task.Driver = task.CreatedBy.__dict__ - task.Driver["AssignedVehicle"] = task.CreatedBy.vehicle if not task: return "notaskfound" + task.Driver = task.CreatedBy.__dict__ + task.Driver["AssignedVehicle"] = task.CreatedBy.vehicle return task diff --git a/app/db/repository/fuelingtask.py b/app/db/repository/fuelingtask.py index 6b3cd7e..5a083c4 100644 --- a/app/db/repository/fuelingtask.py +++ b/app/db/repository/fuelingtask.py @@ -7,16 +7,17 @@ from db.models.fuelingtask import FuelingTask from db.repository.user import get_car_driver, get_user_by_id from db.repository.vehicle import get_vehicle_by_id -def create_fueling_task(fueling_task: CreateFuelingTask, current_user: int, db: Session): - + +def create_fueling_task( + fueling_task: CreateFuelingTask, current_user: int, db: Session +): if not get_vehicle_by_id(fueling_task.VehicleId, db=db): return "novehicle" - + driver = get_car_driver(fueling_task.VehicleId, db=db) - + if not driver: return "nodriver" - fueling_task_object = FuelingTask( DriverId=driver.Id, VehicleId=fueling_task.VehicleId, @@ -35,31 +36,59 @@ def create_fueling_task(fueling_task: CreateFuelingTask, current_user: int, db: print(driver.__dict__) driverobj = driver.__dict__ driverobj["AssignedVehicle"] = driver.vehicle.__dict__ - fueling_task_object.Driver = driverobj - return fueling_task_object + resobj = fueling_task_object.__dict__ + resobj["Driver"] = driverobj + ia = fueling_task_object.ImageAfter + ib = fueling_task_object.ImageBefore + if ia is not None: + ia = base64.b64encode(ia).decode("ascii") + if ib is not None: + ib = base64.b64encode(ib).decode("ascii") + resobj["ImageBefore"] = ib + resobj["ImageAfter"] = ia + return resobj def delete_fueling_task(fueling_task_id: int, db: Session): - fueling_task = db.query(FuelingTask).filter(FuelingTask.Id == fueling_task_id).first() + fueling_task = ( + db.query(FuelingTask).filter(FuelingTask.Id == fueling_task_id).first() + ) if fueling_task: db.delete(fueling_task) db.commit() return True return False + def get_fueling_task_by_id(fuel_task_id: int, db: Session): fuel_task = db.query(FuelingTask).filter(FuelingTask.Id == fuel_task_id).first() if not fuel_task: return "notfound" - res = fuel_task.__dict__ + res = fuel_task.__dict__ driver = get_user_by_id(fuel_task.DriverId, role="Driver", db=db) driver_obj = driver.__dict__ imagebefore = fuel_task.ImageBefore imageafter = fuel_task.ImageAfter - imagebeforeBase64 = base64.b64encode(imagebefore).decode('ascii') - imageafterBase64 = base64.b64encode(imageafter).decode('ascii') + imagebeforeBase64 = base64.b64encode(imagebefore).decode("ascii") + imageafterBase64 = base64.b64encode(imageafter).decode("ascii") res["ImageBefore"] = imagebeforeBase64 res["ImageAfter"] = imageafterBase64 res["Driver"] = driver_obj res["Driver"]["AssignedVehicle"] = driver.vehicle - return res \ No newline at end of file + return res + + +def get_all_fueling_tasks(db: Session): + fuel_task = db.query(FuelingTask).all() + result = [] + for task in fuel_task: + res = task.__dict__ + res["ImageBefore"] = "" + res["ImageAfter"] = "" + driver = get_user_by_id(task.DriverId, role="Driver", db=db) + driver_obj = driver.__dict__ + res["Driver"] = driver_obj + res["Driver"]["AssignedVehicle"] = driver.vehicle + result.append(res) + x = {"FuelingTasks": result} + return x diff --git a/app/db/repository/maintenancejob.py b/app/db/repository/maintenancejob.py index d977e10..667fa0a 100644 --- a/app/db/repository/maintenancejob.py +++ b/app/db/repository/maintenancejob.py @@ -53,16 +53,23 @@ def calculate_total_cost(car_parts: CarPart): def get_all_maintenance_jobs(db: Session): maintenancejobs = db.query(MaintenanceJob).all() + print("DB Access complete") result = [] for job in maintenancejobs: job_dict = job.__dict__ + print(job_dict) job_dict["CarPartsList"] = [part.__dict__ for part in job.CarParts] + print(len(job_dict["CarPartsList"])) for part in job_dict["CarPartsList"]: - part["image"] = base64.b64encode(part["ImageURL"]).decode("ascii") + if (part["ImageURL"] is None) or (part["ImageURL"] == ""): + part["image"] = "" + else: + part["image"] = base64.b64encode(part["ImageURL"]).decode("ascii") job_dict["TotalCost"] = calculate_total_cost(job.CarParts) job_dict["AssignedTo"] = job.CreatedBy.__dict__ job_dict["Vehicle"] = job.Vehicle.__dict__ result.append(job_dict) + print("Returning...") return maintenancejobs @@ -70,11 +77,13 @@ def get_maintenance_job(maintenancejob_id: int, db: Session): maintenancejob = ( db.query(MaintenanceJob).filter(MaintenanceJob.Id == maintenancejob_id).first() ) + if maintenancejob is None: + return None res = maintenancejob.__dict__ res["CarPartsList"] = [part.__dict__ for part in maintenancejob.CarParts] for part in maintenancejob.CarPartsList: part["image"] = base64.b64encode(part["ImageURL"]).decode("ascii") - + # print(type(result.CarPartsList)) res["TotalCost"] = calculate_total_cost(maintenancejob.CarParts) # print(result.TotalCost) diff --git a/app/schemas/carpart.py b/app/schemas/carpart.py index e2e3770..8ebf37e 100644 --- a/app/schemas/carpart.py +++ b/app/schemas/carpart.py @@ -1,4 +1,3 @@ - from fastapi import Form, UploadFile from pydantic import BaseModel, Field from dataclasses import dataclass @@ -9,10 +8,8 @@ class CreateCarPart(BaseModel): Name: str = Form(...) Number: str = Form(...) Condition: str = Form(...) - Cost: int = Form(...) + Cost: float = Form(...) image: UploadFile = Form(...) - - class ShowCarPart(BaseModel): @@ -20,5 +17,5 @@ class ShowCarPart(BaseModel): Name: str = Field(...) Number: str = Field(...) Condition: str = Field(...) - Cost: int = Field(...) - image: str = Field(...) \ No newline at end of file + Cost: float = Field(...) + image: str = Field(...) diff --git a/app/schemas/drivetask.py b/app/schemas/drivetask.py index 2132f08..57eef64 100644 --- a/app/schemas/drivetask.py +++ b/app/schemas/drivetask.py @@ -5,7 +5,7 @@ from typing import Optional class CreateTask(BaseModel): - DriverId: int = Field() + DriverId: int = Field(...) Description: str = Field(..., min_length=3, max_length=200) StartLocation: tuple[str, str] = Field(...) EndLocation: tuple[str, str] = Field(...) diff --git a/app/schemas/fuelingtask.py b/app/schemas/fuelingtask.py index fbbed6c..94ee7df 100644 --- a/app/schemas/fuelingtask.py +++ b/app/schemas/fuelingtask.py @@ -3,29 +3,43 @@ from fastapi import Form, UploadFile from datetime import datetime from schemas.user import ShowDriver + class CreateFuelingTask(BaseModel): VehicleId: int = Form(...) Description: str = Form(...) Date: datetime = Form(...) - Cost: int = Form(...) - FuelRefilled: int = Form(...) + Cost: float = Form(...) + FuelRefilled: float = Form(...) GasStationName: str = Form(...) ImageBefore: UploadFile = Form(...) ImageAfter: UploadFile = Form(...) - model_config={ - "arbitrary_types_allowed": True - } + model_config = {"arbitrary_types_allowed": True} + class OutputFuelingTask(BaseModel): + Id: int = Field(...) VehicleId: int = Field(...) Description: str = Field(...) Date: datetime = Field(...) - Cost: int = Field(...) - FuelRefilled: int = Field(...) + Cost: float = Field(...) + FuelRefilled: float = Field(...) GasStationName: str = Field(...) Driver: ShowDriver | None ImageBefore: str = Field(...) ImageAfter: str = Field(...) - model_config={ - "arbitrary_types_allowed": True - } \ No newline at end of file + model_config = {"arbitrary_types_allowed": True} + + +class OutputFuelingTaskMin(BaseModel): + Id: int = Field(...) + VehicleId: int = Field(...) + Description: str = Field(...) + Date: datetime = Field(...) + Cost: float = Field(...) + FuelRefilled: float = Field(...) + GasStationName: str = Field(...) + Driver: ShowDriver | None + + +class OutputFuelingTaskList(BaseModel): + FuelingTasks: list[OutputFuelingTaskMin] diff --git a/app/schemas/maintenancejob.py b/app/schemas/maintenancejob.py index 312f57c..3fee841 100644 --- a/app/schemas/maintenancejob.py +++ b/app/schemas/maintenancejob.py @@ -18,6 +18,6 @@ class OutputMaintenanceJob(BaseModel): Description: str Date: datetime CarPartsList: Optional[List[ShowCarPart]] - TotalCost: int + TotalCost: float Vehicle: OutputVehicle AssignedTo: ShowUser From b1f0eeb1fe5871331552da64500ddf841480917e Mon Sep 17 00:00:00 2001 From: Saruar Date: Wed, 8 Nov 2023 21:37:29 +0600 Subject: [PATCH 2/3] Search functionality --- app/.DS_Store | Bin 0 -> 6148 bytes app/apis/v1/route_user.py | 33 +++++++++++++++++++++++++++++++-- app/db/repository/user.py | 9 +++++++++ app/schemas/user.py | 19 +++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 app/.DS_Store diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8defa378e4ddf097e94317713c170c5e96a63488 GIT binary patch literal 6148 zcmeH~K?=e^3`G;|qTr@Wm$UHz-e4$t0xzH-h#)G8uIK3fWP)IIEh0aV{7Gg)>05Lf z5z+p(or`oL(!xz;W?^88ypfHZWiQwJ>T*1sjyu$>K8mxphIca9k8KJGkN^pg011%5 z4-v3?8`e&$GLirZkie6GeIF9sG>4X|{^>yQ5dhkt?1r_^63}D?Xbvq^QGsbp4;roN zV~Ewg9h%}?4lPw{yJ!p_8c$Z6VqjX^MH3R3W)}t$Ab|maam_os|CjJj^Z%fQDG89k zpApbzv0C(askmF;UeD_5sM@-~p?)0U Date: Wed, 8 Nov 2023 21:56:34 +0600 Subject: [PATCH 3/3] some slight refactoring --- app/apis/v1/route_user.py | 43 ++++++++++++++++----------------------- app/db/repository/user.py | 37 +++++++++++++++++++++++++++++++-- app/schemas/user.py | 6 +++++- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/app/apis/v1/route_user.py b/app/apis/v1/route_user.py index 6cf1569..f8920d1 100644 --- a/app/apis/v1/route_user.py +++ b/app/apis/v1/route_user.py @@ -8,7 +8,14 @@ from typing import List, Annotated from apis.v1.route_auth import get_current_user from core.config import settings from db.models.user import User -from schemas.user import UserCreate, ShowUser, ShowDriver, DriverCreate, OutputUser, UsersPage +from schemas.user import ( + UserCreate, + ShowUser, + ShowDriver, + DriverCreate, + OutputUser, + UsersPage, +) from db.session import get_db from db.repository.user import ( create_new_user, @@ -17,11 +24,11 @@ from db.repository.user import ( replace_user_data, create_new_driver, delete_user_data, - get_users_by_name + get_users_by_name, + user_search_query, ) - router = APIRouter() @@ -133,25 +140,11 @@ def delete_user( @router.get("/search/", response_model=UsersPage) -def search_users(db: Session = Depends(get_db), name: str = None, role: str = None, page: int = 1, per_page: int = 20): - query = db.query(User).filter(User.Name.like(f"{name}%")) - if role is not None and role != "Admin": - query = query.filter(User.Role == role) - total_users = query.count() - total_pages = ceil(total_users / per_page) - users = query.offset((page - 1) * per_page).limit(per_page).all() - - output_users = [OutputUser( - id= user.Id, - Name=user.Name, - MiddleName = user.MiddleName, - LastName=user.LastName, - ContactNumber=user.ContactNumber, - Address=user.Address, - Email=user.Email, - Role=user.Role, - AssignedVehicle= None - ) for user in users] - - - return {"users": output_users, "total_pages": total_pages} +def search_users( + db: Session = Depends(get_db), + name: str = None, + role: str = None, + page: int = 1, + per_page: int = 20, +): + return user_search_query(db=db, name=name, role=role, page=page, per_page=per_page) diff --git a/app/db/repository/user.py b/app/db/repository/user.py index 9ea9534..d1ad2ec 100644 --- a/app/db/repository/user.py +++ b/app/db/repository/user.py @@ -1,7 +1,8 @@ # Creating a new user in the database +from math import ceil from sqlalchemy.orm import Session -from schemas.user import UserCreate, DriverCreate +from schemas.user import OutputUser, UserCreate, DriverCreate from db.models.user import User from core.hashing import Hasher from db.models.drivetask import DriveTask @@ -83,7 +84,10 @@ def list_users(db: Session, role: str = "Any"): users = db.query(User).filter((User.Role == role) | (role == "Any")).all() return users -def get_users_by_name(db: Session, name: str = "", role: str = None, page: int = 1, per_page: int = 20): + +def get_users_by_name( + db: Session, name: str = "", role: str = None, page: int = 1, per_page: int = 20 +): if role == "Admin": return None if role is None: @@ -93,6 +97,7 @@ def get_users_by_name(db: Session, name: str = "", role: str = None, page: int = users = users.offset((page - 1) * per_page).limit(per_page).all() return users + def replace_user_data(user_id: int, user_data: UserCreate, db: Session): user = db.query(User).filter(User.Id == user_id).first() if not user: @@ -121,3 +126,31 @@ def delete_user_data(id: int, db: Session): db.delete(user) db.commit() return "userDeleted" + + +def user_search_query( + db: Session, name: str = "", role: str = None, page: int = 1, per_page: int = 20 +): + query = db.query(User).filter(User.Name.like(f"{name}%")) + if role is not None and role != "Admin": + query = query.filter(User.Role == role) + total_users = query.count() + total_pages = ceil(total_users / per_page) + users = query.offset((page - 1) * per_page).limit(per_page).all() + + output_users = [ + OutputUser( + id=user.Id, + Name=user.Name, + MiddleName=user.MiddleName, + LastName=user.LastName, + ContactNumber=user.ContactNumber, + Address=user.Address, + Email=user.Email, + Role=user.Role, + AssignedVehicle=None, + ) + for user in users + ] + + return {"users": output_users, "total_pages": total_pages} diff --git a/app/schemas/user.py b/app/schemas/user.py index 3496fc0..1a9f188 100644 --- a/app/schemas/user.py +++ b/app/schemas/user.py @@ -46,15 +46,19 @@ class OutputUser(BaseModel): Address: str Email: EmailStr Role: str - AssignedVehicle: Optional[str] # replace str with the actual type of AssignedVehicle + AssignedVehicle: Optional[ + str + ] # replace str with the actual type of AssignedVehicle class Config: orm_mode = True + class UsersPage(BaseModel): users: List[OutputUser] total_pages: int + class ShowDriverNoVehicle(ShowUser): DrivingLicenseNumber: str | None