| @@ -10,7 +10,14 @@ 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.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 | |||
| @@ -27,10 +34,14 @@ def get_repot_jobsdone_by_driver(driver_id: int, db: Session): | |||
| 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 = ( | |||
| 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 | |||
| # for each task, add TOTAL distance driven at the time of completion | |||
| dist = 0 | |||
| taskslist = [] | |||
| for task in tasks: | |||
| @@ -46,19 +57,21 @@ def get_repot_jobsdone_by_driver(driver_id: int, db: Session): | |||
| dist += task.DistanceCovered | |||
| res["TotalDistance"] = dist | |||
| timespent = 0.0 | |||
| for task in tasks: | |||
| edate = task.EndDateTime | |||
| sdate = task.StartDateTime | |||
| if edate is None or sdate is None: | |||
| continue | |||
| 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 | |||
| # time spent in hours and minutes | |||
| hours = timespent // 3600 | |||
| minutes = (timespent % 3600) // 60 | |||
| res["TotalTime"] = str(hours) + " hours " + str(minutes) + " minutes" | |||
| #add fuel expenditures | |||
| # add fuel expenditures | |||
| fuel = db.query(FuelingTask).filter(FuelingTask.DriverId == driver_id).all() | |||
| fuel.sort(key=lambda x: x.Date) | |||
| totalfuelspent = 0 | |||
| @@ -72,9 +85,13 @@ def get_repot_jobsdone_by_driver(driver_id: int, db: Session): | |||
| fuelspent.append(fuelpoint) | |||
| res["FuelSpent"] = fuelspent | |||
| res["TotalFuelSpent"] = totalfuelspent | |||
| #add maintenance costs | |||
| mainten = db.query(MaintenanceJob).filter(MaintenanceJob.VehicleDriverId == driver_id).all() | |||
| # add maintenance costs | |||
| mainten = ( | |||
| db.query(MaintenanceJob) | |||
| .filter(MaintenanceJob.VehicleDriverId == driver_id) | |||
| .all() | |||
| ) | |||
| mainten.sort(key=lambda x: x.Date) | |||
| totalmaintenspent = 0 | |||
| maintenspent = [] | |||
| @@ -90,6 +107,7 @@ def get_repot_jobsdone_by_driver(driver_id: int, db: Session): | |||
| 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": | |||
| @@ -105,11 +123,11 @@ def get_pdf(driver_id: int, db: Session): | |||
| content = [] | |||
| # Add a title to the PDF | |||
| title_style = getSampleStyleSheet()['Title'] | |||
| 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 | |||
| @@ -123,10 +141,12 @@ def get_pdf(driver_id: int, db: Session): | |||
| ["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_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)) | |||
| @@ -147,17 +167,18 @@ def get_pdf(driver_id: int, db: Session): | |||
| ["Capacity", vehicle["Capacity"]], | |||
| ] | |||
| vehicle_table_style = TableStyle([ | |||
| ('ALIGN', (0, 0), (-1, -1), 'LEFT'), | |||
| ('BOX', (0, 0), (-1, -1), 1, colors.black), | |||
| ]) | |||
| 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"]], | |||
| @@ -166,10 +187,12 @@ def get_pdf(driver_id: int, db: Session): | |||
| ["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_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) | |||
| @@ -177,10 +200,6 @@ def get_pdf(driver_id: int, db: Session): | |||
| content.append(PageBreak()) | |||
| title_style = getSampleStyleSheet()["Heading1"] | |||
| content.append(Paragraph("Driving Tasks", title_style)) | |||
| @@ -191,7 +210,10 @@ def get_pdf(driver_id: int, db: Session): | |||
| 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] | |||
| 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() | |||
| @@ -200,7 +222,7 @@ def get_pdf(driver_id: int, db: Session): | |||
| chart.width = 500 | |||
| chart.height = 125 | |||
| chart.data = [task_values] | |||
| chart.categoryAxis.labels.boxAnchor = 'e' | |||
| chart.categoryAxis.labels.boxAnchor = "e" | |||
| chart.valueAxis.valueMin = 0 | |||
| chart.valueAxis.valueMax = max(task_values) + 10 | |||
| chart.lines[0].strokeColor = colors.blue | |||
| @@ -215,18 +237,34 @@ def get_pdf(driver_id: int, db: Session): | |||
| 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_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")] | |||
| 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"] | |||
| @@ -235,30 +273,27 @@ def get_pdf(driver_id: int, db: Session): | |||
| 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_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()) | |||
| content.append(PageBreak()) | |||
| title_style = getSampleStyleSheet()["Heading1"] | |||
| content.append(Paragraph("Fuel Spent Over Time", title_style)) | |||
| # Add chart of fuel spendings | |||
| # 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)) | |||
| @@ -273,7 +308,7 @@ def get_pdf(driver_id: int, db: Session): | |||
| chart.width = 500 | |||
| chart.height = 125 | |||
| chart.data = [fuel_values] | |||
| chart.categoryAxis.labels.boxAnchor = 'e' | |||
| chart.categoryAxis.labels.boxAnchor = "e" | |||
| chart.valueAxis.valueMin = 0 | |||
| chart.valueAxis.valueMax = max(fuel_values) + 10 | |||
| chart.lines[0].strokeColor = colors.blue | |||
| @@ -285,14 +320,18 @@ def get_pdf(driver_id: int, db: Session): | |||
| # 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_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"] | |||
| @@ -301,26 +340,27 @@ def get_pdf(driver_id: int, db: Session): | |||
| 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_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()) | |||
| content.append(PageBreak()) | |||
| title_style = getSampleStyleSheet()["Heading1"] | |||
| content.append(Paragraph("Maintenance Over Time", title_style)) | |||
| # Add chart of fuel spendings | |||
| # Add chart of fuel spendings | |||
| maintenance_data = report_data["MaintenanceSpent"] | |||
| if maintenance_data.__len__() == 0: | |||
| content.append(Paragraph("No maintenance done.", title_style)) | |||
| @@ -335,7 +375,7 @@ def get_pdf(driver_id: int, db: Session): | |||
| chart.width = 500 | |||
| chart.height = 125 | |||
| chart.data = [maintenance_values] | |||
| chart.categoryAxis.labels.boxAnchor = 'e' | |||
| chart.categoryAxis.labels.boxAnchor = "e" | |||
| chart.valueAxis.valueMin = 0 | |||
| chart.valueAxis.valueMax = max(maintenance_values) + 10 | |||
| chart.lines[0].strokeColor = colors.blue | |||
| @@ -347,14 +387,18 @@ def get_pdf(driver_id: int, db: Session): | |||
| # 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"])] | |||
| 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"] | |||
| @@ -363,25 +407,26 @@ def get_pdf(driver_id: int, db: Session): | |||
| 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) | |||
| 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 | |||