]>
us-delaporte.pagekite.me Git - matrix-goal-bot.git/blob - matrix_goal_bot/db.py
3 from datetime
import datetime
as dt
4 from datetime
import timedelta
5 from typing
import List
7 from sqlmodel
import Field
, Session
, SQLModel
, create_engine
, select
, text
, Relationship
9 logger
= logging
.getLogger(__name__
)
11 DATE_FORMAT
= '%Y-%m-%d'
14 return dt
.now().strftime(DATE_FORMAT
)
17 class Vision(SQLModel
, table
=True):
18 id: int |
None = Field(default
=None, primary_key
=True)
19 name
: str = Field(default
=None, unique
=True)
20 complete_date
: dt |
None = Field(default
=None)
21 goals
: list["Goal"] = Relationship(back_populates
="vision")
23 return f
'{self.name} (Vision {self.id})'
26 class PreferGoal(SQLModel
, table
=True):
27 goal_id
: int |
None = Field(default
=None, foreign_key
="goal.id", primary_key
=True)
30 class Goal(SQLModel
, table
=True):
31 id: int |
None = Field(default
=None, primary_key
=True)
32 name
: str = Field(default
=None, unique
=True)
33 start_date
: dt |
None = Field(default
=dt
.today())
34 complete_date
: dt |
None = Field(default
=None)
35 vision_id
: int |
None = Field(default
=None, foreign_key
="vision.id")
36 notes
: str |
None = Field(default
=None)
37 tasks
: list["Task"] = Relationship(back_populates
="goal")
38 vision
: Vision
= Relationship(back_populates
="goals")
40 if not self
.complete_date
:
41 return f
'{self.name} (Goal {self.id})'
43 completed
= self
.complete_date
.strftime(DATE_FORMAT
)
44 return f
'(Done {completed}) {self.name} (Goal {self.id})'
47 class Task(SQLModel
, table
=True):
48 id: int |
None = Field(default
=None, primary_key
=True)
49 name
: str = Field(default
=None, unique
=True)
50 goal_id
: int |
None = Field(default
=None, foreign_key
="goal.id")
51 complete_date
: dt |
None = Field(default
=None)
52 goal
: Goal
= Relationship(back_populates
="tasks")
54 return f
'{self.name} ({self.id})'
57 class Win(SQLModel
, table
=True):
58 id: int |
None = Field(default
=None, primary_key
=True)
59 goal
: str = Field(default
=None, unique
=False)
60 vision
: str |
None = Field(default
=None, unique
=False)
61 complete_date
: dt |
None = Field(default
=dt
.today())
63 completed
= self
.complete_date
.strftime(DATE_FORMAT
)
64 return f
'{self.goal} ({completed} {self.vision})'
66 def pretty_print(goal
, tasks
):
68 results
.append(f
' ## {goal}')
70 results
.append('-- Nothing to list --')
73 if(task
.complete_date
):
74 results
.append(f
' - [x] {task}')
76 results
.append(f
' - [ ] {task}')
80 def _get_with_id(cls
, item_id
):
81 return select(cls
).where(cls
.id == item_id
)
83 def _get_with_name(cls
, name
):
84 return select(cls
).where(func
.lower(cls
.name
) == func
.lower(name
))
87 def _get_goals_by_vision(goals
) -> List
[str]:
92 vision
= str(goal
.vision
)
93 if not vision
in visions
:
95 visions
[vision
].append(str(goal
))
96 for vision
in visions
:
97 results
.append('') # Make some space
98 results
.append(f
'## {vision}')
99 for item
in visions
[vision
]:
100 results
.append(' + ' + item
)
105 def __init__(self
, db_file
=None):
107 db_file
= os
.path
.join(os
.environ
.get('MATRIX_DATA_DIR', ''), 'goal.db')
110 self
.engine
= self
.get_engine()
113 def get_engine(self
):
114 return create_engine(f
"sqlite:///{self.file}")
117 SQLModel
.metadata
.create_all(self
.engine
)
121 with Session(self
.engine
) as session
:
122 session
.exec(text(''' alter table goal add start_date DATETIME; '''))
127 def _set_pref_goal_id(self
, goal_id
):
128 with Session(self
.engine
) as session
:
129 prefs
= session
.exec(select(PreferGoal
)).all()
134 pref
.goal_id
= goal_id
138 def _get_pref_goal_id(self
):
139 with Session(self
.engine
) as session
:
140 pref
= session
.exec(select(PreferGoal
)).one()
144 def clear(self
, goal_id
, clear_all
=False):
145 with Session(self
.engine
) as session
:
146 goal
= session
.exec(_get_with_id(Goal
, goal_id
)).first()
147 for item
in goal
.tasks
:
148 if clear_all
or item
.complete_date
:
152 def get_all_visions(self
):
153 with Session(self
.engine
) as session
:
154 cmd
= select(Vision
).where(Vision
.complete_date
== None)
155 return session
.exec(cmd
).all()
157 def get_all_goals(self
) -> List
[str]:
160 with Session(self
.engine
) as session
:
161 cmd
= select(Goal
).where(Goal
.complete_date
== None)
162 goals
= session
.exec(cmd
).all()
163 results
.append(_get_goals_by_vision(goals
))
167 def get_current_goals(self
):
168 '''List current goals'''
169 with Session(self
.engine
) as session
:
170 cmd
= select(Goal
).where(Goal
.complete_date
== None).where(Goal
.start_date
<= dt
.today())
171 goals
= session
.exec(cmd
).all()
172 logger
.debug(f
'Current goals: {goals}')
173 return _get_goals_by_vision(goals
)
175 def get_done_goals(self
):
176 '''List completed goals'''
177 with Session(self
.engine
) as session
:
178 cmd
= select(Goal
).where(Goal
.complete_date
!= None)
179 goals
= session
.exec(cmd
).all()
180 return _get_goals_by_vision(goals
)
182 def get_goal(self
, goal_id
):
183 self
._set
_pref
_goal
_id
(goal_id
)
184 with Session(self
.engine
) as session
:
185 cmd
= select(Goal
).where(Goal
.id == goal_id
)
186 goal
= session
.exec(cmd
).first()
187 return (goal
, goal
.tasks
)
189 def get_vision(self
, id):
190 with Session(self
.engine
) as session
:
191 cmd
= select(Vision
).where(Vision
.id == id)
192 vision
= session
.exec(cmd
).first()
194 return (vision
, vision
.goals
)
196 return ('Not found', [])
199 def complete_vision(self
, id):
200 with Session(self
.engine
) as session
:
201 cmd
= select(Vision
).where(Vision
.id == id)
202 vision
= session
.exec(cmd
).first()
203 vision
.complete_date
= dt
.today()
207 def complete_goal(self
, goal_id
):
209 with Session(self
.engine
) as session
:
210 cmd
= select(Goal
).where(Goal
.id == goal_id
)
211 goal
= session
.exec(cmd
).first()
212 goal
.complete_date
= dt
.today()
213 vision_id
= goal
.vision_id
215 cmd
= select(Vision
).where(Vision
.id == vision_id
)
219 vision
= session
.exec(cmd
).first()
221 win
.vision
= vision
.name
228 def put_off_vision(self
, vision_id
):
229 with Session(self
.engine
) as session
:
230 # vision = session.exec(cmd).first()
231 cmd
= select(Goal
).where(Goal
.vision_id
== vision_id
)
232 goals
= session
.exec(cmd
).all()
234 goal
.start_date
= dt
.today() + timedelta(days
=14)
238 def start_goal(self
, goal_id
):
240 with Session(self
.engine
) as session
:
241 cmd
= select(Goal
).where(Goal
.id == goal_id
)
242 goal
= session
.exec(cmd
).first()
243 goal
.start_date
= dt
.today()
244 vision_id
= goal
.vision_id
247 return (vision
, vision
.goals
)
249 return ('No Vision Assigned', [])
252 def rename_goal(self
, goal_id
, name
):
253 self
._set
_pref
_goal
_id
(goal_id
)
255 with Session(self
.engine
) as session
:
256 cmd
= select(Goal
).where(Goal
.id == goal_id
)
257 goal
= session
.exec(cmd
).first()
259 vision_id
= goal
.vision_id
264 def complete_task(self
, id):
265 with Session(self
.engine
) as session
:
266 cmd
= select(Task
).where(Task
.id == id)
267 task
= session
.exec(cmd
).first()
268 task
.complete_date
= dt
.today()
269 goal_id
= task
.goal_id
271 self
._set
_pref
_goal
_id
(goal_id
)
274 def add_with_name(self
, cls
, name
):
276 with Session(self
.engine
) as session
:
283 def add_vision(self
, name
):
284 return self
.add_with_name(Vision
, name
)
286 def add_goal(self
, name
):
287 goal_id
= self
.add_with_name(Goal
, name
)
288 self
._set
_pref
_goal
_id
(goal_id
)
291 def quick_add_task(self
, name
):
292 goal_id
= self
._get
_pref
_goal
_id
()
293 task_id
= self
.add_with_name(Task
, name
)
294 with Session(self
.engine
) as session
:
295 cmd
= select(Task
).where(Task
.id == task_id
)
296 new
= session
.exec(cmd
).first()
297 new
.goal_id
= goal_id
301 def remove_task(self
, task_id
):
303 logger
.debug(f
'Removing task with id {task_id}')
304 with Session(self
.engine
) as session
:
305 cmd
= select(Task
).where(Task
.id == int(task_id
))
306 to_remove
= session
.exec(cmd
).first()
308 return f
'Unable to find task with id {task_id}'
310 logger
.debug(f
'Removing task with name {to_remove.name}')
311 task_name
= to_remove
.name
312 session
.delete(to_remove
)
314 return f
'Removed task "{task_name}"'
316 def assign_vision(self
, goal_id
, vision_id
):
317 '''Goals may move between visions'''
318 self
._set
_pref
_goal
_id
(goal_id
)
319 with Session(self
.engine
) as session
:
320 cmd
= select(Goal
).where(Goal
.id == goal_id
)
321 goal
= session
.exec(cmd
).first()
322 goal
.vision_id
= vision_id
326 def visionless(self
):
327 '''Get goals with no vision'''
328 with Session(self
.engine
) as session
:
329 cmd
= select(Goal
).where(Goal
.vision_id
== None).where(Goal
.complete_date
== None)
330 return session
.exec(cmd
).all()
333 def add_note(self
, note
, goal
):
334 '''Notes print with the goal.'''
340 with Session(self
.engine
) as session
:
341 results
= session
.exec(select(Win
)).all()
344 # Someday: Notes on each