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())
Exemple #2
0
    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())
Exemple #3
0
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)
Exemple #4
0
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
            )
Exemple #6
0
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)