diff --git a/mods/db.py b/mods/db.py index 0d6fd72..1a63279 100644 --- a/mods/db.py +++ b/mods/db.py @@ -118,7 +118,11 @@ class ReceptionDiagnosis(BaseModel): class ReceptionAnamnesis(BaseModel): id = AutoIncrementField() reception = ForeignKeyField(Reception, backref='reception_anamnesisses', on_delete='CASCADE') - text = TextField() + anamnesis = ForeignKeyField(ListRecord, backref='reception_anamnesisses', on_delete='CASCADE') +class ReceptionObserve(BaseModel): + id = AutoIncrementField() + reception = ForeignKeyField(Reception, backref='reception_symptoms', on_delete='CASCADE') + symptom = ForeignKeyField(ListRecord, backref='reception_symptoms', on_delete='CASCADE') class PatientIndex(BaseFTSModel): rowid = RowIDField() fio = SearchField() @@ -132,6 +136,9 @@ Patient.add_index( ) Catalog.add_index(Catalog.index(fn.lower(Catalog.name), unique=True, name='catalog_name_unique')) ListRecord.add_index(ListRecord.index(ListRecord.list, fn.lower(ListRecord.text), unique=True, name='listrec_unique')) +ReceptionDiagnosis.add_index(ReceptionDiagnosis.index(ReceptionDiagnosis.reception, ReceptionDiagnosis.diagnosis, unique=True, name='reception_diagnosis_unique')) +ReceptionAnamnesis.add_index(ReceptionAnamnesis.index(ReceptionAnamnesis.reception, ReceptionAnamnesis.anamnesis, unique=True, name='reception_anamnesis_unique')) +ReceptionObserve.add_index(ReceptionObserve.index(ReceptionObserve.reception, ReceptionObserve.symptom, unique=True, name='reception_observe_unique')) db.connect() db.create_tables([ Patient, @@ -149,5 +156,6 @@ db.create_tables([ Reception, ReceptionDiagnosis, ReceptionAnamnesis, + ReceptionObserve, Settings ]) diff --git a/mods/diagnosis.py b/mods/diagnosis.py index 52f1b45..eb2bd46 100644 --- a/mods/diagnosis.py +++ b/mods/diagnosis.py @@ -2,15 +2,16 @@ import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject from mods.files import choose_diagnosis_win_file, diagnosis_row_ui_str -from mods.utils import ConditionalFilter +from mods.utils import ConditionalFilter, enable_widget, disable_widget from mods.db import DiagnosisCategory, Diagnosis, DiagnosisIndex, db import re class DiagnosisFilter(ConditionalFilter): - def filter(self, cat, query): + cat = None + def filter(self, query): if query != self.fstr: self.fstr = query - self.ids = list(map(lambda x:x.id, self.search_func(cat, query))) + self.ids = list(map(lambda x:x.id, self.search_func(self.cat, query))) return self.ids class DiagnosisRow(Gtk.ListBoxRow): @@ -34,16 +35,19 @@ def cats_subcats(cat): def get_categories(parent=None): with db.atomic(): return DiagnosisCategory.select().where(DiagnosisCategory.parent == parent) -def get_diagnosises(cat=None): +def get_reception_diagnosises(cat=None): with db.atomic(): if cat: - d = list(Diagnosis.select().where(Diagnosis.category.in_(cats_subcats(cat))).order_by(Diagnosis.code)) + d = list(Diagnosis.select().where(Diagnosis.category == cat).order_by(Diagnosis.code)) return d else: return Diagnosis.select() def get_category(cat_id): with db.atomic(): return DiagnosisCategory.get_by_id(cat_id) +def get_giagnosis(diag_id): + with db.atomic(): + return Diagnosis.get_by_id(diag_id) def search_diagnosises(cat, q): q = re.sub(r'\s+', ' ', q).strip() q = ' '.join([ f'{x}*' for x in q.split(' ')]) @@ -52,7 +56,7 @@ def search_diagnosises(cat, q): .join( DiagnosisIndex, on=(Diagnosis.id == DiagnosisIndex.rowid)) - .where((Diagnosis.category.in_(cats_subcats(cat))) & (DiagnosisIndex.match(q))) + .where((Diagnosis.category == cat) & (DiagnosisIndex.match(q))) .order_by(DiagnosisIndex.bm25())) diagnosis_filter = DiagnosisFilter(search_diagnosises) ######################################################## @@ -68,20 +72,42 @@ def build_diagnosis_row(diagnosis): row.add(box) return row -def create_choose_diagnosis_win(reception): +def create_choose_diagnosis_win(reception_b): b = Gtk.Builder() + rd_list = reception_b.get_object('diagnosis_list') class ChooseDiagnosisWinHandler: def cat_selection_changed(self, cat_selection): sel_iter = cat_selection.get_selected()[1] model = cat_selection.get_tree_view().get_model() category = get_category(model.get_value(sel_iter, 1)) + diagnosis_filter.cat = category + diagnosis_list.unselect_all() + self.diagnosis_row_unselected() self.redraw_diagnosis_list(category) def redraw_diagnosis_list(self, cat): for c in diagnosis_list.get_children(): diagnosis_list.remove(c) - for d in get_diagnosises(cat): + for d in get_reception_diagnosises(cat): diagnosis_list.add(build_diagnosis_row(d)) diagnosis_list.show_all() + def diagnosis_row_selected(self, *a): + enable_widget([accept_button]) + def diagnosis_row_unselected(self, *a): + disable_widget([accept_button]) + def diagnosis_filter_changed(self, filter_widget): + diagnosis_list.unselect_all() + self.diagnosis_row_unselected() + diagnosis_list.invalidate_filter() + def submit(self, button): + from mods.receptions import build_reception_diagnosis_row + exist_rows = list(map(lambda x: x.props.db_id, rd_list.get_children())) + rows = diagnosis_list.get_selected_rows() + for row in rows: + if row.props.db_id not in exist_rows: + diagnosis = get_giagnosis(row.props.db_id) + rd_list.add(build_reception_diagnosis_row(diagnosis)) + rd_list.show_all() + w.destroy() b.add_from_file(choose_diagnosis_win_file) b.connect_signals(ChooseDiagnosisWinHandler()) cat_liststore = b.get_object('category_list') @@ -92,6 +118,16 @@ def create_choose_diagnosis_win(reception): for c in get_categories(): insert_cat(c) diagnosis_list = b.get_object('diagnosis_list') - diagnosis_list.set_sort_func(None, None) + di_filter = b.get_object('diagnosis_filter') + accept_button = b.get_object('accept_button') + ##### + def diagnosis_filter_func(row): + fstr = di_filter.get_text().strip() + if not fstr: + diagnosis_filter.reset() + return True + return row.props.db_id in diagnosis_filter.filter(fstr) + ##### + diagnosis_list.set_filter_func(diagnosis_filter_func) w = b.get_object('choose_diagnosis_window') return w diff --git a/mods/lists.py b/mods/lists.py index 38dc5a4..43d215d 100644 --- a/mods/lists.py +++ b/mods/lists.py @@ -8,11 +8,8 @@ import re import peewee lists_map = { - 'diagnoz': 'Диагноз', 'anamnez': 'Анамнез', 'observ': 'Осмотр', - 'medicines': 'Медикаменты', - 'procedures': 'Процедуры' } for s_id in lists_map: diff --git a/mods/receptions.py b/mods/receptions.py index 13442a6..f6a0787 100644 --- a/mods/receptions.py +++ b/mods/receptions.py @@ -1,10 +1,11 @@ import gi +from mods.utils import disable_widget, enable_widget gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject, Gdk -from mods.db import db, Reception, Patient -from mods.files import new_reception_win_file, reception_row_ui_str, reception_list_settings_win_file, open_reception_win_file +from mods.db import db, Reception, Patient, ReceptionDiagnosis +from mods.files import new_reception_win_file, reception_row_ui_str, reception_list_settings_win_file, open_reception_win_file, diagnosis_row_ui_str from mods.settings import s_get_reception_list, s_set_reception_list -from mods.diagnosis import create_choose_diagnosis_win +from mods.diagnosis import create_choose_diagnosis_win, get_giagnosis from mods.root import builder from datetime import datetime, timedelta @@ -47,11 +48,38 @@ class NewReceptionPatientLabel(Gtk.Label): @db_id.setter def db_id_setter(self, value): self._db_id = value +class ReceptionDiagnosisRow(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 def get_reception(reception_id): with db.atomic(): return Reception.get_by_id(reception_id) +def get_reception_diagnosises(reception): + with db.atomic(): + return ReceptionDiagnosis.select().where(ReceptionDiagnosis.reception == reception) +def delete_reception_diagnosises(reception, diag_id_list): + if not len(diag_id_list): return + with db.atomic(): + ReceptionDiagnosis.delete().where((ReceptionDiagnosis.reception == reception) & (ReceptionDiagnosis.diagnosis.in_(diag_id_list))).execute() +def add_reception_diagnosises(reception, diag_id_list): + if not len(diag_id_list): return + with db.atomic(): + inserts = list(map(lambda x: {'reception': reception, 'diagnosis': get_giagnosis(x)}, diag_id_list)) + _ = ReceptionDiagnosis.insert_many(inserts).execute() +def save_reception_diagnosises(reception, diag_id_list): + exist_diags = set(map(lambda x: x.diagnosis.id, get_reception_diagnosises(reception))) + new_diags = set(diag_id_list) + to_del = list(exist_diags - new_diags) + to_add = list(new_diags - exist_diags) + delete_reception_diagnosises(reception, to_del) + add_reception_diagnosises(reception, to_add) +################################################################################## def build_reception_row(reception_datetime): b = Gtk.Builder() b.add_from_string(reception_row_ui_str) @@ -79,6 +107,17 @@ def build_reception_row(reception_datetime): row.props.datetime = reception_datetime row.add(box) return row +def build_reception_diagnosis_row(diagnosis): + b = Gtk.Builder() + b.add_from_string(diagnosis_row_ui_str) + win = b.get_object('win') + box = b.get_object('diagnosis_box') + b.get_object('title').set_text(f'{diagnosis.code:<8} {diagnosis.title}') + win.remove(win.get_children()[0]) + row = ReceptionDiagnosisRow() + row.props.db_id = diagnosis.id + row.add(box) + return row def create_open_reception_win(): b = Gtk.Builder() @@ -87,8 +126,23 @@ def create_open_reception_win(): reception = get_reception(reception_row.props.db_id) class OpenReceptionWinHandler: def show_choose_diagnosis_win(self, button): - choose_diagnosis_win = create_choose_diagnosis_win(reception) + choose_diagnosis_win = create_choose_diagnosis_win(b) choose_diagnosis_win.show_all() + def remove_diagnosis(self, button): + row = reception_diag_list.get_selected_row() + reception_diag_list.remove(row) + disable_widget([remove_diag_button]) + reception_diag_list.show_all() + def diagnosis_selected(self, *s): + enable_widget([remove_diag_button]) + def save(self, button): + # Диагнозы + diag_id_list = list(map(lambda x: x.props.db_id, reception_diag_list.get_children())) + save_reception_diagnosises(reception, diag_id_list) + ####### + + ####### + w.destroy() b.add_from_file(open_reception_win_file) b.connect_signals(OpenReceptionWinHandler()) # @@ -96,6 +150,11 @@ def create_open_reception_win(): patient_fio.set_markup(f'{" ".join([reception.patient.last_name, reception.patient.first_name, reception.patient.middle_name])}') reception_dt = b.get_object('reception_datetime') reception_dt.set_markup(f'{reception_row.props.datetime.strftime("%d.%m.%Y - %H:%M")}') + reception_diag_list = b.get_object('diagnosis_list') + remove_diag_button = b.get_object('remove_diag_button') + # Диагнозы + for rd in [x.diagnosis for x in get_reception_diagnosises(reception)]: + reception_diag_list.add(build_reception_diagnosis_row(rd)) # w = b.get_object('open_reception_window') return w diff --git a/res/ui/choose_diagnosis_win.glade b/res/ui/choose_diagnosis_win.glade index 5b5155e..dea92d3 100644 --- a/res/ui/choose_diagnosis_win.glade +++ b/res/ui/choose_diagnosis_win.glade @@ -24,10 +24,12 @@ Выбор диагноза True - + True + False True True + True @@ -111,6 +113,9 @@ True False + multiple + False + @@ -146,6 +151,7 @@ edit-find-symbolic False False + True diff --git a/res/ui/open_reception_win.glade b/res/ui/open_reception_win.glade index a61dd7b..cb48984 100644 --- a/res/ui/open_reception_win.glade +++ b/res/ui/open_reception_win.glade @@ -20,6 +20,7 @@ True True True + True @@ -223,6 +224,7 @@ True + False True True @@ -361,6 +363,7 @@ True + False True True @@ -460,6 +463,7 @@ True False + @@ -509,10 +513,12 @@ - + True + False True True + True @@ -649,6 +655,7 @@ True + False True True @@ -798,6 +805,7 @@ True + False True True