Mercurial > getan
view contrib/zeiterfassung @ 100:8f433e3c2f21
Allow to pass entries to the DeleteEntryState
By default DeleteEntryState uses the selected entries if no entry is passes
to the constructor. This allows to reuse the state class for single entry
deletion
author | Björn Ricks <bjoern.ricks@intevation.de> |
---|---|
date | Mon, 12 Sep 2011 14:05:34 +0200 |
parents | 4b58763e75c1 |
children | e7548b8c6dcc |
line wrap: on
line source
#!/usr/bin/env python # -*- coding: utf-8 -*- # # zeiterfassung # ------------- # (c) 2008 by Sascha L. Teichmann <sascha.teichmann@intevation.de> # # Simple script which generates lines for zeiterfassung.txt files. # # This is Free Software licensed under the terms of GPLv3 or later. # For details see LICENSE coming with the source of 'getan'. # import os import os.path import sys import getopt import re import codecs from pysqlite2 import dbapi2 as db from datetime import date DEFAULT_DATABASE = "time.db" TYPE_OF_ENTRY = "?" WORKPACKAGE = re.compile("^\[(\w*)(\s|\])") USAGE = '''usage: %s <options> with <options> [--user=|-u <user>] : Name of user, default: $USER [--database=|-d <database>]: getan database, default: time.db [--project=|-p <key>] : Key of output project, default: all [--encoding=|-e encoding] : encoding of output, default: none [--week=]|-w <week>] : week of year [--year=]|-y <year>] : year [--list|-l] : list all projects [--help|-h] : This text [--emtpy|-m] : show empty projects''' LIST_PROJECTS = ''' SELECT key, description, active FROM projects ''' PROJECT_ID_BY_KEY = ''' SELECT id, description FROM projects where key = :key ''' ALL_PROJECT_IDS = ''' SELECT id, key, description FROM projects ''' WEEK_ENTRIES = ''' SELECT date(start_time) AS t, sum(strftime('%s', stop_time) - strftime('%s', start_time)), 'no description' AS description FROM entries WHERE project_id = :project_id AND (strftime('%Y', start_time) ) = :year AND (description IS NULL or length(description) = 0) -- trim() function is missing AND (strftime('%W', start_time) = :week OR strftime('%W', stop_time) = :week) GROUP BY round(julianday(start_time)) UNION SELECT date(start_time) AS s, strftime('%s', stop_time) - strftime('%s', start_time), description FROM entries WHERE project_id = :project_id AND (strftime('%Y', start_time) ) = :year AND description IS NOT NULL AND length(description) > 0 AND (strftime('%W', start_time) = :week OR strftime('%W', stop_time) = :week) ORDER BY t ''' ENTRIES = ''' SELECT date(start_time), sum(strftime('%s', stop_time) - strftime('%s', start_time)), 'no description' AS description FROM entries WHERE project_id = :project_id AND (description IS NULL or length(description) = 0) -- trim() function is missing GROUP BY round(julianday(start_time)) UNION SELECT date(start_time), strftime('%s', stop_time) - strftime('%s', start_time), description FROM entries WHERE project_id = :project_id AND description IS NOT NULL AND length(description) > 0 ''' ENTRIES_YEAR = ''' SELECT date(start_time), sum(strftime('%s', stop_time) - strftime('%s', start_time)), 'no description' AS description FROM entries WHERE project_id = :project_id AND (description IS NULL or length(description) = 0) -- trim() function is missing GROUP BY round(julianday(start_time)) UNION SELECT date(start_time), strftime('%s', stop_time) - strftime('%s', start_time), description FROM entries WHERE project_id = :project_id AND (strftime('%Y', start_time) ) = :year AND description IS NOT NULL AND length(description) > 0 ''' def human_time(s): h = s / 3600 m = (s % 3600) / 60 if (s % 60) >= 30: m += 1 if m == 60: m = 0 h += 1 return "%2d:%02d" % (h, m) class TermError(Exception): def __init__(self, msg): Exception.__init__(self) self.msg = msg def __str__(self): return repr(self.msg) def tolerantClose(c): if c: try: c.close() except: pass def usage(exit_code = 0): print USAGE % sys.argv[0] sys.exit(exit_code) def main(): database = DEFAULT_DATABASE user = None list_projects = False project = None encoding = None week = None year = None empty_proj = False opts, args = getopt.getopt( sys.argv[1:], 'd:u:p:e:hl:w:y:m', ['database=', 'user=', 'project=', 'encoding=', 'help', 'list', 'week=', 'year=', 'empty']) for opt, val in opts: if opt in ("--database", "-d"): database = val elif opt in ("--user", "-u"): user = val elif opt in ("--project", "-p"): project = val elif opt in ("--encoding", "-e"): encoding = val elif opt in ("--help", "-h"): usage() elif opt in ("--list", "-l"): list_projects = True elif opt in ("--week", "-w"): week = val elif opt in ("--year", "-y"): year = val elif opt in ("--empty", "-m"): empty_proj = True if not user: user = os.getenv("USER") proj_year = year if not proj_year: proj_year = date.today().strftime("%Y") if encoding: Writer = codecs.getwriter(encoding) sys.stdout = Writer(sys.stdout) if not os.path.isfile(database): print >> sys.stderr, "'%s' does not exist or is not a file." % database sys.exit(1) con, cur = None, None try: try: con = db.connect(database) if encoding: con.text_factory = lambda s: s.decode(encoding) cur = con.cursor() if list_projects: cur.execute(LIST_PROJECTS) while True: row = cur.fetchone() if not row: break print "%s %s %s" % (row[0], row[2] and "*" or "-", row[1]) else: if project: cur.execute(PROJECT_ID_BY_KEY, { 'key': project }) row = cur.fetchone() if row is None: raise TermError("There is no project with key '%s'" % project) project_ids = [[row[0], project, row[1]]] else: cur.execute(ALL_PROJECT_IDS); project_ids = cur.fetchall() total = 0 for project_id, project, proj_desc in project_ids: if not week is None: cur.execute(WEEK_ENTRIES, {'project_id': project_id, 'week': week, 'year' : proj_year}) elif not year: cur.execute(ENTRIES, {'project_id': project_id}) else: cur.execute(ENTRIES_YEAR, {'project_id': project_id, 'year':proj_year}) total_proj = 0 row = cur.fetchone() if row or empty_proj: print "# project: %s (%s)" % (project, proj_desc) while row: d = date(*map(int, row[0].split('-'))) t = max(60, row[1]) c = row[2] total_proj += t workpackage = "----" if c: m = WORKPACKAGE.match(c) if m: workpackage = m.group(1) c = c[m.end():].strip() c = c.replace('\x1b', '') print "%s %sh %s %-3s [%s] %s" % ( d.strftime("%d.%m.%Y"), human_time(t), TYPE_OF_ENTRY, user, workpackage, c) row = cur.fetchone() total += total_proj if empty_proj or total_proj > 0: print "# total: %sh\n\n" % human_time(total_proj) print "# total all projects: %sh\n\n" % human_time(total) finally: tolerantClose(cur) tolerantClose(con) except TermError, e: print >> sys.stderr, "error: %s" % e.msg if __name__ == '__main__': main() # vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: