фильтр справочников
This commit is contained in:
parent
ead0ec5f58
commit
18160ed0b4
63
app.py
63
app.py
|
@ -4,9 +4,10 @@ gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk, GObject, Gdk
|
from gi.repository import Gtk, GObject, Gdk
|
||||||
from mods.db import store_patient_index, update_patient_index, search_patients, dbo
|
from mods.db import store_patient_index, update_patient_index, search_patients, dbo
|
||||||
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.catalogs import add_catalog
|
from mods.catalogs import add_catalog, search_catalogs
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
import peewee
|
import peewee
|
||||||
|
import re
|
||||||
|
|
||||||
gender_dict = {
|
gender_dict = {
|
||||||
'male': 'Мужской',
|
'male': 'Мужской',
|
||||||
|
@ -28,6 +29,7 @@ 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')
|
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')
|
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')
|
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')
|
reception_row_file = os.path.join(ui_dir, 'reception_row.glade')
|
||||||
with open(reception_row_file, 'r') as f:
|
with open(reception_row_file, 'r') as f:
|
||||||
reception_row_ui_str = f.read()
|
reception_row_ui_str = f.read()
|
||||||
|
@ -51,18 +53,20 @@ def get_reception_timelist(rec_date):
|
||||||
shift_minutes_range = range(0, work_day_minutes_total, s.interval)
|
shift_minutes_range = range(0, work_day_minutes_total, s.interval)
|
||||||
return [dstart + timedelta(minutes=x) for x in shift_minutes_range]
|
return [dstart + timedelta(minutes=x) for x in shift_minutes_range]
|
||||||
|
|
||||||
class PatientFilter:
|
class ConditionalFilter:
|
||||||
def __init__(self):
|
def __init__(self, search_func):
|
||||||
|
self.search_func = search_func
|
||||||
self.reset()
|
self.reset()
|
||||||
def filter(self, query):
|
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, search_patients(query)))
|
self.ids = list(map(lambda x: x.id, self.search_func(query)))
|
||||||
return self.ids
|
return self.ids
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.fstr = ''
|
self.fstr = ''
|
||||||
self.ids = []
|
self.ids = []
|
||||||
patient_filter = PatientFilter()
|
patient_filter = ConditionalFilter(search_patients)
|
||||||
|
catalog_filter = ConditionalFilter(search_catalogs)
|
||||||
|
|
||||||
class PatientRow(Gtk.ListBoxRow):
|
class PatientRow(Gtk.ListBoxRow):
|
||||||
@GObject.Property
|
@GObject.Property
|
||||||
|
@ -111,6 +115,12 @@ class CatalogRow(Gtk.ListBoxRow):
|
||||||
@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
|
||||||
|
@GObject.Property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
@name.setter
|
||||||
|
def name_setter(self, value):
|
||||||
|
self._name = value
|
||||||
|
|
||||||
class MainWinHandler:
|
class MainWinHandler:
|
||||||
def main_win_close(self, *args):
|
def main_win_close(self, *args):
|
||||||
|
@ -137,6 +147,9 @@ class MainWinHandler:
|
||||||
row = pl.get_selected_row()
|
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)
|
||||||
open_patient_win.show_all()
|
open_patient_win.show_all()
|
||||||
|
def show_new_catalog_win(self, button):
|
||||||
|
new_catalog_win = create_new_catalog_win()
|
||||||
|
new_catalog_win.show_all()
|
||||||
def patient_list_selected(self, *a):
|
def patient_list_selected(self, *a):
|
||||||
button = builder.get_object('patient_open_button')
|
button = builder.get_object('patient_open_button')
|
||||||
button.set_sensitive(True)
|
button.set_sensitive(True)
|
||||||
|
@ -160,6 +173,10 @@ class MainWinHandler:
|
||||||
for p in patients:
|
for p in patients:
|
||||||
pl.add(build_patient_row(p))
|
pl.add(build_patient_row(p))
|
||||||
pl.show_all()'''
|
pl.show_all()'''
|
||||||
|
def catalog_filter_changed(self, filter_widget):
|
||||||
|
cl = builder.get_object('catalog_list')
|
||||||
|
cl.unselect_all()
|
||||||
|
cl.invalidate_filter()
|
||||||
|
|
||||||
def build_catalog_row(catalog):
|
def build_catalog_row(catalog):
|
||||||
b = Gtk.Builder()
|
b = Gtk.Builder()
|
||||||
|
@ -169,6 +186,7 @@ def build_catalog_row(catalog):
|
||||||
b.get_object('name').set_text(catalog.name)
|
b.get_object('name').set_text(catalog.name)
|
||||||
row = CatalogRow()
|
row = CatalogRow()
|
||||||
row.props.db_id = catalog.id
|
row.props.db_id = catalog.id
|
||||||
|
row.name = catalog.name
|
||||||
win.remove(win.get_children()[0])
|
win.remove(win.get_children()[0])
|
||||||
row.add(box)
|
row.add(box)
|
||||||
return row
|
return row
|
||||||
|
@ -227,6 +245,16 @@ def patient_filter_func(row):
|
||||||
patient_filter.reset()
|
patient_filter.reset()
|
||||||
return True
|
return True
|
||||||
return row.props.db_id in patient_filter.filter(fstr)
|
return row.props.db_id in patient_filter.filter(fstr)
|
||||||
|
def catalog_sort_func(row1, row2, *a):
|
||||||
|
text1 = row1.props.name
|
||||||
|
text2 = row2.props.name
|
||||||
|
return (text1 > text2) - (text1 < text2)
|
||||||
|
def catalog_filter_func(row):
|
||||||
|
fstr = builder.get_object('catalog_filter').get_text().strip()
|
||||||
|
if not fstr:
|
||||||
|
catalog_filter.reset()
|
||||||
|
return True
|
||||||
|
return row.props.db_id in catalog_filter.filter(fstr)
|
||||||
|
|
||||||
def redraw_reception_list(selected_date):
|
def redraw_reception_list(selected_date):
|
||||||
reception_timelist = get_reception_timelist(selected_date)
|
reception_timelist = get_reception_timelist(selected_date)
|
||||||
|
@ -250,7 +278,8 @@ with dbo.db.atomic():
|
||||||
patient_list.add(build_patient_row(p))
|
patient_list.add(build_patient_row(p))
|
||||||
#####
|
#####
|
||||||
catalog_list = builder.get_object('catalog_list')
|
catalog_list = builder.get_object('catalog_list')
|
||||||
|
catalog_list.set_sort_func(catalog_sort_func)
|
||||||
|
catalog_list.set_filter_func(catalog_filter_func)
|
||||||
with dbo.db.atomic():
|
with dbo.db.atomic():
|
||||||
for c in dbo._Catalog.select(): # @UndefinedVariable
|
for c in dbo._Catalog.select(): # @UndefinedVariable
|
||||||
catalog_list.add(build_catalog_row(c))
|
catalog_list.add(build_catalog_row(c))
|
||||||
|
@ -440,6 +469,28 @@ def create_reception_list_settings_win():
|
||||||
w = b.get_object('reception_list_settings_win')
|
w = b.get_object('reception_list_settings_win')
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
def create_new_catalog_win():
|
||||||
|
b = Gtk.Builder()
|
||||||
|
class NewCatalogHandler:
|
||||||
|
def save_catalog(self, *a):
|
||||||
|
catname = re.sub(r'\s+', ' ', b.get_object('catalog_name').get_text()).strip()
|
||||||
|
if not len(catname):
|
||||||
|
return show_msg('Не указано имя справочника', 'Данное поле должно быть заполнено', level='warn')
|
||||||
|
with dbo.db.atomic():
|
||||||
|
try:
|
||||||
|
catalog = add_catalog(catname)
|
||||||
|
except peewee.IntegrityError:
|
||||||
|
return show_msg('Данный справочник уже существует', 'Справочник с указанным названием уже есть с базе данных', level='warn')
|
||||||
|
row = build_catalog_row(catalog)
|
||||||
|
catalog_list.add(row)
|
||||||
|
catalog_list.select_row(row)
|
||||||
|
catalog_list.show_all()
|
||||||
|
b.get_object('new_catalog_window').close()
|
||||||
|
b.add_from_file(new_catalog_win_file)
|
||||||
|
b.connect_signals(NewCatalogHandler())
|
||||||
|
w = b.get_object('new_catalog_window')
|
||||||
|
return w
|
||||||
|
|
||||||
main_win = builder.get_object('main_window')
|
main_win = builder.get_object('main_window')
|
||||||
main_win.show_all()
|
main_win.show_all()
|
||||||
Gtk.main()
|
Gtk.main()
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
from mods.db import dbo
|
||||||
|
|
||||||
|
sys_catalogs = {
|
||||||
|
'diagnoz': 'Диагноз',
|
||||||
|
'anamnez': 'Анамнез',
|
||||||
|
'observ': 'Осмотр',
|
||||||
|
'druggs': 'Медикаменты'
|
||||||
|
}
|
||||||
|
|
||||||
|
def add_catalog(name, system_id = ''):
|
||||||
|
catalog = dbo._Catalog.create(name=name, system_id=system_id) # @UndefinedVariable
|
||||||
|
dbo._CatalogIndex.insert( # @UndefinedVariable
|
||||||
|
{
|
||||||
|
dbo._CatalogIndex.rowid: catalog.id,
|
||||||
|
dbo._CatalogIndex.text: name
|
||||||
|
}
|
||||||
|
).execute() # @UndefinedVariable
|
||||||
|
return catalog
|
||||||
|
|
||||||
|
def search_catalogs(q):
|
||||||
|
with dbo.db.atomic():
|
||||||
|
return (dbo._Catalog.select() # @UndefinedVariable
|
||||||
|
.join( # @UndefinedVariable
|
||||||
|
dbo._CatalogIndex,
|
||||||
|
on=(dbo._Catalog.id == dbo._CatalogIndex.rowid))
|
||||||
|
.where(dbo._CatalogIndex.match(q)) # @UndefinedVariable
|
||||||
|
.order_by(dbo._CatalogIndex.bm25())) # @UndefinedVariable
|
||||||
|
|
||||||
|
for s_id in sys_catalogs:
|
||||||
|
with dbo.db.atomic():
|
||||||
|
q = dbo._Catalog.select().where(dbo._Catalog.system_id == s_id) # @UndefinedVariable
|
||||||
|
if not len(q):
|
||||||
|
add_catalog(sys_catalogs[s_id], s_id) # @UndefinedVariable
|
10
mods/db.py
10
mods/db.py
|
@ -1,5 +1,5 @@
|
||||||
import os
|
import os
|
||||||
from peewee import Model, CharField, DateTimeField, TextField, ForeignKeyField, DateField
|
from peewee import Model, CharField, DateTimeField, TextField, ForeignKeyField, DateField, fn
|
||||||
from playhouse.sqlite_ext import CSqliteExtDatabase, FTS5Model, AutoIncrementField, SearchField, RowIDField, JSONField
|
from playhouse.sqlite_ext import CSqliteExtDatabase, FTS5Model, AutoIncrementField, SearchField, RowIDField, JSONField
|
||||||
|
|
||||||
var_dir = os.path.join(os.path.abspath(os.environ['HOME']), '.eldoc')
|
var_dir = os.path.join(os.path.abspath(os.environ['HOME']), '.eldoc')
|
||||||
|
@ -45,6 +45,9 @@ class DBO:
|
||||||
id = AutoIncrementField()
|
id = AutoIncrementField()
|
||||||
system_id = TextField(null=True)
|
system_id = TextField(null=True)
|
||||||
name = TextField()
|
name = TextField()
|
||||||
|
class CatalogIndex(BaseFTSModel):
|
||||||
|
rowid = RowIDField()
|
||||||
|
text = SearchField()
|
||||||
class CatalogRecord(BaseModel):
|
class CatalogRecord(BaseModel):
|
||||||
id = AutoIncrementField()
|
id = AutoIncrementField()
|
||||||
catalog = ForeignKeyField(Catalog, backref='catalog_records', on_delete='CASCADE')
|
catalog = ForeignKeyField(Catalog, backref='catalog_records', on_delete='CASCADE')
|
||||||
|
@ -74,6 +77,7 @@ class DBO:
|
||||||
###
|
###
|
||||||
self._Patient = Patient
|
self._Patient = Patient
|
||||||
self._Catalog = Catalog
|
self._Catalog = Catalog
|
||||||
|
self._CatalogIndex = CatalogIndex
|
||||||
self._CatalogRecord = CatalogRecord
|
self._CatalogRecord = CatalogRecord
|
||||||
self._CatalogRecordIndex = CatalogRecordIndex
|
self._CatalogRecordIndex = CatalogRecordIndex
|
||||||
self._Reception = Reception
|
self._Reception = Reception
|
||||||
|
@ -84,12 +88,14 @@ class DBO:
|
||||||
self.db.connect()
|
self.db.connect()
|
||||||
def create(self):
|
def create(self):
|
||||||
self._Patient.add_index(
|
self._Patient.add_index(
|
||||||
self._Patient.index(self._Patient.last_name, self._Patient.first_name, self._Patient.birth_date, unique=True)
|
self._Patient.index(fn.lower(self._Patient.last_name), fn.lower(self._Patient.first_name), self._Patient.birth_date, unique=True, name='patient_first_last_name_birth_date_unique')
|
||||||
)
|
)
|
||||||
|
self._Catalog.add_index(self._Catalog.index(fn.lower(self._Catalog.name), unique=True, name='catalog_name_unique'))
|
||||||
self.db.create_tables([
|
self.db.create_tables([
|
||||||
self._Patient,
|
self._Patient,
|
||||||
self._PatientIndex,
|
self._PatientIndex,
|
||||||
self._Catalog,
|
self._Catalog,
|
||||||
|
self._CatalogIndex,
|
||||||
self._CatalogRecord,
|
self._CatalogRecord,
|
||||||
self._CatalogRecordIndex,
|
self._CatalogRecordIndex,
|
||||||
self._Reception,
|
self._Reception,
|
||||||
|
|
|
@ -345,6 +345,7 @@
|
||||||
<property name="label" translatable="yes">Создать</property>
|
<property name="label" translatable="yes">Создать</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="stock_id">gtk-add</property>
|
<property name="stock_id">gtk-add</property>
|
||||||
|
<signal name="clicked" handler="show_new_catalog_win" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -421,6 +422,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="catalog_filter_changed" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
|
|
Loading…
Reference in New Issue