Skip to content

Instantly share code, notes, and snippets.

@crearo
Last active August 4, 2020 21:14
Show Gist options
  • Save crearo/f7c3dc20b7ed60b4f61ea2f06fa9c49b to your computer and use it in GitHub Desktop.
Save crearo/f7c3dc20b7ed60b4f61ea2f06fa9c49b to your computer and use it in GitHub Desktop.

Revisions

  1. crearo revised this gist Aug 4, 2020. 1 changed file with 28 additions and 0 deletions.
    28 changes: 28 additions & 0 deletions monthly_expenses.py
    Original file line number Diff line number Diff line change
    @@ -98,13 +98,41 @@ def query(records, start_date, end_date, category):
    return queried


    def query_misc(records, start_date, end_date, categories):
    misc = []
    filtered = [record for record in records if start_date <= record.date < end_date and record.amount < 0]
    for record in filtered:
    matched = False
    for category in categories:
    for matcher in category:
    if matches(matcher, record):
    matched = True
    if not matched:
    misc.append(record)

    for record in misc:
    print(record)
    return misc


    def print_monthly(start_date, end_date):
    for month_range in month_list(start_date, end_date):
    print(month_range[0], "to", month_range[1])

    for name, matchers in categories.items():
    queried = query(records, month_range[0], month_range[1], matchers)
    print(f"{name}: {sum([record.amount for record in queried])}")

    misc = query_misc(records, month_range[0], month_range[1], list(categories.values()))
    print(f"misc: {sum([record.amount for record in misc])}")

    spent = [record for record in records if
    month_range[0] <= record.date < month_range[1] and record.amount < 0]
    print(f"total spent: {sum([record.amount for record in spent])}")

    saved = [record for record in records if month_range[0] <= record.date < month_range[1]]
    print(f"total saved: {sum([record.amount for record in saved])}")

    # for record in queried:
    # print(record)
    print("")
  2. crearo revised this gist Aug 4, 2020. 1 changed file with 31 additions and 15 deletions.
    46 changes: 31 additions & 15 deletions monthly_expenses.py
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,22 @@
    """
    Converts Deutsche Bank's CSV of transactions to various categories to see what you're spending money on.
    This isn't the neatest code I've written. But it gets what I need done.
    I want to see how much I spend on various categories every month. That's it.
    Output looks like:
    2020-03-01 00:00:00 to 2020-03-31 00:00:00
    essentials: -1275.2
    food: -417.85
    clothing: 0
    amazon: -79.72
    2020-04-01 00:00:00 to 2020-04-30 00:00:00
    essentials: -1275.07
    food: -365.19
    clothing: 0
    amazon: -164.23
    """
    import csv
    import datetime
    @@ -51,13 +67,15 @@ def __init__(self, beneficiary=None, details=None, date=None, payment=None, amou
    self.amount = amount


    essentials = [Record(beneficiary="anton maier"), Record(beneficiary="swm versorgungs"),
    Record(beneficiary="vodafone gmbh"),
    Record(beneficiary="paypal", details="vodafone"), Record(beneficiary="zurich insurance")]
    food = [Record(details="subway"), Record(details="lidl"), Record(details="edeka"), Record(details="vollcorner"),
    Record(details="aldi")]
    clothing = [Record(details="decathlon"), Record(details="karstadt")]
    amazon = [Record(beneficiary="amazon")]
    categories = {
    "essentials": [Record(beneficiary="anton maier"), Record(beneficiary="swm versorgungs"),
    Record(beneficiary="vodafone gmbh"),
    Record(beneficiary="paypal", details="vodafone"), Record(beneficiary="zurich insurance")],
    "food": [Record(details="subway"), Record(details="lidl"), Record(details="edeka"), Record(details="vollcorner"),
    Record(details="aldi")],
    "clothing": [Record(details="decathlon"), Record(details="karstadt")],
    "amazon": [Record(beneficiary="amazon")]
    }


    def matches(matcher, record):
    @@ -83,18 +101,16 @@ def query(records, start_date, end_date, category):
    def print_monthly(start_date, end_date):
    for month_range in month_list(start_date, end_date):
    print(month_range[0], "to", month_range[1])
    queried = query(records, month_range[0], month_range[1], food)
    print("I spent:", sum([record.amount for record in queried]))

    for name, matchers in categories.items():
    queried = query(records, month_range[0], month_range[1], matchers)
    print(f"{name}: {sum([record.amount for record in queried])}")
    # for record in queried:
    # print(record)
    print("")


    if __name__ == '__main__':
    # parser = argparse.ArgumentParser()
    # parser.add_argument("file", required=False,
    # default="/home/rish/Documents/Everything/2020/Bank Statements/db-20200206-20200804.csv")
    # args = parser.parse_args()

    records = []

    file = open("/home/rish/Documents/Everything/2020/Bank Statements/db-20200206-20200804.csv", encoding="iso-8859-1")
    @@ -110,4 +126,4 @@ def print_monthly(start_date, end_date):
    Record(beneficiary=line[3].lower(), details=line[4].lower(), date=date, payment=line[2].lower(),
    amount=float(amount.replace(',', ''))))

    print_monthly(datetime.datetime(2020, 3, 1), datetime.datetime(2020, 7, 31))
    print_monthly(datetime.datetime(2020, 2, 1), datetime.datetime(2020, 7, 31))
  3. crearo revised this gist Aug 4, 2020. 1 changed file with 1 addition and 22 deletions.
    23 changes: 1 addition & 22 deletions monthly_expenses.py
    Original file line number Diff line number Diff line change
    @@ -1,27 +1,6 @@
    """
    Income: Beneficiary / Originator GOOGLE GERMANY GMBH
    Rent: Beneficiary / Originator Anton Maier
    SWM: Beneficiary / Originator SWM Versorgungs GmbH
    Internet: Beneficiary / Originator Vodafone GmbH
    Phone: Payment Details Vodafone
    Insurance: Beneficiary / Originator Zurich Insurance plc Niederlassung für Deutschland
    Subway: Payment Details Subway
    Edeka: Payment Details EDEKA
    Lidl: Payment Details Lidl
    Vollcorner: Payment Details Vollcorner
    Aldi: Payment Details Aldi
    Decathlon: Payment Details Decathlon
    Karstadt: Payment Details Karstadt
    Scooter: Payment Details Lime,TIERMOBILIT
    Amazon: Beneficiary / Originator AMAZON PAYMENTS EUROPE S.C.A.
    Paypal: Beneficiary / Originator PayPal || Buuuut don't count vodafone in this.
    This isn't the neatest code I've written. But it gets what I need done.
    I want to see how much I spend on various categories every month. That's it.
    """
    import csv
    import datetime
  4. crearo created this gist Aug 4, 2020.
    134 changes: 134 additions & 0 deletions monthly_expenses.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,134 @@
    """
    Income: Beneficiary / Originator GOOGLE GERMANY GMBH
    Rent: Beneficiary / Originator Anton Maier
    SWM: Beneficiary / Originator SWM Versorgungs GmbH
    Internet: Beneficiary / Originator Vodafone GmbH
    Phone: Payment Details Vodafone
    Insurance: Beneficiary / Originator Zurich Insurance plc Niederlassung für Deutschland
    Subway: Payment Details Subway
    Edeka: Payment Details EDEKA
    Lidl: Payment Details Lidl
    Vollcorner: Payment Details Vollcorner
    Aldi: Payment Details Aldi
    Decathlon: Payment Details Decathlon
    Karstadt: Payment Details Karstadt
    Scooter: Payment Details Lime,TIERMOBILIT
    Amazon: Beneficiary / Originator AMAZON PAYMENTS EUROPE S.C.A.
    Paypal: Beneficiary / Originator PayPal || Buuuut don't count vodafone in this.
    I want to see how much I spend on various categories every month. That's it.
    """
    import csv
    import datetime
    from itertools import islice


    def last_day_of_month(any_day):
    """https://stackoverflow.com/questions/51293632/how-do-i-divide-a-date-range-into-months-in-python"""
    next_month = any_day.replace(day=28) + datetime.timedelta(days=4) # this will never fail
    return next_month - datetime.timedelta(days=next_month.day)


    def month_list(start_date, end_date):
    """https://stackoverflow.com/questions/51293632/how-do-i-divide-a-date-range-into-months-in-python"""
    result = []
    while True:
    if start_date.month == 12:
    next_month = start_date.replace(year=start_date.year + 1, month=1, day=1)
    else:
    next_month = start_date.replace(month=start_date.month + 1, day=1)
    if next_month > end_date:
    break
    result.append([start_date, last_day_of_month(start_date)])
    start_date = next_month
    result.append([start_date, end_date])
    return result


    def auto_str(cls):
    def __str__(self):
    return '%s(%s)' % (
    type(self).__name__,
    ', '.join('%s=%s' % item for item in vars(self).items())
    )

    cls.__str__ = __str__
    cls.__repr__ = __str__
    return cls


    @auto_str
    class Record:
    def __init__(self, beneficiary=None, details=None, date=None, payment=None, amount=None):
    self.date = date
    self.payment = payment
    self.beneficiary = beneficiary
    self.details = details
    self.amount = amount


    essentials = [Record(beneficiary="anton maier"), Record(beneficiary="swm versorgungs"),
    Record(beneficiary="vodafone gmbh"),
    Record(beneficiary="paypal", details="vodafone"), Record(beneficiary="zurich insurance")]
    food = [Record(details="subway"), Record(details="lidl"), Record(details="edeka"), Record(details="vollcorner"),
    Record(details="aldi")]
    clothing = [Record(details="decathlon"), Record(details="karstadt")]
    amazon = [Record(beneficiary="amazon")]


    def matches(matcher, record):
    if matcher.details is not None and matcher.beneficiary is not None:
    return matcher.details in record.details and matcher.beneficiary in record.beneficiary
    if matcher.details is not None:
    return matcher.details in record.details
    if matcher.beneficiary is not None:
    return matcher.beneficiary in record.beneficiary


    def query(records, start_date, end_date, category):
    """Some really bad querying."""
    queried = []
    filtered = [record for record in records if start_date <= record.date < end_date]
    for record in filtered:
    for matcher in category:
    if matches(matcher, record):
    queried.append(record)
    return queried


    def print_monthly(start_date, end_date):
    for month_range in month_list(start_date, end_date):
    print(month_range[0], "to", month_range[1])
    queried = query(records, month_range[0], month_range[1], food)
    print("I spent:", sum([record.amount for record in queried]))
    # for record in queried:
    # print(record)


    if __name__ == '__main__':
    # parser = argparse.ArgumentParser()
    # parser.add_argument("file", required=False,
    # default="/home/rish/Documents/Everything/2020/Bank Statements/db-20200206-20200804.csv")
    # args = parser.parse_args()

    records = []

    file = open("/home/rish/Documents/Everything/2020/Bank Statements/db-20200206-20200804.csv", encoding="iso-8859-1")
    reader = csv.reader(islice(file, 7, None), delimiter=";")
    for line in reader:
    try:
    date = datetime.datetime.strptime(line[0], '%m/%d/%Y')
    except Exception:
    print('failed to parse ', line, "\n")
    continue
    amount = line[15] + line[16]
    records.append(
    Record(beneficiary=line[3].lower(), details=line[4].lower(), date=date, payment=line[2].lower(),
    amount=float(amount.replace(',', ''))))

    print_monthly(datetime.datetime(2020, 3, 1), datetime.datetime(2020, 7, 31))