eldoc/mods/patients.py

295 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
import os
from mods.files import gender_ui_str, icon_dir, open_patient_win_file, new_patient_win_file, edit_patient_win_file, choose_patient_win_file
from mods.utils import ConditionalFilter, show_msg, gender_dict, doc_type_dict, enable_widget, disable_widget
from mods.db import db, Patient, PatientIndex
from mods.root import builder
from datetime import date
import re
import peewee
def store_patient_index(pat):
fio_list = [pat.last_name, pat.first_name]
if pat.middle_name:
fio_list.append(pat.middle_name)
PatientIndex.insert(
{
PatientIndex.rowid: pat.id,
PatientIndex.fio: ' '.join(fio_list)
}
).execute()
def update_patient_index(pat):
fio_list = [pat.last_name, pat.first_name]
if pat.middle_name:
fio_list.append(pat.middle_name)
PatientIndex.update(
{
PatientIndex.fio: ' '.join(fio_list)
}
).where(PatientIndex.rowid == pat.id).execute()
def search_patients(q):
q = re.sub(r'\s+', ' ', q).strip()
q = ' '.join([ f'{x}*' for x in q.split(' ')])
with db.atomic():
return (Patient.select()
.join(
PatientIndex,
on=(Patient.id == PatientIndex.rowid))
.where(PatientIndex.match(q))
.order_by(PatientIndex.bm25()))
def get_all_patients():
with db.atomic():
return Patient.select()
class PatientRow(Gtk.ListBoxRow):
@GObject.Property
def db_id(self):
return self._db_id
@db_id.setter
def db_id_setter(self, value):
self._db_id = value
@GObject.Property
def fio(self):
return self._fio
@fio.setter
def fio_setter(self, value):
self._fio = value
@GObject.Property
def birth_date(self):
return self._birth_date
@birth_date.setter
def birth_date_setter(self, value):
self._birth_date = value
def build_patient_row(patient):
b = Gtk.Builder()
b.add_from_string(gender_ui_str[patient.gender])
win = b.get_object('win')
box = b.get_object('patient_box')
icon = b.get_object('icon')
icon.set_from_file(os.path.join(icon_dir, f'{patient.gender}.png'))
fio = f'{" ".join([patient.last_name, patient.first_name, patient.middle_name])}'
b.get_object('fio').set_text(fio)
birth_date = patient.birth_date
b.get_object('birth_date').set_text(birth_date.strftime('%d.%m.%Y'))
win.remove(win.get_children()[0])
row = PatientRow()
row.props.db_id = patient.id
row.props.fio = fio
row.props.birth_date = birth_date
row.add(box)
return row
def get_patient_win_values(b):
l_name = b.get_object('last_name').get_text().replace(' ', '')
f_name = b.get_object('first_name').get_text().replace(' ', '')
m_name = b.get_object('middle_name').get_text().replace(' ', '')
if '' in (l_name, f_name):
show_msg('Не указаны имя или фамилия', 'Данные поля должны быть заполнены', level='warn')
return None
try:
birth_d = int(b.get_object('birth_day').get_text())
if birth_d < 1 or birth_d > 31:
return show_msg('Неверный день месяца', 'Укажите число в диапазоне 1-31', level='warn')
birth_m = int(b.get_object('birth_month').get_text())
if birth_m < 1 or birth_m > 12:
show_msg('Неверный номер месяца', 'Укажите число в диапазоне 1-12', level='warn')
return None
birth_y = int(b.get_object('birth_year').get_text())
except ValueError:
show_msg('Неверно указана дата рождения', 'Все поля даты должны быть заполнены', level='warn')
return None
gender = b.get_object('gender').get_active_id()
if not gender:
show_msg('Не выбран пол', level='warn')
return None
birth_date = date(birth_y, birth_m, birth_d)
doc_type = b.get_object('doc_type').get_active_id()
doc_serial = b.get_object('doc_serial').get_text()
doc_number = b.get_object('doc_number').get_text()
policy_number = b.get_object('policy_number').get_text()
policy_company = b.get_object('policy_company').get_text()
snils_number = b.get_object('snils_number').get_text()
notes_buffer = b.get_object('notes_buffer')
notes_start = notes_buffer.get_start_iter()
notes_end = notes_buffer.get_end_iter()
notes = notes_buffer.get_text(notes_start, notes_end, True)
return {
'last_name': l_name,
'first_name': f_name,
'middle_name': m_name,
'gender': gender,
'birth_date': birth_date,
'doc_type': doc_type,
'doc_serial': doc_serial,
'doc_number': doc_number,
'policy_number': policy_number,
'policy_company': policy_company,
'snils_number': snils_number,
'notes': notes
}
def set_patient_win_values(patient_id, b, edit=False):
with db.atomic():
pat = Patient.select().where(Patient.id == patient_id).get()
b.get_object('last_name').set_text(pat.last_name)
b.get_object('first_name').set_text(pat.first_name)
b.get_object('middle_name').set_text(pat.middle_name)
if not edit:
b.get_object('gender').set_text(gender_dict[pat.gender])
else:
b.get_object('gender').set_active_id(pat.gender)
if not edit:
b.get_object('birth_date').set_text(pat.birth_date.strftime('%d.%m.%Y'))
else:
b.get_object('birth_day').set_text(str(pat.birth_date.day))
b.get_object('birth_month').set_text(str(pat.birth_date.month))
b.get_object('birth_year').set_text(str(pat.birth_date.year))
if not edit:
b.get_object('doc_type').set_text(doc_type_dict[pat.doc_type] if pat.doc_type else '')
elif pat.doc_type:
b.get_object('doc_type').set_active_id(pat.doc_type)
b.get_object('doc_serial').set_text(pat.doc_serial)
b.get_object('doc_number').set_text(pat.doc_number)
b.get_object('policy_number').set_text(pat.policy_number)
b.get_object('policy_company').set_text(pat.policy_company)
b.get_object('snils_number').set_text(pat.snils_number)
b.get_object('notes_buffer').set_text(pat.notes)
def create_open_patient_win(patient_id):
b = Gtk.Builder()
patient_list = builder.get_object('patient_list')
class OpenPatientWinHandler:
def show_edit_patient_win(self, *a):
edit_patient_win = create_edit_patient_win(patient_id)
w.destroy()
edit_patient_win.show_all()
b.add_from_file(open_patient_win_file)
b.connect_signals(OpenPatientWinHandler())
w = b.get_object('open_patient_window')
# db_id = b.get_object('db_id')
# db_id.set_text(str(patient_id))
set_patient_win_values(patient_id, b)
return w
def create_edit_patient_win(patient_id):
b = Gtk.Builder()
patient_list = builder.get_object('patient_list')
class EditPatientWinHandler:
def edit_patient_win_close(self, *args):
w.destroy()
open_patient_win = create_open_patient_win(patient_id)
open_patient_win.show_all()
def only_digits(self, entry):
text = entry.get_text()
text = ''.join(filter(lambda x: x.isdigit(), text))
entry.set_text(text)
def save_patient(self, *args):
values = get_patient_win_values(b)
if not values:
return
with db.atomic():
try:
Patient.update(**values).where(Patient.id == patient_id).execute()
except peewee.IntegrityError:
return show_msg('Данный пациент уже существует', 'Другой пациент с указанными фамилией, именем\nи датой рождения уже есть с базе данных', level='warn')
patient = Patient.select().where(Patient.id == patient_id).get()
update_patient_index(patient)
cur_row = list(filter(lambda x: x.props.db_id == patient_id, patient_list.get_children()))[0]
patient_list.remove(cur_row)
row = build_patient_row(patient)
patient_list.add(row)
patient_list.select_row(row)
patient_list.show_all()
b.get_object('edit_patient_window').close()
b.add_from_file(edit_patient_win_file)
b.connect_signals(EditPatientWinHandler())
w = b.get_object('edit_patient_window')
set_patient_win_values(patient_id, b, edit=True)
return w
def create_new_patient_win():
b = Gtk.Builder()
patient_list = builder.get_object('patient_list')
class NewPatienWinHandler:
def only_digits(self, entry):
text = entry.get_text()
text = ''.join(filter(lambda x: x.isdigit(), text))
entry.set_text(text)
def save_patient(self, *args):
values = get_patient_win_values(b)
if not values:
return
with db.atomic():
try:
patient = Patient.create(**values)
except peewee.IntegrityError:
return show_msg('Данный пациент уже существует', 'Пациент с указанными фамилией, именем\nи датой рождения уже есть с базе данных', level='warn')
store_patient_index(patient)
row = build_patient_row(patient)
patient_list.add(row)
patient_list.select_row(row)
patient_list.show_all()
b.get_object('new_patient_window').close()
b.add_from_file(new_patient_win_file)
b.connect_signals(NewPatienWinHandler())
w = b.get_object('new_patient_window')
return w
def create_choose_patient_win(new_reception_b):
b = Gtk.Builder()
patient_cont = new_reception_b.get_object('patient')
save_button = new_reception_b.get_object('save_button')
patient_filter = ConditionalFilter(search_patients)
class ChoosePatientWinHandler:
def patient_filter_changed(self, filter_widget):
pl.unselect_all()
self.patient_list_unselected()
pl.invalidate_filter()
def patient_list_selected(self, *a):
enable_widget([accept_button])
def patient_list_unselected(self, *a):
disable_widget([accept_button])
def submit(self, button):
from mods.receptions import NewReceptionPatientLabel
row = pl.get_selected_row()
for c in patient_cont.get_children():
patient_cont.remove(c)
patient_label = NewReceptionPatientLabel()
patient_label.props.db_id = row.props.db_id
patient_label.set_markup(f'<span size="xx-large">{row.props.fio}</span>')
patient_cont.pack_start(patient_label, True, True, 0)
patient_cont.reorder_child(patient_label, 0)
patient_cont.show_all()
enable_widget([save_button])
w.destroy()
b.add_from_file(choose_patient_win_file)
b.connect_signals(ChoosePatientWinHandler())
accept_button = b.get_object('accept_button')
pl = b.get_object('patient_list')
pl.set_sort_func(patient_sort_func)
pl.set_filter_func(patient_filter_func_factory(patient_filter, b))
###
for p in get_all_patients():
pl.add(build_patient_row(p))
###
w = b.get_object('choose_patient_window')
return w
def patient_sort_func(row1, row2, *a):
text1 = row1.props.fio
text2 = row2.props.fio
return (text1 > text2) - (text1 < text2)
def patient_filter_func_factory(patient_filter, b):
def patient_filter_func(row):
fstr = b.get_object('patient_filter').get_text().strip()
if not fstr:
patient_filter.reset()
return True
return row.props.db_id in patient_filter.filter(fstr)
return patient_filter_func