]>
us-delaporte.pagekite.me Git - matrix-goal-bot.git/blob - matrix_goal_bot/db.py
9676cc3202c3679fb8a63cd46d95c216d811d4b2
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(f
' ## {vision}')
98 for item
in visions
[vision
]:
104 def __init__(self
, db_file
=None):
106 db_file
= os
.path
.join(os
.environ
.get('MATRIX_DATA_DIR', ''), 'goal.db')
109 self
.engine
= self
.get_engine()
112 def get_engine(self
):
113 return create_engine(f
"sqlite:///{self.file}")
116 SQLModel
.metadata
.create_all(self
.engine
)
120 with Session(self
.engine
) as session
:
121 session
.exec(text(''' alter table goal add start_date DATETIME; '''))
126 def _set_pref_goal_id(self
, goal_id
):
127 with Session(self
.engine
) as session
:
128 prefs
= session
.exec(select(PreferGoal
)).all()
133 pref
.goal_id
= goal_id
137 def _get_pref_goal_id(self
):
138 with Session(self
.engine
) as session
:
139 pref
= session
.exec(select(PreferGoal
)).one()
143 def clear(self
, goal_id
, clear_all
=False):
144 with Session(self
.engine
) as session
:
145 goal
= session
.exec(_get_with_id(Goal
, goal_id
)).first()
146 for item
in goal
.tasks
:
147 if clear_all
or item
.complete_date
:
151 def get_all_visions(self
):
152 with Session(self
.engine
) as session
:
153 cmd
= select(Vision
).where(Vision
.complete_date
== None)
154 return session
.exec(cmd
).all()
156 def get_all_goals(self
) -> List
[str]:
159 with Session(self
.engine
) as session
:
160 cmd
= select(Goal
).where(Goal
.complete_date
== None)
161 goals
= session
.exec(cmd
).all()
162 results
.append(_get_goals_by_vision(goals
))
166 def get_current_goals(self
):
167 '''List current goals'''
168 with Session(self
.engine
) as session
:
169 cmd
= select(Goal
).where(Goal
.complete_date
== None).where(Goal
.start_date
<= dt
.today())
170 goals
= session
.exec(cmd
).all()
171 logger
.debug(f
'Current goals: {goals}')
172 return _get_goals_by_vision(goals
)
174 def get_done_goals(self
):
175 '''List completed goals'''
176 with Session(self
.engine
) as session
:
177 cmd
= select(Goal
).where(Goal
.complete_date
!= None)
178 goals
= session
.exec(cmd
).all()
179 return _get_goals_by_vision(goals
)
181 def get_goal(self
, goal_id
):
182 self
._set
_pref
_goal
_id
(goal_id
)
183 with Session(self
.engine
) as session
:
184 cmd
= select(Goal
).where(Goal
.id == goal_id
)
185 goal
= session
.exec(cmd
).first()
186 return (goal
, goal
.tasks
)
188 def get_vision(self
, id):
189 with Session(self
.engine
) as session
:
190 cmd
= select(Vision
).where(Vision
.id == id)
191 vision
= session
.exec(cmd
).first()
193 return (vision
, vision
.goals
)
195 return ('Not found', [])
198 def complete_vision(self
, id):
199 with Session(self
.engine
) as session
:
200 cmd
= select(Vision
).where(Vision
.id == id)
201 vision
= session
.exec(cmd
).first()
202 vision
.complete_date
= dt
.today()
206 def complete_goal(self
, goal_id
):
208 with Session(self
.engine
) as session
:
209 cmd
= select(Goal
).where(Goal
.id == goal_id
)
210 goal
= session
.exec(cmd
).first()
211 goal
.complete_date
= dt
.today()
212 vision_id
= goal
.vision_id
214 cmd
= select(Vision
).where(Vision
.id == vision_id
)
218 vision
= session
.exec(cmd
).first()
220 win
.vision
= vision
.name
227 def put_off_goal(self
, goal_id
):
229 with Session(self
.engine
) as session
:
230 cmd
= select(Goal
).where(Goal
.id == goal_id
)
231 goal
= session
.exec(cmd
).first()
232 goal
.start_date
= dt
.today() + timedelta(days
=14)
233 vision_id
= goal
.vision_id
237 def start_goal(self
, goal_id
):
239 with Session(self
.engine
) as session
:
240 cmd
= select(Goal
).where(Goal
.id == goal_id
)
241 goal
= session
.exec(cmd
).first()
242 goal
.start_date
= dt
.today()
243 vision_id
= goal
.vision_id
246 return (vision
, vision
.goals
)
248 return ('No Vision Assigned', [])
251 def rename_goal(self
, goal_id
, name
):
252 self
._set
_pref
_goal
_id
(goal_id
)
254 with Session(self
.engine
) as session
:
255 cmd
= select(Goal
).where(Goal
.id == goal_id
)
256 goal
= session
.exec(cmd
).first()
258 vision_id
= goal
.vision_id
263 def complete_task(self
, id):
264 with Session(self
.engine
) as session
:
265 cmd
= select(Task
).where(Task
.id == id)
266 task
= session
.exec(cmd
).first()
267 task
.complete_date
= dt
.today()
268 goal_id
= task
.goal_id
270 self
._set
_pref
_goal
_id
(goal_id
)
273 def add_with_name(self
, cls
, name
):
275 with Session(self
.engine
) as session
:
282 def add_vision(self
, name
):
283 return self
.add_with_name(Vision
, name
)
285 def add_goal(self
, name
):
286 goal_id
= self
.add_with_name(Goal
, name
)
287 self
._set
_pref
_goal
_id
(goal_id
)
290 def quick_add_task(self
, name
):
291 goal_id
= self
._get
_pref
_goal
_id
()
292 task_id
= self
.add_with_name(Task
, name
)
293 with Session(self
.engine
) as session
:
294 cmd
= select(Task
).where(Task
.id == task_id
)
295 new
= session
.exec(cmd
).first()
296 new
.goal_id
= goal_id
300 def remove_task(self
, task_id
):
302 logger
.debug(f
'Removing task with id {task_id}')
303 with Session(self
.engine
) as session
:
304 cmd
= select(Task
).where(Task
.id == int(task_id
))
305 to_remove
= session
.exec(cmd
).first()
307 return f
'Unable to find task with id {task_id}'
309 logger
.debug(f
'Removing task with name {to_remove.name}')
310 task_name
= to_remove
.name
311 session
.delete(to_remove
)
313 return f
'Removed task "{task_name}"'
315 def assign_vision(self
, goal_id
, vision_id
):
316 '''Goals may move between visions'''
317 self
._set
_pref
_goal
_id
(goal_id
)
318 with Session(self
.engine
) as session
:
319 cmd
= select(Goal
).where(Goal
.id == goal_id
)
320 goal
= session
.exec(cmd
).first()
321 goal
.vision_id
= vision_id
325 def visionless(self
):
326 '''Get goals with no vision'''
327 with Session(self
.engine
) as session
:
328 cmd
= select(Goal
).where(Goal
.vision_id
== None).where(Goal
.complete_date
== None)
329 return session
.exec(cmd
).all()
332 def add_note(self
, note
, goal
):
333 '''Notes print with the goal.'''
339 with Session(self
.engine
) as session
:
340 results
= session
.exec(select(Win
)).all()
343 # Someday: Notes on each