|
|
|
from collections import namedtuple
|
|
|
|
|
|
|
|
from .helpers import excel_value_as_number
|
|
|
|
|
|
|
|
KIND_OBLIGO = "obligo"
|
|
|
|
KIND_EXPENSES = "expenses"
|
|
|
|
|
|
|
|
VALID_MATERIAL_IDS = {
|
|
|
|
"0216 - Sachmittel",
|
|
|
|
"0227 - Verbrauchsmaterial",
|
|
|
|
"0843 - Verbrauch/Stoffe",
|
|
|
|
"2 - Sachmittel",
|
|
|
|
}
|
|
|
|
|
|
|
|
OverviewBudgetEntry = namedtuple(
|
|
|
|
"OverviewBudgetEntry", ["description", "kind", "amount"]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class ProjectOverview:
|
|
|
|
def __init__(self, budget_data):
|
|
|
|
"""initializes the class"""
|
|
|
|
self.budget_data = budget_data
|
|
|
|
self.entries = []
|
|
|
|
self.found = False
|
|
|
|
|
|
|
|
@property
|
|
|
|
def project(self):
|
|
|
|
"""returns the project number"""
|
|
|
|
return self.budget_data.project
|
|
|
|
|
|
|
|
@property
|
|
|
|
def row(self):
|
|
|
|
"""returns the excel row number"""
|
|
|
|
return self.budget_data.row
|
|
|
|
|
|
|
|
@property
|
|
|
|
def expenses(self):
|
|
|
|
"""returns the accumulated expenses"""
|
|
|
|
numbers = (excel_value_as_number(e.amount) for e in self.entries)
|
|
|
|
values = (abs(entry) for entry in numbers)
|
|
|
|
return sum(values)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def available(self):
|
|
|
|
"""returns the still available budget"""
|
|
|
|
return self.budget_data.budget - self.expenses
|
|
|
|
|
|
|
|
def add(self, description, kind, amount):
|
|
|
|
"""adds an entry that modifies the available budget"""
|
|
|
|
entry = OverviewBudgetEntry(description, kind, amount)
|
|
|
|
self.entries.append(entry)
|
|
|
|
|
|
|
|
|
|
|
|
def _create_overview_map(budget_list):
|
|
|
|
"""returns a dictonary with project as key and overview as value"""
|
|
|
|
map = {}
|
|
|
|
for budget_data in budget_list:
|
|
|
|
overview = ProjectOverview(budget_data)
|
|
|
|
map[str(overview.project)] = overview
|
|
|
|
return map
|
|
|
|
|
|
|
|
|
|
|
|
def _filter_superx_material_expenses(superx_export):
|
|
|
|
"""filters superx data to only contain material entries"""
|
|
|
|
return (i for i in superx_export.data if i.kind in VALID_MATERIAL_IDS)
|
|
|
|
|
|
|
|
|
|
|
|
def _create_entries_from_superx(overview_map, superx_export_data):
|
|
|
|
"""adds overview entries from superx data"""
|
|
|
|
for line in superx_export_data:
|
|
|
|
if line.project in overview_map:
|
|
|
|
overview = overview_map[line.project]
|
|
|
|
overview.add(line.kind, KIND_OBLIGO, line.obligo)
|
|
|
|
overview.add(line.kind, KIND_EXPENSES, line.expenses)
|
|
|
|
return overview_map
|
|
|
|
|
|
|
|
|
|
|
|
def _set_found_state(overview_map, superx_export):
|
|
|
|
superx_projects = {line.project for line in superx_export.data}
|
|
|
|
found_projects = superx_projects.intersection(set(overview_map.keys()))
|
|
|
|
for project in found_projects:
|
|
|
|
overview_map[project].found = True
|
|
|
|
return overview_map
|
|
|
|
|
|
|
|
|
|
|
|
def create_overview(budget_list, superx_export):
|
|
|
|
"""create a overview map with budget entries from the parsed raw data"""
|
|
|
|
tmp_map = _create_overview_map(budget_list)
|
|
|
|
overview_map = _set_found_state(tmp_map, superx_export)
|
|
|
|
material_expenses = _filter_superx_material_expenses(superx_export)
|
|
|
|
return _create_entries_from_superx(overview_map, material_expenses)
|