budget/budget.py

691 líneas
16 KiB
Python
Original Vista normal Històric

2020-12-24 14:13:31 +01:00
import os
2022-04-06 20:08:38 +02:00
from datetime import datetime, timezone, timedelta, date
import time
import pytz
import sys
2020-12-24 14:13:31 +01:00
import psycopg2
2022-04-06 20:08:38 +02:00
from mastodon import Mastodon
from mastodon.Mastodon import MastodonMalformedEventError, MastodonNetworkError, MastodonReadTimeout, MastodonAPIError, MastodonIllegalArgumentError
from prettytable import PrettyTable
import pdb
tz = pytz.timezone('Europe/Madrid')
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
menu_options = {
1: 'Add Bill',
2: 'List Bills',
3: 'Add Donation',
4: 'List Donations',
2022-08-19 14:37:39 +02:00
5: 'Balance',
6: 'Exit',
2022-04-06 20:08:38 +02:00
}
list_show_options = {
1: 'Month',
2: 'Year',
3: 'Total',
4: 'Back',
}
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
def print_menu():
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
for key in menu_options.keys():
print (key, '-', menu_options[key] )
def list_show_menu():
for key in list_show_options.keys():
print (key, '-', list_show_options[key] )
def check_db_conn():
2020-12-24 14:13:31 +01:00
try:
conn = None
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
2022-04-06 20:08:38 +02:00
except (Exception, psycopg2.DatabaseError) as error:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
sys.stdout.write(f'\n{str(error)}\n')
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
sys.exit("Exiting. Run 'python db-setup'")
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
class Bill:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
name = "Bill"
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
def __init__(self):
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.domain = float(input('Enter Domain Bill: ') or '0.00')
self.server = float(input('Server Bill: ') or '0.00')
self.backup = float(input('Backup Bill: ') or '0.00')
self.fileserver = float(input("File server Bill: ") or '0.00')
self.setup = float(input(f'Setup Bill: ') or '0.00')
while True:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
try:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.date = datetime.strptime(input('Enter Bill date in the format d.m.yyyy: '), '%d.%m.%Y')
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
now = datetime.now(tz)
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.date = self.date.replace(hour=now.hour, minute=now.minute, second=now.second)
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
break
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
except:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.date = format(datetime.now(tz).strftime('%d.%m.%Y %H:%M:%S'))
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
break
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
def save(self):
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
sql = "INSERT INTO bills(datetime, domain, server, backup, fileserver, setup) VALUES(%s,%s,%s,%s,%s,%s)"
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
try:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
cur = conn.cursor()
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
cur.execute(sql, (self.date, self.domain, self.server, self.backup, self.fileserver, self.setup))
print("\nUpdating bills...")
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
conn.commit()
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
cur.close()
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
except (Exception, psycopg2.DatabaseError) as error:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
print(error)
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
finally:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
if conn is not None:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
conn.close()
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
class Donation:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
name = "Donation"
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
def __init__(self):
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.amount = float(input('Donation: ') or '0.00')
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
while True:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
try:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
self.date = datetime.strptime(input('Enter Donation date in the format d.m.yyyy: '), '%d.%m.%Y')
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
now = datetime.now(tz)
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
self.date = self.date.replace(hour=now.hour, minute=now.minute, second=now.second)
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
break
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
except:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
self.date = format(datetime.now(tz).strftime('%d.%m.%Y %H:%M:%S'))
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
break
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
def save(self):
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
sql = "INSERT INTO incomes(datetime, donations) VALUES(%s,%s)"
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
try:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
cur = conn.cursor()
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
cur.execute(sql, (self.date, self.amount))
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
print("\nUpdating donations...")
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
conn.commit()
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
cur.close()
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
except (Exception, psycopg2.DatabaseError) as error:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
print(error)
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
finally:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
if conn is not None:
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
conn.close()
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
class BillShow:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
name = "BillShow"
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
def __init__(self):
while(True):
print('\n')
list_show_menu()
show_option = ''
2022-08-19 14:30:39 +02:00
now = datetime.now(tz)
2022-04-06 20:08:38 +02:00
try:
show_option = int(input('\nEnter your choice: '))
except:
print('\nWrong input. Please enter a number between 1 and 4.\n')
if show_option == 1:
self.option = 1
2022-08-19 14:30:39 +02:00
self.criteria = input('Month (enter = current month)? ') or str(now.month)
2022-04-06 20:08:38 +02:00
break
elif show_option == 2:
self.option = 2
2022-08-19 14:30:39 +02:00
self.criteria = input('Year (enter = current year)? ') or str(now.year)
2022-04-06 20:08:38 +02:00
break
elif show_option == 3:
self.option = 3
self.criteria = None
break
elif show_option == 4:
self.option = 4
self.criteria = None
break
def show(self, criteria):
month_date = []
month_domain = []
month_server = []
month_backup = []
month_fileserver = []
month_setup = []
if self.option == 1:
sql = "select datetime, domain, server, backup, fileserver, setup from bills where date_part('year', datetime) = date_part('year', CURRENT_DATE) and date_part('month', datetime) = (%s) order by 1 asc"
elif self.option == 2:
sql = "select datetime, domain, server, backup, fileserver, setup from bills where date_part('year', datetime) = (%s) order by 1 asc"
elif self.option == 3:
sql = "select datetime, domain, server, backup, fileserver, setup from bills order by 1 asc"
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
if self.option == 1 or self.option == 2:
cur.execute(sql, (self.criteria,))
else:
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
month_date.append(row[0])
month_domain.append(row[1])
month_server.append(row[2])
month_backup.append(row[3])
month_fileserver.append(row[4])
month_setup.append(row[5])
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
return (month_date, month_domain, month_server, month_backup, month_fileserver, month_setup)
class DonationShow:
name = "DonationShow"
def __init__(self):
while(True):
print('\n')
list_show_menu()
show_option = ''
2022-08-19 14:30:39 +02:00
now = datetime.now(tz)
2022-04-06 20:08:38 +02:00
try:
show_option = int(input('\nEnter your choice: '))
except:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
print('\nWrong input. Please enter a number between 1 and 4.\n')
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
if show_option == 1:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.option = 1
2022-08-19 14:30:39 +02:00
self.criteria = input('Month (enter = current month)? ') or str(now.month)
2022-04-06 20:08:38 +02:00
break
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
elif show_option == 2:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
self.option = 2
2022-08-19 14:30:39 +02:00
self.criteria = input('Year (enter = current year)? ') or str(now.year)
2022-04-06 20:08:38 +02:00
break
elif show_option == 3:
self.option = 3
self.criteria = None
break
elif show_option == 4:
self.option = 4
self.criteria = None
break
def show(self, criteria):
month_date = []
month_donation = []
if self.option == 1:
sql = "select datetime, donations from incomes where date_part('year', datetime) = date_part('year', CURRENT_DATE) and date_part('month', datetime) = (%s) order by 1 asc"
elif self.option == 2:
sql = "select datetime, donations from incomes where date_part('year', datetime) = (%s) order by 1 asc"
elif self.option == 3:
sql = "select datetime, donations from incomes order by 1 asc"
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
if self.option == 1 or self.option == 2:
cur.execute(sql, (self.criteria,))
else:
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
month_date.append(row[0])
month_donation.append(row[1])
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
return (month_date, month_donation)
2022-08-19 14:37:39 +02:00
class BalanceShow:
name = "BalanceShow"
def __init__(self):
while(True):
print('\n')
list_show_menu()
show_option = ''
now = datetime.now(tz)
try:
show_option = int(input('\nEnter your choice: '))
except:
print('\nWrong input. Please enter a number between 1 and 4.\n')
if show_option == 1:
self.option = 1
self.criteria = input('Month (enter = current month)? ') or str(now.month)
break
elif show_option == 2:
self.option = 2
self.criteria = input('Year (enter = current year)? ') or str(now.year)
break
elif show_option == 3:
self.option = 3
self.criteria = None
break
elif show_option == 4:
self.option = 4
self.criteria = None
break
def show(self, criteria):
balance = 0
if self.option == 1:
incomes_sql = "select sum(donations) from incomes where date_part('year', datetime) = date_part('year', CURRENT_DATE) and date_part('month', datetime) = (%s)"
bills_sql = "select sum(coalesce(domain) + coalesce(server) + coalesce(backup) + coalesce(fileserver) + coalesce(setup)) from bills where date_part('year', datetime) = date_part('year', CURRENT_DATE) and date_part('month', datetime) = (%s)"
elif self.option == 2:
incomes_sql = "select sum(donations) from incomes where date_part('year', datetime) = (%s)"
bills_sql = "select sum(coalesce(domain) + coalesce(server) + coalesce(backup) + coalesce(fileserver) + coalesce(setup)) from bills where date_part('year', datetime) = (%s)"
elif self.option == 3:
incomes_sql = "select sum(donations) from incomes order by 1 asc"
bills_sql = "select sum(coalesce(domain) + coalesce(server) + coalesce(backup) + coalesce(fileserver) + coalesce(setup)) from bills"
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
if self.option == 1 or self.option == 2:
cur.execute(incomes_sql, (self.criteria,))
row = cur.fetchone()
2022-10-02 10:20:06 +02:00
incomes = row[0] if row[0] != None else 0
2022-08-19 14:37:39 +02:00
cur.execute(bills_sql, (self.criteria,))
row = cur.fetchone()
bills = row[0]
2022-10-02 10:20:06 +02:00
bills = row[0] if row[0] != None else 0
2022-08-19 14:37:39 +02:00
else:
cur.execute(incomes_sql)
row = cur.fetchone()
incomes = row[0]
cur.execute(bills_sql)
row = cur.fetchone()
bills = row[0]
balance = incomes - bills
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
return (balance)
2022-04-06 20:08:38 +02:00
def get_config():
global budget_db
global budget_db_user
# Load configuration from config file
2020-12-24 14:13:31 +01:00
config_filepath = "config/db_config.txt"
2022-04-06 20:08:38 +02:00
budget_db = get_db_params("budget_db", config_filepath)
budget_db_user = get_db_params("budget_db_user", config_filepath)
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
return (config_filepath, budget_db, budget_db_user)
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
def get_db_params( parameter, file_path ):
2020-12-24 14:13:31 +01:00
if not os.path.isfile(file_path):
print("File %s not found, exiting."%file_path)
sys.exit(0)
2022-04-06 20:08:38 +02:00
# Find parameter in file
2020-12-24 14:13:31 +01:00
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
2022-04-06 20:08:38 +02:00
# Cannot find parameter, exit
2020-12-24 14:13:31 +01:00
print(file_path + " Missing parameter %s "%parameter)
sys.exit(0)
# main
if __name__ == '__main__':
2022-04-06 20:08:38 +02:00
get_config()
check_db_conn()
while(True):
print('\n')
print_menu()
option = ''
try:
option = int(input('\nEnter your choice: '))
except:
print('\nWrong input. Please enter a number between 1 and 5.\n')
if option == 1:
bill = Bill()
if bill.domain == bill.server == bill.backup == bill.fileserver == bill.setup == 0.0:
print('\nAny bill added')
else:
bill.save()
elif option == 2:
bill = BillShow()
if bill.option == 1 or bill.option == 2 or bill.option == 3:
month_date, month_domain, month_server, month_backup, month_fileserver, month_setup = bill.show(bill.criteria)
if bill.option != 4:
print_table = PrettyTable()
print_table.field_names = ['Date', 'Domain', 'Server', 'Backup', 'File server', 'Setup']
i = 0
total_amount = 0
while i < len(month_date):
b_date = format(month_date[i].strftime('%d.%m.%Y %H:%M:%S'))
b_domain = float(month_domain[i])
b_server = float(month_server[i])
b_backup = float(month_backup[i])
b_fileserver = float(month_fileserver[i])
b_setup = float(month_setup[i])
total_amount = total_amount + b_domain + b_server + b_backup + b_fileserver + b_setup
print_table.add_row([b_date, b_domain, b_server, b_backup, b_fileserver, b_setup])
i += 1
print_table.add_row(['', '', '', '', 'Total', round(total_amount, 2)])
print(print_table)
elif option == 3:
donation = Donation()
if donation.amount == 0.0:
print('\nAny donation added')
else:
donation.save()
elif option == 4:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
donation = DonationShow()
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
if donation.option == 1 or donation.option == 2 or donation.option == 3:
date_lst, donation_lst = donation.show(donation.criteria)
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
if donation.option != 4:
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
print_table = PrettyTable()
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
print_table.field_names = ['Date','Donation']
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
print_table.align['Donation'] = "r"
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
i = 0
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
total_amount = 0
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
while i < len(donation_lst):
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
d_date = format(date_lst[i].strftime('%d.%m.%Y %H:%M:%S'))
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
d_amount = float(donation_lst[i])
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
total_amount = total_amount + d_amount
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
print_table.add_row([d_date, d_amount])
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
i += 1
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
print_table.add_row(['Total', round(total_amount, 2)])
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
print(print_table)
2021-01-22 18:36:18 +01:00
2022-04-06 20:08:38 +02:00
elif option == 5:
2020-12-24 14:13:31 +01:00
2022-08-19 14:37:39 +02:00
balance = BalanceShow()
if balance.option == 1 or balance.option == 2 or balance.option == 3:
balance_result = balance.show(balance.criteria)
if balance.option != 4:
print_table = PrettyTable()
print_table.field_names = ['Balance']
print_table.align['Balance'] = "r"
b_amount = float(balance_result)
print_table.add_row([b_amount])
2022-10-02 10:20:06 +02:00
#print_table.add_row(['Total', round(total_amount, 2)])
2022-08-19 14:37:39 +02:00
print(print_table)
elif option == 6:
2022-04-06 20:08:38 +02:00
print('Bye!')
2020-12-24 14:13:31 +01:00
2022-04-06 20:08:38 +02:00
exit()
2020-12-24 14:13:31 +01:00