Browse Source

added reports

main
Madiwka 1 year ago
parent
commit
f9b3fe31a2
15 changed files with 166 additions and 33 deletions
  1. +2
    -0
      app/apis/base.py
  2. +3
    -3
      app/apis/v1/route_fuelingtask.py
  3. +22
    -0
      app/apis/v1/route_report.py
  4. +2
    -1
      app/apis/v1/route_task.py
  5. +4
    -2
      app/db/models/drivetask.py
  6. +2
    -1
      app/db/models/maintenancejob.py
  7. +1
    -1
      app/db/models/user.py
  8. +6
    -5
      app/db/repository/drivetask.py
  9. +15
    -4
      app/db/repository/fuelingtask.py
  10. +16
    -6
      app/db/repository/maintenancejob.py
  11. +78
    -0
      app/db/repository/report.py
  12. +1
    -0
      app/schemas/carpart.py
  13. +2
    -0
      app/schemas/drivetask.py
  14. +11
    -10
      app/schemas/fuelingtask.py
  15. +1
    -0
      app/schemas/maintenancejob.py

+ 2
- 0
app/apis/base.py View File

@@ -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"])

+ 3
- 3
app/apis/v1/route_fuelingtask.py View File

@@ -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"


+ 22
- 0
app/apis/v1/route_report.py View File

@@ -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

+ 2
- 1
app/apis/v1/route_task.py View File

@@ -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"


+ 4
- 2
app/db/models/drivetask.py View File

@@ -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)

+ 2
- 1
app/db/models/maintenancejob.py View File

@@ -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)

+ 1
- 1
app/db/models/user.py View File

@@ -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")


+ 6
- 5
app/db/repository/drivetask.py View File

@@ -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)


+ 15
- 4
app/db/repository/fuelingtask.py View File

@@ -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

+ 16
- 6
app/db/repository/maintenancejob.py View File

@@ -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



+ 78
- 0
app/db/repository/report.py View File

@@ -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

+ 1
- 0
app/schemas/carpart.py View File

@@ -21,3 +21,4 @@ class ShowCarPart(BaseModel):
Number: str = Field(...)
Condition: str = Field(...)
Cost: int = Field(...)
image: str = Field(...)

+ 2
- 0
app/schemas/drivetask.py View File

@@ -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

+ 11
- 10
app/schemas/fuelingtask.py View File

@@ -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
}

+ 1
- 0
app/schemas/maintenancejob.py View File

@@ -9,6 +9,7 @@ from schemas.vehicle import OutputVehicle
class CreateMaintenanceJob(BaseModel):
Description: str = Field(...)
VehicleID: int = Field(...)
VehicleDriverId: int = Field(...)
Date: datetime = Field(...)




Loading…
Cancel
Save