def parse_csv(filename):
    """Parses all csv-files into the list."""
    export = AfasExport()
    logger.info("Reading AFAS export from %s", filename)
    try:
        with open(filename, encoding="ISO-8859-1") as csv_file:
            reader = csv.DictReader(csv_file, delimiter=';')

            for row in reader:
                try:
                    account_id = row["accountnumber"]
                    counter_account_id = row["counter_account_number"]
                    date = datetime.datetime.strptime(row["date"],
                                                      "%Y-%m-%d").date()
                    try:
                        date2 = datetime.datetime.strptime(
                            row["date2"], "%Y-%m-%d").date()
                    except ValueError:
                        date2 = date
                    amount = float(row["amount"])
                    if row["debit_credit"] == 'D':
                        amount = -amount
                    name = " ".join(row["name"].split())
                    description = " ".join(row["description"].split())
                    cat = row["category"]
                    sub_category = row["subcategory"]

                    try:
                        category = category_repository(
                        ).get_category_by_qualified_name("Uitgaven::" + cat +
                                                         "::" + sub_category)
                    except:
                        try:
                            category = category_repository(
                            ).get_category_by_qualified_name(cat + "::" +
                                                             sub_category)
                        except:
                            logger.warning("Failed to get category for %s::%s",
                                           cat, sub_category)
                            raise

                    if category:
                        transaction = AfasTransaction(account_id, amount, date,
                                                      date2, name, description,
                                                      counter_account_id,
                                                      category)
                        export.add_transaction(transaction)
                except:
                    logger.error("Failed to read row %s", row)
                    raise
    except FileNotFoundError:
        logger.warning(
            "No AFAS.csv found in data-directory. Will not use AFAS historical data to categorize transactions."
        )
    return export
示例#2
0
def get_combined_category_data_for_period(parent_id=None):
    try:
        start = request.args.get('start', None)
        start_date = datetime.fromtimestamp(int(float(start) / 1000)).date()
    except ValueError:
        start_date = application.services.get_date_of_first_transaction()

    try:
        end = request.args.get('end', None)
        end_date = datetime.fromtimestamp(int(float(end) / 1000)).date()
    except ValueError:
        end_date = application.services.get_date_of_last_transaction()

    logger.info("Returning transaction-date from %s to %s", start_date,
                end_date)
    parent_category = category_repository().get_category(parent_id) or None

    if parent_category:
        categories = parent_category.children or [parent_category]
    else:
        categories = [
            c for c in category_repository().get_categories() if not c.parent
        ]

    def get_category_amount(cat):
        cat_data = {
            'name':
            cat.name,
            'value':
            abs(
                float(
                    sum([
                        float(t.amount) for t in
                        application.services.get_transactions_for_category(
                            start_date, end_date, cat)
                    ])))
        }

        if cat.children:
            cat_data['children'] = []
            for child_cat in cat.children:
                cat_data['children'].append(get_category_amount(child_cat))
        return cat_data

    data = []
    for category in categories:
        data.append(get_category_amount(category))
    response = app.response_class(response=dumps(data, cls=CategoryEncoder),
                                  mimetype='application/json')
    return response
示例#3
0
def import_categories(filename):
    with open(filename) as csv_file:
        reader = csv.DictReader(csv_file)
        for row in reader:
            category_id, qualified_name = row["category_id"], row[
                "qualified_name"]
            category = category_repository().get_category_by_qualified_name(
                qualified_name)
            if not category:
                category = category_factory(
                ).create_category_from_qualified_name(qualified_name)
                category.id = category_id
                category_repository().save_category(category)
            else:
                logger.info("Skipping import of existing category %s",
                            category)
示例#4
0
    def init_cache(self):
        logger.info("Initializing cache...")
        sql = """SELECT * FROM accounts"""
        account_rows = self.db.query(sql)
        for row in account_rows:
            account = Account(row["id"], row["name"], row["bank"])
            self.save_account(account)

            logger.debug("Fetching transactions for account %s", account)
            for trow in self.db.query(
                    "SELECT * FROM transactions WHERE account = ?",
                (account.id, )):
                category = category_repository().get_category(trow["category"])
                date_str = trow["date"].split(" ")[
                    0]  # strip trailing characters (if any)
                date = datetime.strptime(date_str, '%Y-%m-%d').date()
                transaction = Transaction(trow["id"], account, trow["serial"],
                                          date, trow["amount"], trow["name"],
                                          trow["description"],
                                          trow["counter_account"],
                                          trow["balance_after"],
                                          trow["internal"], category)
                self.save_transaction(transaction)
                account.add_transaction(transaction)

        logger.info("Cache initialized...")
示例#5
0
def get_combined_data():
    mode = request.args.get('mode', 'monthly')
    category_id = request.args.get('category', None)
    category = category_repository().get_category(category_id)
    date_list = application.services.get_transaction_date_range(mode=mode)
    balance_list = [
        application.services.get_combined_balance_at(date)
        for date in date_list
    ]
    income, expenses, profit, loss = application.services.get_income_expenses_profit_loss(
        date_list, mode=mode)
    category_amounts = [
        application.services.get_combined_amount_for_category(
            category, d, mode) for d in date_list
    ]
    response = app.response_class(response=dumps([
        Combined(date, balance, income, expenses, profit, loss,
                 category_amount).__dict__
        for (date, balance, income, expenses, profit, loss,
             category_amount) in zip(date_list, balance_list, income, expenses,
                                     profit, loss, category_amounts)
    ],
                                                 cls=CategoryEncoder),
                                  mimetype='application/json')
    return response
示例#6
0
def get_categories():
    categories = [Category(0, "None", None).__dict__] + [
        Category(cat.id, cat.qualified_name, cat.parent).__dict__
        for cat in category_repository().get_categories()
    ]
    response = app.response_class(dumps(categories, cls=CategoryEncoder),
                                  mimetype='application/json')
    return response
示例#7
0
def import_transactions(filename):
    if list(
            itertools.chain.from_iterable([
                a.get_transactions()
                for a in account_repository().get_accounts()
            ])):
        logger.error(
            "Native import of transactions is only allowed on an empty transactions table!"
        )
        return

    with open(filename) as csv_file:
        reader = csv.DictReader(csv_file)
        for row in reader:
            transaction_id = row["transaction_id"]
            amount = row["amount"]
            date = datetime.datetime.strptime(row["date"], '%Y-%m-%d').date()
            name = row["name"]
            description = row["description"]
            balance_after = row["balance_after"]
            serial = row["serial"]
            counter_account = row["counter_account"]
            account_id = row["account"]
            category_qualified_name = row["category"]
            transaction = account_repository().get_transaction(transaction_id)
            account = account_repository().get_account(account_id)
            if not transaction:
                transaction = account_factory().create_transaction(
                    account, date, amount, name, description, serial,
                    counter_account, balance_after)
                transaction.id = transaction_id
                if category_qualified_name:
                    category = category_repository(
                    ).get_category_by_qualified_name(category_qualified_name)
                    if not category:
                        category = category_factory(
                        ).create_category_from_qualified_name(
                            category_qualified_name)
                        category_repository().save_category(category)
                    transaction.update_category(category)
            account_repository().save_transaction(transaction)
 def __init__(self):
     self.mapping = [
         (category_repository().get_category_by_qualified_name(
             "Uitgaven::Overige uitgaven::Overboekingen"),
          category_repository().get_category_by_qualified_name(
              "Overboekingen")),
         (category_repository().get_category_by_qualified_name(
             "Uitgaven::Telecom::Televisie"),
          category_repository().get_category_by_qualified_name(
              "Uitgaven::Telecom::Internet/TV")),
         (category_repository().get_category_by_qualified_name(
             "Uitgaven::Telecom::Internet"),
          category_repository().get_category_by_qualified_name(
              "Uitgaven::Telecom::Internet/TV")),
         (category_repository().get_category_by_qualified_name(
             "Uitgaven::Overige uitgaven::Abonnementen"),
          category_repository().get_category_by_qualified_name(
              "Uitgaven::Vrije tijd::Abonnementen")),
         (category_repository().get_category_by_qualified_name(
             "Inkomsten::Belastingtoeslagen"),
          category_repository().get_category_by_qualified_name(
              "Inkomsten::Belastingteruggaaf")),
     ]
示例#9
0
def get_category_data(category_id):
    mode = request.args.get('mode', 'monthly')
    category = category_repository().get_category(category_id)
    date_list = application.services.get_transaction_date_range(day_nr=1,
                                                                mode=mode)
    monthly_amounts = [
        application.services.get_combined_amount_for_category(
            category, month, mode) for month in date_list
    ]
    response = app.response_class(response=dumps([
        Balance(date, amount).__dict__
        for (date, amount) in zip(date_list, monthly_amounts)
    ],
                                                 cls=CategoryEncoder),
                                  mimetype='application/json')
    return response
 def __init__(self, config):
     self.names = {}
     mapping_filename = config.get_file("mapping.csv")
     logger.info("Reading mapping from %s", mapping_filename)
     with open(mapping_filename, encoding="ISO-8859-1") as csv_file:
         reader = csv.DictReader(csv_file, delimiter=',')
         for row in reader:
             name = row["Name"]
             description = row["Description"]
             cat_name = row["Category"]
             try:
                 category = category_repository(
                 ).get_category_by_qualified_name(cat_name)
             except:
                 logger.warning("Failed to get category for %s", cat_name)
                 raise
             self.names[(name, description)] = category
示例#11
0
def set_category(transaction_id):
    category_id = request.json.get('categoryId')
    category = category_repository().get_category(category_id)
    transaction = account_repository().get_transaction(transaction_id)
    logger.info('Setting category of transaction id %s to %s', transaction,
                category)
    transaction.update_category(category)
    account_repository().save_transaction(transaction)
    # TODO: Fix threading issue!!! account_repository().save_transaction(transaction)
    return app.response_class(response=dumps(Transaction(
        transaction.id, transaction.date, transaction.account.name,
        transaction.amount,
        transaction.name, transaction.category and Category(
            transaction.category.id, transaction.category.qualified_name,
            transaction.category.parent).__dict__ or None,
        transaction.description, transaction.counter_account,
        transaction.internal).__dict__,
                                             cls=CategoryEncoder),
                              mimetype='application/json')
 def __init__(self):
     self.DEFAULT_SCORE = 100
     self.internal_transactions_detector = MyInternalTransactionDetector()
     self.internal_transactions_category = category_repository(
     ).get_category_by_qualified_name("Overboekingen")