db.py
author Eugen Sawin <sawine@me73.com>
Mon, 18 Jul 2011 01:03:37 +0200
changeset 14 1b45f8231179
parent 13 4ef9c2142059
permissions -rw-r--r--
Renamed and added default config file.
     1 """
     2 Description: 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 CURRENCIES_TABLE = """currencies(
    29 name text not null)"""
    30 
    31 RATE_TYPES_TABLE = """rate_types(
    32 name text not null)"""
    33 
    34 RATES_TABLE = """rates(
    35 rate smallmoney not null,
    36 currency int not null,
    37 type int not null,
    38 project int not null,
    39 activity int,
    40 constraint currency_fk foreign key(currency) references currencies(rowid) on
    41 delete cascade,
    42 constraint type_fk foreign key(type) references rate_types(rowid) on delete
    43 cascade,
    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 TASKS_TABLE = """tasks(
    50 begin datetime,
    51 end datetime,
    52 project int,
    53 activity int,
    54 log text,
    55 constraint project_fk foreign key(project) references projects(rowid) on delete
    56 cascade,
    57 constraint activity_fk foreign key(activity) references activities(rowid) on delete
    58 cascade)"""
    59 
    60 BREAKS_TABLE = """breaks(
    61 begin datetime,
    62 end datetime,
    63 task int,
    64 log text,
    65 constraint task_fk foreign key(task) references tasks(rowid) on delete
    66 cascade)"""
    67 
    68 TABLES = (ACTIVITIES_TABLE, COMPANIES_TABLE, PROJECTS_TABLE, CURRENCIES_TABLE,
    69 RATES_TABLE, RATE_TYPES_TABLE, TASKS_TABLE, BREAKS_TABLE)
    70 
    71 DEF_PROJECT = "default"
    72 DEF_ACTIVITY = "default"
    73 
    74 def session(db_file):
    75 	con = sqlite3.connect(db_file)
    76 	return con, con.cursor()
    77 
    78 def test(db_file):
    79 	con, cur = session(db_file)
    80 	cur.execute("select * from projects")
    81 	print "\nPROJECTS"
    82 	for c in cur:
    83 		print c
    84 	cur.execute("select * from activities")
    85 	print "\nACTIVITIES"
    86 	for c in cur:
    87 		print c
    88 	cur.execute("select * from tasks")
    89 	print "\nTASKS"
    90 	for c in cur:
    91 		print c
    92 	cur.execute("select * from breaks")
    93 	print "\nBREAKS"
    94 	for c in cur:
    95 		print c
    96 	cur.execute("select * from currencies")
    97 	print "\nCURRENCIES"
    98 	for c in cur:
    99 		print c
   100 	cur.execute("select * from rate_types")
   101 	print "\nRATE_TYPES"
   102 	for c in cur:
   103 		print c
   104 	cur.execute("select * from rates")
   105 	print "\nRATES"
   106 	for c in cur:
   107 		print c
   108 	cur.close()
   109 
   110 def init(db_file):
   111 	con, cur = session(db_file)
   112 	for table in TABLES:
   113 		sql = "create table " + table
   114 		cur.execute(sql)
   115 	con.commit()
   116 	cur.close()
   117 
   118 def update_where(db_file, table, dep_column, dep_value, set_column, set_value):
   119 	con, cur = session(db_file)
   120 	values = (set_value, dep_value)	
   121 	sql = "update %s set %s=? where %s=?" % (table, set_column, dep_column)
   122 	cur.execute(sql, values)
   123 	con.commit()
   124 	cur.close()
   125 	test(db_file)
   126 
   127 def set_rate(db_file, project, activity, rate, currency, type):
   128 	if not activity:
   129 		activity = DEF_ACTIVITY
   130 	con, cur = session(db_file)
   131 	values = (rate, row_id(db_file, "currencies", currency), 
   132 				row_id(db_file, "rate_types", type),
   133 				row_id(db_file, "projects", project), 
   134 				row_id(db_file, "activities", activity))
   135 	sql = "insert into rates values(?, ?, ?, ?, ?)"
   136 	cur.execute(sql, values)
   137 	con.commit()
   138 	cur.close()
   139 	test(db_file)
   140 
   141 def find_last_project(db_file, time):
   142 	con, cur = session(db_file)
   143 	values = (time,)
   144 	sql = "select project from tasks where begin < ? and end is null order by \
   145 begin desc"
   146 	cur.execute(sql, values)
   147 	id = cur.fetchone()
   148 	if id:
   149 		values = (id[0],)
   150 		sql = "select name from projects where rowid=?"
   151 		cur.execute(sql, values)
   152 		project = cur.fetchone()[0]
   153 	else:
   154 		project = None#DEF_PROJECT
   155 	con.commit()
   156 	cur.close()
   157 	return project
   158 
   159 def find_last_activity(db_file, time):
   160 	con, cur = session(db_file)
   161 	values = (time,)
   162 	sql = "select activity from tasks where begin < ? and end is null order by \
   163 begin desc"
   164 	cur.execute(sql, values)
   165 	id = cur.fetchone()
   166 	if id:
   167 		values = (id[0],)
   168 		sql = "select name from activities where rowid=?"
   169 		cur.execute(sql, values)
   170 		activity = cur.fetchone()[0]
   171 	else:
   172 		activity = None#DEF_ACTIVITY
   173 	con.commit()
   174 	cur.close()
   175 	return activity
   176 
   177 def find_active_task(db_file, time=None):
   178 	con, cur = session(db_file)
   179 	if time:
   180 		values = (time, time)
   181 		sql = "select project, activity from tasks where begin < ? and \
   182 (end is null or end > ?)"
   183 	else:
   184 		values = ()
   185 		sql = "select project, activity from tasks where end is null"
   186 	cur.execute(sql, values)	
   187 	task = cur.fetchone()
   188 	if task:
   189 		task = task[0]	
   190 	cur.close()
   191 	return task			
   192 
   193 def id_name(db_file, table, id):
   194 	con, cur = session(db_file)
   195 	values = (id,)
   196 	sql = "select name from %s where rowid=?" % table
   197 	cur.execute(sql, values)
   198 	id = cur.fetchone()
   199 	cur.close()
   200 	return id[0]
   201 
   202 def row_id(db_file, table, name):
   203 	con, cur = session(db_file)
   204 	values = (name,)
   205 	sql = "select rowid from %s where name=?" % table
   206 	cur.execute(sql, values)
   207 	id = cur.fetchone()
   208 	if not id:
   209 		sql = "insert into %s(name) values(?)" % table
   210 		cur.execute(sql, values)
   211 		con.commit()
   212 		cur.close()
   213 		return row_id(db_file, table, name)
   214 	con.commit()
   215 	cur.close()
   216 	return id[0]
   217 
   218 def project_id(db_file, name):
   219 	return row_id(db_file, "projects", name)
   220 
   221 def activity_id(db_file, name):
   222 	return row_id(db_file, "activities", name)
   223 
   224 def end(db_file, project, activity, time, log):
   225 	print "ending: %s:%s" % (project, activity)
   226 	if activity or project:		
   227 		if not activity:
   228 			activity = find_last_activity(db_file, time)
   229 		elif not project:
   230 			project = find_last_project(db_file, time) 	
   231 		
   232 		con, cur = session(db_file)
   233 		if activity == "all" and project == "all":
   234 			values = (time, log)
   235 			sql = "update tasks set end=?, log=? where end is null"
   236 		else:
   237 			values = (time, log, project_id(db_file, project), 
   238 						activity_id(db_file, activity))
   239 			sql = "update tasks set end=?, log=? where project=? and activity=?"
   240 		cur.execute(sql, values)
   241 		con.commit()
   242 		cur.close()
   243 	test(db_file)
   244 
   245 def begin(db_file, project, activity, time):
   246 	print "beginning: %s:%s" % (project, activity)
   247 	last_project = find_last_project(db_file, time) 
   248 	last_activity = find_last_activity(db_file, time)	
   249 	if not project:
   250 		project = last_project
   251 	elif not activity:
   252 			activity = DEF_ACTIVITY
   253 	if activity != last_activity or project != last_project:
   254 		end(db_file, last_project, last_activity, time, None)
   255 		con, cur = session(db_file)
   256 		values = (time, None, project_id(db_file, project), 
   257 					activity_id(db_file, activity), None)
   258 		sql = "insert into tasks values(?, ?, ?, ?, ?)"
   259 		cur.execute(sql, values)
   260 		con.commit()
   261 		cur.close()
   262 	test(db_file)
   263 
   264 def is_paused(db_file, time):
   265 	con, cur = session(db_file)
   266 	values = (time,)
   267 	sql = "select rowid from breaks where begin < ? and end is null"
   268 	cur.execute(sql, values)
   269 	paused = cur.fetchone()
   270 	cur.close()
   271 	return paused
   272 
   273 def pause(db_file, time):
   274 	print "pausing" 
   275 	if not is_paused(db_file, time):
   276 		task = find_active_task(db_file, time)
   277 		con, cur = session(db_file)
   278 		values = (time, None, task, None)
   279 		sql = "insert into breaks values(?, ?, ?, ?)"
   280 		cur.execute(sql, values)
   281 		con.commit()
   282 		cur.close()
   283 	test(db_file)
   284 
   285 def resume(db_file, task, time, log):
   286 	print "resuming"
   287 	if is_paused(db_file, time):	
   288 		if not task:
   289 			task = find_active_task(db_file, time)	
   290 		con, cur = session(db_file)
   291 		values = (time, log, task)
   292 		sql = "update breaks set end=?, log=? where task=? and end is null"
   293 		cur.execute(sql, values)
   294 		con.commit()
   295 		cur.close()
   296 	test(db_file)
   297 
   298 def status(db_file):
   299 	task = find_active_task(db_file)
   300 	con, cur = session(db_file)
   301 	result = None
   302 	if task:
   303 		values = (task,)
   304 		sql = "select project, activity from tasks where rowid=?"
   305 		cur.execute(sql, values)
   306 		result = cur.fetchone()
   307 		if result:
   308 			result = (id_name(db_file, "projects", result[0]),
   309 						id_name(db_file, "activities", result[1]))
   310 	return result
   311