@@ -9,6 +9,7 @@ from apis.v1 import ( | |||||
route_maintenancejob, | route_maintenancejob, | ||||
route_fuelingtask, | route_fuelingtask, | ||||
route_auction, | route_auction, | ||||
route_report | |||||
) | ) | ||||
api_router = APIRouter() | 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_fuelingtask.router, prefix="/fuel", tags=["fueltasks"]) | ||||
api_router.include_router(route_auction.router, prefix="/auction", tags=["auctions"]) | 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 = APIRouter() | ||||
@router.post("/", status_code=status.HTTP_201_CREATED) | |||||
@router.post("/", response_model=OutputFuelingTask, status_code=status.HTTP_201_CREATED) | |||||
def create_fuelingtask( | def create_fuelingtask( | ||||
fuelingtask: CreateFuelingTask, | |||||
fuelingtask: CreateFuelingTask = Depends(), | |||||
db: Session = Depends(get_db), | db: Session = Depends(get_db), | ||||
current_user: User = Depends(get_current_user), | current_user: User = Depends(get_current_user), | ||||
): | ): | ||||
@@ -26,7 +26,7 @@ def create_fuelingtask( | |||||
fuelingtask_res = create_fueling_task( | fuelingtask_res = create_fueling_task( | ||||
fueling_task=fuelingtask, current_user=current_user.Id, db=db | fueling_task=fuelingtask, current_user=current_user.Id, db=db | ||||
) | ) | ||||
print("Created FuelTask") | |||||
if fuelingtask_res == "nodriver": | if fuelingtask_res == "nodriver": | ||||
raise HTTPException( | raise HTTPException( | ||||
status_code=404, detail="Driver ID not found" | 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( | def changeStatus( | ||||
task_id: int, | task_id: int, | ||||
status: str, | status: str, | ||||
distance: float = 0, | |||||
db: Session = Depends(get_db), | db: Session = Depends(get_db), | ||||
current_user: User = Depends(get_current_user), | current_user: User = Depends(get_current_user), | ||||
): | ): | ||||
@@ -59,7 +60,7 @@ def changeStatus( | |||||
status_code=403, | status_code=403, | ||||
detail="You are not authorized to perform this action", | 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": | if task == "notaskfound": | ||||
raise HTTPException( | raise HTTPException( | ||||
status_code=404, detail=f"Task with id {task_id} not found" | 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 db.base import Base | ||||
from sqlalchemy.orm import relationship | from sqlalchemy.orm import relationship | ||||
@@ -11,4 +11,6 @@ class DriveTask(Base): | |||||
Status = Column(String, nullable=False) | Status = Column(String, nullable=False) | ||||
StartLocation = Column(ARRAY(String), nullable=False) | StartLocation = Column(ARRAY(String), nullable=False) | ||||
EndLocation = 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) | Id = Column(Integer, primary_key=True, index=True) | ||||
# a list of weak entities of class CarPart | # a list of weak entities of class CarPart | ||||
CarParts = relationship("CarPart", back_populates="parent") | 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) | VehicleID = Column(ForeignKey("vehicle.Id"), nullable=False) | ||||
Vehicle = relationship("Vehicle", back_populates="maintenanceJobs") | Vehicle = relationship("Vehicle", back_populates="maintenanceJobs") | ||||
VehicleDriverId = Column(ForeignKey("user.Id"), nullable=False) | |||||
Description = Column(String, nullable=False) | Description = Column(String, nullable=False) | ||||
Date = Column(DateTime, nullable=False) | Date = Column(DateTime, nullable=False) | ||||
MaintenanceWorker = Column(ForeignKey("user.Id"), nullable=False) | MaintenanceWorker = Column(ForeignKey("user.Id"), nullable=False) |
@@ -25,7 +25,7 @@ class User(Base): | |||||
driveTasks = relationship("DriveTask", back_populates="CreatedBy") | driveTasks = relationship("DriveTask", back_populates="CreatedBy") | ||||
vehicle = relationship("Vehicle", back_populates="driver") | vehicle = relationship("Vehicle", back_populates="driver") | ||||
#MaintenancePerson-specific relationships | #MaintenancePerson-specific relationships | ||||
maintenanceJobs = relationship("MaintenanceJob", back_populates="CreatedBy") | |||||
maintenanceJobs = relationship("MaintenanceJob", back_populates="CreatedBy", foreign_keys="MaintenanceJob.MaintenanceWorker") | |||||
#FuelingPerson-specific relationships | #FuelingPerson-specific relationships | ||||
fuelingTasks = relationship("FuelingTask", back_populates="CreatedBy", foreign_keys="FuelingTask.CreatedById") | fuelingTasks = relationship("FuelingTask", back_populates="CreatedBy", foreign_keys="FuelingTask.CreatedById") | ||||
@@ -1,3 +1,4 @@ | |||||
from datetime import datetime | |||||
from sqlalchemy.orm import Session | from sqlalchemy.orm import Session | ||||
from schemas.drivetask import CreateTask | from schemas.drivetask import CreateTask | ||||
@@ -24,16 +25,16 @@ def create_new_task(task: CreateTask, db: Session): | |||||
return task_object | 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() | task = db.query(DriveTask).filter(DriveTask.Id == task_id).first() | ||||
if not task: | if not task: | ||||
return "notaskfound" | return "notaskfound" | ||||
if status == "In Progress": | if status == "In Progress": | ||||
# see if there are any other tasks in progress by this driver, if yes, cancel | # 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 | task.Status = status | ||||
db.commit() | db.commit() | ||||
db.refresh(task) | db.refresh(task) | ||||
@@ -1,7 +1,8 @@ | |||||
import base64 | |||||
from sqlalchemy.orm import Session | from sqlalchemy.orm import Session | ||||
from schemas.fuelingtask import CreateFuelingTask | |||||
from schemas.fuelingtask import CreateFuelingTask, OutputFuelingTask | |||||
from db.models.fuelingtask import FuelingTask | from db.models.fuelingtask import FuelingTask | ||||
from db.repository.user import get_car_driver, get_user_by_id | from db.repository.user import get_car_driver, get_user_by_id | ||||
from db.repository.vehicle import get_vehicle_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, | Cost=fueling_task.Cost, | ||||
FuelRefilled=fueling_task.FuelRefilled, | FuelRefilled=fueling_task.FuelRefilled, | ||||
GasStationName=fueling_task.GasStationName, | 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.add(fueling_task_object) | ||||
db.commit() | db.commit() | ||||
db.refresh(fueling_task_object) | 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 | return fueling_task_object | ||||
@@ -49,6 +54,12 @@ def get_fueling_task_by_id(fuel_task_id: int, db: Session): | |||||
res = fuel_task.__dict__ | res = fuel_task.__dict__ | ||||
driver = get_user_by_id(fuel_task.DriverId, role="Driver", db=db) | driver = get_user_by_id(fuel_task.DriverId, role="Driver", db=db) | ||||
driver_obj = driver.__dict__ | 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"] = driver_obj | ||||
res["Driver"]["AssignedVehicle"] = driver.vehicle | res["Driver"]["AssignedVehicle"] = driver.vehicle | ||||
return fuel_task | |||||
return res |
@@ -1,8 +1,10 @@ | |||||
import base64 | |||||
from sqlalchemy.orm import Session | from sqlalchemy.orm import Session | ||||
from schemas.maintenancejob import CreateMaintenanceJob | from schemas.maintenancejob import CreateMaintenanceJob | ||||
from db.models.maintenancejob import MaintenanceJob | from db.models.maintenancejob import MaintenanceJob | ||||
from schemas.carpart import CreateCarPart | from schemas.carpart import CreateCarPart | ||||
from db.models.carpart import CarPart | from db.models.carpart import CarPart | ||||
from db.repository.user import get_car_driver | |||||
def create_new_maintenancejob( | def create_new_maintenancejob( | ||||
@@ -13,6 +15,7 @@ def create_new_maintenancejob( | |||||
Description=maintenancejob.Description, | Description=maintenancejob.Description, | ||||
VehicleID=maintenancejob.VehicleID, | VehicleID=maintenancejob.VehicleID, | ||||
Date=maintenancejob.Date, | Date=maintenancejob.Date, | ||||
VehicleDriverId=get_car_driver(maintenancejob.VehicleID, db).Id, | |||||
) | ) | ||||
print("OBJECT CREATED") | print("OBJECT CREATED") | ||||
db.add(maintenancejob_object) | db.add(maintenancejob_object) | ||||
@@ -36,7 +39,9 @@ def create_car_part(car_part: CreateCarPart, db: Session): | |||||
print("OBJECT SAVED") | print("OBJECT SAVED") | ||||
db.refresh(car_part_object) | db.refresh(car_part_object) | ||||
print("OBJECT REFRESHED") | 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): | def calculate_total_cost(car_parts: CarPart): | ||||
@@ -52,6 +57,8 @@ def get_all_maintenance_jobs(db: Session): | |||||
for job in maintenancejobs: | for job in maintenancejobs: | ||||
job_dict = job.__dict__ | job_dict = job.__dict__ | ||||
job_dict["CarPartsList"] = [part.__dict__ for part in job.CarParts] | 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["TotalCost"] = calculate_total_cost(job.CarParts) | ||||
job_dict["AssignedTo"] = job.CreatedBy.__dict__ | job_dict["AssignedTo"] = job.CreatedBy.__dict__ | ||||
job_dict["Vehicle"] = job.Vehicle.__dict__ | job_dict["Vehicle"] = job.Vehicle.__dict__ | ||||
@@ -63,13 +70,16 @@ def get_maintenance_job(maintenancejob_id: int, db: Session): | |||||
maintenancejob = ( | maintenancejob = ( | ||||
db.query(MaintenanceJob).filter(MaintenanceJob.Id == maintenancejob_id).first() | 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)) | # print(type(result.CarPartsList)) | ||||
maintenancejob.TotalCost = calculate_total_cost(maintenancejob.CarParts) | |||||
res["TotalCost"] = calculate_total_cost(maintenancejob.CarParts) | |||||
# print(result.TotalCost) | # 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") | print("DB Access complete") | ||||
return maintenancejob | 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(...) | Number: str = Field(...) | ||||
Condition: str = Field(...) | Condition: str = Field(...) | ||||
Cost: int = Field(...) | Cost: int = Field(...) | ||||
image: str = Field(...) |
@@ -19,6 +19,8 @@ class ShowTask(BaseModel): | |||||
StartLocation: tuple[str, str] | StartLocation: tuple[str, str] | ||||
EndLocation: tuple[str, str] | EndLocation: tuple[str, str] | ||||
StartDateTime: Optional[datetime] | StartDateTime: Optional[datetime] | ||||
DistanceCovered: Optional[float] | |||||
EndDateTime: Optional[datetime] | |||||
class Config: | class Config: | ||||
orm_mode = True | orm_mode = True |
@@ -1,16 +1,17 @@ | |||||
from pydantic import BaseModel, Field | from pydantic import BaseModel, Field | ||||
from fastapi import Form, UploadFile | |||||
from datetime import datetime | from datetime import datetime | ||||
from schemas.user import ShowDriver | from schemas.user import ShowDriver | ||||
class CreateFuelingTask(BaseModel): | 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={ | model_config={ | ||||
"arbitrary_types_allowed": True | "arbitrary_types_allowed": True | ||||
} | } | ||||
@@ -22,9 +23,9 @@ class OutputFuelingTask(BaseModel): | |||||
Cost: int = Field(...) | Cost: int = Field(...) | ||||
FuelRefilled: int = Field(...) | FuelRefilled: int = Field(...) | ||||
GasStationName: str = Field(...) | GasStationName: str = Field(...) | ||||
ImageBefore: bytearray = Field(...) | |||||
ImageAfter: bytearray = Field(...) | |||||
Driver: ShowDriver | None | Driver: ShowDriver | None | ||||
ImageBefore: str = Field(...) | |||||
ImageAfter: str = Field(...) | |||||
model_config={ | model_config={ | ||||
"arbitrary_types_allowed": True | "arbitrary_types_allowed": True | ||||
} | } |
@@ -9,6 +9,7 @@ from schemas.vehicle import OutputVehicle | |||||
class CreateMaintenanceJob(BaseModel): | class CreateMaintenanceJob(BaseModel): | ||||
Description: str = Field(...) | Description: str = Field(...) | ||||
VehicleID: int = Field(...) | VehicleID: int = Field(...) | ||||
VehicleDriverId: int = Field(...) | |||||
Date: datetime = Field(...) | Date: datetime = Field(...) | ||||