Fix autosort

This commit is contained in:
Felix Breidenstein 2020-10-18 20:11:17 +02:00
parent e49e8c51f5
commit db555fa3b3
4 changed files with 50 additions and 41 deletions

View file

@ -2,16 +2,13 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from models import Category, Tag
from helper import get_session, add_category, get_rules
from models import Tag, Transaction
from helper import get_session, create_tag, get_rules
import re
import sys
import click
import colorful as cf
def print_verbose(verbose, string):
if verbose:
print(string)
@click.command(name="autosort")
@click.option("--profile", "-p")
@ -25,19 +22,15 @@ def command(profile, dry_run, verbose):
print("Found {} unsorted transcations".format(len(unsorted)))
new = []
for t in unsorted:
cat_name = apply_rules(t, rules)
if cat_name:
short_name = t.name[:25] if len(t.name) > 25 else t.name
short_desc = t.description[:45] if len(t.description) > 50 else t.description
print_verbose(verbose, "{:<25} | {:<50}| {:>10}".format(short_name, short_desc, t.amount / 100))
print_verbose(verbose, cf.green(f"Matched '{cat_name}'"))
cat_id = session.query(Category).filter(Category.name == cat_name).first()
if not cat_id:
cat_id = add_category(cat_name, profile, session)
t.category_id = cat_id
new.append(t)
print_verbose(verbose, "-" * 90)
for transaction in unsorted:
taglist = apply_rules(transaction, rules)
if taglist:
for tag_label in taglist:
tag = session.query(Tag).filter(Tag.name == tag_label).first()
if not tag:
tag = create_tag(tag_label, profile, session)
transaction.tags.append(tag)
new.append(transaction)
print(f"Automatically matched {len(new)} transactions")
if not dry_run:
@ -56,11 +49,11 @@ def apply_rules(t, rules):
continue
if name_regex:
if not name_regex.search(t.name):
if not re.search(name_regex, t.name):
continue
if desc_regex:
if not desc_regex.search(t.description):
if not re.search(desc_regext.description):
continue
return r["category"]
return r["tags"].split(",")

23
cli
View file

@ -2,15 +2,16 @@
import click
import os
import sys
from pathlib import Path
import importer
# import serve
# import autosort
# import validate
import autosort
import validate
# import info
# import report
from helper import build_database_filename, create_dirs
from helper import build_database_filename, create_dirs, build_rules_filename
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
@ -26,13 +27,19 @@ def cli():
@cli.command(name="init")
@click.argument("profile_name", required=True)
def init(profile_name):
filename = build_database_filename(profile_name)
if os.path.exists(filename):
db_path = build_database_filename(profile_name)
rule_path = build_rules_filename(profile_name)
if os.path.exists(db_path) and os.path.exists(rule_path):
print(f"Profile '{profile_name}' already exists")
sys.exit(1)
else:
engine = create_engine(f"sqlite:///{filename}")
# database
engine = create_engine(f"sqlite:///{db_path}")
models.Base.metadata.create_all(engine)
# rules
Path(rule_path).touch()
print(f"Sucessfully create the profile '{profile_name}'")
@ -41,8 +48,8 @@ if __name__ == '__main__':
# cli.add_command(sort.command)
cli.add_command(importer.command)
# cli.add_command(serve.command)
# cli.add_command(autosort.command)
# cli.add_command(validate.command)
cli.add_command(autosort.command)
cli.add_command(validate.command)
# cli.add_command(info.command)
# cli.add_command(report.command)
cli()

View file

@ -20,7 +20,7 @@ DATA_DIR = os.path.join(XDG_DATA_HOME, "schmeckels")
def format_amount(cents):
amount = cents/100
amount = cents / 100
return f"{amount:,.2f}"
@ -33,24 +33,24 @@ def create_dirs():
def build_database_filename(profile_name):
return f"{DATA_DIR}/databases/{profile_name}.db"
return f"{DATA_DIR}/{profile_name}.db"
def build_rules_filename(profile_name):
return f"{DATA_DIR}/rules/{profile_name}.yaml"
return f"{CONFIG_DIR}/{profile_name}.yaml"
def check_single_profile():
files = os.listdir(f"{DATA_DIR}/databases")
files = os.listdir(DATA_DIR)
if len(files) == 1:
return files.split(".")[0]
return files[0].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")
files = os.listdir(DATA_DIR)
return [x.split(".")[0] for x in files]
@ -88,7 +88,7 @@ def get_rules(profile_name):
def create_tag(name, profile, session):
t = session.query(models.Tag).filter(models.Tag.name == name).first()
if not t:
c = models.Tag(name=name)
t = models.Tag(name=name)
session.add(t)
session.commit()
return t.id
return t

View file

@ -1,10 +1,17 @@
#! /usr/bin/env python3
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Table
from sqlalchemy.orm import relationship, backref
Base = declarative_base()
association_table = Table(
"association",
Base.metadata,
Column("left_id", Integer, ForeignKey("Transaction.id")),
Column("right_id", Integer, ForeignKey("Tag.id")),
)
class Transaction(Base):
__tablename__ = "Transaction"
@ -14,6 +21,7 @@ class Transaction(Base):
iban = Column(String)
amount = Column(Integer)
description = Column(String)
tags = relationship("Tag", secondary=association_table, back_populates="transactions")
def is_positive(self):
return self.amount > 0
@ -32,9 +40,10 @@ class Transaction(Base):
class Tag(Base):
__tablename__ = "Tag"
name = Column(String, primary_key=True)
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
description = Column(String)
transactions = relationship("Transaction", backref="tags")
transactions = relationship("Transaction", secondary=association_table, back_populates="tags")
def __repr__(self):
return f"<Tag {self.name}>"