@@ -9,6 +9,7 @@ from apis.v1 import ( | |||
route_maintenancejob, | |||
route_fuelingtask, | |||
route_auction, | |||
route_report | |||
) | |||
api_router = APIRouter() | |||
@@ -21,3 +22,4 @@ api_router.include_router( | |||
) | |||
api_router.include_router(route_fuelingtask.router, prefix="/fuel", tags=["fueltasks"]) | |||
api_router.include_router(route_auction.router, prefix="/auction", tags=["auctions"]) | |||
api_router.include_router(route_report.router, prefix="/report", tags=["reports"]) |
@@ -12,9 +12,9 @@ from apis.v1.route_auth import get_current_user | |||
router = APIRouter() | |||
@router.post("/", status_code=status.HTTP_201_CREATED) | |||
@router.post("/", response_model=OutputFuelingTask, status_code=status.HTTP_201_CREATED) | |||
def create_fuelingtask( | |||
fuelingtask: CreateFuelingTask, | |||
fuelingtask: CreateFuelingTask = Depends(), | |||
db: Session = Depends(get_db), | |||
current_user: User = Depends(get_current_user), | |||
): | |||
@@ -26,7 +26,7 @@ def create_fuelingtask( | |||
fuelingtask_res = create_fueling_task( | |||
fueling_task=fuelingtask, current_user=current_user.Id, db=db | |||
) | |||
print("Created FuelTask") | |||
if fuelingtask_res == "nodriver": | |||
raise HTTPException( | |||
status_code=404, detail="Driver ID not found" | |||
@@ -0,0 +1,22 @@ | |||
from fastapi import Depends, APIRouter, HTTPException, status | |||
from requests import Session | |||
from apis.v1.route_auth import get_current_user | |||
from db.models.user import User | |||
from db.repository.report import get_repot_jobsdone_by_driver | |||
from db.session import get_db | |||
router = APIRouter() | |||
@router.get("/jobsdone/{driver_id}", status_code=status.HTTP_200_OK) | |||
def get_report_jobsdone(driver_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): | |||
if current_user.Role != "Admin": | |||
raise HTTPException( | |||
status_code=403, detail="You are not authorized to perform this action" | |||
) | |||
report = get_repot_jobsdone_by_driver(driver_id, db) | |||
if report == "notdriver": | |||
raise HTTPException( | |||
status_code=404, detail=f"Driver with id {driver_id} not found" | |||
) | |||
return report |
@@ -43,6 +43,7 @@ def create_task( | |||
def changeStatus( | |||
task_id: int, | |||
status: str, | |||
distance: float = 0, | |||
db: Session = Depends(get_db), | |||
current_user: User = Depends(get_current_user), | |||
): | |||
@@ -59,7 +60,7 @@ def changeStatus( | |||
status_code=403, | |||
detail="You are not authorized to perform this action", | |||
) | |||
task = change_task_status(task_id, status, db) | |||
task = change_task_status(task_id, status, distance, db) | |||
if task == "notaskfound": | |||
raise HTTPException( | |||
status_code=404, detail=f"Task with id {task_id} not found" | |||
@@ -1,4 +1,4 @@ | |||
from sqlalchemy import Column, Integer, String, ForeignKey, ARRAY, DateTime | |||
from sqlalchemy import Column, Double, Integer, String, ForeignKey, ARRAY, DateTime | |||
from db.base import Base | |||
from sqlalchemy.orm import relationship | |||
@@ -11,4 +11,6 @@ class DriveTask(Base): | |||
Status = Column(String, nullable=False) | |||
StartLocation = Column(ARRAY(String), nullable=False) | |||
EndLocation = Column(ARRAY(String), nullable=False) | |||
StartDateTime = Column(DateTime, nullable=False) | |||
StartDateTime = Column(DateTime, nullable=True) | |||
DistanceCovered = Column(Double, nullable=True) | |||
EndDateTime = Column(DateTime, nullable=True) |
@@ -7,9 +7,10 @@ class MaintenanceJob(Base): | |||
Id = Column(Integer, primary_key=True, index=True) | |||
# a list of weak entities of class CarPart | |||
CarParts = relationship("CarPart", back_populates="parent") | |||
CreatedBy = relationship("User", back_populates="maintenanceJobs") | |||
CreatedBy = relationship("User", back_populates="maintenanceJobs", foreign_keys="MaintenanceJob.MaintenanceWorker") | |||
VehicleID = Column(ForeignKey("vehicle.Id"), nullable=False) | |||
Vehicle = relationship("Vehicle", back_populates="maintenanceJobs") | |||
VehicleDriverId = Column(ForeignKey("user.Id"), nullable=False) | |||
Description = Column(String, nullable=False) | |||
Date = Column(DateTime, nullable=False) | |||
MaintenanceWorker = Column(ForeignKey("user.Id"), nullable=False) |
@@ -25,7 +25,7 @@ class User(Base): | |||
driveTasks = relationship("DriveTask", back_populates="CreatedBy") | |||
vehicle = relationship("Vehicle", back_populates="driver") | |||
#MaintenancePerson-specific relationships | |||
maintenanceJobs = relationship("MaintenanceJob", back_populates="CreatedBy") | |||
maintenanceJobs = relationship("MaintenanceJob", back_populates="CreatedBy", foreign_keys="MaintenanceJob.MaintenanceWorker") | |||
#FuelingPerson-specific relationships | |||
fuelingTasks = relationship("FuelingTask", back_populates="CreatedBy", foreign_keys="FuelingTask.CreatedById") | |||
@@ -1,3 +1,4 @@ | |||
from datetime import datetime | |||
from sqlalchemy.orm import Session | |||
from schemas.drivetask import CreateTask | |||
@@ -24,16 +25,16 @@ def create_new_task(task: CreateTask, db: Session): | |||
return task_object | |||
def change_task_status(task_id: int, status: str, db: Session): | |||
def change_task_status(task_id: int, status: str, distance: int, db: Session): | |||
task = db.query(DriveTask).filter(DriveTask.Id == task_id).first() | |||
if not task: | |||
return "notaskfound" | |||
if status == "In Progress": | |||
# see if there are any other tasks in progress by this driver, if yes, cancel | |||
tasks = db.query(DriveTask).filter(DriveTask.DriverId == task.DriverId).all() | |||
for task in tasks: | |||
if task.Status == "In Progress": | |||
return "driverhasothertask" | |||
task.StartDateTime = datetime.now() | |||
if status == "Completed": | |||
task.DistanceCovered = distance | |||
task.EndDateTime = datetime.now() | |||
task.Status = status | |||
db.commit() | |||
db.refresh(task) | |||
@@ -1,7 +1,8 @@ | |||
import base64 | |||
from sqlalchemy.orm import Session | |||
from schemas.fuelingtask import CreateFuelingTask | |||
from schemas.fuelingtask import CreateFuelingTask, OutputFuelingTask | |||
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 | |||
@@ -25,12 +26,16 @@ def create_fueling_task(fueling_task: CreateFuelingTask, current_user: int, db: | |||
Cost=fueling_task.Cost, | |||
FuelRefilled=fueling_task.FuelRefilled, | |||
GasStationName=fueling_task.GasStationName, | |||
ImageBefore=fueling_task.ImageBefore, | |||
ImageAfter=fueling_task.ImageAfter, | |||
ImageBefore=fueling_task.ImageBefore.file.read(), | |||
ImageAfter=fueling_task.ImageAfter.file.read(), | |||
) | |||
db.add(fueling_task_object) | |||
db.commit() | |||
db.refresh(fueling_task_object) | |||
print(driver.__dict__) | |||
driverobj = driver.__dict__ | |||
driverobj["AssignedVehicle"] = driver.vehicle.__dict__ | |||
fueling_task_object.Driver = driverobj | |||
return fueling_task_object | |||
@@ -49,6 +54,12 @@ def get_fueling_task_by_id(fuel_task_id: int, db: Session): | |||
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') | |||
res["ImageBefore"] = imagebeforeBase64 | |||
res["ImageAfter"] = imageafterBase64 | |||
res["Driver"] = driver_obj | |||
res["Driver"]["AssignedVehicle"] = driver.vehicle | |||
return fuel_task | |||
return res |
@@ -1,8 +1,10 @@ | |||
import base64 | |||
from sqlalchemy.orm import Session | |||
from schemas.maintenancejob import CreateMaintenanceJob | |||
from db.models.maintenancejob import MaintenanceJob | |||
from schemas.carpart import CreateCarPart | |||
from db.models.carpart import CarPart | |||
from db.repository.user import get_car_driver | |||
def create_new_maintenancejob( | |||
@@ -13,6 +15,7 @@ def create_new_maintenancejob( | |||
Description=maintenancejob.Description, | |||
VehicleID=maintenancejob.VehicleID, | |||
Date=maintenancejob.Date, | |||
VehicleDriverId=get_car_driver(maintenancejob.VehicleID, db).Id, | |||
) | |||
print("OBJECT CREATED") | |||
db.add(maintenancejob_object) | |||
@@ -36,7 +39,9 @@ def create_car_part(car_part: CreateCarPart, db: Session): | |||
print("OBJECT SAVED") | |||
db.refresh(car_part_object) | |||
print("OBJECT REFRESHED") | |||
return car_part_object | |||
res_obj = car_part_object.__dict__ | |||
res_obj["image"] = base64.b64encode(car_part_object.ImageURL).decode("ascii") | |||
return res_obj | |||
def calculate_total_cost(car_parts: CarPart): | |||
@@ -52,6 +57,8 @@ def get_all_maintenance_jobs(db: Session): | |||
for job in maintenancejobs: | |||
job_dict = job.__dict__ | |||
job_dict["CarPartsList"] = [part.__dict__ for part in job.CarParts] | |||
for part in job_dict["CarPartsList"]: | |||
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__ | |||
@@ -63,13 +70,16 @@ def get_maintenance_job(maintenancejob_id: int, db: Session): | |||
maintenancejob = ( | |||
db.query(MaintenanceJob).filter(MaintenanceJob.Id == maintenancejob_id).first() | |||
) | |||
maintenancejob.CarPartsList = [part.__dict__ for part in maintenancejob.CarParts] | |||
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)) | |||
maintenancejob.TotalCost = calculate_total_cost(maintenancejob.CarParts) | |||
res["TotalCost"] = calculate_total_cost(maintenancejob.CarParts) | |||
# print(result.TotalCost) | |||
maintenancejob.AssignedTo = maintenancejob.CreatedBy.__dict__ | |||
maintenancejob.Vehicle = maintenancejob.Vehicle.__dict__ | |||
print(maintenancejob.AssignedTo) | |||
res["AssignedTo"] = maintenancejob.CreatedBy.__dict__ | |||
res["Vehicle"] = maintenancejob.Vehicle.__dict__ | |||
print("DB Access complete") | |||
return maintenancejob | |||
@@ -0,0 +1,78 @@ | |||
from datetime import datetime | |||
from sqlalchemy.orm import Session | |||
from db.models.drivetask import DriveTask | |||
from db.models.user import User | |||
from db.models.fuelingtask import FuelingTask | |||
from db.models.maintenancejob import MaintenanceJob | |||
from db.repository.maintenancejob import calculate_total_cost | |||
def get_repot_jobsdone_by_driver(driver_id: int, db: Session): | |||
driver = db.query(User).filter(User.Id == driver_id).first() | |||
if not driver: | |||
return "notdriver" | |||
if driver.Role != "Driver": | |||
return "notdriver" | |||
tasks = db.query(DriveTask).filter((DriveTask.DriverId == driver_id) & (DriveTask.Status == "Completed")).all() | |||
#order tasks by completion date | |||
tasks.sort(key=lambda x: x.EndDateTime) | |||
#for each task, add TOTAL distance driven at the time of completion | |||
dist = 0 | |||
taskslist = [] | |||
for task in tasks: | |||
dist += task.DistanceCovered | |||
taskslist.append(task.__dict__) | |||
taskslist[-1]["DistanceAtTime"] = dist | |||
res = {} | |||
res["tasks"] = taskslist | |||
res["Driver"] = driver.__dict__ | |||
res["Driver"]["AssignedVehicle"] = driver.vehicle | |||
dist = 0 | |||
for task in tasks: | |||
dist += task.DistanceCovered | |||
res["TotalDistance"] = dist | |||
timespent = 0.0 | |||
for task in tasks: | |||
edate = task.EndDateTime | |||
sdate = task.StartDateTime | |||
if type(edate) == str: | |||
edate = datetime.strptime(edate, "%Y-%m-%d %H:%M:%S.%f") | |||
timetaken = edate - sdate | |||
timespent += timetaken.total_seconds() | |||
#time spent in hours and minutes | |||
hours = timespent // 3600 | |||
minutes = (timespent % 3600) // 60 | |||
res["TotalTime"] = str(hours) + " hours " + str(minutes) + " minutes" | |||
#add fuel expenditures | |||
fuel = db.query(FuelingTask).filter(FuelingTask.DriverId == driver_id).all() | |||
fuel.sort(key=lambda x: x.Date) | |||
totalfuelspent = 0 | |||
fuelspent = [] | |||
for f in fuel: | |||
fuelpoint = {} | |||
totalfuelspent += f.FuelRefilled | |||
fuelpoint["fuelrefilled"] = f.FuelRefilled | |||
fuelpoint["total"] = totalfuelspent | |||
fuelpoint["date"] = f.Date | |||
fuelspent.append(fuelpoint) | |||
res["FuelSpent"] = fuelspent | |||
res["TotalFuelSpent"] = totalfuelspent | |||
#add maintenance costs | |||
mainten = db.query(MaintenanceJob).filter(MaintenanceJob.VehicleDriverId == driver_id).all() | |||
mainten.sort(key=lambda x: x.Date) | |||
totalmaintenspent = 0 | |||
maintenspent = [] | |||
for m in mainten: | |||
maintenpoint = {} | |||
cost = calculate_total_cost(m.CarParts) | |||
totalmaintenspent += cost | |||
maintenpoint["cost"] = cost | |||
maintenpoint["total"] = totalmaintenspent | |||
maintenpoint["date"] = m.Date | |||
maintenspent.append(maintenpoint) | |||
res["MaintenanceSpent"] = maintenspent | |||
res["TotalMaintenanceSpent"] = totalmaintenspent | |||
return res |
@@ -21,3 +21,4 @@ class ShowCarPart(BaseModel): | |||
Number: str = Field(...) | |||
Condition: str = Field(...) | |||
Cost: int = Field(...) | |||
image: str = Field(...) |
@@ -19,6 +19,8 @@ class ShowTask(BaseModel): | |||
StartLocation: tuple[str, str] | |||
EndLocation: tuple[str, str] | |||
StartDateTime: Optional[datetime] | |||
DistanceCovered: Optional[float] | |||
EndDateTime: Optional[datetime] | |||
class Config: | |||
orm_mode = True |
@@ -1,16 +1,17 @@ | |||
from pydantic import BaseModel, Field | |||
from fastapi import Form, UploadFile | |||
from datetime import datetime | |||
from schemas.user import ShowDriver | |||
class CreateFuelingTask(BaseModel): | |||
VehicleId: int = Field(...) | |||
Description: str = Field(...) | |||
Date: datetime = Field(...) | |||
Cost: int = Field(...) | |||
FuelRefilled: int = Field(...) | |||
GasStationName: str = Field(...) | |||
ImageBefore: bytearray = Field(...) | |||
ImageAfter: bytearray = Field(...) | |||
VehicleId: int = Form(...) | |||
Description: str = Form(...) | |||
Date: datetime = Form(...) | |||
Cost: int = Form(...) | |||
FuelRefilled: int = Form(...) | |||
GasStationName: str = Form(...) | |||
ImageBefore: UploadFile = Form(...) | |||
ImageAfter: UploadFile = Form(...) | |||
model_config={ | |||
"arbitrary_types_allowed": True | |||
} | |||
@@ -22,9 +23,9 @@ class OutputFuelingTask(BaseModel): | |||
Cost: int = Field(...) | |||
FuelRefilled: int = Field(...) | |||
GasStationName: str = Field(...) | |||
ImageBefore: bytearray = Field(...) | |||
ImageAfter: bytearray = Field(...) | |||
Driver: ShowDriver | None | |||
ImageBefore: str = Field(...) | |||
ImageAfter: str = Field(...) | |||
model_config={ | |||
"arbitrary_types_allowed": True | |||
} |
@@ -9,6 +9,7 @@ from schemas.vehicle import OutputVehicle | |||
class CreateMaintenanceJob(BaseModel): | |||
Description: str = Field(...) | |||
VehicleID: int = Field(...) | |||
VehicleDriverId: int = Field(...) | |||
Date: datetime = Field(...) | |||