"""SuperX Parser""" from collections import namedtuple from datetime import datetime from .exceptions import SuperXParserError from .helpers import get_sheet_of_file, strip_excel_value EXPECTED_HEADLINE = "Verwendungsnachweis und Kassenstand SAP" EXPECTED_METADATA_KEYS = {"Haushaltsjahr", "Stand", "Gruppierung"} EXPECTED_EXPORT_GROUPING = "automatisch" EXPECTED_DATA_TABLE_HEADER = "Kostenstelle" SuperXResult = namedtuple( "SuperXResult", ["account_year", "export_date", "data"] ) SuperXData = namedtuple( "SuperXData", [ "cost_center", "fonds", "project", "kind", "budget_year", "obligo", "expenses", "revenue_actual", "revenue_target", "actual_value", ], ) def _check_export_headline(row): """checks the first line of the excel data if it's what we'd expect""" headline = row[0] if headline != EXPECTED_HEADLINE: msg = f"unexpected headline: '{headline}'" raise SuperXParserError(msg) def _get_export_metadata(row): """extracts the metadata from the second row of the excel sheet""" data = row[0] entries = data.split(";") parts = [entry.split(":", 1) for entry in entries] metadata = {key.strip(): value.strip() for key, value in parts} if EXPECTED_METADATA_KEYS - set(metadata.keys()): msg = f"unexpected metadata: '{data}'" raise SuperXParserError(msg) if metadata["Gruppierung"] != EXPECTED_EXPORT_GROUPING: msg = f"unexpected grouping: {metadata['Gruppierung']}" raise SuperXParserError(msg) date_part, *rest = metadata["Stand"].split(",") return SuperXResult( metadata["Haushaltsjahr"], datetime.strptime(date_part.strip(), "%d.%m.%Y"), None, ) def _skip_export_data_until_table_header(rows): """skip rows until data table headers""" for line in rows: first_cell = line[0] if first_cell == EXPECTED_DATA_TABLE_HEADER: break else: msg = "could not find table header" raise SuperXParserError(msg) def _parse_data_table(rows): """parses non-empty lines of the data table""" for line in rows: if not line[0]: continue data = [strip_excel_value(value) for value in line[:10]] yield SuperXData(*data) def parse_export_data(xls_sheet): """parses the exported superx data""" rows = xls_sheet.values # noqa: PD011 _check_export_headline(next(rows)) metadata = _get_export_metadata(next(rows)) _skip_export_data_until_table_header(rows) data = list(_parse_data_table(rows)) return SuperXResult(metadata.account_year, metadata.export_date, data) def parse_exported_file(file_path): """parses the budget file""" sheet = get_sheet_of_file(file_path, sheet=None) return parse_export_data(sheet)