Creating a budget overview from a SuperX export.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

157 lines
4.5 KiB

""" Views for the create overview part """
from tempfile import NamedTemporaryFile
from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound
from pyramid_mailer.message import Message, Attachment
from . import XLSX_CONTENT_TYPE
from ..budget import parse_budget_file
from ..superx import parse_exported_file
from ..helpers import find_recipients, find_budget_file, get_sheet_of_file
from ..overview import create_overview # noqa: F401
from ..exceptions import BudgetParserError, SuperXParserError # noqa: F401
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
"""
@view_config(
context=dict,
request_method="GET",
renderer="superx_budget:pyramid/templates/start.jinja2",
)
def index(context, request):
return {}
@view_config(
context=dict,
request_method="POST",
renderer="superx_budget:pyramid/templates/overview.jinja2",
)
def superx_upload(context, request):
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=dict,
name="send",
request_method="POST",
renderer="superx_budget:pyramid/templates/sent.jinja2",
)
def send_overview(context, request):
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
expenses = {}
for key, value in request.POST.items():
if key.startswith("expense-"):
row_str = key.split("-")[-1]
row = int(row_str)
try:
value = float(value)
except ValueError:
value = 0
expenses[row] = value
# sanity check
if (
not export_date
or not recipients
or not expenses
or not budget_file.is_file()
):
request.session.flash(
f"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"F{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)
tmp.seek(0)
attachment = Attachment(xls_name, XLSX_CONTENT_TYPE, tmp)
message.attach(attachment)
request.mailer.send(message)
return {"recipients": recipients, "xls_name": xls_name}