Holger Frey
5 years ago
4 changed files with 121 additions and 120 deletions
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
""" SuperX Parser """ |
||||
|
||||
from datetime import datetime |
||||
from collections import namedtuple |
||||
|
||||
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", |
||||
"acutal_value", |
||||
], |
||||
) |
||||
|
||||
|
||||
class SuperXError(ValueError): |
||||
pass |
||||
|
||||
|
||||
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: |
||||
raise SuperXError(f"unexpected headline: '{headline}'") |
||||
|
||||
|
||||
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()): |
||||
raise SuperXError(f"unexpected metadata: '{data}'") |
||||
if metadata["Gruppierung"] != EXPECTED_EXPORT_GROUPING: |
||||
raise SuperXError(f"unexpected grouping: {metadata['Gruppierung']}") |
||||
return SuperXResult( |
||||
metadata["Haushaltsjahr"], |
||||
datetime.strptime(metadata["Stand"], "%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: |
||||
raise SuperXError("could not find table header") |
||||
|
||||
|
||||
def _parse_data_table(rows): |
||||
""" parses non-empty lines of the data table """ |
||||
for line in rows: |
||||
if not line[0]: |
||||
continue |
||||
yield SuperXData(*line[:10]) |
||||
|
||||
|
||||
def parse_export_data(xls_sheet): |
||||
""" parses the exported superx data """ |
||||
rows = xls_sheet.values |
||||
_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) |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
from pathlib import Path |
||||
|
||||
import pytest |
||||
|
||||
|
||||
@pytest.fixture |
||||
def example_file(request): |
||||
root_dir = Path(request.config.rootdir) |
||||
data_dir = root_dir / "test data" |
||||
return data_dir / "Verwendungsnachweis_und_Kassenstand_SAP_Zahlen.xlsx" |
Loading…
Reference in new issue