Диагноз на приёме

This commit is contained in:
Бородин Роман 2019-12-26 15:20:50 +03:00
parent 416d78adff
commit 1a9cd54a88
6 changed files with 133 additions and 19 deletions

View File

@ -118,7 +118,11 @@ class ReceptionDiagnosis(BaseModel):
class ReceptionAnamnesis(BaseModel): class ReceptionAnamnesis(BaseModel):
id = AutoIncrementField() id = AutoIncrementField()
reception = ForeignKeyField(Reception, backref='reception_anamnesisses', on_delete='CASCADE') 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): class PatientIndex(BaseFTSModel):
rowid = RowIDField() rowid = RowIDField()
fio = SearchField() fio = SearchField()
@ -132,6 +136,9 @@ Patient.add_index(
) )
Catalog.add_index(Catalog.index(fn.lower(Catalog.name), unique=True, name='catalog_name_unique')) 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')) 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.connect()
db.create_tables([ db.create_tables([
Patient, Patient,
@ -149,5 +156,6 @@ db.create_tables([
Reception, Reception,
ReceptionDiagnosis, ReceptionDiagnosis,
ReceptionAnamnesis, ReceptionAnamnesis,
ReceptionObserve,
Settings Settings
]) ])

View File

@ -2,15 +2,16 @@ import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject from gi.repository import Gtk, GObject
from mods.files import choose_diagnosis_win_file, diagnosis_row_ui_str 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 from mods.db import DiagnosisCategory, Diagnosis, DiagnosisIndex, db
import re import re
class DiagnosisFilter(ConditionalFilter): class DiagnosisFilter(ConditionalFilter):
def filter(self, cat, query): cat = None
def filter(self, query):
if query != self.fstr: if query != self.fstr:
self.fstr = query 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 return self.ids
class DiagnosisRow(Gtk.ListBoxRow): class DiagnosisRow(Gtk.ListBoxRow):
@ -34,16 +35,19 @@ def cats_subcats(cat):
def get_categories(parent=None): def get_categories(parent=None):
with db.atomic(): with db.atomic():
return DiagnosisCategory.select().where(DiagnosisCategory.parent == parent) return DiagnosisCategory.select().where(DiagnosisCategory.parent == parent)
def get_diagnosises(cat=None): def get_reception_diagnosises(cat=None):
with db.atomic(): with db.atomic():
if cat: 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 return d
else: else:
return Diagnosis.select() return Diagnosis.select()
def get_category(cat_id): def get_category(cat_id):
with db.atomic(): with db.atomic():
return DiagnosisCategory.get_by_id(cat_id) 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): def search_diagnosises(cat, q):
q = re.sub(r'\s+', ' ', q).strip() q = re.sub(r'\s+', ' ', q).strip()
q = ' '.join([ f'{x}*' for x in q.split(' ')]) q = ' '.join([ f'{x}*' for x in q.split(' ')])
@ -52,7 +56,7 @@ def search_diagnosises(cat, q):
.join( .join(
DiagnosisIndex, DiagnosisIndex,
on=(Diagnosis.id == DiagnosisIndex.rowid)) 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())) .order_by(DiagnosisIndex.bm25()))
diagnosis_filter = DiagnosisFilter(search_diagnosises) diagnosis_filter = DiagnosisFilter(search_diagnosises)
######################################################## ########################################################
@ -68,20 +72,42 @@ def build_diagnosis_row(diagnosis):
row.add(box) row.add(box)
return row return row
def create_choose_diagnosis_win(reception): def create_choose_diagnosis_win(reception_b):
b = Gtk.Builder() b = Gtk.Builder()
rd_list = reception_b.get_object('diagnosis_list')
class ChooseDiagnosisWinHandler: class ChooseDiagnosisWinHandler:
def cat_selection_changed(self, cat_selection): def cat_selection_changed(self, cat_selection):
sel_iter = cat_selection.get_selected()[1] sel_iter = cat_selection.get_selected()[1]
model = cat_selection.get_tree_view().get_model() model = cat_selection.get_tree_view().get_model()
category = get_category(model.get_value(sel_iter, 1)) 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) self.redraw_diagnosis_list(category)
def redraw_diagnosis_list(self, cat): def redraw_diagnosis_list(self, cat):
for c in diagnosis_list.get_children(): for c in diagnosis_list.get_children():
diagnosis_list.remove(c) 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.add(build_diagnosis_row(d))
diagnosis_list.show_all() 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.add_from_file(choose_diagnosis_win_file)
b.connect_signals(ChooseDiagnosisWinHandler()) b.connect_signals(ChooseDiagnosisWinHandler())
cat_liststore = b.get_object('category_list') cat_liststore = b.get_object('category_list')
@ -92,6 +118,16 @@ def create_choose_diagnosis_win(reception):
for c in get_categories(): for c in get_categories():
insert_cat(c) insert_cat(c)
diagnosis_list = b.get_object('diagnosis_list') 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') w = b.get_object('choose_diagnosis_window')
return w return w

View File

@ -8,11 +8,8 @@ import re
import peewee import peewee
lists_map = { lists_map = {
'diagnoz': 'Диагноз',
'anamnez': 'Анамнез', 'anamnez': 'Анамнез',
'observ': 'Осмотр', 'observ': 'Осмотр',
'medicines': 'Медикаменты',
'procedures': 'Процедуры'
} }
for s_id in lists_map: for s_id in lists_map:

View File

@ -1,10 +1,11 @@
import gi import gi
from mods.utils import disable_widget, enable_widget
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject, Gdk from gi.repository import Gtk, GObject, Gdk
from mods.db import db, Reception, Patient 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 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.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 mods.root import builder
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -47,11 +48,38 @@ class NewReceptionPatientLabel(Gtk.Label):
@db_id.setter @db_id.setter
def db_id_setter(self, value): def db_id_setter(self, value):
self._db_id = 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): def get_reception(reception_id):
with db.atomic(): with db.atomic():
return Reception.get_by_id(reception_id) 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): def build_reception_row(reception_datetime):
b = Gtk.Builder() b = Gtk.Builder()
b.add_from_string(reception_row_ui_str) b.add_from_string(reception_row_ui_str)
@ -79,6 +107,17 @@ def build_reception_row(reception_datetime):
row.props.datetime = reception_datetime row.props.datetime = reception_datetime
row.add(box) row.add(box)
return row 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(): def create_open_reception_win():
b = Gtk.Builder() b = Gtk.Builder()
@ -87,8 +126,23 @@ def create_open_reception_win():
reception = get_reception(reception_row.props.db_id) reception = get_reception(reception_row.props.db_id)
class OpenReceptionWinHandler: class OpenReceptionWinHandler:
def show_choose_diagnosis_win(self, button): 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() 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.add_from_file(open_reception_win_file)
b.connect_signals(OpenReceptionWinHandler()) b.connect_signals(OpenReceptionWinHandler())
# #
@ -96,6 +150,11 @@ def create_open_reception_win():
patient_fio.set_markup(f'<span size="x-large">{" ".join([reception.patient.last_name, reception.patient.first_name, reception.patient.middle_name])}</span>') patient_fio.set_markup(f'<span size="x-large">{" ".join([reception.patient.last_name, reception.patient.first_name, reception.patient.middle_name])}</span>')
reception_dt = b.get_object('reception_datetime') reception_dt = b.get_object('reception_datetime')
reception_dt.set_markup(f'<span size="x-large">{reception_row.props.datetime.strftime("%d.%m.%Y - %H:%M")}</span>') reception_dt.set_markup(f'<span size="x-large">{reception_row.props.datetime.strftime("%d.%m.%Y - %H:%M")}</span>')
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') w = b.get_object('open_reception_window')
return w return w

View File

@ -24,10 +24,12 @@
<property name="title" translatable="yes">Выбор диагноза</property> <property name="title" translatable="yes">Выбор диагноза</property>
<property name="show_close_button">True</property> <property name="show_close_button">True</property>
<child> <child>
<object class="GtkButton"> <object class="GtkButton" id="accept_button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<signal name="clicked" handler="submit" swapped="no"/>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="visible">True</property> <property name="visible">True</property>
@ -111,6 +113,9 @@
<object class="GtkListBox" id="diagnosis_list"> <object class="GtkListBox" id="diagnosis_list">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="selection_mode">multiple</property>
<property name="activate_on_single_click">False</property>
<signal name="row-selected" handler="diagnosis_row_selected" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>
@ -146,6 +151,7 @@
<property name="primary_icon_name">edit-find-symbolic</property> <property name="primary_icon_name">edit-find-symbolic</property>
<property name="primary_icon_activatable">False</property> <property name="primary_icon_activatable">False</property>
<property name="primary_icon_sensitive">False</property> <property name="primary_icon_sensitive">False</property>
<signal name="changed" handler="diagnosis_filter_changed" swapped="no"/>
</object> </object>
<packing> <packing>
<property name="expand">True</property> <property name="expand">True</property>

View File

@ -20,6 +20,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<signal name="clicked" handler="save" swapped="no"/>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="visible">True</property> <property name="visible">True</property>
@ -223,6 +224,7 @@
<child> <child>
<object class="GtkButton"> <object class="GtkButton">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<child> <child>
@ -361,6 +363,7 @@
<child> <child>
<object class="GtkButton"> <object class="GtkButton">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<child> <child>
@ -460,6 +463,7 @@
<object class="GtkListBox" id="diagnosis_list"> <object class="GtkListBox" id="diagnosis_list">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<signal name="row-selected" handler="diagnosis_selected" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>
@ -509,10 +513,12 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkButton"> <object class="GtkButton" id="remove_diag_button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<signal name="clicked" handler="remove_diagnosis" swapped="no"/>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="visible">True</property> <property name="visible">True</property>
@ -649,6 +655,7 @@
<child> <child>
<object class="GtkButton"> <object class="GtkButton">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<child> <child>
@ -798,6 +805,7 @@
<child> <child>
<object class="GtkButton"> <object class="GtkButton">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<child> <child>