|
@@ -1,4 +1,5 @@ |
|
|
from datetime import datetime |
|
|
from datetime import datetime |
|
|
|
|
|
from fastapi.responses import StreamingResponse |
|
|
from sqlalchemy.orm import Session |
|
|
from sqlalchemy.orm import Session |
|
|
from db.models.drivetask import DriveTask |
|
|
from db.models.drivetask import DriveTask |
|
|
|
|
|
|
|
@@ -7,6 +8,18 @@ from db.models.fuelingtask import FuelingTask |
|
|
from db.models.maintenancejob import MaintenanceJob |
|
|
from db.models.maintenancejob import MaintenanceJob |
|
|
from db.repository.maintenancejob import calculate_total_cost |
|
|
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): |
|
|
def get_repot_jobsdone_by_driver(driver_id: int, db: Session): |
|
|
driver = db.query(User).filter(User.Id == driver_id).first() |
|
|
driver = db.query(User).filter(User.Id == driver_id).first() |
|
@@ -75,4 +88,300 @@ def get_repot_jobsdone_by_driver(driver_id: int, db: Session): |
|
|
maintenspent.append(maintenpoint) |
|
|
maintenspent.append(maintenpoint) |
|
|
res["MaintenanceSpent"] = maintenspent |
|
|
res["MaintenanceSpent"] = maintenspent |
|
|
res["TotalMaintenanceSpent"] = totalmaintenspent |
|
|
res["TotalMaintenanceSpent"] = totalmaintenspent |
|
|
return res |
|
|
|
|
|
|
|
|
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 |