import os from tinydb import TinyDB, Query from tinydb.operations import increment import config os.makedirs(os.path.dirname(config.DB_PATH), exist_ok=True) db = TinyDB(config.DB_PATH) users_table = db.table("users") goals_table = db.table("goals") tasks_table = db.table("tasks") User = Query() Goal = Query() Task = Query() def init_db(): if users_table.count(User.role == "admin") == 0: import bcrypt password_hash = bcrypt.hashpw( config.DEFAULT_ADMIN_PASSWORD.encode("utf-8"), bcrypt.gensalt() ).decode("utf-8") users_table.insert({ "username": config.DEFAULT_ADMIN_USERNAME, "password_hash": password_hash, "role": "admin", "max_goals": 100 }) def get_user_by_username(username): result = users_table.search(User.username == username) return result[0] if result else None def get_user_by_id(user_id): return users_table.get(doc_id=user_id) def create_user(username, password_hash, role="user", max_goals=None): if max_goals is None: max_goals = config.DEFAULT_MAX_GOALS doc_id = users_table.insert({ "username": username, "password_hash": password_hash, "role": role, "max_goals": max_goals }) return users_table.get(doc_id=doc_id) def update_user(user_id, **kwargs): users_table.update(kwargs, doc_ids=[user_id]) def get_all_users(): return users_table.all() def get_goals_by_user(user_id): return goals_table.search(Goal.user_id == user_id) def get_goal_by_id(goal_id): return goals_table.get(doc_id=goal_id) def create_goal(user_id, title): doc_id = goals_table.insert({ "user_id": user_id, "title": title, "activated": True }) return goals_table.get(doc_id=doc_id) def update_goal(goal_id, **kwargs): goals_table.update(kwargs, doc_ids=[goal_id]) def delete_goal(goal_id): tasks = tasks_table.search(Task.goal_id == goal_id) for task in tasks: tasks_table.remove(doc_ids=[task.doc_id]) goals_table.remove(doc_ids=[goal_id]) def count_goals_by_user(user_id): return len(goals_table.search(Goal.user_id == user_id)) def get_tasks_by_goal(goal_id): return tasks_table.search(Task.goal_id == goal_id) def get_task_by_id(task_id): return tasks_table.get(doc_id=task_id) def create_task(goal_id, title, desc="", status="todo", order=None): if order is None: existing_tasks = tasks_table.search(Task.goal_id == goal_id) unfinished = [t for t in existing_tasks if t.get("status") != "done"] order = max([t.get("order", 0) for t in unfinished], default=0) + 1.0 doc_id = tasks_table.insert({ "goal_id": goal_id, "title": title, "desc": desc, "status": status, "start_time": None, "finished_time": None, "order": order }) return tasks_table.get(doc_id=doc_id) def update_task(task_id, **kwargs): tasks_table.update(kwargs, doc_ids=[task_id]) def delete_task(task_id): tasks_table.remove(doc_ids=[task_id]) def get_tasks_sorted(goal_id): all_tasks = tasks_table.search(Task.goal_id == goal_id) unfinished = [t for t in all_tasks if t.get("status") != "done"] finished = [t for t in all_tasks if t.get("status") == "done"] unfinished.sort(key=lambda t: t.get("order", 0)) finished.sort(key=lambda t: t.get("finished_time", ""), reverse=True) return unfinished + finished