Changes in / [12:73483c3145ff:11:30241f3a03eb] in stamper


Ignore:
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • bin/stamps

    r10 r3  
    11#!/usr/bin/env python
    22
    3 import argparse
     3import sys
    44from stamper import Stamper
     5
     6
     7def usage(name):
     8    msg = """
     9    Usage:
     10
     11    To gather information of recorded times: %(name)s
     12
     13    Recorded times for a given customer: %(name)s customer
     14
     15    Detailed times for a given customer: %(name)s customer details
     16    """ % {'name': name}
     17    print(msg)
    518
    619
    720if __name__ == '__main__':
    821
    9     parser = argparse.ArgumentParser(
    10         description='stamps: show recorded times information')
    11     parser.add_argument('customer', action="store", nargs='?',
    12                         help='Show times only for this customer')
    13     parser.add_argument('filter', action="store", nargs='?',
    14                         help='Filter the times by date range')
    15     parser.add_argument('-v', '--verbose', action="store_true",
    16                         help='Include detailed times information')
    17 
    18     args = parser.parse_args()
    19 
    2022    s = Stamper()
    2123    s.load_stamps()
    22     s.show_stamps(args.customer, args.filter, args.verbose)
     24
     25    if len(sys.argv) == 1:
     26        totals = s.totals()
     27        print('Total times for all customers:')
     28        for t in totals:
     29            print(' -> %(customer)s: %(total)s' % {'customer': t,
     30                                                   'total': totals[t]})
     31    elif len(sys.argv) == 2:
     32        if sys.argv[1] in s.customers():
     33            print('Total time for %(customer)s: %(total)s' % {
     34                'customer': sys.argv[1],
     35                'total': s.total_by_customer(sys.argv[1])
     36                })
     37
     38    elif len(sys.argv) == 3:
     39        if sys.argv[1] in s.customers():
     40            print('Detailed time for %(customer)s' % {
     41                'customer': sys.argv[1],
     42                })
     43            details, totals = s.details_by_customer(sys.argv[1])
     44            for day in details:
     45                print('------ %(day)s ------' % {'day': day})
     46                for line in details[day]:
     47                    print(line)
     48                print(' Total: %(total)s' % {'total': totals[day]})
     49
     50    else:
     51        usage(sys.argv[0])
     52        sys.exit(1)
  • stamper/stamper.py

    r9 r0  
    11
    22import json
    3 import re
    43from datetime import datetime, timedelta
    54from os.path import expanduser, exists
    6 
    75
    86STAMPS_FILE = expanduser('~/.workstamps.json')
     
    5149        return worktime.seconds
    5250
    53     def validate_filter(self, stamp_filter):
    54         """
    55         Validate a given filter. Filters can have the following notation:
    56 
    57         - %Y-%m-%d--%Y-%m-%d: Times recorded between two dates
    58 
    59         - -%Y-%m-%d: Times recorded before a given date
    60 
    61         - +%Y-%m-%d: Times recorded after a given date
    62 
    63         - N...N[d|w|m|y]: Times recorded N...N days/weeks/months/years ago
    64         """
    65         # First try the date filters, one by one
    66         matches = ['%Y-%m-%d', '-%Y-%m-%d', '+%Y-%m-%d']
    67         for match in matches:
    68             try:
    69                 if '--' in stamp_filter:
    70                     filter_from, filter_to = stamp_filter.split('--')
    71                     filter_from = datetime.strptime(stamp_filter, match)
    72                     filter_to = datetime.strptime(stamp_filter, match)
    73                 else:
    74                     valid_filter = datetime.strptime(stamp_filter, match)
    75             except ValueError:
    76                 pass
    77             else:
    78                 return stamp_filter
    79 
    80         valid_filter = re.search(r'(\d+[dwmyDWMY]{1})', stamp_filter)
    81         if valid_filter:
    82             return stamp_filter
    83 
    84         # Not a valid filter
    85         return None
    86 
    8751    def customers(self):
    8852        customers = []
     
    9357        return customers
    9458
    95     def totals(self, stamp_filter=None):
     59    def total_by_customer(self, customer):
     60        total = 0
     61        for stamp in self.stamps:
     62            if stamp['customer'] == customer:
     63                total += self.worktime(stamp['start'], stamp['end'])
     64        total = timedelta(seconds=total)
     65        return str(total)
     66
     67    def totals(self):
    9668        totals = {}
    97         for stamp in self.stamps:
    98             customer = stamp['customer']
    99             if customer:
    100                 # c will be None for "start" stamps, having no end time
    101                 if customer not in totals:
    102                     totals[customer] = 0
    103                 totals[customer] += self.worktime(stamp['start'], stamp['end'])
     69        for customer in self.customers():
     70            totals[customer] = self.total_by_customer(customer)
    10471        return totals
    105 
    106     def details(self):
    107         details = {}
    108         totals = {}
    109         for stamp in self.stamps:
    110             if stamp['customer']:
    111                 # avoid "start" stamps
    112                 start_day = stamp['start'].split(' ')[0]
    113                 if start_day not in details:
    114                     details[start_day] = []
    115                 if start_day not in totals:
    116                     totals[start_day] = 0
    117                 worktime = self.worktime(stamp['start'], stamp['end'])
    118                 details[start_day].append(
    119                     ' -> %(worktime)s %(customer)s %(action)s' % {
    120                         'worktime': str(timedelta(seconds=worktime)),
    121                         'customer': stamp['customer'],
    122                         'action': stamp['action']
    123                     })
    124                 totals[start_day] += worktime
    125         for day in totals:
    126             totals[day] = str(timedelta(seconds=totals[day]))
    127         return details, totals
    12872
    12973    def details_by_customer(self, customer):
     
    14892            totals[day] = str(timedelta(seconds=totals[day]))
    14993        return details, totals
    150 
    151     def show_stamps(self, customer=None, stamp_filter=None, verbose=False):
    152         if stamp_filter:
    153             stamp_filter = self.validate_filter(stamp_filter)
    154 
    155         totals = self.totals(stamp_filter)
    156 
    157         if customer:
    158             total = timedelta(seconds=totals.get(customer, 0))
    159             print(' %(customer)s: %(total)s' % {'customer': customer,
    160                                                 'total': total})
    161         else:
    162             for c in totals:
    163                 total = timedelta(seconds=totals[c])
    164                 print(' %(customer)s: %(total)s' % {'customer': c,
    165                                                     'total': total})
    166 
    167         if verbose:
    168             if customer:
    169                 details, totals = self.details_by_customer(customer)
    170             else:
    171                 details, totals = self.details()
    172             for day in details:
    173                 print('------ %(day)s ------' % {'day': day})
    174                 for line in details[day]:
    175                     print(line)
    176                 print(' Total: %(total)s' % {'total': totals[day]})
Note: See TracChangeset for help on using the changeset viewer.