From 0e13795c4b1b69203c254bb3f73ab163c7609c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D1=80=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=A0=D0=BE?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD?= Date: Wed, 4 Dec 2019 17:16:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=B0=D0=B6=D0=B4=D1=8B=D0=B9=20=D1=84?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=20=D0=B2?= =?UTF-8?q?=20=D1=81=D0=B2=D0=BE=D1=91=D0=BC=20=D0=BC=D0=BE=D0=B4=D1=83?= =?UTF-8?q?=D0=BB=D0=B5=20=D0=B8=20=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D1=91=D0=BC=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 314 ++++---------------------------- mods/db.py | 31 ---- mods/files.py | 17 +- mods/patients.py | 246 +++++++++++++++++++++++++ mods/receptions.py | 60 ++++++ mods/utils.py | 10 + res/ui/choose_patient_win.glade | 55 ++++++ res/ui/main_win.glade | 6 +- res/ui/new_reception_win.glade | 158 ++++++++++++++++ 9 files changed, 583 insertions(+), 314 deletions(-) create mode 100644 mods/patients.py create mode 100644 mods/receptions.py create mode 100644 res/ui/choose_patient_win.glade create mode 100644 res/ui/new_reception_win.glade diff --git a/app.py b/app.py index d97a37f..247370f 100644 --- a/app.py +++ b/app.py @@ -2,48 +2,31 @@ import gi import os gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject, Gdk -from mods.db import store_patient_index, update_patient_index, search_patients, db, Patient, Reception, Catalog, List +from mods.db import db, Patient, Reception, Catalog, List from mods.settings import s_get_reception_list, s_set_reception_list from mods.catalogs import add_catalog, search_catalogs +from mods.patients import build_patient_row, patient_sort_func, patient_filter_func_factory, create_new_patient_win, create_open_patient_win +from mods.receptions import create_new_reception_win, build_reception_row from mods.lists import create_open_list_win from mods.files import list_row_ui_str -from mods.utils import show_msg, ConditionalFilter -from datetime import date, datetime, timedelta +from mods.utils import show_msg, ConditionalFilter, enable_widget, disable_widget +from datetime import datetime, timedelta import peewee import re -gender_dict = { - 'male': 'Мужской', - 'female': 'Женский' - } -doc_type_dict = { - 'passport': 'Паспорт', - 'birth_cert': 'Св.о рождении', - 'foreign_passport': 'Паспорт иностранца' - } # Variables resource_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res') ui_dir = os.path.join(resource_dir, 'ui') -icon_dir = os.path.join(resource_dir, 'icons') + main_win_file = os.path.join(ui_dir, 'main_win.glade') -new_patient_win_file = os.path.join(ui_dir, 'new_patient_win.glade') -open_patient_win_file = os.path.join(ui_dir, 'open_patient_win.glade') -edit_patient_win_file = os.path.join(ui_dir, 'edit_patient_win.glade') -male_patient_row_file = os.path.join(ui_dir, 'male_patient_row.glade') reception_list_settings_win_file = os.path.join(ui_dir, 'reception_list_settings.glade') -female_patient_row_file = os.path.join(ui_dir, 'female_patient_row.glade') + new_catalog_win_file = os.path.join(ui_dir, 'new_catalog_win.glade') -reception_row_file = os.path.join(ui_dir, 'reception_row.glade') -with open(reception_row_file, 'r') as f: - reception_row_ui_str = f.read() + catalog_row_file = os.path.join(ui_dir, 'catalog_list_row.glade') with open(catalog_row_file, 'r') as f: catalog_row_ui_str = f.read() -gender_ui_str = {} -with open(male_patient_row_file, 'r') as f: - gender_ui_str['male'] = f.read() -with open(female_patient_row_file, 'r') as f: - gender_ui_str['female'] = f.read() + ############ builder = Gtk.Builder() @@ -56,49 +39,9 @@ def get_reception_timelist(rec_date): shift_minutes_range = range(0, work_day_minutes_total, s.interval) return [dstart + timedelta(minutes=x) for x in shift_minutes_range] -patient_filter = ConditionalFilter(search_patients) + catalog_filter = ConditionalFilter(search_catalogs) -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 - -class ReceptionRow(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 datetime(self): - return self._datetime - @datetime.setter - def datetime_setter(self, value): - self._datetime = value - @GObject.Property - def scheduled(self): - return self._scheduled - @scheduled.setter - def scheduled_setter(self, value): - self._scheduled = value - class CatalogRow(Gtk.ListBoxRow): @GObject.Property def db_id(self): @@ -143,13 +86,16 @@ class MainWinHandler: def show_reception_list_settings_win(self, button): reception_list_settings_win = create_reception_list_settings_win() reception_list_settings_win.show_all() + def show_new_reception_win(self, button): + new_reception_win = create_new_reception_win(builder) + new_reception_win.show_all() def show_new_patient_win(self, button): - new_patient_win = create_new_patient_win() + new_patient_win = create_new_patient_win(patient_list) new_patient_win.show_all() def show_open_patient_win(self, button): pl = builder.get_object('patient_list') row = pl.get_selected_row() - open_patient_win = create_open_patient_win(row.props.db_id) + open_patient_win = create_open_patient_win(row.props.db_id, patient_list) open_patient_win.show_all() def show_open_list_win(self, button): ll = builder.get_object('list_list') @@ -159,12 +105,23 @@ class MainWinHandler: def show_new_catalog_win(self, button): new_catalog_win = create_new_catalog_win() new_catalog_win.show_all() + def reception_list_selected(self, *a): + rl = builder.get_object('reception_list') + new_button = builder.get_object('new_reception_button') + edit_button = builder.get_object('edit_reception_button') + row = rl.get_selected_row() + if row.props.scheduled: + enable_widget([edit_button]) + disable_widget([new_button]) + else: + enable_widget([new_button]) + disable_widget([edit_button]) def patient_list_selected(self, *a): button = builder.get_object('patient_open_button') - button.set_sensitive(True) + enable_widget([button]) def patient_list_unselected(self, *a): button = builder.get_object('patient_open_button') - button.set_sensitive(False) + disable_widget([button]) def patient_filter_changed(self, filter_widget): pl = builder.get_object('patient_list') pl.unselect_all() @@ -172,17 +129,15 @@ class MainWinHandler: pl.invalidate_filter() def list_list_selected(self, *a): open_button = builder.get_object('list_open_button') - open_button.set_sensitive(True) + enable_widget([open_button]) def catalog_list_selected(self, *a): open_button = builder.get_object('catalog_open_button') rename_button = builder.get_object('catalog_rename_button') - open_button.set_sensitive(True) - rename_button.set_sensitive(True) + enable_widget([open_button, rename_button]) def catalog_list_unselected(self, *a): open_button = builder.get_object('catalog_open_button') rename_button = builder.get_object('catalog_rename_button') - open_button.set_sensitive(False) - rename_button.set_sensitive(False) + disable_widget([open_button, rename_button]) def catalog_filter_changed(self, filter_widget): cl = builder.get_object('catalog_list') cl.unselect_all() @@ -215,60 +170,9 @@ def build_catalog_row(catalog): row.add(box) return row -def build_reception_row(reception_datetime): - b = Gtk.Builder() - b.add_from_string(reception_row_ui_str) - win = b.get_object('win') - box = b.get_object('reception_box') - b.get_object('hour').set_text(reception_datetime.strftime('%H')) - b.get_object('minute').set_text(reception_datetime.strftime('%M')) - with db.atomic(): - reception = Reception.select().where(Reception.time == reception_datetime) - row = ReceptionRow() - if len(reception): - row.props.scheduled = True - row.props.db_id = reception.id - reception_cont = b.get_object('reception_cont') - reception_cont.props.border_width = 2 - reception_cont.override_background_color(Gtk.StateFlags(0), Gdk.RGBA(red=0.5, green=0.7, blue=0.5, alpha=1.0)) - reception_patient = Gtk.Label() - reception_patient.set_text(' '.join([reception.patient.last_name, reception.patient.first_name, reception.patient.middle_name])) - reception_cont.add(reception_patient) - else: - row.props.scheduled = False - win.remove(win.get_children()[0]) - row.props.datetime = reception_datetime - row.add(box) - return row -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 patient_sort_func(row1, row2, *a): - text1 = row1.props.fio - text2 = row2.props.fio - return (text1 > text2) - (text1 < text2) -def patient_filter_func(row): - fstr = builder.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) + + def list_sort_func(row1, row2, *a): text1 = row1.props.name text2 = row2.props.name @@ -300,7 +204,7 @@ redraw_reception_list(datetime.now()) ##### patient_list = builder.get_object('patient_list') patient_list.set_sort_func(patient_sort_func) -patient_list.set_filter_func(patient_filter_func) +patient_list.set_filter_func(patient_filter_func_factory(builder)) with db.atomic(): for p in Patient.select(): patient_list.add(build_patient_row(p)) @@ -320,157 +224,7 @@ with db.atomic(): -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() - 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() - 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() - 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_reception_list_settings_win(): b = Gtk.Builder() diff --git a/mods/db.py b/mods/db.py index 1f84e10..66dd2e6 100644 --- a/mods/db.py +++ b/mods/db.py @@ -104,34 +104,3 @@ db.create_tables([ ReceptionAnamnesis, Settings ]) - -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 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() - diff --git a/mods/files.py b/mods/files.py index a9733c2..6d2feb7 100644 --- a/mods/files.py +++ b/mods/files.py @@ -1,7 +1,7 @@ import os resource_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'res') ui_dir = os.path.join(resource_dir, 'ui') - +icon_dir = os.path.join(resource_dir, 'icons') list_row_file = os.path.join(ui_dir, 'list_row.glade') with open(list_row_file, 'r') as f: list_row_ui_str = f.read() @@ -12,3 +12,18 @@ with open(listrecord_row_file, 'r') as f: editable_row_file = os.path.join(ui_dir, 'editable_row.glade') with open(editable_row_file, 'r') as f: editable_row_ui_str = f.read() +male_patient_row_file = os.path.join(ui_dir, 'male_patient_row.glade') +female_patient_row_file = os.path.join(ui_dir, 'female_patient_row.glade') +gender_ui_str = {} +with open(male_patient_row_file, 'r') as f: + gender_ui_str['male'] = f.read() +with open(female_patient_row_file, 'r') as f: + gender_ui_str['female'] = f.read() +reception_row_file = os.path.join(ui_dir, 'reception_row.glade') +with open(reception_row_file, 'r') as f: + reception_row_ui_str = f.read() + +new_patient_win_file = os.path.join(ui_dir, 'new_patient_win.glade') +open_patient_win_file = os.path.join(ui_dir, 'open_patient_win.glade') +edit_patient_win_file = os.path.join(ui_dir, 'edit_patient_win.glade') +new_reception_win_file = os.path.join(ui_dir, 'new_reception_win.glade') diff --git a/mods/patients.py b/mods/patients.py new file mode 100644 index 0000000..891a9bf --- /dev/null +++ b/mods/patients.py @@ -0,0 +1,246 @@ +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 +from mods.utils import ConditionalFilter, show_msg, gender_dict, doc_type_dict +from mods.db import db, Patient, PatientIndex +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())) + +patient_filter = ConditionalFilter(search_patients) + +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, patient_list): + b = Gtk.Builder() + class OpenPatientWinHandler: + def show_edit_patient_win(self, *a): + edit_patient_win = create_edit_patient_win(patient_id, patient_list) + 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, patient_list): + b = Gtk.Builder() + 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(patient_list): + b = Gtk.Builder() + 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 patient_sort_func(row1, row2, *a): + text1 = row1.props.fio + text2 = row2.props.fio + return (text1 > text2) - (text1 < text2) +def patient_filter_func_factory(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 diff --git a/mods/receptions.py b/mods/receptions.py new file mode 100644 index 0000000..1a95541 --- /dev/null +++ b/mods/receptions.py @@ -0,0 +1,60 @@ +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, GObject, Gdk +from mods.db import db, Reception +from mods.files import new_reception_win_file, reception_row_ui_str + +class ReceptionRow(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 datetime(self): + return self._datetime + @datetime.setter + def datetime_setter(self, value): + self._datetime = value + @GObject.Property + def scheduled(self): + return self._scheduled + @scheduled.setter + def scheduled_setter(self, value): + self._scheduled = value + +def build_reception_row(reception_datetime): + b = Gtk.Builder() + b.add_from_string(reception_row_ui_str) + win = b.get_object('win') + box = b.get_object('reception_box') + b.get_object('hour').set_text(reception_datetime.strftime('%H')) + b.get_object('minute').set_text(reception_datetime.strftime('%M')) + with db.atomic(): + reception = Reception.select().where(Reception.time == reception_datetime) + row = ReceptionRow() + if len(reception): + row.props.scheduled = True + row.props.db_id = reception.id + reception_cont = b.get_object('reception_cont') + reception_cont.props.border_width = 2 + reception_cont.override_background_color(Gtk.StateFlags(0), Gdk.RGBA(red=0.5, green=0.7, blue=0.5, alpha=1.0)) + reception_patient = Gtk.Label() + reception_patient.set_text(' '.join([reception.patient.last_name, reception.patient.first_name, reception.patient.middle_name])) + reception_cont.add(reception_patient) + else: + row.props.scheduled = False + win.remove(win.get_children()[0]) + row.props.datetime = reception_datetime + row.add(box) + return row + +def create_new_reception_win(root_builder): + b = Gtk.Builder() + class NewReceptionWinHandler: + pass + b.add_from_file(new_reception_win_file) + b.connect_signals(NewReceptionWinHandler()) + w = b.get_object('new_reception_window') + return w diff --git a/mods/utils.py b/mods/utils.py index 8a46cdb..485ccba 100644 --- a/mods/utils.py +++ b/mods/utils.py @@ -4,6 +4,16 @@ import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk +gender_dict = { + 'male': 'Мужской', + 'female': 'Женский' + } +doc_type_dict = { + 'passport': 'Паспорт', + 'birth_cert': 'Св.о рождении', + 'foreign_passport': 'Паспорт иностранца' + } + def show_msg(text, sec_text='', level='info'): msg_win_file = os.path.join(ui_dir, f'{level}_win.glade') b = Gtk.Builder() diff --git a/res/ui/choose_patient_win.glade b/res/ui/choose_patient_win.glade new file mode 100644 index 0000000..4f55a5c --- /dev/null +++ b/res/ui/choose_patient_win.glade @@ -0,0 +1,55 @@ + + + + + + 600 + 500 + False + True + center + dialog + + + True + False + Выбор пациента + True + + + True + False + True + True + + + True + False + object-select-symbolic + + + + + + + + + True + True + in + + + True + False + + + True + False + + + + + + + + diff --git a/res/ui/main_win.glade b/res/ui/main_win.glade index 1e0d9c7..6f8aa5a 100644 --- a/res/ui/main_win.glade +++ b/res/ui/main_win.glade @@ -43,8 +43,9 @@ False both - + True + False False Создать Создать @@ -57,8 +58,9 @@ - + True + False False Изменить Изменить diff --git a/res/ui/new_reception_win.glade b/res/ui/new_reception_win.glade new file mode 100644 index 0000000..1ce88c4 --- /dev/null +++ b/res/ui/new_reception_win.glade @@ -0,0 +1,158 @@ + + + + + + 500 + False + True + center + dialog + + + True + False + Новый приём + True + + + True + True + True + + + True + False + document-save-symbolic + + + + + + + + + True + False + vertical + + + True + False + 5 + 5 + 5 + 5 + 0 + + + True + False + 5 + 5 + 5 + 5 + 12 + + + True + False + + + + + + + + + + True + False + Дата и время + + + + + False + True + 0 + + + + + True + False + 5 + 5 + 5 + 5 + 0 + + + True + False + 12 + + + True + False + 5 + 5 + 5 + 5 + + + True + False + + + + + + True + True + 0 + + + + + True + True + True + True + + + True + False + gtk-index + + + + + False + True + 1 + + + + + + + + + True + False + Пациент + + + + + False + True + 1 + + + + + +