Exemple #1
0
 def daily_report_timeline(self, output, email, who):
     """Format a daily report with your timeline entries."""
     # Locale is set as a side effect of 'import gtk', so strftime('%a')
     # would give us translated names
     weekday_names = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
     weekday = weekday_names[self.min_timestamp.weekday()]
     week = self.min_timestamp.strftime('%V')
     print(("%(date)s report for %(who)s"
            " (%(weekday)s, week %(week)s)"
            % {'date': self.min_timestamp.strftime('%Y-%m-%d'),
               'weekday': weekday, 'week': week, 'who': who}), file=output)
     print(file=output)
     items = list(self.all_entries())
     if not items:
         print("No work done today.", file=output)
         return
     start, stop, duration, entry = items[0]
     for start, stop, duration, entry in items[1:]:
         print("%s - %s (%3s): %s" % (
             start.strftime('%H:%M'), stop.strftime('%H:%M'),
             duration.seconds // 60, entry), file=output)
     now = datetime.datetime.now()
     if stop.date() == now.date():
         print("%s - %s (%3d): **current task**" % (
             stop.strftime('%H:%M'), now.strftime('%H:%M'),
             (now - stop).seconds / 60), file=output)
     print(file=output)
     work, slack, hold = self.grouped_entries()
     total_work, total_slacking, total_holidays = self.totals()
     print(("Total work done today:       %s" %
            format_duration_long(total_work)), file=output)
Exemple #2
0
    def daily_report(self, output, email, who):
        """Format a daily report.

        Writes a daily report template in RFC-822 format to output.
        """
        # Locale is set as a side effect of 'import gtk', so strftime('%a')
        # would give us translated names
        weekday_names = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        weekday = weekday_names[self.min_timestamp.weekday()]
        week = self.min_timestamp.strftime('%V')
        print >> output, "To: %(email)s" % {'email': email}
        print >> output, ("Subject: %(date)s report for %(who)s"
                          " (%(weekday)s, week %(week)s)" % {
                              'date': self.min_timestamp.strftime('%Y-%m-%d'),
                              'weekday': weekday,
                              'week': week,
                              'who': who
                          })
        print >> output
        items = list(self.all_entries())
        if not items:
            print >> output, "No work done today."
            return
        start, stop, duration, entry = items[0]
        entry = entry[:1].upper() + entry[1:]
        print >> output, "%s at %s" % (entry, start.strftime('%H:%M'))
        print >> output
        work, slack, hold = self.grouped_entries()
        total_work, total_slacking, total_holidays = self.totals()
        if work:
            for start, entry, duration in work:
                entry = entry[:1].upper() + entry[1:]
                print >> output, "%-62s  %s" % (entry,
                                                format_duration_long(duration))
            print >> output
        print >> output, ("Total work done: %s" %
                          format_duration_long(total_work))
        print >> output
        if slack:
            for start, entry, duration in slack:
                entry = entry[:1].upper() + entry[1:]
                print >> output, "%-62s  %s" % (entry,
                                                format_duration_long(duration))
            print >> output
        print >> output, ("Time spent slacking: %s" %
                          format_duration_long(total_slacking))
Exemple #3
0
    def weekly_report(self, output, email, who, estimated_column=False):
        """Format a weekly report.

        Writes a weekly report template in RFC-822 format to output.
        """
        week = self.min_timestamp.strftime('%V')
        print("To: %(email)s" % {'email': email}, file=output)
        print("Subject: Weekly report for %s (week %s)" % (who,
                                                           week), file=output)
        print(file=output)
        items = list(self.all_entries())
        if not items:
            print("No work done this week.", file=output)
            return
        print(" " * 46, end=' ', file=output)
        if estimated_column:
            print("estimated       actual", file=output)
        else:
            print("                time", file=output)
        work, slack, hold = self.grouped_entries()
        total_work, total_slacking, total_holidays = self.totals()
        if work:
            work = [(entry, duration) for start, entry, duration in work]
            work.sort()
            for entry, duration in work:
                if not duration:
                    continue  # skip empty "arrival" entries
                entry = entry[:1].upper() + entry[1:]
                if estimated_column:
                    print(("%-46s  %-14s  %s" %
                           (entry, '-',
                            format_duration_long(duration))), file=output)
                else:
                    print(("%-62s  %s" %
                           (entry, format_duration_long(duration))),
                          file=output)
            print(file=output)
        print(("Total work done this week: %s" %
               format_duration_long(total_work)), file=output)
Exemple #4
0
 def test_format_duration_long(self):
     self.assertEqual(' 0 min', format_duration_long(timedelta(0)))
     self.assertEqual(' 1 min', format_duration_long(timedelta(minutes=1)))
     self.assertEqual(' 1 hour ',
                      format_duration_long(timedelta(minutes=60)))
     self.assertEqual(' 1 hour   5 min',
                      format_duration_long(timedelta(minutes=65)))
     self.assertEqual(' 2 hours', format_duration_long(timedelta(hours=2)))
     self.assertEqual(' 2 hours  1 min',
                      format_duration_long(timedelta(hours=2, minutes=1)))
     self.assertEqual('12 hours 32 min',
                      format_duration_long(timedelta(hours=12, minutes=32)))
Exemple #5
0
def main():
    global Colors
    """Run the program."""
    Colors = WithoutColors
    if curses:
        try:
            curses.setupterm()
            curses.initscr()
            if curses.can_change_color():
                Colors = WithColors
            curses.endwin()
        except curses.error:
            Colors = WithoutColors

    # Argument parsing
    parser = argparse.ArgumentParser(
        description=u'Show the progress of the current week')
    parser.add_argument(
        '--day',
        metavar='YYYY-MM-DD',
        default=datetime.today().strftime('%Y-%m-%d'),
        help='Day of the week the progress should be calculated for. '
        '(default: today)')
    args = parser.parse_args()

    # Load config
    settings, timelog = gocept.gtimelog.cli.load_config_and_timelog()

    # Calculate the progress
    today = datetime.strptime(args.day, '%Y-%m-%d')
    monday = today - timedelta(today.weekday())
    sunday = monday + timedelta(7)

    week_done, week_exp, week_todo = gocept.gtimelog.util.calc_progress(
        settings, timelog, (monday, sunday))

    today_window = timelog.window_for(today, today + timedelta(1))
    today_window.daily_report_timeline(sys.stdout, settings.email,
                                       settings.name)

    total_work, total_slacking, total_holidays = (timelog.window_for(
        monday, sunday).totals())

    print("Total work done this week:   {colors.RED}{total_work}{colors.BLACK}"
          " of {colors.RED}{expected} hours{colors.BLACK}".format(
              colors=Colors,
              total_work=format_duration_long(total_work),
              expected=int(week_exp)))

    first_of_month = datetime(today.year, today.month, 1)
    next_month = today.replace(day=28) + timedelta(days=4)
    last_of_month = next_month - timedelta(days=next_month.day)
    total_customer, total_intern, total_slacking, total_holidays = (
        timelog.window_for(first_of_month, last_of_month).totals(True))
    total_work = total_customer + total_intern

    if total_work.total_seconds():
        total_percent = (total_customer.total_seconds() * 100.0 /
                         total_work.total_seconds())
    else:
        total_percent = 0
    expected = progress_expected = 0
    engagement = settings.engagement
    if engagement:
        expected = engagement[today.month - 1]
        progress_expected = int(
            get_businessdays_until_now(holidays=settings.holidays) *
            settings.hours)

    print("Total work done this month: {colors.RED}{total_work} "
          "({total_percent} %){colors.BLACK} of "
          "{colors.RED}{progress_expected}"
          " ({expected}) hours{colors.BLACK}".format(
              colors=Colors,
              progress_expected=progress_expected,
              expected=expected,
              total_work=format_duration_long(total_work),
              total_percent=round(total_percent, 1)))

    first_of_year = datetime(today.year, 1, 1)
    last_of_year = datetime(today.year, 12, 31)
    total_customer, total_intern, total_slacking, total_holidays = (
        timelog.window_for(first_of_year, last_of_year).totals(True))
    total_work = total_customer + total_intern

    total_percent = (total_customer.total_seconds() * 100.0 /
                     total_work.total_seconds())
    progress_engagement = 0
    now = datetime.now()
    for i in range(1, now.month + 1):
        if i < now.month:
            progress_engagement += settings.engagement[i - 1]
        else:
            progress_engagement += int(
                get_businessdays_until_now(holidays=settings.holidays) *
                settings.hours)
    engagement = sum(settings.engagement)

    print("Total work done this year:  {colors.RED}{total_work} "
          "({total_percent} %){colors.BLACK} of {colors.RED}{progress} "
          "({expected}) hours{colors.BLACK}".format(
              colors=Colors,
              progress=progress_engagement,
              expected=engagement,
              total_work=format_duration_long(total_work),
              total_percent=round(total_percent, 1)))

    print("Overtime this year:          {colors.RED}{overtime}".format(
        colors=Colors,
        overtime=format_duration_long(total_work -
                                      timedelta(hours=progress_engagement))))

    if not today_window.items:
        return
    d_hours = timedelta(hours=today_window.settings.week_hours / 5.0)
    time_left = d_hours - today_window.totals()[0]
    clock_off = today_window.items[0][0] + d_hours + today_window.totals()[1]
    print("")
    print("Time left at work:           {colors.RED}{time_left}{colors.BLACK}"
          " (until {until})".format(colors=Colors,
                                    time_left=format_duration_long(time_left),
                                    until=clock_off.strftime('%H:%M')))
Exemple #6
0
 def daily_report_timeline(self,
                           output,
                           email,
                           who,
                           summary=False,
                           filter_=None):
     """Format a daily report with your timeline entries."""
     # Locale is set as a side effect of 'import gtk', so strftime('%a')
     # would give us translated names
     weekday_names = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
     weekday = weekday_names[self.min_timestamp.weekday()]
     week = self.min_timestamp.strftime('%V')
     print >> output, ("%(date)s report for %(who)s"
                       " (%(weekday)s, week %(week)s)" % {
                           'date': self.min_timestamp.strftime('%Y-%m-%d'),
                           'weekday': weekday,
                           'week': week,
                           'who': who
                       })
     print >> output
     items = list(self.all_entries(filter_))
     if not items:
         print >> output, "No work done today."
         return
     start, stop, duration, entry = items[0]
     if summary == False:
         for start, stop, duration, entry in items[1:]:
             hours, minutes = self._format_duration(duration)
             print >> output, "%s - %s (%s:%s): %s" % (
                 start.strftime('%H:%M'), stop.strftime('%H:%M'), hours,
                 minutes, entry.encode('utf-8'))
     else:
         combined = {}
         items_ = items if filter_ else items[1:]
         for start, stop, duration, entry in items_:
             if ':' not in entry:
                 continue
             proj, subproj, entry = entry.split(':', 2)
             entry = entry.strip()
             project = '%s:%s' % (proj, subproj)
             if entry.startswith('#'):
                 project += entry.split(' ')[0]
             if project not in combined:
                 combined[project] = []
             combined[project].append((duration, entry))
         for project, items in combined.items():
             duration = datetime.timedelta(0)
             entries = []
             for dur, entr in items:
                 duration += dur
                 entries.append(entr)
             entries = list(set(entries))
             if '#' in project:
                 project = project.split('#')[0]
             entry = project + ': ' + '; '.join(entries)
             hours, minutes = self._format_duration(duration)
             print >> output, "(%s:%s): %s" % (hours, minutes,
                                               entry.encode('utf-8'))
     now = datetime.datetime.now()
     if not filter_ and stop.date() == now.date():
         hours, minutes = self._format_duration(now - stop)
         print >> output, "%s - %s (%s:%s): **current task**" % (
             stop.strftime('%H:%M'), now.strftime('%H:%M'), hours, minutes)
     print >> output
     work, slack, hold = self.grouped_entries()
     total_work, total_slacking, total_holidays = self.totals()
     print >> output, ("Total work done today:       %s" %
                       format_duration_long(total_work))