This commit is contained in:
spla 2022-04-06 20:08:38 +02:00
pare 6d73c5a10c
commit 05a6e2f526
S'han modificat 3 arxius amb 435 adicions i 394 eliminacions

Veure arxiu

@ -1,145 +0,0 @@
from datetime import datetime, timezone, timedelta
import time
import threading
import os
import sys
import os.path
import psycopg2
import pytz
import dateutil
from dateutil.parser import parse
from decimal import *
getcontext().prec = 2
###############################################################################
# get bills rows
###############################################################################
def print_bills():
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute("SELECT datetime, domain, server, backup, fileserver, setup FROM bills")
rows = cur.fetchall()
for row in rows:
date = row[0].date().strftime('%d.%m.%Y')
print(date, ', domain: ' + str(row[1]), ', server: ' + str(row[2]), 'backup: ' + str(row[3]), ', fileserver: ' + str(row[4]), ' setup: ' + str(row[5]))
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
###################################################################################
# add bills to database
###################################################################################
def insert_bills(billdate, domainbill, serverbill, backupbill, fileserverbill, setupbill):
sql = "INSERT INTO bills(datetime, domain, server, backup, fileserver, setup) VALUES(%s,%s,%s,%s,%s,%s)"
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute(sql, (billdate, domainbill, serverbill, backupbill, fileserverbill, setupbill))
print("\n")
print("Updating bills...")
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
###############################################################################
# INITIALISATION
###############################################################################
# Returns the parameter from the specified file
def get_parameter( parameter, file_path ):
# Check if db_config.txt file exists
if not os.path.isfile(file_path):
if file_path == "config/db_config.txt":
print("File %s not found, exiting. Run db-setup.py."%file_path)
sys.exit(0)
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
print("Run setup.py")
sys.exit(0)
# Load configuration from config file
config_filepath = "config/db_config.txt"
budget_db = get_parameter("budget_db", config_filepath) # E.g., budget
budget_db_user = get_parameter("budget_db_user", config_filepath) # E.g., mastodon
###############################################################################
while True:
domainbill = input("Domain bill? (q to quit) ")
if domainbill == '':
domainbill = '0.00'
elif domainbill == 'q':
sys.exit("Bye")
domainbill = round(float(domainbill),2)
serverbill = input("Server bill? ")
if serverbill == '':
serverbill = '0.00'
serverbill = round(float(serverbill),2)
backupbill = input("Backup bill? ")
if backupbill == '':
backupbill = '0.00'
backupbill = round(float(backupbill),2)
fileserverbill = input("Fileserver bill? ")
if fileserverbill == '':
fileserverbill = 0.00
fileserverbill = round(float(fileserverbill),2)
setupbill = input("Setup bill? ")
if setupbill == '':
setupbill = 0.00
setupbill = round(float(setupbill),2)
billdate = datetime.strptime(input('Enter Bill date in the format d.m.yyyy '), '%d.%m.%Y')
now = datetime.now()
billdate = billdate.replace(hour=now.hour, minute=now.minute, second=now.second)
insert_bills(billdate, domainbill, serverbill, backupbill, fileserverbill, setupbill)
print_bills()

Veure arxiu

@ -1,132 +0,0 @@
from datetime import datetime, timezone, timedelta
import time
import os
import sys
import os.path
import psycopg2
import dateutil
from dateutil.parser import parse
from decimal import *
getcontext().prec = 2
###############################################################################
# get income rows
###############################################################################
def print_incomes():
conn = None
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute("SELECT datetime, donations, owner FROM incomes")
rows = cur.fetchall()
for row in rows:
date = row[0].date().strftime('%d.%m.%Y')
print(date,' donation: '+ str(row[1]), 'server owner: ' + str(row[2]))
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
###################################################################################
# add incomes to database
###################################################################################
def insert_incomes(incomedate, donationincome, ownerincome):
sql = "INSERT INTO incomes(datetime, donations, owner) VALUES(%s,%s,%s)"
conn = None
try:
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute(sql, (incomedate, donationincome, ownerincome))
print("\n")
print("Updating incomes...")
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
###############################################################################
# INITIALISATION
###############################################################################
# Returns the parameter from the specified file
def get_parameter( parameter, file_path ):
# Check if db_config.txt file exists
if not os.path.isfile(file_path):
if file_path == "config/db_config.txt":
print("File %s not found, exiting. Run db-setup.py."%file_path)
sys.exit(0)
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
print("Run setup.py")
sys.exit(0)
# Load configuration from config file
config_filepath = "config/db_config.txt"
budget_db = get_parameter("budget_db", config_filepath) # E.g., budget
budget_db_user = get_parameter("budget_db_user", config_filepath) # E.g., mastodon
###############################################################################
while True:
donationincome = input("Donation income? (q to quit) ")
if donationincome == '':
donationincome = '0.00'
elif donationincome == 'q':
sys.exit("Bye")
donationincome = round(float(donationincome),2)
ownerincome = input("Server owner income? ")
if ownerincome == '':
ownerincome = '0.00'
ownerincome = round(float(ownerincome),2)
incomedate = datetime.strptime(input('Income date in the format dd.mm.yyyy? '), '%d.%m.%Y')
now = datetime.now()
incomedate = incomedate.replace(hour=now.hour, minute=now.minute, second=now.second)
insert_incomes(incomedate, donationincome, ownerincome)
print_incomes()

552
budget.py
Veure arxiu

@ -1,16 +1,41 @@
import sys
import os
import os.path
import re
from datetime import datetime, timedelta
from mastodon import Mastodon
from datetime import datetime, timezone, timedelta, date
import time
import pytz
import sys
import psycopg2
from mastodon import Mastodon
from mastodon.Mastodon import MastodonMalformedEventError, MastodonNetworkError, MastodonReadTimeout, MastodonAPIError, MastodonIllegalArgumentError
from prettytable import PrettyTable
import pdb
def get_bills():
tz = pytz.timezone('Europe/Madrid')
current_year = now.year
menu_options = {
1: 'Add Bill',
2: 'List Bills',
3: 'Add Donation',
4: 'List Donations',
5: 'Exit',
}
list_show_options = {
1: 'Month',
2: 'Year',
3: 'Total',
4: 'Back',
}
bills = 0
def print_menu():
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():
try:
@ -18,204 +43,497 @@ def get_bills():
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute("select sum (domain) + sum(server) + sum(backup) + sum(fileserver) +sum(setup) from bills where date_part('year', datetime) = (%s)", (current_year,))
row = cur.fetchone()
if row[0] != None:
bills = row[0]
cur.close()
return bills
except (Exception, psycopg2.DatabaseError) as error:
sys.exit(error)
sys.stdout.write(f'\n{str(error)}\n')
finally:
sys.exit("Exiting. Run 'python db-setup'")
if conn is not None:
class Bill:
conn.close()
name = "Bill"
def get_donations():
def __init__(self):
current_year = now.year
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')
donations = 0
while True:
try:
try:
conn = None
self.date = datetime.strptime(input('Enter Bill date in the format d.m.yyyy: '), '%d.%m.%Y')
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
now = datetime.now(tz)
cur = conn.cursor()
self.date = self.date.replace(hour=now.hour, minute=now.minute, second=now.second)
cur.execute("select sum (donations) + sum(owner) from incomes where date_part('year', datetime) = (%s)", (current_year,))
break
row = cur.fetchone()
except:
if row[0] != None:
self.date = format(datetime.now(tz).strftime('%d.%m.%Y %H:%M:%S'))
donations = row[0]
break
else:
def save(self):
donations = 0
sql = "INSERT INTO bills(datetime, domain, server, backup, fileserver, setup) VALUES(%s,%s,%s,%s,%s,%s)"
cur.close()
try:
return donations
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
except (Exception, psycopg2.DatabaseError) as error:
cur = conn.cursor()
sys.exit(error)
cur.execute(sql, (self.date, self.domain, self.server, self.backup, self.fileserver, self.setup))
finally:
print("\nUpdating bills...")
if conn is not None:
conn.commit()
conn.close()
cur.close()
def get_fixed_fees():
except (Exception, psycopg2.DatabaseError) as error:
fees_desc_lst = []
print(error)
fees_types_lst = []
finally:
fees_lst = []
if conn is not None:
conn.close()
try:
class Donation:
conn = None
name = "Donation"
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
def __init__(self):
cur = conn.cursor()
self.amount = float(input('Donation: ') or '0.00')
cur.execute("select fee_description, payment_type, fee from fees")
while True:
rows = cur.fetchall()
try:
for row in rows:
self.date = datetime.strptime(input('Enter Donation date in the format d.m.yyyy: '), '%d.%m.%Y')
fees_desc_lst.append(row[0])
now = datetime.now(tz)
fees_types_lst.append(row[1])
self.date = self.date.replace(hour=now.hour, minute=now.minute, second=now.second)
fees_lst.append(row[2])
break
cur.close()
except:
return (fees_desc_lst, fees_types_lst, fees_lst)
self.date = format(datetime.now(tz).strftime('%d.%m.%Y %H:%M:%S'))
except (Exception, psycopg2.DatabaseError) as error:
break
sys.exit(error)
def save(self):
finally:
sql = "INSERT INTO incomes(datetime, donations) VALUES(%s,%s)"
if conn is not None:
try:
conn.close()
conn = psycopg2.connect(database = budget_db, user = budget_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
def mastodon():
cur.execute(sql, (self.date, self.amount))
# Load secrets from secrets file
secrets_filepath = "secrets/secrets.txt"
uc_client_id = get_parameter("uc_client_id", secrets_filepath)
uc_client_secret = get_parameter("uc_client_secret", secrets_filepath)
uc_access_token = get_parameter("uc_access_token", secrets_filepath)
print("\nUpdating donations...")
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
class BillShow:
name = "BillShow"
def __init__(self):
while(True):
print('\n')
list_show_menu()
show_option = ''
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 (current year)? ')
break
elif show_option == 2:
self.option = 2
self.criteria = input('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):
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 = ''
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 (current year)? ')
break
elif show_option == 2:
self.option = 2
self.criteria = input('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):
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)
def get_config():
global budget_db
global budget_db_user
# Load configuration from config file
config_filepath = "config/config.txt"
mastodon_hostname = get_parameter("mastodon_hostname", config_filepath)
bot_username = get_parameter("bot_username", config_filepath)
# Initialise Mastodon API
mastodon = Mastodon(
client_id = uc_client_id,
client_secret = uc_client_secret,
access_token = uc_access_token,
api_base_url = 'https://' + mastodon_hostname,
)
# Initialise access headers
headers={ 'Authorization': 'Bearer %s'%uc_access_token }
return (mastodon, mastodon_hostname, bot_username)
def db_config():
# Load db configuration from config file
config_filepath = "config/db_config.txt"
budget_db = get_parameter("budget_db", config_filepath)
budget_db_user = get_parameter("budget_db_user", config_filepath)
budget_db = get_db_params("budget_db", config_filepath)
budget_db_user = get_db_params("budget_db_user", config_filepath)
return (budget_db, budget_db_user)
return (config_filepath, budget_db, budget_db_user)
def get_parameter( parameter, file_path ):
def get_db_params( parameter, file_path ):
if not os.path.isfile(file_path):
print("File %s not found, exiting."%file_path)
sys.exit(0)
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
sys.exit(0)
###############################################################################
# main
if __name__ == '__main__':
mastodon, mastodon_hostname, bot_username = mastodon()
get_config()
budget_db, budget_db_user = db_config()
check_db_conn()
now = datetime.now()
while(True):
donations = get_donations()
print('\n')
bills = get_bills()
print_menu()
fees_desc_lst, fees_types_lst, fees_lst = get_fixed_fees()
option = ''
toot_text = 'Finances of ' + mastodon_hostname + '\n\n'
try:
toot_text += 'Year: ' + str(now.year) + '\n'
option = int(input('\nEnter your choice: '))
toot_text += '\n'
except:
toot_text += 'Server bills: ' + str(bills) + '' + '\n'
print('\nWrong input. Please enter a number between 1 and 5.\n')
toot_text += 'Donations: ' + str(donations) + '' + '\n\n'
if option == 1:
if donations != 0 and bills != 0:
bill = Bill()
toot_text += '%: ' + str(round((donations * 100)/bills,2)) + '\n\n'
if bill.domain == bill.server == bill.backup == bill.fileserver == bill.setup == 0.0:
i = 0
print('\nAny bill added')
while i < len(fees_lst):
else:
toot_text += '\n' + str(fees_desc_lst[i]) + ': ' + str(fees_lst[i]) + ' (' + str(fees_types_lst[i]) + ')'
bill.save()
i += 1
elif option == 2:
print(toot_text)
bill = BillShow()
mastodon.status_post(toot_text, in_reply_to_id=None)
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:
donation = DonationShow()
if donation.option == 1 or donation.option == 2 or donation.option == 3:
date_lst, donation_lst = donation.show(donation.criteria)
if donation.option != 4:
print_table = PrettyTable()
print_table.field_names = ['Date','Donation']
print_table.align['Donation'] = "r"
i = 0
total_amount = 0
while i < len(donation_lst):
d_date = format(date_lst[i].strftime('%d.%m.%Y %H:%M:%S'))
d_amount = float(donation_lst[i])
total_amount = total_amount + d_amount
print_table.add_row([d_date, d_amount])
i += 1
print_table.add_row(['Total', round(total_amount, 2)])
print(print_table)
elif option == 5:
print('Bye!')
exit()