"""Views for the create overview part""" from tempfile import NamedTemporaryFile from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config from pyramid_mailer.message import Attachment, Message from ..budget import parse_budget_file from ..exceptions import BudgetParserError, SuperXParserError from ..helpers import find_budget_file, find_recipients, get_sheet_of_file from ..overview import create_overview from ..superx import parse_exported_file from . import XLSX_CONTENT_TYPE, Root MAIL_MESSAGE_BODY = """Hallo an Alle, anbei ist eine aktuelle Übersicht unserer Verbrauchsmittel-Budgets. Frohes Bestellen! -- Dies ist eine automatisch generierte Email, bei Fragen bitte an Holgi wenden """ def _map_from_form_data(request, prefix): if not prefix.endswith("-"): prefix = f"{prefix}-" result = {} for key, value in request.POST.items(): if key.startswith(prefix): row_str = key.split("-")[-1] row = int(row_str) try: as_number = float(value) except ValueError: as_number = 0 result[row] = as_number return result @view_config( context=Root, request_method="GET", renderer="superx_budget:pyramid/templates/start.jinja2", permission="view", ) def index(context, request): # noqa: ARG001 return {} @view_config( context=Root, request_method="POST", renderer="superx_budget:pyramid/templates/overview.jinja2", permission="view", ) def superx_upload(context, request): # noqa: ARG001 upload = request.POST.get("superx") if upload == b"" or not upload.filename.endswith(".xlsx"): request.session.flash("No Excel file uploaded.", "error") return HTTPFound("/") try: superx_export = parse_exported_file(upload.file) except SuperXParserError: request.session.flash( "File does not appear to be the required SuperX export.", "error" ) return HTTPFound("/") budget_file = find_budget_file( request.budgets_dir, superx_export.account_year ) if budget_file is None: request.session.flash( f"No budget file for year {superx_export.account_year} found.", "error", ) return HTTPFound("/") try: budget_data = parse_budget_file(budget_file) except BudgetParserError: request.session.flash( "Budget File does not appear to be in the required format.", "error", ) return HTTPFound("/") overview_map = create_overview(budget_data, superx_export) overview = sorted(overview_map.values(), key=lambda i: i.row) if any(not (item.found) for item in overview): request.session.flash( ( "Some projects in the budget template were not in the SuperX " "export. Please adjust their expenses manually." ), "info", ) recipients = find_recipients(request.budgets_dir) return { "account_year": superx_export.account_year, "export_date": superx_export.export_date.strftime("%Y-%m-%d"), "overview": overview, "template": budget_file.name, "recipients": recipients, } @view_config( context=Root, name="send", request_method="POST", renderer="superx_budget:pyramid/templates/sent.jinja2", permission="view", ) def send_overview(context, request): # noqa: ARG001 export_date = request.POST.get("export_date").strip() tmp_recipients = request.POST.get("recipients").strip() recipients = tmp_recipients.splitlines() budget_template = request.POST.get("template") budget_file = request.budgets_dir / budget_template budgets = _map_from_form_data(request, "budget-") expenses = _map_from_form_data(request, "expense-") available = {k: (v - expenses[k]) for k, v in budgets.items()} # sanity check if ( not export_date or not recipients or not expenses or not available or not budget_file.is_file() ): request.session.flash( "There was an error with your submisssion, please try again.", "error", ) return HTTPFound("/") sheet = get_sheet_of_file(budget_file) for row, value in expenses.items(): cell = f"G{row}" sheet[cell] = value for row, value in available.items(): cell = f"H{row}" sheet[cell] = value budget_year = budget_file.stem.split("-")[-1] message = Message( subject=f"Budget Übersicht {budget_year}, Stand {export_date}", sender="cpiserver@imtek.uni-freiburg.de", recipients=recipients, body=MAIL_MESSAGE_BODY, ) xls_name = f"{export_date}-Budget-Overview-{budget_year}.xlsx" with NamedTemporaryFile() as tmp: sheet._parent.save(tmp.name) # noqa: SLF001 tmp.seek(0) attachment = Attachment(xls_name, XLSX_CONTENT_TYPE, tmp) message.attach(attachment) request.mailer.send_immediately(message, fail_silently=False) return {"recipients": recipients, "xls_name": xls_name}