db.py
author Eugen Sawin <sawine@me73.com>
Fri, 01 Oct 2010 23:23:26 +0200
changeset 8 42c4c96e3ecd
parent 7 878956edb936
child 9 fab8e1981155
permissions -rw-r--r--
Added pause and resume.
     1 """
     2 Database lib for cronrec.
     3 Author: Eugen Sawin (sawine@me73.com)
     4 Dependencies: libsqlite3-dev
     5 """
     6 
     7 import sqlite3
     8 
     9 ACTIVITIES_TABLE = """activities(
    10 name text not null,
    11 description text)"""
    12 
    13 COMPANIES_TABLE = """companies(
    14 name text not null,
    15 street text,
    16 area text,
    17 town text,
    18 country text,
    19 postal text)"""
    20 
    21 PROJECTS_TABLE = """projects(
    22 name text not null,
    23 number int,
    24 customer int,
    25 constraint customer_fk foreign key(customer) references companies(rowid) on delete
    26 cascade)"""
    27 
    28 RATES_TABLE = """rates(
    29 rate smallmoney
    30 flatrate smallmoney,
    31 project int,
    32 activity int,
    33 constraint project_fk foreign key(project) references projects(rowid) on delete
    34 cascade,
    35 constraint activity_fk foreign key(activity) references activities(rowid) on delete
    36 cascade)"""
    37 
    38 TASKS_TABLE = """tasks(
    39 begin datetime,
    40 end datetime,
    41 project int,
    42 activity int,
    43 log text,
    44 constraint project_fk foreign key(project) references projects(rowid) on delete
    45 cascade,
    46 constraint activity_fk foreign key(activity) references activities(rowid) on delete
    47 cascade)"""
    48 
    49 BREAKS_TABLE = """breaks(
    50 begin datetime,
    51 end datetime,
    52 task int,
    53 log text,
    54 constraint task_fk foreign key(task) references tasks(rowid) on delete
    55 cascade)"""
    56 
    57 TABLES = (ACTIVITIES_TABLE, COMPANIES_TABLE, PROJECTS_TABLE, RATES_TABLE,
    58 TASKS_TABLE, BREAKS_TABLE)
    59 
    60 DEF_PROJECT = "default"
    61 DEF_ACTIVITY = "default"
    62 
    63 def session(db_file):
    64 	con = sqlite3.connect(db_file)
    65 	return con, con.cursor()
    66 
    67 def test(db_file):
    68 	con, cur = session(db_file)
    69 	cur.execute("select * from projects")
    70 	print "\nprojects"
    71 	for c in cur:
    72 		print c
    73 	cur.execute("select * from activities")
    74 	print "\nactivities"
    75 	for c in cur:
    76 		print c
    77 	cur.execute("select * from tasks")
    78 	print "\ntasks"
    79 	for c in cur:
    80 		print c
    81 	cur.execute("select * from breaks")
    82 	print "\nbreaks"
    83 	for c in cur:
    84 		print c
    85 	con.commit()
    86 	cur.close()
    87 
    88 def init(db_file):
    89 	con, cur = session(db_file)
    90 	for table in TABLES:
    91 		sql = "create table " + table
    92 		cur.execute(sql)
    93 	con.commit()
    94 	cur.close()
    95 
    96 def find_last_project(db_file, time):
    97 	con, cur = session(db_file)
    98 	values = (time,)
    99 	sql = "select project from tasks where begin < ? and end is null order by \
   100 begin desc"
   101 	cur.execute(sql, values)
   102 	id = cur.fetchone()
   103 	if id:
   104 		values = (id[0],)
   105 		sql = "select name from projects where rowid=?"
   106 		cur.execute(sql, values)
   107 		project = cur.fetchone()[0]
   108 	else:
   109 		project = None#DEF_PROJECT
   110 	con.commit()
   111 	cur.close()
   112 	return project
   113 
   114 def find_last_activity(db_file, time):
   115 	con, cur = session(db_file)
   116 	values = (time,)
   117 	sql = "select activity from tasks where begin < ? and end is null order by \
   118 begin desc"
   119 	cur.execute(sql, values)
   120 	id = cur.fetchone()
   121 	if id:
   122 		values = (id[0],)
   123 		sql = "select name from activities where rowid=?"
   124 		cur.execute(sql, values)
   125 		activity = cur.fetchone()[0]
   126 	else:
   127 		activity = None#DEF_ACTIVITY
   128 	con.commit()
   129 	cur.close()
   130 	return activity
   131 
   132 def find_active_task(db_file):
   133 	con, cur = session(db_file)
   134 	sql = "select project, activity from tasks where end is null"
   135 	cur.execute(sql)	
   136 	task = cur.fetchone()
   137 	if task:
   138 		task = task[0]	
   139 	cur.close()
   140 	return task			
   141 
   142 def id_name(db_file, table, id):
   143 	con, cur = session(db_file)
   144 	values = (id,)
   145 	sql = "select name from %s where rowid=?" % table
   146 	cur.execute(sql, values)
   147 	id = cur.fetchone()
   148 	cur.close()
   149 	return id[0]
   150 
   151 def row_id(db_file, table, name):
   152 	con, cur = session(db_file)
   153 	values = (name,)
   154 	sql = "select rowid from %s where name=?" % table
   155 	cur.execute(sql, values)
   156 	id = cur.fetchone()
   157 	if not id:
   158 		sql = "insert into %s(name) values(?)" % table
   159 		cur.execute(sql, values)
   160 		con.commit()
   161 		cur.close()
   162 		return row_id(db_file, table, name)
   163 	con.commit()
   164 	cur.close()
   165 	return id[0]
   166 
   167 def project_id(db_file, name):
   168 	return row_id(db_file, "projects", name)
   169 
   170 def activity_id(db_file, name):
   171 	return row_id(db_file, "activities", name)
   172 
   173 def end(db_file, project, activity, time):
   174 	print "ending: %s:%s" % (project, activity)
   175 	if activity or project:		
   176 		if not activity:
   177 			activity = find_last_activity(db_file, time)
   178 		elif not project:
   179 			project = find_last_project(db_file, time) 	
   180 		
   181 		con, cur = session(db_file)
   182 		if activity == "all" and project == "all":
   183 			values = (time,)
   184 			sql = "update tasks set end=? where end is null"
   185 		else:
   186 			values = (time, project_id(db_file, project), activity_id(db_file, activity))
   187 			sql = "update tasks set end=? where project=? and activity=?"
   188 		cur.execute(sql, values)
   189 		con.commit()
   190 		cur.close()
   191 	test(db_file)
   192 
   193 def begin(db_file, project, activity, time):
   194 	print "beginning: %s:%s" % (project, activity)
   195 	last_project = find_last_project(db_file, time) 
   196 	last_activity = find_last_activity(db_file, time)	
   197 	if not project:
   198 		project = last_project
   199 	elif not activity:
   200 			activity = DEF_ACTIVITY
   201 	if activity != last_activity or project != last_project:
   202 		end(db_file, last_project, last_activity, time)
   203 		con, cur = session(db_file)
   204 		values = (time, None, project_id(db_file, project), 
   205 					activity_id(db_file, activity), None)
   206 		sql = "insert into tasks values(?, ?, ?, ?, ?)"
   207 		cur.execute(sql, values)
   208 		con.commit()
   209 		cur.close()
   210 	test(db_file)
   211 
   212 def is_paused(db_file, time):
   213 	con, cur = session(db_file)
   214 	sql = "select rowid from breaks where end is null"
   215 	cur.execute(sql)
   216 	paused = cur.fetchone()
   217 	cur.close()
   218 	return paused
   219 
   220 def pause(db_file, project, activity, time):
   221 	print "pausing" 
   222 	if not is_paused(db_file, time):
   223 		project = find_last_project(db_file, time) 
   224 		activity = find_last_activity(db_file, time)
   225 		con, cur = session(db_file)
   226 		values = (time, None, project_id(db_file, project), 
   227 					activity_id(db_file, activity), None)
   228 		sql = "insert into breaks values(?, ?, ?, ?, ?)"
   229 		cur.execute(sql, values)
   230 		con.commit()
   231 		cur.close()
   232 	test(db_file)
   233 
   234 def resume(db_file, project, activity, time):
   235 	print "resuming"
   236 	if is_paused(db_file, time):
   237 		task = find_active_task(db_file)
   238 		activity = find_last_activity(db_file, time)
   239 		project = find_last_project(db_file, time) 			
   240 		con, cur = session(db_file)
   241 		values = (time, project_id(db_file, project), activity_id(db_file, activity))
   242 		sql = "update breaks set end=? where project=? and activity=?"
   243 		cur.execute(sql, values)
   244 		con.commit()
   245 		cur.close()
   246 	test(db_file)
   247 
   248 def status(db_file):
   249 	task = find_active_task(db_file)
   250 	con, cur = session(db_file)
   251 	result = None
   252 	if task:
   253 		values = (task,)
   254 		sql = "select project, activity from tasks where rowid=?"
   255 		cur.execute(sql, values)
   256 		result = cur.fetchone()
   257 		if result:
   258 			result = (id_name(db_file, "projects", result[0]),
   259 						id_name(db_file, "activities", result[1]))
   260 	return result
   261