import copy from collections import defaultdict from datetime import datetime, timedelta from io import BytesIO from typing import Generator, Union, Any, List, Tuple from pathlib import Path import pandas as pd from reportlab.lib import colors from reportlab.lib.enums import TA_CENTER from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib.units import mm, inch from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak, Table from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from werkzeug.datastructures import FileStorage from .exceptions import InvalidNameOrTypeHeaderException from ..students.models import Student, Group from ..examination_schedule.models import TermOfDefence def check_columns(df: pd.DataFrame) -> bool: headers = set(df.keys().values) columns = ['NAZWISKO', 'IMIE', 'INDEKS', 'PESEL', 'EMAIL'] if len(headers - set(columns)) != 0: return False flag = True col_types = ['object', 'object', 'int', 'float64', 'object'] for name, col_type in zip(columns, col_types): if not str(df.dtypes[name]).startswith(col_type): flag = False break return flag def parse_csv(file: FileStorage) -> Generator[Student, Any, None]: df = pd.read_csv(file) if not check_columns(df): raise InvalidNameOrTypeHeaderException students = (Student(last_name=dict(item.items())['NAZWISKO'], first_name=dict(item.items())['IMIE'], index=dict(item.items())['INDEKS'], pesel=str(int(dict(item.items())['PESEL'])) if not pd.isna( dict(item.items())['PESEL']) else None, email=dict(item.items())['EMAIL']) for _, item in df.iterrows()) return students def generate_csv(students_and_groups: List[Tuple[Student, Group]]) -> str: headers = ['PESEL', 'INDEKS', 'IMIE', 'NAZWISKO', 'EMAIL', 'CDYD_KOD', 'PRZ_KOD', 'TZAJ_KOD', 'GR_NR', 'PRG_KOD'] data = [(student.pesel, student.index, student.first_name, student.last_name, student.email, group.cdyd_kod, group.prz_kod, group.tzaj_kod, group.project_supervisor_id, None) for student, group in students_and_groups] dataframe = defaultdict(list) for row in data: for idx, item in enumerate(row): dataframe[headers[idx]].append(item) df = pd.DataFrame(dataframe) return df.to_csv(index=False) def generate_range_dates(start_date: datetime, end_date: datetime, step_in_minutes: int) -> \ Generator[Union[datetime, timedelta], Any, None]: current_date = copy.copy(start_date) while True: next_date = current_date + timedelta(minutes=step_in_minutes) if next_date > end_date: break yield current_date current_date = copy.copy(next_date) def generate_examination_schedule_pdf_file(title: str, nested_term_of_defences: List[List[TermOfDefence]], base_dir: Path) -> bytes: pagesize = (297 * mm, 210 * mm) headers = ["lp.", "Godzina", "Nazwa projektu", "Opiekun", "Zespol", "Komisja"] pdf_buffer = BytesIO() my_doc = SimpleDocTemplate( pdf_buffer, pagesize=pagesize, topMargin=1 * inch, leftMargin=1 * inch, rightMargin=1 * inch, bottomMargin=1 * inch, title=title ) pdfmetrics.registerFont(TTFont('Lato', base_dir / 'fonts' / 'Lato.ttf')) style = getSampleStyleSheet() bodyText = style['BodyText'] bodyText.fontName = 'Lato' normal = style["Heading1"] normal.alignment = TA_CENTER flowables = [] # print(nested_enrollments) for term_of_defences in nested_term_of_defences: if len(term_of_defences) == 0: continue date = datetime.strftime(term_of_defences[0].start_date.date(), '%d.%m.%Y') paragraph_1 = Paragraph(f"{title} ~ {date}", normal) flowables.append(paragraph_1) data = [headers] for idx, td in enumerate(term_of_defences, start=1): new_date = td.start_date + timedelta(hours=2) group_name = td.group.name if td.group is not None else "" if group_name != '': ps = td.group.project_supervisor project_supervisor_fullname = f"{ps.first_name[0]}. {ps.last_name}" students = td.group.students # print(students) team = ", ".join([f"{s.first_name} {s.last_name}" for s in students]) else: project_supervisor_fullname = "" team = "" members = td.members_of_committee # print(members) if len(members) == 0: committee = '' else: members_iter = (f"{m.first_name[0]} {m.last_name}" for m in members) committee = ", ".join(members_iter) data.append([str(idx), new_date.strftime("%H:%M"), Paragraph(group_name, bodyText), Paragraph(project_supervisor_fullname, bodyText), Paragraph(team, bodyText), Paragraph(committee, bodyText), ]) # print(data) table = Table(data=data, style=[ ('GRID', (0, 0), (-1, -1), 0.5, colors.black), ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor("#A6F1A6")), ('BACKGROUND', (0, 0), (1, -1), colors.HexColor("#A6F1A6")) ], colWidths=[0.25 * inch, 0.7 * inch, 1.6 * inch, 1.5 * inch, 4 * inch, 3 * inch] ) flowables.append(table) flowables.append(PageBreak()) my_doc.build(flowables) pdf_value = pdf_buffer.getvalue() pdf_buffer.close() return pdf_value