 0aeff69da8
			
		
	
	
		0aeff69da8
		
	
	
	
	
		
			
			This commit introduces a `Database` class to encapsulate all database-related operations. This improves code organization, testability, and maintainability. - Created Database class with methods for creating tables, loading/saving projects, log entries, and settings. - Added error handling for database connection and operations. - Implemented methods to load and save invoice numbers. - Replaced direct database access with Database class methods.
		
			
				
	
	
		
			188 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # timelogix/database.py
 | |
| import sqlite3
 | |
| 
 | |
| 
 | |
| class Database:
 | |
|     def __init__(self, db_file="timelogix.db"):
 | |
|         self.db_file = db_file
 | |
|         self.conn = None  # Initialize conn to None
 | |
|         self.cursor = None  # Initialize cursor to None
 | |
|         try:
 | |
|             self.conn = sqlite3.connect(self.db_file)
 | |
|             self.cursor = self.conn.cursor()
 | |
|             self.create_tables()
 | |
|         except sqlite3.Error as e:
 | |
|             print(f"Database error: {e}")
 | |
|             # Handle the error appropriately, e.g., exit or disable DB features
 | |
| 
 | |
|     def create_tables(self):
 | |
|         self.cursor.execute(
 | |
|             """
 | |
|             CREATE TABLE IF NOT EXISTS projects (
 | |
|                 id INTEGER PRIMARY KEY AUTOINCREMENT,
 | |
|                 name TEXT NOT NULL UNIQUE
 | |
|             )
 | |
|         """
 | |
|         )
 | |
|         self.cursor.execute(
 | |
|             """
 | |
|             CREATE TABLE IF NOT EXISTS log_entries (
 | |
|                 id INTEGER PRIMARY KEY AUTOINCREMENT,
 | |
|                 task TEXT,
 | |
|                 project_id INTEGER,
 | |
|                 start_time TEXT,
 | |
|                 end_time TEXT,
 | |
|                 duration REAL,
 | |
|                 FOREIGN KEY (project_id) REFERENCES projects (id)
 | |
|             )
 | |
|         """
 | |
|         )
 | |
|         self.cursor.execute(
 | |
|             """
 | |
|             CREATE TABLE IF NOT EXISTS settings (
 | |
|                 id INTEGER PRIMARY KEY AUTOINCREMENT,
 | |
|                 company_name TEXT,
 | |
|                 company_address TEXT,
 | |
|                 client_name TEXT,
 | |
|                 client_address TEXT,
 | |
|                 hourly_rate REAL,
 | |
|                 invoice_number INTEGER
 | |
|             )
 | |
|         """
 | |
|         )
 | |
|         # Check if settings exist, if not create
 | |
|         self.cursor.execute("SELECT COUNT(*) FROM settings")
 | |
|         if self.cursor.fetchone()[0] == 0:
 | |
|             self.cursor.execute(
 | |
|                 """
 | |
|                 INSERT INTO settings (company_name, company_address, client_name, client_address, hourly_rate, invoice_number)
 | |
|                 VALUES (?, ?, ?, ?, ?, ?)
 | |
|             """,
 | |
|                 (
 | |
|                     "Your Company Name",  # Default company name
 | |
|                     "123 Main St, Anytown, USA",  # Default company address
 | |
|                     "Client Name",  # Default client name
 | |
|                     "Client Address",  # Default client address
 | |
|                     60.00,  # Default hourly rate
 | |
|                     1,
 | |
|                 ),
 | |
|             )  # Start invoice number at 1
 | |
|         self.conn.commit()
 | |
| 
 | |
|     def load_projects(self):
 | |
|         self.cursor.execute("SELECT name FROM projects")
 | |
|         projects = [row[0] for row in self.cursor.fetchall()]
 | |
|         return projects
 | |
| 
 | |
|     def save_projects(self, projects):
 | |
|         for project in projects:
 | |
|             try:
 | |
|                 self.cursor.execute(
 | |
|                     "INSERT INTO projects (name) VALUES (?)", (project,)
 | |
|                 )
 | |
|             except sqlite3.IntegrityError:
 | |
|                 pass  # Ignore if project already exists
 | |
|         self.conn.commit()
 | |
| 
 | |
|     def load_invoice_number(self):
 | |
|         self.cursor.execute("SELECT invoice_number FROM settings")
 | |
|         invoice_number = self.cursor.fetchone()[0]
 | |
|         return invoice_number
 | |
| 
 | |
|     def save_invoice_number(self, invoice_number):
 | |
|         self.cursor.execute("UPDATE settings SET invoice_number = ?", (invoice_number,))
 | |
|         self.conn.commit()
 | |
| 
 | |
|     def add_project(self, project_name):
 | |
|         try:
 | |
|             self.cursor.execute(
 | |
|                 "INSERT INTO projects (name) VALUES (?)", (project_name,)
 | |
|             )
 | |
|             self.conn.commit()
 | |
|             return True
 | |
|         except sqlite3.IntegrityError:
 | |
|             return False  # Project already exists
 | |
| 
 | |
|     def get_project_id(self, project_name):
 | |
|         self.cursor.execute("SELECT id FROM projects WHERE name = ?", (project_name,))
 | |
|         result = self.cursor.fetchone()
 | |
|         if result:
 | |
|             return result[0]
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
|     def insert_log_entry(self, task, project_id, start_time, end_time, duration):
 | |
|         self.cursor.execute(
 | |
|             """
 | |
|             INSERT INTO log_entries (task, project_id, start_time, end_time, duration)
 | |
|             VALUES (?, ?, ?, ?, ?)
 | |
|         """,
 | |
|             (task, project_id, start_time, end_time, duration),
 | |
|         )
 | |
|         self.conn.commit()
 | |
| 
 | |
|     def load_log_entries(self):
 | |
|         self.cursor.execute(
 | |
|             """
 | |
|             SELECT log_entries.task, projects.name, log_entries.start_time,
 | |
|                    log_entries.end_time, log_entries.duration
 | |
|             FROM log_entries
 | |
|             JOIN projects ON log_entries.project_id = projects.id
 | |
|         """
 | |
|         )
 | |
|         rows = self.cursor.fetchall()
 | |
|         log_entries = []
 | |
|         for row in rows:
 | |
|             task, project, start_time, end_time, duration = row
 | |
|             entry = {
 | |
|                 "task": task,
 | |
|                 "project": project,
 | |
|                 "start_time": start_time,
 | |
|                 "end_time": end_time,
 | |
|                 "duration": duration,
 | |
|             }
 | |
|             log_entries.append(entry)
 | |
|         return log_entries
 | |
| 
 | |
|     def update_settings(
 | |
|         self, company_name, company_address, client_name, client_address, hourly_rate
 | |
|     ):
 | |
|         self.cursor.execute(
 | |
|             """
 | |
|             UPDATE settings SET
 | |
|             company_name = ?, company_address = ?, client_name = ?,
 | |
|             client_address = ?, hourly_rate = ?
 | |
|         """,
 | |
|             (company_name, company_address, client_name, client_address, hourly_rate),
 | |
|         )
 | |
|         self.conn.commit()
 | |
| 
 | |
|     def load_settings(self):
 | |
|         self.cursor.execute("SELECT * FROM settings")
 | |
|         settings = self.cursor.fetchone()
 | |
|         if settings:
 | |
|             (
 | |
|                 _,
 | |
|                 company_name,
 | |
|                 company_address,
 | |
|                 client_name,
 | |
|                 client_address,
 | |
|                 hourly_rate,
 | |
|                 invoice_number,
 | |
|             ) = settings
 | |
|             return {
 | |
|                 "company_name": company_name,
 | |
|                 "company_address": company_address,
 | |
|                 "client_name": client_name,
 | |
|                 "client_address": client_address,
 | |
|                 "hourly_rate": hourly_rate,
 | |
|                 "invoice_number": invoice_number,
 | |
|             }
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
|     def close(self):
 | |
|         if self.conn:
 | |
|             self.conn.close()
 | |
|             self.conn = None
 | |
|             self.cursor = None
 |