]> us-delaporte.pagekite.me Git - matrix-goal-bot.git/blob - matrix_goal_bot/db.py
fixup
[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 session.commit()
91 pref = PreferGoal()
92 pref.goal_id = goal_id
93 session.add(pref)
94 session.commit()
95
96 def _get_pref_goal_id(self):
97 with Session(self.engine) as session:
98 pref = session.exec(select(PreferGoal)).one()
99 return pref.goal_id
100
101
102 def clear_list(self, goal_id, clear_all=False):
103 with Session(self.engine) as session:
104 goal = session.exec(_get_with_id(Goal, goal_id)).first()
105 for item in goal.tasks:
106 if clear_all or item.complete_date:
107 session.delete(item)
108 session.commit()
109
110 def get_all_visions(self):
111 with Session(self.engine) as session:
112 cmd = select(Vision).where(Vision.complete_date == None)
113 return session.exec(cmd).all()
114
115 def get_all_goals(self):
116 '''List all goals'''
117 with Session(self.engine) as session:
118 cmd = select(Goal).where(Goal.complete_date == None)
119 return session.exec(cmd).all()
120
121 def get_current_goals(self):
122 '''List current goals'''
123 with Session(self.engine) as session:
124 # cmd = select(Goal).where(Goal.complete_date == None).where(Goal.start_date <= today())
125 cmd = select(Goal).where(Goal.complete_date == None)
126 return session.exec(cmd).all()
127
128 def get_done_goals(self):
129 '''List completed goals'''
130 with Session(self.engine) as session:
131 cmd = select(Goal).where(Goal.complete_date != None)
132 return session.exec(cmd).all()
133
134
135 def get_goal(self, goal_id):
136 self._set_pref_goal_id(goal_id)
137 with Session(self.engine) as session:
138 cmd = select(Goal).where(Goal.id == goal_id)
139 goal = session.exec(cmd).first()
140 return (goal, goal.tasks)
141
142 def get_vision(self, id):
143 with Session(self.engine) as session:
144 cmd = select(Vision).where(Vision.id == id)
145 vision = session.exec(cmd).first()
146 if vision:
147 return (vision, vision.goals)
148 else:
149 return ('Not found', [])
150
151
152 def complete_vision(self, id):
153 with Session(self.engine) as session:
154 cmd = select(Vision).where(Vision.id == id)
155 vision = session.exec(cmd).first()
156 vision.complete_date = dt.today()
157 session.commit()
158
159
160 def complete_goal(self, goal_id):
161 vision_id = -1
162 with Session(self.engine) as session:
163 cmd = select(Goal).where(Goal.id == goal_id)
164 goal = session.exec(cmd).first()
165 goal.complete_date = dt.today()
166 vision_id = goal.vision_id
167 session.commit()
168 return vision_id
169
170
171 def put_off_goal(self, goal_id):
172 vision_id = -1
173 with Session(self.engine) as session:
174 cmd = select(Goal).where(Goal.id == goal_id)
175 goal = session.exec(cmd).first()
176 goal.start_date = dt.today() + timedelta(days=14)
177 vision_id = goal.vision_id
178 session.commit()
179 return vision_id
180
181
182 def rename_goal(self, goal_id, name):
183 self._set_pref_goal_id(goal_id)
184 vision_id = -1
185 with Session(self.engine) as session:
186 cmd = select(Goal).where(Goal.id == goal_id)
187 goal = session.exec(cmd).first()
188 goal.name = name
189 vision_id = goal.vision_id
190 session.commit()
191 return vision_id
192
193
194 def complete_task(self, id):
195 with Session(self.engine) as session:
196 cmd = select(Task).where(Task.id == id)
197 task = session.exec(cmd).first()
198 task.complete_date = dt.today()
199 goal_id = task.goal_id
200 session.commit()
201 self._set_pref_goal_id(goal_id)
202 return goal_id
203
204 def add_with_name(self, cls, name):
205 id = -1
206 with Session(self.engine) as session:
207 new = cls(name=name)
208 session.add(new)
209 session.commit()
210 id = new.id
211 return id
212
213 def add_vision(self, name):
214 return self.add_with_name(Vision, name)
215
216 def add_goal(self, name):
217 goal_id = self.add_with_name(Goal, name)
218 self._set_pref_goal_id(goal_id)
219 return goal_id
220
221 def quick_add_task(self, name):
222 goal_id = self._get_pref_goal_id()
223 task_id = self.add_with_name(Task, name)
224 with Session(self.engine) as session:
225 cmd = select(Task).where(Task.id == task_id)
226 new = session.exec(cmd).first()
227 new.goal_id = goal_id
228 session.commit()
229 return goal_id
230
231 def remove_task(self, task_id):
232 task_name = ''
233 logger.debug(f'Removing task with id {task_id}')
234 with Session(self.engine) as session:
235 cmd = select(Task).where(Task.id == int(task_id))
236 to_remove = session.exec(cmd).first()
237 if not to_remove:
238 return f'Unable to find task with id {task_id}'
239
240 logger.debug(f'Removing task with name {to_remove.name}')
241 task_name = to_remove.name
242 session.delete(to_remove)
243 session.commit()
244 return f'Removed task "{task_name}"'
245
246 def assign_vision(self, goal_id, vision_id):
247 '''Goals may move between visions'''
248 self._set_pref_goal_id(goal_id)
249 with Session(self.engine) as session:
250 cmd = select(Goal).where(Goal.id == goal_id)
251 goal = session.exec(cmd).first()
252 goal.vision_id = vision_id
253 session.commit()
254
255 def visionless(self):
256 '''Get goals with no vision'''
257 with Session(self.engine) as session:
258 cmd = select(Goal).where(Goal.vision_id == None)
259 return session.exec(cmd).all()
260
261
262 def add_note(self, note, goal):
263 '''Notes print with the goal.'''
264 pass
265
266 # Someday: Notes on each
267