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 <[email protected]>
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: [email protected]
+--
+-- ==============================================================
+\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

_______________________________________________
debian-med-commit mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit

Reply via email to