]> Softwares of Agnibho - librevax.git/blob - librevax.py
Optional personnel id
[librevax.git] / librevax.py
1 # LibreVax
2 # Copyright (C) 2024 Dr. Agnibho Mondal
3 # This file is part of LibreVax.
4 # LibreVax is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 # LibreVax is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
6 # You should have received a copy of the GNU General Public License along with LibreVax. If not, see <https://www.gnu.org/licenses/>.
7
8 from flask import Flask, render_template, request, session, redirect, g
9 from urllib.parse import urlencode
10 from datetime import datetime
11 import json, sqlite3
12 import advice, auth, inventory, multicenter, patient, personnel, transaction, vaccination
13
14 from config import cid
15
16 app=Flask(__name__)
17 app.config.from_file("config/config.json", load=json.load)
18
19 @app.before_request
20 def preload():
21 g.user=session.get("user", None)
22 g.mid=session.get("mid", None)
23 g.center=session.get("center", None)
24 g.enable_delete=app.config.get("ENABLE_DELETE", False)
25
26 @app.route("/")
27 def index():
28 try:
29 if((ret:=problem())!="go"):
30 return ret
31 cursor=get_db().cursor()
32 (ok, mc)=multicenter.read(cursor, session["mid"])
33 if(not ok):
34 raise exception(mc)
35 (ok, pat)=patient.list(cursor)
36 if(not ok):
37 raise exception(pat)
38 return render_template("index.html", center=mc, patient=pat)
39 except Exception as e:
40 raise(e)
41 return render_template("error.html", data=e)
42
43 @app.get("/login")
44 def login_get(error=False):
45 try:
46 cursor=get_db().cursor()
47 (ok, data)=multicenter.list(cursor)
48 if(not ok):
49 raise exception(data)
50 if(len(data)<=0):
51 data.append("")
52 return render_template("login.html", data=data, error=error)
53 except Exception as e:
54 return render_template("error.html", data=e)
55
56 @app.post("/login")
57 def login_post():
58 cursor=get_db().cursor()
59 if(auth.login(cursor, request.form["user"], request.form["password"], request.form["center"])):
60 return redirect("/")
61 else:
62 return login_get(True)
63
64 @app.route("/logout")
65 def logout():
66 auth.logout()
67 return redirect("/login")
68
69 @app.get("/admin")
70 def admin(msg=None):
71 cursor=get_db().cursor()
72 (ok, mc)=multicenter.list(cursor)
73 if(not ok):
74 raise Exception(mc)
75 users=auth.list(cursor)
76 return render_template("admin.html", users=users, center=mc, msg=msg)
77
78 @app.post("/newuser")
79 def newuser():
80 try:
81 cursor=get_db().cursor()
82 if(auth.new(cursor, request.form["user"], request.form["pwd"])):
83 return admin(msg="New user added")
84 else:
85 return admin(msg="Failed to add")
86 except Exception as e:
87 raise(e)
88 return render_template("error.html", data=e)
89
90 @app.post("/changepass")
91 def changepass():
92 try:
93 cursor=get_db().cursor()
94 if("user" in request.form.keys()):
95 if(auth.change(cursor, request.form["user"], request.form["new"])):
96 return admin(msg="Password changed")
97 else:
98 return admin(msg="Incorrect Password")
99 elif(request.form["new"]==request.form["check"]):
100 user=request.form.get("user", session["user"])
101 if(auth.change(cursor, user, request.form["new"], request.form["old"])):
102 return admin(msg="Password changed")
103 else:
104 return admin(msg="Incorrect Password")
105 else:
106 return admin(msg="Failed to change password")
107 except Exception as e:
108 raise(e)
109 return render_template("error.html", data=e)
110
111 @app.post("/switchcenter")
112 def switchcenter():
113 try:
114 cursor=get_db().cursor()
115 if(auth.switch(cursor, request.form)):
116 return admin(msg="Switched center to "+g.center)
117 else:
118 raise Exception("Failed to switch")
119 except Exception as e:
120 raise(e)
121 return render_template("error.html", data=e)
122
123 @app.get("/center/<action>")
124 @app.get("/center/<action>/<mid>")
125 def center_view(action, mid=None):
126 if((ret:=problem())!="go"):
127 return ret
128 try:
129 cursor=get_db().cursor()
130 if(action=="list"):
131 (ok, data)=multicenter.list(cursor)
132 if(not ok):
133 raise exception(data)
134 return render_template("multicenter-view.html", data=data, action=action)
135 elif(action=="view"):
136 if(mid is not None):
137 (ok, data)=multicenter.read(cursor, mid)
138 if(not ok):
139 raise Exception(data)
140 (ok, invt)=inventory.list(cursor, mid)
141 if(not ok):
142 raise Exception(invt)
143 (ok, pers)=personnel.list(cursor, mid)
144 if(not ok):
145 raise Exception(pers)
146 return render_template("multicenter-view.html", data=data, inventory=invt, personnel=pers, action=action)
147 else:
148 raise Exception("Invalid parameter")
149 elif(action=="edit"):
150 if(mid is not None):
151 (ok, data)=multicenter.read(cursor, mid)
152 if(not ok):
153 raise Exception(data)
154 return render_template("multicenter-edit.html", data=data, action=action)
155 else:
156 raise Exception("Invalid parameter")
157 elif(action=="new"):
158 return render_template("multicenter-edit.html", data=[], action=action)
159 except Exception as e:
160 raise(e)
161 return render_template("error.html", data=e)
162
163 @app.get("/personnel/<action>")
164 @app.get("/personnel/<action>/<sid>")
165 def personnel_view(action, sid=None):
166 if((ret:=problem())!="go"):
167 return ret
168 try:
169 cursor=get_db().cursor()
170 if(action=="list"):
171 (ok, data)=personnel.list(cursor, g.mid)
172 if(not ok):
173 raise exception(data)
174 return render_template("personnel-view.html", data=data, action=action)
175 elif(action=="view"):
176 if(sid is not None):
177 (ok, data)=personnel.read(cursor, sid)
178 if(not ok):
179 raise Exception(data)
180 return render_template("personnel-view.html", data=data, action=action)
181 else:
182 raise Exception("Invalid parameter")
183 elif(action=="edit"):
184 if(sid is not None):
185 (ok, data)=personnel.read(cursor, sid)
186 if(not ok):
187 raise Exception(data)
188 (ok, center)=multicenter.list(cursor)
189 if(not ok):
190 raise Exception(center)
191 return render_template("personnel-edit.html", data=data, center=center, action=action)
192 else:
193 raise Exception("Invalid parameter")
194 elif(action=="new"):
195 (ok, center)=multicenter.list(cursor)
196 if(not ok):
197 raise Exception(center)
198 return render_template("personnel-edit.html", data=[], center=center, action=action)
199 except Exception as e:
200 raise(e)
201 return render_template("error.html", data=e)
202
203 @app.post("/personnel/new")
204 @app.post("/personnel/edit/<sid>")
205 def personnel_edit(sid=None):
206 if((ret:=problem())!="go"):
207 return ret
208 try:
209 cursor=get_db().cursor()
210 if(sid is None):
211 active="active" in request.form.keys()
212 (ok, data)=personnel.create(cursor, request.form, active)
213 if(not ok):
214 raise Exception(data)
215 sid=data
216 else:
217 active="active" in request.form.keys()
218 (ok, data)=personnel.update(cursor, sid, request.form, active)
219 if(not ok):
220 raise Exception(data)
221 return redirect("/personnel/view/"+str(sid))
222 except Exception as e:
223 return render_template("error.html", data=e)
224
225 @app.post("/center/new")
226 @app.post("/center/edit/<mid>")
227 def center_edit(mid=None):
228 if((ret:=problem())!="go"):
229 return ret
230 try:
231 cursor=get_db().cursor()
232 if(mid is None):
233 (ok, data)=multicenter.create(cursor, request.form)
234 if(not ok):
235 raise Exception(data)
236 mid=data
237 else:
238 (ok, data)=multicenter.update(cursor, mid, request.form)
239 if(not ok):
240 raise Exception(data)
241 return redirect("/center/view/"+str(mid))
242 except Exception as e:
243 return render_template("error.html", data=e)
244
245 @app.get("/inventory/<action>")
246 @app.get("/inventory/<action>/<id>")
247 def inventory_view(action, id=None):
248 if((ret:=problem())!="go"):
249 return ret
250 try:
251 cursor=get_db().cursor()
252 if(action=="list"):
253 if(id is not None):
254 (ok, data)=inventory.list(cursor, id)
255 if(not ok):
256 raise exception(data)
257 (ok, center)=multicenter.read(cursor, id)
258 if(not ok):
259 raise exception(center)
260 return render_template("inventory-view.html", data=data, center=center, action=action)
261 else:
262 raise Exception("Invalid parameter")
263 elif(action=="view"):
264 if(id is not None):
265 (ok, data)=inventory.read(cursor, id)
266 if(not ok):
267 raise Exception(data)
268 return render_template("inventory-view.html", data=data, action=action)
269 else:
270 raise Exception("Invalid parameter")
271 elif(action=="edit"):
272 if(id is not None):
273 (ok, data)=inventory.read(cursor, id)
274 if(not ok):
275 raise Exception(data)
276 return render_template("inventory-edit.html", data=data, mid=data["mid"], action=action)
277 else:
278 raise Exception("Invalid parameter")
279 elif(action=="new"):
280 if(id is not None):
281 (ok, center)=multicenter.list(cursor)
282 if(not ok):
283 raise Exception(center)
284 return render_template("inventory-edit.html", data=[], mid=id, action=action, center=center)
285 else:
286 raise Exception("Invalid parameter")
287 except Exception as e:
288 raise(e)
289 return render_template("error.html", data=e)
290
291 @app.post("/inventory/new/<mid>")
292 @app.post("/inventory/edit/<iid>")
293 def inventory_edit(mid=None, iid=None):
294 if((ret:=problem())!="go"):
295 return ret
296 try:
297 cursor=get_db().cursor()
298 if(iid is None):
299 (ok, data)=inventory.create(cursor, request.form)
300 if(not ok):
301 raise Exception(data)
302 iid=data
303 else:
304 (ok, data)=inventory.update(cursor, iid, request.form)
305 if(not ok):
306 raise Exception(data)
307 return redirect("/inventory/view/"+str(iid))
308 except Exception as e:
309 raise(e)
310 return render_template("error.html", data=e)
311
312 @app.get("/patient/<action>")
313 @app.get("/patient/<action>/<pid>")
314 def patient_view(action, pid=None):
315 if((ret:=problem())!="go"):
316 return ret
317 try:
318 cursor=get_db().cursor()
319 if(action=="list"):
320 try:
321 page=int(request.args["page"])
322 except Exception:
323 page=1
324 if(request.args.get("all", False)):
325 (ok, data)=patient.list(cursor, request.args, g.mid)
326 else:
327 (ok, data)=patient.list(cursor, request.args)
328 if(ok):
329 param=dict(request.args)
330 param.pop("page", None)
331 return render_template("patient-list.html", num=app.config["LIST_LENGTH"], data=data, page=page, args=request.args, param=urlencode(param))
332 else:
333 raise Exception(data)
334 elif(action=="view"):
335 if(pid is not None):
336 (ok, data)=patient.read(cursor, pid)
337 if(not ok):
338 raise Exception(data)
339 (ok, vac)=vaccination.list_by_patient(cursor, pid)
340 if(not ok):
341 raise Exception(vac)
342 (ok, adv)=advice.list(cursor, pid)
343 if(not ok):
344 raise Exception(adv)
345
346 return render_template("patient-view.html", data=data, vaccination=vac, advice=adv, action=action)
347 else:
348 raise Exception("Invalid parameter")
349 elif(action=="edit"):
350 if(pid is not None):
351 (ok, data)=patient.read(cursor, pid)
352 if(not ok):
353 raise Exception(data)
354 (ok, center)=multicenter.list(cursor)
355 if(not ok):
356 raise exception(center)
357 return render_template("patient-edit.html", data=data, center=center, action=action)
358 else:
359 raise Exception("Invalid parameter")
360 elif(action=="new"):
361 (ok, last)=patient.list(cursor)
362 if(not ok):
363 raise exception(last)
364 data={"cid": cid.new(last)}
365 (ok, center)=multicenter.list(cursor)
366 if(not ok):
367 raise exception(center)
368 return render_template("patient-edit.html", data=data, center=center, action=action)
369 except Exception as e:
370 raise (e)
371 return render_template("error.html", data=e)
372
373 @app.post("/patient/new")
374 @app.post("/patient/edit/<pid>")
375 def patient_edit(pid=None):
376 if((ret:=problem())!="go"):
377 return ret
378 try:
379 cursor=get_db().cursor()
380 if(pid is None):
381 (ok, data)=patient.create(cursor, request.form)
382 if(not ok):
383 raise Exception(data)
384 pid=data
385 else:
386 (ok, data)=patient.update(cursor, pid, request.form)
387 if(not ok):
388 raise Exception(data)
389 return redirect("/patient/view/"+str(pid))
390 except Exception as e:
391 return render_template("error.html", data=e)
392
393 @app.get("/note/<pid>")
394 def note_get(pid):
395 if((ret:=problem())!="go"):
396 return ret
397 try:
398 cursor=get_db().cursor()
399 (ok, data)=patient.read(cursor, pid)
400 if(ok):
401 return render_template("note.html", data=data)
402 else:
403 return render_template("error.html", data=data)
404 except Exception as e:
405 raise(e)
406 return render_template("error.html", data=e)
407
408 @app.post("/note/<pid>")
409 def note_post(pid):
410 if((ret:=problem())!="go"):
411 return ret
412 try:
413 cursor=get_db().cursor()
414 (ok, data)=patient.note(cursor, pid, request.form)
415 if(not ok):
416 return render_template("error.html", data=data)
417 return redirect("/patient/view/"+str(pid))
418 except Exception as e:
419 raise(e)
420 return render_template("error.html", data=e)
421
422 @app.get("/vaccination/<action>")
423 @app.get("/vaccination/<action>/<id>")
424 def vaccination_view(action, id=None):
425 if((ret:=problem())!="go"):
426 return ret
427 try:
428 cursor=get_db().cursor()
429 if(action=="list"):
430 if(id is not None):
431 (ok, data)=vaccination.list_by_patient(cursor, id)
432 if(not ok):
433 raise exception(data)
434 (ok, pat)=patient.read(cursor, data["pid"])
435 if(not ok):
436 raise exception(patient)
437 (ok, inv)=inventory.list(cursor, data["iid"])
438 if(not ok):
439 raise exception(inventory)
440 return render_template("vaccination-view.html", data=data, patient=pat, inventory=inv, action=action)
441 else:
442 raise Exception("Invalid parameter")
443 elif(action=="view"):
444 if(id is not None):
445 (ok, data)=vaccination.read(cursor, id)
446 if(not ok):
447 raise Exception(data)
448 (ok, inv)=inventory.read(cursor, data["iid"])
449 if(not ok):
450 raise Exception(inventory)
451 (ok, pat)=patient.read(cursor, data["pid"])
452 if(not ok):
453 raise Exception(patient)
454 (ok, consultant)=personnel.read(cursor, data["consultant"])
455 if(not ok):
456 raise Exception(consultant)
457 (ok, vaccinator)=personnel.read(cursor, data["vaccinator"])
458 if(not ok):
459 raise Exception(vaccinator)
460 return render_template("vaccination-view.html", data=data, inventory=inv, patient=pat, consultant=consultant, vaccinator=vaccinator, action=action)
461 else:
462 raise Exception("Invalid parameter")
463 elif(action=="edit"):
464 if(id is not None):
465 (ok, data)=vaccination.read(cursor, g.mid)
466 if(not ok):
467 raise Exception(data)
468 (ok, inv)=inventory.list(cursor, g.mid)
469 if(not ok):
470 raise Exception(inv)
471 (ok, consultant)=personnel.list(cursor, g.mid, "consultant")
472 if(not ok):
473 raise Exception(consultant)
474 (ok, vaccinator)=personnel.list(cursor, g.mid, "vaccinator")
475 if(not ok):
476 raise Exception(vaccinator)
477 return render_template("vaccination-edit.html", data=data, inventory=inv, consultant=consultant, vaccinator=vaccinator, action=action)
478 else:
479 raise Exception("Invalid parameter")
480 elif(action=="new"):
481 if(id is not None):
482 (ok, inv)=inventory.list(cursor, g.mid)
483 if(not ok):
484 raise Exception(inv)
485 (ok, consultant)=personnel.list(cursor, g.mid, "consultant")
486 if(not ok):
487 raise Exception(consultant)
488 (ok, vaccinator)=personnel.list(cursor, g.mid, "vaccinator")
489 if(not ok):
490 raise Exception(vaccinator)
491 data={"pid": id, "date":datetime.now().strftime("%Y-%m-%dT%H:%M:%S")}
492 if(len(inv)<=0):
493 raise Exception("Please add a vaccine to inventory before vaccination.")
494 return render_template("vaccination-edit.html", data=data, inventory=inv, consultant=consultant, vaccinator=vaccinator, action=action)
495 else:
496 raise Exception("Invalid parameter")
497 except Exception as e:
498 raise(e)
499 return render_template("error.html", data=e)
500
501 @app.post("/vaccination/new/<pid>")
502 @app.post("/vaccination/edit/<vid>")
503 def vaccination_edit(vid=None, pid=None):
504 if((ret:=problem())!="go"):
505 return ret
506 try:
507 cursor=get_db().cursor()
508 if(vid is None):
509 given="given" in request.form.keys()
510 (ok, data)=vaccination.create(cursor, request.form, given)
511 if(not ok):
512 raise Exception(data)
513 vid=data
514 else:
515 given="given" in request.form.keys()
516 (ok, data)=vaccination.update(cursor, vid, request.form, given)
517 if(not ok):
518 raise Exception(data)
519 return redirect("/vaccination/view/"+str(vid))
520 except Exception as e:
521 raise(e)
522 return render_template("error.html", data=e)
523
524
525 @app.get("/advice/<action>")
526 @app.get("/advice/<action>/<id>")
527 def advice_view(action, id=None):
528 if((ret:=problem())!="go"):
529 return ret
530 try:
531 cursor=get_db().cursor()
532 if(action=="list"):
533 if(id is not None):
534 (ok, data)=advice.list(cursor, id)
535 if(not ok):
536 raise exception(data)
537 (ok, pat)=patient.read(cursor, id)
538 if(not ok):
539 raise exception(patient)
540 return render_template("advice-view.html", data=data, patient=pat, action=action)
541 else:
542 raise Exception("Invalid parameter")
543 elif(action=="view"):
544 if(id is not None):
545 (ok, data)=advice.read(cursor, id)
546 if(not ok):
547 raise Exception(data)
548 (ok, pat)=patient.read(cursor, data["pid"])
549 if(not ok):
550 raise Exception(pat)
551 (ok, consultant)=personnel.read(cursor, data["consultant"])
552 if(not ok):
553 raise Exception(consultant)
554 return render_template("advice-view.html", data=data, patient=pat, consultant=consultant, action=action)
555 else:
556 raise Exception("Invalid parameter")
557 elif(action=="edit"):
558 if(id is not None):
559 (ok, data)=advice.read(cursor, g.mid)
560 if(not ok):
561 raise Exception(data)
562 (ok, consultant)=personnel.list(cursor, g.mid, "consultant")
563 if(not ok):
564 raise Exception(consultant)
565 return render_template("advice-edit.html", data=data, consultant=consultant, action=action)
566 else:
567 raise Exception("Invalid parameter")
568 elif(action=="new"):
569 if(id is not None):
570 (ok, consultant)=personnel.list(cursor, g.mid, "consultant")
571 if(not ok):
572 raise Exception(consultant)
573 data={"pid": id, "date":datetime.now().strftime("%Y-%m-%dT%H:%M:%S")}
574 return render_template("advice-edit.html", data=data, consultant=consultant, action=action)
575 else:
576 raise Exception("Invalid parameter")
577 except Exception as e:
578 raise(e)
579 return render_template("error.html", data=e)
580
581 @app.post("/advice/new/<pid>")
582 @app.post("/advice/edit/<aid>")
583 def advice_edit(aid=None, pid=None):
584 if((ret:=problem())!="go"):
585 return ret
586 try:
587 cursor=get_db().cursor()
588 if(aid is None):
589 (ok, data)=advice.create(cursor, request.form, pid)
590 if(not ok):
591 raise Exception(data)
592 aid=data
593 else:
594 (ok, data)=advice.update(cursor, aid, request.form)
595 if(not ok):
596 raise Exception(data)
597 return redirect("/advice/view/"+str(aid))
598 except Exception as e:
599 raise(e)
600 return render_template("error.html", data=e)
601
602 @app.get("/delete/<cat>/<id>")
603 def delete(cat, id):
604 if((ret:=problem())!="go"):
605 return ret
606 try:
607 if(not g.enable_delete):
608 raise Exception("Deleting record is not allowed.")
609 cursor=get_db().cursor()
610 if(cat=="advice"):
611 (ok, data)=advice.delete(cursor, id)
612 if(not ok):
613 return render_template("error.html", data=data)
614 elif(cat=="inventory"):
615 (ok, data)=inventory.delete(cursor, id)
616 if(not ok):
617 return render_template("error.html", data=data)
618 elif(cat=="center"):
619 (ok, data)=multicenter.delete(cursor, id)
620 if(not ok):
621 return render_template("error.html", data=data)
622 elif(cat=="patient"):
623 (ok, data)=patient.delete(cursor, id)
624 if(not ok):
625 return render_template("error.html", data=data)
626 elif(cat=="personnel"):
627 (ok, data)=personnel.delete(cursor, id)
628 if(not ok):
629 return render_template("error.html", data=data)
630 elif(cat=="transaction"):
631 (ok, data)=transaction.delete(cursor, id)
632 if(not ok):
633 return render_template("error.html", data=data)
634 elif(cat=="vaccination"):
635 (ok, data)=vaccination.delete(cursor, id)
636 if(not ok):
637 return render_template("error.html", data=data)
638 return redirect("/")
639 except Exception as e:
640 raise(e)
641 return render_template("error.html", data=e)
642
643 @app.route("/card/<pid>")
644 def card(pid):
645 if((ret:=problem())!="go"):
646 return ret
647 try:
648 cursor=get_db().cursor()
649 (ok, data)=patient.read(cursor, pid)
650 if(not ok):
651 raise Exception(data)
652 (ok, vac)=vaccination.list_by_patient(cursor, pid)
653 if(not ok):
654 raise Exception(vac)
655 (ok, adv)=advice.list(cursor, pid)
656 if(not ok):
657 raise Exception(adv)
658 (ok, center)=multicenter.read(cursor, g.mid)
659 if(not ok):
660 raise Exception(center)
661 return render_template("card.html", data=data, vaccination=vac, advice=adv, center=center)
662 except Exception as e:
663 raise(e)
664 return render_template("error.html", data=e)
665
666 @app.route("/report/<mid>")
667 def report(mid):
668 if((ret:=problem())!="go"):
669 return ret
670 try:
671 date=request.args.get("date", datetime.now().strftime("%Y-%m-%d"))
672 cursor=get_db().cursor()
673 (ok, data)=vaccination.list_by_date(cursor, date)
674 if(not ok):
675 raise Exception(data)
676 (ok, center)=multicenter.read(cursor, g.mid)
677 if(not ok):
678 raise Exception(center)
679 return render_template("report.html", data=data, center=center, date=date)
680 except Exception as e:
681 raise(e)
682 return render_template("error.html", data=e)
683
684
685 def get_db():
686 db=getattr(g, "_database", None)
687 if db is None:
688 db=g._database=sqlite3.connect("data/database.db", isolation_level=None)
689 db.row_factory=sqlite3.Row
690 return db
691
692 @app.teardown_appcontext
693 def close_connection(exception):
694 db=getattr(g, "_database", None)
695 if db is not None:
696 db.close()
697
698 def problem(access=""):
699 if(auth.access()==auth.auth.ALL):
700 return "go"
701 else:
702 return redirect("/login")
703
704 @app.template_filter("format_date")
705 def format_date(date):
706 try:
707 if("T" in date):
708 dt=datetime.strptime(date, "%Y-%m-%dT%H:%M:%S")
709 return dt.strftime("%b %d, %Y, %I:%M %p")
710 else:
711 dt=datetime.strptime(date, "%Y-%m-%d")
712 return dt.strftime("%b %d, %Y")
713 except Exception:
714 return date
715
716 def init_db():
717 with app.app_context():
718 db=get_db()
719 with app.open_resource("etc/schema.sql", mode="r") as f:
720 db.cursor().executescript(f.read())
721 db.commit()