[med-svn] [gnumed-server] 01/03: New upstream version 21.9
Andreas Tille
tille at debian.org
Tue Sep 13 13:43:09 UTC 2016
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository gnumed-server.
commit b205d81875a414197b75b8b8d3588e4d063007ab
Author: Andreas Tille <tille at debian.org>
Date: Tue Sep 13 15:38:05 2016 +0200
New upstream version 21.9
---
server/bootstrap/fixup_db-v21.conf | 1 +
server/bootstrap/update_db-v20_v21.conf | 1 +
server/doc/schema/gnumed-entire_schema.html | 2 +-
server/pycommon/gmDateTime.py | 42 +++-
server/pycommon/gmShellAPI.py | 2 +
server/pycommon/gmTools.py | 5 +-
.../v20-v21/dynamic/v21-release_notes-dynamic.sql | 42 ++--
.../v21-clin-get_hints_for_patient-fixup.sql | 218 +++++++++++++++++++++
8 files changed, 284 insertions(+), 29 deletions(-)
diff --git a/server/bootstrap/fixup_db-v21.conf b/server/bootstrap/fixup_db-v21.conf
index a14fab1..b5160c4 100644
--- a/server/bootstrap/fixup_db-v21.conf
+++ b/server/bootstrap/fixup_db-v21.conf
@@ -36,6 +36,7 @@ v21-CD_DVD-sleeve.sql
v21-AMTS_Medikationsplan-fixup.sql
v21-ref-auto_hint-smoking_status-fixup.sql
v21-ref-GKV_CU-fixup.sql
+v21-clin-get_hints_for_patient-fixup.sql
$schema$
#----------------------------------
diff --git a/server/bootstrap/update_db-v20_v21.conf b/server/bootstrap/update_db-v20_v21.conf
index d0de655..9b09bb2 100644
--- a/server/bootstrap/update_db-v20_v21.conf
+++ b/server/bootstrap/update_db-v20_v21.conf
@@ -127,6 +127,7 @@ v21-CD_DVD-sleeve.sql
v21-AMTS_Medikationsplan-fixup.sql
v21-ref-auto_hint-smoking_status-fixup.sql
v21-ref-GKV_CU-fixup.sql
+v21-clin-get_hints_for_patient-fixup.sql
$schema$
#----------------------------------
diff --git a/server/doc/schema/gnumed-entire_schema.html b/server/doc/schema/gnumed-entire_schema.html
index 3061072..967cdf5 100644
--- a/server/doc/schema/gnumed-entire_schema.html
+++ b/server/doc/schema/gnumed-entire_schema.html
@@ -112,7 +112,7 @@
<body>
<!-- Primary Index -->
- <p><br><br>Dumped on 2016-08-01</p>
+ <p><br><br>Dumped on 2016-09-12</p>
<h1><a name="index">Index of database - gnumed_v21</a></h1>
<ul>
diff --git a/server/pycommon/gmDateTime.py b/server/pycommon/gmDateTime.py
index 37aed7c..191c3c4 100644
--- a/server/pycommon/gmDateTime.py
+++ b/server/pycommon/gmDateTime.py
@@ -343,6 +343,17 @@ def pydt_replace(dt=None, year=None, month=None, day=None, hour=None, minute=Non
return dt.replace(year = year, month = month, day = day, hour = hour, minute = minute, second = second, microsecond = microsecond, tzinfo = tzinfo)
#---------------------------------------------------------------------------
+def pydt_is_today(dt):
+ now = pyDT.datetime.now(gmCurrentLocalTimezone)
+ if dt.day != now.day:
+ return False
+ if dt.month != now.month:
+ return False
+ if dt.year != now.year:
+ return False
+ return True
+
+#---------------------------------------------------------------------------
def pydt_now_here():
"""Returns NOW @ HERE (IOW, in the local timezone."""
return pyDT.datetime.now(gmCurrentLocalTimezone)
@@ -429,8 +440,11 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tag = _('interval_format_tag::years::y')[-1:]
tmp += u'%s%s' % (int(years), tag)
-
if accuracy_wanted < acc_months:
+ if tmp == u'':
+ if verbose:
+ return _(u'0 years')
+ return u'0%s' % _('interval_format_tag::years::y')[-1:]
return tmp.strip()
if months > 0:
@@ -444,6 +458,10 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tmp += u' %s%s' % (int(months), tag)
if accuracy_wanted < acc_weeks:
+ if tmp == u'':
+ if verbose:
+ return _(u'0 months')
+ return u'0%s' % _('interval_format_tag::months::m')[-1:]
return tmp.strip()
if weeks > 0:
@@ -457,6 +475,10 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tmp += u' %s%s' % (int(weeks), tag)
if accuracy_wanted < acc_days:
+ if tmp == u'':
+ if verbose:
+ return _(u'0 weeks')
+ return u'0%s' % _('interval_format_tag::weeks::w')[-1:]
return tmp.strip()
if days > 0:
@@ -470,6 +492,10 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tmp += u' %s%s' % (int(days), tag)
if accuracy_wanted < acc_hours:
+ if tmp == u'':
+ if verbose:
+ return _(u'0 days')
+ return u'0%s' % _('interval_format_tag::days::d')[-1:]
return tmp.strip()
if hours > 0:
@@ -483,6 +509,10 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tmp += u' %s%s' % (int(hours), tag)
if accuracy_wanted < acc_minutes:
+ if tmp == u'':
+ if verbose:
+ return _(u'0 hours')
+ return u'0/24'
return tmp.strip()
if mins > 0:
@@ -496,6 +526,10 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tmp += u' %s%s' % (int(mins), tag)
if accuracy_wanted < acc_seconds:
+ if tmp == u'':
+ if verbose:
+ return _(u'0 minutes')
+ return u'0/60'
return tmp.strip()
if secs > 0:
@@ -508,7 +542,13 @@ def format_interval(interval=None, accuracy_wanted=None, none_string=None, verbo
tag = u's'
tmp += u' %s%s' % (int(mins), tag)
+ if tmp == u'':
+ if verbose:
+ return _(u'0 seconds')
+ return u'0s'
+
return tmp.strip()
+
#---------------------------------------------------------------------------
def format_interval_medically(interval=None):
"""Formats an interval.
diff --git a/server/pycommon/gmShellAPI.py b/server/pycommon/gmShellAPI.py
index 9b442c2..a21b2d4 100644
--- a/server/pycommon/gmShellAPI.py
+++ b/server/pycommon/gmShellAPI.py
@@ -139,6 +139,7 @@ def detect_external_binary(binary=None):
_log.debug('not running under Windows, not testing .exe/.bat')
return (False, None)
+
#===========================================================================
def find_first_binary(binaries=None):
found = False
@@ -153,6 +154,7 @@ def find_first_binary(binaries=None):
break
return (found, binary)
+
#===========================================================================
def run_command_in_shell(command=None, blocking=False, acceptable_return_codes=None):
"""Runs a command in a subshell via standard-C system().
diff --git a/server/pycommon/gmTools.py b/server/pycommon/gmTools.py
index 781f5b1..79def17 100644
--- a/server/pycommon/gmTools.py
+++ b/server/pycommon/gmTools.py
@@ -77,6 +77,7 @@ u_up_arrow = u'\u2191'
u_arrow2right = u'\u2192' # -->
u_down_arrow = u'\u2193'
u_left_arrow_with_tail = u'\u21a2' # <--<
+u_arrow2right_from_bar = u'\u21a6' # |->
u_arrow2right_until_vertical_bar = u'\u21e5' # -->|
u_sum = u'\u2211' # sigma
u_almost_equal_to = u'\u2248' # approximately / nearly / roughly
@@ -112,12 +113,14 @@ u_male = u'\u2642'
u_male_female = u'\u26a5'
u_checkmark_thin = u'\u2713'
u_checkmark_thick = u'\u2714'
+u_arrow2right_thick = u'\u2794'
u_writing_hand = u'\u270d'
u_pencil_1 = u'\u270e'
u_pencil_2 = u'\u270f'
u_pencil_3 = u'\u2710'
u_latin_cross = u'\u271d'
-u_kanji_yen = u'\u5186' # Yen kanji
+u_arrow2right_until_black_diamond = u'\u291e' # ->*
+u_kanji_yen = u'\u5186' # Yen kanji
u_replacement_character = u'\ufffd'
u_link_symbol = u'\u1f517'
diff --git a/server/sql/v20-v21/dynamic/v21-release_notes-dynamic.sql b/server/sql/v20-v21/dynamic/v21-release_notes-dynamic.sql
index 417de48..a05d886 100644
--- a/server/sql/v20-v21/dynamic/v21-release_notes-dynamic.sql
+++ b/server/sql/v20-v21/dynamic/v21-release_notes-dynamic.sql
@@ -17,36 +17,26 @@ INSERT INTO dem.message_inbox (
) VALUES (
(select pk from dem.staff where db_user = 'any-doc'),
(select pk_type from dem.v_inbox_item_type where type = 'memo' and category = 'administrative'),
- 'Release Notes for GNUmed 1.6.8 (database v21.8)',
- 'GNUmed 1.6.8 Release Notes:
+ 'Release Notes for GNUmed 1.6.9 (database v21.9)',
+ 'GNUmed 1.6.9 Release Notes:
- 1.6.8
+ 1.6.9
-FIX: remove dynamic hint lacking evidence of clinical relevance
-FIX: off-by-one calculation of substance intake end date
-FIX: faulty use of $<gender_mapper>$ in Begleitbrief template
-FIX: fix EMR access deadlock in encounter display widget [thanks Marc]
-FIX: exception on non-ASCII VCF data
-FIX: exception displaying birthday/age of patient w/ estimated DOB
-FIX: list sorting by column header click
+FIX: faulty detection of dynamic hint applicability
+FIX: exception on Orthanc port out of bounds
+FIX: setting address from list in receiver selection widget
+FIX: no EMR user interaction when updating active encounter display
+FIX: faulty by-day measurements display after patient change
-IMPROVED: document tree orgs sort mode tooltips
-IMPROVED: file description shell script
-IMPROVED: less in-your-face default list tooltip
-IMPROVED: update AMTS Medikationsplan to 2.3
-IMPROVED: log file placement
-IMPROVED: form template EA information
-IMPROVED: logging of EMR access locking
-IMPROVED: EMR journal: show applicable dynamic hints
-IMRPOVED: ES translation [thanks Uwe]
-IMPROVED: show comm channels of org units in receiver selection
-IMPROVED: show doc sources as receiver selection candidates
-IMPROVED: letter receiver selection widget layout
-IMPROVED: logging of patient change encounter editing
+IMPROVED: start-end formatting of substance intake
+IMPROVED: select unicode character from SOAP STC context menu
+IMPROVED: edit test results by context menu from lists
+IMPROVED: AMTS data file generation (v2 -> v2.3)
+IMPROVED: color of focussed line in STC-based SOAP editor
+IMPROVED: information in Hx box of patient overview plugin
-NEW: placeholder $ph_cfg::encoding::$
-NEW: blanko AMTS Medikationsplan ~2.3
+NEW: placeholder $<if_not_empty>$
');
-- --------------------------------------------------------------
-select gm.log_script_insertion('v21-release_notes-dynamic.sql', '21.8');
+select gm.log_script_insertion('v21-release_notes-dynamic.sql', '21.9');
diff --git a/server/sql/v20-v21/fixups/v21-clin-get_hints_for_patient-fixup.sql b/server/sql/v20-v21/fixups/v21-clin-get_hints_for_patient-fixup.sql
new file mode 100644
index 0000000..12b2b9c
--- /dev/null
+++ b/server/sql/v20-v21/fixups/v21-clin-get_hints_for_patient-fixup.sql
@@ -0,0 +1,218 @@
+-- ==============================================================
+-- GNUmed database schema change script
+--
+-- License: GPL v2 or later
+-- Author: karsten.hilbert at gmx.net
+--
+-- ==============================================================
+\set ON_ERROR_STOP 1
+
+set check_function_bodies to on;
+--set default_transaction_read_only to off;
+
+-- --------------------------------------------------------------
+drop view if exists staging.journal_without_suppressed_hints cascade;
+
+create view staging.journal_without_suppressed_hints as
+select * from clin.v_emr_journal
+where
+ src_table != 'clin.suppressed_hint'
+;
+
+grant select on staging.journal_without_suppressed_hints to group "gm-staff";
+
+-- --------------------------------------------------------------
+drop function if exists clin.get_hints_for_patient(integer) cascade;
+
+create function clin.get_hints_for_patient(integer)
+ returns setof ref.v_auto_hints
+ language 'plpgsql'
+ as '
+DECLARE
+ _pk_identity ALIAS FOR $1;
+ _hint ref.v_auto_hints%rowtype;
+ _query text;
+ _sanitized_query text;
+ _md5_suppressed text;
+ _rationale4suppression text;
+ _suppression_exists boolean; -- does not mean that the suppression applies
+ _hint_currently_applies boolean; -- regardless of whether suppressed or not
+ _hint_recommendation text;
+-- _exc_state text;
+-- _exc_msg text;
+-- _exc_detail text;
+-- _exc_hint text;
+-- _exc_context text;
+BEGIN
+ -- loop over all defined hints
+ FOR _hint IN SELECT * FROM ref.v_auto_hints WHERE is_active LOOP
+
+ -- is the hint suppressed ?
+ SELECT
+ md5_sum,
+ rationale
+ INTO
+ _md5_suppressed,
+ _rationale4suppression
+ FROM clin.suppressed_hint WHERE
+ fk_hint = _hint.pk_auto_hint
+ AND
+ fk_encounter IN (
+ SELECT pk FROM clin.encounter WHERE fk_patient = _pk_identity
+ );
+ IF FOUND THEN
+ _suppression_exists := TRUE;
+ ELSE
+ _suppression_exists := FALSE;
+ END IF;
+
+ -- does the hint currently apply ? (regardless of whether it is suppressed)
+ _query := replace(_hint.query, ''ID_ACTIVE_PATIENT'', _pk_identity::text);
+ BEGIN
+ EXECUTE _query INTO STRICT _hint_currently_applies;
+ EXCEPTION
+ --WHEN insufficient_privilege THEN RAISE WARNING ''auto hint query failed: %'', _query;
+ WHEN others THEN
+ RAISE WARNING ''auto hint query failed: %'', _query;
+ -- only available starting with PG 9.2:
+ --GET STACKED DIAGNOSTICS
+ -- _exc_state = RETURNED_SQLSTATE,
+ -- _exc_msg = MESSAGE_TEXT,
+ -- _exc_detail = PG_EXCEPTION_DETAIL,
+ -- _exc_hint = PG_EXCEPTION_HINT,
+ -- _exc_context = PG_EXCEPTION_CONTEXT;
+ --RAISE WARNING ''SQL STATE: %'', _exc_state;
+ --RAISE WARNING ''MESSAGE: %'', _exc_msg;
+ --RAISE WARNING ''DETAIL: %'', _exc_detail;
+ --RAISE WARNING ''HINT: %'', _exc_hint;
+ --RAISE WARNING ''CONTEXT: %'', _exc_context;
+ -- workaround for 9.1:
+ RAISE WARNING ''SQL STATE: %'', SQLSTATE;
+ RAISE WARNING ''MESSAGE: %'', SQLERRM;
+ _hint.title := ''ERROR checking for ['' || _hint.title || ''] !'';
+ _hint.hint := _query;
+ RETURN NEXT _hint;
+ -- process next hint
+ CONTINUE;
+ END;
+
+ -- does it _really_ apply ?
+ -- re-run against staging.journal_without_suppressed_hints which does
+ -- not contain suppressed hints -- because it may have applied only
+ -- because clin.v_emr_journal does contain formatted suppressed hints
+ IF _hint_currently_applies THEN
+ _sanitized_query := replace(_query, ''clin.v_emr_journal'', ''staging.journal_without_suppressed_hints'');
+ -- but only re-run if actually different
+ IF _sanitized_query <> _query THEN
+ BEGIN
+ EXECUTE _sanitized_query INTO STRICT _hint_currently_applies;
+ EXCEPTION
+ --WHEN insufficient_privilege THEN RAISE WARNING ''sanitized auto hint query failed: %'', _sanitized_query;
+ WHEN others THEN
+ RAISE WARNING ''sanitized auto hint query failed: %'', _sanitized_query;
+ -- only available starting with PG 9.2:
+ --GET STACKED DIAGNOSTICS
+ -- _exc_state = RETURNED_SQLSTATE,
+ -- _exc_msg = MESSAGE_TEXT,
+ -- _exc_detail = PG_EXCEPTION_DETAIL,
+ -- _exc_hint = PG_EXCEPTION_HINT,
+ -- _exc_context = PG_EXCEPTION_CONTEXT;
+ --RAISE WARNING ''SQL STATE: %'', _exc_state;
+ --RAISE WARNING ''MESSAGE: %'', _exc_msg;
+ --RAISE WARNING ''DETAIL: %'', _exc_detail;
+ --RAISE WARNING ''HINT: %'', _exc_hint;
+ --RAISE WARNING ''CONTEXT: %'', _exc_context;
+ -- workaround for 9.1:
+ RAISE WARNING ''SQL STATE: %'', SQLSTATE;
+ RAISE WARNING ''MESSAGE: %'', SQLERRM;
+ _hint.title := ''ERROR checking for ['' || _hint.title || ''] !'';
+ _hint.hint := _sanitized_query;
+ RETURN NEXT _hint;
+ -- process next hint
+ CONTINUE;
+ END;
+ END IF;
+ END IF;
+
+ IF _suppression_exists THEN
+ -- is the hint definition still the same as at the time of suppression ?
+ IF _md5_suppressed = _hint.md5_sum THEN
+ -- yes, but does this hint currently apply ?
+ IF _hint_currently_applies THEN
+ -- suppressed, suppression valid, and hint applies: skip this hint
+ CONTINUE;
+ END IF;
+ -- suppressed, suppression valid, hint does NOT apply:
+ -- skip but invalidate suppression, because:
+ -- * previously the hint applied and the user suppressed it,
+ -- * then the patient changed such that the hint does not
+ -- apply anymore (but the suppression is still valid),
+ -- * when the patient changes again, the hint might apply again
+ -- * HOWEVER - since the suppression would still be valid - the
+ -- hint would magically get suppressed again (which is
+ -- medically unsafe) ...
+ -- after invalidation, the hint will no longer be suppressed,
+ -- however - since it does not currently apply it - it will
+ -- still not be returned until it applies again ...
+ --
+ -- -----------------------------------------------------------------------
+ -- UNFORTUNATELY, the following is currently not _possible_ because
+ -- we are running inside a READONLY transaction (due to inherent
+ -- security risks when running arbitrary user queries [IOW the hint
+ -- SQL] against the database) and we cannot execute a
+ -- sub-transaction as READWRITE :-/
+ --
+ --UPDATE clin.suppressed_hint
+ --SET md5_sum = ''invalidated''::text -- will not ever match any md5 sum
+ --WHERE
+ -- fk_encounter IN (
+ -- SELECT pk FROM clin.encounter WHERE fk_patient = _pk_identity
+ -- )
+ -- AND
+ -- fk_hint = _hint.pk_auto_hint;
+ -- -----------------------------------------------------------------------
+ --
+ -- hence our our workaround is to, indeed, return the hint but
+ -- tag it with a magic rationale, by means of which the client
+ -- can detect it to be in need of invalidation:
+ _hint.title := ''HINT DOES NOT APPLY BUT NEEDS INVALIDATION OF EXISTING SUPPRESSION ['' || _hint.title || ''].'';
+ _hint.rationale4suppression := ''magic_tag::please_invalidate_suppression'';
+ RETURN NEXT _hint;
+ CONTINUE;
+ END IF;
+ -- suppression exists but hint definition must have changed
+ -- does the new hint apply ?
+ IF _hint_currently_applies THEN
+ -- yes: ignore the suppression but provide previous
+ -- rationale for suppression to the user
+ _hint.rationale4suppression := _rationale4suppression;
+ -- retrieve recommendation
+ SELECT clin._get_recommendation_for_patient_hint(_hint.recommendation_query, _pk_identity) INTO STRICT _hint_recommendation;
+ _hint.recommendation := _hint_recommendation;
+ RETURN NEXT _hint;
+ CONTINUE;
+ END IF;
+ -- no, new hint does not apply, so ask for
+ -- invalidation of suppression (see above)
+ _hint.title := ''HINT DOES NOT APPLY BUT NEEDS INVALIDATION OF EXISTING SUPPRESSION ['' || _hint.title || ''].'';
+ _hint.rationale4suppression := ''magic_tag::please_invalidate_suppression'';
+ RETURN NEXT _hint;
+ CONTINUE;
+ END IF;
+
+ -- hint is not suppressed
+ -- does the hint currently apply ?
+ IF _hint_currently_applies THEN
+ -- yes: retrieve recommendation
+ SELECT clin._get_recommendation_for_patient_hint(_hint.recommendation_query, _pk_identity) INTO STRICT _hint_recommendation;
+ _hint.recommendation := _hint_recommendation;
+ RETURN NEXT _hint;
+ END IF;
+ -- no: ignore it and process next hint in LOOP
+
+ END LOOP;
+ RETURN;
+END;';
+
+-- --------------------------------------------------------------
+select gm.log_script_insertion('v21-clin-get_hints_for_patient-fixup.sql', '21.9');
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/gnumed-server.git
More information about the debian-med-commit
mailing list