diff --git a/techdb/flightslot/actions/exportweek.py b/techdb/flightslot/actions/exportweek.py index 3d9035f..241a66e 100644 --- a/techdb/flightslot/actions/exportweek.py +++ b/techdb/flightslot/actions/exportweek.py @@ -3,14 +3,15 @@ from django.db.models.query import QuerySet from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment +from openpyxl.utils import get_column_letter -from datetime import date, datetime, timedelta +from datetime import date, datetime from typing import List -import calendar from ..models.weekpref import WeekPreference from ..models.missions import Training -from ..models.hourbuildings import HourBuilding +from ..models.hourbuildings import HourBuilding,HourBuildingLeg + def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse: @@ -20,9 +21,10 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> # Init Variables year = date.today().year week = queryset.first().week if queryset.first() else date.today().isocalendar().week + weeks = queryset.order_by("week").distinct("week").all() # Prepare export filename and http content - filename = f"{year}-week{week}_export.xlsx" + filename = f"{year}_week{'+'.join([str(w.week) for w in weeks])}_export.xlsx" response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') response['Content-Disposition'] = f'attachment; filename="{filename}"' @@ -31,7 +33,7 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> ws = wb.active if not ws: raise Exception("Export: cannot select active workbook") - ws.title = f"{year} Week {week} Preferences" + ws.title = f"Week Preferences" # Header titles days = [f"{datetime.strptime(f"{year} {week} {x}", "%G %V %u").strftime("%A")} {datetime.strptime(f"{year} {week} {x}", "%G %V %u").day}" for x in range(1,8)] @@ -56,11 +58,9 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> cell.font = bold_white cell.alignment = center - # Scrittura dati + # Fill worksheet with EVERY training and hb for every student row: int = 2 row_offset: int = 0 - - # Fill worksheet with EVERY training and hb for every student for i, q in enumerate(queryset.order_by("student__surname", "student__name", "student__course"), start=1): student_data: List[str] student_phone: str = q.student.phone if q.student.phone else "" @@ -89,7 +89,7 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> mission_name if t.sunday else "" ] mission_notes = t.notes if t.notes else "--" - mission_data.append([str(week), *student_data, *mission_days, student_phone, student_email, mission_notes]) + mission_data.append([str(q.week), *student_data, *mission_days, student_phone, student_email, mission_notes]) # Fill HourBuilding rows hb_name: str @@ -97,7 +97,7 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> hb_notes: str hb_data: List[List[str]] = [] for h in HourBuilding.objects.filter(weekpref = q.id): - hb_name = f"HB-{h.aircraft}" + hb_name = f"HB-{h.aircraft}\nVedi Note ->" hb_days = [ hb_name if h.monday else "", hb_name if h.tuesday else "", @@ -107,18 +107,18 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> hb_name if h.saturday else "", hb_name if h.sunday else "" ] - hb_notes = h.notes if h.notes else "--" - hb_data.append([str(week), *student_data, *hb_days, str(q.student.phone), q.student.email, hb_notes]) + hb_notes = f"{h.notes}\n----\n" if h.notes else "" + hb_legs = HourBuildingLeg.objects.filter(hb_id = h.id) + for hh in hb_legs: + hb_notes += f"{hh.departure} -> {hh.destination} [{hh.time}]\n" if not hh.stop else f"STOP at {hh.departure} [{hh.time}]\n" + hb_notes.strip('\r') + hb_data.append([str(q.week), *student_data, *hb_days, str(q.student.phone), q.student.email, hb_notes]) # Build rows for table + all_data: List[List[str]] = mission_data + hb_data student_start: int = row + row_offset - for r in mission_data + hb_data: - prev_cell_val: str | None = None - merge_start: bool = False - merge_col_start: int = 1 + for r in all_data: for j, c in enumerate(r, start=1): - if prev_cell_val is None: - prev_cell_val = c cell = ws.cell(row = row + row_offset, column = j, value = c) cell.alignment = center # Format Student Name @@ -127,21 +127,27 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> # Format Course Column if j == course_index and q.student.course: cell.fill = PatternFill("solid", fgColor=str(q.student.course.color).lstrip('#').lower()) + + prev_cell_val: str = r[0] + merge_start: bool = False + merge_col_start: int = 1 + for c, v in enumerate(r, start=1): # Merge cells in the row - if c == prev_cell_val and not merge_start: + if v == prev_cell_val and not merge_start: merge_start = True - merge_col_start = max(j-1, 1) - elif c != prev_cell_val and merge_start: + merge_col_start = c-1 # start merge from previous column + elif v != prev_cell_val and merge_start: merge_start = False ws.merge_cells(start_row=row+row_offset, - end_row=row+row_offset, - start_column=merge_col_start, - end_column=max(j-1,1)) + end_row=row+row_offset, + start_column=max(merge_col_start,1), + end_column=max(c-1,1)) # end merge to previous column + prev_cell_val = v # Incement row counter row_offset += 1 - # End f preferences for this student + # End week preferences for this student student_end: int = row + row_offset -1 # Merge Name ws.merge_cells(start_row=student_start, end_row=student_end, start_column=student_index, end_column=student_index) @@ -152,6 +158,14 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> # Merge Mail ws.merge_cells(start_row=student_start, end_row=student_end, start_column=mail_index, end_column=mail_index) + # Keep the largest column + for column_cells in ws.columns: + length: int = max(len(str(cell.value)) for cell in column_cells) + col_letter: str = "A" + if column_cells[0].column: + get_column_letter(column_cells[0].column) + ws.column_dimensions[col_letter].width = length + # Save document in HttpResponse wb.save(response) diff --git a/techdb/static/password b/techdb/static/password new file mode 100644 index 0000000..667feba --- /dev/null +++ b/techdb/static/password @@ -0,0 +1 @@ +admin: CantorAdmin2k25