112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
#! /usr/bin/env python3
|
|
import os
|
|
import sys
|
|
import yaml
|
|
import re
|
|
from xdg import XDG_CONFIG_HOME, XDG_DATA_HOME
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
import models
|
|
import locale
|
|
|
|
try:
|
|
from yaml import CLoader as Loader
|
|
except ImportError:
|
|
from yaml import Loader
|
|
|
|
|
|
CONFIG_DIR = os.path.join(XDG_CONFIG_HOME, "schmeckels")
|
|
DATA_DIR = os.path.join(XDG_DATA_HOME, "schmeckels")
|
|
|
|
|
|
def format_amount(cents):
|
|
amount = cents/100
|
|
return f"{amount:,.2f}"
|
|
|
|
|
|
def get_list_of_bookable_categories(session):
|
|
categories = session.query(models.Category).all()
|
|
return [c for c in categories if c.is_child()]
|
|
|
|
|
|
def create_dirs():
|
|
for directory in [CONFIG_DIR, DATA_DIR]:
|
|
try:
|
|
os.mkdir(directory)
|
|
except FileExistsError:
|
|
pass
|
|
|
|
|
|
def build_database_filename(profile_name):
|
|
return f"{DATA_DIR}/databases/{profile_name}.db"
|
|
|
|
|
|
def build_rules_filename(profile_name):
|
|
return f"{DATA_DIR}/rules/{profile_name}.yaml"
|
|
|
|
|
|
def check_single_profile():
|
|
files = os.listdir(f"{DATA_DIR}/databases")
|
|
if len(files) == 1:
|
|
return files.split(".")[0]
|
|
else:
|
|
print("--profile is required when you have more than one database.")
|
|
sys.exit(1)
|
|
|
|
|
|
def list_profiles():
|
|
files = os.listdir(f"{DATA_DIR}/databases")
|
|
return [x.split(".")[0] for x in files]
|
|
|
|
|
|
def get_session(profile_name):
|
|
if not profile_name:
|
|
profile_name = check_single_profile()
|
|
filename = build_database_filename(profile_name)
|
|
if os.path.exists(filename) and os.path.isfile(filename):
|
|
engine = create_engine(f"sqlite:///{filename}")
|
|
Session = sessionmaker(bind=engine)
|
|
return Session()
|
|
else:
|
|
print(f"No database for profile '{profile_name}'. Did you run 'init'?")
|
|
sys.exit(1)
|
|
|
|
|
|
def get_rules(profile_name):
|
|
if not profile_name:
|
|
profile_name = check_single_profile()
|
|
filename = build_rules_filename(profile_name)
|
|
if os.path.exists(filename) and os.path.isfile(filename):
|
|
with open(filename) as fh:
|
|
data = yaml.load(fh, Loader=Loader)
|
|
for rule in data:
|
|
if rule.get("name"):
|
|
rule["name_regex"] = re.compile(rule["name"])
|
|
if rule.get("description"):
|
|
rule["desc_regex"] = re.compile(rule["description"])
|
|
return data
|
|
else:
|
|
print(f"No rules for profile '{profile_name}'. Did you run 'init'?")
|
|
sys.exit(1)
|
|
|
|
|
|
def create_category(name, parent, profile, session):
|
|
c = session.query(models.Category).filter(models.Category.name == name).first()
|
|
if not c:
|
|
c = models.Category(name=name, parent_id=parent)
|
|
session.add(c)
|
|
session.commit()
|
|
return c.id
|
|
|
|
|
|
def add_category(name, profile, session):
|
|
parts = name.split(":")
|
|
if len(parts) == 1:
|
|
return create_category(name, None, profile, session)
|
|
else:
|
|
for i in range(len(parts) - 1):
|
|
parent = parts[i]
|
|
child = parts[i + 1]
|
|
parent_id = create_category(parent, None, profile, session)
|
|
id = create_category(child, parent_id, profile, session)
|
|
return id
|