| @@ -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 | |||
| @@ -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" | |||
| ) | |||
| status_code=403, detail="You are not authorized to perform this action" | |||
| ) | |||
| tasks = get_all_fueling_tasks(db) | |||
| return tasks | |||
| @@ -38,7 +38,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), | |||
| @@ -80,6 +82,10 @@ def get_maintenancejob( | |||
| db: Session = Depends(get_db), | |||
| ): | |||
| 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 | |||
| @@ -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": | |||
| @@ -1,12 +1,21 @@ | |||
| # Routes for user. MAIN PART OF THE API | |||
| from fastapi import APIRouter, HTTPException, status | |||
| from math import ceil | |||
| from fastapi import APIRouter, HTTPException, status, Query | |||
| from sqlalchemy.orm import Session | |||
| from sqlalchemy import or_ | |||
| from fastapi import Depends | |||
| 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 | |||
| from schemas.user import ( | |||
| UserCreate, | |||
| ShowUser, | |||
| ShowDriver, | |||
| DriverCreate, | |||
| OutputUser, | |||
| UsersPage, | |||
| ) | |||
| from db.session import get_db | |||
| from db.repository.user import ( | |||
| create_new_user, | |||
| @@ -15,6 +24,8 @@ from db.repository.user import ( | |||
| replace_user_data, | |||
| create_new_driver, | |||
| delete_user_data, | |||
| get_users_by_name, | |||
| user_search_query, | |||
| ) | |||
| @@ -126,3 +137,14 @@ def delete_user( | |||
| if result == "userNotFound": | |||
| raise HTTPException(status_code=404, detail="User not found") | |||
| return result | |||
| @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, | |||
| ): | |||
| return user_search_query(db=db, name=name, role=role, page=page, per_page=per_page) | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| 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 | |||
| @@ -58,16 +58,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 | |||
| @@ -75,11 +82,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) | |||
| @@ -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 | |||
| @@ -84,6 +85,19 @@ def list_users(db: Session, role: str = "Any"): | |||
| return users | |||
| 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: | |||
| users = db.query(User).filter(User.Name.like(f"{name}%"), User.Role != "Admin") | |||
| else: | |||
| users = db.query(User).filter(User.Name.like(f"{name}%"), User.Role == role) | |||
| 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: | |||
| @@ -112,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} | |||
| @@ -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(...) | |||
| Cost: float = Field(...) | |||
| image: str = Field(...) | |||
| @@ -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(...) | |||
| @@ -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 | |||
| } | |||
| 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] | |||
| @@ -17,7 +17,7 @@ class OutputMaintenanceJob(BaseModel): | |||
| Description: str | |||
| Date: datetime | |||
| CarPartsList: Optional[List[ShowCarPart]] | |||
| TotalCost: int | |||
| TotalCost: float | |||
| Vehicle: OutputVehicle | |||
| FinishedBy: Optional[ShowUser] | |||
| Status: str | |||
| @@ -1,6 +1,7 @@ | |||
| # Purpose: User schema for pydantic (validation, inside-api usage) | |||
| from pydantic import BaseModel, EmailStr, Field | |||
| from typing import Optional, List | |||
| class UserCreate(BaseModel): | |||
| @@ -36,6 +37,28 @@ class ShowUser(BaseModel): | |||
| validate_assignment = True | |||
| class OutputUser(BaseModel): | |||
| id: int | |||
| Name: str | |||
| MiddleName: Optional[str] | |||
| LastName: str | |||
| ContactNumber: str | |||
| Address: str | |||
| Email: EmailStr | |||
| Role: str | |||
| 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 | |||