]> apps.delaporte.us Git - matrix-goal-bot.git/blob - matrix_goal_bot/db.py
d7896e08d062c84797ba9e2dadf1defaad67f9f2
[matrix-goal-bot.git] / matrix_goal_bot / db.py
1 import logging
2 import os
3 from datetime import datetime as dt
4
5 from sqlmodel import Field, Session, SQLModel, create_engine, select, text, Relationship
6
7 logger = logging.getLogger(__name__)
8
9 DATE_FORMAT = '%Y-%m-%d'
10
11 def today():
12 return dt.now().strftime(DATE_FORMAT)
13
14
15 class Vision(SQLModel, table=True):
16 id: int | None = Field(default=None, primary_key=True)
17 name: str = Field(default=None, unique=True)
18 complete_date: dt | None = Field(default=None)
19 goals: list["Goal"] = Relationship(back_populates="vision")
20 def __str__(self):
21 return f'{self.name} (Vision {self.id})'
22
23
24 class PreferGoal(SQLModel, table=True):
25 goal_id: int | None = Field(default=None, foreign_key="goal.id", primary_key=True)
26
27
28 class Goal(SQLModel, table=True):
29 id: int | None = Field(default=None, primary_key=True)
30 name: str = Field(default=None, unique=True)
31 start_date: dt | None = Field(default=today())
32 complete_date: dt | None = Field(default=None)
33 vision_id: int | None = Field(default=None, foreign_key="vision.id")
34 notes: str | None = Field(default=None)
35 tasks: list["Task"] = Relationship(back_populates="goal")
36 vision: Vision = Relationship(back_populates="goals")
37 def __str__(self):
38 if not self.complete_date:
39 return f'{self.name} (Goal {self.id})'
40 else:
41 completed = self.complete_date.strftime(DATE_FORMAT)
42 return f'(Done {completed}) {self.name} (Goal {self.id})'
43
44 class Task(SQLModel, table=True):
45 id: int | None = Field(default=None, primary_key=True)
46 name: str = Field(default=None, unique=True)
47 goal_id: int | None = Field(default=None, foreign_key="goal.id")
48 complete_date: dt | None = Field(default=None)
49 goal: Goal = Relationship(back_populates="tasks")
50 def __str__(self):
51 return f'{self.name} ({self.id})'
52
53
54 def pretty_print(goal, tasks):
55 results = []
56 results.append(f' ## {goal}')
57 if not tasks:
58 results.append('-- Nothing to list --')
59
60 for task in tasks:
61 if(task.complete_date):
62 results.append(f' - [x] {task}')
63 else:
64 results.append(f' - [ ] {task}')
65 return results
66
67
68 class Data():
69 def __init__(self, db_file=None):
70 if not db_file:
71 db_file = os.path.join(os.environ.get('MATRIX_DATA_DIR', ''), 'goal.db')
72
73 self.file = db_file
74 self.engine = self.get_engine()
75
76
77 def get_engine(self):
78 return create_engine(f"sqlite:///{self.file}")
79
80 def setup(self):
81 SQLModel.metadata.create_all(self.engine)
82 return 'Success'
83
84
85 def _set_pref_goal_id(self, goal_id):
86 with Session(self.engine) as session:
87 prefs = session.exec(select(PreferGoal)).all()
88 for pref in prefs:
89 session.delete(pref)
90 pref = PreferGoal()
91 pref.goal_id = goal_id
92 session.add(pref)
93 session.commit()
94
95 def _get_pref_goal_id(self):
96 with Session(self.engine) as session:
97 pref = session.exec(select(PreferGoal)).one()
98 return pref.goal_id
99
100
101 def clear_list(self, goal_id, clear_all=False):
102 with Session(self.engine) as session:
103 goal = session.exec(_get_with_id(Goal, goal_id)).first()
104 for item in goal.tasks:
105 if clear_all or item.complete_date:
106 session.delete(item)
107 session.commit()
108
109 def get_all_visions(self):
110 with Session(self.engine) as session:
111 cmd = select(Vision).where(Vision.complete_date == None)
112 return session.exec(cmd).all()
113
114 def get_all_goals(self):
115 '''List all goals'''
116 with Session(self.engine) as session:
117 cmd = select(Goal).where(Goal.complete_date == None)
118 return session.exec(cmd).all()
119
120 def get_current_goals(self):
121 '''List current goals'''
122 with Session(self.engine) as session:
123 cmd = select(Goal).where(Goal.complete_date == None).where(Goal.start_date <= today())
124 return session.exec(cmd).all()
125
126 def get_done_goals(self):
127 '''List completed goals'''
128 with Session(self.engine) as session:
129 cmd = select(Goal).where(Goal.complete_date != None)
130 return session.exec(cmd).all()
131
132
133 def get_goal(self, goal_id):
134 self._set_pref_goal_id(goal_id)
135 with Session(self.engine) as session:
136 cmd = select(Goal).where(Goal.id == goal_id)
137 goal = session.exec(cmd).first()
138 return (goal, goal.tasks)
139
140 def get_vision(self, id):
141 with Session(self.engine) as session:
142 cmd = select(Vision).where(Vision.id == id)
143 vision = session.exec(cmd).first()
144 if vision:
145 return (vision, vision.goals)
146 else:
147 return ('Not found', [])
148
149
150 def complete_vision(self, id):
151 with Session(self.engine) as session:
152 cmd = select(Vision).where(Vision.id == id)
153 vision = session.exec(cmd).first()
154 vision.complete_date = dt.today()
155 session.commit()
156
157
158 def complete_goal(self, goal_id):
159 vision_id = -1
160 with Session(self.engine) as session:
161 cmd = select(Goal).where(Goal.id == goal_id)
162 goal = session.exec(cmd).first()
163 goal.complete_date = dt.today()
164 vision_id = goal.vision_id
165 session.commit()
166 return vision_id
167
168
169 def put_off_goal(self, goal_id):
170 vision_id = -1
171 with Session(self.engine) as session:
172 cmd = select(Goal).where(Goal.id == goal_id)
173 goal = session.exec(cmd).first()
174 goal.start_date = dt.today() + timedelta(days=14)
175 vision_id = goal.vision_id
176 session.commit()
177 return vision_id
178
179
180 def rename_goal(self, goal_id, name):
181 self._set_pref_goal_id(goal_id)
182 vision_id = -1
183 with Session(self.engine) as session:
184 cmd = select(Goal).where(Goal.id == goal_id)
185 goal = session.exec(cmd).first()
186 goal.name = name
187 vision_id = goal.vision_id
188 session.commit()
189 return vision_id
190
191
192 def complete_task(self, id):
193 with Session(self.engine) as session:
194 cmd = select(Task).where(Task.id == id)
195 task = session.exec(cmd).first()
196 task.complete_date = dt.today()
197 goal_id = task.goal_id
198 session.commit()
199 self._set_pref_goal_id(goal_id)
200 return goal_id
201
202 def add_with_name(self, cls, name):
203 id = -1
204 with Session(self.engine) as session:
205 new = cls(name=name)
206 session.add(new)
207 session.commit()
208 id = new.id
209 return id
210
211 def add_vision(self, name):
212 return self.add_with_name(Vision, name)
213
214 def add_goal(self, name):
215 goal_id = self.add_with_name(Goal, name)
216 self._set_pref_goal_id(goal_id)
217 return goal_id
218
219 def quick_add_task(self, name):
220 goal_id = self._get_pref_goal_id()
221 task_id = self.add_with_name(Task, name)
222 with Session(self.engine) as session:
223 cmd = select(Task).where(Task.id == task_id)
224 new = session.exec(cmd).first()
225 new.goal_id = goal_id
226 session.commit()
227 return goal_id
228
229 def remove_task(self, task_id):
230 task_name = ''
231 logger.debug(f'Removing task with id {task_id}')
232 with Session(self.engine) as session:
233 cmd = select(Task).where(Task.id == int(task_id))
234 to_remove = session.exec(cmd).first()
235 if not to_remove:
236 return f'Unable to find task with id {task_id}'
237
238 logger.debug(f'Removing task with name {to_remove.name}')
239 task_name = to_remove.name
240 session.delete(to_remove)
241 session.commit()
242 return f'Removed task "{task_name}"'
243
244 def assign_vision(self, goal_id, vision_id):
245 '''Goals may move between visions'''
246 self._set_pref_goal_id(goal_id)
247 with Session(self.engine) as session:
248 cmd = select(Goal).where(Goal.id == goal_id)
249 goal = session.exec(cmd).first()
250 goal.vision_id = vision_id
251 session.commit()
252
253 def visionless(self):
254 '''Get goals with no vision'''
255 with Session(self.engine) as session:
256 cmd = select(Goal).where(Goal.vision_id == None)
257 return session.exec(cmd).all()
258
259
260 def add_note(self, note, goal):
261 '''Notes print with the goal.'''
262 pass
263
264 # Someday: Notes on each
265