Verified Commit 227bc51b authored by Jakob Moser's avatar Jakob Moser
Browse files

Start working on terminal UI

parent 3402b46f
Loading
Loading
Loading
Loading
+3 −51
Changes for muffin/__main__.py: 3 added lines, 51 removed lines.
Original line number Diff line number Diff line
from pathlib import Path
from decimal import Decimal
import sys
import json
from .ui.InteractiveUserInterface import start

from tabulate import tabulate

from .payment_order.PaymentOrderCollection import PaymentOrderCollection
from .budget_plan.BudgetPlanLoader import load_pdf

directory = Path(sys.argv[1])

sums = PaymentOrderCollection(directory).sums_by_budgetary_item_id
# print(sums)

budget_plan = load_pdf(sys.argv[2])
with open("instance/budget_plan.json", "w") as f:
    json.dump(budget_plan.as_dict, f, indent=4, ensure_ascii=False)


def _format_as_euro_de(amount: Decimal) -> str:
    return f"{amount} €".replace(".", ",")


output_rows = [
    (
        item.id,
        item.name,
        spent := sums.get(item.id, Decimal("0.00")),
        remaining := item.amount - spent,
        item.amount,
    )
    for item in budget_plan.items
]

formatted_output_rows = [
    (
        id,
        name,
        _format_as_euro_de(spent),
        _format_as_euro_de(remaining),
        _format_as_euro_de(total),
    )
    for (id, name, spent, remaining, total) in output_rows
]

print(
    tabulate(
        formatted_output_rows,
        headers=["Budgetposten", "Name", "Ausgegeben", "Verbleibend", "Geplant"],
        colalign=("right", "left", "right", "right", "right"),
    )
)
if __name__ == "__main__":
    start()
+52 −0
Changes for muffin/analysis/cash_accounting.py: 52 added lines, 0 removed lines.
Original line number Diff line number Diff line
from pathlib import Path
from decimal import Decimal
import sys
import json

from tabulate import tabulate

from ..payment_order.PaymentOrderCollection import PaymentOrderCollection
from ..budget_plan.BudgetPlanLoader import load_pdf


def _format_as_euro_de(amount: Decimal) -> str:
    return f"{amount} €".replace(".", ",")


def tabulate_balances(payment_orders_path: Path, budget_plan_path: Path) -> None:
    sums = PaymentOrderCollection(payment_orders_path).sums_by_budgetary_item_id
    # print(sums)
    budget_plan = load_pdf(budget_plan_path)

    with open("instance/budget_plan.json", "w") as f:
        json.dump(budget_plan.as_dict, f, indent=4, ensure_ascii=False)

    output_rows = [
        (
            item.id,
            item.name,
            spent := sums.get(item.id, Decimal("0.00")),
            remaining := item.amount - spent,
            item.amount,
        )
        for item in budget_plan.items
    ]

    formatted_output_rows = [
        (
            id,
            name,
            _format_as_euro_de(spent),
            _format_as_euro_de(remaining),
            _format_as_euro_de(total),
        )
        for (id, name, spent, remaining, total) in output_rows
    ]

    print(
        tabulate(
            formatted_output_rows,
            headers=["Budgetposten", "Name", "Ausgegeben", "Verbleibend", "Geplant"],
            colalign=("right", "left", "right", "right", "right"),
        )
    )
+81 −0
Changes for muffin/ui/InteractiveUserInterface.py: 81 added lines, 0 removed lines.
Original line number Diff line number Diff line
from termcolor import cprint, colored
from pathlib import Path
import questionary

from ..analysis.cash_accounting import tabulate_balances
from ..integrations.schwalbe.studienfachschaften import (
    get_studienfachschaften,
    Studienfachschaft,
)


def _start_auto_mode() -> None:
    studienfachschaft = _ask_for_studienfachschaft()


def _start_manual_mode() -> None:
    budget_plan_path_str = questionary.path("Pfad zum Budgetplan (*.pdf):").ask()
    if budget_plan_path_str is None:
        exit(20)

    budget_plan_path = Path(budget_plan_path_str).expanduser()
    if not budget_plan_path.is_file():
        print(
            colored("!", "red"),
            "Es gibt keine Datei mit dem Namen",
            colored(budget_plan_path_str, "yellow"),
        )
        exit(200)

    payment_orders_path_str = questionary.path(
        "Pfad zu den Zahlungsanweisungen (Ordner):"
    ).ask()
    if payment_orders_path_str is None:
        exit(21)

    payment_orders_path = Path(payment_orders_path_str).expanduser()
    if not payment_orders_path.is_dir():
        print(
            colored("!", "red"),
            "Es gibt keinen Ordner mit dem Namen",
            colored(payment_orders_path_str, "yellow"),
        )
        exit(210)

    print()
    tabulate_balances(payment_orders_path, budget_plan_path)


def _ask_for_studienfachschaft() -> Studienfachschaft:
    studienfachschaften = {
        fachschaft.name: fachschaft
        for fachschaft in sorted(
            get_studienfachschaften(), key=lambda fachschaft: fachschaft.name
        )
    }

    studienfachschaft_name = questionary.autocomplete(
        "Fachschaft:",
        choices=studienfachschaften.keys(),
        validate=lambda name: name in studienfachschaften
        or "Bitte vollständigen Namen angeben, übernehmen mit [Tab]",
    ).ask()

    if not studienfachschaft_name:
        exit(30)

    return studienfachschaften[studienfachschaft_name]


def start() -> None:
    cprint("Willkommen bei Muffin!", attrs=["bold"])
    print()

    use_auto_mode = questionary.confirm(
        "Soll Muffin die benötigten Daten automatisch verwalten (herunterladen und speichern)?"
    ).ask()

    if use_auto_mode:
        _start_auto_mode()
    else:
        _start_manual_mode()

muffin/ui/__init__.py

0 → 100644
+0 −0

Empty file added.