def _wrapped_view_func(*args, **kwargs): try: user = request.environ.get('TIMEBOOK_USER') human_username = get_human_username(user) config_file = os.path.expanduser("~%s/.config/timebook/timebook.ini" % user) timesheet_db = os.path.expanduser("~%s/.config/timebook/sheets.db" % user) config = parse_config(config_file) config.add_section('temp') config.set('temp', 'human_name', human_username) cursor = Database( timesheet_db, config, ) if("TIMEBOOK_LOG_FILE" in request.environ.keys()): from logging.handlers import RotatingFileHandler file_handler = RotatingFileHandler( request.environ.get('TIMEBOOK_LOG_FILE'), maxBytes=2 ** 20, backupCount=1, ) file_handler.setLevel(logging.DEBUG) app.logger.addHandler(file_handler) logger.addHandler(file_handler) logger.info(cursor.config) return view_func(cursor, config, *args, **kwargs) except Exception as e: import traceback return error_view("Error encountered: %s" % traceback.format_exc())
def _wrapped_view_func(*args, **kwargs): try: user = request.environ.get('TIMEBOOK_USER') human_username = get_human_username(user) config_file = os.path.expanduser( "~%s/.config/timebook/timebook.ini" % user) timesheet_db = os.path.expanduser( "~%s/.config/timebook/sheets.db" % user) config = parse_config(config_file) config.add_section('temp') config.set('temp', 'human_name', human_username) cursor = Database( timesheet_db, config, ) if ("TIMEBOOK_LOG_FILE" in request.environ.keys()): from logging.handlers import RotatingFileHandler file_handler = RotatingFileHandler( request.environ.get('TIMEBOOK_LOG_FILE'), maxBytes=2**20, backupCount=1, ) file_handler.setLevel(logging.DEBUG) app.logger.addHandler(file_handler) logger.addHandler(file_handler) logger.info(cursor.config) return view_func(cursor, config, *args, **kwargs) except Exception as e: import traceback return error_view("Error encountered: %s" % traceback.format_exc())
def taskwarrior(db, args, extra=None): def poll_taskwarrior(): tasks = [] results = subprocess.check_output( [ "task", "export", "status:pending", "start.not:", ] ) for line in results.splitlines(): if len(line.strip()) > 0: tasks.append( json.loads(line.rstrip(',')) ) return ( tasks, hashlib.md5('|'.join([t.get('uuid') for t in tasks])).hexdigest() ) logger.info("Watching taskwarrior output...") task_hash_status = '' while True: tasks, task_hash = poll_taskwarrior() args = [] command = 'change' do_change = False value = dbutil.get_current_active_info(db) if not value and task_hash_status != '': logger.error("Clocked-out.") task_hash_status = '' elif value and task_hash != task_hash_status: task_hash_status = task_hash if tasks: if len(tasks) > 1: logger.warning( "Multiple tasks currently active; using first." ) task = tasks[0] logger.info("Active task changed: %s" % task) # Ticket No. ticket = task.get('ticket') if ticket: args.append('--ticket=%s' % ticket) # Pull Request No. pr = task.get('pr') if pr: args.append('--pr=%s' % pr.replace('/', ':')) # Description description = task.get('description') if description: args.append(description) _, duration = value logger.error(duration) if duration < 60: command = 'alter' do_change = True else: logger.warning("No active tasks; changing to nil.") do_change = True if do_change: logger.info("Running %s %s" % (command, args)) run_command(db, command, args) time.sleep(1)
def taskwarrior(db, args, extra=None): def poll_taskwarrior(): tasks = [] results = subprocess.check_output([ "task", "export", "status:pending", "start.not:", ]) for line in results.splitlines(): if len(line.strip()) > 0: tasks.append(json.loads(line.rstrip(','))) return (tasks, hashlib.md5('|'.join([t.get('uuid') for t in tasks])).hexdigest()) logger.info("Watching taskwarrior output...") task_hash_status = '' while True: tasks, task_hash = poll_taskwarrior() args = [] command = 'change' do_change = False value = dbutil.get_current_active_info(db) if not value and task_hash_status != '': logger.error("Clocked-out.") task_hash_status = '' elif value and task_hash != task_hash_status: task_hash_status = task_hash if tasks: if len(tasks) > 1: logger.warning( "Multiple tasks currently active; using first.") task = tasks[0] logger.info("Active task changed: %s" % task) # Ticket No. ticket = task.get('ticket') if ticket: args.append('--ticket=%s' % ticket) # Pull Request No. pr = task.get('pr') if pr: args.append('--pr=%s' % pr.replace('/', ':')) # Description description = task.get('description') if description: args.append(description) _, duration = value logger.error(duration) if duration < 60: command = 'alter' do_change = True else: logger.warning("No active tasks; changing to nil.") do_change = True if do_change: logger.info("Running %s %s" % (command, args)) run_command(db, command, args) time.sleep(1)
def billable(cursor, config): start = request.args.get('start', (datetime.datetime.now() - datetime.timedelta(days = 30)).strftime("%Y-%m-%d")) end = request.args.get('end', datetime.datetime.now().strftime("%Y-%m-%d")) project = request.args.getlist('project') select_constraint = '' if start: select_constraint = select_constraint + " AND start_time > STRFTIME('%%s', '%s', 'utc') " % start if end: select_constraint = select_constraint + " AND start_time < STRFTIME('%%s', '%s', 'utc', '1 day') " % end if project: project_constraints = [] for p in project: project_constraints.append(" project = '%s' " % p) project_constraint = " OR ".join(project_constraints) select_constraint = select_constraint + " AND ( %s ) " % project_constraint logger.info(select_constraint) billable_by_day_sql = """ SELECT date, ROUND(SUM(CASE WHEN entry.billable = 1 THEN entry.duration ELSE 0 END) / CAST(SUM(entry.duration) AS FLOAT) * 100, 1) FROM ( SELECT billable, STRFTIME('%Y-%m-%d', start_time, 'unixepoch', 'localtime') AS date, end_time - start_time as duration FROM entry INNER JOIN entry_details ON entry_details.entry_id = entry.id LEFT JOIN ticket_details ON entry_details.ticket_number = ticket_details.number WHERE sheet = 'default' """ + (select_constraint if select_constraint else "") + """ ) AS entry GROUP BY date ORDER BY date """ billable_by_day_raw = cursor.execute(billable_by_day_sql).fetchall() billable_by_day = [] prev_date = False for row in billable_by_day_raw: this_date = row[0] while prev_date and prev_date != (datetime.datetime.strptime(this_date, "%Y-%m-%d") - datetime.timedelta(days = 1)).strftime("%Y-%m-%d"): prev_date_object = (datetime.datetime.strptime(prev_date, "%Y-%m-%d") + datetime.timedelta(days = 1)) prev_date = prev_date_object.strftime("%Y-%m-%d") if 0 < int(datetime.datetime.strptime(prev_date, "%Y-%m-%d").strftime("%w")) < 6: if not date_is_untracked(cursor, prev_date_object.year, prev_date_object.month, prev_date_object.day): billable_by_day.append([prev_date, 0]) billable_by_day.append(row) prev_date = row[0] all_client_list = cursor.execute(""" SELECT distinct project FROM ticket_details """).fetchall() client_list = cursor.execute(""" SELECT distinct project FROM ticket_details INNER JOIN entry_details ON entry_details.ticket_number = ticket_details.number INNER JOIN entry ON entry_details.entry_id = entry.id WHERE sheet = 'default' """ + ( select_constraint if select_constraint else "") + """ ; """).fetchall() if client_list: per_client_sql_array = []; per_client_sql_array.append(""" COALESCE(ROUND(SUM(entry.duration), 1), 0) AS total """) for client in client_list: per_client_sql_array.append(""" SUM(CASE WHEN project = '%s' THEN entry.duration ELSE 0 END) AS '%s' """ % (client[0], client[0], )) per_client_sql = ", ".join(per_client_sql_array) client_by_day_sql = """ SELECT date, %s FROM ( SELECT ticket_details.project, STRFTIME('%%Y-%%m-%%d', start_time, 'unixepoch', 'localtime') AS date, ROUND(SUM((COALESCE(end_time, STRFTIME('%%s', 'now')) - start_time)/ CAST(3600 AS FLOAT)), 1) as duration FROM entry LEFT JOIN entry_details ON entry_details.entry_id = entry.id LEFT JOIN ticket_details ON entry_details.ticket_number = ticket_details.number WHERE sheet = 'default' """ + (select_constraint.replace("%", "%%") if select_constraint else '') + """ GROUP BY STRFTIME('%%Y-%%m-%%d', start_time, 'unixepoch', 'localtime'), ticket_details.project ) AS entry GROUP BY date ORDER BY date """; client_by_day_sql = client_by_day_sql % per_client_sql client_by_day = cursor.execute(client_by_day_sql).fetchall() client_by_day_json_arr = []; prev_date = False for c in client_by_day: logging.info(c) this_date = c[0] while prev_date and prev_date != (datetime.datetime.strptime(this_date, "%Y-%m-%d") - datetime.timedelta(days = 1)).strftime("%Y-%m-%d"): prev_date_object = (datetime.datetime.strptime(prev_date, "%Y-%m-%d") + datetime.timedelta(days = 1)) prev_date = prev_date_object.strftime("%Y-%m-%d") if 0 < int(datetime.datetime.strptime(prev_date, "%Y-%m-%d").strftime("%w")) < 6: if not date_is_untracked(cursor, prev_date_object.year, prev_date_object.month, prev_date_object.day): day_arr = [prev_date] day_arr.append(0) for client in client_list: day_arr.append(0) client_by_day_json_arr.append(json.dumps(day_arr)) client_by_day_json_arr.append(json.dumps(c)) prev_date = c[0] else: client_by_day_json_arr = [] return render_template("dailygraph.html", billable_data = billable_by_day, all_client_list = all_client_list, client_list = client_list, client_by_day = client_by_day_json_arr, start = start, end = end, project = project )
def billable(cursor, config): start = request.args.get( 'start', (datetime.datetime.now() - datetime.timedelta(days=30)).strftime("%Y-%m-%d")) end = request.args.get('end', datetime.datetime.now().strftime("%Y-%m-%d")) project = request.args.getlist('project') select_constraint = '' if start: select_constraint = select_constraint + " AND start_time > STRFTIME('%%s', '%s', 'utc') " % start if end: select_constraint = select_constraint + " AND start_time < STRFTIME('%%s', '%s', 'utc', '1 day') " % end if project: project_constraints = [] for p in project: project_constraints.append(" project = '%s' " % p) project_constraint = " OR ".join(project_constraints) select_constraint = select_constraint + " AND ( %s ) " % project_constraint logger.info(select_constraint) billable_by_day_sql = """ SELECT date, ROUND(SUM(CASE WHEN entry.billable = 1 THEN entry.duration ELSE 0 END) / CAST(SUM(entry.duration) AS FLOAT) * 100, 1) FROM ( SELECT billable, STRFTIME('%Y-%m-%d', start_time, 'unixepoch', 'localtime') AS date, end_time - start_time as duration FROM entry INNER JOIN entry_details ON entry_details.entry_id = entry.id LEFT JOIN ticket_details ON entry_details.ticket_number = ticket_details.number WHERE sheet = 'default' """ + (select_constraint if select_constraint else "") + """ ) AS entry GROUP BY date ORDER BY date """ billable_by_day_raw = cursor.execute(billable_by_day_sql).fetchall() billable_by_day = [] prev_date = False for row in billable_by_day_raw: this_date = row[0] while prev_date and prev_date != ( datetime.datetime.strptime(this_date, "%Y-%m-%d") - datetime.timedelta(days=1)).strftime("%Y-%m-%d"): prev_date_object = ( datetime.datetime.strptime(prev_date, "%Y-%m-%d") + datetime.timedelta(days=1)) prev_date = prev_date_object.strftime("%Y-%m-%d") if 0 < int( datetime.datetime.strptime(prev_date, "%Y-%m-%d").strftime("%w")) < 6: if not date_is_untracked(cursor, prev_date_object.year, prev_date_object.month, prev_date_object.day): billable_by_day.append([prev_date, 0]) billable_by_day.append(row) prev_date = row[0] all_client_list = cursor.execute(""" SELECT distinct project FROM ticket_details """).fetchall() client_list = cursor.execute(""" SELECT distinct project FROM ticket_details INNER JOIN entry_details ON entry_details.ticket_number = ticket_details.number INNER JOIN entry ON entry_details.entry_id = entry.id WHERE sheet = 'default' """ + ( select_constraint if select_constraint else "") + """ ; """).fetchall() if client_list: per_client_sql_array = [] per_client_sql_array.append(""" COALESCE(ROUND(SUM(entry.duration), 1), 0) AS total """) for client in client_list: per_client_sql_array.append(""" SUM(CASE WHEN project = '%s' THEN entry.duration ELSE 0 END) AS '%s' """ % ( client[0], client[0], )) per_client_sql = ", ".join(per_client_sql_array) client_by_day_sql = """ SELECT date, %s FROM ( SELECT ticket_details.project, STRFTIME('%%Y-%%m-%%d', start_time, 'unixepoch', 'localtime') AS date, ROUND(SUM((COALESCE(end_time, STRFTIME('%%s', 'now')) - start_time)/ CAST(3600 AS FLOAT)), 1) as duration FROM entry LEFT JOIN entry_details ON entry_details.entry_id = entry.id LEFT JOIN ticket_details ON entry_details.ticket_number = ticket_details.number WHERE sheet = 'default' """ + (select_constraint.replace( "%", "%%") if select_constraint else '') + """ GROUP BY STRFTIME('%%Y-%%m-%%d', start_time, 'unixepoch', 'localtime'), ticket_details.project ) AS entry GROUP BY date ORDER BY date """ client_by_day_sql = client_by_day_sql % per_client_sql client_by_day = cursor.execute(client_by_day_sql).fetchall() client_by_day_json_arr = [] prev_date = False for c in client_by_day: logging.info(c) this_date = c[0] while prev_date and prev_date != ( datetime.datetime.strptime(this_date, "%Y-%m-%d") - datetime.timedelta(days=1)).strftime("%Y-%m-%d"): prev_date_object = ( datetime.datetime.strptime(prev_date, "%Y-%m-%d") + datetime.timedelta(days=1)) prev_date = prev_date_object.strftime("%Y-%m-%d") if 0 < int( datetime.datetime.strptime( prev_date, "%Y-%m-%d").strftime("%w")) < 6: if not date_is_untracked(cursor, prev_date_object.year, prev_date_object.month, prev_date_object.day): day_arr = [prev_date] day_arr.append(0) for client in client_list: day_arr.append(0) client_by_day_json_arr.append(json.dumps(day_arr)) client_by_day_json_arr.append(json.dumps(c)) prev_date = c[0] else: client_by_day_json_arr = [] return render_template("dailygraph.html", billable_data=billable_by_day, all_client_list=all_client_list, client_list=client_list, client_by_day=client_by_day_json_arr, start=start, end=end, project=project)