diff --git a/cntmanage/flightslot/actions/exportweek.py b/cntmanage/flightslot/actions/exportweek.py index 7da0961..6ca40fa 100644 --- a/cntmanage/flightslot/actions/exportweek.py +++ b/cntmanage/flightslot/actions/exportweek.py @@ -5,6 +5,7 @@ from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment, Border, Side from openpyxl.utils import get_column_letter +from ..models.courses import CourseTypes from ..models.missions import Training from ..models.weekpref import WeekPreference from ..models.hourbuildings import HourBuilding, HourBuildingLegFlight, HourBuildingLegStop, HourBuildingLegBase @@ -12,6 +13,19 @@ from ..models.hourbuildings import HourBuilding, HourBuildingLegFlight, HourBuil from datetime import date, datetime from typing import List +# Enable cell merging for equal mission +MERGE: bool = False + +PALETTE : List[str] = [ + "#E6F2FF", # azzurro chiarissimo + "#E5FBF8", # verde acqua molto chiaro + "#ECFBE1", # verde chiarissimo + "#FFFBD1", # giallo molto chiaro + "#FFF1D6", # giallo-arancio molto chiaro + "#FFE3DD", # rosa pesca molto chiaro + "#F3E6FA", # lilla chiarissimo +] + def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse: if not queryset.first(): @@ -84,68 +98,72 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> student_email: str = q.student.email student_course_type: str student_course_number: str - student_course_ac: str + student_course_ac: str = f"({'/'.join(t.type for t in q.student.aircrafts.distinct("type").all())})" if q.student.course: student_course_type = q.student.course.ctype student_course_number = str(q.student.course.cnumber) - student_course_ac = " / ".join(t.type for t in q.student.aircrafts.distinct("type").all()) student_data = [ - f"{q.student.surname} {q.student.name}\n{student_course_ac}", + "\n".join([f"{q.student.surname} {q.student.name}", student_course_ac]), f"{student_course_type}-{student_course_number}" ] else: student_data = [f"{q.student.surname} {q.student.name}", f"No Course Assigned"] # Fill Training mission rows - mission_name: str + mission_name: List[str] mission_days: List[str] mission_notes: str mission_data: List[List[str]] = [] for t in Training.objects.filter(weekpref = q.id): if not t.mission: raise Exception("No Training Mission Assigned") - mission_name = f"{t.mission.mtype}-{t.mission.mnum}" + mission_notes = t.notes.strip().capitalize() if t.notes else "---" + mission_name = [f"{t.mission.mtype}-{t.mission.mnum}"] + if q.student.course and q.student.course.ctype == CourseTypes.PPL: # add course aircraft only for PPL students + mission_name.append(student_course_ac) + mission_name_joined: str = "\n".join(mission_name) mission_days = [ - mission_name if t.monday else "", - mission_name if t.tuesday else "", - mission_name if t.wednesday else "", - mission_name if t.thursday else "", - mission_name if t.friday else "", - mission_name if t.saturday else "", - mission_name if t.sunday else "" + mission_name_joined if t.monday else "", + mission_name_joined if t.tuesday else "", + mission_name_joined if t.wednesday else "", + mission_name_joined if t.thursday else "", + mission_name_joined if t.friday else "", + mission_name_joined if t.saturday else "", + mission_name_joined if t.sunday else "" ] - mission_notes = t.notes.strip() if t.notes else "--" mission_data.append([str(q.week), *student_data, *mission_days, mission_notes, student_phone, student_email, ]) # Fill HourBuilding rows - hb_name: str + hb_name: List[str] hb_days: List[str] hb_data: List[List[str]] = [] for h in HourBuilding.objects.filter(weekpref = q.id): - hb_name = f"HB - {h.aircraft}\nVedi Note ->" - hb_days = [ - hb_name if h.monday else "", - hb_name if h.tuesday else "", - hb_name if h.wednesday else "", - hb_name if h.thursday else "", - hb_name if h.friday else "", - hb_name if h.saturday else "", - hb_name if h.sunday else "" - ] - hb_notes: List[str] = [f"{h.notes.strip()}", "---"] if h.notes else [] + hb_name = ["HB", f"({h.aircraft})"] hb_legs_all = HourBuildingLegBase.objects.filter(hb_id = h.id) for hh in hb_legs_all: time_str: str = ':'.join(str(hh.time).split(':')[:2]) # keep only hours and minutes if isinstance(hh, HourBuildingLegFlight): - hb_notes.append(f"{hh.departure} -> {hh.destination} [{time_str}]{f' / PAX: {hh.pax.capitalize()}' if hh.pax else ''}") + hb_pax: str | None = " ".join(x.capitalize() for x in hh.pax.split()) if hh.pax else None + hb_name.append(f"{hh.departure} -> {hh.destination} [{time_str}]{f' / Pax: {hb_pax}' if hb_pax else ''}") elif isinstance(hh, HourBuildingLegStop): - hb_notes.append(f"STOP [{time_str}] {"Refuel" if hh.refuel else ""}" ) - hb_data.append([str(q.week), *student_data, *hb_days, "\n".join(hb_notes), str(q.student.phone), q.student.email]) + hb_name.append(f"STOP [{time_str}] {"Refuel" if hh.refuel else ""}" ) + hb_name_joined: str = "\n".join(hb_name) + hb_days = [ + hb_name_joined if h.monday else "", + hb_name_joined if h.tuesday else "", + hb_name_joined if h.wednesday else "", + hb_name_joined if h.thursday else "", + hb_name_joined if h.friday else "", + hb_name_joined if h.saturday else "", + hb_name_joined if h.sunday else "" + ] + hb_notes: str = h.notes.strip().capitalize() if h.notes else "" + hb_data.append([str(q.week), *student_data, *hb_days, hb_notes, str(q.student.phone), q.student.email]) # Build rows for table all_data: List[List[str]] = mission_data + hb_data student_start: int = row + row_offset - for row_content in all_data: + for ri, row_content in enumerate(all_data): for c, cell_content in enumerate(row_content, start=1): cell = ws.cell(row = row + row_offset, column = c, value = cell_content) cell.alignment = center @@ -160,25 +178,25 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> elif c > course_index and c <= note_index: cell.border = border_bottom_thin + border_right_thin # Fill mix cells if the cell is not empty - if c > course_index and c < note_index: + if c > course_index and c <= note_index: if len(cell_content): - cell.fill = PatternFill('solid', fgColor="f0f0f0") - - prev_cell_val: str = row_content[0] - merge_start: bool = False - merge_col_start: int = 1 - for c, cell_content in enumerate(row_content, start=1): - # Merge cells in the row - if cell_content == prev_cell_val and not merge_start: - merge_start = True - merge_col_start = c-1 # start merge from previous column - elif cell_content != prev_cell_val and merge_start: - merge_start = False - ws.merge_cells(start_row=row+row_offset, - 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 = cell_content + cell.fill = PatternFill('solid', fgColor=PALETTE[ri % len(PALETTE)].lstrip("#").lower()) + if MERGE: + prev_cell_val: str = row_content[0] + merge_start: bool = False + merge_col_start: int = 1 + for c, cell_content in enumerate(row_content, start=1): + # Merge cells in the row + if cell_content == prev_cell_val and not merge_start: + merge_start = True + merge_col_start = c-1 # start merge from previous column + elif cell_content != prev_cell_val and merge_start: + merge_start = False + ws.merge_cells(start_row=row+row_offset, + 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 = cell_content # Incement row counter row_offset += 1 @@ -208,6 +226,7 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> # Keep the largest column max_len: List[int] = [] + col_letter: str = "A" for column_cells in ws.columns: for cell in column_cells: cell_lines = str(cell.value).splitlines() @@ -215,11 +234,9 @@ def export_selected(request: HttpRequest, queryset: QuerySet[WeekPreference]) -> continue max_len.append(max([len(ll) for ll in cell_lines])) length: int = max(max_len) - col_letter: str = "A" if column_cells[0].column: col_letter = get_column_letter(column_cells[0].column) ws.column_dimensions[col_letter].width = length + 2 - ### End of Student Loop ### # Save document in HttpResponse diff --git a/note.txt b/note.txt new file mode 100644 index 0000000..1562a56 --- /dev/null +++ b/note.txt @@ -0,0 +1,6 @@ +OK leg delle hb all'interno del riquadro per i giorni +OK aereo assegnato allo studente di fianco al numero della missione per PPL, invece per CPL e IR e HB il tipo va di fiaco al nome dello studente +OK le missioni ripetute su piu' giorni hanno una cella per giorno (non unite) +lo studente vede solo le missioni della sua fase PPL->PPL ATPL-> tutto +OK ogni richiesta ha un colore diverso che cicla con delle tinte pastello +