Example #1
0
File: app.py Project: gyhor/redmein
def time_entry_list(from_date, to_date, user, redmine):
    print("Fetching time entries from {} to {} for {}...".format(
        from_date, to_date, user))
    print()

    # Get yesterday's time entries
    time_entries = redmine.time_entry.filter(user_id=user.id,
                                             from_date=from_date,
                                             to_date=to_date,
                                             sort='hours:desc')

    if time_entries:
        sum = 0

        # Print scrum update template
        report = "Time entries:\n"

        for entry in time_entries:
            report += helpers.entry_bullet_point(entry)
            sum += entry.hours

        report += "\n" + str(sum) + " hours.\n"
    else:
        report = "No time entries.\n"

    print(report)
Example #2
0
def update_entry(args, config, app_data):
    changed = False

    # Need to use cached time entry data because API doesn't support getting time entry data by ID
    cached_entry = app_data['clockify'].cache.get_cached_entry(args.id)

    if not cached_entry:
        print('Time entry does not exist or is not cached.')
        return

    # Establish entry hours
    cached_hours = app_data['clockify'].cache.iso_duration_to_hours(cached_entry['timeInterval']['duration'])
    updated_hours = cached_hours

    # Adjust hours, if necessary
    if args.hours and (helpers.contains_calculation(args.hours) or cached_hours != float(args.hours)):
        changed = True
        updated_hours = helpers.handle_hours_calculation_value(float(cached_hours), args.hours)
        print("Changing hours from {} to: {}".format(str(cached_hours), str(updated_hours)))

    updated_entry = app_data['clockify'].cache.generate_update_entry(args.id, comments=args.comments, date=args.date, hours=updated_hours)

    # Update description, if necessary
    if args.comments and args.comments != cached_entry['description']:
        changed = True
        print("Changing comments to: {}".format(args.comments))

    # Append to description, if necesary
    if args.append:
        changed = True
        updated_entry['description'] += ' ' + args.append
        print("Appended to comments: {}".format(args.append))

    # Update start date, if necessary
    if args.date:
        cached_date_local = app_data['clockify'].utc_iso_8601_string_to_local_datetime(cached_entry['timeInterval']['start'])
        update_date_local = app_data['clockify'].utc_iso_8601_string_to_local_datetime(updated_entry['start'])

        if cached_date_local.date() != update_date_local.date():
            changed = True
            print("Changing date to {}".format(args.date))

    if changed:
        # Perform update via API
        response = app_data['clockify'].update_entry(updated_entry, cached_entry)

        if response.status_code == 200:
            print(helpers.entry_bullet_point(app_data['clockify'], cached_entry))
            print('Time entry updated.')
        else:
            response_data = response.json()
            print('Unexpected response status code: ' + str(response.status_code))
            if 'message' in response_data:
                print('Message: ' + response_data['message'])
    else:
        print('No update as no change requested.')
Example #3
0
def update_entry(args, config, app_data):
    if args.id:
        changed = False

        try:
            entry = app_data['redmine'].time_entry.get(args.id)
            if entry.user.id != app_data['user'].id:
                print("Entry was created by {}. Update skipped.".format(
                    str(entry.user)))
                return
        except redminelib.exceptions.ResourceNotFoundError:
            print("Entry not found.")
            return

        print(helpers.entry_bullet_point(entry))

        if args.comments and entry.comments != args.comments:
            changed = True
            entry.comments = args.comments
            print('Changing comments to: ' + args.comments)

        if args.hours and (args.hours[:1] == '+' or args.hours[:1] == '-'
                           or entry.hours != float(args.hours)):
            changed = True
            original_hours = entry.hours

            if args.hours[:1] == '+':
                entry.hours += float(args.hours[1:])
            elif args.hours[:1] == '-':
                entry.hours -= float(args.hours[1:])
            else:
                entry.hours = float(args.hours)
            print('Changing hours from ' + str(original_hours) + ' to: ' +
                  str(entry.hours))

        if args.date:
            changed = True
            original_date = entry.spent_on
            entry.spent_on = helpers.handle_date_calculation_value(args.date)
            print('Changing activies from ' + str(original_date) + ' to ' +
                  str(entry.spent_on))

        # share code with new_entry?
        if args.activity:
            changed = True
            original_activity = str(entry.activity)
            entry.activity_id = app_data['activities'][args.activity]
            print('Changing activity from ' + original_activity + ' to ' +
                  args.activity)

        if changed:
            entry.save()

    else:
        print("Specify a time entry ID using the --id option.")
Example #4
0
def new_entry(args, config, app_data):
    if 'hours' not in args or not args.hours:
        print('Specifiy hours.')
        return

    entry = app_data['clockify'].create_entry(args.id, args.comments,
                                              args.hours, args.date)

    if 'message' in entry and 'code' in entry:
        print(entry['message'])
        return

    print(helpers.entry_bullet_point(entry))

    print("Time entry created.")
Example #5
0
def new_entry(args, config, app_data):
    if 'hours' not in args or not args.hours:
        print('Specifiy hours.')
        return

    # Check if ID indicates a task rather than project
    task_id = None
    project_id = app_data['clockify'].get_task_project_id(args.id)

    if project_id is None:
        project_id = args.id
    else:
        task_id = args.id

    entry = app_data['clockify'].create_entry(project_id, args.comments, args.hours, args.date, args.start, task=task_id)

    if 'message' in entry and 'code' in entry:
        print(entry['message'])
        return

    print(helpers.entry_bullet_point(app_data['clockify'], entry))
    print("Time entry created.")
Example #6
0
def new_entry(args, config, app_data):
    if args.id:
        # Warn user is issue isn't assigned or is assigned to another user
        issue = app_data['redmine'].issue.get(args.id)
        if not hasattr(issue, 'assigned_to'):
            print("*** Note: Issue is unassigned. ***\n")
        elif issue.assigned_to.id != app_data['user'].id:
            print("*** Note: Issue is not assigned to you. ***\n")

        entry = app_data['redmine'].time_entry.new()
        entry.issue_id = args.id
        entry.spent_on = date.today()

        if args.date:
            entry.spent_on = datetime.strptime(
                helpers.handle_date_calculation_value(args.date),
                '%Y-%m-%d').date()

        if args.comments:
            entry.comments = args.comments

        if args.hours:
            entry.hours = args.hours

        if not args.activity and 'default activity' in config:
            args.activity = helpers.resolve_activity_alias(
                config['default activity'], config['activities'])

        if args.activity:
            entry.activity_id = app_data['activities'][args.activity]

        entry.save()

        print(helpers.entry_bullet_point(entry))

        print("Time entry created.")

    else:
        print("Specify an issue ID using the --id option.")
Example #7
0
def update_entry(args, config, app_data):
    changed = False

    # Need to use cached time entry data because API doesn't support getting time entry data by ID
    cached_entry = helpers.get_cached_entry(args.id)

    if not cached_entry:
        print('Time entry does not exist or is not cached.')
        return

    # Change TimeEntrySummaryDto to work as UpdateTimeEntryRequest format (see Clockify API documentation)
    entry = {}
    entry['id'] = cached_entry['id']
    entry['description'] = cached_entry['description']
    entry['start'] = cached_entry['timeInterval']['start']
    entry['end'] = cached_entry['timeInterval']['end']
    entry['projectId'] = cached_entry['project']['id']
    entry['billable'] = cached_entry['billable']
    entry['tagIds'] = []

    if 'task' in cached_entry and cached_entry['task']:
        entry['taskId'] = cached_entry['task']['id']

    if 'tags' in cached_entry and cached_entry['tags']:
        for tag in cached_entry['tags']:
            entry['tagIds'].append(tag['id'])

    # Update description, if necessary
    if args.comments and args.comments != entry['description']:
        changed = True

        entry['description'] = args.comments
        cached_entry['description'] = args.comments
        print('Changing comments to: ' + args.comments)

    # Establish entry hours
    current_hours = helpers.iso_duration_to_hours(
        cached_entry['timeInterval']['duration'])

    if args.hours and (args.hours[:1] == '+' or args.hours[:1] == '-'
                       or current_hours != float(args.hours)):
        changed = True

        original_hours = current_hours

        if args.hours[:1] == '+':
            current_hours += float(args.hours[1:])
        elif args.hours[:1] == '-':
            current_hours -= float(args.hours[1:])
        else:
            current_hours = float(args.hours)

        print('Changing hours from ' + str(original_hours) + ' to: ' +
              str(current_hours))

    # Change UTC start date/time, if necessary
    if args.date:
        # Convert entry date to simple sting in local timezone
        original_date_localized = dateutil.parser.parse(
            entry['start']).astimezone(app_data['clockify'].tz)
        original_date = original_date_localized.strftime('%Y-%m-%d')

        if original_date != args.date:
            changed = True

            # Convert new date to UTC ISO 8601
            entry['start'] = app_data[
                'clockify'].local_date_string_to_utc_iso_8601(args.date)
            cached_entry['timeInterval']['start'] = entry['start']

            print('Changing activies from ' + original_date + ' to ' +
                  args.date)

    # Convert UTC start/time to localized datetime and use it to calculate ISO 8601 end date/time
    start_datetime = dateutil.parser.parse(entry['start'])
    entry['end'] = app_data[
        'clockify'].add_hours_to_localized_datetime_and_convert_to_iso_8601(
            start_datetime, current_hours)

    cached_entry['timeInterval']['duration'] = isodate.duration_isoformat(
        dateutil.parser.parse(entry['end']) -
        dateutil.parser.parse(entry['start']))
    cached_entry['timeInterval']['end'] = entry['end']

    if changed:
        # Perform update via API
        response = app_data['clockify'].update_entry(entry)

        if response.status_code == 200:
            helpers.write_cache_entry(cached_entry)
            print(helpers.entry_bullet_point(cached_entry))
            print('Time entry updated.')
        else:
            response_data = response.json()
            print('Unexpected response status code: ' +
                  str(response.status_code))
            if 'message' in response_data:
                print('Message: ' + response_data['message'])
    else:
        print('No update as no change requested.')