[med-svn] [gnumed-server] 01/03: Imported Upstream version 21.8

Andreas Tille tille at debian.org
Wed Aug 3 14:40:13 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 bf3660b653daa5ebcc433ff3afa49b3445604ae3
Author: Andreas Tille <tille at debian.org>
Date:   Wed Aug 3 16:28:48 2016 +0200

    Imported Upstream version 21.8
---
 server/bootstrap/fixup_db-v21.conf                 |   1 +
 server/bootstrap/update_db-v20_v21.conf            |   5 +-
 server/doc/schema/gnumed-entire_schema.html        |   2 +-
 server/pycommon/gmDateTime.py                      |   8 +
 server/pycommon/gmTools.py                         |  42 +-
 server/sql/v20-v21/data/v21-Begleitbrief.tex       |   2 +-
 ...dikationsplan_AMTS-2.3-nicht_konform-blanko.tex | 417 +++++++++++++++++++
 .../v21-Medikationsplan_AMTS-2.3-nicht_konform.tex | 447 ++++++++++++++++++++
 .../v20-v21/data/v21-Medikationsplan_AMTS-2.3.tex  | 463 +++++++++++++++++++++
 .../v20-v21/dynamic/v21-release_notes-dynamic.sql  |  45 +-
 .../fixups/v21-AMTS_Medikationsplan-fixup.sql      | 112 +++++
 .../v21-ref-auto_hint-klug_entscheiden_pulmo.sql   |  61 +--
 .../python/v21-import-form-template-fixups.py      |  46 +-
 13 files changed, 1566 insertions(+), 85 deletions(-)

diff --git a/server/bootstrap/fixup_db-v21.conf b/server/bootstrap/fixup_db-v21.conf
index 6ff6ffa..a14fab1 100644
--- a/server/bootstrap/fixup_db-v21.conf
+++ b/server/bootstrap/fixup_db-v21.conf
@@ -33,6 +33,7 @@ v21-ref-auto_hint-tetanus_STIKO.sql
 v21-ref-auto_hint-klug_entscheiden_pulmo.sql
 v21-ref-auto_hint-klug_entscheiden_endokrino.sql
 v21-CD_DVD-sleeve.sql
+v21-AMTS_Medikationsplan-fixup.sql
 v21-ref-auto_hint-smoking_status-fixup.sql
 v21-ref-GKV_CU-fixup.sql
 $schema$
diff --git a/server/bootstrap/update_db-v20_v21.conf b/server/bootstrap/update_db-v20_v21.conf
index 12d41f9..d0de655 100644
--- a/server/bootstrap/update_db-v20_v21.conf
+++ b/server/bootstrap/update_db-v20_v21.conf
@@ -124,6 +124,7 @@ v21-ref-auto_hint-tetanus_STIKO.sql
 v21-ref-auto_hint-klug_entscheiden_pulmo.sql
 v21-ref-auto_hint-klug_entscheiden_endokrino.sql
 v21-CD_DVD-sleeve.sql
+v21-AMTS_Medikationsplan-fixup.sql
 v21-ref-auto_hint-smoking_status-fixup.sql
 v21-ref-GKV_CU-fixup.sql
 $schema$
@@ -250,8 +251,8 @@ requests on results::::select count(1) from clin.test_result where fk_request is
 clinical code links (total) - internal consistency::::select True
 	select ((select count(1) from clin.lnk_code2item_root) = (select ((select count(1) from clin.lnk_code2procedure) + (select count(1) from clin.lnk_code2rfe) + (select count(1) from clin.lnk_code2aoe) + (select count(1) from clin.lnk_code2episode) + (select count(1) from clin.lnk_code2h_issue) + (select count(1) from clin.lnk_code2narrative))))
 paperwork templates::::select count(1) from ref.paperwork_templates
-	select count(1) - 4 from ref.paperwork_templates
-automatic hints::::select count(1) + 10 from ref.auto_hint
+	select count(1) - 7 from ref.paperwork_templates
+automatic hints::::select count(1) + 9 from ref.auto_hint
 	select count(1) from ref.auto_hint
 suppressed hints::::select count(1) from clin.suppressed_hint
 	select count(1) from clin.suppressed_hint
diff --git a/server/doc/schema/gnumed-entire_schema.html b/server/doc/schema/gnumed-entire_schema.html
index 82a80df..3061072 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-07-07</p>
+	<p><br><br>Dumped on 2016-08-01</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 06cd3ea..37aed7c 100644
--- a/server/pycommon/gmDateTime.py
+++ b/server/pycommon/gmDateTime.py
@@ -240,6 +240,7 @@ def mxdt2py_dt(mxDateTime):
 			mxDateTime.tz
 		)
 		raise
+
 #===========================================================================
 def format_dob(dob, format='%Y %b %d', encoding=None, none_string=None, dob_is_estimated=False):
 	if dob is None:
@@ -252,6 +253,7 @@ def format_dob(dob, format='%Y %b %d', encoding=None, none_string=None, dob_is_e
 		return u'%s%s' % (u'\u2248', dob_txt)
 
 	return dob_txt
+
 #---------------------------------------------------------------------------
 def pydt_strftime(dt=None, format='%Y %b %d  %H:%M.%S', encoding=None, accuracy=None, none_str=None):
 
@@ -296,6 +298,7 @@ def pydt_strftime(dt=None, format='%Y %b %d  %H:%M.%S', encoding=None, accuracy=
 		dt.minute,
 		dt.second
 	)
+
 #---------------------------------------------------------------------------
 def pydt_replace(dt=None, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, tzinfo=None, strict=True):
 
@@ -338,13 +341,16 @@ def pydt_replace(dt=None, year=None, month=None, day=None, hour=None, minute=Non
 			day = 30
 
 	return dt.replace(year = year, month = month, day = day, hour = hour, minute = minute, second = second, microsecond = microsecond, tzinfo = tzinfo)
+
 #---------------------------------------------------------------------------
 def pydt_now_here():
 	"""Returns NOW @ HERE (IOW, in the local timezone."""
 	return pyDT.datetime.now(gmCurrentLocalTimezone)
+
 #---------------------------------------------------------------------------
 def pydt_max_here():
 	return pyDT.datetime.max.replace(tzinfo = gmCurrentLocalTimezone)
+
 #---------------------------------------------------------------------------
 def wx_now_here(wx=None):
 	"""Returns NOW @ HERE (IOW, in the local timezone."""
@@ -606,6 +612,7 @@ def is_leap_year(year):
 		return True
 
 	return False
+
 #---------------------------------------------------------------------------
 def calculate_apparent_age(start=None, end=None):
 	"""The result of this is a tuple (years, ..., seconds) as one would
@@ -706,6 +713,7 @@ def calculate_apparent_age(start=None, end=None):
 			seconds = seconds - 1
 
 	return (years, months, days, hours, minutes, seconds)
+
 #---------------------------------------------------------------------------
 def format_apparent_age_medically(age=None):
 	"""<age> must be a tuple as created by calculate_apparent_age()"""
diff --git a/server/pycommon/gmTools.py b/server/pycommon/gmTools.py
index bbf50cc..781f5b1 100644
--- a/server/pycommon/gmTools.py
+++ b/server/pycommon/gmTools.py
@@ -82,6 +82,7 @@ u_sum = u'\u2211'								# sigma
 u_almost_equal_to = u'\u2248'					# approximately / nearly / roughly
 u_corresponds_to = u'\u2258'
 u_infinity = u'\u221E'
+u_arrow2right_until_vertical_bar2 = u'\u2b72'	# -->|
 u_diameter = u'\u2300'
 u_checkmark_crossed_out = u'\u237B'
 u_box_vert_left = u'\u23b8'
@@ -677,6 +678,43 @@ def get_unique_filename(prefix=None, suffix=None, tmp_dir=None, include_timestam
 
 	return filename
 
+#---------------------------------------------------------------------------
+def __make_symlink_on_windows(physical_name, link_name):
+	import ctypes
+	csl = ctypes.windll.kernel32.CreateSymbolicLinkW
+	csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
+	csl.restype = ctypes.c_ubyte
+	if os.path.isdir(physical_name):
+		flags = 1
+	else:
+		flags = 0
+	ret_code = csl(link_name, physical_name.replace('/', '\\'), flags)
+	_log.debug('ctypes.windll.kernel32.CreateSymbolicLinkW() exit code: %s', ret_code)
+	if ret_code == 0:
+		raise ctypes.WinError()
+	return ret_code
+
+#---------------------------------------------------------------------------
+def mklink(physical_name, link_name, overwrite=False):
+
+	_log.debug('creating symlink (overwrite = %s):', overwrite)
+	_log.debug('link [%s] =>', link_name)
+	_log.debug('=> physical [%s]', physical_name)
+
+	if os.path.exists(link_name):
+		_log.debug('link exists')
+		if overwrite:
+			return True
+		return False
+
+	try:
+		os.symlink(physical_name, link_name)
+	except AttributeError:
+		_log.debug('Windows does not have os.symlink(), resorting to ctypes')
+		__make_symlink_on_windows(physical_name, link_name)
+
+	return True
+
 #===========================================================================
 def import_module_from_directory(module_path=None, module_name=None, always_remove_path=False):
 	"""Import a module from any location."""
@@ -1838,10 +1876,10 @@ second line\n
 	#test_fname_stem()
 	#test_tex_escape()
 	#test_dir_is_empty()
-	#test_compare_dicts()
+	test_compare_dicts()
 	#test_rm_dir()
 	#test_strip_prefix()
 	#test_shorten_text()
-	test_format_compare_dicts()
+	#test_format_compare_dicts()
 
 #===========================================================================
diff --git a/server/sql/v20-v21/data/v21-Begleitbrief.tex b/server/sql/v20-v21/data/v21-Begleitbrief.tex
index 66737c4..ba39a42 100644
--- a/server/sql/v20-v21/data/v21-Begleitbrief.tex
+++ b/server/sql/v20-v21/data/v21-Begleitbrief.tex
@@ -155,7 +155,7 @@
 
 
 % Anrede
-\opening{Sehr $<gender_mapper::geehrter Herr//geehrte Frau//Hallo::>$ $<receiver_name::::>$,}
+\opening{$<free_text::Anrede, z.B. "Sehr geehrte Frau" (wird automatisch ergänzt durch " <Name des Empfängers>,")::140>$ $<receiver_name::::>$,}
 
 
 % Brieftext
diff --git a/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3-nicht_konform-blanko.tex b/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3-nicht_konform-blanko.tex
new file mode 100644
index 0000000..70d1b5e
--- /dev/null
+++ b/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3-nicht_konform-blanko.tex
@@ -0,0 +1,417 @@
+%------------------------------------------------------------------
+% Medikationsplan gemäß AMTS 2.3 für GNUmed (http://www.gnumed.de)
+%
+% License: GPL v2 or later
+%
+% Author: karsten.hilbert at gmx.net
+% Thanks to: G.Hellmann
+%
+% requires pdflatex to be run with -recorder option
+%------------------------------------------------------------------
+
+% debugging
+\listfiles
+\errorcontextlines 10000
+
+\documentclass[
+	version=last,
+	paper=landscape,
+	paper=a4,
+	DIV=9,									% help typearea find a good Satzspiegel
+	BCOR=0mm,								% keine BindeCORrektur
+	fontsize=12pt,							% per spec
+	parskip=full,							% Absätze mit Leerzeilen trennen, kein Einzug
+	headsepline=off,
+	footsepline=off,
+	titlepage=false
+]{scrartcl}
+
+%------------------------------------------------------------------
+% packages
+\usepackage{scrlayer-scrpage}				% Kopf- und Fußzeilen
+\usepackage{geometry}						% setup margins
+\usepackage{microtype}						% micro-adjustments to typesetting
+\usepackage[cjkjis,graphics]{ucs}			% lots of UTF8 symbols, breaks with xelatex
+\usepackage[T1]{fontenc}					% fonts are T1
+\usepackage[ngerman]{babel}					% Deutsch und Trennung
+\usepackage[utf8x]{inputenc}				% content is UTF8, breaks with xelatex
+\usepackage{textcomp}						% Symbole für Textmodus zum Escapen
+\usepackage{ragged2e}						% improved alignment, needed for raggedleft in header table cell
+\usepackage{tabularx}						% bessere Tabellen
+\usepackage{tabu}							% bessere Tabellen
+\usepackage{longtable}						% Tabellen über mehrere Seiten
+\usepackage[table]{xcolor}					% gray headers
+\usepackage{helvet}							% Arial alike Helvetica
+\usepackage{lastpage}						% easy access to page number of last page
+\usepackage{embedfile}						% store copy of data file for producing data matrix inside PDF
+\usepackage{array}							% improved column styles
+\usepackage[abspath]{currfile}				% generically refer to input file
+\usepackage{graphicx}						% Grafiken laden (datamatrix)
+\usepackage[space]{grffile}					% besserer Zugriff auf Grafikdateien
+\usepackage[export]{adjustbox}				% improved options for \includegraphics
+\usepackage{marvosym}						% Symbole: Handy, Telefon, E-Mail, used in non-conformant layout
+%\usepackage[ocgcolorlinks=true]{hyperref}	% aktive URLs, needs to be loaded last, most of the time
+\usepackage{hyperref}						% aktive URLs, needs to be loaded last, most of the time
+
+% debugging:
+%\usepackage{showkeys}							% print labels (anchors and stuff) as margin notes
+%\usepackage{interfaces}						% \papergraduate
+
+%\usepackage{calc}						% \widthof (für signature)
+
+%------------------------------------------------------------------
+% setup:
+% - debugging
+%\tracingtabu=3
+%\usetikz{basic}
+%\hypersetup{debug=true}
+
+
+% - placeholder handler options
+% switch on ellipsis handling:
+$<ph_cfg::ellipsis//…//%% <%(name)s> set to [%(value)s]::>$
+
+
+% - PDF metadata
+\hypersetup{
+	pdftitle = {Medikationsplan: $<name::%(firstnames)s %(lastnames)s::>$, $<date_of_birth::%d.%b %Y::>$},
+	pdfauthor = {$<current_provider::::>$, $<praxis::%(branch)s, %(praxis)s::>$},
+	pdfsubject = {Medikationsplan (AMTS, NICHT KONFORM)},
+	pdfproducer = {GNUmed $<client_version::::>$, Vorlage $<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]},
+	pdfdisplaydoctitle = true
+}
+
+
+% - precise positioning of things to satisfy spec
+\setlength{\tabcolsep}{0pt}
+\setlength{\parskip}{0pt}
+\setlength{\topskip}{0pt}
+\setlength{\floatsep}{0pt}
+\setlength{\textfloatsep}{0pt}
+
+
+% - page
+\geometry{
+	verbose,
+	% debugging:
+%	showframe,											% show page frames
+%	showcrop,											% show crop marks
+	a4paper,
+	landscape,
+	bindingoffset=0pt,
+%
+	% top-to-bottom on page:
+	top=8mm,					% per spec
+	includehead,				% into <total body>, not into topmargin
+	headheight=48mm,			% per spec, decrease textheight, top margin (8mm) + actual header size (40mm)
+	headsep=0mm,				% no more space until *top* of textheight (not baseline of first line ...)
+	%textheight,				% is calculated by the other dimensions, should amount to 144mm (210 - (8+40+0+10+9))
+	includefoot,				% into <total body>, not into bottommargin
+	% need to be calculated to work:
+	footskip=\dimexpr+\ht\strutbox\relax,		% 10mm per spec, decreases textheight
+	bottom=\dimexpr15mm+\ht\strutbox\relax,		% 8mm per spec, 15mm found empirically (includes the 10mm footskip, but why ?)
+%
+	% left-to-right on page:
+	left=8mm,					% per spec
+	%textwidth,					% is calculated by the other dimensions, should amount to 281mm (297 - (8+0+0+8))
+	includemp,					% include marginparsep and marginparwidth into width, decreases textwidth (but set to 0 below)
+	marginparsep=0mm,			% no margin notes offset
+	marginparwidth=0mm,			% no margin notes width
+	right=8mm					% per spec
+}
+
+
+% - font: Arial (Helvetica)
+\renewcommand{\rmdefault}{phv}
+\renewcommand{\sfdefault}{phv}
+
+
+% - tabu
+\tabulinesep=^1mm_1mm
+
+
+% - header = top part
+\lohead{
+	\upshape
+	\begin{tabu} to \textwidth {|>{\raggedleft\arraybackslash}p{7cm}|@{\hspace{1mm}}X[-1,L]@{\hspace{1cm}}X[-1,R]|p{4.3cm}}
+			\tabucline{1-3}
+			% line 1
+				\fontsize{20pt}{22pt}\selectfont					% \fontsize{<font size>}{<line spacing>}
+				%(1)\ % debugging
+				\textbf{\href{http://www.kbv.de/html/medikationsplan.php}{Medikationsplan}} \newline
+			% line 2
+				\fontsize{14pt}{16pt}\selectfont
+				%(2)\ % debugging
+				Seite 1 von 1 \newline
+			% line 3
+				\fontsize{12pt}{14pt}\selectfont
+				%(3) % debugging
+				% as long as we don't have certification or claim conformance we can put here any image we want :-)
+				\includegraphics[scale=5,max height=2.4cm,center]{$<<patient_photo::%s//image/png//.png::>>$}
+		&
+			% line 1: patient name, part 1
+				\fontsize{14pt}{20pt}\selectfont									% keep line spacing in sync with left hand side
+				%(1)\ % debugging
+				$<ph_cfg::ellipsis//NONE//%% <%(name)s> set to [%(value)s]::>$		% switch off ellipsis handling so first range of name does not get one if too long
+				für:\ \textbf{$<name::%(firstnames)s %(lastnames)s::1-37>$} \newline
+				$<ph_cfg::ellipsis//…//%% <%(name)s> set to [%(value)s]::>$			% but reenable in case second line of name still too long so that we need an ellipsis
+			% line 2: patient name, part 2, if any
+				\fontsize{14pt}{16pt}\selectfont									% keep line spacing in sync with left hand side
+				%(2)\ % debugging
+				$<name::\textbf{%(firstnames)s %(lastnames)s}::38-90>$\ \newline
+			% line 3: provider name
+				\fontsize{12pt}{14pt}\selectfont
+				%(3)\ % debugging
+				ausgedruckt von: $<current_provider::::30>$ \newline
+			% line 4: praxis name
+				%(4)\ % debugging
+				\href{http://$<praxis_comm::web::>$}{$<praxis::%(branch)s, %(praxis)s::50>$} \newline
+			% line 5: praxis address: street / number / zip / location
+				%(5)\ % debugging
+				%         (use \mbox{TEXT} to prevent TEXT from getting hyphenated)
+				$<ph_cfg::argumentsdivider//||//%% <%(name)s> set to [%(value)s]::>$
+				$<praxis_address::\href{http://nominatim.openstreetmap.org/search/$<<<url_escape::$<<praxis_address::%(country)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(urb)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(street)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(number)s::>>$::>>>$?limit=3}{\mbox{$<<praxis_address::%(street)s %(number)s %(subunit)s,%(postcode)s %(urb)s::55>>$}}::>$\ \newline
+				$<ph_cfg::argumentsdivider//DEFAULT//%% <%(name)s> set back to default of [%(value)s]::>$
+			% line 6: praxis phone number
+				%(6)\ % debugging
+				$<<praxis_comm::workphone//\href{tel:$<praxis_comm::workphone::>$}{$<praxis_comm::workphone//\Telefon\ %(url)s::50>$}::>>$\ \newline
+			% line 7: praxis email address
+				%(7)\ % debugging
+				$<<praxis_comm::email//\href{mailto:$<praxis_comm::email::>$}{$<praxis_comm::email//\Email\ %(url)s::60>$}::>>$\ 
+		&
+			% line 1: patient DOB
+				\fontsize{14pt}{16pt}\selectfont				% keep line spacing in sync with left hand side
+				%(1)\ % debugging
+				geb.\ am: \textbf{$<date_of_birth::%d.%b %Y::>$} \newline
+			% line 2: patient gender -- would benefit from an improved $gender_symbol$ placeholder
+				\fontsize{12pt}{16pt}\selectfont				% keep line spacing in sync with left hand side
+				%(2)\ % debugging
+				Geschl.: $<gender_mapper::m//w//unbestimmt::>$ \newline
+			% line 3: empty
+				\fontsize{12pt}{14pt}\selectfont				% keep line spacing in sync with left hand side
+				%(3)\ % debugging
+				\ \newline
+%			% line 4
+%				$<ph_cfg::ellipsis//NONE//%% <%(name)s> set to [%(value)s]::>$		% switch off ellipsis handling so first line of parameters does not get one if too long
+%				$<<range_of::$<test_result::LOINC=XX//,Gew.: %s::>$$<test_result::LOINC=XX//,Krea.: %s::>$$<breastfeeding::,stillend//::>$$<pregnant::,schwanger (ET %(edc)s)////%d.%b %Y::>$::25>>$\newline
+%			% line 5
+%				$<ph_cfg::ellipsis//…//%% <%(name)s> set to [%(value)s]::>$			% but reenable in case second line of parameters still too long so that we need an ellipsis
+%				$<<range_of::$<test_result::LOINC=XX//,Gew.: %s::>$$<test_result::LOINC=XX//,Krea.: %s::>$$<breastfeeding::,stillend//::>$$<pregnant::,schwanger (ET %(edc)s)////%d.%m.%Y::>$::26-50>>$\ \newline
+%			% line 6: parameter: allergies
+%			%         %$<allergy_state::::25>$
+%				Allerg/Unv: Seite \pageref{LastPage}\ \hyperref[AnchorAllergieDetails]{unten}\newline
+			% line 4: empty
+				%(4)\ % debugging
+				\ \newline
+			% line 5: empty
+				%(5)\ % debugging
+				\ \newline
+			% line 6: parameter: allergies ($<allergy_state::::25>$)
+				%(6)\ % debugging
+				Allerg/Unv: siehe \pageref{LastPage}\ \hyperref[AnchorAllergieDetails]{unten} \newline
+			% line 7: soll eigentlich linksbündig ...
+				%(7)\ % debugging
+				ausgedruckt am: $<today::%d.%b %Y::>$\ 
+		&
+			% empty plan cannot have datamatrix
+			%\includegraphics[valign=t,raise=6ex,max height=4cm,max width=4cm,center]{$<<amts_png_file_current_page::::>>$}
+		\tabularnewline
+		\tabucline{1-3}
+	\end{tabu}
+}
+%\lehead{}
+%\cehead{}
+%\cohead{}
+%\rehead{}
+%\rohead{}
+
+
+% footer setup = bottom part
+\lofoot{{
+	\begin{tabular}[t]{p{12cm}p{16cm}}
+		\hline
+		{	% left side: Versionsinformationen
+			\fontsize{8pt}{9pt}\selectfont
+			\upshape
+			\parbox[t][1cm][t]{12cm}{
+				\raggedright
+				Für Vollständigkeit und Aktualität des Medikationsplans wird keine Gewähr übernommen.\newline
+				NICHT KONFORM zu: de-DE-Version 2.3
+			}
+		} & {
+			% middle part: Herstellerfeld
+			\fontsize{8pt}{9pt}\selectfont
+			\parbox[t][1cm][t]{16cm}{
+				\centering
+				GNUmed $<client_version::::>$ --- \href{http://www.gnumed.org}{www.gnumed.org}\newline
+				$<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]
+			}
+		}
+	\end{tabular}
+}}
+\lefoot{{
+	\begin{tabular}[t]{p{12cm}p{16cm}}
+		\hline
+		{	% left side: Versionsinformationen
+			\fontsize{8pt}{9pt}\selectfont
+			\upshape
+			\parbox[t][1cm][t]{12cm}{
+				\raggedright
+				Für Vollständigkeit und Aktualität des Medikationsplans wird keine Gewähr übernommen.\newline
+				NICHT KONFORM zu: de-DE-Version 2.3
+			}
+		} & {
+			% middle part: Herstellerfeld
+			\fontsize{8pt}{9pt}\selectfont
+			\parbox[t][1cm][t]{16cm}{
+				\centering
+				GNUmed $<client_version::::>$ --- \href{http://www.gnumed.org}{www.gnumed.org}\newline
+				$<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]
+			}
+		}
+	\end{tabular}
+}}
+\cefoot{}
+\cofoot{}
+\refoot{}
+\rofoot{}
+
+%------------------------------------------------------------------
+\begin{document}
+
+% debugging
+%\papergraduate
+
+% middle part: Medikationsliste
+\begin{longtable} {|
+	% column definition
+	p{4cm}|									% Wirkstoff
+	p{4.4cm}|								% Handelsname
+	>{\RaggedLeft}p{1.8cm}|					% Stärke
+	p{1.8cm}|								% Form
+	p{0.8cm}								% Dosierung: morgens
+	p{0.8cm}								% Dosierung: mittags
+	p{0.8cm}								% Dosierung: abends
+	p{0.8cm}|								% Dosierung: zur Nacht
+	p{2.0cm}|								% Einheit
+	p{6.4cm}|								% Hinweise
+	p{4.3cm}|								% Grund
+}
+	% Tabellenkopf:
+	\hline
+	\rowcolor{gray!20}
+	\fontsize{14pt}{16pt}\selectfont \centering Wirkstoff &
+	\fontsize{14pt}{16pt}\selectfont \centering Handelsname &
+	\fontsize{14pt}{16pt}\selectfont \centering Stärke &
+	\fontsize{14pt}{16pt}\selectfont \centering Form &
+%	\fontsize{8pt}{8pt}\selectfont \centering mor-\newline{}gens &
+%	\fontsize{8pt}{8pt}\selectfont \centering mit-\newline{}tags &
+%	\fontsize{8pt}{8pt}\selectfont \centering abends &
+%	\fontsize{8pt}{8pt}\selectfont \centering zur\newline{}Nacht &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{morgens} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{mittags} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{abends} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{z.\newline{}Nacht} &
+	\fontsize{14pt}{16pt}\selectfont \centering Einheit &
+	\fontsize{14pt}{16pt}\selectfont \centering Hinweise &
+	\fontsize{14pt}{16pt}\selectfont \centering Grund
+	\endhead
+	% Tabellenende auf 1. und 2. Seite
+	\endfoot
+	% Tabellenende auf letzter (3.) Seite
+	\endlastfoot
+	% Tabelleninhalt:
+\hline
+ & & & & & & & & & & \tabularnewline							% 1
+\hline
+ & & & & & & & & & & \tabularnewline							% 2
+\hline
+ & & & & & & & & & & \tabularnewline							% 3
+\hline
+ & & & & & & & & & & \tabularnewline							% 4
+\hline
+ & & & & & & & & & & \tabularnewline							% 5
+\hline
+ & & & & & & & & & & \tabularnewline							% 6
+\hline
+ & & & & & & & & & & \tabularnewline							% 7
+\hline
+ & & & & & & & & & & \tabularnewline							% 8
+\hline
+ & & & & & & & & & & \tabularnewline							% 9
+\hline
+ & & & & & & & & & & \tabularnewline							% 10
+
+% allergy state: Zwischenüberschrift: 31 Zeichen, $..., 14pt, no frame, \textwidth
+\hline
+\multicolumn{11}{>{\RaggedRight}p{27.9cm}}{
+	\rule{0pt}{4.5mm}
+	\fontsize{14pt}{16pt}\selectfont{}
+	$<allergy_state::::>$
+	\label{AnchorAllergieDetails}
+} \tabularnewline												% 11
+
+% allergy state comment - not supported by GNUmed just yet :-/
+% Freitextzeile: 200 Zeichen, @..., \textwidth
+%\multicolumn{11}{>{\RaggedRight}p{27.9cm}}{
+%	$<allergy_state::%(comment)s::>$
+%} \tabularnewline
+
+% allergy rows, hopefully no more than 4 ...
+% Freitextzeile: 200 Zeichen, @...								% 12-15
+$<allergies::\multicolumn{1}{>{\RaggedRight}p{4cm}}{%(descriptor)s} & \multicolumn{10}{>{\RaggedRight}p{23.9cm}}{%(l10n_type)s: %(reaction)s}\tabularnewline::>$
+\hline
+\end{longtable}
+
+%------------------------------------------------------------------
+% include data in PDF for easier processing:
+
+% VCF of creator
+\IfFileExists{$<praxis_vcf::::>$}{
+	\embedfile[
+		desc=01) digitale Visitenkarte des Erstellers des Medikationsplans,
+		mimetype=text/vcf,
+		ucfilespec=AMTS-Medikationsplan-Ersteller.vcf
+	]{$<praxis_vcf::::>$}
+}{\typeout{[$<praxis_vcf::::>$] not found}}
+
+% LaTeX source code from which the PDF was produced
+\embedfile[
+	desc=02) LaTeX-Quellcode des Medikationsplans (übersetzbar mit "pdflatex -recorder -interaction=nonstopmode \currfilename\ "),
+	mimetype=text/plain,
+	ucfilespec=\currfilename
+]{\currfileabspath}
+
+% patient photo
+\IfFileExists{$<patient_photo::%s//image/png//.png::>$}{
+	\embedfile[
+		desc=11) Patientenphoto,
+		mimetype=image/png,
+		ucfilespec=Patientenphoto.png
+	]{$<patient_photo::%s//image/png//.png::>$}
+}{\typeout{[$<patient_photo::%s//image/png//.png::>$] (patient photo) not found}}
+
+% patient vcf -- really a good idea ? (it would tell more
+% about the patient than is defined by the Medikationsplan specs)
+\IfFileExists{$<patient_vcf::::>$}{
+	\embedfile[
+		desc=12) digitale Visitenkarte des Patienten,
+		mimetype=text/vcf,
+		ucfilespec=Patient.vcf
+	]{$<patient_vcf::::>$}
+}{\typeout{[$<patient_vcf::::>$] (patient VCF) not found}}
+
+% patient gdt -- really a good idea ? (it would tell more
+% about the patient than is defined by the Medikationsplan specs)
+\IfFileExists{$<patient_gdt::::>$}{
+	\embedfile[
+		desc=13) GDT-Datei des Patienten,
+		mimetype=text/plain,
+		ucfilespec=Patient.gdt
+	]{$<patient_gdt::::>$}
+}{\typeout{[$<patient_gdt::::>$] (patient GDT) not found}}
+
+%------------------------------------------------------------------
+
+\end{document}
+%------------------------------------------------------------------
diff --git a/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3-nicht_konform.tex b/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3-nicht_konform.tex
new file mode 100644
index 0000000..4134bf7
--- /dev/null
+++ b/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3-nicht_konform.tex
@@ -0,0 +1,447 @@
+%------------------------------------------------------------------
+% Medikationsplan gemäß AMTS 2.3 für GNUmed (http://www.gnumed.de)
+%
+% License: GPL v2 or later
+%
+% Author: karsten.hilbert at gmx.net
+% Thanks to: G.Hellmann
+%
+% requires pdflatex to be run with -recorder option
+%------------------------------------------------------------------
+
+% debugging
+\listfiles
+\errorcontextlines 10000
+
+\documentclass[
+	version=last,
+	paper=landscape,
+	paper=a4,
+	DIV=9,									% help typearea find a good Satzspiegel
+	BCOR=0mm,								% keine BindeCORrektur
+	fontsize=12pt,							% per spec
+	parskip=full,							% Absätze mit Leerzeilen trennen, kein Einzug
+	headsepline=off,
+	footsepline=off,
+	titlepage=false
+]{scrartcl}
+
+%------------------------------------------------------------------
+% packages
+\usepackage{scrlayer-scrpage}				% Kopf- und Fußzeilen
+\usepackage{geometry}						% setup margins
+\usepackage{microtype}						% micro-adjustments to typesetting
+\usepackage[cjkjis,graphics]{ucs}			% lots of UTF8 symbols, breaks with xelatex
+\usepackage[T1]{fontenc}					% fonts are T1
+\usepackage[ngerman]{babel}					% Deutsch und Trennung
+\usepackage[utf8x]{inputenc}				% content is UTF8, breaks with xelatex
+\usepackage{textcomp}						% Symbole für Textmodus zum Escapen
+\usepackage{ragged2e}						% improved alignment, needed for raggedleft in header table cell
+\usepackage{tabularx}						% bessere Tabellen
+\usepackage{tabu}							% bessere Tabellen
+\usepackage{longtable}						% Tabellen über mehrere Seiten
+\usepackage[table]{xcolor}					% gray headers
+\usepackage{helvet}							% Arial alike Helvetica
+\usepackage{lastpage}						% easy access to page number of last page
+\usepackage{embedfile}						% store copy of data file for producing data matrix inside PDF
+\usepackage{array}							% improved column styles
+\usepackage[abspath]{currfile}				% generically refer to input file
+\usepackage{graphicx}						% Grafiken laden (datamatrix)
+\usepackage[space]{grffile}					% besserer Zugriff auf Grafikdateien
+\usepackage[export]{adjustbox}				% improved options for \includegraphics
+\usepackage{marvosym}						% Symbole: Handy, Telefon, E-Mail, used in non-conformant layout
+%\usepackage[ocgcolorlinks=true]{hyperref}	% aktive URLs, needs to be loaded last, most of the time
+\usepackage{hyperref}						% aktive URLs, needs to be loaded last, most of the time
+
+% debugging:
+%\usepackage{showkeys}						% print labels (anchors and stuff) as margin notes
+%\usepackage{interfaces}					% \papergraduate
+
+%\usepackage{calc}							% \widthof (für signature)
+
+%------------------------------------------------------------------
+% setup:
+% - debugging
+%\tracingtabu=3
+%\usetikz{basic}
+%\hypersetup{debug=true}
+
+
+% - placeholder handler options
+% switch on ellipsis handling:
+$<ph_cfg::ellipsis//…//%% <%(name)s> set to [%(value)s]::>$
+
+
+% - PDF metadata
+\hypersetup{
+	pdftitle = {Medikationsplan: $<name::%(firstnames)s %(lastnames)s::>$, $<date_of_birth::%d.%b %Y::>$},
+	pdfauthor = {$<current_provider::::>$, $<praxis::%(branch)s, %(praxis)s::>$},
+	pdfsubject = {Medikationsplan (AMTS, NICHT KONFORM)},
+	pdfproducer = {GNUmed $<client_version::::>$, Vorlage $<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]},
+	pdfdisplaydoctitle = true
+}
+
+
+% - precise positioning of things to satisfy spec
+\setlength{\tabcolsep}{0pt}
+\setlength{\parskip}{0pt}
+\setlength{\topskip}{0pt}
+\setlength{\floatsep}{0pt}
+\setlength{\textfloatsep}{0pt}
+
+
+% - page
+\geometry{
+	verbose,
+	% debugging:
+%	showframe,											% show page frames
+%	showcrop,											% show crop marks
+	a4paper,
+	landscape,
+	bindingoffset=0pt,
+%
+	% top-to-bottom on page:
+	top=8mm,					% per spec
+	includehead,				% into <total body>, not into topmargin
+	headheight=48mm,			% per spec, decrease textheight, top margin (8mm) + actual header size (40mm)
+	headsep=0mm,				% no more space until *top* of textheight (not baseline of first line ...)
+	%textheight,				% is calculated by the other dimensions, should amount to 144mm (210 - (8+40+0+10+9))
+	includefoot,				% into <total body>, not into bottommargin
+	% need to be calculated to work:
+	footskip=\dimexpr+\ht\strutbox\relax,		% 10mm per spec, decreases textheight
+	bottom=\dimexpr15mm+\ht\strutbox\relax,		% 8mm per spec, 15mm found empirically (includes the 10mm footskip, but why ?)
+%
+	% left-to-right on page:
+	left=8mm,					% per spec
+	%textwidth,					% is calculated by the other dimensions, should amount to 281mm (297 - (8+0+0+8))
+	includemp,					% include marginparsep and marginparwidth into width, decreases textwidth (but set to 0 below)
+	marginparsep=0mm,			% no margin notes offset
+	marginparwidth=0mm,			% no margin notes width
+	right=8mm					% per spec
+}
+
+
+% - font: Arial (Helvetica)
+\renewcommand{\rmdefault}{phv}
+\renewcommand{\sfdefault}{phv}
+
+
+% - tabu
+\tabulinesep=^1mm_1mm
+
+
+% - header = top part
+\lohead{
+	\upshape
+	\begin{tabu} to \textwidth {|>{\raggedleft\arraybackslash}p{7cm}|@{\hspace{1mm}}X[-1,L]@{\hspace{1cm}}X[-1,R]|p{4.3cm}}
+			\tabucline{1-3}
+			% line 1
+				\fontsize{20pt}{22pt}\selectfont					% \fontsize{<font size>}{<line spacing>}
+				%(1)\ % debugging
+				\textbf{\href{http://www.kbv.de/html/medikationsplan.php}{Medikationsplan}} \newline
+			% line 2
+				\fontsize{14pt}{16pt}\selectfont
+				%(2)\ % debugging
+				Seite \thepage\ von \pageref{LastPage} \newline
+			% line 3
+				\fontsize{12pt}{14pt}\selectfont
+				%(3) % debugging
+				% as long as we don't have certification or claim conformance we can put here any image we want :-)
+				\includegraphics[scale=5,max height=2.4cm,center]{$<<patient_photo::%s//image/png//.png::>>$}
+		&
+			% line 1: patient name, part 1
+				\fontsize{14pt}{20pt}\selectfont									% keep line spacing in sync with left hand side
+				%(1)\ % debugging
+				$<ph_cfg::ellipsis//NONE//%% <%(name)s> set to [%(value)s]::>$		% switch off ellipsis handling so first range of name does not get one if too long
+				für:\ \textbf{$<name::%(firstnames)s %(lastnames)s::1-37>$} \newline
+				$<ph_cfg::ellipsis//…//%% <%(name)s> set to [%(value)s]::>$			% but reenable in case second line of name still too long so that we need an ellipsis
+			% line 2: patient name, part 2, if any
+				\fontsize{14pt}{16pt}\selectfont									% keep line spacing in sync with left hand side
+				%(2)\ % debugging
+				$<name::\textbf{%(firstnames)s %(lastnames)s}::38-90>$\ \newline
+			% line 3: provider name
+				\fontsize{12pt}{14pt}\selectfont
+				%(3)\ % debugging
+				ausgedruckt von: $<current_provider::::30>$ \newline
+			% line 4: praxis name
+				%(4)\ % debugging
+				\href{http://$<praxis_comm::web::>$}{$<praxis::%(branch)s, %(praxis)s::50>$} \newline
+			% line 5: praxis address: street / number / zip / location
+				%(5)\ % debugging
+				%         (use \mbox{TEXT} to prevent TEXT from getting hyphenated)
+				$<ph_cfg::argumentsdivider//||//%% <%(name)s> set to [%(value)s]::>$
+				$<praxis_address::\href{http://nominatim.openstreetmap.org/search/$<<<url_escape::$<<praxis_address::%(country)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(urb)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(street)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(number)s::>>$::>>>$?limit=3}{\mbox{$<<praxis_address::%(street)s %(number)s %(subunit)s,%(postcode)s %(urb)s::55>>$}}::>$\ \newline
+				$<ph_cfg::argumentsdivider//DEFAULT//%% <%(name)s> set back to default of [%(value)s]::>$
+			% line 6: praxis phone number
+				%(6)\ % debugging
+				$<<praxis_comm::workphone//\href{tel:$<praxis_comm::workphone::>$}{$<praxis_comm::workphone//\Telefon\ %(url)s::50>$}::>>$\ \newline
+			% line 7: praxis email address
+				%(7)\ % debugging
+				$<<praxis_comm::email//\href{mailto:$<praxis_comm::email::>$}{$<praxis_comm::email//\Email\ %(url)s::60>$}::>>$\ 
+		&
+			% line 1: patient DOB
+				\fontsize{14pt}{16pt}\selectfont				% keep line spacing in sync with left hand side
+				%(1)\ % debugging
+				geb.\ am: \textbf{$<date_of_birth::%d.%b %Y::>$} \newline
+			% line 2: patient gender -- would benefit from an improved $gender_symbol$ placeholder
+				\fontsize{12pt}{16pt}\selectfont				% keep line spacing in sync with left hand side
+				%(2)\ % debugging
+				Geschl.: $<gender_mapper::m//w//unbestimmt::>$ \newline
+			% line 3: empty
+				\fontsize{12pt}{14pt}\selectfont				% keep line spacing in sync with left hand side
+				%(3)\ % debugging
+				\ \newline
+%			% line 4
+%				$<ph_cfg::ellipsis//NONE//%% <%(name)s> set to [%(value)s]::>$		% switch off ellipsis handling so first line of parameters does not get one if too long
+%				$<<range_of::$<test_result::LOINC=XX//,Gew.: %s::>$$<test_result::LOINC=XX//,Krea.: %s::>$$<breastfeeding::,stillend//::>$$<pregnant::,schwanger (ET %(edc)s)////%d.%b %Y::>$::25>>$\newline
+%			% line 5
+%				$<ph_cfg::ellipsis//…//%% <%(name)s> set to [%(value)s]::>$			% but reenable in case second line of parameters still too long so that we need an ellipsis
+%				$<<range_of::$<test_result::LOINC=XX//,Gew.: %s::>$$<test_result::LOINC=XX//,Krea.: %s::>$$<breastfeeding::,stillend//::>$$<pregnant::,schwanger (ET %(edc)s)////%d.%m.%Y::>$::26-50>>$\ \newline
+%			% line 6: parameter: allergies
+%			%         %$<allergy_state::::25>$
+%				Allerg/Unv: Seite \pageref{LastPage}\ \hyperref[AnchorAllergieDetails]{unten}\newline
+			% line 4: empty
+				%(4)\ % debugging
+				\ \newline
+			% line 5: empty
+				%(5)\ % debugging
+				\ \newline
+			% line 6: parameter: allergies ($<allergy_state::::25>$)
+				%(6)\ % debugging
+				Allerg/Unv: Seite \pageref{LastPage}\ \hyperref[AnchorAllergieDetails]{unten} \newline
+			% line 7: soll eigentlich linksbündig ...
+				%(7)\ % debugging
+				ausgedruckt am: $<today::%d.%b %Y::>$\ 
+		&
+			\includegraphics[valign=t,raise=6ex,max height=4cm,max width=4cm,center]{$<<amts_png_file_current_page::::>>$}
+		\tabularnewline
+		\tabucline{1-3}
+	\end{tabu}
+}
+%\lehead{}
+%\cehead{}
+%\cohead{}
+%\rehead{}
+%\rohead{}
+
+
+% footer setup = bottom part
+\lofoot{{
+	\begin{tabular}[t]{p{12cm}p{16cm}}
+		\hline
+		{	% left side: Versionsinformationen
+			\fontsize{8pt}{9pt}\selectfont
+			\upshape
+			\parbox[t][1cm][t]{12cm}{
+				\raggedright
+				Für Vollständigkeit und Aktualität des Medikationsplans wird keine Gewähr übernommen.\newline
+				NICHT KONFORM zu: de-DE-Version 2.3
+			}
+		} & {
+			% middle part: Herstellerfeld
+			\fontsize{8pt}{9pt}\selectfont
+			\parbox[t][1cm][t]{16cm}{
+				\centering
+				GNUmed $<client_version::::>$ --- \href{http://www.gnumed.org}{www.gnumed.org}\newline
+				$<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]
+			}
+		}
+	\end{tabular}
+}}
+\lefoot{{
+	\begin{tabular}[t]{p{12cm}p{16cm}}
+		\hline
+		{	% left side: Versionsinformationen
+			\fontsize{8pt}{9pt}\selectfont
+			\upshape
+			\parbox[t][1cm][t]{12cm}{
+				\raggedright
+				Für Vollständigkeit und Aktualität des Medikationsplans wird keine Gewähr übernommen.\newline
+				NICHT KONFORM zu: de-DE-Version 2.3
+			}
+		} & {
+			% middle part: Herstellerfeld
+			\fontsize{8pt}{9pt}\selectfont
+			\parbox[t][1cm][t]{16cm}{
+				\centering
+				GNUmed $<client_version::::>$ --- \href{http://www.gnumed.org}{www.gnumed.org}\newline
+				$<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]
+			}
+		}
+	\end{tabular}
+}}
+\cefoot{}
+\cofoot{}
+\refoot{}
+\rofoot{}
+
+%------------------------------------------------------------------
+\begin{document}
+
+% debugging
+%\papergraduate
+
+% middle part: Medikationsliste
+\begin{longtable} {|
+	% column definition
+	p{4cm}|									% Wirkstoff
+	p{4.4cm}|								% Handelsname
+	>{\RaggedLeft}p{1.8cm}|					% Stärke
+	p{1.8cm}|								% Form
+	p{0.8cm}								% Dosierung: morgens
+	p{0.8cm}								% Dosierung: mittags
+	p{0.8cm}								% Dosierung: abends
+	p{0.8cm}|								% Dosierung: zur Nacht
+	p{2.0cm}|								% Einheit
+	p{6.4cm}|								% Hinweise
+	p{4.3cm}|								% Grund
+}
+	% Tabellenkopf:
+	\hline
+	\rowcolor{gray!20}
+	\fontsize{14pt}{16pt}\selectfont \centering Wirkstoff &
+	\fontsize{14pt}{16pt}\selectfont \centering Handelsname &
+	\fontsize{14pt}{16pt}\selectfont \centering Stärke &
+	\fontsize{14pt}{16pt}\selectfont \centering Form &
+%	\fontsize{8pt}{8pt}\selectfont \centering mor-\newline{}gens &
+%	\fontsize{8pt}{8pt}\selectfont \centering mit-\newline{}tags &
+%	\fontsize{8pt}{8pt}\selectfont \centering abends &
+%	\fontsize{8pt}{8pt}\selectfont \centering zur\newline{}Nacht &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{morgens} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{mittags} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{abends} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{z.\newline{}Nacht} &
+	\fontsize{14pt}{16pt}\selectfont \centering Einheit &
+	\fontsize{14pt}{16pt}\selectfont \centering Hinweise &
+	\fontsize{14pt}{16pt}\selectfont \centering Grund
+	\endhead
+	% Tabellenende auf 1. und 2. Seite
+	\endfoot
+	% Tabellenende auf letzter (3.) Seite
+	\endlastfoot
+	% Tabelleninhalt:
+\hline
+$<current_meds_AMTS_enhanced::::>$
+\end{longtable}
+
+%------------------------------------------------------------------
+% include data in PDF for easier processing:
+
+% VCF of creator
+\IfFileExists{$<praxis_vcf::::>$}{
+	\embedfile[
+		desc=01) digitale Visitenkarte des Erstellers des Medikationsplans,
+		mimetype=text/vcf,
+		ucfilespec=AMTS-Medikationsplan-Ersteller.vcf
+	]{$<praxis_vcf::::>$}
+}{\typeout{[$<praxis_vcf::::>$] not found}}
+
+% LaTeX source code from which the PDF was produced
+\embedfile[
+	desc=02) LaTeX-Quellcode des Medikationsplans (übersetzbar mit "pdflatex -recorder -interaction=nonstopmode \currfilename\ "),
+	mimetype=text/plain,
+	ucfilespec=\currfilename
+]{\currfileabspath}
+
+% enhanced datamatrix
+\IfFileExists{$<<amts_png_file_utf8::::>>$}{
+	\embedfile[
+		desc=03) Datamatrix (Bild) für alle Seiten (lesbar mit "dmtxread -v $<<amts_png_file_utf8::::>>$ > $<<amts_png_file_utf8::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-utf8-alle-Seiten.png
+	]{$<<amts_png_file_utf8::::>>$}
+}{\typeout{[$<<amts_png_file_utf8::::>>$] (all pages) not found}}
+
+\IfFileExists{$<<amts_data_file_utf8::::>>$}{
+	\embedfile[
+		desc=04) Datamatrix (Daten) für alle Seiten (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_utf8::::>>$.png -s s -v $<<amts_data_file_utf8::::>>$"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-utf8-alle-Seiten.txt
+	]{$<<amts_data_file_utf8::::>>$}
+}{\typeout{[$<<amts_data_file_utf8::::>>$] (all pages) not found}}
+
+% per-page datamatrix files
+% page 1
+\IfFileExists{$<<amts_png_file_1::::>>$}{
+	\embedfile[
+		desc=05) Datamatrix (Bild) für Seite 1 (lesbar mit "dmtxread -U -v $<<amts_png_file_1::::>>$ > $<<amts_png_file_1::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-Seite-1.png
+	]{$<<amts_png_file_1::::>>$}
+}{\typeout{[$<<amts_png_file_1::::>>$] (page 1) not found}}
+
+\IfFileExists{$<<amts_data_file_1::::>>$}{
+	\embedfile[
+		desc=06) Datamatrix (Daten) für Seite 1 (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_1::::>>$.png -s s -v $<<amts_data_file_1::::>>$"),
+		mimetype=text/plain,
+		ucfilespec=AMTS-Datamatrix-Daten-Seite-1.txt
+	]{$<<amts_data_file_1::::>>$}
+}{\typeout{[$<<amts_data_file_1::::>>$] (page 1) not found}}
+
+% page 2
+\IfFileExists{$<<amts_png_file_2::::>>$}{
+	\embedfile[
+		desc=07) Datamatrix (Bild) für Seite 2 (lesbar mit "dmtxread -U -v $<<amts_png_file_1::::>>$ > $<<amts_png_file_2::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-Seite-2.png
+	]{$<<amts_png_file_2::::>>$}
+}{\typeout{[$<<amts_png_file_2::::>>$] (page 2) not found}}
+
+\IfFileExists{$<<amts_data_file_2::::>>$}{
+	\embedfile[
+		desc=08) Datamatrix (Daten) für Seite 2 (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_2::::>>$.png -s s -v $<<amts_data_file_2::::>>$"),
+		mimetype=text/plain,
+		ucfilespec=AMTS-Datamatrix-Daten-Seite-2.txt
+	]{$<<amts_data_file_2::::>>$}
+}{\typeout{[$<<amts_data_file_2::::>>$] (page 2) not found}}
+
+% page 3
+\IfFileExists{$<<amts_png_file_3::::>>$}{
+	\embedfile[
+		desc=09) Datamatrix (Bild) für Seite 3 (lesbar mit "dmtxread -U -v $<<amts_png_file_1::::>>$ > $<<amts_png_file_3::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-Seite-3.png
+	]{$<<amts_png_file_3::::>>$}
+}{\typeout{[$<<amts_png_file_3::::>>$] (page 3) not found}}
+
+\IfFileExists{$<<amts_data_file_3::::>>$}{
+	\embedfile[
+		desc=10) Datamatrix (Daten) für Seite 3 (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_3::::>>$.png -s s -v $<<amts_data_file_3::::>>$"),
+		mimetype=text/plain,
+		ucfilespec=AMTS-Datamatrix-Daten-Seite-3.txt
+	]{$<<amts_data_file_3::::>>$}
+}{\typeout{[$<<amts_data_file_3::::>>$] (page 3) not found}}
+
+% patient photo
+\IfFileExists{$<patient_photo::%s//image/png//.png::>$}{
+	\embedfile[
+		desc=11) Patientenphoto,
+		mimetype=image/png,
+		ucfilespec=Patientenphoto.png
+	]{$<patient_photo::%s//image/png//.png::>$}
+}{\typeout{[$<patient_photo::%s//image/png//.png::>$] (patient photo) not found}}
+
+% patient vcf -- really a good idea ? (it would tell more
+% about the patient than is defined by the Medikationsplan specs)
+\IfFileExists{$<patient_vcf::::>$}{
+	\embedfile[
+		desc=12) digitale Visitenkarte des Patienten,
+		mimetype=text/vcf,
+		ucfilespec=Patient.vcf
+	]{$<patient_vcf::::>$}
+}{\typeout{[$<patient_vcf::::>$] (patient VCF) not found}}
+
+% patient gdt -- really a good idea ? (it would tell more
+% about the patient than is defined by the Medikationsplan specs)
+\IfFileExists{$<patient_gdt::::>$}{
+	\embedfile[
+		desc=13) GDT-Datei des Patienten,
+		mimetype=text/plain,
+		ucfilespec=Patient.gdt
+	]{$<patient_gdt::::>$}
+}{\typeout{[$<patient_gdt::::>$] (patient GDT) not found}}
+
+%------------------------------------------------------------------
+
+\end{document}
+%------------------------------------------------------------------
diff --git a/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3.tex b/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3.tex
new file mode 100644
index 0000000..ef2ae93
--- /dev/null
+++ b/server/sql/v20-v21/data/v21-Medikationsplan_AMTS-2.3.tex
@@ -0,0 +1,463 @@
+%------------------------------------------------------------------
+% Medikationsplan gemäß AMTS 2.3 für GNUmed (http://www.gnumed.de)
+%
+% License: GPL v2 or later
+%
+% Author: karsten.hilbert at gmx.net
+% Thanks to: G.Hellmann
+%
+% requires pdflatex to be run with -recorder option
+%------------------------------------------------------------------
+
+% debugging
+\listfiles
+\errorcontextlines 10000
+
+\documentclass[
+	version=last,
+	paper=landscape,
+	paper=a4,
+	DIV=9,									% help typearea find a good Satzspiegel
+	BCOR=0mm,								% keine BindeCORrektur
+	fontsize=12pt,							% per spec
+	parskip=full,							% Absätze mit Leerzeilen trennen, kein Einzug
+	headsepline=off,
+	footsepline=off,
+	titlepage=false
+]{scrartcl}
+
+%------------------------------------------------------------------
+% packages
+\usepackage{scrlayer-scrpage}				% Kopf- und Fußzeilen
+\usepackage{geometry}						% setup margins
+\usepackage{microtype}						% micro-adjustments to typesetting
+\usepackage[cjkjis,graphics]{ucs}			% lots of UTF8 symbols, breaks with xelatex
+\usepackage[T1]{fontenc}					% fonts are T1
+\usepackage[ngerman]{babel}					% Deutsch und Trennung
+\usepackage[utf8x]{inputenc}				% content is UTF8, breaks with xelatex
+\usepackage{textcomp}						% Symbole für Textmodus zum Escapen
+\usepackage{ragged2e}						% improved alignment, needed for raggedleft in header table cell
+\usepackage{tabularx}						% bessere Tabellen
+\usepackage{tabu}							% bessere Tabellen
+\usepackage{longtable}						% Tabellen über mehrere Seiten
+\usepackage[table]{xcolor}					% gray headers
+\usepackage{helvet}							% Arial alike Helvetica
+\usepackage{lastpage}						% easy access to page number of last page
+\usepackage{embedfile}						% store copy of data file for producing data matrix inside PDF
+\usepackage{array}							% improved column styles
+\usepackage[abspath]{currfile}				% generically refer to input file
+\usepackage{graphicx}						% Grafiken laden (datamatrix)
+\usepackage[space]{grffile}					% besserer Zugriff auf Grafikdateien
+\usepackage[export]{adjustbox}				% improved options for \includegraphics
+%\usepackage{marvosym}						% Symbole: Handy, Telefon, E-Mail, used in non-conformant layout
+%\usepackage[ocgcolorlinks=true]{hyperref}	% aktive URLs, needs to be loaded last, most of the time
+\usepackage{hyperref}						% aktive URLs, needs to be loaded last, most of the time
+
+% debugging:
+%\usepackage{showkeys}						% print labels (anchors and stuff) as margin notes
+%\usepackage{interfaces}					% \papergraduate
+
+%\usepackage{calc}							% \widthof (für signature)
+
+%------------------------------------------------------------------
+% setup:
+% - debugging
+%\tracingtabu=3
+%\usetikz{basic}
+%\hypersetup{debug=true}
+
+
+% - placeholder handler options
+% switch on ellipsis handling:
+$<ph_cfg::ellipsis//...//%% <%(name)s> set to [%(value)s]::>$
+% set target encoding per spec:
+$<ph_cfg::encoding//iso-8859-1//%% <%(name)s> set to [%(value)s]::>$
+
+
+% - PDF metadata
+\hypersetup{
+	pdftitle = {Medikationsplan: $<name::%(firstnames)s %(lastnames)s::>$, $<date_of_birth::%d.%m.%Y::>$},
+	pdfauthor = {$<current_provider::::>$, $<praxis::%(branch)s, %(praxis)s::>$},
+	pdfsubject = {Medikationsplan (AMTS)},
+	pdfproducer = {GNUmed $<client_version::::>$, Vorlage $<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]},
+	pdfdisplaydoctitle = true
+}
+
+
+% - precise positioning of things to satisfy spec
+\setlength{\tabcolsep}{0pt}
+\setlength{\parskip}{0pt}
+\setlength{\topskip}{0pt}
+\setlength{\floatsep}{0pt}
+\setlength{\textfloatsep}{0pt}
+
+
+% - page
+\geometry{
+	verbose,
+	% debugging:
+%	showframe,											% show page frames
+%	showcrop,											% show crop marks
+	a4paper,
+	landscape,
+	bindingoffset=0pt,
+%
+	% top-to-bottom on page:
+	top=8mm,					% per spec
+	includehead,				% into <total body>, not into topmargin
+	headheight=48mm,			% per spec, decrease textheight, top margin (8mm) + actual header size (40mm)
+	headsep=0mm,				% no more space until *top* of textheight (not baseline of first line ...)
+	%textheight,				% is calculated by the other dimensions, should amount to 144mm (210 - (8+40+0+10+9))
+	includefoot,				% into <total body>, not into bottommargin
+	% need to be calculated to work:
+	footskip=\dimexpr+\ht\strutbox\relax,		% 10mm per spec, decreases textheight
+	bottom=\dimexpr15mm+\ht\strutbox\relax,		% 8mm per spec, 15mm found empirically (includes the 10mm footskip, but why ?)
+%
+	% left-to-right on page:
+	left=8mm,					% per spec
+	%textwidth,					% is calculated by the other dimensions, should amount to 281mm (297 - (8+0+0+8))
+	includemp,					% include marginparsep and marginparwidth into width, decreases textwidth (but set to 0 below)
+	marginparsep=0mm,			% no margin notes offset
+	marginparwidth=0mm,			% no margin notes width
+	right=8mm					% per spec
+}
+
+
+% - font: Arial (Helvetica)
+\renewcommand{\rmdefault}{phv}
+\renewcommand{\sfdefault}{phv}
+
+
+% - tabu
+\tabulinesep=^1mm_1mm
+
+
+% - header = top part
+\lohead{
+	\upshape
+	\begin{tabu} to \textwidth {|>{\raggedleft\arraybackslash}p{7cm}|@{\hspace{1mm}}X[-1,L]@{\hspace{1cm}}X[-1,R]|p{4.3cm}}
+			\tabucline{1-3}
+			% line 1
+			\fontsize{20pt}{22pt}\selectfont					% \fontsize{<font size>}{<line spacing>}
+			%(1)\ % debugging
+			\textbf{\href{http://www.kbv.de/html/medikationsplan.php}{Medikationsplan}} \newline
+			% line 2
+			\fontsize{14pt}{16pt}\selectfont
+			%(2)\ % debugging
+			Seite \thepage\ von \pageref{LastPage} \newline
+			% line 3
+			\fontsize{12pt}{14pt}\selectfont
+			% -- debugging --
+			%(3)\newline
+			%(4)\newline
+			%(5)\newline
+			%(6)\newline
+			%(7)
+			% -- debugging --
+			% after certification we would replace this with the certification image...
+			%\includegraphics[scale=5,max height=2.4cm,center]{certification-image}
+		&
+			% line 1: patient name, part 1
+			\fontsize{14pt}{20pt}\selectfont									% keep line spacing in sync with left hand side
+			%(1)\ % debugging
+			$<ph_cfg::ellipsis//NONE//%% <%(name)s> set to [%(value)s]::>$		% switch off ellipsis handling so first range of name does not get one if too long
+			für:\ \textbf{$<name::%(firstnames)s %(lastnames)s::1-37>$} \newline
+			$<ph_cfg::ellipsis//...//%% <%(name)s> set to [%(value)s]::>$		% but reenable in case second line of name still too long so that we need an ellipsis
+			% line 2: patient name, part 2, if any
+			\fontsize{14pt}{16pt}\selectfont									% keep line spacing in sync with left hand side
+			%(2)\ % debugging
+			$<name::\textbf{%(firstnames)s %(lastnames)s}::38-90>$\ \newline
+			% line 3: provider name
+			\fontsize{12pt}{14pt}\selectfont
+			%(3)\ % debugging
+			ausgedruckt von: $<current_provider::::30>$ \newline
+			% line 4: praxis name
+			%(4)\ % debugging
+			\href{http://$<praxis_comm::web::>$}{$<praxis::%(branch)s, %(praxis)s::50>$} \newline
+			% line 5: praxis address: street / number / zip / location
+			%(5)\ % debugging
+			%         (use \mbox{TEXT} to prevent TEXT from getting hyphenated)
+			$<ph_cfg::argumentsdivider//||//%% <%(name)s> set to [%(value)s]::>$
+			$<praxis_address::\href{http://nominatim.openstreetmap.org/search/$<<<url_escape::$<<praxis_address::%(country)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(urb)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(street)s::>>$::>>>$/$<<<url_escape::$<<praxis_address::%(number)s::>>$::>>>$?limit=3}{\mbox{$<<praxis_address::%(street)s %(number)s %(subunit)s,%(postcode)s %(urb)s::55>>$}}::>$\ \newline
+			$<ph_cfg::argumentsdivider//DEFAULT//%% <%(name)s> set back to default of [%(value)s]::>$
+			% line 6: praxis phone number
+			%(6)\ % debugging
+			$<<praxis_comm::workphone//\href{tel:$<praxis_comm::workphone::>$}{$<praxis_comm::workphone//Tel: %(url)s::25>$}::>>$\ \newline
+			% line 7: praxis email address
+			%(7)\ % debugging
+			$<<praxis_comm::email//\href{mailto:$<praxis_comm::email::>$}{$<praxis_comm::email//E-Mail: %(url)s::48>$}::>>$\ 
+		&
+			\fontsize{14pt}{16pt}\selectfont				% keep line spacing in sync with left hand side
+			% line 1: patient DOB
+			%(1)\ % debugging
+			geb.\ am: \textbf{$<date_of_birth::%d.%m.%Y::10>$}\newline
+			% line 2: empty
+			\fontsize{14pt}{16pt}\selectfont				% keep line spacing in sync with left hand side
+			%(2)\ % debugging
+			\ \newline
+			% line 3: empty
+			\fontsize{12pt}{14pt}\selectfont				% keep line spacing in sync with left hand side
+			%(3)\ % debugging
+			\ \newline
+%			% line 4
+%			$<ph_cfg::ellipsis//NONE//%% <%(name)s> set to [%(value)s]::>$		% switch off ellipsis handling so first line of parameters does not get one if too long
+%			$<<range_of::Geschl.: $<gender_mapper::m//w//unbestimmt::>$$<test_result::LOINC=XX//,Gew.: %s::>$$<test_result::LOINC=XX//,Krea.: %s::>$$<breastfeeding::,stillend//::>$$<pregnant::,schwanger////::>$$<pregnant::,ET %(edc)s////%d.%m.%Y::>$::25>>$\newline
+%			% line 5
+%			$<ph_cfg::ellipsis//...//%% <%(name)s> set to [%(value)s]::>$			% but reenable in case second line of parameters still too long so that we need an ellipsis
+%			$<<range_of::Geschl.: $<gender_mapper::m//w//unbestimmt::>$$<test_result::LOINC=XX//,Gew.: %s::>$$<test_result::LOINC=XX//,Krea.: %s::>$$<breastfeeding::,stillend//::>$$<pregnant::,schwanger////::>$$<pregnant::,ET %(edc)s////%d.%m.%Y::>$::26-50>>$\ \newline
+%			% line 6: parameter: allergies
+%			%         %$<allergy_state::::25>$
+%			Allrg/Unv.: Seite \pageref{LastPage}\ \hyperref[AnchorAllergieDetails]{unten}\newline		% muß eigentlich "Allerg./Unv." sein, aber das sind dann 2 Zeichen zuviel ...
+			% line 4: parameter: gender
+			%(4)\ % debugging
+			Geschl.: $<gender_mapper::m//w//unbestimmt::16>$\newline
+			% line 5:
+			%(5)\ % debugging
+			\ \newline
+			% line 6: parameter: allergies ($<allergy_state::::25>$)
+			%(6)\ % debugging
+			Allrg/Unv.: Seite \pageref{LastPage}\ \hyperref[AnchorAllergieDetails]{unten}\newline		% muß eigentlich "Allerg./Unv." sein, aber das sind dann 2 Zeichen zuviel ...
+			% line 7: soll eigentlich linksbündig ...
+			%(7)\ % debugging
+			ausgedruckt am: $<today::%d.%m.%Y::10>$
+		&
+			\includegraphics[valign=t,raise=6ex,max height=4cm,max width=4cm,center]{$<<amts_png_file_current_page::::>>$}
+		\tabularnewline
+		\tabucline{1-3}
+	\end{tabu}
+}
+%\lehead{}
+%\cehead{}
+%\cohead{}
+%\rehead{}
+%\rohead{}
+
+
+% footer setup = bottom part
+\lofoot{{
+	\begin{tabular}[t]{p{12cm}p{11cm}p{5cm}}
+		\hline
+		{	% left side: Versionsinformationen
+			\fontsize{8pt}{9pt}\selectfont
+			\upshape
+			\parbox[t][1cm][t]{12cm}{
+				\raggedright
+				Für Vollständigkeit und Aktualität des Medikationsplans wird keine Gewähr übernommen.\newline
+				de-DE-Version 2.3
+			}
+		} & {
+			% middle part: Herstellerfeld
+			\fontsize{8pt}{9pt}\selectfont
+			\parbox[t][1cm][t]{11cm}{
+				\centering
+				GNUmed $<client_version::::>$ --- \href{http://www.gnumed.org}{www.gnumed.org}\newline
+				$<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]
+			}
+		} & {
+			% right side: Freifeld, MUST be empty per spec
+			% debugging:
+			%---Freifeld---
+		}
+	\end{tabular}
+}}
+\lefoot{{
+	\begin{tabular}[t]{p{12cm}p{11cm}p{5cm}}
+		\hline
+		{	% left side: Versionsinformationen
+			\fontsize{8pt}{9pt}\selectfont
+			\upshape
+			\parbox[t][1cm][t]{12cm}{
+				\raggedright
+				Für Vollständigkeit und Aktualität des Medikationsplans wird keine Gewähr übernommen.\newline
+				de-DE-Version 2.3
+			}
+		} & {
+			% middle part: Herstellerfeld
+			\fontsize{8pt}{9pt}\selectfont
+			\parbox[t][1cm][t]{11cm}{
+				\centering
+				GNUmed $<client_version::::>$ --- \href{http://www.gnumed.org}{www.gnumed.org}\newline
+				$<form_name_long::::>$, $<form_version::::>$ [$<form_version_internal::::>$, $<form_last_modified::::>$]
+			}
+		} & {
+			% right side: Freifeld, MUST be empty per spec
+			% debugging:
+			%---Freifeld---
+		}
+	\end{tabular}
+}}
+\cefoot{}
+\cofoot{}
+\refoot{}
+\rofoot{}
+
+%------------------------------------------------------------------
+\begin{document}
+
+% debugging
+%\papergraduate
+
+% middle part: Medikationsliste
+\begin{longtable} {|
+	% column definition
+	p{4cm}|									% Wirkstoff
+	p{4.4cm}|								% Handelsname
+	>{\RaggedLeft}p{1.8cm}|					% Stärke
+	p{1.8cm}|								% Form
+	p{0.8cm}								% Dosierung: morgens
+	p{0.8cm}								% Dosierung: mittags
+	p{0.8cm}								% Dosierung: abends
+	p{0.8cm}|								% Dosierung: zur Nacht
+	p{2.0cm}|								% Einheit
+	p{6.4cm}|								% Hinweise
+	p{4.3cm}|								% Grund
+}
+	% Tabellenkopf:
+	\hline
+	\rowcolor{gray!20}
+	\fontsize{14pt}{16pt}\selectfont \centering Wirkstoff &
+	\fontsize{14pt}{16pt}\selectfont \centering Handelsname &
+	\fontsize{14pt}{16pt}\selectfont \centering Stärke &
+	\fontsize{14pt}{16pt}\selectfont \centering Form &
+%	\fontsize{8pt}{8pt}\selectfont \centering mor-\newline{}gens &
+%	\fontsize{8pt}{8pt}\selectfont \centering mit-\newline{}tags &
+%	\fontsize{8pt}{8pt}\selectfont \centering abends &
+%	\fontsize{8pt}{8pt}\selectfont \centering zur\newline{}Nacht &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{morgens} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{mittags} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{abends} &
+	\fontsize{8pt}{8pt}\selectfont\rotatebox{40}{zur Nacht} &
+	\fontsize{14pt}{16pt}\selectfont \centering Einheit &
+	\fontsize{14pt}{16pt}\selectfont \centering Hinweise &
+	\fontsize{14pt}{16pt}\selectfont \centering Grund
+	\endhead
+	% Tabellenende auf 1. und 2. Seite
+	\endfoot
+	% Tabellenende auf letzter (3.) Seite
+	\endlastfoot
+	% Tabelleninhalt:
+\hline
+$<current_meds_AMTS::::999999999>$
+\end{longtable}
+
+%------------------------------------------------------------------
+% include data in PDF for easier processing:
+
+% VCF of creator
+\IfFileExists{$<praxis_vcf::::>$}{
+	\embedfile[
+		desc=01) digitale Visitenkarte des Erstellers des Medikationsplans,
+		mimetype=text/vcf,
+		ucfilespec=AMTS-Medikationsplan-Ersteller.vcf
+	]{$<praxis_vcf::::>$}
+}{\typeout{[$<praxis_vcf::::>$] not found}}
+
+% LaTeX source code from which the PDF was produced
+\embedfile[
+	desc=02) LaTeX-Quellcode des Medikationsplans (übersetzbar mit "pdflatex -recorder -interaction=nonstopmode \currfilename\ "),
+	mimetype=text/plain,
+	ucfilespec=\currfilename
+]{\currfileabspath}
+
+% enhanced datamatrix
+\IfFileExists{$<<amts_png_file_utf8::::>>$}{
+	\embedfile[
+		desc=03) Datamatrix (Bild) für alle Seiten (lesbar mit "dmtxread -v $<<amts_png_file_utf8::::>>$ > $<<amts_png_file_utf8::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-utf8-alle-Seiten.png
+	]{$<<amts_png_file_utf8::::>>$}
+}{\typeout{[$<<amts_png_file_utf8::::>>$] (all pages) not found}}
+
+\IfFileExists{$<<amts_data_file_utf8::::>>$}{
+	\embedfile[
+		desc=04) Datamatrix (Daten) für alle Seiten (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_utf8::::>>$.png -s s -v $<<amts_data_file_utf8::::>>$"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-utf8-alle-Seiten.txt
+	]{$<<amts_data_file_utf8::::>>$}
+}{\typeout{[$<<amts_data_file_utf8::::>>$] (all pages) not found}}
+
+% per-page datamatrix files
+% page 1
+\IfFileExists{$<<amts_png_file_1::::>>$}{
+	\embedfile[
+		desc=05) Datamatrix (Bild) für Seite 1 (lesbar mit "dmtxread -U -v $<<amts_png_file_1::::>>$ > $<<amts_png_file_1::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-Seite-1.png
+	]{$<<amts_png_file_1::::>>$}
+}{\typeout{[$<<amts_png_file_1::::>>$] (page 1) not found}}
+
+\IfFileExists{$<<amts_data_file_1::::>>$}{
+	\embedfile[
+		desc=06) Datamatrix (Daten) für Seite 1 (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_1::::>>$.png -s s -v $<<amts_data_file_1::::>>$"),
+		mimetype=text/plain,
+		ucfilespec=AMTS-Datamatrix-Daten-Seite-1.txt
+	]{$<<amts_data_file_1::::>>$}
+}{\typeout{[$<<amts_data_file_1::::>>$] (page 1) not found}}
+
+% page 2
+\IfFileExists{$<<amts_png_file_2::::>>$}{
+	\embedfile[
+		desc=07) Datamatrix (Bild) für Seite 2 (lesbar mit "dmtxread -U -v $<<amts_png_file_1::::>>$ > $<<amts_png_file_2::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-Seite-2.png
+	]{$<<amts_png_file_2::::>>$}
+}{\typeout{[$<<amts_png_file_2::::>>$] (page 2) not found}}
+
+\IfFileExists{$<<amts_data_file_2::::>>$}{
+	\embedfile[
+		desc=08) Datamatrix (Daten) für Seite 2 (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_2::::>>$.png -s s -v $<<amts_data_file_2::::>>$"),
+		mimetype=text/plain,
+		ucfilespec=AMTS-Datamatrix-Daten-Seite-2.txt
+	]{$<<amts_data_file_2::::>>$}
+}{\typeout{[$<<amts_data_file_2::::>>$] (page 2) not found}}
+
+% page 3
+\IfFileExists{$<<amts_png_file_3::::>>$}{
+	\embedfile[
+		desc=09) Datamatrix (Bild) für Seite 3 (lesbar mit "dmtxread -U -v $<<amts_png_file_1::::>>$ > $<<amts_png_file_3::::>>$.txt"),
+		mimetype=image/png,
+		ucfilespec=AMTS-Datamatrix-Seite-3.png
+	]{$<<amts_png_file_3::::>>$}
+}{\typeout{[$<<amts_png_file_3::::>>$] (page 3) not found}}
+
+\IfFileExists{$<<amts_data_file_3::::>>$}{
+	\embedfile[
+		desc=10) Datamatrix (Daten) für Seite 3 (übersetzbar mit "dmtxwrite -e a -m 2 -f PNG -o $<<amts_data_file_3::::>>$.png -s s -v $<<amts_data_file_3::::>>$"),
+		mimetype=text/plain,
+		ucfilespec=AMTS-Datamatrix-Daten-Seite-3.txt
+	]{$<<amts_data_file_3::::>>$}
+}{\typeout{[$<<amts_data_file_3::::>>$] (page 3) not found}}
+
+% patient photo
+\IfFileExists{$<patient_photo::%s//image/png//.png::>$}{
+	\embedfile[
+		desc=11) Patientenphoto,
+		mimetype=image/png,
+		ucfilespec=Patientenphoto.png
+	]{$<patient_photo::%s//image/png//.png::>$}
+}{\typeout{[$<patient_photo::%s//image/png//.png::>$] (patient photo) not found}}
+
+% patient vcf -- not a good idea as it would tell more about
+% the patient than is defined by the Medikationsplan specs
+%\IfFileExists{$<patient_vcf::::>$}{
+%	\embedfile[
+%		desc=12) digitale Visitenkarte des Patienten,
+%		mimetype=text/vcf,
+%		ucfilespec=Patient.vcf
+%	]{$<patient_vcf::::>$}
+%}{\typeout{[$<patient_vcf::::>$] (patient VCF) not found}}
+
+% patient gdt -- not a good idea ? as it would tell more
+% about the patient than is defined by the Medikationsplan specs
+%\IfFileExists{$<patient_gdt::::>$}{
+%	\embedfile[
+%		desc=13) GDT-Datei des Patienten,
+%		mimetype=text/plain,
+%		ucfilespec=Patient.gdt
+%	]{$<patient_gdt::::>$}
+%}{\typeout{[$<patient_gdt::::>$] (patient GDT) not found}}
+
+%------------------------------------------------------------------
+
+\end{document}
+%------------------------------------------------------------------
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 8fed502..417de48 100644
--- a/server/sql/v20-v21/dynamic/v21-release_notes-dynamic.sql
+++ b/server/sql/v20-v21/dynamic/v21-release_notes-dynamic.sql
@@ -17,29 +17,36 @@ 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.7 (database v21.7)',
-	'GNUmed 1.6.7 Release Notes:
+	'Release Notes for GNUmed 1.6.8 (database v21.8)',
+	'GNUmed 1.6.8 Release Notes:
 
-	1.6.7
+	1.6.8
 
-FIX: constrain hospital stay PRW to current patient
-FIX: smoking status detection in dynamic hints
-FIX: GKV checkup auto hint
-FIX: tetanus shot auto hint
-FIX: substance intake discontinuation reason field behaviour
-FIX: exception in clinical calculator with pre-birth test results
+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
 
-IMPROVED: file viewer detection on Windows [thanks John]
-IMPROVED: DICOM studies/series display
-IMPROVED: ZIP-with-DICOMDIR support
-IMPROVED: browse index.html after saving/burning from export area
-IMPROVED: substance abuse management workflow
-IMPROVED: check for tools im gm-describe_file
-IMPROVED: substance intake start/end formatting
+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
 
-NEW: a few hints from the German Choosing Wisely initiative
-NEW: CD/DVD sleeve LaTeX template
+NEW: placeholder $ph_cfg::encoding::$
+NEW: blanko AMTS Medikationsplan ~2.3
 ');
 
 -- --------------------------------------------------------------
-select gm.log_script_insertion('v21-release_notes-dynamic.sql', '21.6');
+select gm.log_script_insertion('v21-release_notes-dynamic.sql', '21.8');
diff --git a/server/sql/v20-v21/fixups/v21-AMTS_Medikationsplan-fixup.sql b/server/sql/v20-v21/fixups/v21-AMTS_Medikationsplan-fixup.sql
new file mode 100644
index 0000000..9c53a0f
--- /dev/null
+++ b/server/sql/v20-v21/fixups/v21-AMTS_Medikationsplan-fixup.sql
@@ -0,0 +1,112 @@
+-- ==============================================================
+-- GNUmed database schema change script
+--
+-- License: GPL v2 or later
+-- Author: karsten.hilbert at gmx.net
+--
+-- ==============================================================
+\set ON_ERROR_STOP 1
+--set default_transaction_read_only to off;
+
+-- --------------------------------------------------------------
+update ref.paperwork_templates set
+	name_long = 'Medikationsplan 2.0 (Deutschland, AMTS)',
+	name_short = 'MedPlan AMTS (D,2.0)',
+	gnumed_revision = '21.7',
+	in_use = false
+where
+	name_long = 'Medikationsplan (Deutschland, AMTS)';
+
+-- --------------------------------------------------------------
+delete from ref.paperwork_templates where name_long = 'Medikationsplan 2.3 (AMTS, Deutschland)';
+
+insert into ref.paperwork_templates (
+	fk_template_type,
+	instance_type,
+	name_short,
+	name_long,
+	external_version,
+	gnumed_revision,
+	engine,
+	filename,
+	edit_after_substitution,
+	data
+) values (
+	(select pk from ref.form_types where name = 'current medication list'),
+	'current medication list',
+	'MedPlan AMTS 2.3 (D)',
+	'Medikationsplan 2.3 (AMTS, Deutschland)',
+	'de-DE-2.3 AMTS',
+	21.8,
+	'L',
+	'amts-med_plan-2_3.tex',
+	false,
+	'real template missing'::bytea
+);
+
+-- --------------------------------------------------------------
+update ref.paperwork_templates set
+	name_long = 'Medikationsplan (Deutschland, NICHT konform zu AMTS 2.0)',
+	name_short = 'MedPlan AMTS (ähnlich 2.0, D)',
+	gnumed_revision = '21.7',
+	in_use = false
+where
+	name_long = 'Medikationsplan (Deutschland, NICHT konform zu AMTS)';
+
+
+-- --------------------------------------------------------------
+delete from ref.paperwork_templates where name_long = 'Medikationsplan AMTS (~2.3, NICHT konform, Deutschland)';
+
+insert into ref.paperwork_templates (
+	fk_template_type,
+	instance_type,
+	name_short,
+	name_long,
+	external_version,
+	gnumed_revision,
+	engine,
+	filename,
+	edit_after_substitution,
+	data
+) values (
+	(select pk from ref.form_types where name = 'current medication list'),
+	'current medication list',
+	'MedPlan AMTS (~2.3, D)',
+	'Medikationsplan AMTS (~2.3, NICHT konform, Deutschland)',
+	'21.8',
+	21.8,
+	'L',
+	'not-amts-med-plan-2_3.tex',
+	false,
+	'real template missing'::bytea
+);
+
+-- --------------------------------------------------------------
+delete from ref.paperwork_templates where name_long = 'Medikationsplan AMTS (blanko, ~2.3, NICHT konform, Deutschland)';
+
+insert into ref.paperwork_templates (
+	fk_template_type,
+	instance_type,
+	name_short,
+	name_long,
+	external_version,
+	gnumed_revision,
+	engine,
+	filename,
+	edit_after_substitution,
+	data
+) values (
+	(select pk from ref.form_types where name = 'current medication list'),
+	'current medication list',
+	'MedPlan AMTS (leer, ~2.3, D)',
+	'Medikationsplan AMTS (blanko, ~2.3, NICHT konform, Deutschland)',
+	'21.8',
+	21.8,
+	'L',
+	'not-amts-med-plan-2_3-blanko.tex',
+	false,
+	'real template missing'::bytea
+);
+
+-- --------------------------------------------------------------
+select gm.log_script_insertion('v21-AMTS_Medikationsplan-fixup.sql', '21.8');
diff --git a/server/sql/v20-v21/fixups/v21-ref-auto_hint-klug_entscheiden_pulmo.sql b/server/sql/v20-v21/fixups/v21-ref-auto_hint-klug_entscheiden_pulmo.sql
index 5822ab8..e0e5fee 100644
--- a/server/sql/v20-v21/fixups/v21-ref-auto_hint-klug_entscheiden_pulmo.sql
+++ b/server/sql/v20-v21/fixups/v21-ref-auto_hint-klug_entscheiden_pulmo.sql
@@ -11,69 +11,12 @@
 -- --------------------------------------------------------------
 DELETE FROM ref.auto_hint WHERE title = 'Raucher->Spiro (DGP/DGIM)';
 
-insert into ref.auto_hint(title, hint, source, lang, query, recommendation_query) values (
-	'Raucher->Spiro (DGP/DGIM)',
-	'Raucher sollen mit Spirometrie überwacht werden',
-	'"Gemeinsam klug entscheiden" (DGIM: DGP, 2016)',
-	'de',
-	'-- recently confirmed to be a smoker
-SELECT EXISTS (
-	SELECT 1 FROM clin.v_substance_intakes WHERE
-		(pk_patient = ID_ACTIVE_PATIENT)
-			AND
-		(atc_substance = ''N07BA01'')
-			AND
-		(coalesce(harmful_use_type, -1) IN (1,2))
-			AND
-		((discontinued IS NULL) OR (discontinued > now()))
-			AND
-		(last_checked_when > now() - ''1 year''::interval)
--- but no FEV1 documented within the last year
-) AND NOT EXISTS (
-	SELECT 1 FROM clin.v_test_results WHERE
-		(pk_patient = ID_ACTIVE_PATIENT)
-			AND
-		(
-			(unified_loinc = ''20150-9'')
-				OR
-			(lower(unified_name) = ''fev1'')
-				OR
-			(lower(unified_abbrev) = ''fev1'')
-		)
-			AND
-		(clin_when > now() - ''1 year''::interval)
-);',
-	'SELECT (
-	SELECT
-		''Patient raucht ('' || to_char(last_checked_when, ''YYYY Mon'') || ''), aber ''
-	FROM clin.v_substance_intakes WHERE
-		(pk_patient = ID_ACTIVE_PATIENT)
-			AND
-		(atc_substance = ''N07BA01'')
-) || (SELECT
-	coalesce (
-		(SELECT ''die letzte Spirometrie (FEV1 [20150-9)] ist über 1 Jahr her ('' || to_char(clin_when, ''YYYY Mon'') || '').''
-		FROM clin.v_test_results WHERE
-				(pk_patient = ID_ACTIVE_PATIENT)
-					AND
-				(
-					(unified_loinc = ''20150-9'')
-						OR
-					(lower(unified_name) = ''fev1'')
-						OR
-					(lower(unified_abbrev) = ''fev1'')
-				)
-		)::TEXT,
-		''es ist keine Spirometrie (FEV1 [20150-9]) dokumentiert.''::TEXT
-	)
-) as recommendation;'
-);
-
 -- --------------------------------------------------------------
 DELETE FROM ref.auto_hint WHERE title = 'Lunge->Pneumokkken-Impfg (DGP/DGIM)';
+DELETE FROM ref.auto_hint WHERE title = 'Lunge->Pneumokokken-Impfg (DGP/DGIM)';
 
 insert into ref.auto_hint(title, hint, source, lang, query, recommendation_query) values (
-	'Lunge->Pneumokkken-Impfg (DGP/DGIM)',
+	'Lunge->Pneumokokken-Impfg (DGP/DGIM)',
 	'Lungenkranke älter 60 sollen eine Pneumokokkenimpfung angeboten bekommen.',
 	'"Gemeinsam klug entscheiden" (DGIM: DGP, 2016)',
 	'de',
diff --git a/server/sql/v20-v21/python/v21-import-form-template-fixups.py b/server/sql/v20-v21/python/v21-import-form-template-fixups.py
index c2f555e..9dbe970 100644
--- a/server/sql/v20-v21/python/v21-import-form-template-fixups.py
+++ b/server/sql/v20-v21/python/v21-import-form-template-fixups.py
@@ -11,7 +11,6 @@ import os
 from Gnumed.pycommon import gmPG2
 
 #--------------------------------------------------------------
-
 def run(conn=None):
 
 	# CD/DVD sleeve
@@ -26,6 +25,51 @@ def run(conn=None):
 		conn = conn
 	)
 
+	# Begleitbrief
+	gmPG2.file2bytea (
+		query = u"""
+			UPDATE ref.paperwork_templates SET
+				data = %(data)s::bytea,
+				external_version = '21.8'
+			WHERE
+				name_long = 'Begleitbrief ohne medizinische Daten [K.Hilbert]'""",
+		filename = os.path.join('..', 'sql', 'v20-v21', 'data', 'v21-Begleitbrief.tex'),
+		conn = conn
+	)
+
+	# AMTS Medikationsplan v2.3, nicht konform
+	gmPG2.file2bytea (
+		query = u"""
+			UPDATE ref.paperwork_templates SET
+				data = %(data)s::bytea
+			WHERE
+				name_long = 'Medikationsplan 2.3 (AMTS, Deutschland)'""",
+		filename = os.path.join('..', 'sql', 'v20-v21', 'data', 'v21-Medikationsplan_AMTS-2.3.tex'),
+		conn = conn
+	)
+
+	# AMTS Medikationsplan v2.3, nicht konform
+	gmPG2.file2bytea (
+		query = u"""
+			UPDATE ref.paperwork_templates SET
+				data = %(data)s::bytea
+			WHERE
+				name_long = 'Medikationsplan AMTS (~2.3, NICHT konform, Deutschland)'""",
+		filename = os.path.join('..', 'sql', 'v20-v21', 'data', 'v21-Medikationsplan_AMTS-2.3-nicht_konform.tex'),
+		conn = conn
+	)
+
+	# AMTS Medikationsplan v2.3, nicht konform, blanko
+	gmPG2.file2bytea (
+		query = u"""
+			UPDATE ref.paperwork_templates SET
+				data = %(data)s::bytea
+			WHERE
+				name_long = 'Medikationsplan AMTS (blanko, ~2.3, NICHT konform, Deutschland)'""",
+		filename = os.path.join('..', 'sql', 'v20-v21', 'data', 'v21-Medikationsplan_AMTS-2.3-nicht_konform-blanko.tex'),
+		conn = conn
+	)
+
 	return True
 
 #==============================================================

-- 
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