]> apps.delaporte.us 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 complete_date: dt | None = Field(default=None)
32 vision_id: int | None = Field(default=None, foreign_key="vision.id")
33 notes: str | None = Field(default=None)
34 tasks: list["Task"] = Relationship(back_populates="goal")
35 vision: Vision = Relationship(back_populates="goals")
36 def __str__(self):
37 if not self.complete_date:
38 return f'{self.name} (Goal {self.id})'
39 else:
40 completed = self.complete_date.strftime(DATE_FORMAT)
41 return f'(Done {completed}) {self.name} (Goal {self.id})'
42
43 class Task(SQLModel, table=True):
44 id: int | None = Field(default=None, primary_key=True)
45 name: str = Field(default=None, unique=True)
46 goal_id: int | None = Field(default=None, foreign_key="goal.id")
47 complete_date: dt | None = Field(default=None)
48 goal: Goal = Relationship(back_populates="tasks")
49 def __str__(self):
50 return f'{self.name} ({self.id})'
51
52
53 def pretty_print(goal, tasks):
54 results = []
55 results.append(f' ## {goal}')
56 if not tasks:
57 results.append('-- Nothing to list --')
58
59 for task in tasks:
60 if(task.complete_date):
61 results.append(f' - [x] {task}')
62 else:
63 results.append(f' - [ ] {task}')
64 return results
65
66
67 class Data():
68 def __init__(self, db_file=None):
69 if not db_file:
70 db_file = os.path.join(os.environ.get('MATRIX_DATA_DIR', ''), 'goal.db')
71
72 self.file = db_file
73 self.engine = self.get_engine()
74
75
76 def get_engine(self):
77 return create_engine(f"sqlite:///{self.file}")
78
79 def setup(self):
80 SQLModel.metadata.create_all(self.engine)
81 return 'Success'
82
83
84 def _set_pref_goal_id(self, goal_id):
85 with Session(self.engine) as session:
86 prefs = session.exec(select(PreferGoal)).all()
87 for pref in prefs:
88 session.delete(pref)
89 pref = PreferGoal()
90 pref.goal_id = goal_id
91 session.add(pref)
92 session.commit()
93
94 def _get_pref_goal_id(self):
95 with Session(self.engine) as session:
96 pref = session.exec(select(PreferGoal)).one()
97 return pref.goal_id
98
99
100
101 def get_all_visions(self):
102 with Session(self.engine) as session:
103 cmd = select(Vision).where(Vision.complete_date == None)
104 return session.exec(cmd).all()
105
106 def get_all_goals(self):
107 '''List all goals'''
108 with Session(self.engine) as session:
109 cmd = select(Goal).where(Goal.complete_date == None)
110 return session.exec(cmd).all()
111
112
113 def get_done_goals(self):
114 '''List completed goals'''
115 with Session(self.engine) as session:
116 cmd = select(Goal).where(Goal.complete_date != None)
117 return session.exec(cmd).all()
118
119
120 def get_goal(self, goal_id):
121 self._set_pref_goal_id(goal_id)
122 with Session(self.engine) as session:
123 cmd = select(Goal).where(Goal.id == goal_id)
124 goal = session.exec(cmd).first()
125 return (goal, goal.tasks)
126
127 def get_vision(self, id):
128 with Session(self.engine) as session:
129 cmd = select(Vision).where(Vision.id == id)
130 vision = session.exec(cmd).first()
131 if vision:
132 return (vision, vision.goals)
133 else:
134 return ('Not found', [])
135
136
137 def complete_vision(self, id):
138 with Session(self.engine) as session:
139 cmd = select(Vision).where(Vision.id == id)
140 vision = session.exec(cmd).first()
141 vision.complete_date = dt.today()
142 session.commit()
143
144
145 def complete_goal(self, goal_id):
146 self._set_pref_goal_id(goal_id)
147 vision_id = -1
148 with Session(self.engine) as session:
149 cmd = select(Goal).where(Goal.id == goal_id)
150 goal = session.exec(cmd).first()
151 goal.complete_date = dt.today()
152 vision_id = goal.vision_id
153 session.commit()
154 return vision_id
155
156 def rename_goal(self, goal_id, name):
157 self._set_pref_goal_id(goal_id)
158 vision_id = -1
159 with Session(self.engine) as session:
160 cmd = select(Goal).where(Goal.id == goal_id)
161 goal = session.exec(cmd).first()
162 goal.name = name
163 vision_id = goal.vision_id
164 session.commit()
165 return vision_id
166
167
168 def complete_task(self, id):
169 with Session(self.engine) as session:
170 cmd = select(Task).where(Task.id == id)
171 task = session.exec(cmd).first()
172 task.complete_date = dt.today()
173 goal_id = task.goal_id
174 session.commit()
175 self._set_pref_goal_id(goal_id)
176 return goal_id
177
178 def add_with_name(self, cls, name):
179 id = -1
180 with Session(self.engine) as session:
181 new = cls(name=name)
182 session.add(new)
183 session.commit()
184 id = new.id
185 return id
186
187 def add_vision(self, name):
188 return self.add_with_name(Vision, name)
189
190 def add_goal(self, name):
191 goal_id = self.add_with_name(Goal, name)
192 self._set_pref_goal_id(goal_id)
193 return goal_id
194
195 def quick_add_task(self, name):
196 goal_id = self._get_pref_goal_id()
197 task_id = self.add_with_name(Task, name)
198 with Session(self.engine) as session:
199 cmd = select(Task).where(Task.id == task_id)
200 new = session.exec(cmd).first()
201 new.goal_id = goal_id
202 session.commit()
203 return goal_id
204
205 def remove_task(self, task_id):
206 task_name = ''
207 with Session(self.engine) as session:
208 cmd = select(Task).where(Task.id == task_id)
209 to_remove = session.exec(cmd).first()
210 task_name = to_remove.name
211 session.delete(to_remove)
212 session.commit()
213 return f'Removed task "{task_name}"'
214
215 def assign_vision(self, goal_id, vision_id):
216 '''Goals may move between visions'''
217 self._set_pref_goal_id(goal_id)
218 with Session(self.engine) as session:
219 cmd = select(Goal).where(Goal.id == goal_id)
220 goal = session.exec(cmd).first()
221 goal.vision_id = vision_id
222 session.commit()
223
224 def visionless(self):
225 '''Get goals with no vision'''
226 with Session(self.engine) as session:
227 cmd = select(Goal).where(Goal.vision_id == None)
228 return session.exec(cmd).all()
229
230
231 def add_note(self, note, goal):
232 '''Notes print with the goal.'''
233 pass
234
235 # Someday: Notes on each
236