[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