Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • stamper/stamper.py

    r0 r9  
    11
    22import json
     3import re
    34from datetime import datetime, timedelta
    45from os.path import expanduser, exists
     6
    57
    68STAMPS_FILE = expanduser('~/.workstamps.json')
     
    4951        return worktime.seconds
    5052
     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
    5187    def customers(self):
    5288        customers = []
     
    5793        return customers
    5894
    59     def total_by_customer(self, customer):
    60         total = 0
     95    def totals(self, stamp_filter=None):
     96        totals = {}
    6197        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)
     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'])
     104        return totals
    66105
    67     def totals(self):
     106    def details(self):
     107        details = {}
    68108        totals = {}
    69         for customer in self.customers():
    70             totals[customer] = self.total_by_customer(customer)
    71         return 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
    72128
    73129    def details_by_customer(self, customer):
     
    92148            totals[day] = str(timedelta(seconds=totals[day]))
    93149        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.