diff --git a/src-modules/module/rpta/schluesseltabellen/lm_exam_unit_dim_studiengang_virtuell.sql b/src-modules/module/rpta/schluesseltabellen/lm_exam_unit_dim_studiengang_virtuell.sql
new file mode 100644
index 0000000..8f56eac
--- /dev/null
+++ b/src-modules/module/rpta/schluesseltabellen/lm_exam_unit_dim_studiengang_virtuell.sql
@@ -0,0 +1,384 @@
+--freemarker template
+
+
+select sp_table_exists('lm_exam_unit') from xdummy;
+
+
+select name
+ from sx_tables where name ='lm_exam_unit'
+
+
+= semester_von and lm_exam_unit.sem_der_pruefung <= semester_bis' as joinclause
+ from sx_tables where name in ('dim_studiengang')
+
+]]>
+
+
+
+
+<#if lm_exam_unit_exists==1>
+
+<#assign fact_table_target = {"name":"lm_exam_unit_dim_studiengang", "caption":"Einzelprüfungen und Studiengänge"}
+ />
+
+drop index if exists ix_lm_exam_unit_is_modul;
+
+
+CREATE temp table tmp_tables(
+name CHAR(255) ,
+caption CHAR(255) ,
+description CHAR(255) ,
+table_type CHAR(255) ,
+systeminfo_id INTEGER ,
+systeminfo_orig INTEGER ,
+thema CHAR(255) ,
+sachgebiete_id CHAR(255)
+);
+CREATE temp TABLE tmp_fields(
+tid serial NOT NULL,
+table_name VARCHAR(255) not null,
+name VARCHAR(255) not null,
+caption VARCHAR(255) ,
+description VARCHAR(255) ,
+field_type VARCHAR(255) not null,
+field_size VARCHAR(255) ,
+field_not_null smallint,
+currentlyused SMALLINT ,
+is_primarykey SMALLINT default 0 ,
+foreignkey_tab VARCHAR(255) ,
+foreignkey_col VARCHAR(255) ,
+foreignkey_int VARCHAR(255) ,
+foreignkey_cap VARCHAR(255) ,
+foreignkey_cond VARCHAR(255) ,
+foreignkey_func VARCHAR(255) ,
+check_integrity SMALLINT,
+is_sum SMALLINT default 1,
+foreignkey_uniquename VARCHAR(255)
+
+);
+
+
+
+update sx_fields set
+ is_sum=0
+ where table_name='lm_exam_unit'
+ and name!='summe';
+update sx_fields set
+ is_sum=1
+ where table_name='lm_exam_unit'
+ and name='summe';
+
+
+insert into tmp_tables (
+name,
+caption,
+description,
+table_type,
+systeminfo_id,
+thema,
+sachgebiete_id
+)
+select
+'${fact_table_target.name}',
+'${fact_table_target.caption}',
+description,
+table_type,
+systeminfo_id,
+thema,
+sachgebiete_id
+from sx_tables where name='${fact_table_source.name}'
+;
+
+
+insert into tmp_fields (table_name,
+ name,
+ caption,
+ description,
+ field_type,
+ field_size,
+ field_not_null,
+ currentlyused,
+ is_primarykey,
+ foreignkey_tab,
+ foreignkey_col,
+ foreignkey_int,
+ foreignkey_cap,
+ foreignkey_cond,
+ foreignkey_func,
+ check_integrity,
+ is_sum,
+ foreignkey_uniquename)
+select '${fact_table_target.name}' as table_name,
+ name,
+ caption,
+ description,
+ field_type,
+ field_size,
+ field_not_null,
+ currentlyused,
+ is_primarykey,
+ foreignkey_tab,
+ foreignkey_col,
+ foreignkey_int,
+ foreignkey_cap,
+ foreignkey_cond,
+ foreignkey_func,
+ check_integrity,
+ is_sum,
+ foreignkey_uniquename
+ from sx_fields where table_name ='${fact_table_source.name}'
+ and currentlyused=1;
+<#foreach added_table in added_tables>
+insert into tmp_fields (table_name,
+ name,
+ caption,
+ description,
+ field_type,
+ field_size,
+ field_not_null,
+ currentlyused,
+ is_primarykey,
+ foreignkey_tab,
+ foreignkey_col,
+ foreignkey_int,
+ foreignkey_cap,
+ foreignkey_cond,
+ foreignkey_func,
+ check_integrity,
+ is_sum,
+ foreignkey_uniquename)
+select '${fact_table_target.name}' as table_name,
+ '${added_table.prefix}' || name,
+ '${added_table.caption}: ' || caption,
+ description,
+ field_type,
+ field_size,
+ field_not_null,
+ currentlyused,
+ is_primarykey,
+ foreignkey_tab,
+ foreignkey_col,
+ foreignkey_int,
+ foreignkey_cap,
+ foreignkey_cond,
+ foreignkey_func,
+ check_integrity,
+ is_sum,
+ foreignkey_uniquename
+ from sx_fields where table_name ='${added_table.name}'
+ and currentlyused=1;
+#foreach>
+
+CREATE temp TABLE tmp_rpta_resultset
+(
+ caption varchar(255),
+ uniquename varchar(255),
+ fieldclause text,
+ joinclause text,
+ whereclause text,
+ systeminfo_id integer
+);
+
+insert into tmp_rpta_resultset(caption,
+ uniquename,
+ systeminfo_id)
+ select '${fact_table_target.caption}',
+ '${fact_table_target.name}',
+ 7
+;
+
+
+update tmp_rpta_resultset set fieldclause='
+<#foreach field_target in fields_target>
+${field_target.table_name}.${field_target.name} as ${field_target.targetname},
+#foreach>
+null::varchar as dummy',
+joinclause='${fact_table_source.name}
+<#foreach added_table in added_tables>
+left outer join ${added_table.name} on (${added_table.joinclause})
+#foreach>';
+
+select * into temp tmp_rs1
+from rpta_resultset
+;
+
+update rpta_resultset set caption=T.caption,
+ fieldclause=T.fieldclause,
+ joinclause=T.joinclause,
+ whereclause=T.whereclause
+ from tmp_rpta_resultset T
+ where T.systeminfo_id=rpta_resultset.systeminfo_id
+ and T.uniquename=rpta_resultset.uniquename
+ ;
+
+insert into rpta_resultset(caption,
+ uniquename,
+ fieldclause,
+ joinclause,
+ whereclause,
+ systeminfo_id)
+select caption,
+ uniquename,
+ fieldclause,
+ joinclause,
+ whereclause,
+ systeminfo_id
+ from tmp_rpta_resultset
+ where 0=(select count(*)
+ from tmp_rs1 T
+ where T.systeminfo_id=tmp_rpta_resultset.systeminfo_id
+ and T.uniquename=tmp_rpta_resultset.uniquename)
+ ;
+drop table tmp_rpta_resultset;
+drop table tmp_rs1;
+
+delete from sx_tables where name
+in (select T.name from tmp_tables T);
+
+insert into sx_tables (name,caption,description,table_type,systeminfo_id,systeminfo_orig,thema,sachgebiete_id)
+select name,caption,description,table_type,systeminfo_id,systeminfo_orig,thema,sachgebiete_id
+from tmp_tables;
+
+
+delete from sx_fields where table_name
+in (select T.table_name from tmp_fields T);
+
+insert into sx_fields (table_name,name,caption,description,field_type,
+field_size,
+field_not_null,
+currentlyUsed,
+foreignkey_tab,
+foreignkey_col,
+foreignkey_cap,
+foreignkey_int,
+foreignkey_cond,
+foreignkey_func,
+check_integrity,
+is_sum,
+foreignkey_uniquename
+)
+select
+F.table_name,F.name,F.caption,F.description,F.field_type,
+F.field_size,
+F.field_not_null,
+F.currentlyUsed,
+F.foreignkey_tab,
+F.foreignkey_col,
+F.foreignkey_cap,
+F.foreignkey_int,
+F.foreignkey_cond,
+F.foreignkey_func,
+F.check_integrity,
+F.is_sum,
+F.foreignkey_uniquename
+
+from tmp_fields F;
+
+
+drop table tmp_fields;
+drop table tmp_tables;
+
+
+--rpta_column füllen:
+select * into temp tmp_rc1
+from rpta_column;
+
+
+create temp table tmp_rpta_column(
+ uniquename varchar(255) NOT NULL,
+ caption varchar(255),
+ srcfieldname varchar(255),
+ column_type integer,
+ col_function text,
+ is_aggregate smallint,
+ resultset_id integer,
+ description text,
+ custom integer default 0
+ );
+
+insert into tmp_rpta_column( uniquename,
+ caption,
+ srcfieldname,
+ column_type,
+ col_function,
+ is_aggregate,
+ resultset_id,
+ description)
+ select F.name as uniquename,
+ coalesce(T.caption,T.name) || ' - ' || F.caption,
+ F.name as srcfieldname,
+ 1 as column_type,
+ (case when F.is_sum=1 then 'sum' else null::varchar end) as col_function,
+ (case when F.is_sum=1 then 1 else 0 end) as is_aggregate,
+ R.tid as resultset_id,
+ F.description
+from rpta_resultset R, sx_fields F left outer join sx_tables T on (T.name=F.table_name)
+where F.table_name='${fact_table_target.name}'
+and R.uniquename='${fact_table_target.name}'
+and F.currentlyused=1
+;
+
+update rpta_column set
+ caption=T.caption,
+ srcfieldname=T.srcfieldname,
+ column_type=T.column_type,
+ col_function=T.col_function,
+ is_aggregate=T.is_aggregate,
+ resultset_id=R.tid,
+ description=T.description,
+ custom=T.custom
+ from tmp_rpta_column T, rpta_resultset R
+where T.uniquename=rpta_column.uniquename
+and rpta_column.resultset_id=R.tid
+and R.uniquename='${fact_table_target.name}'
+;
+insert into rpta_column( uniquename,
+ caption,
+ srcfieldname,
+ column_type,
+ col_function,
+ is_aggregate,
+ resultset_id,
+ description,
+ custom)
+select T.uniquename,
+T.caption,
+T.srcfieldname,
+T.column_type,
+T.col_function,
+T.is_aggregate,
+R.tid as resultset_id,
+T.description,
+T.custom
+ from tmp_rpta_column T, rpta_resultset R
+ where R.uniquename='${fact_table_target.name}'
+ and 0=(select count(*) from tmp_rc1 C
+ where C.uniquename=T.uniquename
+ and C.resultset_id=R.tid)
+ ;
+
+drop table tmp_rpta_column;
+drop table tmp_rc1;
+
+#if> --wenn lm_exam_unit_exists=1
diff --git a/src-modules/module/rpta/schluesseltabellen/rptaColLay_lm_exam_unit_dim_studiengang_note_fuellen.sql b/src-modules/module/rpta/schluesseltabellen/rptaColLay_lm_exam_unit_dim_studiengang_note_fuellen.sql
new file mode 100644
index 0000000..bc777dd
--- /dev/null
+++ b/src-modules/module/rpta/schluesseltabellen/rptaColLay_lm_exam_unit_dim_studiengang_note_fuellen.sql
@@ -0,0 +1,373 @@
+--freemarker template
+<#include "RPTA-Makros"/>
+
+
+select count(*) from rpta_resultset where uniquename='lm_exam_unit_dim_studiengang';
+
+
+select uniquename from rpta_resultset where uniquename='lm_exam_unit_dim_studiengang';
+
+
+<#assign rpta_column_layouts = [{"uniquename":"lm_exam_unit_dim_studiengang_note",
+"caption":"Prüfungsergebnisse",
+"rpta_resultset":"lm_exam_unit_dim_studiengang",
+"whereclause":"modulart=''P''",
+"description":"Prüfung und Noten"
+}]
+ />
+
+<#assign rpta_columns = [
+
+{"uniquename":"elementnr",
+"srcfieldname":"elementnr",
+"column_type":"physicalColumn",
+"col_function":"",
+"format_code":"",
+"caption":"pnr",
+"is_visible":"1",
+"is_aggregate":0,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"pdtxt",
+"srcfieldname":"pdtxt",
+"column_type":"physicalColumn",
+"col_function":"",
+"format_code":"",
+"caption":"",
+"is_visible":"1",
+"is_aggregate":0,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"summe",
+"srcfieldname":"summe",
+"column_type":"physicalColumn",
+"col_function":"sum",
+"format_code":"",
+"caption":"Teilnehmer",
+"is_visible":"1",
+"is_aggregate":1,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"note_schnitt",
+"srcfieldname":"note",
+"targetfieldname":"note_schnitt",
+"column_type":"physicalColumn",
+"col_function":"avg",
+"format_code":"",
+"caption":"Durchschnittsnote *",
+"is_visible":"0",
+"is_aggregate":1,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"note_schnitt_case",
+"srcfieldname":"note_schnitt",
+"targetfieldname":"note_schnitt_case",
+"column_type":"computedColumn",
+"col_function":"case when summe < 5 then null else note_schnitt end",
+"format_code":"",
+"caption":"Durchschnittsnote *",
+"is_visible":"1",
+"is_aggregate":1,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"pstatus_nb",
+"srcfieldname":"pstatus",
+"targetfieldname":"pstatus_nb",
+"column_type":"logicalColumn",
+"col_function":"(case when pstatus in (''NB'',''EN'') then 1 else 0 end)",
+"format_code":"",
+"caption":"Durchfallquote in % *",
+"is_visible":"0",
+"is_aggregate":0,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"pstatus_nb_sum",
+"srcfieldname":"pstatus_nb",
+"targetfieldname":"pstatus_nb_sum",
+"column_type":"processingColumn",
+"col_function":"sum",
+"format_code":"",
+"caption":"Durchfallquote in % *",
+"is_visible":"0",
+"is_aggregate":1,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"pstatus_nb_quote",
+"srcfieldname":"pstatus_nb_sum",
+"targetfieldname":"pstatus_nb_quote",
+"column_type":"computedColumn",
+"col_function":"case when summe < 5 then null else pstatus_nb_sum/summe*100 end",
+"format_code":"",
+"caption":"Durchfallquote in % *",
+"is_visible":"1",
+"is_aggregate":1,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"pvermerk_ne",
+"srcfieldname":"pvermerk",
+"targetfieldname":"pvermerk_ne",
+"column_type":"logicalColumn",
+"col_function":"(case when pvermerk in (''NE'',''N'') then 1 else 0 end)",
+"format_code":"",
+"caption":"Nicht erschienen",
+"is_visible":"0",
+"is_aggregate":0,
+"visible_size":5,
+"description":""},
+
+ {"uniquename":"pvermerk_ne_sum",
+"srcfieldname":"pvermerk_ne",
+"targetfieldname":"pvermerk_ne_sum",
+"column_type":"processingColumn",
+"col_function":"sum",
+"format_code":"INTEGER",
+"caption":"Nicht erschienen",
+"is_visible":"1",
+"is_aggregate":1,
+"visible_size":5,
+"description":""}
+
+
+ ] />
+
+
+ ---ab hier nicht mehr ändern:
+
+CREATE temp TABLE tmp_rpta_column
+(
+ uniquename varchar(255) NOT NULL,
+ caption varchar(255),
+ srcfieldname varchar(255),
+ targetfieldname varchar(255),
+ column_type integer,
+ col_function text,
+ is_visible smallint,
+ visible_size smallint,
+ is_aggregate smallint,
+ resultset_id integer,
+ sortnr integer,
+ description TEXT,
+ format_code_uniquename varchar(255),
+ format_code_id integer
+);
+
+CREATE temp TABLE tmp_rpta_column_layout
+(
+ uniquename varchar(255) NOT NULL,
+ caption varchar(255),
+ resultset_id integer,
+ whereclause text,
+ description text
+);
+
+
+<#foreach rpta_column_layout in rpta_column_layouts>
+
+insert into tmp_rpta_column_layout(
+resultset_id,
+uniquename,
+caption,
+whereclause,
+ description
+)
+select tid,
+'${rpta_column_layout.uniquename}',
+'${rpta_column_layout.caption}',
+'${rpta_column_layout.whereclause}',
+'${rpta_column_layout.description}'
+FROM rpta_resultset
+where uniquename='${rpta_column_layout.rpta_resultset}';
+
+#foreach >
+
+<#assign sortnr=0 />
+<#foreach column in rpta_columns>
+<#assign sortnr=sortnr +1 />
+
+INSERT INTO tmp_rpta_column
+(resultset_id,
+ uniquename,
+ caption,
+ srcfieldname,
+ targetfieldname,
+ column_type,
+ col_function,
+ is_visible,
+ visible_size,
+ is_aggregate,
+ sortnr,
+ description,
+ format_code_uniquename
+ )
+select R.tid,
+'${column.uniquename}',
+'${column.caption}',
+'${column.srcfieldname}',
+<#if !column.targetfieldname?exists || column.targetfieldname=="">null::varchar <#else>'${column.targetfieldname}' #if>,
+T.tid as column_type,
+<#if column.col_function?exists>'${column.col_function}'<#else>null::varchar #if>,
+${column.is_visible},
+${column.visible_size},
+${column.is_aggregate},
+${sortnr*10},
+<#if column.description?exists>'${column.description}'<#else>null::varchar #if>,
+<#if column.format_code?exists>'${column.format_code}'<#else>null::varchar #if>
+FROM rpta_resultset R, rpta_column_type T
+where R.uniquename='${rpta_resultset}'
+and T.uniquename='${column.column_type}';
+
+#foreach>
+
+update tmp_rpta_column set format_code_id=C.tid
+from rpta_format_code C
+where C.uniquename=tmp_rpta_column.format_code_uniquename
+and format_code_uniquename is not null;
+
+
+select * into temp tmp_rpta_column2layout
+from rpta_column2layout
+where layout_id in (select L.tid
+from rpta_column_layout L,rpta_resultset R
+where R.tid=L.resultset_id
+and R.uniquename='${rpta_resultset}'
+and L.uniquename in (
+<#foreach rpta_column_layout in rpta_column_layouts>
+'${rpta_column_layout.uniquename}',
+#foreach>'xy')
+)
+;
+
+select * into temp tmp_rpta_column_layout_target
+from rpta_column_layout
+where resultset_id in (select tid
+FROM rpta_resultset
+where uniquename='${rpta_resultset}')
+and uniquename in (select uniquename from tmp_rpta_column_layout)
+;
+
+insert into rpta_column_layout
+(uniquename,
+ caption,
+ resultset_id,
+ whereclause,
+ description)
+ select uniquename,
+ caption,
+ resultset_id,
+ whereclause,
+ description
+FROM tmp_rpta_column_layout T
+where 0=(select count(*) from tmp_rpta_column_layout_target T2
+where T.uniquename=T2.uniquename);
+
+drop table tmp_rpta_column_layout_target;
+
+delete from rpta_column2layout
+where layout_id in (select L.tid
+from rpta_column_layout L,rpta_resultset R
+where R.tid=L.resultset_id
+and R.uniquename='${rpta_resultset}'
+and L.uniquename in (
+<#foreach rpta_column_layout in rpta_column_layouts>
+'${rpta_column_layout.uniquename}',
+#foreach>'xy')
+)
+;
+
+select * into temp tmp_rpta_column2
+from tmp_rpta_column T
+where (resultset_id,uniquename) not in
+(select resultset_id,uniquename from rpta_column);
+
+INSERT INTO rpta_column
+(resultset_id,
+ uniquename,
+ caption,
+ srcfieldname,
+ targetfieldname,
+ column_type,
+ col_function,
+ is_aggregate,
+ description,
+ custom
+ )
+ select
+resultset_id,
+ uniquename,
+ caption,
+ srcfieldname,
+ targetfieldname,
+ column_type,
+ col_function,
+ is_aggregate,
+ description,
+ 0 as custom
+from tmp_rpta_column2;
+
+--evtl. neuen Satz einfügen, dann alle updaten
+
+update rpta_column set ( caption,
+ srcfieldname,
+ targetfieldname,
+ column_type,
+ col_function,
+ is_aggregate,
+ description)
+ = (select caption,
+ srcfieldname,
+ targetfieldname,
+ column_type,
+ col_function,
+ is_aggregate,
+ description
+ from tmp_rpta_column T
+ where T.resultset_id=rpta_column.resultset_id
+ and T.uniquename=rpta_column.uniquename)
+ where custom=0
+ and (resultset_id,uniquename) in
+(select T.resultset_id,T.uniquename
+from tmp_rpta_column T)
+;
+
+drop table tmp_rpta_column2;
+
+insert into rpta_column2layout(column_id,
+ layout_id,
+ sortnr,
+ is_visible,
+ visible_size,
+ caption,
+ description,
+ format_code_id)
+select C.tid as column_id,
+ L.tid as layout_id,
+ T.sortnr,
+ T.is_visible,
+ T.visible_size,
+ T.caption,
+ T.description,
+ T.format_code_id
+FROM rpta_column C, rpta_column_layout L, tmp_rpta_column T
+where C.uniquename=T.uniquename
+and C.resultset_id=T.resultset_id
+and L.uniquename in (
+<#foreach rpta_column_layout in rpta_column_layouts>
+'${rpta_column_layout.uniquename}',
+#foreach>'xy')
+and L.resultset_id=T.resultset_id
+ ;
+drop table tmp_rpta_column;
+drop table if exists tmp_rpta_column2;
+drop TABLE tmp_rpta_column_layout;
+
+
+
+