|
- from datetime import datetime
- from fastapi.responses import StreamingResponse
- 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
-
- from reportlab.lib import colors
- from reportlab.lib.pagesizes import letter
- from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Image, PageBreak
- from reportlab.lib.styles import getSampleStyleSheet
- from reportlab.lib.units import inch
- from reportlab.graphics.shapes import Drawing
- from reportlab.graphics.charts.linecharts import HorizontalLineChart
- from reportlab.graphics.widgets.markers import makeMarker
- from reportlab.platypus import Spacer
- from reportlab.graphics.charts.axes import CategoryAxis
- from dateutil import parser
-
-
- 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
-
- def get_pdf(driver_id: int, db: Session):
- report_data = get_repot_jobsdone_by_driver(driver_id, db)
- if report_data == "notdriver":
- return "notdriver"
-
- # Assuming your report data is stored in a variable named 'report_data'
-
- # Create a PDF document
- pdf_filename = "report1.pdf"
- document = SimpleDocTemplate(pdf_filename, pagesize=letter)
-
- # Create a list to hold the contents of the PDF
- content = []
-
- # Add a title to the PDF
- title_style = getSampleStyleSheet()['Title']
- title = Paragraph("Driver Report", title_style)
- content.append(title)
- content.append(Paragraph("<br/>", title_style))
-
- print(report_data["Driver"])
-
- # Add detailed information about the driver
- driver_info = [
- ["Driver Name", report_data["Driver"]["Name"]],
- ["Last Name", report_data["Driver"]["LastName"]],
- ["Government ID", report_data["Driver"]["GovernmentId"]],
- ["Email", report_data["Driver"]["Email"]],
- ["Contact Number", report_data["Driver"]["ContactNumber"]],
- ["Address", report_data["Driver"]["Address"]],
- ["Role", report_data["Driver"]["Role"]],
- ]
-
- driver_table_style = TableStyle([
- ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
- ('BOX', (0, 0), (-1, -1), 1, colors.black),
- ])
-
- driver_table = Table(driver_info, style=driver_table_style)
- content.append(Paragraph("<br/><br/>", title_style))
-
- vehicle = report_data["Driver"]["AssignedVehicle"].__dict__
- print(vehicle)
- loc = vehicle["CurrentLocation"][0]
- if len(vehicle["CurrentLocation"]) > 1:
- loc += ", " + vehicle["CurrentLocation"][1]
- # Add vehicle details
- vehicle_info = [
- ["Vehicle Type", vehicle["Type"]],
- ["Vehicle Model", vehicle["Model"]],
- ["Year", vehicle["Year"]],
- ["License Plate", vehicle["LicensePlate"]],
- ["Current Location", loc],
- ["Mileage", vehicle["Mileage"]],
- ["Capacity", vehicle["Capacity"]],
- ]
-
-
- vehicle_table_style = TableStyle([
- ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
- ('BOX', (0, 0), (-1, -1), 1, colors.black),
- ])
-
- vehicle_table = Table(vehicle_info, style=vehicle_table_style)
- content.append(Spacer(1, 12)) # Add space between the tables
- content.append(Table([[driver_table, vehicle_table]]))
- content.append(Paragraph("<br/><br/>", title_style))
-
- total_info = [
- ["Total Tasks Done", report_data["tasks"].__len__()],
- ["Total Fuel Spent", report_data["TotalFuelSpent"]],
- ["Total Time Spent", report_data["TotalTime"]],
- ["Total Distance Driven", report_data["TotalDistance"]],
- ["Total Money Spent", report_data["TotalMaintenanceSpent"]],
- ]
-
- total_table_style = TableStyle([
- ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
- ('BOX', (0, 0), (-1, -1), 1, colors.black),
- ])
-
- total_table = Table(total_info, style=total_table_style)
- content.append(total_table)
- content.append(Paragraph("<br/><br/>", title_style))
-
- content.append(PageBreak())
-
-
-
-
-
- title_style = getSampleStyleSheet()["Heading1"]
- content.append(Paragraph("Driving Tasks", title_style))
-
- title_style = getSampleStyleSheet()["Heading2"]
- content.append(Paragraph("Distance Driven over Time", title_style))
- tasks_data = report_data["tasks"]
- if tasks_data.__len__() == 0:
- content.append(Paragraph("No tasks done.", title_style))
- else:
- task_values = [entry["DistanceAtTime"] for entry in tasks_data]
- task_dates = [parser.parse(entry['EndDateTime']).strftime("%m/%d/%Y, %H:%M:%S") for entry in tasks_data]
-
- drawing = Drawing(width=400, height=200)
- chart = HorizontalLineChart()
- chart.x = 0
- chart.y = 50
- chart.width = 500
- chart.height = 125
- chart.data = [task_values]
- chart.categoryAxis.labels.boxAnchor = 'e'
- chart.valueAxis.valueMin = 0
- chart.valueAxis.valueMax = max(task_values) + 10
- chart.lines[0].strokeColor = colors.blue
- chart.lines[0].strokeWidth = 2
- chart.categoryAxis.categoryNames = [str(date) for date in task_dates]
- chart.categoryAxis.labels.angle = 90
- drawing.add(chart)
-
- # Add space between the tables
- content.append(drawing)
- content.append(Paragraph("<br/><br/>", title_style))
- content.append(Paragraph("<br/><br/>", title_style))
- content.append(Paragraph("<br/><br/>", title_style))
-
-
- # Add tasks information
- title_style = getSampleStyleSheet()["Heading2"]
- content.append(Paragraph("All DriveTasks", title_style))
- tasks_header = ["Task ID", "Description", "Start Location", "End Location", "Distance Covered", "Status", "Start DateTime", "End DateTime"]
- tasks_info = []
-
- for task in tasks_data:
- task_info = [f"{task['Id']}", task["Description"], f"{task['StartLocation'][0]}, {task['StartLocation'][1]}", f"{task['EndLocation'][0]}, {task['EndLocation'][1]}",
- "{} km".format(task["DistanceCovered"]), task["Status"], task['StartDateTime'].strftime("%m/%d/%Y, %H:%M:%S"), parser.parse(task['EndDateTime']).strftime("%m/%d/%Y, %H:%M:%S")]
- tasks_info.append(task_info)
-
- # Define the styles
- styles = getSampleStyleSheet()
- normal_style = styles["Normal"]
-
- # Convert strings to Paragraphs to allow line breaks
- for row in tasks_info:
- for i, cell in enumerate(row):
- row[i] = Paragraph(cell, normal_style)
-
- tasks_table_style = TableStyle([
- ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
- ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
- ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
- ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
- ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
- ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
- ('GRID', (0, 0), (-1, -1), 1, colors.black),
- ])
-
- tasks_table = Table([tasks_header] + tasks_info, style=tasks_table_style)
- content.append(tasks_table)
-
-
-
-
-
- content.append(PageBreak())
-
-
- title_style = getSampleStyleSheet()["Heading1"]
- content.append(Paragraph("Fuel Spent Over Time", title_style))
- # Add chart of fuel spendings
- fuel_spent_data = report_data["FuelSpent"]
- if fuel_spent_data.__len__() == 0:
- content.append(Paragraph("No fuel spent.", title_style))
- else:
- fuel_values = [entry["total"] for entry in fuel_spent_data]
- fuel_dates = [entry["date"] for entry in fuel_spent_data]
-
- drawing = Drawing(width=400, height=200)
- chart = HorizontalLineChart()
- chart.x = 0
- chart.y = 50
- chart.width = 500
- chart.height = 125
- chart.data = [fuel_values]
- chart.categoryAxis.labels.boxAnchor = 'e'
- chart.valueAxis.valueMin = 0
- chart.valueAxis.valueMax = max(fuel_values) + 10
- chart.lines[0].strokeColor = colors.blue
- chart.lines[0].strokeWidth = 2
- chart.categoryAxis.categoryNames = [str(date) for date in fuel_dates]
- chart.categoryAxis.labels.angle = 90
- drawing.add(chart)
-
- # Add space between the tables
- content.append(drawing)
- content.append(Paragraph("<br/><br/>", title_style))
-
- fuel_header = ["Date", "Fuel Refilled", "Total Fuel Spent"]
- fuel_info = []
-
- for fuel in fuel_spent_data:
- fuel_info1 = [fuel["date"].strftime("%m/%d/%Y, %H:%M:%S"), "{} L".format(fuel["fuelrefilled"]), "{} L".format(fuel["total"])]
- fuel_info.append(fuel_info1)
-
- # Define the styles
- styles = getSampleStyleSheet()
- normal_style = styles["Normal"]
-
- # Convert strings to Paragraphs to allow line breaks
- for row in fuel_info:
- for i, cell in enumerate(row):
- row[i] = Paragraph(cell, normal_style)
-
- fuel_table_style = TableStyle([
- ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
- ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
- ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
- ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
- ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
- ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
- ('GRID', (0, 0), (-1, -1), 1, colors.black),
- ])
-
- fuel_table = Table([fuel_header] + fuel_info, style=fuel_table_style)
- content.append(fuel_table)
-
- content.append(PageBreak())
-
-
- title_style = getSampleStyleSheet()["Heading1"]
- content.append(Paragraph("Maintenance Over Time", title_style))
- # Add chart of fuel spendings
- maintenance_data = report_data["MaintenanceSpent"]
- if maintenance_data.__len__() == 0:
- content.append(Paragraph("No maintenance done.", title_style))
- else:
- maintenance_values = [entry["total"] for entry in maintenance_data]
- maintenance_dates = [entry["date"] for entry in maintenance_data]
-
- drawing = Drawing(width=400, height=200)
- chart = HorizontalLineChart()
- chart.x = 0
- chart.y = 50
- chart.width = 500
- chart.height = 125
- chart.data = [maintenance_values]
- chart.categoryAxis.labels.boxAnchor = 'e'
- chart.valueAxis.valueMin = 0
- chart.valueAxis.valueMax = max(maintenance_values) + 10
- chart.lines[0].strokeColor = colors.blue
- chart.lines[0].strokeWidth = 2
- chart.categoryAxis.categoryNames = [str(date) for date in maintenance_dates]
- chart.categoryAxis.labels.angle = 90
- drawing.add(chart)
-
- # Add space between the tables
- content.append(drawing)
- content.append(Paragraph("<br/><br/>", title_style))
-
- maintenance_header = ["Date", "Maintenance Cost", "Total Maintenance Cost"]
- maintenance_info = []
-
- for fuel in maintenance_data:
- fuel_info1 = [fuel["date"].strftime("%m/%d/%Y, %H:%M:%S"), "{} L".format(fuel["cost"]), "{} L".format(fuel["total"])]
- maintenance_info.append(fuel_info1)
-
- # Define the styles
- styles = getSampleStyleSheet()
- normal_style = styles["Normal"]
-
- # Convert strings to Paragraphs to allow line breaks
- for row in maintenance_info:
- for i, cell in enumerate(row):
- row[i] = Paragraph(cell, normal_style)
-
- maintenance_table_style = TableStyle([
- ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
- ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
- ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
- ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
- ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
- ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
- ('GRID', (0, 0), (-1, -1), 1, colors.black),
- ])
-
- maintenance_table = Table([maintenance_header] + maintenance_info, style=maintenance_table_style)
- content.append(maintenance_table)
-
-
-
-
- document.build(content)
-
- print(f"PDF generated successfully: {pdf_filename}")
-
- return pdf_filename
|