5 Commits

Author SHA1 Message Date
58d0e6191c optimized screen clear 2021-06-06 14:21:57 +02:00
3d9d1a1d5f db handling optimized 2021-06-05 11:39:28 +02:00
a5cde65967 fix sheebang (Issue#2) 2021-06-04 18:38:40 +02:00
6834469b62 Menu navigation optimized (Issue#1) 2021-06-04 18:07:25 +02:00
28bc3b319e set to v.2.0.0 aplha 2021-06-04 11:22:58 +02:00

View File

@@ -1,9 +1,9 @@
#!/bin/python3 #!/usr/bin/env python3
######################### #########################
# #
# timeTrack.py # timeTrack.py
# by 4nima # by 4nima
# v.0.5.0 # v.2.0.4
# #
######################### #########################
# simple time tracking with database # simple time tracking with database
@@ -24,6 +24,7 @@ class TimeTrack:
self.USERNAME = '' self.USERNAME = ''
self.OLDEVENT = 2 self.OLDEVENT = 2
self.LOGFILE = 'timetrack.log' self.LOGFILE = 'timetrack.log'
self.DBCON = sqlite3.connect(self.DATABASE, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
logging.basicConfig( logging.basicConfig(
filename=self.LOGFILE, filename=self.LOGFILE,
level=logging.DEBUG, level=logging.DEBUG,
@@ -33,6 +34,9 @@ class TimeTrack:
self.db_setup() self.db_setup()
self.load_config() self.load_config()
def __del__(self):
self.DBCON.close()
## Prepartation ## Prepartation
### Check OS and clear screen ### Check OS and clear screen
def clear_screen(self): def clear_screen(self):
@@ -95,23 +99,20 @@ class TimeTrack:
) )
""") """)
connect = sqlite3.connect(self.DATABASE)
cursor = connect.cursor()
logging.debug('Create initial database tables') logging.debug('Create initial database tables')
for SQL in sql:
try: try:
cursor.execute(SQL) with self.DBCON as con:
except: for SQL in sql:
con.execute(SQL)
except sqlite3.Error as err:
logging.error('Table could not be created') logging.error('Table could not be created')
logging.debug(SQL) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
print('TimeTrack wird beendet: Fehler bei Datanbank Setup') print('TimeTrack wird beendet: Fehler bei Datanbank Setup')
quit() quit()
else: else:
logging.debug('Table was created successfully or already exists') logging.debug('Table was created successfully or already exists')
connect.commit()
connect.close()
### Loads or creates a config file ### Loads or creates a config file
def load_config(self): def load_config(self):
if os.path.isfile(self.CONFIG): if os.path.isfile(self.CONFIG):
@@ -160,21 +161,16 @@ class TimeTrack:
logging.debug('Accepted username: {}'.format(username)) logging.debug('Accepted username: {}'.format(username))
connect = sqlite3.connect(self.DATABASE)
cursor = connect.cursor()
sql = "INSERT INTO users ( name ) values ( ? )" sql = "INSERT INTO users ( name ) values ( ? )"
try: try:
cursor.execute(sql, [username]) with self.DBCON as con:
except: con.execute(sql, [username])
except sqlite3.Error as err:
logging.error('User could not be saved in database') logging.error('User could not be saved in database')
logging.debug(sql) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
else: else:
logging.info('User was saved successfully') logging.info('User was saved successfully')
connect.commit()
connect.close()
### Outputs existing users from the DB ### Outputs existing users from the DB
def get_users(self, UID=0, NAME=''): def get_users(self, UID=0, NAME=''):
@@ -191,25 +187,23 @@ class TimeTrack:
data = '' data = ''
sql = "SELECT * FROM users" sql = "SELECT * FROM users"
connect = sqlite3.connect(self.DATABASE)
cursor = connect.cursor()
try: try:
with self.DBCON as con:
cur = con.cursor()
if data: if data:
cursor.execute(sql, [data]) cur.execute(sql, [data])
else: else:
cursor.execute(sql) cur.execute(sql)
except: data = cur.fetchall()
except sqlite3.Error as err:
logging.error('Could not get user') logging.error('Could not get user')
logging.debug(sql) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
print('Fehler beim Zugriff auf die Benutzer Datenbank') print('Fehler beim Zugriff auf die Benutzer Datenbank')
return 1 return 1
else: else:
logging.debug('User database read out successfully') logging.debug('User database read out successfully')
connect.commit()
data = cursor.fetchall()
connect.close()
return data return data
### Defines a user for the session ### Defines a user for the session
@@ -231,23 +225,22 @@ class TimeTrack:
def save_event(self, TIME=datetime.datetime.now()): def save_event(self, TIME=datetime.datetime.now()):
if not self.get_event(USERID=self.USERID): if not self.get_event(USERID=self.USERID):
logging.debug('No active events found for the user: {}'.format(self.USERID)) logging.debug('No active events found for the user: {}'.format(self.USERID))
connect = sqlite3.connect(self.DATABASE)
cursor = connect.cursor()
sql = "INSERT INTO active_events ( starttime, user_id ) VALUES ( ?, ? )"
sql = "INSERT INTO active_events ( starttime, user_id ) VALUES ( ?, ? )"
try: try:
cursor.execute(sql, [TIME, self.USERID]) with self.DBCON as con:
except: con.execute(sql, [TIME, self.USERID])
except sqlite3.Error as err:
logging.error('Event could not be created') logging.error('Event could not be created')
logging.debug(sql) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
print('Event konnte nicht gespeichert werden.') print('Event konnte nicht gespeichert werden.')
return False return False
else: else:
logging.info('Event was created successfully') logging.info('Event was created successfully')
connect.commit()
connect.close()
return True return True
else: else:
logging.warning('Active events found for the user, new event could not be created') logging.warning('Active events found for the user, new event could not be created')
return False return False
@@ -267,20 +260,16 @@ class TimeTrack:
print('Keine angabe was gelöscht werden soll') print('Keine angabe was gelöscht werden soll')
return 0 return 0
connect = sqlite3.connect(self.DATABASE, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
cursor = connect.cursor()
try: try:
cursor.execute(sql, [data]) with self.DBCON as con:
except: con.execute(sql, [data])
except sqlite3.Error as err:
logging.error('Event could not be deleted') logging.error('Event could not be deleted')
logging.debug(sql) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
print('Fehler beim löschen des Events.') print('Fehler beim löschen des Events.')
else: else:
logging.debug('Event was successfully deleted') logging.debug('Event was successfully deleted')
connect.commit()
connect.close()
### Get an active event based on a user or event ID ### Get an active event based on a user or event ID
def get_event(self, ENTRYID='', USERID=''): def get_event(self, ENTRYID='', USERID=''):
@@ -296,23 +285,24 @@ class TimeTrack:
sql = "SELECT * FROM active_events" sql = "SELECT * FROM active_events"
data = '' data = ''
connect = sqlite3.connect(self.DATABASE, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
cursor = connect.cursor()
try: try:
with self.DBCON as con:
cur = con.cursor()
if data: if data:
logging.debug('Search event') logging.debug('Search event')
cursor.execute(sql, [data]) cur.execute(sql, [data])
else: else:
logging.debug('Get all Events') logging.debug('Get all Events')
cursor.execute(sql) cur.execute(sql)
except: data = cur.fetchall()
except sqlite3.Error as err:
logging.error('Events could not be read') logging.error('Events could not be read')
logging.debug(sql) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
print('Fehler beim auslesen der aktiven Events') print('Fehler beim auslesen der aktiven Events')
else: else:
logging.debug('Events could be read out successfully') logging.debug('Events could be read out successfully')
data = cursor.fetchall()
connect.close()
if data == []: if data == []:
logging.debug('No active events found') logging.debug('No active events found')
return 0 return 0
@@ -348,24 +338,24 @@ class TimeTrack:
logging.debug('Event younger than 1 day') logging.debug('Event younger than 1 day')
print('Vergangene Zeit: >{} Stunden'.format(int(elapsed.seconds/3600))) print('Vergangene Zeit: >{} Stunden'.format(int(elapsed.seconds/3600)))
userinput = '' userinput = 0
while True: while not 0 < int(userinput) < 4:
if userinput == "F" or userinput == "f" or userinput == "1" \
or userinput == "L" or userinput == "l" or userinput == "2" \
or userinput == "A" or userinput == "a" or userinput == "3":
break
print('Soll das Event fortgesetzt oder gelöscht werden?') print('Soll das Event fortgesetzt oder gelöscht werden?')
print('[1/F/f] für fortsetzen') print('[1] für fortsetzen')
print('[2/L/l] für löschen') print('[2] für löschen')
print('[3/A/a] für abbrechen') print('[3] für abbrechen')
userinput = input('Aktion: ') userinput = input('Aktion: ')
logging.debug('User input: {}'.format(userinput)) logging.debug('User input: {}'.format(userinput))
try:
int(userinput)
except ValueError:
userinput = 0
self.clear_screen() self.clear_screen()
if userinput == "F" or userinput == "f" or userinput == "1": if userinput == "1":
logging.debug('Event should be continued') logging.debug('Event should be continued')
self.time_stop() self.time_stop()
elif userinput == "L" or userinput == "l" or userinput == "2": elif userinput == "2":
logging.info('Event should be deleted (eventid: {})'.format(data[0])) logging.info('Event should be deleted (eventid: {})'.format(data[0]))
self.delete_event(data[0]) self.delete_event(data[0])
self.time_start() self.time_start()
@@ -383,21 +373,21 @@ class TimeTrack:
logging.debug('Event stop progess is started') logging.debug('Event stop progess is started')
if data: if data:
self.clear_screen() self.clear_screen()
userinput = '' userinput = 0
while True: while not 0 < int(userinput) < 4:
if userinput == "B" or userinput == "b" or userinput == "1" \
or userinput == "L" or userinput == "l" or userinput == "2" \
or userinput == "A" or userinput == "a" or userinput == "3":
break
print('Event von {} Uhr beenden?'.format(data[1].strftime("%H:%M"))) print('Event von {} Uhr beenden?'.format(data[1].strftime("%H:%M")))
print('[1/B/b] für beenden') print('[1] für beenden')
print('[2/L/l] für löschen') print('[2] für löschen')
print('[3/A/a] für abbrechen') print('[3] für abbrechen')
userinput = input('Aktion: ') userinput = input('Aktion: ')
logging.debug('User input: {}'.format(userinput)) logging.debug('User input: {}'.format(userinput))
try:
int(userinput)
except ValueError:
userinput = 0
self.clear_screen() self.clear_screen()
if userinput == "B" or userinput == "b" or userinput == "1": if userinput == "1":
logging.debug('Event is ended') logging.debug('Event is ended')
print('Eingabe beenden mittels doppelter Leerzeile.') print('Eingabe beenden mittels doppelter Leerzeile.')
print('Durchgeführte Tätigkeiten:') print('Durchgeführte Tätigkeiten:')
@@ -421,44 +411,43 @@ class TimeTrack:
endtime = datetime.datetime.now() endtime = datetime.datetime.now()
logging.debug('Event end process start at {}'.format(endtime)) logging.debug('Event end process start at {}'.format(endtime))
connect = sqlite3.connect(self.DATABASE)
cursor = connect.cursor()
sql = "INSERT INTO time_entries ( starttime, endtime, user_id, activity ) VALUES ( ?, ?, ?, ? )"
sql = "INSERT INTO time_entries ( starttime, endtime, user_id, activity ) VALUES ( ?, ?, ?, ? )"
try: try:
cursor.execute(sql, [data[1], endtime, self.USERID, action]) with self.DBCON as con:
except: con.execute(sql, [data[1], endtime, self.USERID, action])
except sqlite3.Error as err:
logging.error('Time entry could not be created') logging.error('Time entry could not be created')
logging.debug(sql) logging.debug(sql)
logging.error('SQLError: {}'.format(err))
print('Zeiteintrag konnte nicht gespeichert werden.') print('Zeiteintrag konnte nicht gespeichert werden.')
return False return False
else: else:
logging.info('Time entry was created successfully') logging.info('Time entry was created successfully')
connect.commit()
self.delete_event(data[0]) self.delete_event(data[0])
self.print_time_entry(STARTTIME=data[1], ENDTIME=endtime, ACTIVITY=action) self.print_time_entry(STARTTIME=data[1], ENDTIME=endtime, ACTIVITY=action)
print('Zeiteintrag wurde gespeichert.') print('Zeiteintrag wurde gespeichert.')
while True: userinput = 0
if userinput == "J" or userinput == "j" or userinput == "1" \ while not 0 < int(userinput) < 3:
or userinput == "N" or userinput == "n" or userinput == "2": print('Nächsten Zeiteintrag beginnen ?')
break print('[1] Ja')
print('Nächsten Zeiteintrag begrinnen ?') print('[2] Nein')
print('[1/J/j] Ja')
print('[2/N/n] Nein')
userinput = input('Aktion: ') userinput = input('Aktion: ')
logging.debug('User input: {}'.format(userinput)) logging.debug('User input: {}'.format(userinput))
try:
int(userinput)
except ValueError:
userinput = 0
self.clear_screen() self.clear_screen()
if userinput == "J" or userinput == "j" or userinput == "1": if userinput == "1":
self.time_start() self.time_start()
else: else:
logging.debug('Terminated by the user') logging.debug('Terminated by the user')
exit() exit()
elif userinput == "2":
connect.close()
elif userinput == "L" or userinput == "l" or userinput == "2":
logging.info('Event should be deleted (eventid: {})'.format(data[0])) logging.info('Event should be deleted (eventid: {})'.format(data[0]))
self.delete_event(data[0]) self.delete_event(data[0])
else: else:
@@ -469,6 +458,7 @@ class TimeTrack:
pass pass
def print_time_entry(self, STARTTIME='', ENDTIME='', ACTIVITY=''): def print_time_entry(self, STARTTIME='', ENDTIME='', ACTIVITY=''):
self.clear_screen()
s = (ENDTIME - STARTTIME).seconds s = (ENDTIME - STARTTIME).seconds
hours, remainder = divmod(s, 3600) hours, remainder = divmod(s, 3600)
minutes, seconds = divmod(remainder, 60) minutes, seconds = divmod(remainder, 60)
@@ -482,8 +472,7 @@ class TimeTrack:
print(ACTIVITY) print(ACTIVITY)
print(50*"-") print(50*"-")
if __name__ == "__main__":
test = TimeTrack()
test.time_start()
test = TimeTrack() test.DBCON.close()
test.time_start()