@@ -33,7 +33,19 @@ OR | |||
``` | |||
python3 -m uvicorn main:app --reload | |||
``` | |||
## Explaining the file structure | |||
``` | |||
app //main app | |||
|-alembic //Alembic -- database migration manager. Helps keep databases in sync and changeable (handles all SQL logic and keeps everything up-to-date) | |||
| |- //All files irrelevant | |||
|-apis //Stores the actual API Endpoints. | |||
| |-v1 //Main API endpoints | |||
|-core //Core project components | |||
|-db //Stores database information and data | |||
| |-models //Stores database models (represents SQL Tables) | |||
| |-repository //Stores scripts to create, update and interact with the database | |||
|-schemas //Stores Pydantic data models (Kind of like db/models except for use in the API itself, not just the database. Uses for data validation and stuff) | |||
``` | |||
## Git Guide | |||
- [Git Reference](http://git.github.io/git-reference): despite its name it is more of a user guide. | |||
- ["Pro Git" Book](http://git-scm.com/book): by a core developer, also a thorough user guide. | |||
@@ -1,7 +1,8 @@ | |||
# Base API router -- collecting all APIs here to not clutter main.py | |||
from fastapi import APIRouter | |||
from apis.v1 import route_user | |||
from apis.v1 import route_user, route_vehicle | |||
api_router = APIRouter() | |||
api_router.include_router(route_user.router, prefix="/user", tags=["users"]) | |||
api_router.include_router(route_vehicle.router, prefix="/vehicle", tags=["vehicles"]) |
@@ -2,10 +2,11 @@ | |||
from fastapi import APIRouter, status | |||
from sqlalchemy.orm import Session | |||
from fastapi import Depends | |||
from typing import List | |||
from schemas.user import UserCreate, ShowUser | |||
from db.session import get_db | |||
from db.repository.user import create_new_user | |||
from db.repository.user import create_new_user, list_users | |||
router = APIRouter() | |||
@@ -15,3 +16,12 @@ router = APIRouter() | |||
def create_user(user: UserCreate, db: Session = Depends(get_db)): | |||
user = create_new_user(user=user, db=db) | |||
return user | |||
@router.get("/", response_model=List[ShowUser], status_code=status.HTTP_200_OK) | |||
def get_all_users(db: Session = Depends(get_db), role: str = None): | |||
if role == None: | |||
users = list_users(db=db) | |||
return users | |||
users = list_users(db=db, role=role) | |||
return users |
@@ -0,0 +1,48 @@ | |||
from fastapi import APIRouter, status, HTTPException | |||
from sqlalchemy.orm import Session | |||
from fastapi import Depends | |||
from typing import List | |||
from db.session import get_db | |||
from schemas.vehicle import OutputVehicle, CreateVehicle | |||
from db.repository.vehicle import ( | |||
create_new_vehicle, | |||
assign_vehicle_driver, | |||
list_vehicles, | |||
) | |||
router = APIRouter() | |||
@router.post("/new", response_model=OutputVehicle, status_code=status.HTTP_201_CREATED) | |||
async def create_vehicle(vehicle: CreateVehicle, db: Session = Depends(get_db)): | |||
vehicle = create_new_vehicle(vehicle=vehicle, db=db) | |||
return vehicle | |||
@router.get( | |||
"/assign/{vehicle_id}/{driver_id}", | |||
response_model=OutputVehicle, | |||
status_code=status.HTTP_200_OK, | |||
) | |||
async def assign_drver(vehicle_id: int, driver_id: int, db: Session = Depends(get_db)): | |||
vehicle = assign_vehicle_driver(vehicle_id=vehicle_id, driver_id=driver_id, db=db) | |||
if vehicle == "nodriver": | |||
raise HTTPException( | |||
status_code=404, detail=f"Driver with id {driver_id} not found" | |||
) | |||
if vehicle == "novehicle": | |||
raise HTTPException( | |||
status_code=404, detail=f"Vehicle with id {vehicle_id} not found" | |||
) | |||
if vehicle == "alreadyassigned": | |||
raise HTTPException( | |||
status_code=400, | |||
detail=f"Driver with id {driver_id} is already assigned to vehicle with id {vehicle_id}", | |||
) | |||
return vehicle | |||
@router.get("/", response_model=List[OutputVehicle], status_code=status.HTTP_200_OK) | |||
async def get_all_vehicles(db: Session = Depends(get_db)): | |||
vehicles = list_vehicles(db=db) | |||
return vehicles |
@@ -21,3 +21,17 @@ def create_new_user(user: UserCreate, db: Session): | |||
db.commit() | |||
db.refresh(user) | |||
return user | |||
def verify_driver_exists(driver_id: int, db: Session): | |||
driver = db.query(User).filter(User.Id == driver_id).first() | |||
if not driver: | |||
return False | |||
if driver.Role != "Driver": | |||
return False | |||
return True | |||
def list_users(db: Session, role: str = "Any"): | |||
users = db.query(User).filter((User.Role == role) | (role == "Any")).all() | |||
return users |
@@ -0,0 +1,46 @@ | |||
from sqlalchemy.orm import Session | |||
from schemas.vehicle import CreateVehicle, OutputVehicle | |||
from db.models.vehicle import Vehicle | |||
from db.repository.user import verify_driver_exists | |||
def create_new_vehicle(vehicle: CreateVehicle, db: Session): | |||
vehicle = Vehicle( | |||
Model=vehicle.model, | |||
Year=vehicle.year, | |||
LicensePlate=vehicle.license_plate, | |||
Type=vehicle.type, | |||
Mileage=vehicle.mileage, | |||
AssignedDriverIds=[], | |||
CurrentLocation=[], | |||
Fuel=0, | |||
MaintenanceNotes=[], | |||
) | |||
db.add(vehicle) | |||
db.commit() | |||
db.refresh(vehicle) | |||
return vehicle | |||
def assign_vehicle_driver(vehicle_id: int, driver_id: int, db: Session): | |||
vehicledb = db.query(Vehicle).filter(Vehicle.Id == vehicle_id) | |||
vehicle = vehicledb.first() | |||
if not vehicle: | |||
return "novehicle" | |||
if driver_id in vehicle.AssignedDriverIds: | |||
return "alreadyassigned" | |||
if verify_driver_exists(driver_id=driver_id, db=db): | |||
print(vehicle.AssignedDriverIds) | |||
vehicledb.update({"AssignedDriverIds": vehicle.AssignedDriverIds + [driver_id]}) | |||
print(vehicle.AssignedDriverIds) | |||
db.add(vehicle) | |||
db.commit() | |||
db.refresh(vehicle) | |||
return vehicle | |||
# return a 404 error if the driver does not exist | |||
return "nodriver" | |||
def list_vehicles(db: Session): | |||
vehicles = db.query(Vehicle).all() | |||
return vehicles |
@@ -0,0 +1,24 @@ | |||
from typing import Optional | |||
from pydantic import BaseModel, root_validator | |||
from datetime import datetime | |||
class CreateVehicle(BaseModel): | |||
id: int | |||
model: str | |||
year: int | |||
license_plate: str | |||
type: str | |||
mileage: int | |||
class OutputVehicle(BaseModel): | |||
Model: str | |||
Year: int | |||
LicensePlate: str | |||
Type: str | |||
Mileage: int | |||
CurrentLocation: Optional[list[str]] = None | |||
Fuel: Optional[int] = 0 | |||
MaintenanceNotes: Optional[list[str]] = None | |||
AssignedDriverIds: Optional[list[int]] = None |