diff --git a/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeKeyword_target_group.xml b/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeKeyword_target_group.xml
index 5d05350bab596ec9287d824a8c7ab0165f29d690..f8515fb50122a8812e7a0f974511d40592ceff61 100644
--- a/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeKeyword_target_group.xml
+++ b/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeKeyword_target_group.xml
@@ -4,7 +4,6 @@
         <insert tableName="AB_ATTRIBUTE">
             <column name="AB_ATTRIBUTEID" value="5d1a2b05-f04e-4ad7-9fd0-8efa09a33a53"/>
             <column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-            <column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
             <column name="ATTRIBUTE_NAME" value="Zielgruppe"/>
             <column name="ATTRIBUTE_PARENT_ID"/>
             <column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
diff --git a/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeType.xml b/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeType.xml
index d9d8b0d5c9a7af796f4e305693341aeacc76967b..93ebb8ff36a275392160f83e2038deba91ac4d51 100644
--- a/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeType.xml
+++ b/.liquibase/Data_alias/basic/2019.2/AditoBasic/init_AttributeType.xml
@@ -17,6 +17,24 @@
             <column name="ISACTIVE" valueNumeric="1"/>
             <column name="ISESSENTIAL" valueNumeric="1"/>
         </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="ee893a1c-d007-46fe-a190-727124c4467b"/>
+            <column name="KEYID" value="MEMO"/>
+            <column name="TITLE" value="Memo"/>
+            <column name="CONTAINER" value="AttributeType"/>
+            <column name="SORTING" valueNumeric="8"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="1"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="191d7293-3b3f-4dc7-bbe2-9da1a897f7df"/>
+            <column name="KEYID" value="VOID"/>
+            <column name="TITLE" value="${ATTRIBUTE_VOID}"/>
+            <column name="CONTAINER" value="AttributeType"/>
+            <column name="SORTING" valueNumeric="9"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="1"/>
+        </insert>
         <rollback>
             <delete tableName="AB_KEYWORD_ENTRY">
                 <where>AB_KEYWORD_ENTRYID = ?</where>
@@ -24,6 +42,18 @@
                     <param value="9d2f9605-1a5e-47d3-8920-168f5637e37f"/>
                 </whereParams>
             </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="ee893a1c-d007-46fe-a190-727124c4467b"/>
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="191d7293-3b3f-4dc7-bbe2-9da1a897f7df"/>
+                </whereParams>
+            </delete>
         </rollback>
     </changeSet>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.2/AttributeKeyword.xml b/.liquibase/Data_alias/basic/2019.2/AttributeKeyword.xml
index 272ae0c6a2922b4096ce2e511adc036fcdb3b88c..49dee3ca55dc85a16e91e58b830c601be7f83572 100644
--- a/.liquibase/Data_alias/basic/2019.2/AttributeKeyword.xml
+++ b/.liquibase/Data_alias/basic/2019.2/AttributeKeyword.xml
@@ -1,20 +1,23 @@
-<?xml version="1.1" encoding="UTF-8" standalone="no"?>
-<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
-    <changeSet author="s.listl" id="f527a5cc-f1e5-497f-a069-33aee944d421">
-	<addColumn tableName="AB_ATTRIBUTE">
-            <column name="KEYWORD_CONTAINER" type="VARCHAR(80)"/>
-            <column name="ATTRIBUTE_INFO" type="NCLOB"/>
-            <column name="SORTING" type="INTEGER"/>
-	</addColumn>
-	<addColumn tableName="AB_ATTRIBUTERELATION">
-            <column name="INT_VALUE" type="INTEGER"/>
-	</addColumn>
-        <dropColumn tableName="AB_ATTRIBUTERELATION">
-            <column name="BOOL_VALUE"/>
-        </dropColumn>
-	<modifyDataType tableName="AB_ATTRIBUTERELATION" columnName="CHAR_VALUE" newDataType="NVARCHAR(512)"/>
-	<createIndex indexName="IDX_ATTRPARENT" tableName="AB_ATTRIBUTE">
-		<column name="ATTRIBUTE_PARENT_ID"/>
-	</createIndex>
-    </changeSet>
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="s.listl" id="f527a5cc-f1e5-497f-a069-33aee944d421">
+	<addColumn tableName="AB_ATTRIBUTE">
+            <column name="KEYWORD_CONTAINER" type="VARCHAR(80)"/>
+            <column name="ATTRIBUTE_INFO" type="NCLOB"/>
+            <column name="SORTING" type="INTEGER"/>
+	</addColumn>
+	<addColumn tableName="AB_ATTRIBUTERELATION">
+            <column name="INT_VALUE" type="INTEGER"/>
+	</addColumn>
+        <dropColumn tableName="AB_ATTRIBUTERELATION">
+            <column name="BOOL_VALUE"/>
+        </dropColumn>
+        <dropColumn tableName="AB_ATTRIBUTE">
+            <column name="ATTRIBUTE_LEVEL"/>
+        </dropColumn>
+	<modifyDataType tableName="AB_ATTRIBUTERELATION" columnName="CHAR_VALUE" newDataType="NVARCHAR(512)"/>
+	<createIndex indexName="IDX_ATTRPARENT" tableName="AB_ATTRIBUTE">
+		<column name="ATTRIBUTE_PARENT_ID"/>
+	</createIndex>
+    </changeSet>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.2/activity_rename_Creator_to_Responsible.xml b/.liquibase/Data_alias/basic/2019.2/activity_rename_Creator_to_Responsible.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9892f159854d05b95c6dadcc766220e9746d2b61
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.2/activity_rename_Creator_to_Responsible.xml
@@ -0,0 +1,9 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+  <changeSet author="j.hoermann" id="5e48c1ac-ceb1-4b93-90b1-900a3c68351d">
+    <renameColumn tableName="ACTIVITY" oldColumnName="CREATOR" newColumnName="RESPONSIBLE"/>
+    <rollback>
+        <renameColumn tableName="ACTIVITY" oldColumnName="RESPONSIBLE" newColumnName="CREATOR"/>
+    </rollback>
+  </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2019.2/addDefaultAddresses.xml b/.liquibase/Data_alias/basic/2019.2/addDefaultAddresses.xml
new file mode 100644
index 0000000000000000000000000000000000000000..53c2858677b011f511d70426a00f473448665451
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.2/addDefaultAddresses.xml
@@ -0,0 +1,274 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="j.hoermann" id="58c94c79-1c82-43b3-bd19-324955d4cbfb">
+        <!--Lisa Sommer-->
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="11d01332-985b-4efe-a634-da71ae482907"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="ef345d11-a40d-59e0-a24c-afcb6095d2cb" />
+            </whereParams>
+        </update>
+        
+        <!--MNF-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="b3292432-bca2-4674-8b06-b78b2b06351e"/>
+            <column name="CITY" value="München"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="e6da1393-f46b-41a4-826b-2c7d22de2246"/>
+            <column name="ADDRIDENTIFIER" value="Tor 1"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="6a3f6232-7a66-4a72-8d2d-66a3a9f1b9ea"/>
+            <column name="BUILDINGNO" value="3"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="80807"/>
+            <column name="ADDRESS" value="Muster-Straße"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="6a3f6232-7a66-4a72-8d2d-66a3a9f1b9ea"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="e6da1393-f46b-41a4-826b-2c7d22de2246" />
+            </whereParams>
+        </update>
+        
+        <!--Lichtenstein-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="b3292432-bca2-4674-8b06-b78b2b06351e"/>
+            <column name="CITY" value="München"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="e83c45e0-c30b-436e-b445-00a8b58383b0"/>
+            <column name="ADDRIDENTIFIER" value="Tor 1"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="f54606ee-ecdd-4859-ad7d-aa096c5e9596"/>
+            <column name="BUILDINGNO" value="35"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="80807"/>
+            <column name="ADDRESS" value="Lützowplatz"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="f54606ee-ecdd-4859-ad7d-aa096c5e9596"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="e83c45e0-c30b-436e-b445-00a8b58383b0" />
+            </whereParams>
+        </update>
+        
+        <!--International Kältetechnik AG-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="b3292432-bca2-4674-8b06-b78b2b06351e"/>
+            <column name="CITY" value="München"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="eda61ea6-35ed-4a92-a93c-6118fc67d533"/>
+            <column name="ADDRIDENTIFIER" value="Tor 1"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="92a244c5-6065-458c-abc7-57d0dc955011"/>
+            <column name="BUILDINGNO" value="48"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="63847"/>
+            <column name="ADDRESS" value="Hildburghausen"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="92a244c5-6065-458c-abc7-57d0dc955011"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="e83c45e0-c30b-436e-b445-00a8b58383b0" />
+            </whereParams>
+        </update>
+        
+        <!--Pichelmaier Financial AG-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="b3292432-bca2-4674-8b06-b78b2b06351e"/>
+            <column name="CITY" value="München"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="fd082db5-be43-4219-a705-588f9c06e59b"/>
+            <column name="ADDRIDENTIFIER" value="Tor 1"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="90726b19-f23c-42dd-847a-7eacf4c71d18"/>
+            <column name="BUILDINGNO" value="6"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="54595"/>
+            <column name="ADDRESS" value="Rudower Strasse"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="90726b19-f23c-42dd-847a-7eacf4c71d18"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="fd082db5-be43-4219-a705-588f9c06e59b" />
+            </whereParams>
+        </update>
+        
+        <!--Peter Pfiffig-->
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="14d01332-985b-4efe-a634-da71ae482907"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="a2e084e2-d68a-4f1e-a1bb-f8d46ad6293d" />
+            </whereParams>
+        </update>
+        
+        <!--Franz Müller-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="a7466ee5-3fba-40bf-93cf-aa20a2b32ad6"/>
+            <column name="CITY" value="Bergkirchen"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="f0fb7676-8183-4bc7-beca-ca32c1e11c10"/>
+            <column name="ADDRIDENTIFIER"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="5773392d-cc7a-4170-8ffe-867807634c3c"/>
+            <column name="BUILDINGNO" value="32"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="85230"/>
+            <column name="ADDRESS" value="Büsingstrasse"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="5773392d-cc7a-4170-8ffe-867807634c3c"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="f0fb7676-8183-4bc7-beca-ca32c1e11c10" />
+            </whereParams>
+        </update>
+        
+        <!--Birgit Leicht-->
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="ce990566-3b86-48fe-bd0c-1167142e584b"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87" />
+            </whereParams>
+        </update>
+        
+        <!--Ludwig Kanzler-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="a7466ee5-3fba-40bf-93cf-aa20a2b32ad6"/>
+            <column name="CITY" value="München"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="73d731a2-e7f5-11e8-9f32-f2801f1b9fd1"/>
+            <column name="ADDRIDENTIFIER"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="8f6da43d-adc5-410e-8bc5-14adca88ebfe"/>
+            <column name="BUILDINGNO" value="83"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="80456"/>
+            <column name="ADDRESS" value="Landsberger Allee"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="8f6da43d-adc5-410e-8bc5-14adca88ebfe"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="73d731a2-e7f5-11e8-9f32-f2801f1b9fd1" />
+            </whereParams>
+        </update>
+        
+        <!--Jerome Grüner-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="a7466ee5-3fba-40bf-93cf-aa20a2b32ad6"/>
+            <column name="CITY" value="Niederkirchen"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="73d73404-e7f5-11e8-9f32-f2801f1b9fd1"/>
+            <column name="ADDRIDENTIFIER"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="84e040be-5a5f-48e7-be2c-769d4a169390"/>
+            <column name="BUILDINGNO" value="48"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="67700"/>
+            <column name="ADDRESS" value="Grosse Praesidenten Str."/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="84e040be-5a5f-48e7-be2c-769d4a169390"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="73d73404-e7f5-11e8-9f32-f2801f1b9fd1" />
+            </whereParams>
+        </update>
+        
+        <!--Herbert Obermeier-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Bayern"/>
+            <column name="ADDR_TYPE" value="a7466ee5-3fba-40bf-93cf-aa20a2b32ad6"/>
+            <column name="CITY" value="Bielefeld Babenhausen"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="57d524f6-ad66-4550-be83-fee6e31b7a52"/>
+            <column name="ADDRIDENTIFIER"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="f00966ec-693b-4bb5-8c66-26a40f18394f"/>
+            <column name="BUILDINGNO" value="67"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="33739"/>
+            <column name="ADDRESS" value="Spresstrasse"/>
+            <column name="DISTRICT" value="Oberbayern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="f00966ec-693b-4bb5-8c66-26a40f18394f"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="57d524f6-ad66-4550-be83-fee6e31b7a52" />
+            </whereParams>
+        </update>
+        
+        <!--Harold Smith-->
+        <insert tableName="ADDRESS">
+            <column name="STATE" value="Mecklenburg-Vorpommern"/>
+            <column name="ADDR_TYPE" value="a7466ee5-3fba-40bf-93cf-aa20a2b32ad6"/>
+            <column name="CITY" value="Rostock"/>
+            <column name="COUNTRY" value="DE"/>
+            <column name="CONTACT_ID" value="d105f7f4-afd1-4a98-adc2-13fd6934b7e9"/>
+            <column name="ADDRIDENTIFIER"/>
+            <column name="REGION" value=""/>
+            <column name="ADDRESSID" value="85bc81b9-5553-42a8-a643-eb47e1ed3c42"/>
+            <column name="BUILDINGNO" value="95"/>
+            <column name="ADDRESSADDITION"/>
+            <column name="ZIP" value="18074"/>
+            <column name="ADDRESS" value="Kurfürstendamm"/>
+            <column name="DISTRICT" value="Mecklenburg-Vorpommern"/>
+            <column name="USER_NEW" value="Admin"/>
+            <column name="DATE_NEW" valueComputed="current_datetime"/>
+        </insert>
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="85bc81b9-5553-42a8-a643-eb47e1ed3c42"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="d105f7f4-afd1-4a98-adc2-13fd6934b7e9" />
+            </whereParams>
+        </update>
+        
+        <!--Susanne Lustig-->
+        <update tableName="CONTACT">
+            <column name="ADDRESS_ID" value="89cbad0e-9901-42e2-ae40-a5a20c7ed5c8"/>
+            <where>CONTACTID = ? and ADDRESS_ID is null</where>
+            <whereParams>
+                <param value="1a67eaa7-21da-4a18-97ab-755ac5cb74f7" />
+            </whereParams>
+        </update>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.2/changelog.xml b/.liquibase/Data_alias/basic/2019.2/changelog.xml
index 696a1530088850673a2bf9f11448cd27a197ce00..1b72708d8c02275f50d4696ecf9e53ea4603a009 100644
--- a/.liquibase/Data_alias/basic/2019.2/changelog.xml
+++ b/.liquibase/Data_alias/basic/2019.2/changelog.xml
@@ -136,13 +136,20 @@
     <!-- Derby needs special handling -->
     <include relativeToChangelogFile="true" file="alter_activityLink_notDerby.xml" />
     <include relativeToChangelogFile="true" file="alter_activityLink_Derby.xml" />
-
+    
     <include relativeToChangelogFile="true" file="renameCycle_to_Milestone.xml" />
     <!-- Derby needs special handling -->
     <include relativeToChangelogFile="true" file="change_Milestone_datatype_to_new_Keyword_logic_notDerby.xml" />
     <include relativeToChangelogFile="true" file="change_Milestone_datatype_to_new_Keyword_logic_Derby.xml" />
     <include relativeToChangelogFile="true" file="update_Milestone_to_new_Keyword.xml" />
 
+    <include relativeToChangelogFile="true" file="data/example_person/PERSON_admin.xml" context="example"/>
+
+    <include relativeToChangelogFile="true" file="addDefaultAddresses.xml" context="example"/>
+
+    <include relativeToChangelogFile="true" file="activity_rename_Creator_to_Responsible.xml" />
+    <include relativeToChangelogFile="true" file="miscellaneous/Contact_additionalColumns.xml" />
+
     <include relativeToChangelogFile="true" file="CampaignManagement/create_campaign.xml"/>
     <include relativeToChangelogFile="true" file="CampaignManagement/create_campaignStep.xml"/>
     <include relativeToChangelogFile="true" file="CampaignManagement/create_campaignParticipant.xml"/>
diff --git a/.liquibase/Data_alias/basic/2019.2/create_salutation.xml b/.liquibase/Data_alias/basic/2019.2/create_salutation.xml
index 70b4f1edcdc170e7cc26d53a0969048ce77ca013..67338c9e4c8f7493a7221d9fbdd03c66e69d8492 100644
--- a/.liquibase/Data_alias/basic/2019.2/create_salutation.xml
+++ b/.liquibase/Data_alias/basic/2019.2/create_salutation.xml
@@ -7,8 +7,8 @@
             </column>   
             <column name="HEADLINE" type="NVARCHAR(50)"/>                       
             <column name="LANGUAGE" type="CHAR(3)"/>
-            <column name="LETTERSALUTATION" type="NVARCHAR(50)"/>
-            <column name="SALUTATION" type="NVARCHAR(50)"/>
+            <column name="LETTERSALUTATION" type="NVARCHAR(200)"/>
+            <column name="SALUTATION" type="NVARCHAR(200)"/>
             <column name="SEX" type="CHAR(36)"/>
             <column name="SORT" type="INTEGER"/>
             <column name="TITLE" type="NVARCHAR(30)"/>       
diff --git a/.liquibase/Data_alias/basic/2019.2/data/example_attribute/Attribute.xml b/.liquibase/Data_alias/basic/2019.2/data/example_attribute/Attribute.xml
index 632b9c9749a3758287c9d0ddfc316b3e6295dc25..83631681baec26337618c5f5a98b8aeb7fcf9618 100644
--- a/.liquibase/Data_alias/basic/2019.2/data/example_attribute/Attribute.xml
+++ b/.liquibase/Data_alias/basic/2019.2/data/example_attribute/Attribute.xml
@@ -1,17 +1,77 @@
 <?xml version="1.1" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
     <changeSet author="s.listl" id="f1b149fb-bd9d-44b7-a334-8f6d77261b95">
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Abteilungen"/>
+	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="29e6ddbf-77fd-4fb2-ae20-fdad9495dbd5"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Geschäftsleitung"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="0"/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="c9d81109-4406-4205-8b90-e27acf587cf1"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Vertrieb"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="1"/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="dc1427a9-056a-463a-a07f-f08f820fae0e"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Außendienst"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="c9d81109-4406-4205-8b90-e27acf587cf1"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="0"/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="5999ee67-44a4-4ec6-a4c4-6c6d58b8e50a"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Innendienst"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="c9d81109-4406-4205-8b90-e27acf587cf1"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="1"/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="93de7e9f-3ecd-45e7-aafe-020ab5f3ee79"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Marketing"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="2"/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="e47c7fb1-1072-4f03-a275-e4b6331deec1"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="IT/Service"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="3"/>
+</insert>
+<insert tableName="AB_ATTRIBUTE">
+	<column name="AB_ATTRIBUTEID" value="c133a157-0109-4d88-8343-71db25b12fc5"/>
+	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
+	<column name="ATTRIBUTE_NAME" value="Produktion"/>
+	<column name="ATTRIBUTE_PARENT_ID" value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+	<column name="ATTRIBUTE_TYPE" value="VOID                                "/>
+	<column name="SORTING" valueNumeric="4"/>
+</insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="752d7706-ac6e-4b51-a918-4265531794a4"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Mitbewerber"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="8af37871-d407-4414-98ad-e64dbaa5794a"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Preispolitik"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="752d7706-ac6e-4b51-a918-4265531794a4"/>
 	<column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
@@ -20,7 +80,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="558419b2-6113-4060-b88d-cc6324754765"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Stärke"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="752d7706-ac6e-4b51-a918-4265531794a4"/>
 	<column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
@@ -29,7 +88,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="71226196-2812-4d70-b90f-c3e2c14fd4d1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Schwäche"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="752d7706-ac6e-4b51-a918-4265531794a4"/>
 	<column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
@@ -38,14 +96,12 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="0644222a-2b3b-4f5e-a85a-d24c32fa0e72"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Interessen"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="53266a7c-58ed-47dc-bbe8-9e00b33cb344"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Kulanz"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="965823ef-fe63-41f8-9b0b-432f17ac31a7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -54,28 +110,24 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="0ecd14d9-837c-47fc-9676-afe71f7e5518"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Schadensart"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="965823ef-fe63-41f8-9b0b-432f17ac31a7"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Regulierung"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="10dc7354-cb50-4354-8412-2c35b569e3ad"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Technische Merkmale"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e7e05c6e-6108-44bd-824a-c076dfa5ae93"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="B"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="f11f65d0-4352-4f81-85d0-bfd034275e34"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -84,23 +136,22 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="ed4c3079-51b0-4bb5-b228-55de4309d5ab"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="0 gering"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e73ed929-8631-46de-b28f-eb1423abb808"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="6266b41c-fa20-47b9-bd71-5633015d0796"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="gut"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="dc52ede6-2b79-488c-b7bb-48877bd5d198"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="dc52ede6-2b79-488c-b7bb-48877bd5d198"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Stimmung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -109,7 +160,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Risiko"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -118,7 +168,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="54018b5e-0e02-48d1-873c-1c934d2e97ed"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Rennrad"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="65f0027d-7939-4342-b531-f31f10c3c045"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -127,15 +176,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="292825e8-fa96-4b7b-8dab-71955ae14571"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="A"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="f11f65d0-4352-4f81-85d0-bfd034275e34"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="4fcd8bb8-72fd-48d0-9e64-4c80e5177c36"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="NPO"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -145,14 +193,12 @@
 	<column name="AB_ATTRIBUTEID" value="9e9568c5-ad8a-4c1e-a6e6-72c9b4a3acf7"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
 	<column name="ATTRIBUTE_INFO" value="Als Attribut ist der Name aus lib_frame z.B. 'ORG' 'PERS' 'OFFER' etc. zu verwenden."/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Doku Vorlagen Verwendung"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="2b6e3225-9447-4706-9313-62c9463d6671"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Handwerk"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="da8e8568-63e0-41d3-a83f-2d8ae4982ba5"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -161,7 +207,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="be60e4b3-19b1-48a9-ad5c-c7d38698b4a1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Dumpingpreis Wettbewerb"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -170,23 +215,21 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="6d15f683-389e-4915-9043-c4cfdf188095"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Vollberechnung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="965823ef-fe63-41f8-9b0b-432f17ac31a7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="ab545654-1fce-4993-b763-0ec469781302"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
 	<column name="ATTRIBUTE_INFO" value="Konditionen die bei Angebotserstellung übernommen werden"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Konditionen"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="25e97db1-f796-497d-9842-3efcbb5bebf1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Sonstiges"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0644222a-2b3b-4f5e-a85a-d24c32fa0e72"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -195,7 +238,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="a844a395-e857-447d-b8f8-fa850bbceb82"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Produkttyp"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -204,7 +246,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="b1c552a0-eab9-417d-9f12-039d41603f6d"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="mittel"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="dc52ede6-2b79-488c-b7bb-48877bd5d198"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -213,7 +254,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="9e20d257-e2a7-4ef7-9253-1d8ed971b7b9"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="D"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="f11f65d0-4352-4f81-85d0-bfd034275e34"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -222,7 +262,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="0a6cbbc0-bd0e-4794-96ef-3d458d5fdb70"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="1 mittel"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e73ed929-8631-46de-b28f-eb1423abb808"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -231,7 +270,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="32612c75-b32c-4043-88c4-e8237acf8d5c"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="liebt Geselligkeit"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="25e97db1-f796-497d-9842-3efcbb5bebf1"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -240,7 +278,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="6db07a20-86bc-48da-8b27-b39bdd73b86b"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Projektverschiebung Kunde"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -249,7 +286,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="85c9cdd8-f7a6-4210-840e-fab8628f4dbe"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Qualitätsproblem Kunde"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -258,15 +294,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="7c39913b-a07c-4332-96ff-7b34b566ff49"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Wein"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7621696c-40ce-4cf2-92ec-74bc940e49ec"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="07fc6730-6c83-4996-bfd9-41c18765a10a"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Wechsel Entscheidungsträger"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -275,7 +310,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="26385e16-6b2f-428c-9c28-1bfa9c2ccf6f"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Finanzdienstleistung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -284,7 +318,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="65f0027d-7939-4342-b531-f31f10c3c045"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Sport"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0644222a-2b3b-4f5e-a85a-d24c32fa0e72"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -293,15 +326,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="7f01bfa6-ce9d-4964-b1e2-3cd5464d076a"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Gerät/Maschine"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="a844a395-e857-447d-b8f8-fa850bbceb82"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e857f9ee-fb27-4507-8381-46ba0a181cef"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Jahresurlaub"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="acaf54c3-9613-4740-aa22-4f6ebd0d6cb0"/>
 	<column name="ATTRIBUTE_TYPE" value="NUMBER                              "/>
@@ -309,15 +341,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="005b2ec8-68f3-4cbe-b9e5-783526e4c288"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Fernreisen"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="25e97db1-f796-497d-9842-3efcbb5bebf1"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="4dce5406-9a91-4a92-b55e-d1313c18f9c6"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Teilberechnung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="965823ef-fe63-41f8-9b0b-432f17ac31a7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -326,7 +357,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="9cfa5ce3-f1ae-4d18-9a65-0571f5ffb786"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="PERS"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="9e9568c5-ad8a-4c1e-a6e6-72c9b4a3acf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -335,14 +365,12 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Beurteilung"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Branche"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -350,7 +378,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="c7d28377-8cb1-4f92-a9ac-ed08041a782b"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Zielgruppe"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -359,7 +386,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="bb0c6356-33be-4e7c-a409-9ef5145f7aae"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Dienstleistung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -368,15 +394,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="17746b46-2702-447a-b749-a92bfdf4bb38"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Kunde"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="c7d28377-8cb1-4f92-a9ac-ed08041a782b"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="d0a9eb78-6dcf-48e0-ba91-04a3ba104d26"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Interessent"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="c7d28377-8cb1-4f92-a9ac-ed08041a782b"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -385,7 +410,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e4a60941-513f-4e75-a787-f00070ecb00a"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Hersteller"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="c7d28377-8cb1-4f92-a9ac-ed08041a782b"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -394,7 +418,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="1d30d0ab-6103-4972-84c0-fd23eef15ca1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Wettbewerber"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="c7d28377-8cb1-4f92-a9ac-ed08041a782b"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -403,7 +426,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Betreuung"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 	<column name="SORTING" valueNumeric="1"/>
@@ -411,21 +433,18 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="786148de-56b3-497e-88db-2ff5e4dc0bd7"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Kontaktierung"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="1d4c071b-237e-4a11-abff-0acaeaf6f8b1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Signatur"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="79ee6a0f-5192-4db3-9b05-156fd18b01b4"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Bier"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7621696c-40ce-4cf2-92ec-74bc940e49ec"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -434,7 +453,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="7621696c-40ce-4cf2-92ec-74bc940e49ec"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Genuss"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0644222a-2b3b-4f5e-a85a-d24c32fa0e72"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -443,7 +461,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="a3972e57-d081-463a-a33c-5d4d3af6d8f2"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Motorrad"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="65f0027d-7939-4342-b531-f31f10c3c045"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -452,7 +469,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="6819c616-a580-4bd6-ba41-9ba1db569dc4"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Drehzahl (rpm)"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="10dc7354-cb50-4354-8412-2c35b569e3ad"/>
 	<column name="ATTRIBUTE_TYPE" value="NUMBER                              "/>
@@ -461,15 +477,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="4c28a67b-dbc5-4399-bf33-b52e4cf82ffd"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="ORG"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="9e9568c5-ad8a-4c1e-a6e6-72c9b4a3acf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="2318607b-556a-4537-92f0-9870ee9a9201"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Zigarren"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7621696c-40ce-4cf2-92ec-74bc940e49ec"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -478,7 +493,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="43321e69-c8aa-4b0e-9c4e-8cde74f5c0fc"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Verschleißteil"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="a844a395-e857-447d-b8f8-fa850bbceb82"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -487,15 +501,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="9882c4bc-a3d9-43a9-8238-81ef39387869"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Maschinenbau"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e73ed929-8631-46de-b28f-eb1423abb808"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Loyalität"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -504,7 +517,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="b93fc811-e0dc-4e50-9ca6-107f43ac4c0c"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Tabellen Daten"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="be31d7a5-9a02-4ae0-8265-916d32c1fccb"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -512,14 +524,12 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="915d566f-acbe-448c-a7b6-11898adc3880"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Liefersperre"/>
 	<column name="ATTRIBUTE_TYPE" value="BOOLEAN                             "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="d14f6eea-8760-43bf-ad3a-e7c3e4416392"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Partner"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="c7d28377-8cb1-4f92-a9ac-ed08041a782b"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -528,7 +538,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="f310ae37-5ec3-47c6-839b-a92fc8fcd252"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Geburtstagsliste"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -537,7 +546,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="62b43c0f-9afb-4b57-8b7d-de38d43a9d47"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Nein"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="f310ae37-5ec3-47c6-839b-a92fc8fcd252"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -546,22 +554,20 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="ddf607c0-a45b-4255-bf4e-b2d515df4b86"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Ja"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="f310ae37-5ec3-47c6-839b-a92fc8fcd252"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="fd3963bc-8e60-411a-9911-b97eb73e5cf7"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Projektart"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="3265f271-2e85-42b2-84af-c9e23e8a1e8c"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Intern"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="fd3963bc-8e60-411a-9911-b97eb73e5cf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -570,7 +576,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="615d3850-ef32-4988-9a8d-7b702b489194"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Partner"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="fd3963bc-8e60-411a-9911-b97eb73e5cf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -579,7 +584,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="be3b5fe2-2146-4eab-80a4-3c1cf4d6156a"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Bestandskunde"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="fd3963bc-8e60-411a-9911-b97eb73e5cf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -588,23 +592,22 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="87204e4b-2db2-4eb4-b216-5e16b227561e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Interessent"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="fd3963bc-8e60-411a-9911-b97eb73e5cf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="4a9625ed-0cd9-445f-ae13-5bdbfdf3f38c"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Fussball"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="65f0027d-7939-4342-b531-f31f10c3c045"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="66271d11-a275-4141-8f84-86ab2ed3fedf"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Förderband"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="10dc7354-cb50-4354-8412-2c35b569e3ad"/>
 	<column name="ATTRIBUTE_TYPE" value="BOOLEAN                             "/>
@@ -613,7 +616,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="fa0171cf-2e0d-4ff0-bbe7-8ff083a96593"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="weitere Daten"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="be31d7a5-9a02-4ae0-8265-916d32c1fccb"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -622,7 +624,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="974bbd28-08b3-41a4-bd74-7d9c3c778249"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="kein Risiko"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -631,7 +632,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="9350afa2-7181-4eb4-b731-3699fe71b0f6"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="schlecht"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="dc52ede6-2b79-488c-b7bb-48877bd5d198"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -640,7 +640,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="d8949d8f-051b-4f5b-ba61-5af49e9499cc"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Ersatzteil"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="a844a395-e857-447d-b8f8-fa850bbceb82"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -649,7 +648,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="23a4d394-9fae-4205-a811-730d5109c115"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Segeln"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="65f0027d-7939-4342-b531-f31f10c3c045"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -658,7 +656,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="b78ef891-16a3-4354-bc95-7b70ef5b4e2e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Werkzeugwechsler"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="10dc7354-cb50-4354-8412-2c35b569e3ad"/>
 	<column name="ATTRIBUTE_TYPE" value="BOOLEAN                             "/>
@@ -667,7 +664,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="617da3f5-d8bc-45ff-85a1-258621ea2a0b"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Logistik"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -676,7 +672,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="1a3c1c77-e57c-4481-a67f-adf7e084ea90"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="IT"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="da8e8568-63e0-41d3-a83f-2d8ae4982ba5"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -685,15 +680,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="953e3b5e-0ca7-4215-8dee-b0ba28ef1bf9"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Zahlungsproblem Kunde"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="691452ec-3b9f-43dc-91a2-645a97b775b2"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="2bdb04cb-4cd3-4454-802c-8e2b4a5e2e36"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Behörde"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -702,7 +696,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="30be2556-e09b-4169-be32-d4bafeb89a2f"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Tourismus"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="da8e8568-63e0-41d3-a83f-2d8ae4982ba5"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -711,7 +704,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="acafca42-8ef4-4c21-abe8-1c2ca358a5aa"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Handel"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -720,7 +712,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="79378933-9f74-4391-b876-4528b582661f"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Bauwesen"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="7e9927a4-41e4-426f-bddd-c3e9ee3b093e"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -729,7 +720,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="c85a5ebe-80fe-4176-a92a-35d2200baa07"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="2 gross"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e73ed929-8631-46de-b28f-eb1423abb808"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -738,7 +728,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="7b687991-601c-4d75-b201-00a6cc9c6b93"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Gewicht (kg)"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="10dc7354-cb50-4354-8412-2c35b569e3ad"/>
 	<column name="ATTRIBUTE_TYPE" value="NUMBER                              "/>
@@ -746,7 +735,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="f11f65d0-4352-4f81-85d0-bfd034275e34"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Bonität"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="e32cd923-3774-41c1-95d5-57b79e52e568"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -755,7 +743,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="da8e8568-63e0-41d3-a83f-2d8ae4982ba5"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Beruf"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0644222a-2b3b-4f5e-a85a-d24c32fa0e72"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBO                               "/>
@@ -763,14 +750,12 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="acaf54c3-9613-4740-aa22-4f6ebd0d6cb0"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Personal"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="957d61a4-0038-46e0-b5a3-fc2a5d413004"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="C"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="f11f65d0-4352-4f81-85d0-bfd034275e34"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -779,22 +764,20 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="be31d7a5-9a02-4ae0-8265-916d32c1fccb"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="zusätzliche Daten"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="4d4ef830-68e6-4228-9e4f-13614d841328"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Wirtschaft"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="da8e8568-63e0-41d3-a83f-2d8ae4982ba5"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="bb62ae03-be34-4d34-885c-27591c5bf1b4"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Golf"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="65f0027d-7939-4342-b531-f31f10c3c045"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -803,7 +786,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="0afb463f-6ce4-4dfb-b093-09a8fcd925a3"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="2"/>
 	<column name="ATTRIBUTE_NAME" value="Bauteil"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="a844a395-e857-447d-b8f8-fa850bbceb82"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -812,14 +794,12 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="bad29370-3c47-4ac7-8d5d-4e86439000ef"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Mitarbeiterkonto"/>
 	<column name="ATTRIBUTE_TYPE" value="GROUP                               "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="97c6f6ec-2ed2-4c26-8612-b524e3ef15db"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="DOCUMENT"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="9e9568c5-ad8a-4c1e-a6e6-72c9b4a3acf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -828,7 +808,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="fffbb6b5-05ea-4f76-83c6-cf2cb29ef576"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="unvollständige Lieferung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0ecd14d9-837c-47fc-9676-afe71f7e5518"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -837,7 +816,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="5c188c8c-14b2-4c66-ad48-65b750e05353"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Qualitätsbeanstandung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0ecd14d9-837c-47fc-9676-afe71f7e5518"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -846,7 +824,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="3600aba4-01d4-4ca3-a3e7-79e0b946a2b1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="fehlerhafte Lieferung"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0ecd14d9-837c-47fc-9676-afe71f7e5518"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -855,15 +832,14 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="66b64741-a896-4404-874a-b83b3525fcff"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Transportschaden"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="0ecd14d9-837c-47fc-9676-afe71f7e5518"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
+	<column name="SORTING" valueNumeric="0"/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="c0fb9a3a-89a5-46a4-9b95-f48c9481375e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="EVENT"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="9e9568c5-ad8a-4c1e-a6e6-72c9b4a3acf7"/>
 	<column name="ATTRIBUTE_TYPE" value="COMBOVALUE                          "/>
@@ -872,7 +848,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="292fae38-6557-466d-8843-3b1b4a1f6599"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Zahlungskondition"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="ab545654-1fce-4993-b763-0ec469781302"/>
 	<column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
@@ -881,7 +856,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="3a6e11fc-b00a-4cf3-975a-a5e8b60fc5cb"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Lieferkondition"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="ab545654-1fce-4993-b763-0ec469781302"/>
 	<column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
@@ -890,7 +864,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="97b449a5-d9b4-42ff-b9b0-4f8b27b8a9ec"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Preisliste"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="ab545654-1fce-4993-b763-0ec469781302"/>
 	<column name="ATTRIBUTE_TYPE" value="KEYWORD                             "/>
@@ -900,14 +873,12 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e7886e41-252e-414c-a169-5d1481d010c8"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Lieferant"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="44d53f3a-a8cd-4e79-bc09-a6e17d678e7e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Rückantwort Kampagne"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="786148de-56b3-497e-88db-2ff5e4dc0bd7"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -915,7 +886,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e8999504-5851-4934-a3f1-fb4b513d41e9"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="schreibt für"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="1d4c071b-237e-4a11-abff-0acaeaf6f8b1"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -923,21 +893,18 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="33cb83f1-aee2-469e-b57d-666ac6725f61"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="Unterkampagne von"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="093c7337-c134-4be5-a215-dc94804c3511"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="0"/>
 	<column name="ATTRIBUTE_NAME" value="übergeordnete Kampagne von"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="28fd7a4b-72d8-40ff-a893-a9479abcf19e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Feiertag"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="bad29370-3c47-4ac7-8d5d-4e86439000ef"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -945,7 +912,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="14847ea6-b6fd-43f6-a819-af2b1e53177e"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Innendienst"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -953,7 +919,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="cd90b9e3-e663-4248-b9ed-4e25ed330c58"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Aussendienst"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -961,7 +926,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="7abdc3a7-f46b-4021-b695-7fde6b21c6a4"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Service"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -969,7 +933,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="2f963668-9e8c-41d7-aee4-6beaf37492e4"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Besuchsfrequenz"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -977,7 +940,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="ff84c147-27c7-4698-83ff-0e25b1d33851"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Vorgesetzter von"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -985,7 +947,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="d637fc6c-9452-4498-8379-ec71d946cbab"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="berichtet an"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -993,7 +954,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="6bdb658c-94bc-4e68-aefb-a38483ee68b1"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Gebiet"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -1001,7 +961,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="3e5736c4-93ff-4471-96f5-48bb34ab53d2"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Urlaubsgenehmigung durch"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -1009,7 +968,6 @@
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="3f119858-9d69-4903-a572-d286be151f73"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="1"/>
-	<column name="ATTRIBUTE_LEVEL" valueNumeric="1"/>
 	<column name="ATTRIBUTE_NAME" value="Urlaubsprüfung durch"/>
 	<column name="ATTRIBUTE_PARENT_ID" value="83e627b7-39da-4519-8023-ed384d3a0a42"/>
 	<column name="ATTRIBUTE_TYPE" value="TEXT                                "/>
@@ -1735,6 +1693,19 @@
 		<param value="3f119858-9d69-4903-a572-d286be151f73"/>
 	</whereParams>
 </delete>
+<delete tableName="AB_ATTRIBUTE">
+	<where>AB_ATTRIBUTEID in (?, ?, ?, ?, ?, ?, ?, ?)</where>
+	<whereParams>
+		<param value="87d4ff5b-0ab6-4534-be26-76c6ef486072"/>
+		<param value="29e6ddbf-77fd-4fb2-ae20-fdad9495dbd5"/>
+		<param value="c9d81109-4406-4205-8b90-e27acf587cf1"/>
+		<param value="dc1427a9-056a-463a-a07f-f08f820fae0e"/>
+		<param value="5999ee67-44a4-4ec6-a4c4-6c6d58b8e50a"/>
+		<param value="93de7e9f-3ecd-45e7-aafe-020ab5f3ee79"/>
+		<param value="e47c7fb1-1072-4f03-a275-e4b6331deec1"/>
+		<param value="c133a157-0109-4d88-8343-71db25b12fc5"/>
+	</whereParams>
+</delete>
 </rollback>
     </changeSet>
 </databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2019.2/data/example_person/PERSON_admin.xml b/.liquibase/Data_alias/basic/2019.2/data/example_person/PERSON_admin.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0c15468561e1105847a568f7e64803487f37cbeb
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.2/data/example_person/PERSON_admin.xml
@@ -0,0 +1,78 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+<changeSet author="j.hoermann" id="d750c022-e34c-4903-8146-bd89121c0214">
+    <insert tableName="PERSON">
+        <column name="PERSONID" value="b16282bd-254e-4569-a56e-675449821467"/>
+        <column name="FIRSTNAME" value="Tim"/>
+        <column name="MIDDLENAME"/>
+        <column name="LASTNAME" value="Admin"/>
+        <column name="SALUTATION" value="Herr"/>
+        <column name="DATEOFBIRTH" valueDate="1993-05-07"/>
+        <column name="USER_NEW" value="Admin"/>
+        <column name="DATE_NEW" valueComputed="current_datetime"/>
+    </insert>
+    <insert tableName="CONTACT">
+        <column name="RELATIONSHIP" valueNumeric="1"/>
+        <column name="LANGUAGE" value="deu"/>
+        <column name="PERSON_ID" value="b16282bd-254e-4569-a56e-675449821467"/>
+        <column name="CONTACTID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
+        <column name="ORGANISATION_ID" value="b219b58a-f120-42d8-9a64-0b176501eac7"/>
+        <column name="STATUS" value="BSIC0rel-stat-actv-ae03-b6b04430e90b"/>
+        <column name="ADDRESS_ID" value="0e6d2504-adda-453a-bb36-981e6d0f06c7"/>
+        <column name="USER_NEW" value="Admin"/>
+        <column name="DATE_NEW" valueComputed="current_datetime"/>
+    </insert>
+    <insert tableName="ADDRESS">
+        <column name="STATE" value="Freistaat Bayern"/>
+        <column name="ADDR_TYPE" value="a7466ee5-3fba-40bf-93cf-aa20a2b32ad6"/>
+        <column name="CITY" value="Heinrichsthal"/>
+        <column name="COUNTRY" value="DE"/>
+        <column name="CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
+        <column name="ADDRIDENTIFIER"/>
+        <column name="REGION" value=""/>
+        <column name="ADDRESSID" value="0e6d2504-adda-453a-bb36-981e6d0f06c7"/>
+        <column name="BUILDINGNO" value="77"/>
+        <column name="ADDRESSADDITION"/>
+        <column name="ZIP" value="18074"/>
+        <column name="ADDRESS" value="Rudolstaedter Strasse"/>
+        <column name="DISTRICT" value="Bayern"/>
+        <column name="USER_NEW" value="Admin"/>
+        <column name="DATE_NEW" valueComputed="current_datetime"/>
+    </insert>
+    <insert tableName="COMMUNICATION">
+        <column name="COMMUNICATIONID" value="3ccc54d5-dfb0-4da9-a0a0-472025f65994"/>
+        <column name="CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
+        <column name="MEDIUM_ID" value="85ee16dd-c878-4463-be6a-324c25e76764"/>
+        <column name="ADDR" value="Admin@domain.local"/>
+        <column name="STANDARD" valueNumeric="1"/>
+        <column name="USER_NEW" value="Admin"/>
+        <column name="DATE_NEW" valueComputed="current_datetime"/>
+    </insert>
+    <rollback>
+        <delete tableName="CONTACT">
+            <where>CONTACTID = ?</where>
+            <whereParams>
+                <param value="c7ddf982-0e58-4152-b82b-8f5673b0b729" />
+            </whereParams>
+        </delete>
+        <delete tableName="COMMUNICATION">
+            <where>CONTACTID = ?</where>
+            <whereParams>
+                <param value="c7ddf982-0e58-4152-b82b-8f5673b0b729" />
+            </whereParams>
+        </delete>
+        <delete tableName="PERSON">
+            <where>PERSONID = ?</where>
+            <whereParams>
+                <param value="b16282bd-254e-4569-a56e-675449821467" />
+            </whereParams>
+        </delete>
+        <delete tableName="ADDRESS">
+            <where>CONTACT_ID = ?</where>
+            <whereParams>
+                <param value="c7ddf982-0e58-4152-b82b-8f5673b0b729" />
+            </whereParams>
+        </delete>
+    </rollback>
+</changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2019.2/miscellaneous/Contact_additionalColumns.xml b/.liquibase/Data_alias/basic/2019.2/miscellaneous/Contact_additionalColumns.xml
new file mode 100644
index 0000000000000000000000000000000000000000..83081ee094303aef88ca871bfbcbc6a55bc6eb61
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.2/miscellaneous/Contact_additionalColumns.xml
@@ -0,0 +1,9 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    
+    <changeSet author="j.goderbauer" id="bd41fff1-d139-41ea-ad0f-b30b77d69690">
+        <addColumn tableName="CONTACT">
+            <column name="LETTERSALUTATION" type="NVARCHAR(200)" />
+        </addColumn>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/2019.2/changelog.xml b/.liquibase/_____SYSTEMALIAS/basic/2019.2/changelog.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d389926043b6ea55c275f5074e7234d8874dc4cc
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/2019.2/changelog.xml
@@ -0,0 +1,5 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <include relativeToChangelogFile="true" file="create_asys_notifications.xml"/>
+    <include relativeToChangelogFile="true" file="create_asys_notificationcontents.xml"/>
+</databaseChangeLog>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/2019.2/create_asys_notificationcontents.xml b/.liquibase/_____SYSTEMALIAS/basic/2019.2/create_asys_notificationcontents.xml
new file mode 100644
index 0000000000000000000000000000000000000000..83818826decb7b62e72d42f34875cb823311b982
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/2019.2/create_asys_notificationcontents.xml
@@ -0,0 +1,22 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+<changeSet author="a.schindlbeck" id="6b25f062-fb39-4230-9348-b67ec5ec45a1">
+    <createTable tableName="ASYS_NOTIFICATIONCONTENTS">
+        <column name="CONTENTID" type="CHAR(36)">
+            <constraints primaryKey="true" primaryKeyName="PK_ASYS_NOTIFICATIONCONTENTS_CONTENTID"/>
+        </column>
+        <column name="BACKPACK" type="CLOB"/>
+        <column name="CAPTION" type="VARCHAR(512)"/>
+        <column name="CREATIONDATE" type="BIGINT"/>
+        <column name="DESCRIPTION" type="VARCHAR(1023)"/>
+        <column name="FORCEDPRIORITY" type="INTEGER"/>
+        <column name="ICON_INFO" type="VARCHAR(1023)"/>
+        <column name="LIFETIME" type="BIGINT"/>
+        <column name="LINK_INFO" type="VARCHAR(1023)"/>
+        <column name="ORIGINATORNAME" type="VARCHAR(63)"/>
+        <column name="RECIPIENTUSERIDS" type="CLOB"/>
+        <column name="TYPECODE" type="VARCHAR(63)"/>
+        <column name="VERSION" type="INTEGER"/>
+    </createTable>
+</changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/2019.2/create_asys_notifications.xml b/.liquibase/_____SYSTEMALIAS/basic/2019.2/create_asys_notifications.xml
new file mode 100644
index 0000000000000000000000000000000000000000..540cf0a19ee9c36c179b3f49a772afd8495473f7
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/2019.2/create_asys_notifications.xml
@@ -0,0 +1,17 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+<changeSet author="a.schindlbeck" id="98f057b6-0140-4edd-b08d-9cc7cf178bab">
+    <!---
+	its ok to drop the old ASYS_NOTIFICATIONS due to new version
+    -->
+    <dropTable tableName="ASYS_NOTIFICATIONS"/>
+    <createTable tableName="ASYS_NOTIFICATIONS">
+        <column name="ID" type="CHAR(36)">
+            <constraints primaryKey="true" primaryKeyName="PK_ASYS_NOTIFICATIONS_ID"/>
+        </column>
+        <column name="CONTENTID" type="CHAR(36)"/>
+        <column name="STATE" type="VARCHAR(16)"/>
+        <column name="USERID" type="VARCHAR(63)"/>
+    </createTable>
+</changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____configuration.xml b/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____configuration.xml
index 0808967704be0c95f53d4cad4524a9660e07eb8a..a57bd0f04271547aaf28e4f103e6a625bd2d8804 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____configuration.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____configuration.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<aliasConfig xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.7" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/aliasConfig/1.0.7">
+<aliasConfig xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/aliasConfig/1.1.0">
   <name>_____CONFIGURATION</name>
   <serverId>default</serverId>
   <definitionName>_____CONFIGURATION</definitionName>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____system_sysdb_version.xml b/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____system_sysdb_version.xml
index 59bf0767b66fe17465aa47e845310a64b932ea6d..263bf76d5d876fa69aaabaef1f06f01b5e4e1c01 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____system_sysdb_version.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/_____system_sysdb_version.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <sysDbVersion xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/sysDbVersion/1.2.0">
   <name>_____SYSTEM_SYSDB_VERSION</name>
-  <systemDbVersion>2.5.1</systemDbVersion>
+  <systemDbVersion>2.6.0</systemDbVersion>
 </sysDbVersion>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/data_alias.xml b/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/data_alias.xml
index 96e374b63bfba36595e9eef04af49ece136932a9..e6eb125c832854bf0e6dd3e0c5f88d2ee198db51 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/data_alias.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/data/defaultBlob/data_alias.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<aliasConfig xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.7" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/aliasConfig/1.0.7">
+<aliasConfig xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/aliasConfig/1.1.0">
   <name>f50ee138-12d9-420d-a4f9-9b8257e207e4</name>
   <description>jdbc:derby://localhost:1527/basic_data</description>
   <serverId>default</serverId>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_system.xml b/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_system.xml
index 5065651e3bced3f53c7fcd357f402fba4ba1384c..38d99e05952657760911852cb369a4853b78e69e 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_system.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_system.xml
@@ -7,7 +7,7 @@
         <column name="DATE_NEW" valueDate="2018-05-24T14:53:57.763"/>
         <column name="KIND" valueNumeric="600"/>
         <column name="NAME" value="_____SYSTEM_SYSDB_VERSION"/>
-        <column name="TITLE" value="2.5.1"/>
+        <column name="TITLE" value="2.6.0"/>
         <column name="USER_EDIT" value="_____DESIGNERANONYM"/>
         <column name="USER_NEW" value="_____DESIGNERANONYM"/>
         <column name="XMLDATA" valueBlobFile="defaultBlob/_____system_sysdb_version.xml"/>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_users-admin.xml b/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_users-admin.xml
index 985b5d19534f4f4ffcc60ecd673f6c907f1e0730..33f7425c15c97e76ac83a3a172c4c79849fb88bb 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_users-admin.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/data/insert_asys_users-admin.xml
@@ -10,6 +10,15 @@
         <column name="PROPKEY" value="lastModified"/>
         <column name="PROPVAL" value="1544193908535"/>
     </insert>
+    <insert tableName="ASYS_USERS">
+        <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
+        <column name="DATE_NEW" valueDate="2018-05-25T09:52:30.361"/>
+        <column name="GROUPID" value="BASIC"/>
+        <column name="ID" value="cdb34f95-e414-4807-bbdb-f369138ee49f"/>
+        <column name="NAME" value="_____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046"/>
+        <column name="PROPKEY" value="contactID"/>
+        <column name="PROPVAL" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
+    </insert>
     <insert tableName="ASYS_USERS">
         <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
         <column name="DATE_NEW" valueDate="2018-05-25T09:52:30.361"/>
@@ -19,6 +28,15 @@
         <column name="PROPKEY" value="name"/>
         <column name="PROPVAL" value="_____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046"/>
     </insert>
+    <insert tableName="ASYS_USERS">
+        <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
+        <column name="DATE_NEW" valueDate="2018-05-25T09:52:30.361"/>
+        <column name="GROUPID" value="BASIC"/>
+        <column name="ID" value="c17c88f5-74e2-44a1-ae68-8130918b43d3"/>
+        <column name="NAME" value="_____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046"/>
+        <column name="PROPKEY" value="isActive"/>
+        <column name="PROPVAL" value="true"/>
+    </insert>
     <insert tableName="ASYS_USERS">
         <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
         <column name="DATE_NEW" valueDate="2018-05-25T09:52:30.361"/>
@@ -28,6 +46,15 @@
         <column name="PROPKEY" value="title"/>
         <column name="PROPVAL" value="Admin"/>
     </insert>
+    <insert tableName="ASYS_USERS">
+        <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
+        <column name="DATE_NEW" valueDate="2018-05-25T09:52:30.361"/>
+        <column name="GROUPID" value="PERSONAL"/>
+        <column name="ID" value="93c88dff-a6b0-49ce-b7b4-e474b7ca7fb6"/>
+        <column name="NAME" value="_____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046"/>
+        <column name="PROPKEY" value="firstname"/>
+        <column name="PROPVAL" value="Tim"/>
+    </insert>
     <insert tableName="ASYS_USERS">
         <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
         <column name="DATE_NEW" valueDate="2018-05-25T09:52:30.361"/>
@@ -35,7 +62,7 @@
         <column name="ID" value="f63d0946-3960-43bb-9888-4c36d962f955"/>
         <column name="NAME" value="_____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046"/>
         <column name="PROPKEY" value="lastname"/>
-        <column name="PROPVAL" value="Administrator"/>
+        <column name="PROPVAL" value="Admin"/>
     </insert>
     <insert tableName="ASYS_USERS">
         <column name="DATE_EDIT" valueDate="2018-12-07T15:45:08.535"/>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/init.xml b/.liquibase/_____SYSTEMALIAS/basic/init/init.xml
index 4e94f2543871caa8a6c85f12715d0856d3f6a6e2..d29b9203a5b0089545e87bd7641479f7fa4003e9 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/init.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/init.xml
@@ -1,18 +1,18 @@
 <?xml version="1.1" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
-    <include file="struct/create_asys_aliasconfig.xml"/>
-    <include file="struct/create_asys_binaries.xml"/>
-    <include file="struct/create_asys_dashletconfigurations.xml"/>
-    <include file="struct/create_asys_dashlets.xml"/>
-    <include file="struct/create_asys_notifications.xml"/>
-    <include file="struct/create_asys_sequences.xml"/>
-    <include file="struct/create_asys_system.xml"/>
-    <include file="struct/create_asys_timer.xml"/>
-    <include file="struct/create_asys_users.xml"/>
-    <include file="struct/create_asys_calendarbackend.xml"/>
-    <include file="struct/create_asys_calendarlink.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_aliasconfig.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_binaries.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_dashletconfigurations.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_dashlets.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_notifications.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_sequences.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_system.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_timer.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_users.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_calendarbackend.xml"/>
+    <include relativeToChangelogFile="true" file="struct/create_asys_calendarlink.xml"/>
     
-    <include file="data/insert_asys_aliasconfig.xml"/>
-    <include file="data/insert_asys_system.xml"/>
-    <include file="data/insert_asys_users-admin.xml"/>
+    <include relativeToChangelogFile="true" file="data/insert_asys_aliasconfig.xml"/>
+    <include relativeToChangelogFile="true" file="data/insert_asys_system.xml"/>
+    <include relativeToChangelogFile="true" file="data/insert_asys_users-admin.xml"/>
 </databaseChangeLog>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/struct/create_asys_notificationcontents.xml b/.liquibase/_____SYSTEMALIAS/basic/init/struct/create_asys_notificationcontents.xml
new file mode 100644
index 0000000000000000000000000000000000000000..83818826decb7b62e72d42f34875cb823311b982
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/struct/create_asys_notificationcontents.xml
@@ -0,0 +1,22 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+<changeSet author="a.schindlbeck" id="6b25f062-fb39-4230-9348-b67ec5ec45a1">
+    <createTable tableName="ASYS_NOTIFICATIONCONTENTS">
+        <column name="CONTENTID" type="CHAR(36)">
+            <constraints primaryKey="true" primaryKeyName="PK_ASYS_NOTIFICATIONCONTENTS_CONTENTID"/>
+        </column>
+        <column name="BACKPACK" type="CLOB"/>
+        <column name="CAPTION" type="VARCHAR(512)"/>
+        <column name="CREATIONDATE" type="BIGINT"/>
+        <column name="DESCRIPTION" type="VARCHAR(1023)"/>
+        <column name="FORCEDPRIORITY" type="INTEGER"/>
+        <column name="ICON_INFO" type="VARCHAR(1023)"/>
+        <column name="LIFETIME" type="BIGINT"/>
+        <column name="LINK_INFO" type="VARCHAR(1023)"/>
+        <column name="ORIGINATORNAME" type="VARCHAR(63)"/>
+        <column name="RECIPIENTUSERIDS" type="CLOB"/>
+        <column name="TYPECODE" type="VARCHAR(63)"/>
+        <column name="VERSION" type="INTEGER"/>
+    </createTable>
+</changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/init/system_aliasTestdata.xml b/.liquibase/_____SYSTEMALIAS/basic/init/system_aliasTestdata.xml
index 12e4b957ade3bd0f87acb1decb681cb98398f0df..9471a52c15d6bcf528b3d86b509fba763553a793 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/init/system_aliasTestdata.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/init/system_aliasTestdata.xml
@@ -1,13 +1,13 @@
 <?xml version="1.1" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">   
-    <include file="data/example_asys_users/Birgit_Leicht.xml"/>
-    <include file="data/example_asys_binaries/Birgit_Leicht_Image.xml"/>
-    <include file="data/example_asys_users/Harold_Smith.xml"/>
-    <include file="data/example_asys_binaries/Harold_Smith_Image.xml"/>
-    <include file="data/example_asys_users/Herbert_Obermeier.xml"/>
-    <include file="data/example_asys_binaries/Herbert_Obermeier_Image.xml"/>
-    <include file="data/example_asys_users/Lisa_Sommer.xml"/>
-    <include file="data/example_asys_binaries/Lisa_Sommer_Image.xml"/>
-    <include file="data/example_asys_users/Susanne_Lustig.xml"/>
-    <include file="data/example_asys_binaries/Susanne_Lustig_Image.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_users/Birgit_Leicht.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_binaries/Birgit_Leicht_Image.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_users/Harold_Smith.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_binaries/Harold_Smith_Image.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_users/Herbert_Obermeier.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_binaries/Herbert_Obermeier_Image.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_users/Lisa_Sommer.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_binaries/Lisa_Sommer_Image.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_users/Susanne_Lustig.xml"/>
+    <include relativeToChangelogFile="true" file="data/example_asys_binaries/Susanne_Lustig_Image.xml"/>
 </databaseChangeLog>
diff --git a/.liquibase/_____SYSTEMALIAS/changelog.xml b/.liquibase/_____SYSTEMALIAS/changelog.xml
index 5fea0f98a129af771181ebddc56030c59aa75c10..0754d5e05adc7a470dd86c988b58939825717e3d 100644
--- a/.liquibase/_____SYSTEMALIAS/changelog.xml
+++ b/.liquibase/_____SYSTEMALIAS/changelog.xml
@@ -1,4 +1,5 @@
 <?xml version="1.1" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
     <include file="basic/init/init.xml"/>
+    <include file="basic/2019.2/changelog.xml"/>
 </databaseChangeLog>
diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod
index 72714b6c2dca0c5a437bf28d1f98a763f09a8d23..14f45d9f626d05e233415b8babf14b5b9cf5de08 100644
--- a/aliasDefinition/Data_alias/Data_alias.aod
+++ b/aliasDefinition/Data_alias/Data_alias.aod
@@ -3346,20 +3346,6 @@
                 <title></title>
                 <description></description>
               </entityFieldDb>
-              <entityFieldDb>
-                <name>CREATOR</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="12" />
-                <size v="50" />
-                <scale v="0" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
               <entityFieldDb>
                 <name>PARENT_CONTEXT</name>
                 <dbName></dbName>
@@ -3444,6 +3430,20 @@
                 <title></title>
                 <description></description>
               </entityFieldDb>
+              <entityFieldDb>
+                <name>RESPONSIBLE</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="50" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
             </entityFields>
           </entityDb>
           <entityDb>
@@ -4426,20 +4426,6 @@
                 <title></title>
                 <description></description>
               </entityFieldDb>
-              <entityFieldDb>
-                <name>ATTRIBUTE_LEVEL</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="4" />
-                <size v="10" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
               <entityFieldDb>
                 <name>KEYWORD_CONTAINER</name>
                 <dbName></dbName>
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/organisation/query.js b/aliasDefinition/Data_alias/indexsearchgroups/organisation/query.js
index 791c356592a9b881be9e598b9a5ba50cd7c86bab..f05cf8b21c1fffd80488dc3e08a7c1230fabf526 100644
--- a/aliasDefinition/Data_alias/indexsearchgroups/organisation/query.js
+++ b/aliasDefinition/Data_alias/indexsearchgroups/organisation/query.js
@@ -19,8 +19,8 @@ sqlQuery = "select CONTACT.CONTACTID "
     + "," + sqlHelper.concat([
          sqlHelper.concat(["defaultAddress.ADDRESS", "defaultAddress.BUILDINGNO", "'-'"
             ,"defaultAddress.COUNTRY", "defaultAddress.ZIP", "defaultAddress.CITY"])
-        ,sqlHelper.concat(["'" + translate.text("Phone") + ":'", CommUtil.getStandardSubSqlPhone("CONTACTID")])
-        ,sqlHelper.concat(["'" + translate.text("Email") + ":'", CommUtil.getStandardSubSqlMail("CONTACTID")])
+        ,sqlHelper.concat(["'" + translate.text("Phone") + ":'", "(" + CommUtil.getStandardSubSqlPhone() + ")"])
+        ,sqlHelper.concat(["'" + translate.text("Email") + ":'", "(" + CommUtil.getStandardSubSqlMail() + ")"])
         ], " | ") + " as DESCCOLUMN "
     //additional indexed fields
     + ",ORGANISATION.NAME, COMMUNICATION.ADDR "
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/person/query.js b/aliasDefinition/Data_alias/indexsearchgroups/person/query.js
index 44981a5fe2a7c0a2510485756b7d3ef523f743d2..e184e55bb1769daf4875b5019d526e381a0cec54 100644
--- a/aliasDefinition/Data_alias/indexsearchgroups/person/query.js
+++ b/aliasDefinition/Data_alias/indexsearchgroups/person/query.js
@@ -19,8 +19,8 @@ sqlQuery = "select CONTACT.CONTACTID "
     + "," + sqlHelper.concat([
          sqlHelper.concat(["defaultAddress.ADDRESS", "defaultAddress.BUILDINGNO", "'-'"
             ,"defaultAddress.COUNTRY", "defaultAddress.ZIP", "defaultAddress.CITY"])
-        ,sqlHelper.concat(["'" + translate.text("Phone") + ":'", CommUtil.getStandardSubSqlPhone("CONTACTID")])
-        ,sqlHelper.concat(["'" + translate.text("Email") + ":'", CommUtil.getStandardSubSqlMail("CONTACTID")])
+        ,sqlHelper.concat(["'" + translate.text("Phone") + ":'", "(" + CommUtil.getStandardSubSqlPhone() + ")"])
+        ,sqlHelper.concat(["'" + translate.text("Email") + ":'", "(" + CommUtil.getStandardSubSqlMail() + ")"])
         ], " | ") + " as DESCCOLUMN "
     //additional indexed fields
     + ",ORGANISATION.NAME, COMMUNICATION.ADDR "
diff --git a/entity/360Degree_entity/360Degree_entity.aod b/entity/360Degree_entity/360Degree_entity.aod
index 6a7428cd5b9bf1fb69c189f97952a8fbcdeeb0e7..a3c6eb0248f699e4c4038ba5e6e33328a2ef622f 100644
--- a/entity/360Degree_entity/360Degree_entity.aod
+++ b/entity/360Degree_entity/360Degree_entity.aod
@@ -14,6 +14,7 @@
     </entityField>
     <entityField>
       <name>TITLE</name>
+      <linkedContextProcess>%aditoprj%/entity/360Degree_entity/entityfields/title/linkedContextProcess.js</linkedContextProcess>
       <searchable v="false" />
     </entityField>
     <entityParameter>
diff --git a/entity/360Degree_entity/entityfields/title/linkedContextProcess.js b/entity/360Degree_entity/entityfields/title/linkedContextProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c493945bed68e5998cc4a2e8f2f18aa500683f72
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/title/linkedContextProcess.js
@@ -0,0 +1,3 @@
+import("system.vars");
+import("system.result");
+result.string(vars.get("$field.TARGET_CONTEXT"));
\ No newline at end of file
diff --git a/entity/ActivityLink_entity/ActivityLink_entity.aod b/entity/ActivityLink_entity/ActivityLink_entity.aod
index 312eb108037270268629d5641532f061c3d07e27..00d2c837e4ba4cdbb7253c1baa75966e9cc111ef 100644
--- a/entity/ActivityLink_entity/ActivityLink_entity.aod
+++ b/entity/ActivityLink_entity/ActivityLink_entity.aod
@@ -16,6 +16,7 @@
       <name>OBJECT_TYPE</name>
       <title>{$OBJECTLINK_TYPE}</title>
       <consumer>Context</consumer>
+      <mandatory v="true" />
       <displayValueProcess>%aditoprj%/entity/ActivityLink_entity/entityfields/object_type/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
@@ -23,6 +24,7 @@
       <title>{$OBJECTLINK_OBJECT}</title>
       <consumer>Objects</consumer>
       <linkedContextProcess>%aditoprj%/entity/ActivityLink_entity/entityfields/object_rowid/linkedContextProcess.js</linkedContextProcess>
+      <mandatory v="true" />
       <displayValueProcess>%aditoprj%/entity/ActivityLink_entity/entityfields/object_rowid/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
diff --git a/entity/Activity_entity/Activity_entity.aod b/entity/Activity_entity/Activity_entity.aod
index cd65065c38663b5ab510ec227d4807fbf1260f4d..8b3af6c8559617e7842a27bf0e3dc875726432e4 100644
--- a/entity/Activity_entity/Activity_entity.aod
+++ b/entity/Activity_entity/Activity_entity.aod
@@ -118,6 +118,7 @@
       <name>MainDocuments</name>
       <title>Maindocuments</title>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Activity_entity/entityfields/maindocuments/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Document_entity</entityName>
@@ -260,13 +261,13 @@
       </children>
     </entityProvider>
     <entityField>
-      <name>CREATOR</name>
-      <title>Creator</title>
+      <name>RESPONSIBLE</name>
+      <title>Responsible</title>
       <consumer>Employees</consumer>
       <linkedContext>Person</linkedContext>
       <searchable v="false" />
-      <valueProcess>%aditoprj%/entity/Activity_entity/entityfields/creator/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Activity_entity/entityfields/creator/displayValueProcess.js</displayValueProcess>
+      <valueProcess>%aditoprj%/entity/Activity_entity/entityfields/responsible/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Activity_entity/entityfields/responsible/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityConsumer>
       <name>ModuleTrees</name>
@@ -478,10 +479,6 @@
           <name>DIRECTION.displayValue</name>
           <expression>%aditoprj%/entity/Activity_entity/recordcontainers/db/recordfieldmappings/direction.displayvalue/expression.js</expression>
         </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CREATOR.value</name>
-          <recordfield>ACTIVITY.CREATOR</recordfield>
-        </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>PARENT_CONTEXT.value</name>
           <recordfield>ACTIVITY.PARENT_CONTEXT</recordfield>
@@ -494,10 +491,6 @@
           <name>CATEGORY.displayValue</name>
           <expression>%aditoprj%/entity/Activity_entity/recordcontainers/db/recordfieldmappings/category.displayvalue/expression.js</expression>
         </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>CREATOR.displayValue</name>
-          <expression>%aditoprj%/entity/Activity_entity/recordcontainers/db/recordfieldmappings/creator.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>USER_NEW.value</name>
           <recordfield>ACTIVITY.USER_NEW</recordfield>
@@ -514,6 +507,14 @@
           <name>DATE_EDIT.value</name>
           <recordfield>ACTIVITY.DATE_EDIT</recordfield>
         </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>RESPONSIBLE.displayValue</name>
+          <expression>%aditoprj%/entity/Activity_entity/recordcontainers/db/recordfieldmappings/responsible.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>RESPONSIBLE.value</name>
+          <recordfield>ACTIVITY.RESPONSIBLE</recordfield>
+        </dbRecordFieldMapping>
       </recordFieldMappings>
     </dbRecordContainer>
   </recordContainers>
diff --git a/entity/Activity_entity/entityfields/maindocuments/stateProcess.js b/entity/Activity_entity/entityfields/maindocuments/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb349d978f74911958575fd56fcf2cce34dee071
--- /dev/null
+++ b/entity/Activity_entity/entityfields/maindocuments/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.result");
+import("system.db");
+import("system.vars");
+import("system.neon");
+import("Sql_lib");
+
+if (0 == db.getBinaryCount("ACTIVITY", "DOCUMENT", vars.get("$sys.uid"), SqlUtils.getSystemAlias(), "MAINDOCUMENT"))
+{
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/Activity_entity/entityfields/creator/displayValueProcess.js b/entity/Activity_entity/entityfields/responsible/displayValueProcess.js
similarity index 100%
rename from entity/Activity_entity/entityfields/creator/displayValueProcess.js
rename to entity/Activity_entity/entityfields/responsible/displayValueProcess.js
diff --git a/entity/Activity_entity/entityfields/creator/valueProcess.js b/entity/Activity_entity/entityfields/responsible/valueProcess.js
similarity index 100%
rename from entity/Activity_entity/entityfields/creator/valueProcess.js
rename to entity/Activity_entity/entityfields/responsible/valueProcess.js
diff --git a/entity/Activity_entity/recordcontainers/db/conditionProcess.js b/entity/Activity_entity/recordcontainers/db/conditionProcess.js
index c772668cbde4f80831fa000cd266d7e6d8cc97af..9e14d0b2ef2ed8f4ad75bbee6884c2d96c9bcd92 100644
--- a/entity/Activity_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Activity_entity/recordcontainers/db/conditionProcess.js
@@ -23,7 +23,7 @@ if (vars.exists("$param.RowId_param") && vars.get("$param.RowId_param") && vars.
 }
     
 if(vars.exists("$param.OnlyInnate_param") && vars.get("$param.OnlyInnate_param")) {    
-    cond.andPrepare("ACTIVITY.CREATOR", vars.get("$sys.user"));
+    cond.andPrepare("ACTIVITY.RESPONSIBLE", vars.get("$sys.user"));
 }
 
 //TODO: use a preparedCondition when available #1030812 #1034026
diff --git a/entity/Activity_entity/recordcontainers/db/recordfieldmappings/creator.displayvalue/expression.js b/entity/Activity_entity/recordcontainers/db/recordfieldmappings/creator.displayvalue/expression.js
deleted file mode 100644
index 411a003b91936f9c3e8681311ff40e1f1e010ad6..0000000000000000000000000000000000000000
--- a/entity/Activity_entity/recordcontainers/db/recordfieldmappings/creator.displayvalue/expression.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.result");
-import("Person_lib");
-
-result.string(PersUtils.getResolvingDisplaySubSql("CREATOR"))
\ No newline at end of file
diff --git a/entity/Activity_entity/recordcontainers/db/recordfieldmappings/responsible.displayvalue/expression.js b/entity/Activity_entity/recordcontainers/db/recordfieldmappings/responsible.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..fdec89201f8a11f9163187314f21c55ba7f15735
--- /dev/null
+++ b/entity/Activity_entity/recordcontainers/db/recordfieldmappings/responsible.displayvalue/expression.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Person_lib");
+
+result.string(PersUtils.getResolvingDisplaySubSql("RESPONSIBLE"))
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/AddressValidation_entity.aod b/entity/AddressValidation_entity/AddressValidation_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..0f243581fef1c1d06b617bce59b7ee8239e875ac
--- /dev/null
+++ b/entity/AddressValidation_entity/AddressValidation_entity.aod
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.1">
+  <name>AddressValidation_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <titleProcess>%aditoprj%/entity/AddressValidation_entity/titleProcess.js</titleProcess>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>UID</name>
+      <title>Address</title>
+      <description>UID consists of all fields as JSON. </description>
+    </entityField>
+    <entityProvider>
+      <name>ZipValidaton</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>1b2e3be5-b3be-42c5-a55f-b892fdfbf21f</name>
+          <entityName>Communication_entity</entityName>
+          <fieldName>AddressValidator</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>fcfcbebe-260a-4773-a874-9791b4887ae2</name>
+          <entityName>Address_entity</entityName>
+          <fieldName>ZipValidation</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/zipvalidaton/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>Type_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>Country_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>COUNTRY</name>
+      <title>Country</title>
+    </entityField>
+    <entityField>
+      <name>ZIP</name>
+      <title>Zip</title>
+    </entityField>
+    <entityField>
+      <name>CITY</name>
+      <title>City</title>
+    </entityField>
+    <entityField>
+      <name>DISTRICT</name>
+      <title>District</title>
+    </entityField>
+    <entityField>
+      <name>REGION</name>
+      <title>Region</title>
+    </entityField>
+    <entityField>
+      <name>STATE</name>
+      <title>State</title>
+    </entityField>
+    <entityField>
+      <name>VALUE</name>
+      <description>Final value returned</description>
+    </entityField>
+    <entityProvider>
+      <name>CityValidation</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>27114db7-8562-43b2-87d8-fa605bbf2319</name>
+          <entityName>Address_entity</entityName>
+          <fieldName>CityValidation</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/cityvalidation/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <contentProcess>%aditoprj%/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
+      <recordFields>
+        <element>UID.value</element>
+        <element>UID.displayValue</element>
+        <element>ZIP.value</element>
+        <element>CITY.value</element>
+        <element>COUNTRY.value</element>
+        <element>DISTRICT.value</element>
+        <element>REGION.value</element>
+        <element>STATE.value</element>
+        <element>VALUE.value</element>
+      </recordFields>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/AddressValidation_entity/entityfields/cityvalidation/children/type_param/valueProcess.js b/entity/AddressValidation_entity/entityfields/cityvalidation/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..605d65eb517e3f51c7d9a129c17c0d6e46b79452
--- /dev/null
+++ b/entity/AddressValidation_entity/entityfields/cityvalidation/children/type_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("AddressValidation_lib");
+import("system.result");
+
+result.string(AddressValidationType.get().TYPE_CITY.key);
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/entityfields/cityvalidatior/children/type_param/valueProcess.js b/entity/AddressValidation_entity/entityfields/cityvalidatior/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..605d65eb517e3f51c7d9a129c17c0d6e46b79452
--- /dev/null
+++ b/entity/AddressValidation_entity/entityfields/cityvalidatior/children/type_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("AddressValidation_lib");
+import("system.result");
+
+result.string(AddressValidationType.get().TYPE_CITY.key);
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/entityfields/validate/children/zip_param/valueProcess.js b/entity/AddressValidation_entity/entityfields/validate/children/zip_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..212bdd0b1df7e31a5b3c126f1d0b58926f924dda
--- /dev/null
+++ b/entity/AddressValidation_entity/entityfields/validate/children/zip_param/valueProcess.js
@@ -0,0 +1 @@
+result.object(tr)
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/entityfields/zipvalidaton/children/type_param/valueProcess.js b/entity/AddressValidation_entity/entityfields/zipvalidaton/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e980e6dd0b82b651a1025901c43d74fc6be1632d
--- /dev/null
+++ b/entity/AddressValidation_entity/entityfields/zipvalidaton/children/type_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("AddressValidation_lib");
+import("system.result");
+
+result.string(AddressValidationType.get().TYPE_ZIP.key);
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/entityfields/zipvalidator/children/type_param/valueProcess.js b/entity/AddressValidation_entity/entityfields/zipvalidator/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e980e6dd0b82b651a1025901c43d74fc6be1632d
--- /dev/null
+++ b/entity/AddressValidation_entity/entityfields/zipvalidator/children/type_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("AddressValidation_lib");
+import("system.result");
+
+result.string(AddressValidationType.get().TYPE_ZIP.key);
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js b/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b816f84362c53ed72404ba157b67b711b55c5283
--- /dev/null
+++ b/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
@@ -0,0 +1,22 @@
+import("system.result");
+import("AddressValidation_lib");
+import("system.vars");
+
+var type = "";
+if (vars.exists("$param.Type_param") && vars.get("$param.Type_param"))
+    type = vars.get("$param.Type_param");
+
+var country = "";
+if (vars.exists("$param.Country_param") && vars.get("$param.Country_param"))
+    country = vars.get("$param.Country_param");
+
+// get the value typed by the user
+var filter = "";
+var sysFilter = vars.get("$sys.filter");
+if(sysFilter.filter != null) {
+    filter = JSON.parse(sysFilter.filter).childs[0].value;
+}
+
+var foundAddresses = AddressValidationUtils.validate(filter, type, country);
+
+result.object(foundAddresses);
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/titleProcess.js b/entity/AddressValidation_entity/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..137427fc9c938b9d7ad105818377943e2c1a8e0a
--- /dev/null
+++ b/entity/AddressValidation_entity/titleProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.VALUE"));
\ No newline at end of file
diff --git a/entity/Address_entity/Address_entity.aod b/entity/Address_entity/Address_entity.aod
index df8385fa8fbe6b6e32f925fcf2bba765e0d03d3d..cf8f5b77c530176b0dcb06a5db6f52259dab8ddd 100644
--- a/entity/Address_entity/Address_entity.aod
+++ b/entity/Address_entity/Address_entity.aod
@@ -37,7 +37,13 @@
     <entityField>
       <name>CITY</name>
       <title>City</title>
+      <consumer>CityValidation</consumer>
       <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/city/mandatoryProcess.js</mandatoryProcess>
+      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/city/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/city/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
     </entityField>
     <entityField>
       <name>COUNTRY</name>
@@ -68,8 +74,14 @@
     <entityField>
       <name>ZIP</name>
       <title>postcode</title>
+      <consumer>ZipValidation</consumer>
       <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/zip/mandatoryProcess.js</mandatoryProcess>
+      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/zip/displayValueProcess.js</displayValueProcess>
       <onValidation>%aditoprj%/entity/Address_entity/entityfields/zip/onValidation.js</onValidation>
+      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/zip/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
     </entityField>
     <entityProvider>
       <name>OrganisationAddresses</name>
@@ -288,6 +300,30 @@
       <contentTypeProcess>%aditoprj%/entity/Address_entity/entityfields/is_standard_icon/contentTypeProcess.js</contentTypeProcess>
       <valueProcess>%aditoprj%/entity/Address_entity/entityfields/is_standard_icon/valueProcess.js</valueProcess>
     </entityField>
+    <entityConsumer>
+      <name>ZipValidation</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AddressValidation_entity</entityName>
+        <fieldName>ZipValidaton</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>Country_param</name>
+          <valueProcess>%aditoprj%/entity/Address_entity/entityfields/zipvalidation/children/country_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityConsumer>
+      <name>CityValidation</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AddressValidation_entity</entityName>
+        <fieldName>CityValidation</fieldName>
+      </dependency>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Address_entity/entityfields/city/displayValueProcess.js b/entity/Address_entity/entityfields/city/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..de2c5e835eaf4fe6dd8b3521b3e17a39c9ac23c1
--- /dev/null
+++ b/entity/Address_entity/entityfields/city/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+
+// needed for instant display name change if value set by neon.setFieldValue
+result.string(vars.get("$this.value"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/city/onValueChange.js b/entity/Address_entity/entityfields/city/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..29bde9d486834bcd1fcd747d5ded932d2fe60196
--- /dev/null
+++ b/entity/Address_entity/entityfields/city/onValueChange.js
@@ -0,0 +1,3 @@
+import("AddressValidation_lib");
+
+AddressValidationUtils.setFields();
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/displayValueProcess.js b/entity/Address_entity/entityfields/zip/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..de2c5e835eaf4fe6dd8b3521b3e17a39c9ac23c1
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+
+// needed for instant display name change if value set by neon.setFieldValue
+result.string(vars.get("$this.value"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zip/onValueChange.js b/entity/Address_entity/entityfields/zip/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..29bde9d486834bcd1fcd747d5ded932d2fe60196
--- /dev/null
+++ b/entity/Address_entity/entityfields/zip/onValueChange.js
@@ -0,0 +1,3 @@
+import("AddressValidation_lib");
+
+AddressValidationUtils.setFields();
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zipvalidation/children/country_param/valueProcess.js b/entity/Address_entity/entityfields/zipvalidation/children/country_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..bece889b8e3ca6d6141ac5a750d0d068b23dc85a
--- /dev/null
+++ b/entity/Address_entity/entityfields/zipvalidation/children/country_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("system.vars");
+
+result.string(vars.get("$field.COUNTRY"))
\ No newline at end of file
diff --git a/entity/Analyses_entity/Analyses_entity.aod b/entity/Analyses_entity/Analyses_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..5aeae376f2304ddae22c44736a846177419ffc5b
--- /dev/null
+++ b/entity/Analyses_entity/Analyses_entity.aod
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.1">
+  <name>Analyses_entity</name>
+  <title>Analyses</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <icon>VAADIN:GRID_BIG_O</icon>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>NEW_TASKS</name>
+      <title>New tasks</title>
+      <contentType>NUMBER</contentType>
+      <valueProcess>%aditoprj%/entity/Analyses_entity/entityfields/new_tasks/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>OVERDUE_TASKS</name>
+      <title>Overdue tasks</title>
+      <contentType>NUMBER</contentType>
+      <valueProcess>%aditoprj%/entity/Analyses_entity/entityfields/overdue_tasks/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>IMMINENT_APPOINTMENTS</name>
+      <title>Imminent appointments for today</title>
+      <contentType>NUMBER</contentType>
+      <valueProcess>%aditoprj%/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js</valueProcess>
+    </entityField>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js b/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..47a1fc47f439997182d48840a09062d6777baad9
--- /dev/null
+++ b/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js
@@ -0,0 +1,55 @@
+import("system.SQLTYPES");
+import("system.logging");
+import("system.db");
+import("system.datetime");
+import("system.result");
+import("system.vars");
+import("Date_lib");
+import("Sql_lib");
+import("system.calendars");
+import("Calendar_lib");
+
+var pFilter =  reset_filterEvent();
+var conditions = [];
+var conditioncount = 0;
+var user = undefined;
+var stati = [];
+var entries = [];
+
+var startnumber = Number(vars.get("$sys.date"));
+var endnumber = startnumber + 43200000 ;
+
+var start = startnumber + "";
+var end = endnumber + "";
+
+if ( pFilter.tentative == "true" )    
+    stati.push(calendars.STATUS_TENTATIVE);
+
+if ( pFilter.cancelled == "true" )    
+    stati.push(calendars.STATUS_CANCELLED);
+
+if ( pFilter.confirmed == "true" )
+    stati.push(mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
+
+if (getCalendarSystemType(calendars.VEVENT) == calendars.BACKEND_EXCHANGEWS && pFilter.free == "true")
+    stati.push(calendars.STATUS_FREE);
+
+if ( pFilter.user != "" )	
+    user = (pFilter.user).trim();
+
+for ( var z = 0; z < stati.length; z++ )
+    _addEntryCondition(conditions, ++conditioncount,
+    {
+        TYPE: calendars.VEVENT,
+        START: start,
+        END: end,
+        USER: user,
+        STATUS: stati[z]
+    });
+
+conditions["COUNT"] = String(conditioncount);
+entries = calendars.getEntries(conditions);
+
+logging.log("entries: " + entries.toSource());
+
+result.string(entries.length);
\ No newline at end of file
diff --git a/entity/Analyses_entity/entityfields/new_tasks/valueProcess.js b/entity/Analyses_entity/entityfields/new_tasks/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..497dffdbfa7ef331b91e5568df2ac738bc09477c
--- /dev/null
+++ b/entity/Analyses_entity/entityfields/new_tasks/valueProcess.js
@@ -0,0 +1,11 @@
+import("system.datetime");
+import("system.db");
+import("system.result");
+import("system.vars");
+import("Date_lib");
+import("Sql_lib");
+import("system.SQLTYPES")
+
+var opentask = db.cell("select count(STATUS) from TASK join AB_KEYWORD_ENTRY on KEYID = STATUS and CONTAINER  = 'TaskStatus' and TITLE = 'new' group by KEYID, AB_KEYWORD_ENTRY.TITLE");                             
+                                  
+result.string(opentask);
\ No newline at end of file
diff --git a/entity/Analyses_entity/entityfields/overdue_tasks/valueProcess.js b/entity/Analyses_entity/entityfields/overdue_tasks/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..9708434347425c22451c1cf149c8e22e2c6034d2
--- /dev/null
+++ b/entity/Analyses_entity/entityfields/overdue_tasks/valueProcess.js
@@ -0,0 +1,15 @@
+import("system.db");
+import("system.datetime");
+import("system.result");
+import("system.vars");
+import("Date_lib");
+import("Sql_lib");
+
+
+var overduetask = db.cell(SqlCondition.begin()
+                                   .andPrepare("TASK.MATURITY_DATE", vars.get("$sys.date"), "# < ?")
+                                   .buildSql("select count(TASKID) from TASK", "1=2"));
+                                                                  
+result.string(overduetask);
+
+
diff --git a/entity/Appointment_entity/entityfields/summary/valueProcess.js b/entity/Appointment_entity/entityfields/summary/valueProcess.js
index 8fd3d347cac2df60651d46bdab6fb9caffbd7ca6..c42150fdff40e956026f65addcdcadc10049df0b 100644
--- a/entity/Appointment_entity/entityfields/summary/valueProcess.js
+++ b/entity/Appointment_entity/entityfields/summary/valueProcess.js
@@ -9,8 +9,6 @@ import("system.result");
  */
 if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.Entry_param"))
 {
-    logging.log()
-    
     var event = JSON.parse(vars.getString("$param.Entry_param"));
 
     if(event[calendars.SUMMARY])
diff --git a/entity/AttributeRelationTree_entity/AttributeRelationTree_entity.aod b/entity/AttributeRelationTree_entity/AttributeRelationTree_entity.aod
index bb483a46acd306a1096488ef3a58288d6e768fd0..1ebda72befd7012f439e2e203fba8ac236578ebe 100644
--- a/entity/AttributeRelationTree_entity/AttributeRelationTree_entity.aod
+++ b/entity/AttributeRelationTree_entity/AttributeRelationTree_entity.aod
@@ -10,9 +10,6 @@
     <entityField>
       <name>PARENT_ID</name>
     </entityField>
-    <entityField>
-      <name>TITLE</name>
-    </entityField>
     <entityField>
       <name>UID</name>
     </entityField>
@@ -74,16 +71,54 @@
         </entityDependency>
       </dependencies>
     </entityProvider>
+    <entityField>
+      <name>AB_ATTRIBUTE_ID</name>
+      <title>Attribute</title>
+      <consumer>SpecificAttribute</consumer>
+      <onValueChange>%aditoprj%/entity/AttributeRelationTree_entity/entityfields/ab_attribute_id/onValueChange.js</onValueChange>
+    </entityField>
+    <entityField>
+      <name>VALUE</name>
+      <title>Value</title>
+      <contentTypeProcess>%aditoprj%/entity/AttributeRelationTree_entity/entityfields/value/contentTypeProcess.js</contentTypeProcess>
+      <resolution>DAY</resolution>
+      <mandatoryProcess>%aditoprj%/entity/AttributeRelationTree_entity/entityfields/value/mandatoryProcess.js</mandatoryProcess>
+      <possibleItemsProcess>%aditoprj%/entity/AttributeRelationTree_entity/entityfields/value/possibleItemsProcess.js</possibleItemsProcess>
+      <stateProcess>%aditoprj%/entity/AttributeRelationTree_entity/entityfields/value/stateProcess.js</stateProcess>
+    </entityField>
+    <entityConsumer>
+      <name>SpecificAttribute</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Attribute_entity</entityName>
+        <fieldName>SpecificAttribute</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <valueProcess>%aditoprj%/entity/AttributeRelationTree_entity/entityfields/specificattribute/children/objecttype_param/valueProcess.js</valueProcess>
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
       <name>jdito</name>
       <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
       <contentProcess>%aditoprj%/entity/AttributeRelationTree_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
+      <onInsert>%aditoprj%/entity/AttributeRelationTree_entity/recordcontainers/jdito/onInsert.js</onInsert>
+      <onUpdate>%aditoprj%/entity/AttributeRelationTree_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
+      <onDelete>%aditoprj%/entity/AttributeRelationTree_entity/recordcontainers/jdito/onDelete.js</onDelete>
       <recordFields>
         <element>UID.value</element>
         <element>PARENT_ID.value</element>
-        <element>TITLE.value</element>
+        <element>VALUE.value</element>
+        <element>VALUE.displayValue</element>
+        <element>AB_ATTRIBUTE_ID.value</element>
+        <element>AB_ATTRIBUTE_ID.displayValue</element>
+        <element>ATTRIBUTE_TYPE.value</element>
       </recordFields>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/AttributeRelationTree_entity/entityfields/ab_attribute_id/onValueChange.js b/entity/AttributeRelationTree_entity/entityfields/ab_attribute_id/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..1cebe1b3feaf01b51d151221f833a7255541bfb5
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/entityfields/ab_attribute_id/onValueChange.js
@@ -0,0 +1,8 @@
+import("system.vars");
+import("system.neon");
+
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT || 
+    vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) 
+{
+    neon.setFieldValue("$field.VALUE", null);
+}
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/entityfields/specificattribute/children/objecttype_param/valueProcess.js b/entity/AttributeRelationTree_entity/entityfields/specificattribute/children/objecttype_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c2ba1e99bd66da1cbc065319b7644302880879f
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/entityfields/specificattribute/children/objecttype_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.exists("$param.ObjectType_param") ? vars.get("$param.ObjectType_param") : "");
diff --git a/entity/AttributeRelationTree_entity/entityfields/value/contentTypeProcess.js b/entity/AttributeRelationTree_entity/entityfields/value/contentTypeProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e692170633914456e09edf154860eb0a1f6842ef
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/entityfields/value/contentTypeProcess.js
@@ -0,0 +1,6 @@
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+result.string(AttributeTypeUtil.getContentType(attributeType));
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/entityfields/value/mandatoryProcess.js b/entity/AttributeRelationTree_entity/entityfields/value/mandatoryProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..564b24d9e769f678a1da3de8776adf941e94217e
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/entityfields/value/mandatoryProcess.js
@@ -0,0 +1,6 @@
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+result.string(AttributeTypeUtil.getContentType(attributeType) != null);
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/entityfields/value/possibleItemsProcess.js b/entity/AttributeRelationTree_entity/entityfields/value/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..26adcbcda38f9326940557d75bb7e2197f3ac69e
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/entityfields/value/possibleItemsProcess.js
@@ -0,0 +1,47 @@
+import("system.translate");
+import("system.db");
+import("system.result");
+import("system.vars");
+import("Attribute_lib");
+import("Sql_lib");
+
+var attributeId = vars.get("$field.AB_ATTRIBUTE_ID");
+var attrType = AttributeUtil.getAttributeType(attributeId);
+
+if (attrType == $AttributeTypes.COMBO)
+{
+    var valueSql = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_ACTIVE", "1")
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", attributeId)
+        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE)
+        .buildSql("select AB_ATTRIBUTEID, ATTRIBUTE_NAME from AB_ATTRIBUTE", "1=2", "order by SORTING asc");
+    var valueList = db.table(valueSql);
+    
+    result.object(valueList);
+}
+else if (attrType == $AttributeTypes.BOOLEAN)
+{
+    result.object([
+        ["1", translate.text("Yes")],
+        ["0", translate.text("No")]
+    ]);
+}
+
+//TODO this is a workaround for keywords, when it's possible to use the consumer remove this
+else if (attrType == $AttributeTypes.KEYWORD)
+{
+    var attrKeywordSelect = "select KEYWORD_CONTAINER from AB_ATTRIBUTE";
+    attrKeywordSelect = SqlCondition.begin()
+        .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$field.AB_ATTRIBUTE_ID")
+        .buildSql(attrKeywordSelect);
+    
+    var sql = SqlCondition.begin()
+        .andPrepare("AB_KEYWORD_ENTRY.CONTAINER", db.cell(attrKeywordSelect))
+        .buildSql("select AB_KEYWORD_ENTRY.KEYID, AB_KEYWORD_ENTRY.TITLE from AB_KEYWORD_ENTRY", "1=2", "order by SORTING asc");
+    var keywords = db.table(sql).map(function (row)
+    {
+        return [row[0], translate.text(row[1])];
+    });
+    
+    result.object(keywords);
+}
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/entityfields/value/stateProcess.js b/entity/AttributeRelationTree_entity/entityfields/value/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7eb783c7dfa26f85106d4836ba568ea05641bc6b
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/entityfields/value/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+result.string(AttributeTypeUtil.getContentType(attributeType));
+var fieldState;
+if (AttributeTypeUtil.getContentType(attributeType) != null)
+    fieldState = neon.COMPONENTSTATE_EDITABLE;
+else
+    fieldState = neon.COMPONENTSTATE_READONLY;
+
+result.string(fieldState);
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/recordcontainers/jdito/contentProcess.js b/entity/AttributeRelationTree_entity/recordcontainers/jdito/contentProcess.js
index e6b4f8a5171e30c73818b120f6f4de53eabef89f..fb2ce69024eef40394e9b3155c30bfffb8ed46e5 100644
--- a/entity/AttributeRelationTree_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/AttributeRelationTree_entity/recordcontainers/jdito/contentProcess.js
@@ -1,44 +1,102 @@
-import("system.vars");
-import("system.result");
-import("system.db");
-import("Attribute_lib");
-import("Sql_lib");
-
-var objectType = vars.get("$param.ObjectType_param");
-var rowId = vars.get("$param.ObjectRowId_param");
-var attributeObj = {};
-var allAttributes = [];
-var sqlSelect = "select AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, ATTRIBUTE_NAME, ATTRIBUTE_LEVEL from AB_ATTRIBUTE";
-
-var attributeValues = AttributeRelationUtils.getAllAttributes(rowId, objectType, false, true);
-
-_fetchAttributes(attributeValues.map(function (row) {return row[1]}));
-
-allAttributes = allAttributes
-    .sort(function (a, b) {return a[3] - b[3];}) //sort by level to make sure parents are added first
-    .map(function (row) {return [row[0], row[1], row[2]];}) //remove level from array
-    .concat(attributeValues);
-result.object(allAttributes);
-
-function _fetchAttributes (pAttributeIds)
-{
-    var condition = SqlCondition.begin();
-    var nextIds = [];
-    pAttributeIds.forEach(function (id)
-    {
-        if (!(id in this))
-            condition.orPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", id);
-    }, attributeObj);
-    db.table(condition.buildSql(sqlSelect, "1=2"))
-        .forEach(function (row)
-            {
-                this[row[0]] = true;
-                if (row[1])
-                    nextIds.push(row[1]);
-                else
-                    row[1] = null;
-                allAttributes.push(row);
-            }, attributeObj);
-    if (nextIds.length)
-        _fetchAttributes(nextIds);
+import("system.vars");
+import("system.result");
+import("system.db");
+import("Attribute_lib");
+import("Sql_lib");
+
+var objectType = vars.get("$param.ObjectType_param");
+var rowId = vars.get("$param.ObjectRowId_param");
+var attributeObj = {};
+var allAttributes = [];
+var sqlSelect = "select AB_ATTRIBUTEID, ATTRIBUTE_PARENT_ID, '', '', AB_ATTRIBUTEID, ATTRIBUTE_NAME, ATTRIBUTE_TYPE from AB_ATTRIBUTE";
+
+var attrCond = SqlCondition.begin()
+    .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", rowId);
+if (objectType != null)
+    attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", objectType);
+
+var defaultFields = [
+    "AB_ATTRIBUTERELATIONID",
+    "AB_ATTRIBUTE.AB_ATTRIBUTEID", 
+    "AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", 
+    "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
+    "AB_ATTRIBUTE.ATTRIBUTE_NAME", 
+    "AB_ATTRIBUTE.KEYWORD_CONTAINER", 
+    "COMBOVAL.ATTRIBUTE_NAME"
+];
+var valueFields = AttributeTypeUtil.getAllDatabaseFields();
+var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
+    + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
+    + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
+
+var attributeNameMap = {};
+var attributeValues = db.table(attributeSql).map(function (row) 
+{
+    let attributeId = row[1];
+    let attributeName = row[4];
+    let value = row[AttributeTypeUtil.getTypeColumnIndex(row[3]) + defaultFields.length];
+    let viewValue;
+    if (row[3].trim() == $AttributeTypes.COMBO)
+        viewValue = row[6];
+    else
+        viewValue = AttributeTypeUtil.getAttributeViewValue(row[3].trim(), value, row[5]);
+
+    return [row[0], row[2], value, viewValue, attributeId, attributeName, row[3]];
+});
+
+
+_fetchAttributes(attributeValues.map(function (row) {return row[1]}));
+
+allAttributes = _sortArrayForTree(allAttributes).concat(attributeValues);
+result.object(allAttributes);
+
+function _fetchAttributes (pAttributeIds)
+{
+    var condition = SqlCondition.begin();
+    var nextIds = [];
+    pAttributeIds.forEach(function (id)
+    {
+        if (!(id in this))
+            condition.orPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", id);
+    }, attributeObj);
+    db.table(condition.buildSql(sqlSelect, "1=2"))
+        .forEach(function (row)
+            {
+                this[row[0]] = true;
+                if (row[1])
+                    nextIds.push(row[1]);
+                else
+                    row[1] = null;
+                allAttributes.push(row);
+            }, attributeObj);
+    if (nextIds.length)
+        _fetchAttributes(nextIds);
+}
+
+function _sortArrayForTree (pArray) 
+{
+    var rows = {};
+    var allIds = {};
+    var idIndex = 0;
+    var parentIdIndex = 1;
+    
+    pArray.forEach(function (row) {allIds[row[idIndex]] = true;});
+    var index = 0;
+    
+    for (let itemsAdded = true; itemsAdded; itemsAdded = oldIndex != index)
+    {
+        var oldIndex = index;
+        pArray.forEach(function (row)
+        {
+            if (!(row[idIndex] in this) && (row[parentIdIndex] in this || !allIds[row[parentIdIndex]]))
+                this[row[idIndex]] = {
+                    data : row,
+                    index : index++
+                };
+        }, rows);
+    }
+    var sortedArray = new Array(index);
+    for (let i in rows)
+        sortedArray[rows[i].index] = rows[i].data;
+    return sortedArray;
 }
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/recordcontainers/jdito/onDelete.js b/entity/AttributeRelationTree_entity/recordcontainers/jdito/onDelete.js
new file mode 100644
index 0000000000000000000000000000000000000000..219317e107752606f09b507bbdd68e17a018af4c
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/recordcontainers/jdito/onDelete.js
@@ -0,0 +1,10 @@
+import("system.neon");
+import("system.vars");
+import("Sql_lib");
+import("system.db");
+
+if (vars.get("$field.AB_ATTRIBUTE_ID"))
+{
+    db.deleteData("AB_ATTRIBUTERELATION", SqlCondition.begin().andPrepareVars("AB_ATTRIBUTERELATION.AB_ATTRIBUTERELATIONID", "$field.UID").build("1=2"));
+    neon.refresh();
+}
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/recordcontainers/jdito/onInsert.js b/entity/AttributeRelationTree_entity/recordcontainers/jdito/onInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba344ff704777c942370bfbe0731b2a80e69660a
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/recordcontainers/jdito/onInsert.js
@@ -0,0 +1,31 @@
+import("system.datetime");
+import("system.util");
+import("system.db");
+import("system.vars");
+import("Attribute_lib");
+
+var type = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+var valueField = AttributeTypeUtil.getDatabaseField(type);
+
+if (valueField)
+{
+    var columns = [
+        "AB_ATTRIBUTERELATIONID",
+        "AB_ATTRIBUTE_ID",
+        "OBJECT_ROWID",
+        "OBJECT_TYPE",
+        "DATE_NEW",
+        "USER_NEW",
+        valueField
+    ];
+    var values = [
+        util.getNewUUID(),
+        vars.get("$field.AB_ATTRIBUTE_ID"),
+        vars.get("$param.ObjectRowId_param"),
+        vars.get("$param.ObjectType_param"),
+        String(datetime.date()),
+        vars.get("$sys.user"),
+        vars.get("$field.VALUE")
+    ];
+    db.insertData("AB_ATTRIBUTERELATION", columns, null, values);
+}
\ No newline at end of file
diff --git a/entity/AttributeRelationTree_entity/recordcontainers/jdito/onUpdate.js b/entity/AttributeRelationTree_entity/recordcontainers/jdito/onUpdate.js
new file mode 100644
index 0000000000000000000000000000000000000000..ffe8298ae35f313e717bb0895c2ca41e3a84141e
--- /dev/null
+++ b/entity/AttributeRelationTree_entity/recordcontainers/jdito/onUpdate.js
@@ -0,0 +1,25 @@
+import("Sql_lib");
+import("system.util");
+import("system.db");
+import("system.vars");
+import("Attribute_lib");
+
+var type = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+
+var columns = [
+    "AB_ATTRIBUTE_ID"
+];
+var values = [
+    vars.get("$field.AB_ATTRIBUTE_ID")
+];
+
+var dbFields = AttributeTypeUtil.getAllDatabaseFields();
+dbFields.forEach(function (row)
+{
+    columns.push(row);
+    values.push("");
+});
+values[AttributeTypeUtil.getTypeColumnIndex(type) + 1] = vars.get("$field.VALUE");
+
+db.updateData("AB_ATTRIBUTERELATION", columns, null, values, 
+    SqlCondition.begin().andPrepareVars("AB_ATTRIBUTERELATION.AB_ATTRIBUTERELATIONID", "$field.UID"));
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/AttributeRelation_entity.aod b/entity/AttributeRelation_entity/AttributeRelation_entity.aod
index d06a6101b3c5dd8a0a0c2582f4333610b8a91cb5..d9b79a7996e09b8459e2264a8222f4edb8793495 100644
--- a/entity/AttributeRelation_entity/AttributeRelation_entity.aod
+++ b/entity/AttributeRelation_entity/AttributeRelation_entity.aod
@@ -4,7 +4,6 @@
   <title>Attribute Relation</title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/AttributeRelation_entity/documentation.adoc</documentation>
-  <afterOperatingState>%aditoprj%/entity/AttributeRelation_entity/afterOperatingState.js</afterOperatingState>
   <recordContainer>db</recordContainer>
   <entityFields>
     <entityProvider>
@@ -41,8 +40,10 @@
       <title>Value</title>
       <contentTypeProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js</contentTypeProcess>
       <resolution>DAY</resolution>
-      <mandatory v="true" />
+      <mandatory v="false" />
+      <mandatoryProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/mandatoryProcess.js</mandatoryProcess>
       <possibleItemsProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/possibleItemsProcess.js</possibleItemsProcess>
+      <stateProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/displayValueProcess.js</displayValueProcess>
       <onValueChange>%aditoprj%/entity/AttributeRelation_entity/entityfields/valueproxy/onValueChange.js</onValueChange>
diff --git a/entity/AttributeRelation_entity/afterOperatingState.js b/entity/AttributeRelation_entity/afterOperatingState.js
deleted file mode 100644
index d3061e715463d1b8fb004c30a3750ff6b0a2d4a6..0000000000000000000000000000000000000000
--- a/entity/AttributeRelation_entity/afterOperatingState.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("system.neon");
-
-if (vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_VIEW) 
-    neon.refresh();
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js b/entity/AttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js
index 1e7cfe8ada6f58bd12a58cf076c0a887ceee54f7..e692170633914456e09edf154860eb0a1f6842ef 100644
--- a/entity/AttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/contentTypeProcess.js
@@ -1,6 +1,6 @@
-import("system.vars");
-import("system.result");
-import("Attribute_lib");
-
-var attrType = AttributeHandler.begin(vars.get("$field.AB_ATTRIBUTE_ID")).getAttributeContentType();
-result.string(attrType);
\ No newline at end of file
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+result.string(AttributeTypeUtil.getContentType(attributeType));
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/displayValueProcess.js b/entity/AttributeRelation_entity/entityfields/valueproxy/displayValueProcess.js
index c2cd0971b53da78645efc3ea3db900d49d9d412a..412402a7e204e4fd01e21b755ae15ab57a5ceaa5 100644
--- a/entity/AttributeRelation_entity/entityfields/valueproxy/displayValueProcess.js
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/displayValueProcess.js
@@ -1,26 +1,26 @@
-import("system.db");
-import("system.result");
-import("system.vars");
-import("Attribute_lib");
-import("Keyword_lib");
-
-var attrType = AttributeHandler.begin(vars.get("$field.AB_ATTRIBUTE_ID")).getAttributeType();
-var value;
-if (attrType == $AttributeTypes.COMBO)
-    value = AttributeUtil.getSimpleAttributeName(vars.get("$field.ID_VALUE"));
-
-//TODO this is a workaround for keywords, when it's possible to use the consumer remove this else if
-else if (attrType == $AttributeTypes.KEYWORD)
-{
-    var keywordContainer = db.cell(
-        SqlCondition.begin()
-            .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$field.AB_ATTRIBUTE_ID")
-            .buildSql("select KEYWORD_CONTAINER from AB_ATTRIBUTE")
-    );
-    value = KeywordUtils.getViewValue(keywordContainer, vars.get("$field.ID_VALUE"));
-}
-
-else
-    value = vars.get("$field.valueProxy");
-
-result.string(value);
+import("system.db");
+import("system.result");
+import("system.vars");
+import("Attribute_lib");
+import("Keyword_lib");
+
+var attrType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+var value;
+if (attrType == $AttributeTypes.COMBO)
+    value = AttributeUtil.getSimpleAttributeName(vars.get("$field.ID_VALUE"));
+
+//TODO this is a workaround for keywords, when it's possible to use the consumer remove this else if
+else if (attrType == $AttributeTypes.KEYWORD)
+{
+    var keywordContainer = db.cell(
+        SqlCondition.begin()
+            .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$field.AB_ATTRIBUTE_ID")
+            .buildSql("select KEYWORD_CONTAINER from AB_ATTRIBUTE")
+    );
+    value = KeywordUtils.getViewValue(keywordContainer, vars.get("$field.ID_VALUE"));
+}
+
+else
+    value = vars.get("$field.valueProxy");
+
+result.string(value);
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/mandatoryProcess.js b/entity/AttributeRelation_entity/entityfields/valueproxy/mandatoryProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..564b24d9e769f678a1da3de8776adf941e94217e
--- /dev/null
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/mandatoryProcess.js
@@ -0,0 +1,6 @@
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+result.string(AttributeTypeUtil.getContentType(attributeType) != null);
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/onValueChange.js b/entity/AttributeRelation_entity/entityfields/valueproxy/onValueChange.js
index 5d8c07fa23edf16c4178d05f5de69dec3196dd17..44aaa91f083773956443f739a0d9cb8e6705330a 100644
--- a/entity/AttributeRelation_entity/entityfields/valueproxy/onValueChange.js
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/onValueChange.js
@@ -1,10 +1,35 @@
+import("system.neon");
 import("system.vars");
 import("Entity_lib");
 import("Attribute_lib");
 
 var attrValue = vars.exists("$field.valueProxy") ? vars.get("$field.valueProxy") : "";
 attrValue = ProcessHandlingUtils.getOnValidationValue(attrValue);
-var attribute = AttributeHandler.begin(vars.get("$field.AB_ATTRIBUTE_ID"));
 
-if(attrValue != null)
-    attribute.setAttributeValue(attrValue);
\ No newline at end of file
+if (attrValue != null)
+{
+    var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+    var attrField = (function (pType)
+    {
+        switch (pType)
+        {
+            case $AttributeTypes.TEXT.toString():
+            case $AttributeTypes.MEMO.toString():
+                return "$field.CHAR_VALUE";
+            case $AttributeTypes.DATE.toString():
+                return "$field.DATE_VALUE";
+            case $AttributeTypes.NUMBER.toString():
+                return "$field.NUMBER_VALUE";
+            case $AttributeTypes.BOOLEAN.toString():
+                return "$field.INT_VALUE";
+            case $AttributeTypes.COMBO.toString():
+            case $AttributeTypes.KEYWORD.toString():
+                return "$field.ID_VALUE";
+            default:
+                return null;
+        }
+    }).call(null, attributeType);
+
+    if (attrField)
+        neon.setFieldValue(attrField, attrValue);
+}
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/possibleItemsProcess.js b/entity/AttributeRelation_entity/entityfields/valueproxy/possibleItemsProcess.js
index 4a7f1e46eda7a88afbfe7523691dd836a6f774bf..104cdfb69131ecc5c4cd06163ae52cf16283c408 100644
--- a/entity/AttributeRelation_entity/entityfields/valueproxy/possibleItemsProcess.js
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/possibleItemsProcess.js
@@ -6,7 +6,7 @@ import("Attribute_lib");
 import("Sql_lib");
 
 var attributeId = vars.get("$field.AB_ATTRIBUTE_ID");
-var attrType = AttributeHandler.begin(attributeId).getAttributeType();
+var attrType = AttributeUtil.getAttributeType(attributeId);
 
 if (attrType == $AttributeTypes.COMBO)
 {
@@ -14,7 +14,7 @@ if (attrType == $AttributeTypes.COMBO)
         .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_ACTIVE", "1")
         .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", attributeId)
         .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE)
-        .buildSql("select AB_ATTRIBUTEID, ATTRIBUTE_NAME from AB_ATTRIBUTE", "1=2", "order by ATTRIBUTE_NAME");
+        .buildSql("select AB_ATTRIBUTEID, ATTRIBUTE_NAME from AB_ATTRIBUTE", "1=2", "order by SORTING asc");
     var valueList = db.table(valueSql);
     result.object(valueList);
 }
@@ -36,7 +36,7 @@ else if (attrType == $AttributeTypes.KEYWORD)
     
     var sql = SqlCondition.begin()
         .andPrepare("AB_KEYWORD_ENTRY.CONTAINER", db.cell(attrKeywordSelect))
-        .buildSql("select AB_KEYWORD_ENTRY.KEYID, AB_KEYWORD_ENTRY.TITLE from AB_KEYWORD_ENTRY");
+        .buildSql("select AB_KEYWORD_ENTRY.KEYID, AB_KEYWORD_ENTRY.TITLE from AB_KEYWORD_ENTRY", "1=2", "order by SORTING asc");
     var keywords = db.table(sql).map(function (row)
     {
         return [row[0], translate.text(row[1])];
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/stateProcess.js b/entity/AttributeRelation_entity/entityfields/valueproxy/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7eb783c7dfa26f85106d4836ba568ea05641bc6b
--- /dev/null
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+result.string(AttributeTypeUtil.getContentType(attributeType));
+var fieldState;
+if (AttributeTypeUtil.getContentType(attributeType) != null)
+    fieldState = neon.COMPONENTSTATE_EDITABLE;
+else
+    fieldState = neon.COMPONENTSTATE_READONLY;
+
+result.string(fieldState);
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/entityfields/valueproxy/valueProcess.js b/entity/AttributeRelation_entity/entityfields/valueproxy/valueProcess.js
index bea46eecb189b5b83f3704ecf8ea3f019d0581c4..10d3aadcf50110dd9da7e5b189729ebd2f8174dd 100644
--- a/entity/AttributeRelation_entity/entityfields/valueproxy/valueProcess.js
+++ b/entity/AttributeRelation_entity/entityfields/valueproxy/valueProcess.js
@@ -3,20 +3,38 @@ import("system.result");
 import("system.vars");
 import("Attribute_lib");
 
-"$field.CHAR_VALUE";
-"$field.DATE_VALUE";
-"$field.NUMBER_VALUE";
-"$field.INT_VALUE";
-"$field.ID_VALUE";
-
 if(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW)
 {
-    var attrField = AttributeHandler.begin(vars.get("$field.AB_ATTRIBUTE_ID")).getAttributeField();
+    var rowId = vars.get("$param.ObjectRowId_param");
+    var objectType = vars.get("$param.ObjectType_param");
+    var attributeId = vars.get("$field.AB_ATTRIBUTE_ID");
+    
+    var attributeType = AttributeUtil.getAttributeType(vars.get("$field.AB_ATTRIBUTE_ID"));
+    var attrField = (function (type)
+    {
+        switch (type)
+        {
+            case $AttributeTypes.TEXT.toString():
+            case $AttributeTypes.MEMO.toString():
+                return "$field.CHAR_VALUE";
+            case $AttributeTypes.DATE.toString():
+                return "$field.DATE_VALUE";
+            case $AttributeTypes.NUMBER.toString():
+                return "$field.NUMBER_VALUE";
+            case $AttributeTypes.BOOLEAN.toString():
+                return "$field.INT_VALUE";
+            case $AttributeTypes.COMBO.toString():
+            case $AttributeTypes.KEYWORD.toString():
+                return "$field.ID_VALUE";
+        }
+    }).call(null, attributeType);
     var value = null;
     if (attrField != null) //load the value from the correct field for the type
-        value = vars.get("$field." + attrField);
+        value = vars.get(attrField);
     
     if(value != null && value != "")
-        result.string(value); 
+        result.string(value);
+    else if (attributeType == $AttributeTypes.VOID)
+        result.string("");
 }
 
diff --git a/entity/AttributeUsage_entity/AttributeUsage_entity.aod b/entity/AttributeUsage_entity/AttributeUsage_entity.aod
index 1d04eaa1faddc57d89dd575a5bd69803b7ae14fa..592e1c543ee3153657b8835c77f89b5ab4a9b33c 100644
--- a/entity/AttributeUsage_entity/AttributeUsage_entity.aod
+++ b/entity/AttributeUsage_entity/AttributeUsage_entity.aod
@@ -75,6 +75,14 @@
           <name>GetAllContexts_param</name>
           <valueProcess>%aditoprj%/entity/AttributeUsage_entity/entityfields/context/children/getallcontexts_param/valueProcess.js</valueProcess>
         </entityParameter>
+        <entityParameter>
+          <name>UseExclusives_param</name>
+          <valueProcess>%aditoprj%/entity/AttributeUsage_entity/entityfields/context/children/useexclusives_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>ExclusiveContexts_param</name>
+          <valueProcess>%aditoprj%/entity/AttributeUsage_entity/entityfields/context/children/exclusivecontexts_param/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
     </entityConsumer>
   </entityFields>
diff --git a/entity/AttributeUsage_entity/entityfields/context/children/exclusivecontexts_param/valueProcess.js b/entity/AttributeUsage_entity/entityfields/context/children/exclusivecontexts_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ccd8c87e5829b0b4895728bee6a2d184aaa0424
--- /dev/null
+++ b/entity/AttributeUsage_entity/entityfields/context/children/exclusivecontexts_param/valueProcess.js
@@ -0,0 +1,12 @@
+import("system.result");
+
+result.object([
+    "Organisation",
+    "Person",
+    "Contract",
+    "Product",
+    "Activity",
+    "Offer",
+    "Employee",
+    "Salesproject"
+]);
\ No newline at end of file
diff --git a/entity/AttributeUsage_entity/entityfields/context/children/useexclusives_param/valueProcess.js b/entity/AttributeUsage_entity/entityfields/context/children/useexclusives_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..cda204045d2aba9ae974e0ce2200ba0cc6c852c0
--- /dev/null
+++ b/entity/AttributeUsage_entity/entityfields/context/children/useexclusives_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string(true);
\ No newline at end of file
diff --git a/entity/Attribute_entity/Attribute_entity.aod b/entity/Attribute_entity/Attribute_entity.aod
index 27bd01462c6cfe52e580468756201a33b84bd200..8aac32466a499fe984a1c8f2655e6a311c829212 100644
--- a/entity/Attribute_entity/Attribute_entity.aod
+++ b/entity/Attribute_entity/Attribute_entity.aod
@@ -1,338 +1,318 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.1">
-  <name>Attribute_entity</name>
-  <title>Attribute</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/Attribute_entity/documentation.adoc</documentation>
-  <afterUiInit>%aditoprj%/entity/Attribute_entity/afterUiInit.js</afterUiInit>
-  <iconId>VAADIN:TAG</iconId>
-  <titleProcess>%aditoprj%/entity/Attribute_entity/titleProcess.js</titleProcess>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>ATTRIBUTE_NAME</name>
-      <title>Name</title>
-      <mandatory v="true" />
-      <state>EDITABLE</state>
-    </entityField>
-    <entityField>
-      <name>ATTRIBUTE_TYPE</name>
-      <title>Type</title>
-      <consumer>KeywordAttributeTypes</consumer>
-      <mandatory v="true" />
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js</stateProcess>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/onValueChange.js</onValueChange>
-    </entityField>
-    <entityField>
-      <name>AB_ATTRIBUTEID</name>
-      <searchable v="false" />
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/ab_attributeid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>ATTRIBUTE_PARENT_ID</name>
-      <title>Superordinate Attribute</title>
-      <consumer>AttributeGroup</consumer>
-      <linkedContext>Attribute</linkedContext>
-      <searchable v="false" />
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/stateProcess.js</stateProcess>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/displayValueProcess.js</displayValueProcess>
-      <onValueChangeTypes>
-        <element>MASK</element>
-        <element>PROCESS</element>
-        <element>PROCESS_SETVALUE</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityConsumer>
-      <name>AttributeChildren</name>
-      <title>Attributes</title>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Attribute_entity</entityName>
-        <fieldName>AttributeParent</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-          <triggerRecalculation v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentType_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-          <triggerRecalculation v="true" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityProvider>
-      <name>AttributeParent</name>
-      <fieldType>DEPENDENCY_IN</fieldType>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>18bd148d-bed3-429f-ba54-c5eac76c5083</name>
-          <entityName>Attribute_entity</entityName>
-          <fieldName>AttributeChildren</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>AttrParentType_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>GetGroups_param</name>
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>AttrParentId_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>AttributeUsages</name>
-      <title>Usage</title>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>AttributeUsage_entity</entityName>
-        <fieldName>SpecificAttribute</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AttributeId_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-          <triggerRecalculation v="true" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>ATTRIBUTE_ACTIVE</name>
-      <title>Active</title>
-      <contentType>BOOLEAN</contentType>
-      <possibleItemsProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/possibleItemsProcess.js</possibleItemsProcess>
-      <groupable v="true" />
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/valueProcess.js</valueProcess>
-    </entityField>
-    <entityConsumer>
-      <name>KeywordAttributeTypes</name>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>ContainerName_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/keywordattributetypes/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-          <triggerRecalculation v="true" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>ATTRIBUTE_LEVEL</name>
-      <title>Level</title>
-      <description>The level is required in the order-by to make sure that superordinate attributes come before their subordinates for the tree</description>
-      <contentType>NUMBER</contentType>
-      <state>INVISIBLE</state>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_level/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>KEYWORD_CONTAINER</name>
-      <title>Keyword</title>
-      <possibleItemsProcess>%aditoprj%/entity/Attribute_entity/entityfields/keyword_container/possibleItemsProcess.js</possibleItemsProcess>
-      <searchable v="false" />
-      <state>AUTO</state>
-      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/keyword_container/stateProcess.js</stateProcess>
-    </entityField>
-    <entityParameter>
-      <name>AttrParentType_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>ObjectType_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityProvider>
-      <name>SpecificAttribute</name>
-      <fieldType>DEPENDENCY_IN</fieldType>
-      <lookupIdfield>AB_ATTRIBUTEID</lookupIdfield>
-      <dependencies>
-        <entityDependency>
-          <name>342e8ba6-db61-411b-9f79-e9271335b00f</name>
-          <entityName>AttributeRelation_entity</entityName>
-          <fieldName>SpecificAttribute</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>ObjectType_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>FilteredAttributeIds_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>DisplaySimpleName_param</name>
-          <expose v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityField>
-      <name>FULL_ATTRIBUTE_NAME</name>
-      <title>Name</title>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/full_attribute_name/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>FilteredAttributeIds_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityActionGroup>
-      <name>AttributeActions</name>
-      <children>
-        <entityActionField>
-          <name>newChildAttribute</name>
-          <fieldType>ACTION</fieldType>
-          <title>New attribute</title>
-          <onActionProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:FILE_TREE_SMALL</iconId>
-          <tooltipProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/tooltipProcess.js</tooltipProcess>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
-    <entityParameter>
-      <name>GetGroups_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>DisplaySimpleName_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityField>
-      <name>USAGELIST</name>
-      <title>Usages</title>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/usagelist/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>NAME_WITH_TYPE</name>
-      <title>Name</title>
-      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/name_with_type/valueProcess.js</valueProcess>
-    </entityField>
-    <entityProvider>
-      <name>AttributeGroups</name>
-      <fieldType>DEPENDENCY_IN</fieldType>
-      <recordContainer>db</recordContainer>
-      <children>
-        <entityParameter>
-          <name>GetGroups_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroups/children/getgroups_param/valueProcess.js</valueProcess>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <expose v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityConsumer>
-      <name>AttributeGroup</name>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Attribute_entity</entityName>
-        <fieldName>AttributeGroups</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AttrParentId_param</name>
-          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>IMAGE</name>
-      <contentType>IMAGE</contentType>
-    </entityField>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <conditionProcess>%aditoprj%/entity/Attribute_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <orderClauseProcess>%aditoprj%/entity/Attribute_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
-      <onDBUpdate>%aditoprj%/entity/Attribute_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
-      <onDBDelete>%aditoprj%/entity/Attribute_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
-      <linkInformation>
-        <linkInformation>
-          <name>b5fd38e1-b315-4e66-bd68-569dfc04710c</name>
-          <tableName>AB_ATTRIBUTE</tableName>
-          <primaryKey>AB_ATTRIBUTEID</primaryKey>
-          <isUIDTable v="true" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>AB_ATTRIBUTEID.value</name>
-          <recordfield>AB_ATTRIBUTE.AB_ATTRIBUTEID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ATTRIBUTE_PARENT_ID.value</name>
-          <recordfield>AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ATTRIBUTE_TYPE.value</name>
-          <recordfield>AB_ATTRIBUTE.ATTRIBUTE_TYPE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ATTRIBUTE_ACTIVE.value</name>
-          <recordfield>AB_ATTRIBUTE.ATTRIBUTE_ACTIVE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ATTRIBUTE_TYPE.displayValue</name>
-          <expression>%aditoprj%/entity/Attribute_entity/recordcontainers/db/recordfieldmappings/attribute_type.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ATTRIBUTE_NAME.value</name>
-          <recordfield>AB_ATTRIBUTE.ATTRIBUTE_NAME</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ATTRIBUTE_LEVEL.value</name>
-          <recordfield>AB_ATTRIBUTE.ATTRIBUTE_LEVEL</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>KEYWORD_CONTAINER.value</name>
-          <recordfield>AB_ATTRIBUTE.KEYWORD_CONTAINER</recordfield>
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-    </dbRecordContainer>
-  </recordContainers>
-</entity>
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.1">
+  <name>Attribute_entity</name>
+  <title>Attribute</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/Attribute_entity/documentation.adoc</documentation>
+  <afterUiInit>%aditoprj%/entity/Attribute_entity/afterUiInit.js</afterUiInit>
+  <onValidation>%aditoprj%/entity/Attribute_entity/onValidation.js</onValidation>
+  <iconId>VAADIN:TAG</iconId>
+  <titleProcess>%aditoprj%/entity/Attribute_entity/titleProcess.js</titleProcess>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>ATTRIBUTE_NAME</name>
+      <title>Name</title>
+      <mandatory v="true" />
+      <state>EDITABLE</state>
+    </entityField>
+    <entityField>
+      <name>ATTRIBUTE_TYPE</name>
+      <title>Type</title>
+      <consumer>KeywordAttributeTypes</consumer>
+      <mandatory v="true" />
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/onValueChange.js</onValueChange>
+    </entityField>
+    <entityField>
+      <name>ATTRIBUTE_PARENT_ID</name>
+      <title>Superordinate Attribute</title>
+      <consumer>AttributeGroup</consumer>
+      <linkedContext>Attribute</linkedContext>
+      <searchable v="false" />
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_parent_id/displayValueProcess.js</displayValueProcess>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+        <element>PROCESS_SETVALUE</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityConsumer>
+      <name>AttributeChildren</name>
+      <title>Attributes</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/stateProcess.js</stateProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Attribute_entity</entityName>
+        <fieldName>AttributeParent</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityProvider>
+      <name>AttributeParent</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>18bd148d-bed3-429f-ba54-c5eac76c5083</name>
+          <entityName>Attribute_entity</entityName>
+          <fieldName>AttributeChildren</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>9fb3569c-7c75-48b1-9dc0-3f707940813a</name>
+          <entityName>Employee_entity</entityName>
+          <fieldName>Departments</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <expose v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>AttrParentId_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>AttributeUsages</name>
+      <title>Usage</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AttributeUsage_entity</entityName>
+        <fieldName>SpecificAttribute</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttributeId_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>ATTRIBUTE_ACTIVE</name>
+      <title>Active</title>
+      <contentType>BOOLEAN</contentType>
+      <possibleItemsProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/possibleItemsProcess.js</possibleItemsProcess>
+      <groupable v="true" />
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_active/valueProcess.js</valueProcess>
+    </entityField>
+    <entityConsumer>
+      <name>KeywordAttributeTypes</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/keywordattributetypes/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>KEYWORD_CONTAINER</name>
+      <title>Keyword</title>
+      <possibleItemsProcess>%aditoprj%/entity/Attribute_entity/entityfields/keyword_container/possibleItemsProcess.js</possibleItemsProcess>
+      <searchable v="false" />
+      <state>AUTO</state>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/keyword_container/stateProcess.js</stateProcess>
+    </entityField>
+    <entityParameter>
+      <name>AttrParentType_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>ObjectType_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>SpecificAttribute</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <lookupIdfield>UID</lookupIdfield>
+      <dependencies>
+        <entityDependency>
+          <name>342e8ba6-db61-411b-9f79-e9271335b00f</name>
+          <entityName>AttributeRelation_entity</entityName>
+          <fieldName>SpecificAttribute</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>ba3b4d47-7385-49df-bf61-54c99f5b2c81</name>
+          <entityName>AttributeRelationTree_entity</entityName>
+          <fieldName>SpecificAttribute</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>FilteredAttributeIds_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>DisplaySimpleName_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>GetGroups_param</name>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityField>
+      <name>FULL_ATTRIBUTE_NAME</name>
+      <title>Name</title>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/full_attribute_name/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>FilteredAttributeIds_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityActionGroup>
+      <name>AttributeActions</name>
+      <children>
+        <entityActionField>
+          <name>newChildAttribute</name>
+          <fieldType>ACTION</fieldType>
+          <title>New attribute</title>
+          <onActionProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js</onActionProcess>
+          <isMenuAction v="true" />
+          <isObjectAction v="false" />
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:FILE_TREE_SMALL</iconId>
+          <tooltipProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/tooltipProcess.js</tooltipProcess>
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityParameter>
+      <name>GetGroups_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>DisplaySimpleName_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>USAGELIST</name>
+      <title>Usage</title>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/usagelist/valueProcess.js</valueProcess>
+    </entityField>
+    <entityProvider>
+      <name>AttributeGroups</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <children>
+        <entityParameter>
+          <name>GetGroups_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroups/children/getgroups_param/valueProcess.js</valueProcess>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <expose v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityConsumer>
+      <name>AttributeGroup</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Attribute_entity</entityName>
+        <fieldName>AttributeGroups</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>IMAGE</name>
+      <contentType>IMAGE</contentType>
+    </entityField>
+    <entityField>
+      <name>UID</name>
+      <searchable v="false" />
+    </entityField>
+    <entityField>
+      <name>SORTING</name>
+      <title>Sorting</title>
+      <searchable v="false" />
+    </entityField>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
+      <contentProcess>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
+      <onInsert>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onInsert.js</onInsert>
+      <onUpdate>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
+      <onDelete>%aditoprj%/entity/Attribute_entity/recordcontainers/jdito/onDelete.js</onDelete>
+      <recordFields>
+        <element>UID.value</element>
+        <element>ATTRIBUTE_ACTIVE.value</element>
+        <element>ATTRIBUTE_NAME.value</element>
+        <element>ATTRIBUTE_PARENT_ID.value</element>
+        <element>ATTRIBUTE_TYPE.value</element>
+        <element>ATTRIBUTE_TYPE.displayValue</element>
+        <element>KEYWORD_CONTAINER.value</element>
+        <element>SORTING.value</element>
+      </recordFields>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/Attribute_entity/afterUiInit.js b/entity/Attribute_entity/afterUiInit.js
index 87febc93d555370828def178d66937ba02b37a7e..4bfd7805a27d3e9e0b27292222ffc1f4a101cd9b 100644
--- a/entity/Attribute_entity/afterUiInit.js
+++ b/entity/Attribute_entity/afterUiInit.js
@@ -1,27 +1,27 @@
-import("system.util");
-import("system.db");
-import("system.neon");
-import("system.vars");
-import("Context_lib");
-import("Attribute_lib");
-
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW 
-    && vars.get("$field.ATTRIBUTE_TYPE").trim() != $AttributeTypes.COMBOVALUE
-    && vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param"))
-{
-    var parentId = vars.get("$param.AttrParentId_param");
-    var attributeId = vars.get("$field.AB_ATTRIBUTEID");
-
-    var usageSql = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", parentId)
-        .buildSql("select OBJECT_TYPE from AB_ATTRIBUTEUSAGE", "1=0");
-    var usages = db.array(db.COLUMN, usageSql);
-
-    //preset the usages with the ones from the parent
-    usages.forEach(function (usage) 
-    {
-        neon.addRecord(null, "AttributeUsages", {
-            "OBJECT_TYPE" : usage
-        });
-    });
+import("system.util");
+import("system.db");
+import("system.neon");
+import("system.vars");
+import("Context_lib");
+import("Attribute_lib");
+
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW 
+    && vars.get("$field.ATTRIBUTE_TYPE").trim() != $AttributeTypes.COMBOVALUE
+    && vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param"))
+{
+    var parentId = vars.get("$param.AttrParentId_param");
+    var attributeId = vars.get("$field.UID");
+
+    var usageSql = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", parentId)
+        .buildSql("select OBJECT_TYPE from AB_ATTRIBUTEUSAGE", "1=0");
+    var usages = db.array(db.COLUMN, usageSql);
+
+    //preset the usages with the ones from the parent
+    usages.forEach(function (usage) 
+    {
+        neon.addRecord(null, "AttributeUsages", {
+            "OBJECT_TYPE" : usage
+        });
+    });
 }
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/ab_attributeid/valueProcess.js b/entity/Attribute_entity/entityfields/ab_attributeid/valueProcess.js
deleted file mode 100644
index 7df83b4096e7df4d63cc4d81f8fadf0884444479..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/entityfields/ab_attributeid/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.util");
-import("system.result");
-import("system.neon");
-import("system.vars");
-
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-    result.string(util.getNewUUID());
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attribute_level/valueProcess.js b/entity/Attribute_entity/entityfields/attribute_level/valueProcess.js
deleted file mode 100644
index e91a822698ae74d9b594ed31998920eb6f639c74..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/entityfields/attribute_level/valueProcess.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import("system.db");
-import("system.neon");
-import("system.result");
-import("system.vars");
-import("Sql_lib");
-
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
-    if (vars.get("$field.ATTRIBUTE_PARENT_ID") != "")
-    {
-        var level = db.cell(SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", vars.get("$field.ATTRIBUTE_PARENT_ID"))
-            .buildSql("select ATTRIBUTE_LEVEL from AB_ATTRIBUTE"));
-        result.string(parseInt(level) + 1);
-    }
-    else
-        result.string("0");
diff --git a/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js b/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js
index b0787c129334740faccc1539867edf1574daf8cc..6f4ceebb8446e53fd41fee8d92bbd07185d2a4d0 100644
--- a/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attribute_parent_id/valueProcess.js
@@ -2,5 +2,5 @@ import("system.neon");
 import("system.result");
 import("system.vars");
 
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param"))
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param") && !vars.get("$this.value"))
     result.string(vars.get("$param.AttrParentId_param"));
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js b/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js
index 1b16072cc5a33cdaf35fd48c69d9b74e98b526f7..8c164c65749178bf883b0548ce4b019169451264 100644
--- a/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js
+++ b/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js
@@ -8,7 +8,6 @@ import("KeywordRegistry_basic");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$field.ATTRIBUTE_PARENT_ID") != "")
 {
-    var type = AttributeHandler.begin(vars.get("$field.ATTRIBUTE_PARENT_ID")).getAttributeType();
-    if (type == $AttributeTypes.COMBO)
-        result.string(KeywordUtils.getViewValue($KeywordRegistry.attributeType(), $AttributeTypes.COMBOVALUE));
+    var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+    result.string(KeywordUtils.getViewValue($KeywordRegistry.attributeType(), type));
 }
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js b/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
index f663dddf570f4246c8ae5babd6035026d2bc2ffc..184ef602b204e022ed7be351ad8e3d56b07f61eb 100644
--- a/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
+++ b/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
@@ -1,31 +1,32 @@
-import("system.db");
-import("system.neon");
-import("system.result");
-import("system.vars");
-import("Attribute_lib");
-import("Sql_lib");
-
-var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
-var state = neon.COMPONENTSTATE_AUTO
-if (type == $AttributeTypes.COMBOVALUE)
-{
-    state = neon.COMPONENTSTATE_READONLY;
-}
-else if (type == $AttributeTypes.GROUP || type == $AttributeTypes.COMBO)
-{
-    var hasSubordinate = db.cell(SqlCondition.begin()
-        .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$field.AB_ATTRIBUTEID")
-        .buildSql(
-            "select exists ("
-            +    "select SUB.AB_ATTRIBUTEID from AB_ATTRIBUTE SUB "
-            +    "where SUB.ATTRIBUTE_PARENT_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
-            + ") from AB_ATTRIBUTE", "1=2"
-        )
-    ) == "true";
-    if (hasSubordinate)
-        state = neon.COMPONENTSTATE_READONLY;
-}
-else if (AttributeUtil.hasRelations(vars.get("$field.AB_ATTRIBUTEID")))
-        state = neon.COMPONENTSTATE_READONLY;
-
+import("system.db");
+import("system.neon");
+import("system.result");
+import("system.vars");
+import("Attribute_lib");
+import("Sql_lib");
+
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+var parentType = AttributeUtil.getAttributeType(vars.get("$field.ATTRIBUTE_PARENT_ID"));
+var state = neon.COMPONENTSTATE_EDITABLE;
+if (parentType == $AttributeTypes.COMBO || parentType == $AttributeTypes.VOID)
+{
+    state = neon.COMPONENTSTATE_READONLY;
+}
+else if (AttributeTypeUtil.isGroupType(type))
+{
+    var hasSubordinate = db.cell(SqlCondition.begin()
+        .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$field.UID")
+        .buildSql(
+            "select exists ("
+            +    "select SUB.AB_ATTRIBUTEID from AB_ATTRIBUTE SUB "
+            +    "where SUB.ATTRIBUTE_PARENT_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
+            + ") from AB_ATTRIBUTE", "1=2"
+        )
+    ) == "true";
+    if (hasSubordinate)
+        state = neon.COMPONENTSTATE_READONLY;
+}
+else if (AttributeUtil.hasRelations(vars.get("$field.UID")))
+        state = neon.COMPONENTSTATE_READONLY;
+
 result.string(state)
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js b/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js
index 8c60a83409d16ed0c06f474820e356a9c71b4fbb..dce209f82e8327acf4eeed9795e5ad9c82e80383 100644
--- a/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js
@@ -6,7 +6,9 @@ import("Attribute_lib");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$field.ATTRIBUTE_PARENT_ID") != "")
 {
-    var type = AttributeHandler.begin(vars.get("$field.ATTRIBUTE_PARENT_ID")).getAttributeType();
+    var type = AttributeUtil.getAttributeType(vars.get("$field.ATTRIBUTE_PARENT_ID"));
     if (type == $AttributeTypes.COMBO)
         result.string($AttributeTypes.COMBOVALUE);
+    else if (type == $AttributeTypes.VOID)
+        result.string($AttributeTypes.VOID);
 }
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js b/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js
index cb209fd2f503d12661c8c35b76f6ce767bf7b0bc..0ccfa2e4bf15531b52a7d33d316b14af3d0c1819 100644
--- a/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js
+++ b/entity/Attribute_entity/entityfields/attributeactions/children/newchildattribute/onActionProcess.js
@@ -8,8 +8,8 @@ if (vars.exists("$local.rows"))
     var row = JSON.parse(vars.get("$local.rows"));
     
     var type = row[0].ATTRIBUTE_TYPE.trim();
-    if (type == $AttributeTypes.GROUP || type == $AttributeTypes.COMBO)
-        params["AttrParentId_param"] = row[0].AB_ATTRIBUTEID;
+    if (AttributeTypeUtil.isGroupType(type))
+        params["AttrParentId_param"] = row[0].UID;
     else if (row[0].ATTRIBUTE_PARENT_ID)
         params["AttrParentId_param"] = row[0].ATTRIBUTE_PARENT_ID;
 }
diff --git a/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js b/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js
index b68489b6e02b29d34ae67b14c7371f985305f014..7bef0e16cef98c0686c4062dea4f92127436826c 100644
--- a/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js
@@ -3,5 +3,5 @@ import("system.result");
 import("Attribute_lib");
 
 var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
-if (type == $AttributeTypes.GROUP || type == $AttributeTypes.COMBO)
-    result.string(vars.getString("$field.AB_ATTRIBUTEID"));
+if (AttributeTypeUtil.isGroupType(type))
+    result.string(vars.getString("$field.UID"));
diff --git a/entity/Attribute_entity/entityfields/attributechildren/stateProcess.js b/entity/Attribute_entity/entityfields/attributechildren/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b1a6d07e3863f8959fe3923888d7e366becd9e34
--- /dev/null
+++ b/entity/Attribute_entity/entityfields/attributechildren/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.neon");
+import("system.result");
+import("system.vars");
+import("Attribute_lib");
+
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+if (AttributeTypeUtil.isGroupType(type))
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+else
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js b/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js
index 033bf9a666c5254c8945077776b2834560164e56..16c85500b5355a72548030867e3d300661e9d4aa 100644
--- a/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attributegroup/children/attrparentid_param/valueProcess.js
@@ -1,4 +1,4 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.AB_ATTRIBUTEID"));
\ No newline at end of file
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js b/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js
index f7ac89492841d22780c3d2eb1d38d4b0aa7de476..d2802861c77c62c37f3274882eba0e5c90cc8074 100644
--- a/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attributeusages/children/attributeid_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.AB_ATTRIBUTEID"));
+result.string(vars.get("$field.UID"));
diff --git a/entity/Attribute_entity/entityfields/name_with_type/valueProcess.js b/entity/Attribute_entity/entityfields/name_with_type/valueProcess.js
deleted file mode 100644
index 747a495cf7bb42324c1fb691b2609eae4e6df7cf..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/entityfields/name_with_type/valueProcess.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import("system.translate");
-import("system.result");
-import("system.vars");
-import("Attribute_lib");
-
-var name = vars.get("$field.ATTRIBUTE_NAME");
-if (vars.get("$field.ATTRIBUTE_TYPE").trim() != $AttributeTypes.COMBOVALUE)
-    name += " (" + translate.text("Type") + ": " + vars.get("$field.ATTRIBUTE_TYPE.displayValue") + ")";
-result.string(name);
\ No newline at end of file
diff --git a/entity/Attribute_entity/entityfields/usagelist/valueProcess.js b/entity/Attribute_entity/entityfields/usagelist/valueProcess.js
index 675da9521dc245e23992c051dc34239c6f262963..130b4cc5a16fb171b4613faf46c3a3734725750f 100644
--- a/entity/Attribute_entity/entityfields/usagelist/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/usagelist/valueProcess.js
@@ -1,18 +1,18 @@
-import("system.translate");
-import("system.result");
-import("system.db");
-import("system.vars");
-import("Sql_lib");
-import("Attribute_lib");
-
-var retStr = "\u00A0"; // \u00A0 -> space character that doesn't get trimmed 
-if (vars.get("$field.ATTRIBUTE_TYPE").trim() != $AttributeTypes.COMBOVALUE)
-{
-    var usages = db.array(db.COLUMN, SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", vars.get("$field.AB_ATTRIBUTEID"))
-        .buildSql("select OBJECT_TYPE from AB_ATTRIBUTEUSAGE"));
-    if (usages.length)
-        retStr = translate.text("Usage") +  ": " + usages.join(", ");
-}
-
+import("system.translate");
+import("system.result");
+import("system.db");
+import("system.vars");
+import("Sql_lib");
+import("Attribute_lib");
+
+var retStr = "\u00A0"; // \u00A0 -> space character that doesn't get trimmed 
+if (vars.get("$field.ATTRIBUTE_TYPE").trim() != $AttributeTypes.COMBOVALUE)
+{
+    var usages = db.array(db.COLUMN, SqlCondition.begin()
+        .andPrepareVars("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", "$field.UID")
+        .buildSql("select OBJECT_TYPE from AB_ATTRIBUTEUSAGE"));
+    if (usages.length)
+        retStr = usages.join(", ");
+}
+
 result.string(retStr);
\ No newline at end of file
diff --git a/entity/Attribute_entity/onValidation.js b/entity/Attribute_entity/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..b29f26919c078f346a53bc819a7f728948aa2dba
--- /dev/null
+++ b/entity/Attribute_entity/onValidation.js
@@ -0,0 +1,22 @@
+import("system.translate");
+import("system.db");
+import("system.vars");
+import("system.text");
+import("system.neon");
+import("Sql_lib");
+
+//TODO: this should no happen in onValidation; waiting for #1032668
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+{
+    var parentId = vars.get("$field.ATTRIBUTE_PARENT_ID");
+    if (parentId)
+    {
+        var cond = SqlCondition.begin().andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", parentId);
+        var maskingHelper = new SqlMaskingUtils();
+        var newCodeNumber = db.cell(cond.buildSql("select " + maskingHelper.max("AB_ATTRIBUTE.SORTING") + " from AB_ATTRIBUTE", "1 = 2"));
+        newCodeNumber = Number(newCodeNumber);//if no number exists till no, start value will be 1 (due to: ++0)
+        if (isNaN(newCodeNumber))
+            throw new TypeError(translate.text("The code number is not a valid number."));
+        neon.setFieldValue("$field.SORTING", ++newCodeNumber);
+    }
+}
\ No newline at end of file
diff --git a/entity/Attribute_entity/recordcontainers/db/conditionProcess.js b/entity/Attribute_entity/recordcontainers/db/conditionProcess.js
deleted file mode 100644
index ed323a5c82da868f9b3ae4deafd54ad035520109..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/recordcontainers/db/conditionProcess.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import("system.db");
-import("system.vars");
-import("system.result");
-import("Sql_lib");
-import("Attribute_lib");
-
-var condition = "1 = 2";
-
-var getGroups = vars.exists("$param.GetGroups_param") && vars.get("$param.GetGroups_param");
-var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param");
-if (getGroups)
-{
-    //this is for the selection of the superordinate attribute, this condition
-    //filters out the own id and the children to prevent loops
-    condition = db.translateCondition(SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP)
-        .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$param.AttrParentId_param", "# != ?")
-        .and("AB_ATTRIBUTE.AB_ATTRIBUTEID not in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')")
-        .build());
-}
-else if (objectType)  //if there's an objectType, it comes from the AttributeRelation entity
-{
-    var filteredAttributes = [];
-    if (vars.exists("$param.FilteredAttributeIds_param") && vars.get("$param.FilteredAttributeIds_param"))
-        filteredAttributes = JSON.parse(vars.get("$param.FilteredAttributeIds_param"));
-    
-    var ids = AttributeUtil.getPossibleAttributes(objectType, false, filteredAttributes);
-    condition = "AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + ids.join("','") + "')";
-} 
-else 
-{
-    var type = vars.exists("$param.AttrParentType_param") && vars.get("$param.AttrParentType_param");
-    if (type == $AttributeTypes.COMBO)
-        condition = SqlCondition.begin()
-            .andPrepareVars("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", "$param.AttrParentId_param")
-            .build();
-
-    var parentId = vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param");
-    if (parentId)
-        condition = "AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')";
-    else if (!type)
-        condition = "";
-    
-}
-
-result.string(condition);
diff --git a/entity/Attribute_entity/recordcontainers/db/onDBDelete.js b/entity/Attribute_entity/recordcontainers/db/onDBDelete.js
deleted file mode 100644
index 7d1eb8b477436101b8cacb2fa7aa00241708adae..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/recordcontainers/db/onDBDelete.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import("system.vars");
-import("system.db");
-import("Sql_lib");
-import("Attribute_lib");
-
-var attributeId = vars.get("$field.AB_ATTRIBUTEID");
-
-var childIds = AttributeUtil.getAllChildren(attributeId).concat(attributeId);
-
-var condition = SqlCondition.begin()
-    .and("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID in ('" + childIds.join("','") + "')")
-    .build();
-
-//delete all entries in AB_ATTRIBUTEUSAGE belonging to the attribute to avoid unrelated entries
-db.deleteData("AB_ATTRIBUTEUSAGE", condition);
-
-condition = SqlCondition.begin()
-    .and("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID in ('" + childIds.join("','") + "')")
-    .build();
-
-//delete all entries in AB_ATTRIBUTERELATION for the attributes
-db.deleteData("AB_ATTRIBUTERELATION", condition);
-
-condition = SqlCondition.begin()
-    .and("AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + childIds.join("','") + "')")
-    .build();
-
-//delete all attribute children
-db.deleteData("AB_ATTRIBUTE", condition);
diff --git a/entity/Attribute_entity/recordcontainers/db/onDBUpdate.js b/entity/Attribute_entity/recordcontainers/db/onDBUpdate.js
deleted file mode 100644
index 38704929f969ef673a7fafd41ac71a1fa2c05282..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/recordcontainers/db/onDBUpdate.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import("system.db");
-import("system.neon");
-import("system.vars");
-import("Attribute_lib");
-
-var level = parseInt(vars.get("$field.ATTRIBUTE_LEVEL"));
-
-var table = "AB_ATTRIBUTE";
-var columns = ["ATTRIBUTE_LEVEL"];
-var types = db.getColumnTypes(table, columns);
-var toUpdate = [];
-
-var attributes = [vars.get("$field.AB_ATTRIBUTEID")];
-while (attributes.length > 0)
-{
-    var condition = SqlCondition.begin()
-        .and("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID in ('" + attributes.join("','") + "')");
-
-    toUpdate.push([table, columns, types, [String(++level)], condition.build()]);
-
-    attributes = db.array(db.COLUMN, SqlCondition.begin()
-        .and("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID in ('" + attributes.join("','") + "')")
-        .buildSql("select AB_ATTRIBUTEID from AB_ATTRIBUTE")
-    );
-}
-
-db.updates(toUpdate);
diff --git a/entity/Attribute_entity/recordcontainers/db/orderClauseProcess.js b/entity/Attribute_entity/recordcontainers/db/orderClauseProcess.js
deleted file mode 100644
index 003688a8bb9231d8f68eada88a41012db8d2ac2c..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/recordcontainers/db/orderClauseProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.db");
-import("system.result");
-result.object({
-    "AB_ATTRIBUTE.ATTRIBUTE_LEVEL" : db.ASCENDING,
-    "AB_ATTRIBUTE.ATTRIBUTE_NAME" : db.ASCENDING
-});
\ No newline at end of file
diff --git a/entity/Attribute_entity/recordcontainers/db/recordfieldmappings/attribute_type.displayvalue/expression.js b/entity/Attribute_entity/recordcontainers/db/recordfieldmappings/attribute_type.displayvalue/expression.js
deleted file mode 100644
index 70d91a13284d4fe84c3ac11898f9818d944f46a2..0000000000000000000000000000000000000000
--- a/entity/Attribute_entity/recordcontainers/db/recordfieldmappings/attribute_type.displayvalue/expression.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.result");
-import("Keyword_lib");
-import("KeywordRegistry_basic");
-
-var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.attributeType(), "AB_ATTRIBUTE.ATTRIBUTE_TYPE");
-result.string(sql);
\ No newline at end of file
diff --git a/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js b/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
index c56f881e002f57622f6c794a36084061d48df894..db6a619a464b63ba118b82c8cf51e07f55a8ccea 100644
--- a/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
@@ -1,3 +1,4 @@
+import("system.datetime");
 import("JditoFilter_lib");
 import("KeywordRegistry_basic");
 import("Keyword_lib");
@@ -7,19 +8,34 @@ import("system.result");
 import("Sql_lib");
 import("Attribute_lib");
 
+var sqlSelect = "select AB_ATTRIBUTEID, ATTRIBUTE_ACTIVE, " 
+    + "ATTRIBUTE_NAME, ATTRIBUTE_PARENT_ID, ATTRIBUTE_TYPE, " 
+    + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.attributeType(), "ATTRIBUTE_TYPE")
+    + ", KEYWORD_CONTAINER, SORTING from AB_ATTRIBUTE";
+
+var sqlOrder = " order by ATTRIBUTE_PARENT_ID asc, SORTING asc";
+
 var condition = new SqlCondition();
 
 var getGroups = vars.exists("$param.GetGroups_param") && vars.get("$param.GetGroups_param");
 var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param");
-if (getGroups)
+
+if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
+    condition.and("AB_ATTRIBUTEID in ('" + vars.get("$local.idvalues").join("','") + "')");
+else if (getGroups)
 {
     //this is for the selection of the superordinate attribute, this condition
     //filters out the own id and the children to prevent loops
+    
+    var isGroupCondition = new SqlCondition();
+    for (let type in $AttributeTypes)
+        if ($AttributeTypes[type].isGroup && $AttributeTypes[type] != $AttributeTypes.COMBO)
+            isGroupCondition.orPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes[type]);
     condition.andSqlCondition(SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.GROUP)
+        .andSqlCondition(isGroupCondition)
         .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$param.AttrParentId_param", "# != ?")
         .and("AB_ATTRIBUTE.AB_ATTRIBUTEID not in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')")
-        .build());
+    );
 }
 else if (objectType)  //if there's an objectType, it comes from the AttributeRelation entity
 {
@@ -32,35 +48,27 @@ else if (objectType)  //if there's an objectType, it comes from the AttributeRel
 } 
 else 
 {
-    var type = vars.exists("$param.AttrParentType_param") && vars.get("$param.AttrParentType_param");
-    if (type == $AttributeTypes.COMBO)
-        condition = SqlCondition.begin()
-            .andPrepareVars("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", "$param.AttrParentId_param")
-            .build();
-    else if (type)
+    var type = vars.exists("$param.AttrParentType_param") && vars.get("$param.AttrParentType_param");   
+    if (AttributeTypeUtil.isGroupType(type))
     {
-    var parentId = vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param");
-    if (parentId)
-        condition.and("AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')");
+        var parentId = vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param");
+        if (parentId)
+            condition.and("AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')");
     }
+    else if (type)
+        condition.and("1=2");
 }
 
-var sql = "select AB_ATTRIBUTEID, AB_ATTRIBUTEID, ATTRIBUTE_ACTIVE, " 
-    + "ATTRIBUTE_NAME, ATTRIBUTE_PARENT_ID, ATTRIBUTE_TYPE, " 
-    + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.attributeType(), "ATTRIBUTE_TYPE")
-    + ", KEYWORD_CONTAINER from AB_ATTRIBUTE";
-
-if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
-    condition.and(" AB_ATTRIBUTEID in ('" + vars.get("$local.idvalues").join("','") + "')");
-else if (vars.exists("$local.filter") && vars.get("$local.filter"))
+//when there are filters selected, add them to the conditon
+if (vars.exists("$local.filter") && vars.get("$local.filter"))
 {
     var filter = vars.get("$local.filter");
     condition.andSqlCondition((JditoFilterUtils.getSqlCondition(filter, "AB_ATTRIBUTE")));
 }
 
-var attributes = db.table(condition.buildSql(sql, "1=1"));
+var attributes = db.table(condition.buildSql(sqlSelect, "1=1", sqlOrder));
 
-if (!(vars.exists("$local.idvalues") && vars.get("$local.idvalues")))
+if (attributes.length > 1)
     attributes = _sortArrayForTree(attributes);
 
 result.object(attributes);
@@ -70,8 +78,8 @@ function _sortArrayForTree (pArray)
 {
     var rows = {};
     var allIds = {};
-    var idIndex = 1;
-    var parentIdIndex = 4;
+    var idIndex = 0;
+    var parentIdIndex = 3;
     
     pArray.forEach(function (row) {allIds[row[idIndex]] = true;});
     
@@ -82,6 +90,8 @@ function _sortArrayForTree (pArray)
         var oldIndex = index;
         pArray.forEach(function (row)
         {
+            //item will be added if the id is not already in the object and
+            //the parent is already added (or the parent is not in the array)
             if (!(row[idIndex] in this) && (row[parentIdIndex] in this || !allIds[row[parentIdIndex]]))
                 this[row[idIndex]] = {
                     data : row,
diff --git a/entity/Attribute_entity/recordcontainers/jdito/onInsert.js b/entity/Attribute_entity/recordcontainers/jdito/onInsert.js
index 87565632d7cf592ac1bfe137d87ca62be849a32c..4562756bb00d4618c663365b69d352456c6fca71 100644
--- a/entity/Attribute_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/Attribute_entity/recordcontainers/jdito/onInsert.js
@@ -4,20 +4,20 @@ import("system.vars");
 var columns = [
     "AB_ATTRIBUTEID",
     "ATTRIBUTE_ACTIVE",
-    "ATTRIBUTE_LEVEL",
     "ATTRIBUTE_NAME",
     "ATTRIBUTE_PARENT_ID",
     "ATTRIBUTE_TYPE",
-    "KEYWORD_CONTAINER"
+    "KEYWORD_CONTAINER",
+    "SORTING"
 ];
 var values = [
     vars.get("$field.UID"),
     vars.get("$field.ATTRIBUTE_ACTIVE"),
-    vars.get("$field.ATTRIBUTE_LEVEL"),
     vars.get("$field.ATTRIBUTE_NAME"),
     vars.get("$field.ATTRIBUTE_PARENT_ID"),
     vars.get("$field.ATTRIBUTE_TYPE"),
-    vars.get("$field.KEYWORD_CONTAINER")
+    vars.get("$field.KEYWORD_CONTAINER"),
+    vars.get("$field.SORTING")
 ];
 
 db.insertData("AB_ATTRIBUTE", columns, null, values);
\ No newline at end of file
diff --git a/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js b/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js
index 6740df0d149b19858958fbc5b0c9839a721bd4e1..232f0ee995b3266e82a1fe1174fe7081a4edd02c 100644
--- a/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js
+++ b/entity/Attribute_entity/recordcontainers/jdito/onUpdate.js
@@ -4,23 +4,23 @@ import("system.vars");
 
 var columns = [
     "ATTRIBUTE_ACTIVE",
-    "ATTRIBUTE_LEVEL",
     "ATTRIBUTE_NAME",
     "ATTRIBUTE_PARENT_ID",
     "ATTRIBUTE_TYPE",
-    "KEYWORD_CONTAINER"
+    "KEYWORD_CONTAINER",
+    "SORTING"
 ];
 var values = [
     vars.get("$field.ATTRIBUTE_ACTIVE"),
-    vars.get("$field.ATTRIBUTE_LEVEL"),
     vars.get("$field.ATTRIBUTE_NAME"),
     vars.get("$field.ATTRIBUTE_PARENT_ID"),
     vars.get("$field.ATTRIBUTE_TYPE"),
-    vars.get("$field.KEYWORD_CONTAINER")
+    vars.get("$field.KEYWORD_CONTAINER"),
+    vars.get("$field.SORTING")
 ];
 
 var condition = SqlCondition.begin()
     .andPrepareVars("AB_ATTRIBUTE.AB_ATTRIBUTEID", "$field.UID")
     .build("1=2");
 
-db.updateData("AB_ATTRIBUTE", columns, null, values, conditon);
\ No newline at end of file
+db.updateData("AB_ATTRIBUTE", columns, null, values, condition);
\ No newline at end of file
diff --git a/entity/Communication_entity/Communication_entity.aod b/entity/Communication_entity/Communication_entity.aod
index 8c7e0e773a9a474fae34ce2b9438a725009f5c7f..dc93aa2b68f3689d6028ecb7131f699660e22b52 100644
--- a/entity/Communication_entity/Communication_entity.aod
+++ b/entity/Communication_entity/Communication_entity.aod
@@ -14,6 +14,11 @@
       <mandatory v="true" />
       <valueProcess>%aditoprj%/entity/Communication_entity/entityfields/addr/valueProcess.js</valueProcess>
       <onValidation>%aditoprj%/entity/Communication_entity/entityfields/addr/onValidation.js</onValidation>
+      <onValueChange>%aditoprj%/entity/Communication_entity/entityfields/addr/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+      </onValueChangeTypes>
     </entityField>
     <entityField>
       <name>COMMUNICATIONID</name>
@@ -203,6 +208,15 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
       <name>DATE_EDIT</name>
       <valueProcess>%aditoprj%/entity/Communication_entity/entityfields/date_edit/valueProcess.js</valueProcess>
     </entityField>
+    <entityConsumer>
+      <name>AddressValidator</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AddressValidation_entity</entityName>
+        <fieldName>ZipValidaton</fieldName>
+      </dependency>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Communication_entity/entityfields/addr/onValueChange.js b/entity/Communication_entity/entityfields/addr/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..c6bc6676a2735c9892523a68b9719a4949cbf414
--- /dev/null
+++ b/entity/Communication_entity/entityfields/addr/onValueChange.js
@@ -0,0 +1,40 @@
+import("system.util");
+import("system.net");
+import("system.vars");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+import("system.neon");
+import("PostalAddress_lib");
+
+var addr = vars.get("$this.value");
+
+if (addr)
+{
+    var commMedium = vars.get("$field.MEDIUM_ID");
+    var keywordAttributes = KeywordUtils.getAttributeRelationsByKey(commMedium, $KeywordRegistry.communicationMedium());
+    var commCategory = keywordAttributes.contentType || "TEXT";
+
+    switch (commCategory)
+    {
+        case "TELEPHONE": // Phone
+            if(addr.length > 5) // https://services.aditosoftware.local/services/rest/ws_checkPhoneNumber?Number=017666862716&Country=DE
+            {
+                var url = "https://services.aditosoftware.local/services/rest/ws_checkPhoneNumber";
+                var actionType = "GET";
+
+                var ret = JSON.parse(net.callRestWebserviceBasicAuth(url, actionType, {Number:addr, Country:vars.get("$param.ContactsMainCountry_param")}, null, null, "text/plain", "text/plain", util.DATA_TEXT, util.DATA_TEXT, "Admin", "a", true));
+                if (ret.hasHttpSuccessStatusCode)
+                {
+                    neon.setFieldValue("$field.ADDR", ret.body);
+                }
+                else
+                {
+                    // error handling
+                }
+            }
+            break;
+        default:
+                  
+    }
+    
+}
\ No newline at end of file
diff --git a/entity/Context_entity/Context_entity.aod b/entity/Context_entity/Context_entity.aod
index ae0b115f7aeb9e8496d700685ebd2bf01c2271c8..f1169026a4f400e22cbff3a169ee330dacb486e0 100644
--- a/entity/Context_entity/Context_entity.aod
+++ b/entity/Context_entity/Context_entity.aod
@@ -45,13 +45,13 @@
       </dependencies>
       <children>
         <entityParameter>
-          <name>excludeContexts_param</name>
+          <name>ExclusiveContexts_param</name>
           <expose v="false" />
         </entityParameter>
       </children>
     </entityProvider>
     <entityParameter>
-      <name>excludeContexts_param</name>
+      <name>ExclusiveContexts_param</name>
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
@@ -68,8 +68,9 @@
       </dependencies>
       <children>
         <entityParameter>
-          <name>excludeContexts_param</name>
-          <valueProcess>%aditoprj%/entity/Context_entity/entityfields/activitylinkable/children/excludecontexts_param/valueProcess.js</valueProcess>
+          <name>ExclusiveContexts_param</name>
+          <valueProcess>%aditoprj%/entity/Context_entity/entityfields/activitylinkable/children/exclusivecontexts_param/valueProcess.js</valueProcess>
+          <expose v="false" />
         </entityParameter>
       </children>
     </entityProvider>
@@ -86,8 +87,9 @@
       </dependencies>
       <children>
         <entityParameter>
-          <name>excludeContexts_param</name>
-          <valueProcess>%aditoprj%/entity/Context_entity/entityfields/tasklinkable/children/excludecontexts_param/valueProcess.js</valueProcess>
+          <name>ExclusiveContexts_param</name>
+          <valueProcess>%aditoprj%/entity/Context_entity/entityfields/tasklinkable/children/exclusivecontexts_param/valueProcess.js</valueProcess>
+          <expose v="false" />
         </entityParameter>
       </children>
     </entityProvider>
@@ -96,6 +98,11 @@
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
+    <entityParameter>
+      <name>UseExclusives_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
diff --git a/entity/Context_entity/entityfields/activitylinkable/children/excludecontexts_param/valueProcess.js b/entity/Context_entity/entityfields/activitylinkable/children/exclusivecontexts_param/valueProcess.js
similarity index 100%
rename from entity/Context_entity/entityfields/activitylinkable/children/excludecontexts_param/valueProcess.js
rename to entity/Context_entity/entityfields/activitylinkable/children/exclusivecontexts_param/valueProcess.js
diff --git a/entity/Context_entity/entityfields/tasklinkable/children/excludecontexts_param/valueProcess.js b/entity/Context_entity/entityfields/tasklinkable/children/exclusivecontexts_param/valueProcess.js
similarity index 100%
rename from entity/Context_entity/entityfields/tasklinkable/children/excludecontexts_param/valueProcess.js
rename to entity/Context_entity/entityfields/tasklinkable/children/exclusivecontexts_param/valueProcess.js
diff --git a/entity/Context_entity/recordcontainers/jdito/contentProcess.js b/entity/Context_entity/recordcontainers/jdito/contentProcess.js
index 6ae2f8ad3cb2027b7ca6d81d5c7a803cf78b2663..29391c90234a2a5d1408843663ae6e6c4c1e4abd 100644
--- a/entity/Context_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Context_entity/recordcontainers/jdito/contentProcess.js
@@ -2,9 +2,10 @@ import("system.vars");
 import("system.result");
 import("Context_lib");
 
-var excludeContexts = vars.getString("$param.excludeContexts_param");
+var excludeContexts = vars.getString("$param.ExclusiveContexts_param");
 if (excludeContexts)
     excludeContexts = JSON.parse(excludeContexts);
 var filterContexts = !(vars.exists("$param.GetAllContexts_param") && vars.get("$param.GetAllContexts_param") == "true");
+var useExclusives = vars.exists("$param.UseExclusives_param") && vars.get("$param.UseExclusives_param") == "true";
 
-result.object(ContextUtils.getContexts(filterContexts, excludeContexts));
\ No newline at end of file
+result.object(ContextUtils.getContexts(filterContexts, excludeContexts, useExclusives));
\ No newline at end of file
diff --git a/entity/Contract_entity/Contract_entity.aod b/entity/Contract_entity/Contract_entity.aod
index 8136cd6d2dc78eafd8bc2d5132e4906de381078d..2263146c6e974eabfdda484af29da869dd0de04b 100644
--- a/entity/Contract_entity/Contract_entity.aod
+++ b/entity/Contract_entity/Contract_entity.aod
@@ -149,6 +149,10 @@
           <name>ObjectId_param</name>
           <valueProcess>%aditoprj%/entity/Contract_entity/entityfields/activities/children/objectid_param/valueProcess.js</valueProcess>
         </entityParameter>
+        <entityParameter>
+          <name>PresetLinks_param</name>
+          <valueProcess>%aditoprj%/entity/Contract_entity/entityfields/activities/children/presetlinks_param/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
     </entityConsumer>
     <entityConsumer>
@@ -209,6 +213,7 @@
       <name>MainDocuments</name>
       <title>Maindocuments</title>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Contract_entity/entityfields/maindocuments/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Document_entity</entityName>
@@ -283,6 +288,8 @@
       <title>New activity</title>
       <onActionProcess>%aditoprj%/entity/Contract_entity/entityfields/newactivity/onActionProcess.js</onActionProcess>
       <iconId>NEON:HISTORY</iconId>
+      <tooltip>New activity</tooltip>
+      <tooltipProcess>%aditoprj%/entity/Contract_entity/entityfields/newactivity/tooltipProcess.js</tooltipProcess>
     </entityActionField>
     <entityConsumer>
       <name>Attributes</name>
@@ -330,6 +337,38 @@
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityConsumer>
+      <name>Tasks</name>
+      <title>Tasks</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Contract_entity/entityfields/tasks/stateProcess.js</stateProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Task_entity</entityName>
+        <fieldName>LinkedObjects</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ObjectId_param</name>
+          <valueProcess>%aditoprj%/entity/Contract_entity/entityfields/tasks/children/objectid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>RowId_param</name>
+          <valueProcess>%aditoprj%/entity/Contract_entity/entityfields/tasks/children/rowid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>PresetLinks_param</name>
+          <valueProcess>%aditoprj%/entity/Contract_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityActionField>
+      <name>newTask</name>
+      <fieldType>ACTION</fieldType>
+      <title>New task</title>
+      <onActionProcess>%aditoprj%/entity/Contract_entity/entityfields/newtask/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:TASKS</iconId>
+    </entityActionField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -338,6 +377,7 @@
       <maximumDbRows v="0" />
       <fromClauseProcess>%aditoprj%/entity/Contract_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Contract_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/Contract_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
       <linkInformation>
         <linkInformation>
           <name>78925203-f1c5-4e7e-9424-1a23500c655d</name>
diff --git a/entity/Contract_entity/entityfields/activities/children/presetlinks_param/valueProcess.js b/entity/Contract_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..650bf07d2a39d1c673866de4ef9753f13f3ebed3
--- /dev/null
+++ b/entity/Contract_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
@@ -0,0 +1,13 @@
+import("system.vars");
+import("system.result");
+import("Contact_lib");
+
+var contactId = vars.get("$field.CONTACT_ID");
+var links = [];
+
+if (contactId)
+{
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
+}
+
+result.object(links);
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/maindocuments/stateProcess.js b/entity/Contract_entity/entityfields/maindocuments/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d22f90760a8cc65ddc9c0752d92c11bb48cfe947
--- /dev/null
+++ b/entity/Contract_entity/entityfields/maindocuments/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.result");
+import("system.db");
+import("system.vars");
+import("system.neon");
+import("Sql_lib");
+
+if (0 == db.getBinaryCount("CONTRACT", "DOCUMENT", vars.get("$sys.uid"), SqlUtils.getSystemAlias(), "MAINDOCUMENT"))
+{
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/newactivity/onActionProcess.js b/entity/Contract_entity/entityfields/newactivity/onActionProcess.js
index 41454e813d0f046d85bbb4b17767ee81990519df..41a76599f06b678e7f2a3f89f59d0c5e0c0c3004 100644
--- a/entity/Contract_entity/entityfields/newactivity/onActionProcess.js
+++ b/entity/Contract_entity/entityfields/newactivity/onActionProcess.js
@@ -1,4 +1,13 @@
+import("Contact_lib");
 import("system.vars");
 import("ActivityTask_lib");
 
-ActivityUtils.createNewActivity(vars.getString("$field.CONTRACTID"));
\ No newline at end of file
+var contactId = vars.get("$field.CONTACT_ID");
+var links = [];
+
+if (contactId)
+{
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
+}
+
+ActivityUtils.createNewActivity(vars.getString("$field.CONTRACTID"), links);
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/newactivity/tooltipProcess.js b/entity/Contract_entity/entityfields/newactivity/tooltipProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c71e677c22663c2295e524aa7f3ed3dd571724d7
--- /dev/null
+++ b/entity/Contract_entity/entityfields/newactivity/tooltipProcess.js
@@ -0,0 +1,4 @@
+import("system.translate");
+import("system.result");
+
+result.string(translate.text("New activity"));
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/newtask/onActionProcess.js b/entity/Contract_entity/entityfields/newtask/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7e165e15e52378d09e5723adcb0bedd748d84676
--- /dev/null
+++ b/entity/Contract_entity/entityfields/newtask/onActionProcess.js
@@ -0,0 +1,13 @@
+import("system.vars");
+import("ActivityTask_lib");
+import("Contact_lib");
+
+var contactId = vars.get("$field.CONTACT_ID");
+var links = [];
+
+if (contactId)
+{
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
+}
+
+TaskUtils.createNewTask(vars.get("$field.CONTRACTID"), links);
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/tasks/children/objectid_param/valueProcess.js b/entity/Contract_entity/entityfields/tasks/children/objectid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..008915f61deac19ccdd40fff81701de63eb3b6a2
--- /dev/null
+++ b/entity/Contract_entity/entityfields/tasks/children/objectid_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Context_lib");
+
+result.string(ContextUtils.getCurrentContextId());
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js b/entity/Contract_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..650bf07d2a39d1c673866de4ef9753f13f3ebed3
--- /dev/null
+++ b/entity/Contract_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
@@ -0,0 +1,13 @@
+import("system.vars");
+import("system.result");
+import("Contact_lib");
+
+var contactId = vars.get("$field.CONTACT_ID");
+var links = [];
+
+if (contactId)
+{
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
+}
+
+result.object(links);
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/tasks/children/rowid_param/valueProcess.js b/entity/Contract_entity/entityfields/tasks/children/rowid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..645e7585b75cdbb9e83fb8a6e4c572c100ae70da
--- /dev/null
+++ b/entity/Contract_entity/entityfields/tasks/children/rowid_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.vars");
+import("system.result");
+result.string(vars.get("$field.CONTRACTID"));
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/tasks/stateProcess.js b/entity/Contract_entity/entityfields/tasks/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..f66e3b89565ade4ff0e1b2b982a17f2fd328f02f
--- /dev/null
+++ b/entity/Contract_entity/entityfields/tasks/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("ActivityTask_lib");
+import("Context_lib");
+
+if(TaskUtils.hasTasks(vars.get("$field.CONTRACTID"), ContextUtils.getCurrentContextId()))
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+else
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Contract_entity/recordcontainers/db/orderClauseProcess.js b/entity/Contract_entity/recordcontainers/db/orderClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..07f2fb663f3b7fd1e616836207c8764572658947
--- /dev/null
+++ b/entity/Contract_entity/recordcontainers/db/orderClauseProcess.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("system.db");
+
+result.object({
+    "CONTRACT.CONTRACTCODE": db.DESCENDING
+});
\ No newline at end of file
diff --git a/entity/Employee_entity/Employee_entity.aod b/entity/Employee_entity/Employee_entity.aod
index b519ec2a71e5ead5066c0fcbbae644d258205ef9..a6c0196547b9d746c8b1adc4f40ada9562048f55 100644
--- a/entity/Employee_entity/Employee_entity.aod
+++ b/entity/Employee_entity/Employee_entity.aod
@@ -22,7 +22,6 @@
       <name>TITLE</name>
       <title>Username</title>
       <mandatory v="true" />
-      <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/title/valueProcess.js</valueProcess>
       <onValidation>%aditoprj%/entity/Employee_entity/entityfields/title/onValidation.js</onValidation>
     </entityField>
     <entityField>
@@ -38,11 +37,13 @@
     <entityField>
       <name>FIRSTNAME</name>
       <title>Firstname</title>
+      <state>READONLY</state>
     </entityField>
     <entityField>
       <name>LASTNAME</name>
       <title>Lastname</title>
       <mandatory v="false" />
+      <state>READONLY</state>
     </entityField>
     <entityField>
       <name>ISACTIVE</name>
@@ -145,7 +146,9 @@
     <entityField>
       <name>DEPARTMENT</name>
       <title>Department</title>
-      <state>INVISIBLE</state>
+      <consumer>Departments</consumer>
+      <mandatory v="true" />
+      <displayValueProcess>%aditoprj%/entity/Employee_entity/entityfields/department/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>DESCRIPTION</name>
@@ -256,6 +259,25 @@
       <name>TITLE_ORIGINAL</name>
       <searchable v="false" />
     </entityField>
+    <entityConsumer>
+      <name>Departments</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Attribute_entity</entityName>
+        <fieldName>AttributeParent</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AttrParentId_param</name>
+          <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/departments/children/attrparentid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>AttrParentType_param</name>
+          <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/departments/children/attrparenttype_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
@@ -277,7 +299,7 @@
         <element>DESCRIPTION.value</element>
         <element>CONTACT_ID.value</element>
         <element>CONTACT_ID.displayValue</element>
-        <element>STORED_SELECTIONS.value</element>
+        <element>DEPARTMENT.value</element>
       </recordFields>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/Employee_entity/entityfields/contact_id/onValueChange.js b/entity/Employee_entity/entityfields/contact_id/onValueChange.js
index 8b8af980eacaa7cf7553115592be5a360dd3406b..26cac2df6b6b30fe19726b66e078f286f4d7400b 100644
--- a/entity/Employee_entity/entityfields/contact_id/onValueChange.js
+++ b/entity/Employee_entity/entityfields/contact_id/onValueChange.js
@@ -1,25 +1,28 @@
-import("Communication_lib");
-import("Entity_lib");
-import("system.result");
-import("system.db");
-import("system.neon");
-import("system.vars");
-import("Sql_lib");
-
-var contactId = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.CONTACT_ID"));
-if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
-    && contactId)
-{
-    var name = db.array(
-        db.ROW, 
-        SqlCondition.begin()
-            .andPrepare("CONTACT.CONTACTID", contactId)
-            .buildSql("select FIRSTNAME, LASTNAME, (" + CommUtil.getStandardSubSqlMail() + ") from PERSON join CONTACT on CONTACT.PERSON_ID = PERSON.PERSONID")
-    );
-    
-    neon.setFieldValues({
-        "$field.FIRSTNAME" : name[0] || "",
-        "$field.LASTNAME" : name[1] || "",
-        "$field.EMAIL_ADDRESS" : name[2] || ""
-    });
+import("Communication_lib");
+import("Entity_lib");
+import("system.result");
+import("system.db");
+import("system.neon");
+import("system.vars");
+import("Sql_lib");
+import("Employee_lib");
+
+var contactId = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.CONTACT_ID"));
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+    && contactId)
+{
+    var name = db.array(
+        db.ROW, 
+        SqlCondition.begin()
+            .andPrepare("CONTACT.CONTACTID", contactId)
+            .buildSql("select FIRSTNAME, LASTNAME, (" + CommUtil.getStandardSubSqlMail() + ") from PERSON join CONTACT on CONTACT.PERSON_ID = PERSON.PERSONID")
+    );
+    var username = EmployeeUtils.generateUserName(name[0], name[1], "f.l+");
+    
+    neon.setFieldValues({
+        "$field.FIRSTNAME" : name[0] || "",
+        "$field.LASTNAME" : name[1] || "",
+        "$field.EMAIL_ADDRESS" : name[2] || "",
+        "$field.TITLE" : username
+    });
 }
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/department/displayValueProcess.js b/entity/Employee_entity/entityfields/department/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..054924b0a34bb4c52b0b3ffe2648ecfedb2aedf7
--- /dev/null
+++ b/entity/Employee_entity/entityfields/department/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("system.vars");
+import("Attribute_lib");
+
+result.string(AttributeUtil.getFullAttributeName(vars.get("$field.DEPARTMENT")));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/departments/children/attrparentid_param/valueProcess.js b/entity/Employee_entity/entityfields/departments/children/attrparentid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..69d5189f033b57b9df7bc2b150851c4785abfeee
--- /dev/null
+++ b/entity/Employee_entity/entityfields/departments/children/attrparentid_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string("87d4ff5b-0ab6-4534-be26-76c6ef486072");
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/departments/children/attrparenttype_param/valueProcess.js b/entity/Employee_entity/entityfields/departments/children/attrparenttype_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..67a485769c386a03ada03f1ecb2c774b87fcd091
--- /dev/null
+++ b/entity/Employee_entity/entityfields/departments/children/attrparenttype_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+import("Attribute_lib");
+result.string($AttributeTypes.VOID);
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js b/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js
index 21bbfcda32c97039f276ebb89db9eecaf6e21db1..725e579e084bd3072e07f85f0abede7bb0182b1f 100644
--- a/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js
+++ b/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js
@@ -26,5 +26,3 @@ if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.r
             
     result.object(addresses);
 }
-else
-    result.object([]);
diff --git a/entity/Employee_entity/entityfields/title/valueProcess.js b/entity/Employee_entity/entityfields/title/valueProcess.js
deleted file mode 100644
index 058b37c3c1c367ab44f6212d3e684707bb3a398b..0000000000000000000000000000000000000000
--- a/entity/Employee_entity/entityfields/title/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.neon");
-import("system.vars");
-import("system.result");
-import("Employee_lib");
-
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT && !vars.get("$field.TITLE"))
-    result.string(EmployeeUtils.generateUserName(vars.get("$field.FIRSTNAME"), vars.get("$field.LASTNAME"), "f.l+"));
\ No newline at end of file
diff --git a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
index f40cbd25c020ec69598596d91c051cac0ab0c538..ecccde702a88fb72646dd5d94ffd3917a22bec48 100644
--- a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
@@ -1,11 +1,10 @@
+import("Attribute_lib");
 import("system.vars");
 import("system.result");
 import("system.tools");
 import("Util_lib");
 import("Contact_lib");
 import("JditoFilter_lib");
-import("Employee_lib");
-
 var users;
 if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
     users = [tools.getUser(vars.get("$local.idvalues"), tools.PROFILE_FULL)];
@@ -31,16 +30,16 @@ users = users.map(function (user)
         user[tools.DESCRIPTION],
         user[tools.PARAMS][tools.CONTACTID],
         ContactUtils.getTitleByContactId(user[tools.PARAMS][tools.CONTACTID]), //TODO: get the names more efficiently
-        user[tools.PARAMS][tools.FRAME_STOREDSEARCHES]
+        user[tools.PARAMS].department
     ];
 });
 
 var filter = vars.exists("$local.filter") && vars.get("$local.filter"); 
 
 //TODO: this is a workaround that filters the records manually, it should be possible to filter the users with a tools.* method
-users = JditoFilterUtils.filterRecords(["UID", "TITLE", "TITLE_ORIGINAL", "ISACTIVE", "FIRSTNAME", "LASTNAME", "EMAIL_ADDRESS", "DESCRIPTION", "CONTACT_ID", ""], users, filter);
+users = JditoFilterUtils.filterRecords(["UID", "TITLE", "TITLE_ORIGINAL", "ISACTIVE", "FIRSTNAME", "LASTNAME", "EMAIL_ADDRESS", "DESCRIPTION", "CONTACT_ID", "", "DEPARTMENT"], users, filter);
 
 
 ArrayUtils.sort2d(users, 0, true, false); //sort by username
 
-result.object(users);
\ No newline at end of file
+result.object(users);
diff --git a/entity/Employee_entity/recordcontainers/jdito/onInsert.js b/entity/Employee_entity/recordcontainers/jdito/onInsert.js
index 9d7e0fddbe405e9a445b8373a512eec792dc929c..5d7b9281709e2d6896f6b5b126ccfd959089cf40 100644
--- a/entity/Employee_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/Employee_entity/recordcontainers/jdito/onInsert.js
@@ -12,6 +12,7 @@ params[tools.CALENDARID] = vars.get("$field.EMAIL_ADDRESS");
 params[tools.CONTACTID] = vars.get("$field.CONTACT_ID");
 params[tools.DESCRIPTION] = vars.get("$field.DESCRIPTION");
 params[tools.ISACTIVE] = vars.get("$field.ISACTIVE");
+params.department = vars.get("$field.DEPARTMENT");
 
 user[tools.TITLE] = vars.get("$field.TITLE");
 user[tools.PARAMS] = params;
diff --git a/entity/Employee_entity/recordcontainers/jdito/onUpdate.js b/entity/Employee_entity/recordcontainers/jdito/onUpdate.js
index 6402be1fa563698440eecb3c0421427a58406644..ccc3af0949642f34fef08f954f3ee0a71b29f9fb 100644
--- a/entity/Employee_entity/recordcontainers/jdito/onUpdate.js
+++ b/entity/Employee_entity/recordcontainers/jdito/onUpdate.js
@@ -27,6 +27,7 @@ user[tools.PARAMS][tools.EMAIL] = vars.get("$field.EMAIL_ADDRESS");
 user[tools.PARAMS][tools.CALENDARID] = vars.get("$field.EMAIL_ADDRESS");
 user[tools.PARAMS][tools.CONTACTID] = vars.get("$field.CONTACT_ID");
 user[tools.PARAMS][tools.DESCRIPTION] = vars.get("$field.DESCRIPTION");
+user[tools.PARAMS].department = vars.get("$field.DEPARTMENT");
 
 if (vars.exists("$param.PasswordChange_param") && vars.get("$param.PasswordChange_param") 
     && vars.get("$field.PASSWORD") == vars.get("$field.CONFIRM_PASSWORD"))
diff --git a/entity/ObjectTree_entity/ObjectTree_entity.aod b/entity/ObjectTree_entity/ObjectTree_entity.aod
index 732a7815ac7d2253db4ed90aa3965728076c95b4..b96830a64744f5d8ae89cf6b30f531e2ed44ffb9 100644
--- a/entity/ObjectTree_entity/ObjectTree_entity.aod
+++ b/entity/ObjectTree_entity/ObjectTree_entity.aod
@@ -67,6 +67,7 @@
     <entityField>
       <name>TITLE</name>
       <title>Object</title>
+      <linkedContextProcess>%aditoprj%/entity/ObjectTree_entity/entityfields/title/linkedContextProcess.js</linkedContextProcess>
       <searchable v="false" />
     </entityField>
     <entityField>
@@ -106,7 +107,7 @@
     </entityField>
     <entityField>
       <name>TARGET_ID</name>
-      <title>Relation</title>
+      <title>Object</title>
       <consumer>Objects</consumer>
       <linkedContextProcess>%aditoprj%/entity/ObjectTree_entity/entityfields/target_id/linkedContextProcess.js</linkedContextProcess>
       <mandatory v="true" />
diff --git a/entity/ObjectTree_entity/entityfields/title/linkedContextProcess.js b/entity/ObjectTree_entity/entityfields/title/linkedContextProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c493945bed68e5998cc4a2e8f2f18aa500683f72
--- /dev/null
+++ b/entity/ObjectTree_entity/entityfields/title/linkedContextProcess.js
@@ -0,0 +1,3 @@
+import("system.vars");
+import("system.result");
+result.string(vars.get("$field.TARGET_CONTEXT"));
\ No newline at end of file
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index 3e594fdf6c0dd8614fd4b85533e42f1ba771bb8c..bff3e3c28f7425f46588ae40fc1c4effad5385b1 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -310,6 +310,7 @@
     <entityConsumer>
       <name>MainDocuments</name>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/maindocuments/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Document_entity</entityName>
@@ -359,9 +360,12 @@
       <title>Choose address</title>
       <consumer>PossibleAddresses</consumer>
       <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/chosenaddress/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/chosenaddress/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/chosenaddress/displayValueProcess.js</displayValueProcess>
       <onValueChange>%aditoprj%/entity/Offer_entity/entityfields/chosenaddress/onValueChange.js</onValueChange>
       <onValueChangeTypes>
         <element>MASK</element>
+        <element>PROCESS</element>
       </onValueChangeTypes>
     </entityField>
     <entityConsumer>
@@ -724,6 +728,7 @@
       <maximumDbRows v="0" />
       <fromClauseProcess>%aditoprj%/entity/Offer_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Offer_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/Offer_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
       <onDBInsert>%aditoprj%/entity/Offer_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <onDBDelete>%aditoprj%/entity/Offer_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
diff --git a/entity/Offer_entity/entityfields/chosenaddress/displayValueProcess.js b/entity/Offer_entity/entityfields/chosenaddress/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..698ddd21921ba4623f9eeae0c1a61f579da714f5
--- /dev/null
+++ b/entity/Offer_entity/entityfields/chosenaddress/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("PostalAddress_lib");
+import("system.result");
+
+result.string(AddressUtils.getFormattedOnlineAddressById(vars.get("$this.value")))
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/chosenaddress/valueProcess.js b/entity/Offer_entity/entityfields/chosenaddress/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6ebcf9a49b9f2a8d6f2a5b7f54b38fb6a2481fce
--- /dev/null
+++ b/entity/Offer_entity/entityfields/chosenaddress/valueProcess.js
@@ -0,0 +1,11 @@
+import("Contact_lib");
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT) && !vars.get("$field.ADDRESS"))
+{
+    var defaultAddressId = ContactUtils.getDefaultAddressId(vars.get("$field.CONTACT_ID"));
+    if (defaultAddressId)
+        result.string(defaultAddressId);
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/maindocuments/stateProcess.js b/entity/Offer_entity/entityfields/maindocuments/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c640c079ddca224a84ea8fe108d10d39d0f926c
--- /dev/null
+++ b/entity/Offer_entity/entityfields/maindocuments/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.result");
+import("system.db");
+import("system.vars");
+import("system.neon");
+import("Sql_lib");
+
+if (0 == db.getBinaryCount("OFFER", "DOCUMENT", vars.get("$sys.uid"), SqlUtils.getSystemAlias(), "MAINDOCUMENT"))
+{
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/recordcontainers/db/orderClauseProcess.js b/entity/Offer_entity/recordcontainers/db/orderClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1208b5ef06821f02683cfabf23bfc18c89d3d934
--- /dev/null
+++ b/entity/Offer_entity/recordcontainers/db/orderClauseProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.db");
+
+result.object({
+    "OFFER.OFFERCODE": db.DESCENDING,
+    "OFFER.VERSNR": db.DESCENDING
+});
\ No newline at end of file
diff --git a/entity/Order_entity/Order_entity.aod b/entity/Order_entity/Order_entity.aod
index 92de79ba4fa97d6419751e7271a6bc246005e0b2..819dbb9a4ddb11b39cee9797f1bd0b85d3c349a6 100644
--- a/entity/Order_entity/Order_entity.aod
+++ b/entity/Order_entity/Order_entity.aod
@@ -263,6 +263,7 @@
     <entityConsumer>
       <name>MainDocuments</name>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Order_entity/entityfields/maindocuments/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Document_entity</entityName>
@@ -424,6 +425,7 @@
       <name>Tasks</name>
       <title>Tasks</title>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Order_entity/entityfields/tasks/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Task_entity</entityName>
@@ -452,6 +454,7 @@
       <maximumDbRows v="0" />
       <fromClauseProcess>%aditoprj%/entity/Order_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Order_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/Order_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
       <onDBInsert>%aditoprj%/entity/Order_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <onDBDelete>%aditoprj%/entity/Order_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
diff --git a/entity/Order_entity/entityfields/language/displayValueProcess.js b/entity/Order_entity/entityfields/language/displayValueProcess.js
index 528cfe6e1659e4d9d720cd96594f2aa5be7ac58d..d60342f7264e2cb7c41a787563070a80c827eb53 100644
--- a/entity/Order_entity/entityfields/language/displayValueProcess.js
+++ b/entity/Order_entity/entityfields/language/displayValueProcess.js
@@ -1,15 +1,15 @@
-import("system.db");
-import("system.translate");
-import("system.result");
-import("system.vars");
-import("Sql_lib");
-
-if (vars.exists("$param.OrderLanguage_param")) 
-{
-    var iso3 = vars.get("$param.OrderLanguage_param");
-    var latinName = db.cell(SqlCondition.begin()
-        .andPrepare("AB_LANGUAGE.ISO3", iso3)
-        .buildSql("select NAME_LATIN from AB_LANGUAGE", "1=0"));
-    latinName = translate.text(latinName);
-    result.string(latinName);
+import("system.db");
+import("system.translate");
+import("system.result");
+import("system.vars");
+import("Sql_lib");
+
+if (vars.exists("$param.OrderLanguage_param") && vars.get("$param.OrderLanguage_param")) 
+{
+    var iso3 = vars.get("$param.OrderLanguage_param");
+    var latinName = db.cell(SqlCondition.begin()
+        .andPrepare("AB_LANGUAGE.ISO3", iso3)
+        .buildSql("select NAME_LATIN from AB_LANGUAGE", "1=0"));
+    latinName = translate.text(latinName);
+    result.string(latinName);
 }
\ No newline at end of file
diff --git a/entity/Order_entity/entityfields/maindocuments/stateProcess.js b/entity/Order_entity/entityfields/maindocuments/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..9104233a61bb17be448f09b778adfa11c61162de
--- /dev/null
+++ b/entity/Order_entity/entityfields/maindocuments/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.result");
+import("system.db");
+import("system.vars");
+import("system.neon");
+import("Sql_lib");
+
+if (0 == db.getBinaryCount("SALESORDER", "DOCUMENT", vars.get("$sys.uid"), SqlUtils.getSystemAlias(), "MAINDOCUMENT"))
+{
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/Order_entity/entityfields/tasks/stateProcess.js b/entity/Order_entity/entityfields/tasks/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..712bf69e9725d83a9d77d7569b0b83917e404d8e
--- /dev/null
+++ b/entity/Order_entity/entityfields/tasks/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("ActivityTask_lib");
+import("Context_lib");
+
+if(TaskUtils.hasTasks(vars.get("$field.SALESORDERID"), ContextUtils.getCurrentContextId()))
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+else
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Order_entity/recordcontainers/db/orderClauseProcess.js b/entity/Order_entity/recordcontainers/db/orderClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..0a999f92f57acc25ef6cab045a745b37f1cac1ea
--- /dev/null
+++ b/entity/Order_entity/recordcontainers/db/orderClauseProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.db");
+
+result.object({
+    "SALESORDER.SALESORDERCODE": db.DESCENDING,
+    "SALESORDER.VERSNR": db.DESCENDING
+});
\ No newline at end of file
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 0d7643173af7613e0f3e739c5e449d858d44cbed..417b672dbf42b8b88cec9db792d2ef1c4d61c3b0 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -96,9 +96,6 @@
           <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/contact/children/orgid_param/valueProcess.js</valueProcess>
           <triggerRecalculation v="true" />
         </entityParameter>
-        <entityParameter>
-          <name>ContactId_param</name>
-        </entityParameter>
       </children>
     </entityConsumer>
     <entityFieldGroup>
diff --git a/entity/Organisation_entity/recordcontainers/db/orderClauseProcess.js b/entity/Organisation_entity/recordcontainers/db/orderClauseProcess.js
index 4e5e1db97f786170e23f3951f9bf75bcd0f5cadd..effa3a63f928c2539626177c5bd96c67de96ba78 100644
--- a/entity/Organisation_entity/recordcontainers/db/orderClauseProcess.js
+++ b/entity/Organisation_entity/recordcontainers/db/orderClauseProcess.js
@@ -2,6 +2,5 @@ import("system.result");
 import("system.db");
 
 result.object({
-    "ORGANISATION.CUSTOMERCODE": db.ASCENDING,
     "ORGANISATION.NAME": db.ASCENDING
     });
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js b/entity/Person_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js
index 4170a76c71fa1e8732debf6ab2d719341a786d1a..babb0e1760093b90e065d2202e4c0f871f3b6940 100644
--- a/entity/Person_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.PERSONID"));
+result.string(vars.get("$field.CONTACTID"));
diff --git a/entity/Person_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js b/entity/Person_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js
index 07081dc34f62162ad93f6b7b28f0caeb67dc283e..3d9e27e02fddb7859929d550e3fec80b3bdbf585 100644
--- a/entity/Person_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.PERSONID"));
+result.string(vars.get("$field.CONTACTID"));
diff --git a/entity/Person_entity/entityfields/objecttrees/children/objectid_param/valueProcess.js b/entity/Person_entity/entityfields/objecttrees/children/objectid_param/valueProcess.js
index f8f18bbb44f53cdf36e79af50410f0ccf70c2585..821415ae694dd9c3d98a7703f4c59b81a37f524b 100644
--- a/entity/Person_entity/entityfields/objecttrees/children/objectid_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/objecttrees/children/objectid_param/valueProcess.js
@@ -1,3 +1,3 @@
 import("system.vars");
 import("system.result");
-result.string(vars.get("$field.PERSON_ID"));
\ No newline at end of file
+result.string(vars.get("$field.CONTACTID"));
\ No newline at end of file
diff --git a/entity/Product_entity/Product_entity.aod b/entity/Product_entity/Product_entity.aod
index f8474184d24ac58559ce37fe1aa4455afc5f16f4..124f95ac4fada61bc328689d1334ce3f86d6f39b 100644
--- a/entity/Product_entity/Product_entity.aod
+++ b/entity/Product_entity/Product_entity.aod
@@ -242,6 +242,7 @@
     <entityConsumer>
       <name>MainDocuments</name>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Product_entity/entityfields/maindocuments/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Document_entity</entityName>
@@ -458,6 +459,7 @@
       <maximumDbRows v="0" />
       <fromClauseProcess>%aditoprj%/entity/Product_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Product_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/Product_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
       <onDBUpdate>%aditoprj%/entity/Product_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
       <onDBDelete>%aditoprj%/entity/Product_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
diff --git a/entity/Product_entity/entityfields/maindocuments/stateProcess.js b/entity/Product_entity/entityfields/maindocuments/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..72587c51cbebb63a1d3ec977426cc04e3ede0ecf
--- /dev/null
+++ b/entity/Product_entity/entityfields/maindocuments/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.result");
+import("system.db");
+import("system.vars");
+import("system.neon");
+import("Sql_lib");
+
+if (0 == db.getBinaryCount("PRODUCT", "DOCUMENT", vars.get("$sys.uid"), SqlUtils.getSystemAlias(), "MAINDOCUMENT"))
+{
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/Product_entity/recordcontainers/db/orderClauseProcess.js b/entity/Product_entity/recordcontainers/db/orderClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..9413afd74b16e991bf4cfb744a9d335e1648c839
--- /dev/null
+++ b/entity/Product_entity/recordcontainers/db/orderClauseProcess.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("system.db");
+
+result.object({
+    "PRODUCT.PRODUCTCODE": db.ASCENDING
+});
\ No newline at end of file
diff --git a/entity/Productprice_entity/Productprice_entity.aod b/entity/Productprice_entity/Productprice_entity.aod
index 6d4fd26abd696730231d506e3b47cf0ec5dda513..b346d7223660af95be51618339e58487e621732e 100644
--- a/entity/Productprice_entity/Productprice_entity.aod
+++ b/entity/Productprice_entity/Productprice_entity.aod
@@ -50,7 +50,7 @@
       <consumer>Products</consumer>
       <linkedContext>Product</linkedContext>
       <mandatory v="true" />
-      <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/Productprice_entity/entityfields/product_id/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/product_id/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Productprice_entity/entityfields/product_id/displayValueProcess.js</displayValueProcess>
     </entityField>
diff --git a/entity/Productprice_entity/entityfields/product_id/stateProcess.js b/entity/Productprice_entity/entityfields/product_id/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..07518244a575e451e071fc07387960724911c5e3
--- /dev/null
+++ b/entity/Productprice_entity/entityfields/product_id/stateProcess.js
@@ -0,0 +1,12 @@
+import("system.vars");
+import("system.result");
+import("system.neon");
+
+if(vars.exists("$param.ProductId_param") && vars.get("$param.ProductId_param"))
+{
+    result.string(neon.COMPONENTSTATE_DISABLED);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_AUTO);
+}
\ No newline at end of file
diff --git a/entity/SalesprojectAnalyses_entity/recordcontainers/jdito/contentProcess.js b/entity/SalesprojectAnalyses_entity/recordcontainers/jdito/contentProcess.js
index e65797a6adb0da41ded6a02f5b1ba74a45d3c7d3..0eb24b9e842ca3435a90aaf55a691acaa95586ba 100644
--- a/entity/SalesprojectAnalyses_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/SalesprojectAnalyses_entity/recordcontainers/jdito/contentProcess.js
@@ -1,34 +1,34 @@
-import("system.vars");
-import("system.datetime");
-import("system.db");
-import("system.result");
-import("system.translate");
-import("Data_lib");
-import("Keyword_lib");
-import("Money_lib");
-import("KeywordRegistry_basic");
-    
-// load data
-
-var phases = db.table("select KEYID, AB_KEYWORD_ENTRY.TITLE, count(PHASE), AB_KEYWORD_ENTRY.SORTING \n\
-from SALESPROJECT join AB_KEYWORD_ENTRY on KEYID = PHASE and  CONTAINER  = 'SalesprojectPhase' and SORTING <> 7 \n\
-group by KEYID, AB_KEYWORD_ENTRY.TITLE, AB_KEYWORD_ENTRY.SORTING order by SORTING");
-
-for(i = 0; i < phases.length; i++){
-    if(phases[i][1] == "${SALESPROJECT_OFFER}"){
-        phases[i][1] = "Offer";
-    }   
-}
-
-   
-result.object(phases);
-
-
-
-
-
-
-
-
-
-
+import("system.logging");
+import("system.vars");
+import("system.datetime");
+import("system.db");
+import("system.result");
+import("system.translate");
+import("Data_lib");
+import("Keyword_lib");
+import("Money_lib");
+import("KeywordRegistry_basic");
+    
+// load data
+
+var phases = db.table("select KEYID, AB_KEYWORD_ENTRY.TITLE, count(PHASE), AB_KEYWORD_ENTRY.SORTING \n\
+from SALESPROJECT join AB_KEYWORD_ENTRY on KEYID = PHASE and  CONTAINER  = 'SalesprojectPhase' and SORTING <> 7 \n\
+group by KEYID, AB_KEYWORD_ENTRY.TITLE, AB_KEYWORD_ENTRY.SORTING order by SORTING");
+
+for(i = 0; i < phases.length; i++){
+    if(phases[i][1] == "${SALESPROJECT_OFFER}"){
+        phases[i][1] = "Offer";
+    }   
+}
+ 
+result.object(phases);
+
+
+
+
+
+
+
+
+
+
diff --git a/entity/SalesprojectCompetition_entity/entityfields/image/valueProcess.js b/entity/SalesprojectCompetition_entity/entityfields/image/valueProcess.js
index d071e384e95b26e1b3013d43ac5c4f45ae4cc579..dac257b091616b1d7320eec46615813728b6faf0 100644
--- a/entity/SalesprojectCompetition_entity/entityfields/image/valueProcess.js
+++ b/entity/SalesprojectCompetition_entity/entityfields/image/valueProcess.js
@@ -1,4 +1,4 @@
-import("system.vars");
-import("system.result");
-
+import("system.vars");
+import("system.result");
+
 result.string("TEXT:" + vars.getString("$field.ORGANISATION_NAME"));
\ No newline at end of file
diff --git a/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod b/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod
index d390c31108e434406bb56161e32cbe4d650f5a9f..34def483f6a2474a1db42ba55b59108fe7dfb5a6 100644
--- a/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod
+++ b/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.1">
   <name>SalesprojectMilestone_entity</name>
-  <title>Milestones</title>
+  <title></title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <titleProcess>%aditoprj%/entity/SalesprojectMilestone_entity/titleProcess.js</titleProcess>
   <recordContainer>db</recordContainer>
   <entityFields>
     <entityProvider>
@@ -41,9 +42,9 @@
     </entityField>
     <entityField>
       <name>VALUE</name>
-      <title>Milestone</title>
       <consumer>Keywords</consumer>
       <mandatory v="true" />
+      <titleProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/value/titleProcess.js</titleProcess>
       <displayValueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/value/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityParameter>
@@ -57,19 +58,15 @@
       <name>SalesprojectMilestones</name>
       <fieldType>DEPENDENCY_IN</fieldType>
       <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>b05e2bdf-5d8b-4ba2-8dba-a8560c255470</name>
-          <entityName>Salesproject_entity</entityName>
-          <fieldName>SalesprojectMilestones</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
       <children>
         <entityParameter>
           <name>SalesprojectId_param</name>
           <expose v="true" />
         </entityParameter>
+        <entityParameter>
+          <name>Type_param</name>
+          <expose v="false" />
+        </entityParameter>
       </children>
     </entityProvider>
     <entityField>
@@ -95,6 +92,48 @@
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityParameter>
+      <name>Type_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>StateMilestones</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>da87708b-e998-4694-81ae-d0068f789a89</name>
+          <entityName>Salesproject_entity</entityName>
+          <fieldName>SalesprojectStateMilestones</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/statemilestones/children/type_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityProvider>
+      <name>PhaseMilestones</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>b132527b-990c-416a-b2d6-ddbe6f4397e2</name>
+          <entityName>Salesproject_entity</entityName>
+          <fieldName>SalesprojectPhaseMilestones</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/phasemilestones/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/SalesprojectMilestone_entity/entityfields/phasemilestones/children/type_param/valueProcess.js b/entity/SalesprojectMilestone_entity/entityfields/phasemilestones/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..5b8076cef459fb0d8e18d6aac23c9b0172112560
--- /dev/null
+++ b/entity/SalesprojectMilestone_entity/entityfields/phasemilestones/children/type_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.string("SalesprojectPhase");
\ No newline at end of file
diff --git a/entity/SalesprojectMilestone_entity/entityfields/statemilestones/children/type_param/valueProcess.js b/entity/SalesprojectMilestone_entity/entityfields/statemilestones/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a1b3322838a6b972bd777abd8ce16e816d412d3
--- /dev/null
+++ b/entity/SalesprojectMilestone_entity/entityfields/statemilestones/children/type_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.string("SalesprojectState");
\ No newline at end of file
diff --git a/entity/SalesprojectMilestone_entity/entityfields/value/titleProcess.js b/entity/SalesprojectMilestone_entity/entityfields/value/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..658e8105ef136f6e374f80363f1c1d0ace5fba7e
--- /dev/null
+++ b/entity/SalesprojectMilestone_entity/entityfields/value/titleProcess.js
@@ -0,0 +1,10 @@
+import("system.vars");
+import("system.translate");
+import("system.result");
+
+if (vars.exists("$field.TYPE") && vars.get("$field.TYPE"))
+{
+    result.string(translate.text("Milestones") + " " + translate.text(vars.get("$field.TYPE")));
+}
+else
+    result.string(translate.text("Milestones"));
\ No newline at end of file
diff --git a/entity/SalesprojectMilestone_entity/recordcontainers/db/conditionProcess.js b/entity/SalesprojectMilestone_entity/recordcontainers/db/conditionProcess.js
index 7711ad471a8ed5e095a39703339fdedc6bc6153f..e0aa733ba874bae3fa610a4f560592836dc9ba07 100644
--- a/entity/SalesprojectMilestone_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/SalesprojectMilestone_entity/recordcontainers/db/conditionProcess.js
@@ -3,8 +3,9 @@ import("system.result");
 import("system.vars");
 import("Sql_lib");
 
-var cond = new SqlCondition();
-cond.andPrepareVars("SALESPROJECT_MILESTONE.SALESPROJECT_ID", "$param.SalesprojectId_param");
+var cond = SqlCondition.begin()
+                       .andPrepareVars("SALESPROJECT_MILESTONE.SALESPROJECT_ID", "$param.SalesprojectId_param")
+                       .andPrepareVars("SALESPROJECT_MILESTONE.TYPE", "$param.Type_param");
 
 //TODO: use a preparedCondition when available #1030812 #1034026
 result.string(db.translateCondition(cond.build("1 = 1")));
\ No newline at end of file
diff --git a/entity/SalesprojectMilestone_entity/titleProcess.js b/entity/SalesprojectMilestone_entity/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..658e8105ef136f6e374f80363f1c1d0ace5fba7e
--- /dev/null
+++ b/entity/SalesprojectMilestone_entity/titleProcess.js
@@ -0,0 +1,10 @@
+import("system.vars");
+import("system.translate");
+import("system.result");
+
+if (vars.exists("$field.TYPE") && vars.get("$field.TYPE"))
+{
+    result.string(translate.text("Milestones") + " " + translate.text(vars.get("$field.TYPE")));
+}
+else
+    result.string(translate.text("Milestones"));
\ No newline at end of file
diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod
index a7c8206d47e7428825c0f1c5f304530f20e5f385..371cfd5b7fd35cde820f97552e8c59885a2c164d 100644
--- a/entity/Salesproject_entity/Salesproject_entity.aod
+++ b/entity/Salesproject_entity/Salesproject_entity.aod
@@ -135,18 +135,18 @@
       </children>
     </entityConsumer>
     <entityConsumer>
-      <name>SalesprojectMilestones</name>
+      <name>SalesprojectPhaseMilestones</name>
       <title>Milestone</title>
       <fieldType>DEPENDENCY_OUT</fieldType>
       <dependency>
         <name>dependency</name>
         <entityName>SalesprojectMilestone_entity</entityName>
-        <fieldName>SalesprojectMilestones</fieldName>
+        <fieldName>PhaseMilestones</fieldName>
       </dependency>
       <children>
         <entityParameter>
           <name>SalesprojectId_param</name>
-          <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/salesprojectmilestones/children/salesprojectid_param/valueProcess.js</valueProcess>
+          <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/salesprojectphasemilestones/children/salesprojectid_param/valueProcess.js</valueProcess>
           <triggerRecalculation v="true" />
         </entityParameter>
       </children>
@@ -348,6 +348,7 @@
     <entityConsumer>
       <name>MainDocuments</name>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <stateProcess>%aditoprj%/entity/Salesproject_entity/entityfields/maindocuments/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>Document_entity</entityName>
@@ -546,6 +547,15 @@
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
+    <entityConsumer>
+      <name>SalesprojectStateMilestones</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>SalesprojectMilestone_entity</entityName>
+        <fieldName>StateMilestones</fieldName>
+      </dependency>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -553,6 +563,7 @@
       <alias>Data_alias</alias>
       <fromClauseProcess>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
       <onDBInsert>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <onDBUpdate>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
       <onDBDelete>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
diff --git a/entity/Salesproject_entity/entityfields/maindocuments/stateProcess.js b/entity/Salesproject_entity/entityfields/maindocuments/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..08207c042cac0a6a659b044a2572c39de7550047
--- /dev/null
+++ b/entity/Salesproject_entity/entityfields/maindocuments/stateProcess.js
@@ -0,0 +1,14 @@
+import("system.result");
+import("system.db");
+import("system.vars");
+import("system.neon");
+import("Sql_lib");
+
+if (0 == db.getBinaryCount("SALESPROJECT", "DOCUMENT", vars.get("$sys.uid"), SqlUtils.getSystemAlias(), "MAINDOCUMENT"))
+{
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
\ No newline at end of file
diff --git a/entity/Salesproject_entity/entityfields/salesprojectmilestones/children/salesprojectid_param/valueProcess.js b/entity/Salesproject_entity/entityfields/salesprojectphasemilestones/children/salesprojectid_param/valueProcess.js
similarity index 100%
rename from entity/Salesproject_entity/entityfields/salesprojectmilestones/children/salesprojectid_param/valueProcess.js
rename to entity/Salesproject_entity/entityfields/salesprojectphasemilestones/children/salesprojectid_param/valueProcess.js
diff --git a/entity/Salesproject_entity/recordcontainers/db/orderClauseProcess.js b/entity/Salesproject_entity/recordcontainers/db/orderClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..319594ed7e2cd8b1860d7426852261155c9cf13b
--- /dev/null
+++ b/entity/Salesproject_entity/recordcontainers/db/orderClauseProcess.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("system.db");
+
+result.object({
+    "SALESPROJECT.PROJECTTITLE": db.ASCENDING
+});
\ No newline at end of file
diff --git a/entity/Task_entity/Task_entity.aod b/entity/Task_entity/Task_entity.aod
index 370f210a8fd53d25f1f55b93cb6f94af250d0fbf..954b18c3d26f2ffeb3f2ef532cdee3d267812f45 100644
--- a/entity/Task_entity/Task_entity.aod
+++ b/entity/Task_entity/Task_entity.aod
@@ -25,7 +25,6 @@
     <entityField>
       <name>SUBJECT</name>
       <title>subject</title>
-      <linkedContext>Task</linkedContext>
       <mandatory v="true" />
     </entityField>
     <entityField>
@@ -52,6 +51,7 @@
       <consumer>ContactRequestors</consumer>
       <linkedContext>Person</linkedContext>
       <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Task_entity/entityfields/requestor_contact_id/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
@@ -354,6 +354,12 @@
           <fieldName>Tasks</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>2b0c15eb-fa9a-4ee8-a8b1-5d0f344ddad6</name>
+          <entityName>Contract_entity</entityName>
+          <fieldName>Tasks</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
       <children>
         <entityParameter>
@@ -384,6 +390,17 @@
       <documentation>%aditoprj%/entity/Task_entity/entityfields/presetlinks_param/documentation.adoc</documentation>
       <description>PARAMETER</description>
     </entityParameter>
+    <entityField>
+      <name>SUBJECT_DETAILS</name>
+      <title>subject</title>
+      <linkedContext>Task</linkedContext>
+    </entityField>
+    <entityParameter>
+      <name>FilterOnlyOwnTask_param</name>
+      <valueProcess>%aditoprj%/entity/Task_entity/entityfields/filteronlyowntask_param/valueProcess.js</valueProcess>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -486,6 +503,10 @@
           <name>PROGRESS.displayValue</name>
           <expression>%aditoprj%/entity/Task_entity/recordcontainers/db/recordfieldmappings/progress.displayvalue/expression.js</expression>
         </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>SUBJECT_DETAILS.value</name>
+          <recordfield>TASK.SUBJECT</recordfield>
+        </dbRecordFieldMapping>
       </recordFieldMappings>
     </dbRecordContainer>
   </recordContainers>
diff --git a/entity/Task_entity/entityfields/filteronlyowntask_param/valueProcess.js b/entity/Task_entity/entityfields/filteronlyowntask_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e0f3ec47e2b963a577204e41d9847dd6ad0725a8
--- /dev/null
+++ b/entity/Task_entity/entityfields/filteronlyowntask_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.string(false);
\ No newline at end of file
diff --git a/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js b/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1e62e7551ccb20b0b0d7aca34f64b6e448b5dda7
--- /dev/null
+++ b/entity/Task_entity/entityfields/requestor_contact_id/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("Employee_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+    result.string(EmployeeUtils.getCurrentContactId());
\ No newline at end of file
diff --git a/entity/Task_entity/recordcontainers/db/conditionProcess.js b/entity/Task_entity/recordcontainers/db/conditionProcess.js
index 28d6be4aaec51ac7f9ed51fd64dc1cf6029462c1..923b39eb1ad3e4f8da08275b3786b33bf2ed135c 100644
--- a/entity/Task_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Task_entity/recordcontainers/db/conditionProcess.js
@@ -1,18 +1,29 @@
+import("Employee_lib");
 import("system.vars");
 import("system.db");
 import("system.result");
 import("Sql_lib");
 
 var cond = new SqlCondition();
+var alternativeFallbackCondition = "1 = 1";
+
+if (vars.getString("$param.FilterOnlyOwnTask_param") == "true")
+{
+    var ownContactId = EmployeeUtils.getCurrentContactId();
+    if (ownContactId)
+        cond.andPrepareIfSet("TASK.EDITOR_CONTACT_ID", ownContactId);
+    else
+        alternativeFallbackCondition = "1 = 2";
+}
 if (vars.exists("$param.RowId_param") && vars.get("$param.RowId_param") && vars.exists("$param.ObjectId_param") && vars.get("$param.ObjectId_param"))
 {
     var activityLinkCond = SqlCondition.begin().andPrepareVars("TASKLINK.OBJECT_ROWID", "$param.RowId_param")
                                                .andPrepareVars("TASKLINK.OBJECT_TYPE", "$param.ObjectId_param");
 
-                                                            // TODO: more performant way than IN. Maybe a join??
+                                                            // TODO: more performant way than IN. Maybe a join?
     cond.and(db.translateStatement(activityLinkCond.buildSql("TASK.TASKID in (select TASKLINK.TASK_ID from TASKLINK", "1=2", ")")))
 }
 
 //TODO: use a preparedCondition when available #1030812 #1034026
-var resCond = db.translateCondition(cond.build("1 = 1"));
+var resCond = db.translateCondition(cond.build(alternativeFallbackCondition));
 result.string(resCond);
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 80500ad7d4e9466b7d358dfab7a541e3aa0d9824..8fbbafa7eca42b702d5a793dfb4f69d002d63c3e 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -2973,6 +2973,60 @@
     <entry>
       <key>Current participants</key>
     </entry>
+    <entry>
+      <key>Overdue tasks</key>
+    </entry>
+    <entry>
+      <key>Open tasks</key>
+    </entry>
+    <entry>
+      <key>[%0]the tableName is not a string after interpreting</key>
+    </entry>
+    <entry>
+      <key>[%0]%1 has to be a string or array but it is %2</key>
+    </entry>
+    <entry>
+      <key>[%0]has now an incorrect length; estimated 2 elements but got %1</key>
+    </entry>
+    <entry>
+      <key>[%0]the columnName is not a string after interpreting</key>
+    </entry>
+    <entry>
+      <key>[%0]%1 is an object but seems not to be a valid array or array-like</key>
+    </entry>
+    <entry>
+      <key>Responsible</key>
+    </entry>
+    <entry>
+      <key>New tasks</key>
+    </entry>
+    <entry>
+      <key>Imminent appointments for today</key>
+    </entry>
+    <entry>
+      <key>Analyses</key>
+    </entry>
+    <entry>
+      <key>Imminent appointments for today </key>
+    </entry>
+    <entry>
+      <key>To-Do</key>
+    </entry>
+    <entry>
+      <key>My Tasks</key>
+    </entry>
+    <entry>
+      <key>Calendar</key>
+    </entry>
+    <entry>
+      <key>${SQL_LIB_UNDEFINED_VALUE} field: %0</key>
+    </entry>
+    <entry>
+      <key>My tasks</key>
+    </entry>
+    <entry>
+      <key>${ATTRIBUTE_VOID}</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
   <sqlModels>
diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
index cf3c88bfb26694a3b8cfb774e96ff224966da918..2f7b32271dab5967e532396547b22599a2f74954 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -26,6 +26,10 @@
       <key>Company</key>
       <value>Firma</value>
     </entry>
+    <entry>
+      <key>Open tasks</key>
+      <value>Offene Aufgaben</value>
+    </entry>
     <entry>
       <key>Picture</key>
       <value>Bild</value>
@@ -34,6 +38,10 @@
       <key>Office staff</key>
       <value>Innendienst</value>
     </entry>
+    <entry>
+      <key>Overdue tasks</key>
+      <value>Überfällige Aufgaben</value>
+    </entry>
     <entry>
       <key>Confirm password</key>
       <value>Passwort prüfen</value>
@@ -50,6 +58,10 @@
       <key>Salesproject phases</key>
       <value>Vertriebsprojektphasen</value>
     </entry>
+    <entry>
+      <key>${ATTRIBUTE_VOID}</key>
+      <value>Kein Wert</value>
+    </entry>
     <entry>
       <key>Turnover</key>
       <value>Umsatz</value>
@@ -102,6 +114,10 @@
       <key>${ADDRESS_STATE}</key>
       <value>Staat</value>
     </entry>
+    <entry>
+      <key>New tasks</key>
+      <value>Neue Aufgaben</value>
+    </entry>
     <entry>
       <key>New module</key>
       <value>Neuanlage</value>
@@ -957,6 +973,10 @@
       <key>Identical price list found!</key>
       <value>Identische Preisliste gefunden!</value>
     </entry>
+    <entry>
+      <key>Imminent appointments for today</key>
+      <value>Bevorstehende Termine für heute</value>
+    </entry>
     <entry>
       <key>Parts list</key>
       <value>Stückliste</value>
@@ -3073,6 +3093,7 @@
     </entry>
     <entry>
       <key>Group</key>
+      <value>Gruppe</value>
     </entry>
     <entry>
       <key>Combobox</key>
@@ -3153,7 +3174,7 @@
       <value>Neue Aufgabe</value>
     </entry>
     <entry>
-      <key>MyTasks</key>
+      <key>My tasks</key>
       <value>Meine Aufgaben</value>
     </entry>
     <entry>
@@ -3744,6 +3765,47 @@
     <entry>
       <key>Would you like to clear the forecast and set the state to \"%0\"?</key>
     </entry>
+    <entry>
+      <key>[%0]the tableName is not a string after interpreting</key>
+    </entry>
+    <entry>
+      <key>[%0]%1 has to be a string or array but it is %2</key>
+    </entry>
+    <entry>
+      <key>[%0]has now an incorrect length; estimated 2 elements but got %1</key>
+    </entry>
+    <entry>
+      <key>[%0]the columnName is not a string after interpreting</key>
+    </entry>
+    <entry>
+      <key>[%0]%1 is an object but seems not to be a valid array or array-like</key>
+    </entry>
+    <entry>
+      <key>Responsible</key>
+      <value>Verantwortlich</value>
+    </entry>
+    <entry>
+      <key>Analyses</key>
+    </entry>
+    <entry>
+      <key>Imminent appointments for today </key>
+    </entry>
+    <entry>
+      <key>To-Do</key>
+    </entry>
+    <entry>
+      <key>My Tasks</key>
+    </entry>
+    <entry>
+      <key>Calendar</key>
+    </entry>
+    <entry>
+      <key>${SQL_LIB_UNDEFINED_VALUE} field: %0</key>
+      <value>Der Wert für das Feld %0 ist undefined.</value>
+    </entry>
+    <entry>
+      <key>MyTasks</key>
+    </entry>
     <entry>
       <key>Approved</key>
       <value>Freigegeben</value>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index 1372b43c6b7be5f24b9332414e8c0f7906afe481..2bc9e8f85f628142f054910f4c5714aaf646a721 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -3004,6 +3004,62 @@
     <entry>
       <key>Current participants</key>
     </entry>
+    <entry>
+      <key>Overdue tasks</key>
+    </entry>
+    <entry>
+      <key>Open tasks</key>
+    </entry>
+    <entry>
+      <key>[%0]the tableName is not a string after interpreting</key>
+    </entry>
+    <entry>
+      <key>[%0]%1 has to be a string or array but it is %2</key>
+    </entry>
+    <entry>
+      <key>[%0]has now an incorrect length; estimated 2 elements but got %1</key>
+    </entry>
+    <entry>
+      <key>[%0]the columnName is not a string after interpreting</key>
+    </entry>
+    <entry>
+      <key>[%0]%1 is an object but seems not to be a valid array or array-like</key>
+    </entry>
+    <entry>
+      <key>Responsible</key>
+    </entry>
+    <entry>
+      <key>New tasks</key>
+    </entry>
+    <entry>
+      <key>Imminent appointments for today</key>
+    </entry>
+    <entry>
+      <key>Analyses</key>
+    </entry>
+    <entry>
+      <key>Imminent appointments for today </key>
+    </entry>
+    <entry>
+      <key>To-Do</key>
+    </entry>
+    <entry>
+      <key>My Tasks</key>
+    </entry>
+    <entry>
+      <key>Calendar</key>
+    </entry>
+    <entry>
+      <key>${SQL_LIB_UNDEFINED_VALUE} field: %0</key>
+      <value>The value for the field %0 is undefined.</value>
+    </entry>
+    <entry>
+      <key>My tasks</key>
+    </entry>
+    <entry>
+      <key>${ATTRIBUTE_VOID}</key>
+      <value>Void</value>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/AddressValidation/AddressValidation.aod b/neonContext/AddressValidation/AddressValidation.aod
new file mode 100644
index 0000000000000000000000000000000000000000..7542f8466fc2c7dbfbf84c32253d970b121a2517
--- /dev/null
+++ b/neonContext/AddressValidation/AddressValidation.aod
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
+  <name>AddressValidation</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <lookupview>AddressValidationLookup_view</lookupview>
+  <entity>AddressValidation_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>a093b522-3dc9-4c77-85f1-46ed07bd4be7</name>
+      <view>AddressValidationLookup_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/Analyses/Analyses.aod b/neonContext/Analyses/Analyses.aod
new file mode 100644
index 0000000000000000000000000000000000000000..f9466ef0070a184017d9a5ace7105ef623acd44f
--- /dev/null
+++ b/neonContext/Analyses/Analyses.aod
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
+  <name>Analyses</name>
+  <title>Analyses</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterview>MyDashboardScoreCard_view</filterview>
+  <entity>Analyses_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>f995b030-7b74-4513-89ca-57c6979ac06f</name>
+      <view>MyDashboardScoreCard_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/AttributeRelationTree/AttributeRelationTree.aod b/neonContext/AttributeRelationTree/AttributeRelationTree.aod
index bcd7bec8f8c74b3791ebdd93a728c950493b2781..9acb4ce97d8d3d086df679b67f01a23ac945eb63 100644
--- a/neonContext/AttributeRelationTree/AttributeRelationTree.aod
+++ b/neonContext/AttributeRelationTree/AttributeRelationTree.aod
@@ -1,12 +1,16 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
-  <name>AttributeRelationTree</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <entity>AttributeRelationTree_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>55f89863-72b0-4179-8494-b1e320d79de9</name>
-      <view>AttributeRelationTree_view</view>
-    </neonViewReference>
-  </references>
-</neonContext>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
+  <name>AttributeRelationTree</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <entity>AttributeRelationTree_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>55f89863-72b0-4179-8494-b1e320d79de9</name>
+      <view>AttributeRelationTree_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>591d27d7-e963-4ff0-9d82-2e24b18e6b5c</name>
+      <view>AttributeRelationTreeEdit_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/Salesproject/Salesproject.aod b/neonContext/Salesproject/Salesproject.aod
index a5422082d260a0e651632846afbc6b826ae25ff3..918124f55773f30f2c60e4ef6a6c16f7809456fb 100644
--- a/neonContext/Salesproject/Salesproject.aod
+++ b/neonContext/Salesproject/Salesproject.aod
@@ -26,5 +26,9 @@
       <name>c35cc718-94a8-43cf-afe4-f02d251d4e9f</name>
       <view>SalesprojectEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>9d4603e0-6e0e-4c9e-af97-f5c059debe9e</name>
+      <view>SalesprojectMilestone_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonContext/SalesprojectMember/SalesprojectMember.aod b/neonContext/SalesprojectMember/SalesprojectMember.aod
index f337d45bcc6578adb7025667f8433c3b7697d45e..be5169e7862f9c01cb2a794a2eae9dd2d4b648f5 100644
--- a/neonContext/SalesprojectMember/SalesprojectMember.aod
+++ b/neonContext/SalesprojectMember/SalesprojectMember.aod
@@ -4,7 +4,6 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <filterview>SalesprojectMemberFilter_view</filterview>
   <editview>SalesprojectMemberEdit_view</editview>
-  <preview>SalesprojectMemberPreview_view</preview>
   <entity>SalesprojectMember_entity</entity>
   <references>
     <neonViewReference>
@@ -15,9 +14,5 @@
       <name>ebef21a3-c0e1-4333-b769-eb967cb4099b</name>
       <view>SalesprojectMemberEdit_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>dc850b82-3c28-4626-a0fd-a856c624c2e3</name>
-      <view>SalesprojectMemberPreview_view</view>
-    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonNotificationType/AndisNotification/AndisNotification.aod b/neonNotificationType/AndisNotification/AndisNotification.aod
new file mode 100644
index 0000000000000000000000000000000000000000..7aae24c40748d72225570cd8d6f72b9c81ba6c15
--- /dev/null
+++ b/neonNotificationType/AndisNotification/AndisNotification.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0">
+  <name>AndisNotification</name>
+  <title>Andis Noti</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <resultFrameNeon></resultFrameNeon>
+  <onResultOpen>%aditoprj%/neonNotificationType/AndisNotification/onResultOpen.js</onResultOpen>
+  <context>Contact</context>
+</neonNotificationType>
diff --git a/neonNotificationType/AndisNotification/onResultOpen.js b/neonNotificationType/AndisNotification/onResultOpen.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/neonView/ActivityEdit_view/ActivityEdit_view.aod b/neonView/ActivityEdit_view/ActivityEdit_view.aod
index 5c306e04cb11a4044f1a5aaec99b17a5dd734f44..4a16fe2dd5f1e1ef88a07a1e8230ba5c1b62a17d 100644
--- a/neonView/ActivityEdit_view/ActivityEdit_view.aod
+++ b/neonView/ActivityEdit_view/ActivityEdit_view.aod
@@ -38,7 +38,7 @@
         </entityFieldLink>
         <entityFieldLink>
           <name>91514e62-f4f7-4eb7-84c0-8d94adbb3408</name>
-          <entityField>CREATOR</entityField>
+          <entityField>RESPONSIBLE</entityField>
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
@@ -47,5 +47,10 @@
       <entityField>Links</entityField>
       <view>ActivityLinkMultiEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>7fcf9c09-189a-47b7-a171-9975676ed704</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/ActivityFilter_view/ActivityFilter_view.aod b/neonView/ActivityFilter_view/ActivityFilter_view.aod
index fd33556f856997695ea211f98288dd4a7d791259..78a81d68932c0bf91139e730cb800fc2b19df0a3 100644
--- a/neonView/ActivityFilter_view/ActivityFilter_view.aod
+++ b/neonView/ActivityFilter_view/ActivityFilter_view.aod
@@ -93,7 +93,7 @@
     </tableViewTemplate>
     <treeViewTemplate>
       <name>ActivitiesTreetable</name>
-      <titleField>SUBJECT</titleField>
+      <titleField>SUBJECT_DETAILS</titleField>
       <descriptionField>INFO</descriptionField>
       <iconField>#IMAGE</iconField>
       <entityField>#ENTITY</entityField>
diff --git a/neonView/ActivityLinkPreview_view/ActivityLinkPreview_view.aod b/neonView/ActivityLinkPreview_view/ActivityLinkPreview_view.aod
index 891ec75b0ff78ee3771627dc31753896ca281caa..b384acfdd505a2023c7aea5cd671a3aa72bd5ca3 100644
--- a/neonView/ActivityLinkPreview_view/ActivityLinkPreview_view.aod
+++ b/neonView/ActivityLinkPreview_view/ActivityLinkPreview_view.aod
@@ -3,9 +3,9 @@
   <name>ActivityLinkPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+    </headerFooterLayout>
   </layout>
   <children>
     <genericViewTemplate>
diff --git a/neonView/ActivityPreview_view/ActivityPreview_view.aod b/neonView/ActivityPreview_view/ActivityPreview_view.aod
index e142cb9bf33ee4d6acce56e5463e8ca7e6f05c67..5553ffc4d225860fab8196668e128b6d4368661f 100644
--- a/neonView/ActivityPreview_view/ActivityPreview_view.aod
+++ b/neonView/ActivityPreview_view/ActivityPreview_view.aod
@@ -3,9 +3,10 @@
   <name>ActivityPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
@@ -35,7 +36,7 @@
         </entityFieldLink>
         <entityFieldLink>
           <name>c4569e50-223e-4b99-8253-e8fa72ef45a0</name>
-          <entityField>CREATOR</entityField>
+          <entityField>RESPONSIBLE</entityField>
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
diff --git a/neonView/AddressList_view/AddressList_view.aod b/neonView/AddressList_view/AddressList_view.aod
index 0baa8a57551446a1b41fc43aff6da1974c8a0425..3ef2a83f526949e497254b822cdde3928d6023ae 100644
--- a/neonView/AddressList_view/AddressList_view.aod
+++ b/neonView/AddressList_view/AddressList_view.aod
@@ -38,6 +38,18 @@
           <name>12727b21-0359-4430-a9c2-54eb48e2e864</name>
           <entityField>CITY</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>af515eed-da89-49dc-ba3a-30958bd4fedd</name>
+          <entityField>DISTRICT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>29dbb3f5-6f80-4100-aed3-334ac0b9cc48</name>
+          <entityField>REGION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>aafc58cf-7dbb-42cb-b04c-d0869e58d09a</name>
+          <entityField>STATE</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>6af52273-25bf-4286-83cc-217aea94ad09</name>
           <entityField>ADDRIDENTIFIER</entityField>
diff --git a/neonView/AddressValidationLookup_view/AddressValidationLookup_view.aod b/neonView/AddressValidationLookup_view/AddressValidationLookup_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..a0bf44af7ce2d5e9e872e1025e207d724ec1d3b6
--- /dev/null
+++ b/neonView/AddressValidationLookup_view/AddressValidationLookup_view.aod
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>AddressValidationLookup_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>DataTable</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>a8787cc8-57a2-4cd5-903e-da14924a9052</name>
+          <entityField>ZIP</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>fb715731-9162-405e-b2e2-6c20921f026f</name>
+          <entityField>CITY</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>d32d92bf-db7d-443f-b911-6731ea89cf3b</name>
+          <entityField>COUNTRY</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>4035d833-ece7-4562-8acf-51c7a01b8497</name>
+          <entityField>DISTRICT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>05bb9d3b-0e90-4a1a-bfe8-03b7dab6ed01</name>
+          <entityField>REGION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>22779be5-4111-49c2-8821-0ec02cca40bb</name>
+          <entityField>STATE</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod b/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
index dbec2da120f3c7ad0d96b8e42326b6c48cd6c6e3..952afaabcfe9ba63036c4edaaf4fff95348d22ba 100644
--- a/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
+++ b/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
@@ -13,31 +13,43 @@
       <entityField>#ENTITY</entityField>
       <columns>
         <neonTableColumn>
-          <name>b210372e-dfd3-4cec-bc2e-84b72aebb2b6</name>
+          <name>2aebe24e-875a-4c57-8461-16da46d6f080</name>
           <entityField>ADDR_TYPE</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>d8a7a26b-9d7f-44d7-bbb1-b0404d5b8b2f</name>
+          <name>435f10b8-b6ef-4187-bffc-fc6104a6130c</name>
           <entityField>COUNTRY</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>c20668f3-6722-4a90-86d6-0d29be06dbe1</name>
+          <name>ac71d5eb-7ce7-41a0-91aa-5594f2238788</name>
           <entityField>ADDRESS</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>0eac127d-de3d-4ff0-9ac2-1227b33c854a</name>
+          <name>61261845-740e-4f4b-a1f8-5e6aeac2deba</name>
           <entityField>BUILDINGNO</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>0eac127d-de3d-aff0-9ac2-1327b33c854a</name>
+          <name>c1372a93-cf83-4c55-90e6-3b6b352abebf</name>
           <entityField>ZIP</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>fafca2d6-c2dd-4b66-b1ff-1d6ba451827b</name>
+          <name>2e7ba632-36ad-4852-bcca-d75bcf3f7de1</name>
           <entityField>CITY</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>481496b8-d611-4b4a-9c5e-1d28a7136a2d</name>
+          <name>e25f4140-0772-4417-85f0-41052b413c30</name>
+          <entityField>DISTRICT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>b62515bf-e89d-44a9-94ff-933766657fe5</name>
+          <entityField>REGION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>66ae75ca-7a5c-4cf0-b768-6c2900f7b7c6</name>
+          <entityField>STATE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>443b9d7d-dac2-40b2-bb2b-d5e0091877a9</name>
           <entityField>ADDRIDENTIFIER</entityField>
         </neonTableColumn>
       </columns>
diff --git a/neonView/AppointmentPreview_view/AppointmentPreview_view.aod b/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
index 53f8e32a4dbd252c66310003096c528b5aac0b44..ff89173c01ea28f661e4216e92d58d74a86808a1 100644
--- a/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
+++ b/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
@@ -1,36 +1,36 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>AppointmentPreview_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/neonView/AppointmentPreview_view/documentation.adoc</documentation>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <appointmentPreviewViewTemplate>
-      <name>Appointments</name>
-      <summaryField>SUMMARY</summaryField>
-      <descriptionField>DESCRIPTION</descriptionField>
-      <beginField>BEGIN</beginField>
-      <endField>END</endField>
-      <periodField>STARTEND</periodField>
-      <attendeesField>ATTENDEES</attendeesField>
-      <privateField>CLASSIFICATION</privateField>
-      <transparencyField>TRANSPARENCY</transparencyField>
-      <statusField>STATUS</statusField>
-      <locationField>LOCATION</locationField>
-      <linkField>LINKS</linkField>
-      <organizerField>ORGANIZER</organizerField>
-      <categoriesField>CATEGORIES</categoriesField>
-      <favoriteActionGroup1>PartStatActionGroup</favoriteActionGroup1>
-      <entityField>#ENTITY</entityField>
-    </appointmentPreviewViewTemplate>
-    <neonViewReference>
-      <name>be0befe0-4b29-4c23-924a-0167240d2b54</name>
-      <entityField>AppointmentLinks</entityField>
-      <view>AppointmentLinkFilter_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>AppointmentPreview_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/neonView/AppointmentPreview_view/documentation.adoc</documentation>
+  <layout>
+    <headerFooterLayout>
+      <name>layout</name>
+    </headerFooterLayout>
+  </layout>
+  <children>
+    <appointmentPreviewViewTemplate>
+      <name>Appointments</name>
+      <summaryField>SUMMARY</summaryField>
+      <descriptionField>DESCRIPTION</descriptionField>
+      <beginField>BEGIN</beginField>
+      <endField>END</endField>
+      <periodField>STARTEND</periodField>
+      <attendeesField>ATTENDEES</attendeesField>
+      <privateField>CLASSIFICATION</privateField>
+      <transparencyField>TRANSPARENCY</transparencyField>
+      <statusField>STATUS</statusField>
+      <locationField>LOCATION</locationField>
+      <linkField>LINKS</linkField>
+      <organizerField>ORGANIZER</organizerField>
+      <categoriesField>CATEGORIES</categoriesField>
+      <favoriteActionGroup1>PartStatActionGroup</favoriteActionGroup1>
+      <entityField>#ENTITY</entityField>
+    </appointmentPreviewViewTemplate>
+    <neonViewReference>
+      <name>be0befe0-4b29-4c23-924a-0167240d2b54</name>
+      <entityField>AppointmentLinks</entityField>
+      <view>AppointmentLinkFilter_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/neonView/AttributeFilter_view/AttributeFilter_view.aod b/neonView/AttributeFilter_view/AttributeFilter_view.aod
index 0b65a9ac7b1714029130c254f1f20168b244bbd6..cadb8afc80a55d8af99a17f82f798828a6200a72 100644
--- a/neonView/AttributeFilter_view/AttributeFilter_view.aod
+++ b/neonView/AttributeFilter_view/AttributeFilter_view.aod
@@ -10,14 +10,27 @@
     </groupLayout>
   </layout>
   <children>
-    <treeViewTemplate>
-      <name>AttributesTreetable</name>
+    <treeTableViewTemplate>
+      <name>AttributeTreeTable</name>
       <parentField>ATTRIBUTE_PARENT_ID</parentField>
       <favoriteActionGroup1>AttributeActions</favoriteActionGroup1>
-      <titleField>NAME_WITH_TYPE</titleField>
-      <descriptionField>USAGELIST</descriptionField>
+      <showChildrenCount v="false" />
       <entityField>#ENTITY</entityField>
-    </treeViewTemplate>
+      <columns>
+        <neonTableColumn>
+          <name>a776a053-6712-44f9-943f-da26d1ce11ee</name>
+          <entityField>ATTRIBUTE_NAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>b975154d-8bac-4182-9030-e3b3d744c642</name>
+          <entityField>ATTRIBUTE_TYPE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>ad92d325-6cdb-4fa0-a99b-27c937c89936</name>
+          <entityField>USAGELIST</entityField>
+        </neonTableColumn>
+      </columns>
+    </treeTableViewTemplate>
     <tableViewTemplate>
       <name>AttributesTable</name>
       <entityField>#ENTITY</entityField>
diff --git a/neonView/AttributePreview_view/AttributePreview_view.aod b/neonView/AttributePreview_view/AttributePreview_view.aod
index 1a5041da04ba58d9a141c8bdbe8d37acf2e30124..5a8e785eb7471b2b09da7a94db7797460926cf79 100644
--- a/neonView/AttributePreview_view/AttributePreview_view.aod
+++ b/neonView/AttributePreview_view/AttributePreview_view.aod
@@ -3,9 +3,10 @@
   <name>AttributePreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Head</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
@@ -24,6 +25,10 @@
           <name>70953962-9472-484b-ac95-567d2249f42e</name>
           <entityField>ATTRIBUTE_ACTIVE</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>1b1cfdcb-fcab-4ca9-b0e0-b69fe88b65f0</name>
+          <entityField>SORTING</entityField>
+        </entityFieldLink>
       </fields>
     </genericViewTemplate>
     <genericViewTemplate>
diff --git a/neonView/AttributeRelationTreeEdit_view/AttributeRelationTreeEdit_view.aod b/neonView/AttributeRelationTreeEdit_view/AttributeRelationTreeEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..08416feb076e503124b8e5a94f0f3f8d3dbfb463
--- /dev/null
+++ b/neonView/AttributeRelationTreeEdit_view/AttributeRelationTreeEdit_view.aod
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>AttributeRelationTreeEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <genericViewTemplate>
+      <name>Generic</name>
+      <editMode v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>e5635cd6-1a95-455a-af89-5baf4259caa0</name>
+          <entityField>AB_ATTRIBUTE_ID</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>abec86c9-3d77-4129-b34b-d30da0526572</name>
+          <entityField>VALUE</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/AttributeRelationTree_view/AttributeRelationTree_view.aod b/neonView/AttributeRelationTree_view/AttributeRelationTree_view.aod
index 47d34ce205514a2df8cb6cb601ec8925ba2ff69d..1eee2f28de6b9b5b3cc9b459b211176b261aa5ef 100644
--- a/neonView/AttributeRelationTree_view/AttributeRelationTree_view.aod
+++ b/neonView/AttributeRelationTree_view/AttributeRelationTree_view.aod
@@ -1,18 +1,28 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>AttributeRelationTree_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <treeViewTemplate>
-      <name>AttributeRelationTree</name>
-      <parentField>PARENT_ID</parentField>
-      <titleField>TITLE</titleField>
-      <entityField>#ENTITY</entityField>
-    </treeViewTemplate>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>AttributeRelationTree_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <treeTableViewTemplate>
+      <name>TreeTable</name>
+      <parentField>PARENT_ID</parentField>
+      <showChildrenCount v="false" />
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>840551af-5a99-4965-a96a-ed134efb28a9</name>
+          <entityField>AB_ATTRIBUTE_ID</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>7844082c-fd31-4878-9e57-024cb2b2b627</name>
+          <entityField>VALUE</entityField>
+        </neonTableColumn>
+      </columns>
+    </treeTableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/AttributeUsageFilter_view/AttributeUsageFilter_view.aod b/neonView/AttributeUsageFilter_view/AttributeUsageFilter_view.aod
index 87500bc6ffd7b9f4aa4cd883890dad531c326028..be89cedfa70b52fba0ae98df1cd41f9ee8419383 100644
--- a/neonView/AttributeUsageFilter_view/AttributeUsageFilter_view.aod
+++ b/neonView/AttributeUsageFilter_view/AttributeUsageFilter_view.aod
@@ -18,6 +18,14 @@
           <name>ba8d5468-4e59-4ab8-8174-afcca1ae0d9e</name>
           <entityField>OBJECT_TYPE</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>22924cb1-25df-4c5c-92ec-2e51cb5b330b</name>
+          <entityField>MIN_COUNT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>ee879f6d-dc3a-4e85-9711-e470c0eb9cc4</name>
+          <entityField>MAX_COUNT</entityField>
+        </neonTableColumn>
       </columns>
     </tableViewTemplate>
   </children>
diff --git a/neonView/AttributeUsageMultiEdit_view/AttributeUsageMultiEdit_view.aod b/neonView/AttributeUsageMultiEdit_view/AttributeUsageMultiEdit_view.aod
index 0ecf44f96e8d1228876b0e755871a296b9a81386..ce7b20e704ad302fe485ba0d951bb285e8e9f3bd 100644
--- a/neonView/AttributeUsageMultiEdit_view/AttributeUsageMultiEdit_view.aod
+++ b/neonView/AttributeUsageMultiEdit_view/AttributeUsageMultiEdit_view.aod
@@ -17,6 +17,14 @@
           <entityField>OBJECT_TYPE</entityField>
           <width v="75" />
         </neonTableColumn>
+        <neonTableColumn>
+          <name>4eb1b225-5856-4585-b6dd-401d1334d8ba</name>
+          <entityField>MIN_COUNT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>16bd5079-6496-4c5f-a821-ae145e1bc981</name>
+          <entityField>MAX_COUNT</entityField>
+        </neonTableColumn>
       </columns>
     </genericMultipleViewTemplate>
   </children>
diff --git a/neonView/ContractEdit_view/ContractEdit_view.aod b/neonView/ContractEdit_view/ContractEdit_view.aod
index ec6443f7b56cc44a107522a5d858d7a836bc2e87..21e04e53a2be56f8e8c2d0a5a6b3f0b5bdbec3ef 100644
--- a/neonView/ContractEdit_view/ContractEdit_view.aod
+++ b/neonView/ContractEdit_view/ContractEdit_view.aod
@@ -51,5 +51,10 @@
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
+    <neonViewReference>
+      <name>49eafd04-4d72-4a11-8818-97407e0fe154</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/ContractMain_view/ContractMain_view.aod b/neonView/ContractMain_view/ContractMain_view.aod
index 83ff714a33918c32ee14942f3b1146e3fa2a9814..dd52050bf2edb9d1e3ed7d972a4006db611390c2 100644
--- a/neonView/ContractMain_view/ContractMain_view.aod
+++ b/neonView/ContractMain_view/ContractMain_view.aod
@@ -19,6 +19,11 @@
       <entityField>Activities</entityField>
       <view>ActivityFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>24fb8357-a6f7-425c-a579-a9251913c8d7</name>
+      <entityField>Tasks</entityField>
+      <view>TaskFilter_view</view>
+    </neonViewReference>
     <neonViewReference>
       <name>1bf6faf5-9a22-4900-a497-54b6c225584b</name>
       <entityField>Documents</entityField>
diff --git a/neonView/ContractPreview_view/ContractPreview_view.aod b/neonView/ContractPreview_view/ContractPreview_view.aod
index ff1f59a0aab0710c324372bbf12e94502032f0f3..328e2dd523937fb023dda5ce211cc3678946b96b 100644
--- a/neonView/ContractPreview_view/ContractPreview_view.aod
+++ b/neonView/ContractPreview_view/ContractPreview_view.aod
@@ -3,9 +3,10 @@
   <name>ContractPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
@@ -13,6 +14,7 @@
       <iconField>IMAGE</iconField>
       <titleField>CONTRACTCODE_DISPLAY_fieldGroup</titleField>
       <descriptionField>CONTACT_ID</descriptionField>
+      <favoriteAction1>newActivity</favoriteAction1>
       <entityField>#ENTITY</entityField>
     </cardViewTemplate>
     <genericViewTemplate>
diff --git a/neonView/EmployeeEdit_view/EmployeeEdit_view.aod b/neonView/EmployeeEdit_view/EmployeeEdit_view.aod
index 71614eff593bccfb770ea91b005d958a6feecad7..766d45a551b95b7988fd3c119c450145322a455c 100644
--- a/neonView/EmployeeEdit_view/EmployeeEdit_view.aod
+++ b/neonView/EmployeeEdit_view/EmployeeEdit_view.aod
@@ -1,60 +1,69 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>EmployeeEdit_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <genericViewTemplate>
-      <name>Generic</name>
-      <editMode v="true" />
-      <entityField>#ENTITY</entityField>
-      <fields>
-        <entityFieldLink>
-          <name>1925ef51-54a8-41e2-aa78-6d95d1ee4b99</name>
-          <entityField>CONTACT_ID</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>9170856b-45c2-4d8a-864d-4db36bfe4a8c</name>
-          <entityField>ISACTIVE</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>7d36467f-8b79-4647-b8e5-5759bdbf37a7</name>
-          <entityField>FIRSTNAME</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>00a2dedb-67f5-4662-b053-bf841b30e365</name>
-          <entityField>LASTNAME</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>9c030b62-bf17-4be1-bcc6-87b304a618c0</name>
-          <entityField>TITLE</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>6155e6b7-ee2c-45b4-87f5-9e506ffc5775</name>
-          <entityField>EMAIL_ADDRESS</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>8cffaf75-f2dc-42c5-95d7-1ce1e4927d8a</name>
-          <entityField>DESCRIPTION</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>4ad9c1aa-37a9-46f9-a566-94e5be5c2a7f</name>
-          <entityField>PASSWORD</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>5381db3a-762d-439a-b41b-e4e67edc2099</name>
-          <entityField>CONFIRM_PASSWORD</entityField>
-        </entityFieldLink>
-      </fields>
-    </genericViewTemplate>
-    <neonViewReference>
-      <name>af8112a3-78d3-436f-b665-ebce595a7c24</name>
-      <entityField>EmployeeRoles</entityField>
-      <view>EmployeeRoleEdit_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>EmployeeEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <genericViewTemplate>
+      <name>Generic</name>
+      <editMode v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>1925ef51-54a8-41e2-aa78-6d95d1ee4b99</name>
+          <entityField>CONTACT_ID</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>9170856b-45c2-4d8a-864d-4db36bfe4a8c</name>
+          <entityField>ISACTIVE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>7d36467f-8b79-4647-b8e5-5759bdbf37a7</name>
+          <entityField>FIRSTNAME</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>00a2dedb-67f5-4662-b053-bf841b30e365</name>
+          <entityField>LASTNAME</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>9c030b62-bf17-4be1-bcc6-87b304a618c0</name>
+          <entityField>TITLE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>6155e6b7-ee2c-45b4-87f5-9e506ffc5775</name>
+          <entityField>EMAIL_ADDRESS</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>6abf045b-88f9-40c9-a009-f85538d6fe23</name>
+          <entityField>DEPARTMENT</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>8cffaf75-f2dc-42c5-95d7-1ce1e4927d8a</name>
+          <entityField>DESCRIPTION</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>4ad9c1aa-37a9-46f9-a566-94e5be5c2a7f</name>
+          <entityField>PASSWORD</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>5381db3a-762d-439a-b41b-e4e67edc2099</name>
+          <entityField>CONFIRM_PASSWORD</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+    <neonViewReference>
+      <name>af8112a3-78d3-436f-b665-ebce595a7c24</name>
+      <entityField>EmployeeRoles</entityField>
+      <view>EmployeeRoleEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>07e77840-e140-4ba0-ac09-d8e10e7d88a2</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/neonView/EmployeePreview_view/EmployeePreview_view.aod b/neonView/EmployeePreview_view/EmployeePreview_view.aod
index 198c613625f55b8cf69b2094f843b9876ad4fc3e..9854f076d27c12eb237d322449d017e0bdd456f0 100644
--- a/neonView/EmployeePreview_view/EmployeePreview_view.aod
+++ b/neonView/EmployeePreview_view/EmployeePreview_view.aod
@@ -3,9 +3,10 @@
   <name>EmployeePreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/KeywordAttributeEdit_view/KeywordAttributeEdit_view.aod b/neonView/KeywordAttributeEdit_view/KeywordAttributeEdit_view.aod
index 6c8ad7446a55027ca2a01a8502667b82e1c27d15..cf2b3b2248c676aea6eb7b541d9d9adfab9de5de 100644
--- a/neonView/KeywordAttributeEdit_view/KeywordAttributeEdit_view.aod
+++ b/neonView/KeywordAttributeEdit_view/KeywordAttributeEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>KeywordAttributeEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/KeywordEntryEdit_view/KeywordEntryEdit_view.aod b/neonView/KeywordEntryEdit_view/KeywordEntryEdit_view.aod
index 31283c6fff3ca4221d2f5c881bba0963824645ee..061bbb6eebafc1131e711f7ab64fe66fb11bba7d 100644
--- a/neonView/KeywordEntryEdit_view/KeywordEntryEdit_view.aod
+++ b/neonView/KeywordEntryEdit_view/KeywordEntryEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>KeywordEntryEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod b/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod
index f8a6856aa390ed0ace0165a842b3f98b587975c4..56c89cf8897a305cd083da826ecb48ba15099d76 100644
--- a/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod
+++ b/neonView/KeywordEntryPreview_view/KeywordEntryPreview_view.aod
@@ -3,9 +3,10 @@
   <name>KeywordEntryPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/MyDashboardScoreCard_view/MyDashboardScoreCard_view.aod b/neonView/MyDashboardScoreCard_view/MyDashboardScoreCard_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..1dda983c317269889fd41ecd94a1666364e88dae
--- /dev/null
+++ b/neonView/MyDashboardScoreCard_view/MyDashboardScoreCard_view.aod
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>MyDashboardScoreCard_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <dashletConfigurations>
+    <neonDashletConfiguration>
+      <name>Information</name>
+      <title>To-Do</title>
+      <fragment>Analyses/full</fragment>
+      <singleton v="true" />
+      <icon>VAADIN:CLIPBOARD_CHECK</icon>
+      <categories>
+        <neonDashletCategory>
+          <name>tasks</name>
+          <title>Tasks</title>
+        </neonDashletCategory>
+        <neonDashletCategory>
+          <name>calendar</name>
+          <title>Calendar</title>
+        </neonDashletCategory>
+      </categories>
+    </neonDashletConfiguration>
+  </dashletConfigurations>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <scoreCardViewTemplate>
+      <name>Scorecard</name>
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>158d3dd5-4de6-470b-b61d-6de1e9907264</name>
+          <entityField>OVERDUE_TASKS</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>5bbd7580-6fdd-4134-b33a-1082f4891c7c</name>
+          <entityField>NEW_TASKS</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>3631eda6-dfda-4c75-9caa-8b2c2e7c39e4</name>
+          <entityField>IMMINENT_APPOINTMENTS</entityField>
+        </entityFieldLink>
+      </fields>
+    </scoreCardViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/ObjectRelationTypeEdit_view/ObjectRelationTypeEdit_view.aod b/neonView/ObjectRelationTypeEdit_view/ObjectRelationTypeEdit_view.aod
index 6560a70b55a6184da2e9bb2fcfd0cf2ca821d37f..2c89e7aaf5a2ac56411d4e3e9105fb2276aef838 100644
--- a/neonView/ObjectRelationTypeEdit_view/ObjectRelationTypeEdit_view.aod
+++ b/neonView/ObjectRelationTypeEdit_view/ObjectRelationTypeEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>ObjectRelationTypeEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/ObjectTreeEdit_view/ObjectTreeEdit_view.aod b/neonView/ObjectTreeEdit_view/ObjectTreeEdit_view.aod
index 472f2ae6756a22dc87731ca9a58aebddefba22a3..84df33d76d26106a9ad4823f9a0a1fe528aea555 100644
--- a/neonView/ObjectTreeEdit_view/ObjectTreeEdit_view.aod
+++ b/neonView/ObjectTreeEdit_view/ObjectTreeEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>ObjectTreeEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/ObjectTreePreview/ObjectTreePreview.aod b/neonView/ObjectTreePreview/ObjectTreePreview.aod
index b6b2c90c68a7ba9c2b8376378700684acb382a10..d7e3916a28c515ec3ae3c150fe75b9b4c6fdbe04 100644
--- a/neonView/ObjectTreePreview/ObjectTreePreview.aod
+++ b/neonView/ObjectTreePreview/ObjectTreePreview.aod
@@ -3,9 +3,9 @@
   <name>ObjectTreePreview</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+    </headerFooterLayout>
   </layout>
   <children>
     <genericViewTemplate>
diff --git a/neonView/OfferPreview_view/OfferPreview_view.aod b/neonView/OfferPreview_view/OfferPreview_view.aod
index 5ebc5733ab8f4abba5d853538e634828874a9593..9b73e6cfe911f0906c5aed7bc0eb83f034975aca 100644
--- a/neonView/OfferPreview_view/OfferPreview_view.aod
+++ b/neonView/OfferPreview_view/OfferPreview_view.aod
@@ -3,9 +3,10 @@
   <name>OfferPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/OfferitemPreview_view/OfferitemPreview_view.aod b/neonView/OfferitemPreview_view/OfferitemPreview_view.aod
index 6927e3f06da1aa5dec4d1f4e6c708eaab6a082ab..c93ad8c9ef329db4797b3726f77dafbf10044c28 100644
--- a/neonView/OfferitemPreview_view/OfferitemPreview_view.aod
+++ b/neonView/OfferitemPreview_view/OfferitemPreview_view.aod
@@ -3,9 +3,10 @@
   <name>OfferitemPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/OrderPreview_view/OrderPreview_view.aod b/neonView/OrderPreview_view/OrderPreview_view.aod
index 62dcd724c0b5d265a297f298926e8d747602af67..d9aa97ac59cc3bec65c625d8cc72bcb3fa7f37dd 100644
--- a/neonView/OrderPreview_view/OrderPreview_view.aod
+++ b/neonView/OrderPreview_view/OrderPreview_view.aod
@@ -3,9 +3,10 @@
   <name>OrderPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/OrderitemPreview_view/OrderitemPreview_view.aod b/neonView/OrderitemPreview_view/OrderitemPreview_view.aod
index 71fd61ff8999e63801852f32c973ce6e45f1a065..9cf09add5fc3db3568e6592679b0a876ab7a5faf 100644
--- a/neonView/OrderitemPreview_view/OrderitemPreview_view.aod
+++ b/neonView/OrderitemPreview_view/OrderitemPreview_view.aod
@@ -3,9 +3,10 @@
   <name>OrderitemPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/OrganisationPreview_view/OrganisationPreview_view.aod b/neonView/OrganisationPreview_view/OrganisationPreview_view.aod
index 37be5f599a73966439a01de1bc475ad38996b106..4ac4e0f35270000aff358c1a72d47d3176488bb5 100644
--- a/neonView/OrganisationPreview_view/OrganisationPreview_view.aod
+++ b/neonView/OrganisationPreview_view/OrganisationPreview_view.aod
@@ -3,9 +3,10 @@
   <name>OrganisationPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/PersonPreview_view/PersonPreview_view.aod b/neonView/PersonPreview_view/PersonPreview_view.aod
index dea509d10e2d57637e8d05b9b5c0c48dec837aab..4948fa0ae20d3ab16c766c03ef30bdedaffae570 100644
--- a/neonView/PersonPreview_view/PersonPreview_view.aod
+++ b/neonView/PersonPreview_view/PersonPreview_view.aod
@@ -3,9 +3,10 @@
   <name>PersonPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod b/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod
index 9b5a532217021a9c0d6de0c7d50c2b20166bc242..fc5c333248e7eda23103f6092291af70fa3699b3 100644
--- a/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod
+++ b/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>Prod2ProdEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/ProductEdit_view/ProductEdit_view.aod b/neonView/ProductEdit_view/ProductEdit_view.aod
index 687d513b1e6fbfbdf724e4835f2323124f9f0543..04a5f765b82c18a34e08728c52168bdd8f3bdd55 100644
--- a/neonView/ProductEdit_view/ProductEdit_view.aod
+++ b/neonView/ProductEdit_view/ProductEdit_view.aod
@@ -59,5 +59,10 @@
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
+    <neonViewReference>
+      <name>34659538-e8a5-4f76-9710-a322548885ef</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/ProductPreview_view/ProductPreview_view.aod b/neonView/ProductPreview_view/ProductPreview_view.aod
index b66c4446cddc5458a4088d5c0abe58ac9b662636..7e1a9a45302931054f22caa2d0d7c63019d0c67f 100644
--- a/neonView/ProductPreview_view/ProductPreview_view.aod
+++ b/neonView/ProductPreview_view/ProductPreview_view.aod
@@ -3,9 +3,10 @@
   <name>ProductPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/ProductpriceEdit_view/ProductpriceEdit_view.aod b/neonView/ProductpriceEdit_view/ProductpriceEdit_view.aod
index 958b508810443d6db2777fbfe3d5619dcfe0a044..4d0c69c899429e6c7118c605f9d60d37d2d56750 100644
--- a/neonView/ProductpriceEdit_view/ProductpriceEdit_view.aod
+++ b/neonView/ProductpriceEdit_view/ProductpriceEdit_view.aod
@@ -3,6 +3,7 @@
   <name>ProductpriceEdit_view</name>
   <title>Price list</title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/SalesprojectClassificationEntryPreview_view/SalesprojectClassificationEntryPreview_view.aod b/neonView/SalesprojectClassificationEntryPreview_view/SalesprojectClassificationEntryPreview_view.aod
index cf4ddc5040f214b04d211b2f2f53aa42606e95fc..32393670ae7d33074fcc5bc9ddd0673035992b15 100644
--- a/neonView/SalesprojectClassificationEntryPreview_view/SalesprojectClassificationEntryPreview_view.aod
+++ b/neonView/SalesprojectClassificationEntryPreview_view/SalesprojectClassificationEntryPreview_view.aod
@@ -4,9 +4,9 @@
   <title>asdf</title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+    </headerFooterLayout>
   </layout>
   <children>
     <titledListViewTemplate>
diff --git a/neonView/SalesprojectClassificationPreview_view/SalesprojectClassificationPreview_view.aod b/neonView/SalesprojectClassificationPreview_view/SalesprojectClassificationPreview_view.aod
index b6773490cfbfc248deae7412bbefd5b89a0969cc..7fc86e847504296d1b616f06fc346fb3d866b6ad 100644
--- a/neonView/SalesprojectClassificationPreview_view/SalesprojectClassificationPreview_view.aod
+++ b/neonView/SalesprojectClassificationPreview_view/SalesprojectClassificationPreview_view.aod
@@ -3,9 +3,9 @@
   <name>SalesprojectClassificationPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+    </headerFooterLayout>
   </layout>
   <children>
     <genericViewTemplate>
diff --git a/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod b/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod
index d315479fd2d8778e4c655d01681a69f172ac7bff..f07324516eb75e61d0841a18a2b4af2ae49faed7 100644
--- a/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod
+++ b/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>SalesprojectCompetitionEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/SalesprojectCompetitionPreview_view/SalesprojectCompetitionPreview_view.aod b/neonView/SalesprojectCompetitionPreview_view/SalesprojectCompetitionPreview_view.aod
index e3f46d0784614e5bfe394425774171e73e0d5b8c..bac5b4dc39e0682be2a66933ed98eca0e4427193 100644
--- a/neonView/SalesprojectCompetitionPreview_view/SalesprojectCompetitionPreview_view.aod
+++ b/neonView/SalesprojectCompetitionPreview_view/SalesprojectCompetitionPreview_view.aod
@@ -3,9 +3,10 @@
   <name>SalesprojectCompetitionPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/SalesprojectForecastEdit_view/SalesprojectForecastEdit_view.aod b/neonView/SalesprojectForecastEdit_view/SalesprojectForecastEdit_view.aod
index 366face9408918159d95b834b1d8906c2b2a1df2..626e71ea6539a7164475d7f6c829ed5d53289ad6 100644
--- a/neonView/SalesprojectForecastEdit_view/SalesprojectForecastEdit_view.aod
+++ b/neonView/SalesprojectForecastEdit_view/SalesprojectForecastEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>SalesprojectForecastEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/SalesprojectForecastPreview_view/SalesprojectForecastPreview_view.aod b/neonView/SalesprojectForecastPreview_view/SalesprojectForecastPreview_view.aod
index 1afb1bf945c05122fc551d8dbec268e4a08dd67e..8b7f0b9c84e4a46bb94aff397eb6a168831b3f13 100644
--- a/neonView/SalesprojectForecastPreview_view/SalesprojectForecastPreview_view.aod
+++ b/neonView/SalesprojectForecastPreview_view/SalesprojectForecastPreview_view.aod
@@ -3,9 +3,10 @@
   <name>SalesprojectForecastPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/SalesprojectMain_view/SalesprojectMain_view.aod b/neonView/SalesprojectMain_view/SalesprojectMain_view.aod
index d2651987d7b1400048898ae5d5ad86b2f5b670d3..2ac8547b5b4d4913bfdc9c98b2e4e1f8468f406a 100644
--- a/neonView/SalesprojectMain_view/SalesprojectMain_view.aod
+++ b/neonView/SalesprojectMain_view/SalesprojectMain_view.aod
@@ -29,6 +29,11 @@
       <entityField>SalesprojectForecasts</entityField>
       <view>SalesprojectForecastFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>8986df12-88fc-49a8-9e48-f4c1f371532f</name>
+      <entityField>#ENTITY</entityField>
+      <view>SalesprojectMilestone_view</view>
+    </neonViewReference>
     <neonViewReference>
       <name>5d7248e8-3f3e-4262-8f13-6d5eff7165c1</name>
       <entityField>SalesprojectCompetitions</entityField>
@@ -59,10 +64,5 @@
       <entityField>Documents</entityField>
       <view>DocumentFilter_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>349a82ad-4a83-4718-b37e-b0adf1ddb0b2</name>
-      <entityField>SalesprojectMilestones</entityField>
-      <view>SalesprojectMilestoneChart_view</view>
-    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/SalesprojectMemberEdit_view/SalesprojectMemberEdit_view.aod b/neonView/SalesprojectMemberEdit_view/SalesprojectMemberEdit_view.aod
index 635fc5f1b4fc56b31e2d464d342e44ee91646a1e..c8bd8886231cc4481d9680a3f30462b8169ae2f5 100644
--- a/neonView/SalesprojectMemberEdit_view/SalesprojectMemberEdit_view.aod
+++ b/neonView/SalesprojectMemberEdit_view/SalesprojectMemberEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>SalesprojectMemberEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/SalesprojectMemberPreview_view/SalesprojectMemberPreview_view.aod b/neonView/SalesprojectMemberPreview_view/SalesprojectMemberPreview_view.aod
deleted file mode 100644
index b940c76d5bfff45bebc53f5250ff63de6da233c4..0000000000000000000000000000000000000000
--- a/neonView/SalesprojectMemberPreview_view/SalesprojectMemberPreview_view.aod
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>SalesprojectMemberPreview_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <cardViewTemplate>
-      <name>Header</name>
-      <titleField>CONTACT_ID</titleField>
-      <descriptionField>SALESPROJECT_ROLE</descriptionField>
-      <entityField>#ENTITY</entityField>
-    </cardViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/SalesprojectMilestone_view/SalesprojectMilestone_view.aod b/neonView/SalesprojectMilestone_view/SalesprojectMilestone_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..603dfb9ffa5354b8fcf974e27a9befa054e5ec25
--- /dev/null
+++ b/neonView/SalesprojectMilestone_view/SalesprojectMilestone_view.aod
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>SalesprojectMilestone_view</name>
+  <title>Milestones</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <neonViewReference>
+      <name>30c775ea-7488-4dfd-8e6d-c65b7982849d</name>
+      <entityField>SalesprojectStateMilestones</entityField>
+      <view>SalesprojectMilestoneChart_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>cc8f1469-805f-4e2c-aa4f-d55f932c6deb</name>
+      <entityField>SalesprojectPhaseMilestones</entityField>
+      <view>SalesprojectMilestoneChart_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/neonView/SalesprojectPreview_view/SalesprojectPreview_view.aod b/neonView/SalesprojectPreview_view/SalesprojectPreview_view.aod
index 26ce3663b06bf4b0e809e176f0cfae3d57a98b0d..3cbdfdbad942b1e3fc8d7e6e0a7bf1b6836a24b9 100644
--- a/neonView/SalesprojectPreview_view/SalesprojectPreview_view.aod
+++ b/neonView/SalesprojectPreview_view/SalesprojectPreview_view.aod
@@ -5,6 +5,7 @@
   <layout>
     <headerFooterLayout>
       <name>layout</name>
+      <header>Head</header>
       <footer>AdditionalInfo</footer>
     </headerFooterLayout>
   </layout>
diff --git a/neonView/SalesprojectSourceEdit_view/SalesprojectSourceEdit_view.aod b/neonView/SalesprojectSourceEdit_view/SalesprojectSourceEdit_view.aod
index 5eb40994bb6928ec3a516ea10f6fb69856caa649..e022fe5f28cba9d24cab6a68cf328dd5e5c64a73 100644
--- a/neonView/SalesprojectSourceEdit_view/SalesprojectSourceEdit_view.aod
+++ b/neonView/SalesprojectSourceEdit_view/SalesprojectSourceEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>SalesprojectSourceEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/SalesprojectSourcePreview_view/SalesprojectSourcePreview_view.aod b/neonView/SalesprojectSourcePreview_view/SalesprojectSourcePreview_view.aod
index 9191fc15cb6c28165625455d7302b8b4475218c3..dd2d009711d7cdfe60217035fcc3564c588da3ca 100644
--- a/neonView/SalesprojectSourcePreview_view/SalesprojectSourcePreview_view.aod
+++ b/neonView/SalesprojectSourcePreview_view/SalesprojectSourcePreview_view.aod
@@ -3,9 +3,10 @@
   <name>SalesprojectSourcePreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/TaskFilter_view/TaskFilter_view.aod b/neonView/TaskFilter_view/TaskFilter_view.aod
index a04bd4d99520afa22000c81decd2b2f623d7caaa..71b689354145bd3359f1dc80cfa43ca8ae4510f8 100644
--- a/neonView/TaskFilter_view/TaskFilter_view.aod
+++ b/neonView/TaskFilter_view/TaskFilter_view.aod
@@ -5,8 +5,8 @@
   <filterable v="true" />
   <dashletConfigurations>
     <neonDashletConfiguration>
-      <name></name>
-      <title>MyTasks</title>
+      <name>mytasks</name>
+      <title>My tasks</title>
       <description>Show my tasks</description>
       <fragment>Task/filter</fragment>
       <singleton v="true" />
@@ -18,6 +18,12 @@
           <title>Tasks</title>
         </neonDashletCategory>
       </categories>
+      <parameters>
+        <neonDashletParameter>
+          <name>FilterOnlyOwnTask_param</name>
+          <value>true</value>
+        </neonDashletParameter>
+      </parameters>
     </neonDashletConfiguration>
   </dashletConfigurations>
   <layout>
@@ -29,7 +35,7 @@
     <timelineViewTemplate>
       <name>TasksTimeline</name>
       <dateField>MATURITY_DATE</dateField>
-      <titleField>SUBJECT</titleField>
+      <titleField>SUBJECT_DETAILS</titleField>
       <descriptionField>DESCRIPTION</descriptionField>
       <iconIdField>#ICON</iconIdField>
       <entityField>#ENTITY</entityField>
@@ -64,7 +70,7 @@
     </tableViewTemplate>
     <treeViewTemplate>
       <name>TasksTreetable</name>
-      <titleField>SUBJECT</titleField>
+      <titleField>SUBJECT_DETAILS</titleField>
       <descriptionField>DESCRIPTION</descriptionField>
       <iconField>#ICON</iconField>
       <entityField>#ENTITY</entityField>
diff --git a/neonView/TaskPreview_view/TaskPreview_view.aod b/neonView/TaskPreview_view/TaskPreview_view.aod
index 16fa80da79ee06dc6f93093c0a7054600755459d..8ebad251deea0138b7ca14dcd7cc2d9a1c69e3c0 100644
--- a/neonView/TaskPreview_view/TaskPreview_view.aod
+++ b/neonView/TaskPreview_view/TaskPreview_view.aod
@@ -3,9 +3,10 @@
   <name>TaskPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+      <header>Header</header>
+    </headerFooterLayout>
   </layout>
   <children>
     <cardViewTemplate>
diff --git a/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod b/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod
index aeaa8657f0a4ac08321c4bbfadc9f0ab9076e170..2fc9b6faccedc4fbabc072d66b670163b0e8187e 100644
--- a/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod
+++ b/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>TimetrackingEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/TimetrackingPreview_view/TimetrackingPreview_view.aod b/neonView/TimetrackingPreview_view/TimetrackingPreview_view.aod
index 140d82d9c7479f5fdc47189dc34660d51fecb982..4a5957525d9385b65959951416ff21e9a6ce35a1 100644
--- a/neonView/TimetrackingPreview_view/TimetrackingPreview_view.aod
+++ b/neonView/TimetrackingPreview_view/TimetrackingPreview_view.aod
@@ -3,9 +3,9 @@
   <name>TimetrackingPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <headerFooterLayout>
       <name>layout</name>
-    </boxLayout>
+    </headerFooterLayout>
   </layout>
   <children>
     <genericViewTemplate>
diff --git a/process/AddressValidation_lib/AddressValidation_lib.aod b/process/AddressValidation_lib/AddressValidation_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..d9b312c9ea010874d7543ac38a170160ad71c158
--- /dev/null
+++ b/process/AddressValidation_lib/AddressValidation_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>AddressValidation_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/AddressValidation_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/AddressValidation_lib/process.js b/process/AddressValidation_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..38e23ed26f06145485c267f0f5b10309b47668cd
--- /dev/null
+++ b/process/AddressValidation_lib/process.js
@@ -0,0 +1,140 @@
+import("system.vars");
+import("system.neon");
+import("system.net");
+import("system.util");
+
+/**
+ * Class used for the address validation types.
+ * Do not create new instances anywhere else than inside of the get-function!
+ * @param {String} pKey the key-name
+ * @param {String} pParamName name used by the webservice
+ */
+function AddressValidationType(pKey, pParamName) 
+{
+    this.key = pKey;
+    this.paramName = pParamName;
+}
+
+/**
+ * get all possible validation types or one specific
+ * @param {String} [pKey=undefined] if provided, this function returns only the validation type with this key
+ * 
+ * @return {Object|AddressValidationType} object containing all AddressValidationTypes or one specific AddressValidationType
+ */
+AddressValidationType.get = function(pKey)
+{
+    if (!this._cache)
+        this._cache = {
+            TYPE_ZIP: new AddressValidationType("TYPE_ZIP", "zip"),
+            TYPE_CITY: new AddressValidationType("TYPE_CITY", "city")
+        }
+    
+    if (pKey)
+        return this._cache[pKey];
+    
+    return this._cache;
+}
+
+/**
+ * Class containing utility functions for address validation
+ * do not create an instance of this
+ * 
+ * @class
+ */
+function AddressValidationUtils() {}
+
+/**
+ * validate the value with the webservice
+ * @param {String} pValue to search for
+ * @param {AddressValidationType|String} pType type used for the search. Can be an AddressValidationType or the key of the AddressValidationType
+ * @param {String} pCountry needed by the webservice e.g. "DE"
+ * 
+ * @return {String[][]} [UID,
+ *                       displayName,
+ *                       zip,
+ *                       city,
+ *                       country,
+ *                       district,
+ *                       region,
+ *                       state,
+ *                       value (the result. e.g. if pType was ZIP, the value is the found zip)
+ */
+AddressValidationUtils.validate = function(pValue, pType, pCountry)
+{
+    // TODO: Options for url, user, pw
+    var userName = "Admin";
+    var pw = "a";
+    var url = "https://services.aditosoftware.local/services/rest/ws_checkAddress";
+    var actionType = "GET";
+    
+    // get AddressValidationType-Object if it is only the key
+    if (typeof pType == "string")
+        pType = AddressValidationType.get(pType);
+    
+    if (pValue && pType)
+    {
+        // fill params
+        var parameters = {};
+        if (pCountry)
+        {
+            parameters.country = pCountry;
+        }
+        parameters[pType.paramName] = pValue;
+        
+        // call webservice
+        var ret = JSON.parse(net.callRestWebserviceBasicAuth(url, actionType, parameters, null, null, "text/plain", "text/plain", util.DATA_TEXT, util.DATA_TEXT, userName, pw, true));
+        
+        if (ret.hasHttpSuccessStatusCode)
+        {
+            // add default result consisting of pValue
+            var defaultResult = [[{}, pValue]];
+            defaultResult[0][0][pType.paramName] = pValue;
+            
+            return JSON.parse(ret.body)
+                       .concat(defaultResult)
+                       .map(function(pAddress)
+                        {
+                            var data = pAddress[0];
+                            return [
+                                JSON.stringify(data),
+                                pAddress[1],
+                                data.zip,
+                                data.city,
+                                data.country,
+                                data.district,
+                                data.region,
+                                data.state,
+                                data[pType.paramName]
+                            ]
+                        });
+        }
+        else
+        {
+           
+            // error handling
+        }
+    }
+    
+    return [];
+}
+
+/**
+ * set all address-fields by the value of $this.value, which should contain an object of all values as JSON
+ */
+AddressValidationUtils.setFields = function()
+{
+    var data = JSON.parse(vars.get("$this.value"));
+
+    _setField("$field.ZIP", data.zip);
+    _setField("$field.COUNTRY", data.country);
+    _setField("$field.CITY", data.city);
+    _setField("$field.DISTRICT", data.district);
+    _setField("$field.REGION", data.region);
+    _setField("$field.STATE", data.state);
+        
+    function _setField(pField, pValue)
+    {
+        if (pValue)
+            neon.setFieldValue(pField, pValue);
+    }
+}
\ No newline at end of file
diff --git a/process/Address_lib/Address_lib.aod b/process/Address_lib/Address_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..5e7cbd6ac0376eb634046a65ee1b9468154061fc
--- /dev/null
+++ b/process/Address_lib/Address_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>Address_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/Address_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/Address_lib/process.js b/process/Address_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..5827d6bbe88171d09a90f2236fd8bafbdec0cc98
--- /dev/null
+++ b/process/Address_lib/process.js
@@ -0,0 +1,445 @@
+import("system.swing");
+import("system.text");
+import("system.db");
+import("system.logging");
+import("system.vars");
+import("system.translate");
+import("Attribute_lib");
+import("Sql_lib");
+import("Util_lib");
+
+/*
+* Creates a Address Object
+* 
+* @param {String} pRelationID req relationid for which address should be retrieved
+* @param {String} pAddressID opt addressid for which address should be retrieved
+* @param {boolean} pPerson whether the address is from a person, not an organisation
+*  
+* @return {String} the formatted address
+*/
+
+function AddrObject( pRelationID, pPerson, pAddressID )
+{
+    this.Data = fetchAddressData( [ pRelationID ] , [["", "addressformat", ""]], pAddressID, pPerson );
+    this.fmt = this.Data[0][0][26]; 
+	
+    /*
+    * creates a formatted address
+    * 
+    * @param {boolean} pCountry whether the country should be displayed
+    * @param {String} pFormat a fixed format for the address
+    * 
+    * @return {String} formatted address
+    */
+    this.getFormattedAddress = function( pCountry, pFormat )
+    {	
+        return _formatAddrData( _getAddrData(  this.Data[0][0] ), pFormat, pCountry );
+    }
+}
+
+/*
+* creates address data
+* 
+* @param {String} pCondition req SQL-Where-Condition  
+* @param {String [[]]} pConfig req ( name, functionality, details )
+* @param {String} pSenderID opt UserRelationID
+* @param {String} pAddressID opt addressid
+* 
+* @return {[]}  Daten 
+*/
+function getAddressesData( pCondition, pConfig, pSenderID, pAddressID )
+{ 
+    var returndata = [];
+    var senderconfig = [];
+    var employeeconfig = [];
+    var config = [];
+    for ( var i = 0; i < pConfig.length; i++ )
+    {
+        var type = pConfig[i][1].split(".");
+        switch( type[0] )
+        {
+            case "employee":
+                employeeconfig.push([pConfig[i][0], type[1], pConfig[i][2]]);
+                break;
+            case "sender":
+                senderconfig.push([pConfig[i][0], type[1], pConfig[i][2]]);
+                break;
+            default:
+                config.push(pConfig[i]);
+                break;
+        } 
+    }
+    var data = getAddressData( pCondition, config, pAddressID );
+    if ( pSenderID == undefined )  pSenderID = vars.get("$global.user").relationid;
+    if ( senderconfig.length > 0 ) 
+        var senderdata = getAddressData( [ pSenderID ], senderconfig );
+    if ( employeeconfig.length > 0 ) 
+        var employeedata = getAddressData( [ vars.get("$global.user").relationid ], employeeconfig );
+    if ( data.length > 0 && ( senderconfig.length > 0 || employeeconfig.length > 0  ) )
+    { 
+        var ze = data[0];
+        if ( employeeconfig.length > 0 ) ze = ze.concat( employeedata[0] );
+        if ( senderconfig.length > 0 ) ze = ze.concat( senderdata[0] ); 
+        returndata.push(ze);
+        for ( i = 1; i < data.length; i++ )
+        {
+            ze = data[i];
+            if ( employeeconfig.length > 0 ) ze = ze.concat( employeedata[1] );
+            if ( senderconfig.length > 0 ) ze = ze.concat( senderdata[1] ); 
+            returndata.push(ze);
+        }
+        return returndata;
+    }
+    else return data;
+}
+
+/*
+* creates
+* 
+* @param {String} pCondition req SQL-Where-Condition  
+* @param {String [[]]} pConfig req ( name, functionality, details )
+* @param {String} AddressID opt addressid
+* 
+* @return {[]}  Daten 
+*/
+function getAddressData( pCondition, pConfig, AddressID )
+{ 
+    return setAddressData( fetchAddressData( pCondition, pConfig, AddressID ) );
+}
+
+/*
+* reads data from the database
+* 
+* @param {String} pCondition req SQL-Where-Condition  
+* @param {String [[]]} pConfig req ( name, functionality, details )
+* @param {String} AddressID opt addressid
+* @param {boolean} pPerson opt if private person
+* 
+* @return {[]}  data 
+*/
+function fetchAddressData( pCondition, pConfig, AddressID, pPerson )
+{ 
+    if ( typeof(pCondition) == "object") pCondition = "CONTACT.CONTACTID in ('" + pCondition.join("','") + "')";
+    if ( pConfig.length > 0 )
+    { 
+        var header = [];
+        var fields = [];
+        var output = [];
+        var pos = 0;
+        var posaddrfields = -1;
+        var functionCalls = [];
+        var addrfields = ["case when CONTACT.PERSON_ID is null then 1 else case when " + SqlMaskingUtils.prototype.trim("CONTACT.ORGANISATION_ID") + " = '0' then 2 else 3 end end", //0
+        "ADDRESS.ADDRESS", "ADDRESS.BUILDINGNO", "ADDRESS.ZIP", "ADDRESS.CITY", "ADDRESS.COUNTRY", "ADDRESS.ADDRESSADDITION",  // 1-6
+        "ADDRESS.ADDRIDENTIFIER", "ADDRESS.DISTRICT", "ADDRESS.REGION", "ADDRESS.STATE", "CONTACT.DEPARTMENT", "CONTACT.CONTACTROLE", // 7-12
+        "CONTACT.POSITION", "CONTACT.LETTERSALUTATION", "ORGANISATION.NAME", "PERSON.FIRSTNAME", "PERSON.MIDDLENAME", "PERSON.LASTNAME",  // 13-18
+        "PERSON.SALUTATION", "PERSON.TITLE", "PERSON.TITLESUFFIX", // 19-21
+        "coalesce( CONTACT.LANGUAGE, (select C.LANGUAGE from CONTACT C where C.ORGANISATION_ID = CONTACT.ORGANISATION_ID and PERSON_ID is null))", // 22
+        "''", "''", "''", "(select ADDR_FORMAT from AB_COUNTRYINFO where ISO2 = ADDRESS.COUNTRY)", "ADDRESS.ADDR_TYPE"]; // 23-27
+											
+        for (var i=0; i < pConfig.length; i++ )
+        {
+            switch( pConfig[i][1] )
+            {
+                case "fieldname": // database fields
+                    fields.push( pConfig[i][2] );
+                    output.push([pos++, pConfig[i][1]]);
+                    header.push( pConfig[i][0] );
+                    break;
+                case "function": // adito SQL functions
+                    fields.push( evalScript("Address_lib.fetchAddressData", vars.resolveVariables(pConfig[i][2]), {}, ["Attribute_lib", "Sql_lib", "Keyword_lib", "Person_lib"], true) );
+                    output.push([pos++, pConfig[i][1]]);
+                    header.push( pConfig[i][0] );
+                    break;
+                case "afunction": // adito functions
+                    try
+                    {
+                        fields.push( "'" + evalScript("Address_lib.fetchAddressData", vars.resolveVariables(pConfig[i][2]), {}, ["Attribute_lib", "Sql_lib", "Keyword_lib", "Person_lib"], true).replace(new RegExp("'","g"), "''") + "'" ); 
+                        output.push([pos++, pConfig[i][1]]);
+                        header.push( pConfig[i][0] );
+                    }
+                    catch( err )
+                    {                      
+                        logging.log( err )
+                    }
+                    break;
+                case "select": // Subselects
+                    fields.push( "(" + vars.resolveVariables(pConfig[i][2]) + " )" );
+                    output.push([pos++, pConfig[i][1]]);
+                    header.push( pConfig[i][0] );
+                    break;
+                case "addressformat": // Addressformat
+                    if ( posaddrfields == -1 )
+                    {        
+                        var sortfields = ["ORGANISATION.NAME", "PERSON.LASTNAME"];
+                        fields.push( addrfields.join(", ") );
+                        posaddrfields = pos;
+                        pos += addrfields.length;								
+                    }
+                    output.push([posaddrfields, pConfig[i][1], pConfig[i][2]]);
+                    header.push( pConfig[i][0] );
+                    break;
+                case "resolveIDFunction":
+                    var configJSON = pConfig[i][2];
+                    fields.push( configJSON.rowIDField );
+
+                    functionCalls.push([pos,
+                        configJSON.resolveFunction,
+                        configJSON.imports,
+                        configJSON.localVars]);
+                                    
+                    output.push([pos++, pConfig[i][1]]);
+                    header.push( pConfig[i][0] );                
+                    break;
+            }
+        }
+        if (!pPerson) {           
+            var sqlstr =  "select " + fields.join(",") 
+            + " from CONTACT join ORGANISATION on CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID "
+            + " left join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID "
+            + " left join ADDRESS on CONTACT.ADDRESS_ID = ";
+        } else {
+            
+            sqlstr = "select " + fields.join(",")
+            + " from CONTACT join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID "
+            + " left join ORGANISATION on CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID "
+            + " left join ADDRESS on CONTACT.ADDRESS_ID = ";
+        }
+        
+        if ( AddressID != undefined && AddressID != "" )  sqlstr += "'" + AddressID + "'"; 
+        else sqlstr += "ADDRESS.ADDRESSID";
+        if ( pCondition != "" ) sqlstr += " where " + pCondition;
+        var data = db.table(sqlstr + (sortfields != undefined ? " order by " + sortfields.join(", ") : "" ));
+
+        // loop over all returned datasets
+        for( var j = 0; j < data.length; j++)
+        {
+            // loop over all possible resolveFunction entries
+            for( var k = 0; k < functionCalls.length; k++ )
+            {
+                // get the local variables, which should be present in the function call
+                var localVars = functionCalls[k][3];
+                // add the row id value to the localVars Object so the funtion can gather the data for this dataset
+                localVars.rowIDValue = data[j][ functionCalls[k][0] ];
+                // replace the row id with its base64 string
+                data[j][ functionCalls[k][0] ] = evalScript("Address_lib.fetchAddressData.resolveFunction", 
+                    vars.resolveVariables( functionCalls[k][1]+"()" ), 
+                    localVars, 
+                    functionCalls[k][2], // imports
+                    true);
+            }
+        }
+        
+        if ( data.length == 0 ) 
+        {   
+            logging.log("Address_lib: " +  pCondition, logging.ERROR);
+            data = [[]];
+            for ( i = 0; i < addrfields.length + fields.length; i++ )   data[0].push("Err.");
+        }
+        data = [ data, output, header, addrfields ];
+    }
+    return data;
+}
+
+/*
+* reads data from the database
+* 
+* @param {String [[]]} pData req array of data
+* 
+* @return {String [[]]}  data 
+*/
+function setAddressData( pData )
+{ 
+    var sqlresult = pData[0];
+    var data = [];
+    if ( sqlresult.length > 0 )
+    {
+        var output = pData[1]; 
+        var header = pData[2];
+        var addrfields = pData[3];
+        data.push( header );
+        for ( var i = 0; i < sqlresult.length; i++ )
+        {		
+            var addrdata = [];
+            var row = [];	
+            for ( var z = 0; z < header.length; z++ )
+            {
+                switch( output[z][1] )
+                {
+                    case "fieldname":
+                    case "function":
+                    case "afunction":
+                    case "resolveIDFunction":
+                    case "select":
+                        row[z] = sqlresult[i][output[z][0]];
+                        break;
+                    case "addressformat":
+                        if (addrdata.length == 0) addrdata = _getAddrData( sqlresult[i].slice(output[z][0], output[z][0] + addrfields.length) );
+                        row[z] = _formatAddrData( addrdata, output[z][2] );
+                        break;
+                }
+            }
+            data.push( row );
+        }
+    }
+    return data;
+}
+/*
+*
+* returns formatted address data
+*
+* @param {String [[]]} pData req data 
+*
+* @return {String [[]]} formatted data
+*/
+function _getAddrData( pData )
+{
+    var lettersalutation = pData[14];
+    var salutation = pData[19];
+    var sformat = "";
+    switch( Number(pData[0]) )
+    {
+        case 1:
+            if ( lettersalutation == "" ) 
+            {
+                sformat = _getSalutation( pData[22] );
+                if ( sformat != undefined && sformat[1] != "" ) lettersalutation = _formatAddrData( pData,  sformat[1] );
+                else lettersalutation = "Sehr geehrte Damen und Herren";
+            }
+            break;
+        case 2:
+            // private -> orgname deleted
+            pData[15] = "";
+        case 3:
+            sformat = _getSalutation( pData[22] + pData[19] + pData[20] );
+            //no language defined
+            if ( sformat == undefined )  sformat = _getSalutation( pData[19] + pData[20] );
+            // no language specific entry in salutation
+            if ( sformat == undefined || sformat[0] == "" || sformat[1] == "" )	sformat = ["{sa} {ti} {fn} {la}", "{sa} {ti} {ln}"];
+            salutation = _formatAddrData( pData,  sformat[0] );
+            // lettersalutation if none existent yet
+            if( lettersalutation == "" ) lettersalutation = _formatAddrData( pData, sformat[1] );
+    }
+
+    pData[23] = salutation;
+    pData[24] = lettersalutation;
+    pData[25] = _getCountryName(pData[5]);
+    return pData;
+}
+
+/*
+* returns a formatted salutation
+* 
+* @param {String} pSalutCode req salutation code
+* 
+* @return {String} translated salutation
+*/
+function _getSalutation( pSalutCode )
+{
+    var salut = new Object();
+    if (vars.exists("$global.Salutation")) {
+        salut = vars.get("$global.Salutation");
+    }
+    else
+    {	
+        var list = db.table("select LANGUAGE, SALUTATION, TITLE, HEADLINE, LETTERSALUTATION from SALUTATION" );
+        for ( var i = 0; i < list.length; i++ )	
+        {   
+            salut[list[i][0] + list[i][1] + list[i][2]] = [list[i][3], list[i][4]];
+            salut[list[i][1] + list[i][2]] = [list[i][3], list[i][4]];
+        }
+        vars.set("$global.Salutation", salut);
+    }
+    return salut[pSalutCode];
+}
+
+/*
+* returns country names 
+*
+* @param {String} pCountryCode req countrycode
+*
+* @return {String} translated countryname
+*/
+function _getCountryName(pCountryCode)
+{
+    var countryname = new Object();
+    if ( vars.exists("$global.CountryName")) countryname = vars.get("$global.CountryName");
+    else
+    {	
+        var list = db.table("select ISO2, NAME_NATIVE from AB_COUNTRYINFO" );
+        for (var i=0; i < list.length; i++ )	countryname[list[i][0]] = translate.text(list[i][1]);
+        vars.set("$global.CountryName", countryname);
+    }
+    return countryname[pCountryCode];
+}
+
+/*
+* returns a formatted address
+*
+* @param {String [[]]} pAddrData req Address data 
+* @param {String} pFormat opt given format
+* @param {boolean} pCountry if the country should be displayed
+*
+* @return {String} formatted address
+*/
+function _formatAddrData( pAddrData, pFormat, pCountry )
+{
+    var placeholder = [["address_street", 1],["buildingno", 2],["zip", 3],["city", 4],["district", 8],["region", 9],["state", 10],["organisation_name", 15], //0-7
+    ["firstname", 16],["middlename", 17],["lastname", 18],["saluation", 19],["title", 20], ["suffix", 21], ["salutation_name", 23],["letter salutation", 24], ["country", 25]]; //8-16
+    var as = pAddrData[26];       
+    if ( pFormat != "" && pFormat != undefined) as = pFormat; 
+    as = _getFormatMapping(as, pAddrData, pCountry);
+    
+    for( var y = 0; y < placeholder.length; y++ )
+    {         
+        as = as.replace(new RegExp(placeholder[y][0], "g"), pAddrData[placeholder[y][1]]);
+        if (pAddrData[placeholder[y][1]] != undefined ) {
+            as = as.replace(new RegExp(placeholder[y][0].toUpperCase(), "g"), pAddrData[placeholder[y][1]].toUpperCase());         
+        }		
+    }
+	 	
+    as = as.replace(/^\n/, "");  // CR am Anfang entfernen;
+    as = as.replace(/  /g, " "); // doppelte leerzeichen entfernen
+    as = as.replace(/\\n/ig, "\n");	// newline marker ersetzen
+    as = as.replace(/ *\n */g, "\n");// leerzeichen am ende und Anfang entfernen
+    as = as.replace(/\s(?=\s)/g, "");	// leerzeilen rauswerfen
+    return as;
+}
+
+/*
+* returns the new format 
+*
+* @param {String [[]]} pAddrData req Daten 
+* @param {String} as req the format string
+* @param {boolean} pCountry if the country should be displayed
+*
+* @return {String} new formate
+* 
+N – Name - salutation
+O – Organisation - orgname
+A – Street Address Line(s) - address + buildingno
+D – Dependent locality - district / region
+C – City or Locality - city
+S – Administrative area - state
+Z – Zip or postal code - zip
+X – Sorting code - not available
+*/
+function _getFormatMapping(as, pAddrData, pCountry) {
+    as = as.replace(new RegExp("%N", "g"), "salutation_name");   
+    as = as.replace(new RegExp("%A", "g"), "address_street buildingno");  
+    as = as.replace(new RegExp("%C", "g"), "city");
+    as = as.replace(new RegExp("%S", "g"), "state");
+    as = as.replace(new RegExp("%Z", "g"), "zip");
+    as = as.replace(new RegExp("%O", "g"), "organisation_name");
+    as = as.replace(new RegExp("%X", "g"), "");   
+    as = as.replace(new RegExp("%n", "g"), "\n");
+    as = as.replace(new RegExp("{fn}", "g"), "firstname");
+    as = as.replace(new RegExp("{ln}", "g"), "lastname");
+    as = as.replace(new RegExp("{ti}", "g"), "title");
+    as = as.replace(new RegExp("{sa}", "g"), "salutation");
+    
+    if (pAddrData[8] == pAddrData[9])  as = as.replace(new RegExp("%D", "g"), "district");
+    else as = as.replace(new RegExp("%D", "g"), "district \n region");   
+    if(pCountry == undefined || pCountry == null || pCountry == true) as = as + "\n country";
+    
+    return as;
+}
\ No newline at end of file
diff --git a/process/Attribute_lib/process.js b/process/Attribute_lib/process.js
index af3d24d9585b86cd16d243fb69b02a0087e47aaf..a5dc1d48142c32188b217cc22ab06b5b907873b6 100644
--- a/process/Attribute_lib/process.js
+++ b/process/Attribute_lib/process.js
@@ -50,8 +50,8 @@ AttributeUtil.getPossibleAttributes = function (pObjectType, pIncludeGroups, pFi
         attrCond.andSqlCondition(filteredIdsCondition);
     }
 
-//    if (!pIncludeGroups)
-//        attrCond.and("ATTRIBUTE_TYPE != '" + $AttributeTypes.GROUP + "'");
+    if (!pIncludeGroups)
+        attrCond.and("ATTRIBUTE_TYPE != '" + $AttributeTypes.GROUP + "'");
     
     var attributes = db.array(db.COLUMN, attrCond.buildSql(attrSql));
     
@@ -155,6 +155,22 @@ AttributeUtil.hasRelations = function (pAttributeId)
     ) == "true";
 }
 
+/**
+ * returns the type of an attribute
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * 
+ * @result {String} attribute type
+ */
+AttributeUtil.getAttributeType = function (pAttributeId)
+{
+    var attrTypeSelect = "select ATTRIBUTE_TYPE from AB_ATTRIBUTE";
+    attrTypeSelect = SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
+        .buildSql(attrTypeSelect);
+    return db.cell(attrTypeSelect).trim();
+}
+
 /*********************************************************************************************************************/
 
 /**
@@ -171,25 +187,39 @@ function AttributeRelationUtils () {}
  * @param {String} pAttributeId attribute-id
  * @param {String} pObjectRowId row-id of the dataset
  * @param {String} [pObjectType=null] object-type
+ * @param {String} [pGetViewValue=false] if true the values are resolved and formatted
  * 
  * @return {String|null} the value of the attribute
  */
-AttributeRelationUtils.getAttribute = function (pAttributeId, pObjectRowId, pObjectType)
+AttributeRelationUtils.getAttribute = function (pAttributeId, pObjectRowId, pObjectType, pGetViewValue)
 {
     var attrCond = SqlCondition.begin()
-        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId)
-        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId);
+        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId)
+        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId);
     if (pObjectType != null)
-        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pAttributeId);
+        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
+    
+    var defaultFields = [
+        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
+        "AB_ATTRIBUTE.KEYWORD_CONTAINER", 
+        "COMBOVAL.ATTRIBUTE_NAME"
+    ];
+    var valueFields = AttributeTypeUtil.getAllDatabaseFields();
+    var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
+        + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
+        + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
     
-    var attributeSql = attrCond.buildSql("select ATTRIBUTE_TYPE, " + AttributeTypeUtil.getAllDatabaseFields().join(", ")
-        + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTEID");
     var attributeValues = db.array(db.ROW, attributeSql);
-    if (attributeValues.length == 0)
+    if (!attributeValues.length)
         return null;
     
-    var valueIndex = AttributeTypeUtil.getTypeColumnIndex(attributeValues[0]) + 1;
-    return attributeValues[valueIndex];
+    let value = attributeValues[AttributeTypeUtil.getTypeColumnIndex(attributeValues[0]) + defaultFields.length];
+    if (pGetViewValue && attributeValues[1].trim() == $AttributeTypes.COMBO)
+        value = attributeValues[2];
+    else if (pGetViewValue)
+        value = AttributeTypeUtil.getAttributeViewValue(attributeValues[0].trim(), value, attributeValues[1]);
+    
+    return value;
 }
 
 /**
@@ -197,139 +227,101 @@ AttributeRelationUtils.getAttribute = function (pAttributeId, pObjectRowId, pObj
  * 
  * @param {String} pObjectRowId object rowid
  * @param {String} [pObjectType=null] object-type
- * @param {String} [pResolveNames=false] if true the full attribute names are used instead of the ids
- * @param {String} [pGetUID=false] include the attributeRelation id
+ * @param {String} [pUseAttributeIds=false] if true the ids are used instead of the full attribute names
+ * @param {String} [pUseIdValues=false] if true the values are not resolved or formatted
  * 
- * @return {String[][]} two-dimensional array a row is [attributeId|attributeName, value] or if pGetUID is true, [attriuteRelationId, attributeId|attributeName, value]
+ * @return {String[][]} two-dimensional array a row is [attributeId|attributeName, value]
  */
-AttributeRelationUtils.getAllAttributes = function (pObjectRowId, pObjectType, pResolveNames, pGetUID)
+AttributeRelationUtils.getAllAttributes = function (pObjectRowId, pObjectType, pUseAttributeIds, pUseIdValues)
 {
     var attrCond = SqlCondition.begin()
         .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId);
     if (pObjectType != null)
         attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pObjectType);
     
-    var attributeSql = attrCond.buildSql("select AB_ATTRIBUTERELATIONID, AB_ATTRIBUTE_ID, AB_ATTRIBUTE.ATTRIBUTE_TYPE, AB_ATTRIBUTE.KEYWORD_CONTAINER, COMBOVAL.ATTRIBUTE_NAME, " 
-        + AttributeTypeUtil.getAllDatabaseFields().join(", ")
+    var defaultFields = [
+        "AB_ATTRIBUTE_ID", 
+        "AB_ATTRIBUTE.ATTRIBUTE_TYPE", 
+        "AB_ATTRIBUTE.KEYWORD_CONTAINER", 
+        "COMBOVAL.ATTRIBUTE_NAME"
+    ];
+    var valueFields = AttributeTypeUtil.getAllDatabaseFields();
+    var attributeSql = attrCond.buildSql("select " + defaultFields.join(", ") + ", " + valueFields.join(", ")
         + " from AB_ATTRIBUTERELATION join AB_ATTRIBUTE on AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID"
         + " left join AB_ATTRIBUTE COMBOVAL on " + $AttributeTypes.COMBO.databaseField + " = COMBOVAL.AB_ATTRIBUTEID");
     
     var attributeNameMap = {};
     var attributeValues = db.table(attributeSql).map(function (row) 
     {
-        let attribute = row[1];
-        if (pResolveNames)
+        let attribute = row[0];
+        if (!pUseAttributeIds)
         {
             if (!(attribute in attributeNameMap))
                 attributeNameMap[attribute] = AttributeUtil.getFullAttributeName(attribute);
             attribute = attributeNameMap[attribute];
         }
-        let value;
-        if (row[2].trim() == $AttributeTypes.COMBO)
-            value = row[4];
-        else
-        {
-            value = row[AttributeTypeUtil.getTypeColumnIndex(row[2]) + 5];
-            value = AttributeTypeUtil.getAttributeViewValue(row[2].trim(), value, row[3]);
-        }
-        if (pGetUID)
-            return [row[0], attribute, value];
+        let value = row[AttributeTypeUtil.getTypeColumnIndex(row[1]) + defaultFields.length];
+        if (!pUseIdValues && row[1].trim() == $AttributeTypes.COMBO)
+            value = row[3];
+        else if (!pUseIdValues)
+            value = AttributeTypeUtil.getAttributeViewValue(row[1].trim(), value, row[2]);
+        
         return [attribute, value];
     });
     
     return attributeValues;
 }
 
-AttributeRelationUtils.getAttributes = function ()
-{
-    //TODO: implement maybe
-}
-
 /**
- * sets the value of an attribute for one dataset (e. g. a person)
- */
-AttributeRelationUtils.setAttribute = function ()
-{
-    //TODO: implement
-}
-
-/*********************************************************************************************************************/
-
-/**
- * This is used in the AttributeRelation enitiy to make the work with attributes there
- * easier. You probaly won't need this for anything else.
+ * gets the correct attribute value from a map with values depending on the attribute id
  * 
- * @param {String} pAttrId the id of the attribute
- * 
- * @class
- */
-function AttributeHandler (pAttrId)   //TODO: find out if this class is necessary, maybe there is a more elegant solution, this could also be static
-{
-    this.attributeId = pAttrId;
-    this._attributeType = null;
-}
-
-/**
- * Returns a new AttributeHandler for the given Attribute
- */
-AttributeHandler.begin = function (pAttrId)
-{
-    return new AttributeHandler(pAttrId);
-}
-
-/**
- * gets the type of the attribute by the attributeId, after the first call the value
- * is stored so that the sql selection is done only once
+ * @param {String} pAttributeId the attribute id
+ * @param {Object} pValueMap a map with the attribute values and the db fields as keys
+ * @param {Boolean} [pGetViewValue=false] if true, get the view value
  * 
- * @return {String} attribute type
+ * @return {String|null} the value of the attribute or null if the attribute doesn't exist
  */
-AttributeHandler.prototype.getAttributeType = function () //TODO: maybe the type should be an own field in the entity instead of getting the type from the attribute id
+AttributeRelationUtils.selectAttributeValue = function (pAttributeId, pValueMap, pGetViewValue)
 {
-    if (this._attributeType == null && this.attributeId != null)
+    var sqlSelect = "select ATTRIBUTE_TYPE, KEYWORD_CONTAINER from AB_ATTRIBUTE";
+    var type = db.array(db.ROW, SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
+        .buildSql(sqlSelect)
+    );
+    if (!type.length)
+        return null;
+    
+    type[0] = type[0].trim();
+    var field = AttributeTypeUtil.getDatabaseField(type[0]);
+    var value = pValueMap[field];
+    if (pGetViewValue && type[0] == $AttributeTypes.COMBO)
     {
-        var attrTypeSelect = "select ATTRIBUTE_TYPE from AB_ATTRIBUTE";
-        attrTypeSelect = SqlCondition.begin()
-            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", this.attributeId)
-            .buildSql(attrTypeSelect);
-        this._attributeType = db.cell(attrTypeSelect).trim();
+        value = db.cell(SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", value)
+            .buildSql("select ATTRIBUTE_NAME from AB_ATTRIBUTE")
+        );
     }
-    return this._attributeType;
+    else if (pGetViewValue)
+        value = AttributeTypeUtil.getAttributeViewValue(type[0], value, type[1]);
+    
+    return value;
 }
 
-/**
- * returns the field that belongs to the type of the attribute
- * 
- * @return {String} attribute field
- */
-AttributeHandler.prototype.getAttributeField = function ()
+AttributeRelationUtils.getAttributes = function ()
 {
-    return AttributeTypeUtil.getEntityField(this.getAttributeType());
+    //TODO: implement maybe
 }
 
 /**
- * returns the content type that belongs to the type of the attribute
- * 
- * @return {String} attribute field
+ * sets the value of an attribute for one dataset (e. g. a person)
  */
-AttributeHandler.prototype.getAttributeContentType = function ()
+AttributeRelationUtils.setAttribute = function ()
 {
-    return AttributeTypeUtil.getContentType(this.getAttributeType());
+    //TODO: implement
 }
 
-/**
- * Sets the value to the AttributeField and also return s the value again.
- * 
- * @param pValue the value
- * 
- * @return {Any} the value
- */
-AttributeHandler.prototype.setAttributeValue = function (pValue)
-{
-    var field = "$field." + this.getAttributeField();
-    if (field != null && vars.exists(field))
-        neon.setFieldValue(field, pValue)
-    return pValue;
-}
+/*********************************************************************************************************************/
+
 
 /**
  * Object for the enumeration and management of all attribute types.
@@ -341,7 +333,6 @@ AttributeHandler.prototype.setAttributeValue = function (pValue)
  * keyword = the key of the corresponding keyword
  * contentType = the value that is returned in the contentType process for the attribute
  * databaseField = the database field that holds values of attributes with the type
- * entityField = the field in the AttributeRelation enity that holds the value of the attribute for that type
  * 
  * The display name is controlled by the keyword 'AttributeType'
  */
@@ -351,15 +342,13 @@ $AttributeTypes.TEXT = {
     toString : function () {return this.keyword},
     keyword : "TEXT",
     contentType : "TEXT", 
-    databaseField : "CHAR_VALUE", 
-    entityField : "CHAR_VALUE"
+    databaseField : "CHAR_VALUE"
 };
 $AttributeTypes.DATE = {
     toString : function () {return this.keyword},
     keyword : "DATE",
     contentType : "DATE", 
-    databaseField : "DATE_VALUE", 
-    entityField : "DATE_VALUE",
+    databaseField : "DATE_VALUE",
     getViewValue : function (pValue)
         {
             return datetime.toDate(pValue, translate.text("dd.MM.yyyy"));
@@ -369,15 +358,13 @@ $AttributeTypes.NUMBER = {
     toString : function () {return this.keyword},
     keyword : "NUMBER",
     contentType : "NUMBER", 
-    databaseField : "NUMBER_VALUE", 
-    entityField : "NUMBER_VALUE"
+    databaseField : "NUMBER_VALUE"
 };
 $AttributeTypes.BOOLEAN = {
     toString : function () {return this.keyword},
     keyword : "BOOLEAN",
     contentType : "BOOLEAN", 
-    databaseField : "INT_VALUE", 
-    entityField : "INT_VALUE",
+    databaseField : "INT_VALUE",
     getViewValue : function (pValue)
         {
             return pValue == "1" ? translate.text("Yes") : translate.text("No");
@@ -387,35 +374,45 @@ $AttributeTypes.COMBO = {
     toString : function () {return this.keyword},
     keyword : "COMBO",
     contentType : "UNKNOWN",
-    databaseField : "ID_VALUE", 
-    entityField : "ID_VALUE"
+    databaseField : "ID_VALUE",
+    isGroup : true
 };
 $AttributeTypes.COMBOVALUE = {
     toString : function () {return this.keyword},
     keyword : "COMBOVALUE",
     contentType : null, 
-    databaseField : null, 
-    entityField : null
+    databaseField : null
 };
 $AttributeTypes.GROUP = {
     toString : function () {return this.keyword},
     keyword : "GROUP",
     contentType : null, 
-    databaseField : null, 
-    entityField : null
+    databaseField : null,
+    isGroup : true
 };
 $AttributeTypes.KEYWORD = {
     toString : function () {return this.keyword},
     keyword : "KEYWORD",
     contentType : "UNKNOWN", 
     databaseField : "ID_VALUE", 
-    entityField : "ID_VALUE",
     getViewValue : function (pValue, pKeyword)
         {
             return KeywordUtils.getViewValue(pKeyword, pValue);
         }
 };
-
+$AttributeTypes.VOID = {
+    toString : function () {return this.keyword},
+    keyword : "VOID",
+    contentType : null,
+    databaseField : null,
+    isGroup : true
+};
+$AttributeTypes.MEMO = { 
+    toString : function () {return this.keyword},
+    keyword : "MEMO",
+    contentType : "LONG_TEXT", 
+    databaseField : "CHAR_VALUE"
+};
 
 function AttributeTypeUtil () {}
 
@@ -434,16 +431,16 @@ AttributeTypeUtil.getContentType = function (pAttributeType)
 }
 
 /**
- * returns the entity field for the given attribute type that holds the value of the attribute
+ * returns if the type is a group type
  * 
  * @param {String} pAttributeType the attribute type 
  *                  (use the values of the AttributeTypes object, e. g. AttributeTypes.TEXT)
- * @return {String} the field for the attribute
+ * @return {Boolean} if the type is a group type
  */
-AttributeTypeUtil.getEntityField = function (pAttributeType)
+AttributeTypeUtil.isGroupType = function (pAttributeType)
 {
     if (pAttributeType in $AttributeTypes)
-        return $AttributeTypes[pAttributeType].entityField;
+        return $AttributeTypes[pAttributeType].isGroup || false;
     return null;
 }
 
diff --git a/process/Calendar_lib/process.js b/process/Calendar_lib/process.js
index 232cf4c3be3db1c4c5a3f0dc30769600b30cd180..d7e20bff690a2d93e1bd7270d1c8e224d07a7091 100644
--- a/process/Calendar_lib/process.js
+++ b/process/Calendar_lib/process.js
@@ -1,1903 +1,1907 @@
-import("system.neon");
-import("system.vars");
-import("system.db");
-import("system.translate");
-import("system.datetime");
-import("system.swing");
-import("system.eMath");
-import("system.calendars");
-import("system.logging");
-import("system.tools");
-import("system.text");
-import("system.question");
-import("system.SQLTYPES");
-import("system.result");
-import("Util_lib");
-import("system.util")
-
-
-/**
- *  @class
- **/
-function CalendarUtil(){}
-
-
-/*
- * Erzeugt und öffnet ein neues Aufgabenobjekt (mit einem Link).
- *
- * @param {String} pSummary opt die Zusammenfassung
- * @param {String} pDescription opt die Beschreibung
- * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
- * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
- *                                   pWithLink[1]: ID des angezeigten Datensatzes
- *                                   pWithLink[2]: Verknüpfungstitel
- * @param {String} pUser opt der Benutzer ( Login )
- * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
- * @param {date} pStart opt Beginn der Aufgabe
- * @param {date} pDuration opt Dauer
- * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
- * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
- * @param {Array{[]} pComps4Refresh opt die zu aktualisierenden Komponenten
- *
- * @return {void}
- */
-CalendarUtil.newTodo = function(pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh)
-{
-    var todo = createEntry( calendars.VTODO, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus );
-    var prompts = [];
-    prompts["comp4refresh"] = [];
-
-    if (pComps4Refresh == undefined)
-        pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Aufgabe"];
-
-    for (var i = 0; i < pComps4Refresh.length; i++)
-    {
-        if ( vars.exists(pComps4Refresh[i]))    prompts["comp4refresh"].push(pComps4Refresh[i]);
-    }
-    if(vars.getString("$sys.scope") == "vaadin")
-        neon.openCalendarEntry([todo], null, neon.OPERATINGSTATE_NEW, null)
-    else
-    {
-        if (vars.exists("$sys.currentwindow"))
-            prompts["window"] = vars.getString("$sys.currentwindow");
-        if (vars.exists("$sys.currentimage"))
-            prompts["image"] = vars.getString("$sys.currentimage");
-
-        swing.openCalendarEntry([todo], null, false, prompts);
-    }
-}
-
-/*
- * Erzeugt eine neue Aufgabe (mit einem Link).
- *
- * @param {String} pSummary opt die Zusammenfassung
- * @param {String} pDescription opt die Beschreibung
- * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
- * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
- *                		     pWithLink[1]: ID des angezeigten Datensatzes
- *               		     pWithLink[2]: Verknüpfungstitel
- * @param {String} pUser opt der Benutzer ( Login )
- * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
- * @param {date} pStart opt Beginn der Aufagebe
- * @param {integer} pGroupType opt ( calendars.GROUP_SINGLE , calendars.GROUP_MULTI )
- * @param {date} pDuration opt Dauer
- * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
- * @param {String} pStatus opt Status der Aufgabe ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
- * @param {String} pPriority opt Priorität der Aufgabe
- * @param {String} pReminder opt Erinnerung der Aufgabe
- *
- * @return {void}
- */
-
-CalendarUtil.newSilentTodo = function(pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pGroupType, pCategory, pStatus, pPriority, pReminder)
-{
-    if ( pGroupType == undefined ) pGroupType = calendars.GROUP_SINGLE;
-    var todo = createEntry( calendars.VTODO, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pPriority, pReminder );
-    
-    return calendars.insert([todo],calendars.GROUP_SINGLE);
-}
-
-/*
- * Erzeugt und öffnet ein neues Terminnobjekt mit einem Link.
- *
- * @param {String} pSummary opt die Zusammenfassung
- * @param {String} pDescription opt die Beschreibung
- * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
- * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
- *                		     pWithLink[1]: ID des angezeigten Datensatzes
- *               		     pWithLink[2]: Verknüpfungstitel
- * @param {String} pUser opt der Benutzer ( Login )
- * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
- * @param {date} pStart opt Beginn der Aufagebe
- * @param {date} pDuration opt Dauer
- * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
- * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
- * @param {Array{[]} pComps4Refresh opt die zu aktualisierenden Komponenten
- * 
- * @return {void}
- */
-CalendarUtil.newEvent = function( pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh, pWorklistId)
-{
-    var event = createEntry( calendars.VEVENT, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus );
-
-    var prompts = [];
-    prompts["comp4refresh"] = [];
-    if (pComps4Refresh == undefined)
-        pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Termine"];
-    for (i = 0; i < pComps4Refresh.length; i++)
-    {
-        if ( vars.exists(pComps4Refresh[i]))    prompts["comp4refresh"].push(pComps4Refresh[i]);
-    }
-
-    if(vars.getString("$sys.scope") == "vaadin")
-        neon.openCalendarEntry([event],"", neon.OPERATINGSTATE_NEW, null)
-    else
-    {
-        prompts["window"] = vars.getString("$sys.currentwindow");
-        prompts["image"] = vars.getString("$sys.currentimage");
-        if (pWorklistId != undefined)
-            prompts["worklistId"]   = pWorklistId;
-        swing.openCalendarEntry([event], null, false, prompts);
-    }
-}
-
-
-/*
- * Erzeugt einen neuen Termineintrag (mit einem Link).
- *
- * @param {String} pSummary opt die Zusammenfassung
- * @param {String} pDescription opt die Beschreibung
- * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
- * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
- *                		     pWithLink[1]: ID des angezeigten Datensatzes
- *                		     pWithLink[2]: Verknüpfungstitel
- * @param {String} pUser opt der Benutzer ( Login )
- * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
- * @param {date} pStart opt Beginn des Termins
- * @param {date} pDuration opt Dauer
- * @param {integer} pGroupType opt ( calendars.GROUP_SINGLE , calendars.GROUP_MULTI )
- * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
- * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
- * @param {String} pReminder opt Erinnerung des Termins
- *
- * @return {void}
- */
-CalendarUtil.newSilentEvent = function( pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pGroupType, pCategory, pStatus, pReminder)
-{
-    if ( pGroupType == undefined ) pGroupType = calendars.GROUP_SINGLE;
-    var event = createEntry( calendars.VEVENT, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, undefined, pReminder );
-    return calendars.insert( [event] , pGroupType );
-}
-
-/*
- * Erzeugt ein neues Aufgaben- / Termin-Objekt (mit einem Link).
- *
- * @param {date} pType req  Augabe oder Termin ( calendars.VTODO, calendars.VEVENT )
- * @param {String} pSummary opt die Zusammenfassung
- * @param {String} pDescription opt die Beschreibung
- * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
- * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
- *                		     pWithLink[1]: ID des angezeigten Datensatzes
- *                		     pWithLink[2]: Verknüpfungstitel
- * @param {String} pUser opt der Benutzer ( Login )
- * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( [ Login ] )
- * @param {date} pStart opt Beginn
- * @param {date} pDuration opt Dauer
- * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
- * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
- * @param {String} pPriority opt Priorität
- * @param {String} pReminder opt Erinnerung
- *
-@return {Object} das EntryObjekt
- */
-CalendarUtil.createEntry = function( pType, pSummary, pDescription, pWithLink, pAppLinkContext, pAppLinkId, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pPriority, pReminder )
-{
-    var Entry = {};
-    var framename;
-    var framdata;
-    var dbid;
-    var linktitle;
-    if ( pSummary == undefined || pSummary == null  ) pSummary = "";
-    if ( pDescription == undefined || pDescription == null )
-    {
-        if(vars.getString("$sys.scope") == "vaadin")
-            pDescription = neon.getImageContent(vars.getString("$sys.currententityname"));
-        else
-            pDescription = swing.getImageContent();
-    }
-    if ( pUser == undefined || pUser == null ) pUser = vars.getString("$sys.user");
-    //kein translate.key hier, weil es sich um einen rein technischen Wert handelt:
-    if ( pStart == undefined ) pStart = datetime.toLong(datetime.toDate(parseInt(vars.getString("$sys.date")) + datetime.ONE_HOUR, "dd.MM.yyyy HH:00"), "dd.MM.yyyy HH:mm");
-    if ( pCategory == undefined || pCategory == null  ) pCategory = "";
-
-    if (pAffectedUsers == null || pAffectedUsers == undefined )
-    {
-        Entry[calendars.AFFECTEDUSERS] = "";
-    }
-    else
-    {
-        Entry[calendars.AFFECTEDUSERS] = text.encodeMS(calendars.getCalendarUsers(pAffectedUsers));
-    }
-    Entry[calendars.TYPE] = pType;
-    Entry[calendars.DTSTART] = pStart;
-    if ( pType == calendars.VEVENT )
-    {
-        if ( pDuration == undefined )
-            pDuration = datetime.ONE_HOUR;
-
-        Entry[calendars.DTEND] = String ( eMath.addInt( pStart, pDuration) );
-
-        if ( pStatus == undefined )
-            pStatus = calendars.STATUS_CONFIRMED;
-
-        pStatus = mapCalendarStatus(pStatus, calendars.getBackendType() );
-    }
-    else if ( pType == calendars.VTODO )
-    {
-        //kein translate.key hier, weil es sich um einen rein technischen Wert handelt:
-        if ( pDuration != undefined )
-            Entry[calendars.DUE] = String ( eMath.addInt( pStart, pDuration) );
-        else
-            Entry[calendars.DUE] = datetime.toLong(datetime.toDate(pStart, "dd.MM.yyyy 23:59")
-                ,"dd.MM.yyyy HH:mm");
-
-        if ( pStatus == undefined )
-            pStatus = calendars.STATUS_NEEDSACTION;
-
-        pStatus = mapCalendarStatus(pStatus, calendars.getBackendTypeTasks() );
-        
-    }
-
-    Entry[calendars.USER] = calendars.getCalendarUser(pUser);
-    Entry[calendars.DESCRIPTION] = pDescription;
-    Entry[calendars.SUMMARY] = pSummary;
-    Entry[calendars.STATUS] = pStatus;
-    Entry[calendars.CLASSIFICATION] = calendars.CLASSIFICATION_PUBLIC;
-    Entry[calendars.CATEGORIES] = pCategory;
-   
-
-    if( pPriority != undefined )
-    {
-        Entry[calendars.PRIORITY] = pPriority;
-    }
-
-    if( pReminder != undefined)
-    {
-        Entry[calendars.HASREMINDER] = "true";
-        Entry[calendars.REMINDER_DURATION] = pReminder;
-    }
-    else
-        Entry[calendars.HASREMINDER] = "false";
-   
-
-    if (pWithLink == false)
-    {
-        Entry[calendars.LINKS] = "0";
-    }
-    else
-    {
-        var fd = new FrameData();
-        if ( typeof(pWithLink) == "object" )
-        {
-            for ( var li = 0; li < pWithLink.length; li++ )
-            {
-                framename = pWithLink[li][0];
-                framdata = fd.getData("name", framename, ["table","idcolumn","title"])[0];
-                dbid = pWithLink[li][1];
-                linktitle = framdata[2] + " - " + pWithLink[li][2];
-
-                Entry["LINK_ALIAS_" + ( li + 1 )] = vars.getString("$sys.dbalias");
-                Entry["LINK_TABLE_" + ( li + 1 )] = framdata[0];
-                Entry["LINK_IDCOLUMN_" + ( li + 1 )] = framdata[1];
-                Entry["LINK_DBID_" + ( li + 1 )] = dbid;
-                Entry["LINK_FRAME_" + ( li + 1 )] = "comp." + framename;
-                Entry["LINK_TITLE_" + ( li + 1 )] = linktitle;
-            }
-            Entry[calendars.LINKS] = pWithLink.length.toString();
-        }
-        else
-        {
-            if ( pWithLink == true || pWithLink == undefined )
-            {
-                framename = vars.getString("$sys.currentimagename");
-                framdata = fd.getData("name", framename, ["table","idcolumn","title"])[0];
-                dbid = vars.getString("$comp.idcolumn");
-                linktitle = framdata[2] + " - " + swing.getImageContent();
-            }
-            Entry[calendars.LINKS] = "1";
-            Entry["LINK_ALIAS_1"] = vars.getString("$sys.dbalias");
-            Entry["LINK_TABLE_1"] = framdata[0];
-            Entry["LINK_IDCOLUMN_1"] = framdata[1];
-            Entry["LINK_DBID_1"] = dbid;
-            Entry["LINK_FRAME_1"] = "comp." + framename;
-            Entry["LINK_TITLE_1"] = linktitle;
-        }
-    }
-    
-
-if(pAppLinkContext && pAppLinkId)
-{
-    Entry["AppLinkContext"] = pAppLinkContext;
-    Entry["AppLinkId"] = pAppLinkId;
-}
-    return Entry;
-}
-
-/*
- * Liefert den CalendarStatus übersetzt zurück.
- * @param {String} pStatus req Status
- * @param {String} pLanguage opt Sprache
- * @param {String} pKind opt ToDo oder Event
- *
- * @return {String} übersetzte Status
- */
-function getCalendarStatus( pStatus, pLanguage, pKind)
-{
-    //kein mappen des Status, da wirklich verschiedene Dinge angezeigt werden sollen
-    switch ( pStatus )
-    {
-        case calendars.STATUS_BUSY: 
-            return translate.text("Gebucht", pLanguage)
-        case calendars.STATUS_CANCELLED:
-            if(pKind == "ToDo" && pKind != undefined) return translate.text("Zurückgestellt", pLanguage)
-            return translate.text("Abgesagt", pLanguage)
-        case calendars.STATUS_COMPLETED:
-            return translate.text("Erledigt", pLanguage)
-        case calendars.STATUS_CONFIRMED:
-            return translate.text("Bestätigt", pLanguage)
-        case calendars.STATUS_FREE:
-            return translate.text("frei", pLanguage)
-        case calendars.STATUS_INPROCESS:
-            return translate.text("In Bearbeitung", pLanguage)
-        case calendars.STATUS_NEEDSACTION:
-            return translate.text("Nicht begonnen", pLanguage)
-        case calendars.STATUS_OOF:
-            return translate.text("Außer Haus", pLanguage)
-        case calendars.STATUS_TENTATIVE:
-            return translate.text("Vorläufig", pLanguage)
-        default:
-            return "";
-    }
-}
-
-/*
- * Zu einer übergebenen Priorität wird ihre Bedeutung übersetzt und zurückgegeben.
- *
- * @param {String} pPriority req Priorität
- * @param {String} pLanguage opt Sprache
- *
- * @return (String) übersetzte Bedeutung einer Priorität
- */
-function getCalendarPriority(pPriority, pLanguage)
-{
-    switch(pPriority)
-    {
-        case "9":
-            return translate.text("niedrig", pLanguage);
-            break;
-        case "5":
-            return translate.text("normal", pLanguage);
-            break;
-        case "1":
-            return translate.text("hoch", pLanguage);
-            break;
-        default:
-            return translate.text("keine", pLanguage);
-            break;
-    }
-}
-
-/*
- * Liefert zum Objekt verknüpfte Aufgaben aus dem Kalender.
- *
- * @param {String} pFrame req Name des Frames
- * @param {String} pDBID req ID des verknüpften Datensatzes
- * @param {String} pAlias opt
- * @param {String} pLanguage opt Sprache
- *
- * @return {[]} mit Aufgaben aus Kalender
- */
-function getLinkedToDos (pFrame, pDBID, pAlias, pLanguage )
-{
-    if (pAlias == undefined ) pAlias = vars.getString("$sys.dbalias");
-    var tab = [];
-    var status = " and STATUS in ('NEEDS-ACTION', 'IN-PROCESS')";
-    var exists = [];
-    var zustaendig = "";
-    var today = getDate(vars.getString("$sys.date"));
-    var filtervalues = ["", "false"];
-    if ( vars.exists("$image.FilterValuesT") )
-    {
-        filtervalues = vars.get("$image.FilterValuesT");
-        zustaendig = filtervalues[0]
-        if (filtervalues[1] == "true") status = " and STATUS in ('COMPLETED', 'CANCELLED')";
-    }
-
-    var entryids = db.table("select ENTRYID, OWNER from ASYS_CALENDARLINK "
-        + "join ASYS_CALENDARBACKEND on ELEMENTUID = ENTRYID where FRAME = 'comp." + pFrame + "' "
-        + "and ENTRYID is not null "
-        + "and ENTRYTYPE = " + calendars.VTODO + " "
-        + "and DBID = '" + pDBID + "' "
-        + status, pAlias);
-
-    for (var i = 0; i < entryids.length; i++)
-    {
-        if ( exists.indexOf(entryids[i][0]) == -1)
-        {
-            try
-                {
-                    var entry = calendars.getEntry(entryids[i][0], null, getTitleCalenderUser( entryids[i][1] ), calendars.VTODO);
-                    var entr = new Array;
-                    status = "";
-                    var user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
-                    if(user == null) user = entry[calendars.USER2]["cn"];
-                     else user = user[tools.TITLE]
-                    if ((user == zustaendig || zustaendig == ""))
-                    {
-                        entr[0] = text.encodeMS([entry[calendars.ID], user]);
-                        var due = getDate(entry[calendars.DUE]);
-                        if (due < today ) entr[1]	= "-1769402";
-                        else  if (due > today) entr[1]	= "-16777216"; else entr[1]	= "-16744020";
-                        entr[2] = "-1";  // Hintergrundfarbe
-                        entr[3] = text.decodeMS(entry[calendars.AFFECTEDUSERS]).length;
-                        entr[4] = entry[calendars.DUE]
-                        entr[5] = getCalendarStatus( entry[calendars.STATUS], pLanguage, "ToDo");
-                        entr[6] = entry[calendars.SUMMARY]
-                        entr[7] = getRealName([entry[calendars.ORGANIZER2]]);
-                        entr[8] = getRealName(entry[calendars.ATTENDEES]);
-                        entr[9] = entry[calendars.DESCRIPTION];
-                        entr[10] = entry[calendars.PRIORITY];
-                        tab.push(entr);
-                        exists.push(entryids[i][0]);
-                    }
-            }
-            catch (ex)
-            {
-                logging.log(ex);
-            }
-        }
-    }
-    array_mDimSort(tab, 4, false); //Sortierung nach Fälligkeitsdatum
-    return tab;
-}
-
-/*
- * Anzeige des Aufgaben-Filter
- *
- * @param {Object} pFilter req
- *
- * @return string Anzeige
- */
-function show_filterLinkedToDos(pFilter)
-{
-    var retstring = "";
-    if (pFilter[0] != "")
-    {
-        var userp = tools.getUser( pFilter[0] )[tools.PARAMS];
-        retstring = translate.text("Aufgaben von") + " " + userp[tools.FIRSTNAME] + " " + userp[tools.LASTNAME];
-    }
-    if (pFilter[1] == "true") retstring += ", " + translate.text("erledigt / zurückgestellt");
-
-    return retstring
-}
-
-/*
- * Liefert zum Objekt verknüpfte Events aus dem Kalender.
- *
- * @param {String} pFrame req Name des Frames
- * @param {String} pDBID req ID des verknüpften Datensatzes
- * @param {Object} pFilter opt
- * @param {String} pAlias opt
- * @param {String} pUser opt Benutzer
- *
- * @return {[]} mit Events aus Kalender
- */
-function getLinkedEvents (pFrame, pDBID, pFilter, pAlias, pUser )
-{
-    if ( pFilter == "" || pFilter == undefined)
-        pFilter = reset_filterEvent();
-
-    var tab = [];
-    var exists = [];
-    var conditions = [];
-    var today = getDate(vars.getString("$sys.date"));
-    var conditioncount = 0;
-    var stati = [];
-
-    if ( pFilter.tentative == "true" )
-        stati.push(mapCalendarStatus(calendars.STATUS_TENTATIVE, calendars.getBackendType() ));
-
-    if ( pFilter.cancelled == "true" )
-        stati.push(mapCalendarStatus(calendars.STATUS_CANCELLED, calendars.getBackendType() ));
-
-    if ( pFilter.confirmed == "true" )
-        stati.push(mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
-
-    if (calendars.getBackendType() == calendars.BACKEND_EXCHANGEWS)
-        stati.push(calendars.STATUS_FREE);
-
-    if (pAlias == undefined ) pAlias = vars.getString("$sys.dbalias");
-
-    var entryids = db.table(["select ENTRYID, OWNER "
-        + "from ASYS_CALENDARLINK "
-        + "join ASYS_CALENDARBACKEND on ELEMENTUID = ENTRYID where FRAME = 'comp."
-        + pFrame + "' and ENTRYID is not null and ENTRYTYPE = " + calendars.VEVENT
-        + " and DBID = '" + pDBID + "' and DTSTART >= ?",
-        [ [ String(pFilter.datefrom - datetime.ONE_WEEK), SQLTYPES.DATE ]]], pAlias );
-
-    /*
-     * Check for rights before constructing condition otherwise you'll get an error by opening linked Data
-     */
-    var userToRead = []
-    if(pUser != undefined)
-    {
-        userToRead = getCalendarUsers( calendars.RIGHT_READ_APPOINTMENT, pUser );
-    }
-    else
-    {
-        userToRead = calendars.getDisplayCalendarUsers(calendars.RIGHT_READ_APPOINTMENT);
-    }
-    var userMap = {};
-    for (let i = 0; i < userToRead.length; i++)
-    {
-        userMap[userToRead[i][1]] = true;
-    }
-
-    for ( var i = 0;i < entryids.length; i++)
-    {
-        var user = getTitleCalenderUser(entryids[i][1]);
-        if(userMap[user])
-        {
-            for ( var z = 0; z < stati.length; z++ )
-                _addEntryCondition(conditions, String(++conditioncount),
-                {
-                    TYPE: calendars.VEVENT,
-                    START: pFilter.datefrom,
-                    END: pFilter.dateto,
-                    USER: user,
-                    STATUS: stati[z],
-                    UID: entryids[i][0]
-                });
-        } else continue
-    }
-    conditions["COUNT"] = String(conditioncount);
-
-    var entries = calendars.getExpandedEntries(conditions, pFilter.datefrom, pFilter.dateto);
-    for ( let i = 0; i < entries.length; i++)
-    {
-        for (var j = 0; j < entries[i].length; j++)
-        {
-            var entry = entries[i][j];
-            if( exists.indexOf(entry[calendars.ID]) == -1 && ( pFilter.category == "" || text.decodeMS(entry[calendars.CATEGORIES]).indexOf(pFilter.category) > 0))
-            {
-                var entr = new Array;
-                var start = getDate(entry[calendars.DTSTART]);
-                var end = getDate(entry[calendars.DTEND]);
-                user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
-                if(user == null) user = entry[calendars.USER2]["cn"];
-                 else user = user[tools.TITLE]
-                entr[0] = text.encodeMS([entry[calendars.ID], user , entry[calendars.RECURRENCEID]]);
-                if (end < today) entr[1]	= "-6710887" ;
-                else if (start <= today && end >= today )   entr[1] = "-16744020" ;
-                else entr[1] = "-16777216";
-                entr[2] = "-1"
-                entr[3] = text.decodeMS(entry[calendars.AFFECTEDUSERS]).length;
-                entr[4] = entry[calendars.DTSTART]
-                entr[5] = entry[calendars.DTEND]
-                entr[6] = entry[calendars.SUMMARY]
-                entr[7] = getRealName([entry[calendars.ORGANIZER2]]);
-                entr[8] = getRealName(entry[calendars.ATTENDEES]);
-                entr[9] = entry[calendars.DESCRIPTION]
-                tab.push(entr);
-                exists.push(entry[calendars.ID]);
-            }
-        }
-    }
-    array_mDimSort(tab, 4, false);
-    return tab;
-}
-
-/*
- * Liefert Aufgaben aus dem Kalender.
- *
- * @param {Object} pFilter req
- * @param {String} pLanguage opt
- * @param {bool} pShortForm opt wenn true wird nur die kurzversion geladen
- *
- * @return {[]} mit allen aufgaben aus dem Kalender
- */
-function getTodos( pFilter, pLanguage, pShortForm )
-{
-    if ( pFilter == "" )    pFilter =  reset_filterToDo();
-    var tab = [];
-    var today = getDate (vars.getString("$sys.date"));
-    var conditions = [];
-    var conditioncount = 0;
-    var user = pFilter.user;
-    var stati = [];
-    var status = [];
-    var exists = [];
-    var entries = [];
-
-    if ( pFilter.needs_action == "true" )
-    {
-        stati.push(mapCalendarStatus(calendars.STATUS_NEEDSACTION, calendars.getBackendTypeTasks() ));
-        status.push("NEEDS-ACTION");
-    }
-    if ( pFilter.in_process == "true" )
-    {
-        stati.push(mapCalendarStatus(calendars.STATUS_INPROCESS, calendars.getBackendTypeTasks() ));
-        status.push("IN-PROCESS");
-    }
-    if ( pFilter.completed == "true" )
-    {
-        stati.push(mapCalendarStatus(calendars.STATUS_COMPLETED, calendars.getBackendTypeTasks() ));
-        status.push("COMPLETED");
-    }
-    if ( pFilter.cancelled == "true" )
-    {
-        stati.push(mapCalendarStatus(calendars.STATUS_CANCELLED, calendars.getBackendTypeTasks() ));
-        status.push("CANCELLED");
-    }
-    if (pFilter.delegated == "true" )
-    {
-        var from = [pFilter.datefrom, SQLTYPES.TIMESTAMP];
-        var to = [pFilter.dateto, SQLTYPES.TIMESTAMP];
-        setAllCalendarGrant();
-        user = calendars.getCalendarUser(user);
-        user = db.table(["select ELEMENTUID, OWNER from ASYS_CALENDARBACKEND where ENTRYTYPE = 2 and OWNER != '" + user + "' and ORGANIZER = '"
-            + user + "' and STATUS in ('" + status.join("', '") + "') and (( STARTTIME >= ? and STARTTIME <= ?) or "
-            + "( ENDTIME >= ? and ENDTIME <= ? ) or ( STARTTIME >= ? and ENDTIME <= ? ))", [from, to, from, to, from, to]] );
-
-        for (let i = 0; i < user.length; i++ )
-        {
-            try
-            {
-                entries.push([calendars.getEntry(user[i][0], null, getTitleCalenderUser(user[i][1]), calendars.VTODO)]);
-            }
-            catch(err){
-                logging.log(err);
-            }
-        }
-        setCalendarGrant();
-    }
-    else
-    {
-        if ( typeof( pFilter.user ) != "object" )  user = [user.trim()];
-        for (let i = 0; i < user.length; i++ )
-        for ( var z = 0; z < stati.length; z++ )
-            _addEntryCondition(conditions, ++conditioncount,
-            {
-                TYPE: calendars.VTODO,
-                START: pFilter.datefrom,
-                END: pFilter.dateto,
-                USER: user[i],
-                STATUS: stati[z]
-            });
-
-        conditions["COUNT"] = String(conditioncount);
-        entries = calendars.getEntries(conditions);
-    }
-
-    for (i = 0; i < entries.length; i++)
-    {
-        var entry = entries[i][0];
-        user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
-        if (user == null)  user = entry[calendars.USER2]["cn"];
-         else user = user[tools.TITLE]
-        if ( !(user != vars.getString("$sys.user") && entry[calendars.CLASSIFICATION] == calendars.CLASSIFICATION_PRIVATE) // no privat
-            && !( pFilter.delegated == "true" && ( isAffectedUser( entry, pFilter.user) || exists.indexOf(entry[calendars.ID]) > -1  ) ) // no duplicate
-            && ( pFilter.category == "" || text.decodeMS(entry[calendars.CATEGORIES]).indexOf( pFilter.category ) > -1 ) ) // Filter category
-            {
-            var entr = [];
-            var links =  entry[calendars.LINKS];
-            var due = entry[calendars.DUE] != "" ? getDate(entry[calendars.DUE]) : "";
-            entr[0] = text.encodeMS([entry[calendars.ID], user]);
-            if (due == today )      entr[1] = "-16744020" ;
-            else if(due == "")      entr[1] = "-13395712";
-            else if (due > today )  entr[1] = "-16777216";
-            else                    entr[1]	= "-1769402";
-            if (entry[calendars.PRIORITY] == "1") entr[2] = "-100";
-            entr[3] = entry[calendars.ATTENDEES].length;
-            entr[4] = entry[calendars.DUE];
-
-            if (pShortForm)
-            {
-                entr[5] = entry[calendars.SUMMARY];
-                entr[6] = entry[calendars.DESCRIPTION];
-            }
-            else
-            {
-                entr[5] = getCalendarStatus( entry[calendars.STATUS], pLanguage, "ToDo");
-                entr[6] = getCalendarPriority( entry[calendars.PRIORITY], pLanguage);
-                entr[7] = entry[calendars.SUMMARY];
-                entr[8] = getRealName( [ entry[calendars.ORGANIZER2] ] );
-                entr[9] = getRealName( entry[calendars.ATTENDEES] );
-                if (links == undefined) entr[10] = "";	else entr[10] = links;
-                entr[11] = entry[calendars.DESCRIPTION];
-                entr[12] = entry[calendars.CREATED];
-            }
-
-            tab.push(entr);
-            if ( pFilter.delegated == "true" )  exists.push(entry[calendars.ID]);
-        }
-    }
-
-    if (pShortForm)
-        sortArray(tab, -1, 4, 1, 5);
-    else
-        sortArray(tab, -1, 4, 1, 12 );
-
-    return tab;
-}
-
-/*
- * Fügt eine Condition hinzu
- *
- * @param {[]} pConditions req die Conditions
- * @param {Integer} pIndex req Index der Condition
- * @param {Object} pValues req
- *
- * @return {void}
- */
-function _addEntryCondition(pConditions, pIndex, pValues)
-{
-    var params = ["TYPE", "START", "END", "USER", "STATUS", "UID"];
-
-    for (var i = 0; i < params.length; i++)
-        if (pValues[params[i]] != undefined)    pConditions[params[i] + "_" + pIndex] = pValues[params[i]];
-}
-
-/*
- * Liefert Events zu bestimmten Usern/Daten in einem Array.
- *
- * @param {Object} pFilter req
- * @param {String} pLanguage opt
- * @param {bool} pShortForm opt wenn true wird nur die kurzversion geladen
- *
- * @return {[]}
- *				[0] ID
- *				[1] Vordergrundfarbe
- *				[2] Hintergrundfarbe
- *				[3] Start
- *				[4] Ende
- *				[5] Betreff
- *				[6] Inhalt
- *				[7] User
- *				[8] Anzahl Verknüpfungen
- *				[9] Klassifikation (privat/öffentlich)
- */
-function getEvents( pFilter, pLanguage, pShortForm )
-{
-    if ( pFilter == "" )  pFilter = reset_filterEvent();
-    var tab = [];
-    var conditions = [];
-    var today = getDate(vars.getString("$sys.date"));
-    var conditioncount = 0;
-    var stati = [];
-    var user = undefined;
-    if ( pFilter.tentative == "true" )    stati.push(calendars.STATUS_TENTATIVE);
-    if ( pFilter.cancelled == "true" )    stati.push(calendars.STATUS_CANCELLED);
-    if ( pFilter.confirmed == "true" )
-        stati.push(mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
-
-    if (getCalendarSystemType(calendars.VEVENT) == calendars.BACKEND_EXCHANGEWS && pFilter.free == "true")
-        stati.push(calendars.STATUS_FREE);
-
-    if ( pFilter.user != "" )	user = (pFilter.user).trim();
-
-    for ( var z = 0; z < stati.length; z++ )
-        _addEntryCondition(conditions, String(++conditioncount),
-        {
-            TYPE: calendars.VEVENT,
-            START: pFilter.datefrom,
-            END: pFilter.dateto,
-            USER: user,
-            STATUS: stati[z]
-        });
-
-    conditions["COUNT"] = String(conditioncount);
-
-    var entries = calendars.getExpandedEntries(conditions, pFilter.datefrom, pFilter.dateto);
-    for ( var i = 0;i < entries.length; i++)
-    {
-        for (var j = 0; j < entries[i].length; j++)
-        {
-            var entry = entries[i][j];
-            if( pFilter.category == "" || text.decodeMS(entry[calendars.CATEGORIES]).indexOf(pFilter.category) > -1 )
-            {
-                var entr = new Array;
-                var start = getDate(entry[calendars.DTSTART]);
-                var end = getDate(entry[calendars.DTEND]);
-
-                user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
-                if(user == null) user = entry[calendars.USER2]["cn"];
-                else user = user[tools.TITLE]
-                entr[0] = text.encodeMS([ entry[calendars.ID], user, entry[calendars.RECURRENCEID]]);
-                if (end < today ) entr[1]	="-6710887" ;
-                else if (start > today) entr[1]	= "-16777216";
-                else entr[1]	= "-16744020" ;
-                entr[2] = "-1"
-                entr[3] = entry[calendars.ATTENDEES].length;
-                entr[4] = entry[calendars.DTSTART];
-                entr[5] = entry[calendars.DTEND];
-                entr[6] = entry[calendars.SUMMARY];
-
-                if (!pShortForm)
-                {
-                    entr[7] = getRealName([entry[calendars.ORGANIZER2]]);
-                    entr[8] = getRealName(entry[calendars.ATTENDEES]);
-                    entr[9] = getCalendarStatus( entry[calendars.STATUS], pLanguage );
-                    if (entry[calendars.LINKS] == undefined) entr[10] = "";
-                    else entr[10] = entry[calendars.LINKS];
-                    entr[11] = entry[calendars.DESCRIPTION];
-                }
-                tab.push( entr );
-            }
-        }
-    }
-    sortArray(tab, -1, 4, 1, 6 );
-    return tab;
-}
-
-/*
- * Liefert den echten Namen anhand des Logins zurück
- *
- * @param {Array}[]} pUserMap req pUserMap
- *
- * @return String
- */
-function getRealName(pUserMap)
-{
-    var resultName = [];
-    var RealNames = getRealNameObject(pUserMap);
-
-    for ( var realname in RealNames )   resultName.push(RealNames[realname]);
-    return resultName.join(", \n");
-}
-
-/*
- * Liefert den echten Namen anhand des Logins zurück
- *
- * @param {Array}[]} pUserMap req pUserMap
- *
- * @return Object
- */
-function getRealNameObject(pUserMap)
-{
-    var resultObject = {};
-    var realname = "";
-
-    for ( let i = 0; i < pUserMap.length; i++ )
-    {
-        let user = tools.getUserByAttribute(tools.CALENDARID, [pUserMap[i]["paramvalue"].substr("mailto:".length)])
-        if ( user != null )
-        {
-            if(vars.exists("$global.firstLastName") && vars.get("$global.firstLastName"))
-                realname = user[tools.PARAMS][tools.LASTNAME] + " " + user[tools.PARAMS][tools.FIRSTNAME];
-            else realname = user[tools.PARAMS][tools.FIRSTNAME] + " " + user[tools.PARAMS][tools.LASTNAME];
-        }
-        else //Der User existiert nicht im System
-        {
-            realname = pUserMap[i]["cn"] + " " + pUserMap[i]["paramvalue"];
-        }
-        resultObject[pUserMap[i]["cn"]] = realname;
-    }
-    return resultObject;
-}
-
-
-/*
- * Gibt an ob der User im Calendarobject vorhanden ist
- *
- * @param {Object} pEntry req Calendarobject
- * @param {String} pUser req Title
- *
- * @return Object
- */
-function isAffectedUser( pEntry, pUser)
-{
-    var usermap = pEntry[calendars.ATTENDEES];
-
-    for ( var i = 0; i < usermap.length; i++ )
-        if( usermap[i]["cn"] == pUser )
-            return true;
-    return false;
-}
-
-/*
- * Liefert das Datum ohne Urzeit zurück
- *
- * @param {String} datetimeIn req DatumZeit
- *
- * @return {date}
- */
-function getDate( datetimeIn )
-{
-    if ( datetimeIn != "")
-        return datetime.clearTime(datetimeIn);
-    else return "";
-}
-
-/*
- * Setzt den Aufgaben-Filter
- *
- * @param {Object} pFilter req
- *
- * @return {image}
- */
-function filterToDo( pFilter )
-{
-    var error = true;
-    var von = pFilter.datefrom;
-    var bis = pFilter.dateto;
-    if ( pFilter == "" )	pFilter =  reset_filterToDo();
-    do
-    {
-        vars.set("$local.relation_id", pFilter.user);
-        vars.set("$local.edt_von", pFilter.datefrom);
-        vars.set("$local.edt_bis", pFilter.dateto);
-        vars.set("$local.category", pFilter.category);
-        vars.set("$local.delegated", pFilter.delegated);
-        vars.set("$local.needs_action", pFilter.needs_action);
-        vars.set("$local.in_process", pFilter.in_process);
-        vars.set("$local.completed", pFilter.completed);
-        vars.set("$local.cancelled", pFilter.cancelled);
-        var res = swing.askUserQuestion(translate.text("Bitte Filterbedingungen setzen"), "DLG_TASK_FILTER");
-        if( res != null )
-        {
-            pFilter.user =      res["DLG_TASK_FILTER.relation_id"];
-            pFilter.datefrom =  res["DLG_TASK_FILTER.edt_von"];
-            pFilter.dateto =    res["DLG_TASK_FILTER.edt_bis"];
-            pFilter.category =  res["DLG_TASK_FILTER.category"];
-            pFilter.delegated = res["DLG_TASK_FILTER.delegated"];
-            pFilter.needs_action = res["DLG_TASK_FILTER.needs_action"];
-            pFilter.in_process = res["DLG_TASK_FILTER.in_process"];
-            pFilter.completed = res["DLG_TASK_FILTER.completed"];
-            pFilter.cancelled = res["DLG_TASK_FILTER.cancelled"];
-            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
-            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
-        }
-        else
-        {
-            pFilter.datefrom = von;
-            pFilter.dateto = bis;
-            error = false;
-        }
-    }
-    while ( error )
-    return pFilter;
-}
-
-/*
- * Setzt den Aufgaben-Filter
- *
- * @param {Object} pFilter req
- *
- * @return {image}
- */
-function filterToDo_Neon( pFilter )
-{
-    var error = true;
-    var von = pFilter.datefrom;
-    var bis = pFilter.dateto;
-    if ( pFilter == "" )	pFilter =  reset_filterToDo();
-    do
-    {
-        var prompts = {
-            FILTER_TEXT: translate.text("Bitte Filterbedingungen setzen"),
-            RESPONSIBLE: pFilter.user,
-            DATE_FROM: pFilter.datefrom,
-            DATE_TO: pFilter.dateto,
-            CATEGORY_TODO: pFilter.category,
-            DELEGATED: pFilter.delegated,
-            NEEDS_ACTION: pFilter.needs_action,
-            IN_PROCESS: pFilter.in_process,
-            COMPLETED: pFilter.completed,
-            CANCELLED: pFilter.cancelled
-        }
-
-        var buttons = {
-            "ok" : translate.text("OK"),
-            "": translate.text("Abbrechen")
-            };
-        var defaultButton = "ok";
-
-        var res = question.openDialog("DLG_FILTER_TODO_Neon", prompts, buttons, defaultButton);
-
-        if( res.button != null )
-        {
-            pFilter.user =      res.RESPONSIBLE;
-            pFilter.datefrom =  res.DATE_FROM;
-            pFilter.dateto =    res.DATE_TO;
-            pFilter.category =  res.CATEGORY_TODO;
-            pFilter.delegated = res.DELEGATED;
-            pFilter.needs_action = res.NEEDS_ACTION;
-            pFilter.in_process = res.IN_PROCESS;
-            pFilter.completed = res.COMPLETED;
-            pFilter.cancelled = res.CANCELLED;
-            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
-            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
-        }
-        else
-        {
-            pFilter.datefrom = von;
-            pFilter.dateto = bis;
-            error = false;
-        }
-    }
-    while ( error )
-    return pFilter;
-}
-
-
-/*
- * Anzeige des Aufgaben-Filter
- *
- * @param {Object} pFilter req
- *
- * @return string Anzeige
- */
-function show_filterToDo(pFilter)
-{
-    var retstring = "";
-    var userp = tools.getUser( pFilter.user )[tools.PARAMS];
-    if (pFilter.user != "") retstring = (translate.text("Aufgaben von") + " " + userp[tools.FIRSTNAME] + " " + userp[tools.LASTNAME]);
-    if (pFilter.datefrom != "") retstring += ", " + datetime.toDate(pFilter.datefrom, translate.text("dd.MM.yyyy"));
-    if (pFilter.dateto != "") retstring += " - " + datetime.toDate(pFilter.dateto, translate.text("dd.MM.yyyy"));
-    if (pFilter.category != "") retstring += ", " + translate.text("Kategorie") + " " + pFilter.category;
-    if (pFilter.delegated == "true") retstring += ", " + translate.text("delegiert");
-    if (pFilter.needs_action == "true") retstring += ", " + translate.text("Nicht begonnen");
-    if (pFilter.in_process == "true") retstring += ", " + translate.text("In Bearbeitung");
-    if (pFilter.completed == "true") retstring += ", " + translate.text("Erledigt");
-    if (pFilter.cancelled == "true") retstring += ", " + translate.text("Zurückgestellt");
-
-    return retstring
-}
-
-/*
- * Setzt den Aufgaben-Filter zurück
- *
- * @return {filter}
- */
-function reset_filterToDo()
-{
-    var today = getDate (vars.getString("$sys.date"));
-
-    return pFilter =  {
-        user: vars.getString("$sys.user"),
-        datefrom: String(eMath.subInt(today, 720 * datetime.ONE_DAY)),
-        dateto: String(eMath.addInt(eMath.addInt(today, 3 * datetime.ONE_DAY)
-            ,datetime.ONE_DAY - datetime.ONE_MINUTE)),
-        category: "",
-        delegated: "",
-        needs_action: "true",
-        in_process: "true",
-        completed: "",
-        cancelled: ""
-    };
-}
-
-/*
- * Setzt den Event-Filter
- *
- * @param {Object} pFilter req
- *
- * @return {image}
- */
-function filterEvent( pFilter )
-{
-    var error = true;
-    var von = pFilter.datefrom;
-    var bis = pFilter.dateto;
-    if ( pFilter == "" )	pFilter =  reset_filterEvent();
-    do
-    {
-        vars.set("$local.relation_id", pFilter.user);
-        vars.set("$local.edt_von", pFilter.datefrom);
-        vars.set("$local.edt_bis", pFilter.dateto);
-        vars.set("$local.category", pFilter.category);
-        vars.set("$local.tentative", pFilter.tentative);
-        vars.set("$local.confirmed", pFilter.confirmed);
-        vars.set("$local.cancelled", pFilter.cancelled);
-        vars.set("$local.free", pFilter.free);
-        var res = swing.askUserQuestion(translate.text("Bitte Filterbedingungen setzen"), "DLG_EVENT_FILTER");
-        if( res != null )
-        {
-            pFilter.user =      res["DLG_EVENT_FILTER.relation_id"];
-            pFilter.datefrom =  res["DLG_EVENT_FILTER.edt_von"];
-            pFilter.dateto =    res["DLG_EVENT_FILTER.edt_bis"];
-            pFilter.category =  res["DLG_EVENT_FILTER.category"];
-            pFilter.tentative = res["DLG_EVENT_FILTER.tentative"];
-            pFilter.confirmed = res["DLG_EVENT_FILTER.confirmed"];
-            pFilter.cancelled = res["DLG_EVENT_FILTER.cancelled"];
-            pFilter.free      = res["DLG_EVENT_FILTER.free"];
-            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
-            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
-        }
-        else
-        {
-            pFilter.datefrom = von;
-            pFilter.dateto = bis;
-            error = false;
-        }
-    }
-    while ( error )
-    return pFilter;
-}
-
-/*
- * Setzt den Event-Filter
- *
- * @param {Object} pFilter req
- *
- * @return {image}
- */
-function filterEvent_Neon( pFilter )
-{
-    var error = true;
-    var von = pFilter.datefrom;
-    var bis = pFilter.dateto;
-    if ( pFilter == "" )	pFilter =  reset_filterEvent();
-    do
-    {
-        var buttons = {
-            "ok" : translate.text("OK"),
-            "": translate.text("Abbrechen")
-        };
-        var defaultButton = "ok";
-
-        var prompts = {
-            FILTER_TEXT: translate.text("Bitte Filterbedingungen setzen"),
-            RESPONSIBLE_APPOINTMENT: pFilter.user,
-            DATE_FROM: pFilter.datefrom,
-            DATE_TO: pFilter.dateto,
-            CATEGORY_APPOINTMENT: pFilter.category,
-            TENTATIVE: pFilter.tentative,
-            CONFIRMED: pFilter.confirmed,
-            CANCELLED: pFilter.cancelled
-        }
-        var res = question.openDialog("DLG_FILTER_APPOINTMENT_Neon", prompts, buttons, defaultButton);
-        if( res.button != null )
-        {
-            pFilter.user =      res.RESPONSIBLE_APPOINTMENT;
-            pFilter.datefrom =  res.DATE_FROM;
-            pFilter.dateto =    res.DATE_TO;
-            pFilter.category =  res.CATEGORY_APPOINTMENT;
-            pFilter.tentative = res.TENTATIVE;
-            pFilter.confirmed = res.CONFIRMED;
-            pFilter.cancelled = res.CANCELLED;
-            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
-            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
-        }
-        else
-        {
-            pFilter.datefrom = von;
-            pFilter.dateto = bis;
-            error = false;
-        }
-    }
-    while ( error )
-    return pFilter;
-}
-
-/*
- * Anzeige des Event-Filter
- *
- * @param {Object} pFilter req
- *
- * @return string Anzeige
- */
-function show_filterEvent(pFilter)
-{
-    var retstring = "";
-
-    var userp = tools.getUser( pFilter.user )[tools.PARAMS];
-    if (pFilter.user != "") retstring = translate.text("Termine von") + " " + userp[tools.FIRSTNAME] + " " + userp[tools.LASTNAME];
-    if (pFilter.datefrom != "") retstring += ", " + datetime.toDate(pFilter.datefrom, translate.text("dd.MM.yyyy"));
-    if (pFilter.dateto != "") retstring += " - " + datetime.toDate(pFilter.dateto, translate.text("dd.MM.yyyy"));
-    if (pFilter.category == "true") retstring += ", " + translate.text("Kategorie") + " " + pFilter.category;
-    if (pFilter.tentative == "true") retstring += ", " + translate.text("Vorläufig");
-    if (pFilter.confirmed == "true") retstring += ", " + translate.text("Bestätigt");
-    if (pFilter.cancelled == "true") retstring += ", " + translate.text("Abgesagt");
-
-    return retstring
-}
-
-/*
- * Setzt den Event-Filter zurück
- *
- * @return {filter}
- */
-function reset_filterEvent()
-{
-    var today = getDate (vars.getString("$sys.date"));
-
-    return pFilter =  {
-        user: vars.getString("$sys.user"),
-        datefrom: String(today), //nur die Termine ab heute anzeigen,
-        //die von vor einer Woche sind uninteressant
-        dateto: String(eMath.addInt(eMath.addInt(today, datetime.ONE_WEEK)
-            ,datetime.ONE_DAY - datetime.ONE_MINUTE)),
-        category: "",
-        tentative: "true",
-        confirmed: "true",
-        cancelled: "",
-        free: "true"
-    };
-}
-
-/*
- * Setzt den Aufgaben-Filter in Tab Aufgaben
- *
- * @return {image}
- */
-function filterLinkedToDo()
-{
-    var filtervalues = ["", "false"];
-    vars.set("$local.CalenderUser", getCalenderUser( calendars.RIGHT_READ_TASK ));
-
-    //Vorbelegen der Werte, wenn bereits gewählt wurde:
-    if(vars.exists("$image.FilterValuesT"))
-    {
-        filtervalues = vars.get("$image.FilterValuesT");
-        vars.set("$local.relation_id", filtervalues[0]);
-        vars.set("$local.done", filtervalues[1]);
-    }
-
-    var res = swing.askUserQuestion(translate.text("Bitte Filterbedingungen setzen"), "DLG_TASK_DATE_LINKED_FILTER");
-
-    if( res != null && res != undefined && res != "")
-    {
-        filtervalues[0] = res["DLG_TASK_DATE_LINKED_FILTER.relation_id"];
-        filtervalues[1] = res["DLG_TASK_DATE_LINKED_FILTER.done"]
-    }
-    vars.set("$image.FilterValuesT", filtervalues );
-
-    return(filtervalues);
-}
-
-/*
- * Setzt den Aufgabe-Filter zurück
- *
- * @return {image}
- */
-function resetfilterLinkedToDo()
-{
-    var filtervalues = ["", "false"];
-
-    vars.set("$image.FilterValuesT", filtervalues );
-
-}
-
-/*
- * setzt die Kalenderrechte
- *
- * @return {void}
- */
-function setCalendarGrant()
-{
-    calendars.resetCalendarUser();
-    var user_read_todo = [];
-    var user_write_todo = [];   // ["Admin"]
-    var user_read_event = [];
-    var user_write_event = [];
-    var tree = {};
-    var data = db.table("select THEMEID, THEME.THEME_ID, LOGIN, STATUS from THEME "
-        + " left join EMPLOYEE on EMPLOYEE.THEME_ID = THEMEID left join RELATION on RELATION_ID = RELATIONID and STATUS = 1"
-        +" where KIND = 2");
-    for ( let i = 0; i < data.length; i++)
-    {
-        if ( tree[data[i][0]] == undefined )    tree[data[i][0]] = {
-            pid: data[i][1],
-            isuser: false
-        };
-        if ( data[i][2] != "" && data[i][3] != "" )     tree[data[i][2]] = {
-            pid: data[i][0],
-            isuser: true
-        };
-    }
-
-    var user = vars.getString("$sys.user");
-    // Lese- und Schreibrechte auf Kalender aus Datentabelle holen
-    data = db.table("select HASRIGHTFOR, TODO_RIGHTS, EVENT_RIGHTS from AOSYS_CALENDAR_RIGHTS where LOGIN = '" + user + "'");
-    for ( var i = 0; i < data.length; i++ )
-        if(tree[data[i][0]] != undefined)
-            tree[data[i][0]].grants = data[i].slice(1);
-
-    for ( login in tree )
-    {
-        if( tree[login].isuser )
-        {
-            var grantstodo = __getGrants( login, 0 );
-            var grantsevent = __getGrants( login, 1 );
-            if ( grantstodo.length + grantsevent.length > 0 )
-            {
-                if ( grantstodo == "1" || grantstodo == "3")  user_read_todo.push(login);
-                if ( grantstodo == "2" || grantstodo == "3")  user_write_todo.push(login);
-                if ( grantsevent == "1" || grantsevent == "3")  user_read_event.push(login);
-                if ( grantsevent == "2" || grantsevent == "3")  user_write_event.push(login);
-            }
-        }
-    }
-    calendars.setCalendarUser(user_read_todo, calendars.RIGHT_READ_TASK, true, calendars.SORTSTRATEGY_NATURAL );
-    calendars.setCalendarUser(user_write_todo, calendars.RIGHT_WRITE_TASK, true, calendars.SORTSTRATEGY_NATURAL );
-    calendars.setCalendarUser(user_read_event, calendars.RIGHT_READ_APPOINTMENT, true, calendars.SORTSTRATEGY_NATURAL );
-    calendars.setCalendarUser(user_write_event, calendars.RIGHT_WRITE_APPOINTMENT, true, calendars.SORTSTRATEGY_NATURAL );
-
-    //********** Ressourcen in Kalender einfügen ************
-    var ressource = tools.getUsersWithRole("PROJECT_Ressource");
-    calendars.setCalendarUser(  ressource, calendars.RIGHT_READ_APPOINTMENT | calendars.RIGHT_WRITE_APPOINTMENT  );
-
-    //add all users from support-role since support-action-tasks (sp_supportAktionen) generates tasks for all support-role members
-    //and if you're a member you are allowed to edit these
-    if (tools.hasRole(user, "PROJECT_Support"))
-    {
-        var support = tools.getUsersWithRole("PROJECT_Support");
-        calendars.setCalendarUser(  support, calendars.RIGHT_WRITE_TASK | calendars.RIGHT_READ_TASK  );
-    }
-
-    function __getGrants( pKey, pIndex )
-    {
-        var grants = [];
-        if ( tree[pKey].grants != undefined && tree[pKey].grants[pIndex]) grants = tree[pKey].grants[pIndex];
-        else if ( tree[pKey].pid != "" )   grants = __getGrants( tree[pKey].pid, pIndex );
-        return grants;
-    }
-}
-
-/*
- * setzt Recht für alle Kalender
- *
- * @return {void}
- */
-function setAllCalendarGrant()
-{
-    calendars.resetCalendarUser();
-    var users = tools.getStoredUsers();
-    var calendar_user = [];
-    for ( var i = 0; i < users.length; i++ )    calendar_user.push( users[i][1] );
-    calendars.setCalendarUser(calendar_user, calendars.RIGHT_READ_TASK | calendars.RIGHT_WRITE_TASK, false, calendars.SORTSTRATEGY_NATURAL );
-}
-
-/*
- * gibt die Logins der user, die den übergebenen User als Attribute eingetragen haben, zurück
- *
- * @param {[]} pUsers req Logins
- * @param {String []} pAttrName req AttributeName für Employee
- * @param {String []} pFields opt
- *
- * @return {String []} Logins
- */
-function getUsersbyAttr( pUsers, pAttrName, pFields )
-{
-    if (typeof(pAttrName) == "string") pAttrName = [pAttrName]
-
-    if ( pFields == undefined )
-    {
-        pFields = ["LOGIN"];
-    }
-
-    var sqlstr = "select " + pFields.join(", ") + " from ATTRLINK join ATTR on ATTRLINK.ATTR_ID = ATTRID and OBJECT_ID = 12 "
-    + "and ATTRNAME in ('" + pAttrName.join("','") + "') "
-    + " join EMPLOYEE on EMPLOYEEID = ATTRLINK.ROW_ID join RELATION on RELATION_ID = RELATIONID join PERS on PERS_ID = PERSID"
-    + " where VALUE_ID in (select EMPLOYEEID from EMPLOYEE where LOGIN in ('" + pUsers.join("','") + "'))"
-    + "";
-
-    if(pFields.length == 1)
-        return db.array(db.COLUMN, sqlstr);
-    else
-        return db.table(sqlstr);
-}
-
-/*
- * Gibt die Anzahl der verknüpften Aufgaben und Termine zurück.
- *
- * @param {String} pID req
- * @param {String} pFrame req
- *
- * @return {String} text
- */
-function countLinkedTodoEvent(pID, pFrame)
-{
-    var today = getDate (vars.getString("$sys.date"));
-    var datefrom = String(today);
-    var dateto = String(eMath.addInt(today, datetime.ONE_WEEK));
-
-    var str = "select count(distinct ELEMENTUID) from ASYS_CALENDARLINK join ASYS_CALENDARBACKEND on ELEMENTUID = ASYS_CALENDARLINK.ENTRYID "
-    + " where FRAME = 'comp." + pFrame + "' and ELEMENTUID is not null and DBID = '" + pID + "'";
-    var rettask = db.cell(str + "and ENTRYTYPE = " + calendars.VTODO + " and STATUS in ('"
-        + mapCalendarStatus(calendars.STATUS_NEEDSACTION, calendars.getBackendTypeTasks() ) + "', '"
-        + mapCalendarStatus(calendars.STATUS_INPROCESS, calendars.getBackendTypeTasks() ) + "')");
-
-    var eventStatusList = [
-         mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() )
-        ,mapCalendarStatus(calendars.STATUS_TENTATIVE, calendars.getBackendType() )
-    ];
-
-    if (calendars.getBackendType() == calendars.BACKEND_EXCHANGEWS)
-        eventStatusList.push(calendars.STATUS_FREE);
-
-    var retevent = db.cell([str + " and ENTRYTYPE = " + calendars.VEVENT + " and STATUS in ('" + eventStatusList.join("', '") + "')"
-            + " and DTSTART >= ? and DTEND <= ?",
-        [ [ String(datefrom), SQLTYPES.DATE ],  [String(dateto), SQLTYPES.DATE ] ]]);
-
-    result.string(translate.withArguments("&Aufg / Term (%0/%1)", [rettask, retevent]));
-}
-
-/*
- * Gibt die Anzahl der verknüpften Aufgaben zurück.
- *
- * @param {String} pID req
- * @param {String} pFrame req
- *
- * @return {String} text
- */
-function countLinkedTodo(pID, pFrame)
-{
-    var str = "select count(distinct ELEMENTUID) "
-    + "from ASYS_CALENDARLINK "
-    + "join ASYS_CALENDARBACKEND on ELEMENTUID = ASYS_CALENDARLINK.ENTRYID "
-    + " where FRAME = 'comp." + pFrame + "' "
-    + "and ELEMENTUID is not null and DBID = '" + pID + "'";
-
-    var rettask = db.cell(str + "and ENTRYTYPE = " + calendars.VTODO
-        + " and  STATUS in ('"
-        + mapCalendarStatus(calendars.STATUS_NEEDSACTION, calendars.getBackendTypeTasks() ) + "', '"
-        + mapCalendarStatus(calendars.STATUS_INPROCESS, calendars.getBackendTypeTasks() ) + "')"
-        + "");
-
-    result.string(translate.withArguments("&Aufgaben (%0)", [rettask]));
-}
-
-/*
- * Gibt die Überschneidungen von Termine zurück.
- *
- * @param {Date} pStart req
- * @param {Date} pEnd req
- * @param {Array} pUsers req
- *
- * @return {String Array} Termine
- */
-function getOverlappingEvents(pStart, pEnd, pUsers  )
-{
-    var resultEvents = new Array();
-    var users = pUsers;
-    if (calendars.getBackendType() == calendars.BACKEND_DB && pStart != "" && pEnd != "" && users.length > 0)
-    {
-        calendars.clearCache();
-        for (var u = 0; u < users.length; u++)
-        {
-            var localuid = vars.get("$image.entry")[calendars.ID]
-            var condition = new Array();
-            condition["COUNT"] = "1";
-            condition["TYPE_1"] = calendars.VFREEBUSY;
-            condition["USER_1"] = users[u][0];
-            condition["START_1"] = pStart;
-            condition["END_1"] = pEnd;
-
-            var fbsall = calendars.getEntries(condition);
-            for (var j = 0; j < fbsall.length; j++)
-            {
-                var fbs = fbsall[j];
-                for (var i = 0; i < fbs.length; i++)
-                {
-                    var next = fbs[i];
-                    var uid = next[calendars.ID];
-                    var sum = next[calendars.SUMMARY];
-                    if (uid != localuid)
-                    {
-                        var freebusy = next[calendars.FREEBUSY];
-                        var freebusyDec = text.decodeMS(freebusy);
-                        var match = false;
-                        for (var k = 0; k < freebusyDec.length; k++)
-                        {
-                            var freebusyInstance = text.decodeMS(freebusyDec[k]);
-                            if (!freebusyInstance[0].equals("FREE"))
-                            {
-                                match = true;
-                            }
-                        }
-                        if (match)  resultEvents.push([users[u][2], sum != null && sum.length > 0 ? sum : "?", uid]);
-                    }
-                }
-            }
-        }
-    }
-    return resultEvents;
-}
-
-/*
- * Überprüft den Eintrag, wenn eine neue Aufgaben angelegt wird darauf, ob private Aufgaben für andere erstellt werden
- *
- * @param {String[]} pUser die Liste der User, denen die Aufgabe zugewiesen werden soll
- * @param {String} pClassification die Klassifizierung der Aufgabe - "PRIVATE"
- *
- * @return {Boolean} ob der Eintrag in der Konstellation möglich ist, wenn nicht wird eine Meldung ausgegeben
- */
-function checkEntry(pUser, pClassification )
-{
-    if( pClassification == "PRIVATE" &&
-        ( pUser.length > 1 || text.decodeMS(pUser[0][0])[1] != "CN:" + vars.getString("$sys.user")))
-        {
-        question.showMessage(translate.text("Eine private Aufgabe kann nicht jemand anderem zugewiesen werden."));
-        return false;
-    }
-    else
-    {
-        return true;
-    }
-}
-
-/*
- * Verschiebt ein Calendareintrag
- *
- * @param {String[]} pIDs req die zu verschiebenden Ids mit den Calenderinformationen (Multistring)
- * @param {String} pTblCompName  opt die Komponente die aktualisiert werden soll
- *
- * @return {void}
- */
-function shiftEntry(pIDs, pTblCompName)
-{
-    var datenew = swing.askUserQuestion(translate.text("Verschieben auf Datum?"), "DLG_DATE");
-    if (datenew != null )
-    {
-        var grantedUsers = calendars.getDisplayCalendarUsers(calendars.RIGHT_WRITE_TASK);
-        var usermap = {};
-        var granted = true;
-        for (let i = 0; i < grantedUsers.length; i++)
-        {
-            usermap[grantedUsers[i][1]] = true;
-        }
-
-        datenew = datetime.clearTime(datenew["DLG_DATE.Edit_date"]);
-        if (datenew <= vars.getString("$sys.today"))
-            question.showMessage(translate.text("nur Verschiebung in die Zukunft erlaubt!"));
-        else
-        {
-            for (var i = 0, j = pIDs.length; i < j; i++)
-            {
-                var id = text.decodeMS(pIDs[i]);
-                var entry = calendars.getEntry(id[0], null, id [1], calendars.VTODO);
-                var affectedUsers = entry[calendars.ATTENDEES];
-
-                granted =  hasGrantForEntryByObject(affectedUsers, usermap);
-                if(granted)
-                {
-                    //Zeitdifferenz von Aufgabenstart und -ende
-                    var dateDiff  = eMath.subInt(entry[calendars.DUE], entry[calendars.DTSTART]);
-
-                    //Startzeit der Aufgabe
-                    var startTime = eMath.subInt(entry[calendars.DTSTART]
-                        , datetime.clearTime(entry[calendars.DTSTART]));
-
-                    entry[calendars.DTSTART] = eMath.addInt(datenew, startTime);
-                    entry[calendars.DUE] = eMath.addInt(entry[calendars.DTSTART], dateDiff);
-                    calendars.update( [ entry ] );
-                }
-                else
-                    question.showMessage(translate.text("Keine Berechtigung zum Verschieben der Aufgabe"));
-            }
-        }
-    }
-}
-
-/*
- * Gibt eine Aufgabe weiter
- *
- * @param {String} pIDs die ID der Aufgabe, welche weitergegeben werden soll
- * @param {String} pTblCompName die Komponente der Aufgaben, die aktualisiert werden soll
- *
- * @return {void}
- */
-function handOverToDo(pIDs, pTblCompName)
-{
-    var calendar_user = "";
-    var users = getCalenderUser( calendars.RIGHT_WRITE_TASK );
-    var publicCount = 0;
-    var privateCount = 0;
-    var notGrantedCount = 0;
-
-    var grantedUsers = calendars.getDisplayCalendarUsers(calendars.RIGHT_WRITE_TASK);
-    var userMap = {};
-    var granted = true;
-    for (let i = 0; i < grantedUsers.length; i++)
-    {
-        userMap[grantedUsers[i][1]] = true;
-    }
-
-    if (pIDs.length == 1)  // only one todo and private
-    {
-        var id = text.decodeMS( pIDs[0] );
-        var entry = calendars.getEntry( id[0], null, id[1] );
-        if(entry[calendars.CLASSIFICATION] == calendars.CLASSIFICATION_PRIVATE)
-        {
-            question.showMessage(translate.text("Kein Weitergeben von privaten Aufgaben möglich!"));
-            return;
-        }
-    }
-
-    for ( let i = 0; i < users.length; i++)  if (pIDs.length > 0 || users[i][0] != id[1])   calendar_user += "|" + users[i][1];
-    var selection = swing.askQuestion(translate.text("Benutzer auswählen"), swing.QUESTION_COMBOBOX, calendar_user);
-    if (selection != null)
-    {
-        for ( let i = 0; i < users.length; i++)
-        {
-            if ( selection == users[i][1] )
-            {
-                selection = users[i];
-                break;
-            }
-        }
-        for( let i = 0; i < pIDs.length; i++)
-        {
-            let id = text.decodeMS( pIDs[i] );
-            let entry = calendars.getEntry( id[0], null, id[1] );
-            if(entry[calendars.CLASSIFICATION] == calendars.CLASSIFICATION_PRIVATE)  privateCount++;
-            else //Nur öffentliche Aufgabe kann weiter gegeben werden.
-            {
-                // User austauschen
-                var usermap = entry[calendars.ATTENDEES];
-                var affectedusers = [];
-
-                granted =  hasGrantForEntryByObject(usermap, userMap);
-
-                for (var ui = 0; ui < usermap.length; ui++)
-                {
-                    var login_cn = usermap[ui]["cn"];
-                    var user = tools.getUserByAttribute(tools.CALENDARID, usermap[ui]["paramvalue"].substr("mailto:".length))
-                    if (user == null)  user = login_cn;
-                    else user = user[tools.TITLE]
-
-                    if ( user == id[1] )   affectedusers.push(selection[0]);
-                    else  if ( user != selection[0] )  affectedusers.push(user);
-                }
-                if(granted)
-                {
-                    entry[calendars.AFFECTEDUSERS] = text.encodeMS(calendars.getCalendarUsers(affectedusers));
-                    calendars.update([entry]);
-                    publicCount++;
-                }
-                else notGrantedCount++
-            }
-        }
-        question.showMessage(translate.withArguments("%0 Aufgabe(n) erfolgreich weitergegeben an: %1"
-            + (privateCount == 0 ? "" : "\n%2 private Aufgabe(n) können nicht weitergegeben werden.")
-            +(notGrantedCount == 0 ? "" : "\n%3 Aufgabe(n) können aufgrund fehlender Berechtigung nicht weitergegeben werden."),
-            [publicCount, selection[1], privateCount, notGrantedCount]));
-
-    }
-}
-
-// ToDo prüfen !!
-/*
- * Verschiebt die Kalendereinträge bei Login-Änderung
- *
- * @param {String} pNewlogin req
- * @param {String} pOldlogin req
- * @param {String} pNewCalendarID req
- * @param {String} pOldCalendarID req
- *
- * @return {void}
- */
-function moveCalendarData ( pNewlogin, pOldlogin, pNewCalendarID, pOldCalendarID )
-{
-    var newcaluser = text.encodeMS(["mailto:" + pNewCalendarID, "CN:" + pNewlogin]);
-    var oldcaluser = text.encodeMS(["mailto:" + pOldCalendarID, "CN:" + pOldlogin]);
-    db.runStatement("update ASYS_CALENDARBACKEND set OWNER = '" + newcaluser + "' where OWNER = '" + oldcaluser + "'");
-    db.runStatement("update ASYS_CALENDARBACKEND set ORGANIZER = '" + newcaluser + "' where ORGANIZER = '" + oldcaluser + "'");
-
-    if(pNewCalendarID != pOldCalendarID) //Nur wenn sich die E-Mailadresse geändert hat
-    {
-        //Messenger-Historien
-        db.runStatement("update ASYS_XMPP_HISTORY set JID_FROM = '" + pNewCalendarID +"' where JID_FROM = '" + pOldCalendarID +"'", "_____SYSTEMALIAS");
-        db.runStatement("update ASYS_XMPP_HISTORY set JID_TO = '" + pNewCalendarID +"' where JID_TO = '" + pOldCalendarID +"'", "_____SYSTEMALIAS");
-    }
-}
-
-/*
- * Löst den CalenderUser in lesbarer From auf
- *
- * @param {String} pValue req
- *
- * @return {String} übersetzten Wert
- */
-function getCalUser( pValue )
-{
-    var realname = pValue;
-    var user = tools.getUser( text.decodeMS(pValue)[1].split(":")[1] );
-    if ( user != null )
-    {
-        realname = user[tools.PARAMS][tools.FIRSTNAME] + " " + user[tools.PARAMS][tools.LASTNAME];
-    }
-    return realname;
-}
-
-/*
- * Gibt den Login eines CalenderUser zurück
- *
- * @param {String} pCalendarUser req
- *
- * @return {String} Title
- */
-function getTitleCalenderUser( pCalendarUser )
-{
-    var data = text.decodeMS(pCalendarUser)
-    for ( var i = 0; i < data.length; i++ )
-    {
-        //if login changes we have to check calendarid
-        if ( data[i].substr(0, "mailto:".length).toUpperCase() == "MAILTO:" )
-        {
-            var user = tools.getUserByAttribute(tools.CALENDARID, [data[i].substr("mailto:".length)]);
-            if (user != null )
-                return user[tools.TITLE];
-        }
-
-        if ( data[i].substr(0, 3).toUpperCase() == "CN:" )
-            return data[i].substr(3);
-    }
-    return "";
-}
-
-
-/*
- * Gibt den richtigen Status zum Prüfen je nach Backend zurück
- *
- *
- * @param {String} pStatus req die konstante für den zu prüfenden status,
- *                             z.B. calendars.STATUS_INPROCESS
- *
- * @param {String} pCalendarType req die konstante für den typen des Termin- oder Aufgabenbackends,
- *                             z.B. calendars.BACKEND_DB
- *
- * @return {String} Konstanten für den Kalender (Backend-Typen), gibt es den status im backend nicht
- *                  wird null geliefert
- */
-function mapCalendarStatus(pStatus, pCalendarType)
-{
-    switch (pCalendarType)
-    {
-        //case calendars.BACKEND_EXCHANGE:
-        case calendars.BACKEND_EXCHANGEWS:
-            if (pStatus == calendars.STATUS_CONFIRMED)
-                return calendars.STATUS_BUSY;
-            else
-                return pStatus;
-        default:
-            if (pStatus == calendars.STATUS_OOF)//nur bei exchange
-                return null;
-            else
-                return pStatus;
-    }
-}
-
-/*
- * Sets the imagevariable with affectedusers
- *
- * @param {Object} pEntry req the Entry of Tasks or Appointments
- *
- * @return {void}
- *
- */
-function setAffectedUsersImage(pEntry)
-{
-    var affectedUsers = [];
-    var usermap = pEntry[calendars.ATTENDEES];
-    var realnames = getRealNameObject(usermap);
-
-    for ( var i = 0; i < usermap.length; i++ )
-    {
-        affectedUsers.push([ text.encodeMS( [usermap[i]["paramvalue"], "CN:" + usermap[i]["cn"]] ), realnames[usermap[i]["cn"]] ]);
-    }
-
-    vars.set("$image.affectedusers", affectedUsers);
-    return affectedUsers;
-}
-
-/*
- * Opens calendar links
- *
- * @param {String} pEntryID req the ID of the link
- *
- * @return {void}
- *
- */
-function openCalendarLinks(pEntryID)
-{
-    var openFramesObj = {};
-    if (typeof(pEntryID) == "object")
-        openFramesObj = pEntryID;
-    else
-    {
-        var links = db.table("SELECT FRAME, DBIDCOLUMN, DBID FROM ASYS_CALENDARLINK WHERE ENTRYID = '" + pEntryID + "'");
-        for (var i = 0; i < links.length; i++)
-        {
-            var frame = links[i][0].substr( 5 );//remove comp. so the frame can be opened with openFrame
-            if ( openFramesObj[frame] == undefined ) openFramesObj[frame] = {
-                IDField: links[i][1],
-                IDs: []
-            };
-            openFramesObj[frame].IDs.push(links[i][2]);
-        }
-    }
-
-    for ( frame in openFramesObj)
-    {
-        var condition = openFramesObj[frame].IDField + " in ('" + openFramesObj[frame].IDs.join("', '") + "')";
-        var framemode = openFramesObj[frame].IDs.length > 1 ? swing.FRAMEMODE_TABLE_SELECTION : swing.FRAMEMODE_SHOW;
-
-        if ( vars.getString("$global.upwardLink") == "link")
-        {
-            swing.openLinkedFrame(frame, condition, swing.WINDOW_CURRENT, framemode, "", null, false, {
-                autoclose: true
-            } );
-        }
-        else
-        {
-            swing.openFrame(frame, condition, swing.WINDOW_CURRENT, framemode, null, false);
-        }
-    }
-}
-
-/**
- * Returns the "real" calendar system/backend type (BackendType & SyncBackendType)
- *
- * @param {Number} pScope - The needed scope (e.g. "calendars.VEVENT", "calendars.VTODO")
- * @return {Number} - The backend type (calendars.BACKEND_*)
- */
-function getCalendarSystemType (pScope)
-{
-    // Check sync backend type
-    if (calendars.getSyncBackendType() != calendars.BACKEND_NONE && calendars.getSyncBackendType() != 3)
-    {
-        var scope = calendars.getSyncBackendTypeScope();
-        if (scope.length == 1 && scope[0] == pScope) // Scope.length = 1 -> VEVENT *OR* VTODO
-            return calendars.getSyncBackendType();
-        else if (scope.length == 2) // Scope.length = 2 -> Both
-            return calendars.getSyncBackendType();
-       // Scope.length = 0 -> Nothing selected -> Skip this block
-    }
-
-    // Fallback to backend type (event)
-    if (calendars.getBackendType() != calendars.BACKEND_NONE && pScope === calendars.VEVENT)
-        return calendars.getBackendType();
-
-    // Second fallback to backend type (todo)
-    if (calendars.getBackendTypeTasks() != calendars.BACKEND_NONE && pScope === calendars.VTODO)
-        return calendars.getBackendTypeTasks();
-
-    // Everything is none
-    return calendars.BACKEND_NONE;
-}
-
-function hasGrantForEntryByMS(pAffectedUsers, pUserMap)
-{
-    for (let i = 0; i < pAffectedUsers.length; i++)
-    {
-        var calUser = getTitleCalenderUser( pAffectedUsers[i][0]);
-        if(pUserMap[calUser] == undefined)
-        {
-            return false;
-            break;
-        }
-        else
-            return true;
-    }
-}
-
-function hasGrantForEntryByObject(pAffectedUsers, pUserMap)
-{
-    for (let i = 0; i < pAffectedUsers.length; i++)
-    {
-        calUser = tools.getUserByAttribute(tools.CALENDARID, pAffectedUsers[i]["paramvalue"].substr("mailto:".length))
-        if (calUser == null)  calUser = pAffectedUsers[i]["cn"];
-        else calUser = calUser[tools.TITLE]
-        if(pUserMap[calUser] == undefined)
-        {
-            return false;
-            break;
-        }
-        else
-            return true;
-    }
-}
+import("system.neon");
+import("system.vars");
+import("system.db");
+import("system.translate");
+import("system.datetime");
+import("system.swing");
+import("system.eMath");
+import("system.calendars");
+import("system.logging");
+import("system.tools");
+import("system.text");
+import("system.question");
+import("system.SQLTYPES");
+import("system.result");
+import("Util_lib");
+import("system.util")
+
+
+/**
+ *  @class
+ **/
+function CalendarUtil(){}
+
+
+/*
+ * Erzeugt und öffnet ein neues Aufgabenobjekt (mit einem Link).
+ *
+ * @param {String} pSummary opt die Zusammenfassung
+ * @param {String} pDescription opt die Beschreibung
+ * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
+ * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
+ *                                   pWithLink[1]: ID des angezeigten Datensatzes
+ *                                   pWithLink[2]: Verknüpfungstitel
+ * @param {String} pUser opt der Benutzer ( Login )
+ * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
+ * @param {date} pStart opt Beginn der Aufgabe
+ * @param {date} pDuration opt Dauer
+ * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
+ * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
+ * @param {Array{[]} pComps4Refresh opt die zu aktualisierenden Komponenten
+ *
+ * @return {void}
+ */
+CalendarUtil.newTodo = function(pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh)
+{
+    var todo = createEntry( calendars.VTODO, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus );
+    var prompts = [];
+    prompts["comp4refresh"] = [];
+
+    if (pComps4Refresh == undefined)
+        pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Aufgabe"];
+
+    for (var i = 0; i < pComps4Refresh.length; i++)
+    {
+        if ( vars.exists(pComps4Refresh[i]))    prompts["comp4refresh"].push(pComps4Refresh[i]);
+    }
+    if(vars.getString("$sys.scope") == "vaadin")
+        neon.openCalendarEntry([todo], null, neon.OPERATINGSTATE_NEW, null)
+    else
+    {
+        if (vars.exists("$sys.currentwindow"))
+            prompts["window"] = vars.getString("$sys.currentwindow");
+        if (vars.exists("$sys.currentimage"))
+            prompts["image"] = vars.getString("$sys.currentimage");
+
+        swing.openCalendarEntry([todo], null, false, prompts);
+    }
+}
+
+/*
+ * Erzeugt eine neue Aufgabe (mit einem Link).
+ *
+ * @param {String} pSummary opt die Zusammenfassung
+ * @param {String} pDescription opt die Beschreibung
+ * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
+ * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
+ *                		     pWithLink[1]: ID des angezeigten Datensatzes
+ *               		     pWithLink[2]: Verknüpfungstitel
+ * @param {String} pUser opt der Benutzer ( Login )
+ * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
+ * @param {date} pStart opt Beginn der Aufagebe
+ * @param {integer} pGroupType opt ( calendars.GROUP_SINGLE , calendars.GROUP_MULTI )
+ * @param {date} pDuration opt Dauer
+ * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
+ * @param {String} pStatus opt Status der Aufgabe ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
+ * @param {String} pPriority opt Priorität der Aufgabe
+ * @param {String} pReminder opt Erinnerung der Aufgabe
+ *
+ * @return {void}
+ */
+
+CalendarUtil.newSilentTodo = function(pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pGroupType, pCategory, pStatus, pPriority, pReminder)
+{
+    if ( pGroupType == undefined ) pGroupType = calendars.GROUP_SINGLE;
+    var todo = createEntry( calendars.VTODO, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pPriority, pReminder );
+    
+    return calendars.insert([todo],calendars.GROUP_SINGLE);
+}
+
+/*
+ * Erzeugt und öffnet ein neues Terminnobjekt mit einem Link.
+ *
+ * @param {String} pSummary opt die Zusammenfassung
+ * @param {String} pDescription opt die Beschreibung
+ * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
+ * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
+ *                		     pWithLink[1]: ID des angezeigten Datensatzes
+ *               		     pWithLink[2]: Verknüpfungstitel
+ * @param {String} pUser opt der Benutzer ( Login )
+ * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
+ * @param {date} pStart opt Beginn der Aufagebe
+ * @param {date} pDuration opt Dauer
+ * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
+ * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
+ * @param {Array{[]} pComps4Refresh opt die zu aktualisierenden Komponenten
+ * 
+ * @return {void}
+ */
+CalendarUtil.newEvent = function( pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh, pWorklistId)
+{
+    var event = createEntry( calendars.VEVENT, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus );
+
+    var prompts = [];
+    prompts["comp4refresh"] = [];
+    if (pComps4Refresh == undefined)
+        pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Termine"];
+    for (i = 0; i < pComps4Refresh.length; i++)
+    {
+        if ( vars.exists(pComps4Refresh[i]))    prompts["comp4refresh"].push(pComps4Refresh[i]);
+    }
+
+    if(vars.getString("$sys.scope") == "vaadin")
+        neon.openCalendarEntry([event],"", neon.OPERATINGSTATE_NEW, null)
+    else
+    {
+        prompts["window"] = vars.getString("$sys.currentwindow");
+        prompts["image"] = vars.getString("$sys.currentimage");
+        if (pWorklistId != undefined)
+            prompts["worklistId"]   = pWorklistId;
+        swing.openCalendarEntry([event], null, false, prompts);
+    }
+}
+
+
+/*
+ * Erzeugt einen neuen Termineintrag (mit einem Link).
+ *
+ * @param {String} pSummary opt die Zusammenfassung
+ * @param {String} pDescription opt die Beschreibung
+ * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
+ * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
+ *                		     pWithLink[1]: ID des angezeigten Datensatzes
+ *                		     pWithLink[2]: Verknüpfungstitel
+ * @param {String} pUser opt der Benutzer ( Login )
+ * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( Login )
+ * @param {date} pStart opt Beginn des Termins
+ * @param {date} pDuration opt Dauer
+ * @param {integer} pGroupType opt ( calendars.GROUP_SINGLE , calendars.GROUP_MULTI )
+ * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
+ * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
+ * @param {String} pReminder opt Erinnerung des Termins
+ *
+ * @return {void}
+ */
+CalendarUtil.newSilentEvent = function( pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pGroupType, pCategory, pStatus, pReminder)
+{
+    if ( pGroupType == undefined ) pGroupType = calendars.GROUP_SINGLE;
+    var event = createEntry( calendars.VEVENT, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, undefined, pReminder );
+    return calendars.insert( [event] , pGroupType );
+}
+
+/*
+ * Erzeugt ein neues Aufgaben- / Termin-Objekt (mit einem Link).
+ *
+ * @param {date} pType req  Augabe oder Termin ( calendars.VTODO, calendars.VEVENT )
+ * @param {String} pSummary opt die Zusammenfassung
+ * @param {String} pDescription opt die Beschreibung
+ * @param {Boolean} pWithLink opt TRUE legt eine Verknüpfung zu $image.frametable
+ * @param {String[][]} pWithLink opt pWithLink[0]: Name des Frames
+ *                		     pWithLink[1]: ID des angezeigten Datensatzes
+ *                		     pWithLink[2]: Verknüpfungstitel
+ * @param {String} pUser opt der Benutzer ( Login )
+ * @param {[]} pAffectedUsers opt die betroffenen Benutzer ( [ Login ] )
+ * @param {date} pStart opt Beginn
+ * @param {date} pDuration opt Dauer
+ * @param {integer} pCategory opt ( calendars.CATEGORIES , encoded(String) z.B.: text.encodeMS(["Service"]) )
+ * @param {String} pStatus opt Status des Termins ( calendars.STATUS_TENTATIVE, calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED )
+ * @param {String} pPriority opt Priorität
+ * @param {String} pReminder opt Erinnerung
+ *
+@return {Object} das EntryObjekt
+ */
+CalendarUtil.createEntry = function( pType, pSummary, pDescription, pWithLink, pAppLinkContext, pAppLinkId, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pPriority, pReminder )
+{
+    var Entry = {};
+    var framename;
+    var framdata;
+    var dbid;
+    var linktitle;
+    if ( pSummary == undefined || pSummary == null  ) pSummary = "";
+    if ( pDescription == undefined || pDescription == null )
+    {
+        if(vars.getString("$sys.scope") == "vaadin")
+            pDescription = neon.getImageContent(vars.getString("$sys.currententityname"));
+        else
+            pDescription = swing.getImageContent();
+    }
+    if ( pUser == undefined || pUser == null ) pUser = vars.getString("$sys.user");
+    //kein translate.key hier, weil es sich um einen rein technischen Wert handelt:
+    if ( pStart == undefined ) pStart = datetime.toLong(datetime.toDate(parseInt(vars.getString("$sys.date")) + datetime.ONE_HOUR, "dd.MM.yyyy HH:00"), "dd.MM.yyyy HH:mm");
+    if ( pCategory == undefined || pCategory == null  ) pCategory = "";
+
+    if (pAffectedUsers == null || pAffectedUsers == undefined )
+    {
+        Entry[calendars.AFFECTEDUSERS] = "";
+    }
+    else
+    {
+        Entry[calendars.AFFECTEDUSERS] = text.encodeMS(calendars.getCalendarUsers(pAffectedUsers));
+    }
+    Entry[calendars.TYPE] = pType;
+    Entry[calendars.DTSTART] = pStart;
+    if ( pType == calendars.VEVENT )
+    {
+        if ( pDuration == undefined )
+            pDuration = datetime.ONE_HOUR;
+
+        Entry[calendars.DTEND] = String ( eMath.addInt( pStart, pDuration) );
+
+        if ( pStatus == undefined )
+            pStatus = calendars.STATUS_CONFIRMED;
+
+        pStatus = mapCalendarStatus(pStatus, calendars.getBackendType() );
+    }
+    else if ( pType == calendars.VTODO )
+    {
+        //kein translate.key hier, weil es sich um einen rein technischen Wert handelt:
+        if ( pDuration != undefined )
+            Entry[calendars.DUE] = String ( eMath.addInt( pStart, pDuration) );
+        else
+            Entry[calendars.DUE] = datetime.toLong(datetime.toDate(pStart, "dd.MM.yyyy 23:59")
+                ,"dd.MM.yyyy HH:mm");
+
+        if ( pStatus == undefined )
+            pStatus = calendars.STATUS_NEEDSACTION;
+
+        pStatus = mapCalendarStatus(pStatus, calendars.getBackendTypeTasks() );
+        
+    }
+
+    Entry[calendars.USER] = calendars.getCalendarUser(pUser);
+    Entry[calendars.DESCRIPTION] = pDescription;
+    Entry[calendars.SUMMARY] = pSummary;
+    Entry[calendars.STATUS] = pStatus;
+    Entry[calendars.CLASSIFICATION] = calendars.CLASSIFICATION_PUBLIC;
+    Entry[calendars.CATEGORIES] = pCategory;
+   
+
+    if( pPriority != undefined )
+    {
+        Entry[calendars.PRIORITY] = pPriority;
+    }
+
+    if( pReminder != undefined)
+    {
+        Entry[calendars.HASREMINDER] = "true";
+        Entry[calendars.REMINDER_DURATION] = pReminder;
+    }
+    else
+        Entry[calendars.HASREMINDER] = "false";
+   
+
+    if (pWithLink == false)
+    {
+        Entry[calendars.LINKS] = "0";
+    }
+    else
+    {
+        var fd = new FrameData();
+        if ( typeof(pWithLink) == "object" )
+        {
+            for ( var li = 0; li < pWithLink.length; li++ )
+            {
+                framename = pWithLink[li][0];
+                framdata = fd.getData("name", framename, ["table","idcolumn","title"])[0];
+                dbid = pWithLink[li][1];
+                linktitle = framdata[2] + " - " + pWithLink[li][2];
+
+                Entry["LINK_ALIAS_" + ( li + 1 )] = vars.getString("$sys.dbalias");
+                Entry["LINK_TABLE_" + ( li + 1 )] = framdata[0];
+                Entry["LINK_IDCOLUMN_" + ( li + 1 )] = framdata[1];
+                Entry["LINK_DBID_" + ( li + 1 )] = dbid;
+                Entry["LINK_FRAME_" + ( li + 1 )] = "comp." + framename;
+                Entry["LINK_TITLE_" + ( li + 1 )] = linktitle;
+            }
+            Entry[calendars.LINKS] = pWithLink.length.toString();
+        }
+        else
+        {
+            if ( pWithLink == true || pWithLink == undefined )
+            {
+                framename = vars.getString("$sys.currentimagename");
+                framdata = fd.getData("name", framename, ["table","idcolumn","title"])[0];
+                dbid = vars.getString("$comp.idcolumn");
+                linktitle = framdata[2] + " - " + swing.getImageContent();
+            }
+            Entry[calendars.LINKS] = "1";
+            Entry["LINK_ALIAS_1"] = vars.getString("$sys.dbalias");
+            Entry["LINK_TABLE_1"] = framdata[0];
+            Entry["LINK_IDCOLUMN_1"] = framdata[1];
+            Entry["LINK_DBID_1"] = dbid;
+            Entry["LINK_FRAME_1"] = "comp." + framename;
+            Entry["LINK_TITLE_1"] = linktitle;
+        }
+    }
+    
+
+if(pAppLinkContext && pAppLinkId)
+{
+    Entry["AppLinkContext"] = pAppLinkContext;
+    Entry["AppLinkId"] = pAppLinkId;
+}
+    return Entry;
+}
+
+/*
+ * Liefert den CalendarStatus übersetzt zurück.
+ * @param {String} pStatus req Status
+ * @param {String} pLanguage opt Sprache
+ * @param {String} pKind opt ToDo oder Event
+ *
+ * @return {String} übersetzte Status
+ */
+function getCalendarStatus( pStatus, pLanguage, pKind)
+{
+    //kein mappen des Status, da wirklich verschiedene Dinge angezeigt werden sollen
+    switch ( pStatus )
+    {
+        case calendars.STATUS_BUSY: 
+            return translate.text("Gebucht", pLanguage)
+        case calendars.STATUS_CANCELLED:
+            if(pKind == "ToDo" && pKind != undefined) return translate.text("Zurückgestellt", pLanguage)
+            return translate.text("Abgesagt", pLanguage)
+        case calendars.STATUS_COMPLETED:
+            return translate.text("Erledigt", pLanguage)
+        case calendars.STATUS_CONFIRMED:
+            return translate.text("Bestätigt", pLanguage)
+        case calendars.STATUS_FREE:
+            return translate.text("frei", pLanguage)
+        case calendars.STATUS_INPROCESS:
+            return translate.text("In Bearbeitung", pLanguage)
+        case calendars.STATUS_NEEDSACTION:
+            return translate.text("Nicht begonnen", pLanguage)
+        case calendars.STATUS_OOF:
+            return translate.text("Außer Haus", pLanguage)
+        case calendars.STATUS_TENTATIVE:
+            return translate.text("Vorläufig", pLanguage)
+        default:
+            return "";
+    }
+}
+
+/*
+ * Zu einer übergebenen Priorität wird ihre Bedeutung übersetzt und zurückgegeben.
+ *
+ * @param {String} pPriority req Priorität
+ * @param {String} pLanguage opt Sprache
+ *
+ * @return (String) übersetzte Bedeutung einer Priorität
+ */
+function getCalendarPriority(pPriority, pLanguage)
+{
+    switch(pPriority)
+    {
+        case "9":
+            return translate.text("niedrig", pLanguage);
+            break;
+        case "5":
+            return translate.text("normal", pLanguage);
+            break;
+        case "1":
+            return translate.text("hoch", pLanguage);
+            break;
+        default:
+            return translate.text("keine", pLanguage);
+            break;
+    }
+}
+
+/*
+ * Liefert zum Objekt verknüpfte Aufgaben aus dem Kalender.
+ *
+ * @param {String} pFrame req Name des Frames
+ * @param {String} pDBID req ID des verknüpften Datensatzes
+ * @param {String} pAlias opt
+ * @param {String} pLanguage opt Sprache
+ *
+ * @return {[]} mit Aufgaben aus Kalender
+ */
+function getLinkedToDos (pFrame, pDBID, pAlias, pLanguage )
+{
+    if (pAlias == undefined ) pAlias = vars.getString("$sys.dbalias");
+    var tab = [];
+    var status = " and STATUS in ('NEEDS-ACTION', 'IN-PROCESS')";
+    var exists = [];
+    var zustaendig = "";
+    var today = getDate(vars.getString("$sys.date"));
+    var filtervalues = ["", "false"];
+    if ( vars.exists("$image.FilterValuesT") )
+    {
+        filtervalues = vars.get("$image.FilterValuesT");
+        zustaendig = filtervalues[0]
+        if (filtervalues[1] == "true") status = " and STATUS in ('COMPLETED', 'CANCELLED')";
+    }
+
+    var entryids = db.table("select ENTRYID, OWNER from ASYS_CALENDARLINK "
+        + "join ASYS_CALENDARBACKEND on ELEMENTUID = ENTRYID where FRAME = 'comp." + pFrame + "' "
+        + "and ENTRYID is not null "
+        + "and ENTRYTYPE = " + calendars.VTODO + " "
+        + "and DBID = '" + pDBID + "' "
+        + status, pAlias);
+
+    for (var i = 0; i < entryids.length; i++)
+    {
+        if ( exists.indexOf(entryids[i][0]) == -1)
+        {
+            try
+                {
+                    var entry = calendars.getEntry(entryids[i][0], null, getTitleCalenderUser( entryids[i][1] ), calendars.VTODO);
+                    var entr = new Array;
+                    status = "";
+                    var user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
+                    if(user == null) user = entry[calendars.USER2]["cn"];
+                     else user = user[tools.TITLE]
+                    if ((user == zustaendig || zustaendig == ""))
+                    {
+                        entr[0] = text.encodeMS([entry[calendars.ID], user]);
+                        var due = getDate(entry[calendars.DUE]);
+                        if (due < today ) entr[1]	= "-1769402";
+                        else  if (due > today) entr[1]	= "-16777216"; else entr[1]	= "-16744020";
+                        entr[2] = "-1";  // Hintergrundfarbe
+                        entr[3] = text.decodeMS(entry[calendars.AFFECTEDUSERS]).length;
+                        entr[4] = entry[calendars.DUE]
+                        entr[5] = getCalendarStatus( entry[calendars.STATUS], pLanguage, "ToDo");
+                        entr[6] = entry[calendars.SUMMARY]
+                        entr[7] = getRealName([entry[calendars.ORGANIZER2]]);
+                        entr[8] = getRealName(entry[calendars.ATTENDEES]);
+                        entr[9] = entry[calendars.DESCRIPTION];
+                        entr[10] = entry[calendars.PRIORITY];
+                        tab.push(entr);
+                        exists.push(entryids[i][0]);
+                    }
+            }
+            catch (ex)
+            {
+                logging.log(ex);
+            }
+        }
+    }
+    array_mDimSort(tab, 4, false); //Sortierung nach Fälligkeitsdatum
+    return tab;
+}
+
+/*
+ * Anzeige des Aufgaben-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return string Anzeige
+ */
+function show_filterLinkedToDos(pFilter)
+{
+    var retstring = "";
+    if (pFilter[0] != "")
+    {
+        var userp = tools.getUser( pFilter[0] )[tools.PARAMS];
+        retstring = translate.text("Aufgaben von") + " " + userp[tools.FIRSTNAME] + " " + userp[tools.LASTNAME];
+    }
+    if (pFilter[1] == "true") retstring += ", " + translate.text("erledigt / zurückgestellt");
+
+    return retstring
+}
+
+/*
+ * Liefert zum Objekt verknüpfte Events aus dem Kalender.
+ *
+ * @param {String} pFrame req Name des Frames
+ * @param {String} pDBID req ID des verknüpften Datensatzes
+ * @param {Object} pFilter opt
+ * @param {String} pAlias opt
+ * @param {String} pUser opt Benutzer
+ *
+ * @return {[]} mit Events aus Kalender
+ */
+function getLinkedEvents (pFrame, pDBID, pFilter, pAlias, pUser )
+{
+    if ( pFilter == "" || pFilter == undefined)
+        pFilter = reset_filterEvent();
+
+    var tab = [];
+    var exists = [];
+    var conditions = [];
+    var today = getDate(vars.getString("$sys.date"));
+    var conditioncount = 0;
+    var stati = [];
+
+    if ( pFilter.tentative == "true" )
+        stati.push(mapCalendarStatus(calendars.STATUS_TENTATIVE, calendars.getBackendType() ));
+
+    if ( pFilter.cancelled == "true" )
+        stati.push(mapCalendarStatus(calendars.STATUS_CANCELLED, calendars.getBackendType() ));
+
+    if ( pFilter.confirmed == "true" )
+        stati.push(mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
+
+    if (calendars.getBackendType() == calendars.BACKEND_EXCHANGEWS)
+        stati.push(calendars.STATUS_FREE);
+
+    if (pAlias == undefined ) pAlias = vars.getString("$sys.dbalias");
+
+    var entryids = db.table(["select ENTRYID, OWNER "
+        + "from ASYS_CALENDARLINK "
+        + "join ASYS_CALENDARBACKEND on ELEMENTUID = ENTRYID where FRAME = 'comp."
+        + pFrame + "' and ENTRYID is not null and ENTRYTYPE = " + calendars.VEVENT
+        + " and DBID = '" + pDBID + "' and DTSTART >= ?",
+        [ [ String(pFilter.datefrom - datetime.ONE_WEEK), SQLTYPES.DATE ]]], pAlias );
+
+    /*
+     * Check for rights before constructing condition otherwise you'll get an error by opening linked Data
+     */
+    var userToRead = []
+    if(pUser != undefined)
+    {
+        userToRead = getCalendarUsers( calendars.RIGHT_READ_APPOINTMENT, pUser );
+    }
+    else
+    {
+        userToRead = calendars.getDisplayCalendarUsers(calendars.RIGHT_READ_APPOINTMENT);
+    }
+    var userMap = {};
+    for (let i = 0; i < userToRead.length; i++)
+    {
+        userMap[userToRead[i][1]] = true;
+    }
+
+    for ( var i = 0;i < entryids.length; i++)
+    {
+        var user = getTitleCalenderUser(entryids[i][1]);
+        if(userMap[user])
+        {
+            for ( var z = 0; z < stati.length; z++ )
+                _addEntryCondition(conditions, String(++conditioncount),
+                {
+                    TYPE: calendars.VEVENT,
+                    START: pFilter.datefrom,
+                    END: pFilter.dateto,
+                    USER: user,
+                    STATUS: stati[z],
+                    UID: entryids[i][0]
+                });
+        } else continue
+    }
+    conditions["COUNT"] = String(conditioncount);
+
+    var entries = calendars.getExpandedEntries(conditions, pFilter.datefrom, pFilter.dateto);
+    for ( let i = 0; i < entries.length; i++)
+    {
+        for (var j = 0; j < entries[i].length; j++)
+        {
+            var entry = entries[i][j];
+            if( exists.indexOf(entry[calendars.ID]) == -1 && ( pFilter.category == "" || text.decodeMS(entry[calendars.CATEGORIES]).indexOf(pFilter.category) > 0))
+            {
+                var entr = new Array;
+                var start = getDate(entry[calendars.DTSTART]);
+                var end = getDate(entry[calendars.DTEND]);
+                user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
+                if(user == null) user = entry[calendars.USER2]["cn"];
+                 else user = user[tools.TITLE]
+                entr[0] = text.encodeMS([entry[calendars.ID], user , entry[calendars.RECURRENCEID]]);
+                if (end < today) entr[1]	= "-6710887" ;
+                else if (start <= today && end >= today )   entr[1] = "-16744020" ;
+                else entr[1] = "-16777216";
+                entr[2] = "-1"
+                entr[3] = text.decodeMS(entry[calendars.AFFECTEDUSERS]).length;
+                entr[4] = entry[calendars.DTSTART]
+                entr[5] = entry[calendars.DTEND]
+                entr[6] = entry[calendars.SUMMARY]
+                entr[7] = getRealName([entry[calendars.ORGANIZER2]]);
+                entr[8] = getRealName(entry[calendars.ATTENDEES]);
+                entr[9] = entry[calendars.DESCRIPTION]
+                tab.push(entr);
+                exists.push(entry[calendars.ID]);
+            }
+        }
+    }
+    array_mDimSort(tab, 4, false);
+    return tab;
+}
+
+/*
+ * Liefert Aufgaben aus dem Kalender.
+ *
+ * @param {Object} pFilter req
+ * @param {String} pLanguage opt
+ * @param {bool} pShortForm opt wenn true wird nur die kurzversion geladen
+ *
+ * @return {[]} mit allen aufgaben aus dem Kalender
+ */
+function getTodos( pFilter, pLanguage, pShortForm )
+{
+    if ( pFilter == "" )    pFilter =  reset_filterToDo();
+    var tab = [];
+    var today = getDate (vars.getString("$sys.date"));
+    var conditions = [];
+    var conditioncount = 0;
+    var user = pFilter.user;
+    var stati = [];
+    var status = [];
+    var exists = [];
+    var entries = [];
+
+    if ( pFilter.needs_action == "true" )
+    {
+        stati.push(mapCalendarStatus(calendars.STATUS_NEEDSACTION, calendars.getBackendTypeTasks() ));
+        status.push("NEEDS-ACTION");
+    }
+    if ( pFilter.in_process == "true" )
+    {
+        stati.push(mapCalendarStatus(calendars.STATUS_INPROCESS, calendars.getBackendTypeTasks() ));
+        status.push("IN-PROCESS");
+    }
+    if ( pFilter.completed == "true" )
+    {
+        stati.push(mapCalendarStatus(calendars.STATUS_COMPLETED, calendars.getBackendTypeTasks() ));
+        status.push("COMPLETED");
+    }
+    if ( pFilter.cancelled == "true" )
+    {
+        stati.push(mapCalendarStatus(calendars.STATUS_CANCELLED, calendars.getBackendTypeTasks() ));
+        status.push("CANCELLED");
+    }
+    if (pFilter.delegated == "true" )
+    {
+        var from = [pFilter.datefrom, SQLTYPES.TIMESTAMP];
+        var to = [pFilter.dateto, SQLTYPES.TIMESTAMP];
+        setAllCalendarGrant();
+        user = calendars.getCalendarUser(user);
+        user = db.table(["select ELEMENTUID, OWNER from ASYS_CALENDARBACKEND where ENTRYTYPE = 2 and OWNER != '" + user + "' and ORGANIZER = '"
+            + user + "' and STATUS in ('" + status.join("', '") + "') and (( STARTTIME >= ? and STARTTIME <= ?) or "
+            + "( ENDTIME >= ? and ENDTIME <= ? ) or ( STARTTIME >= ? and ENDTIME <= ? ))", [from, to, from, to, from, to]] );
+
+        for (let i = 0; i < user.length; i++ )
+        {
+            try
+            {
+                entries.push([calendars.getEntry(user[i][0], null, getTitleCalenderUser(user[i][1]), calendars.VTODO)]);
+            }
+            catch(err){
+                logging.log(err);
+            }
+        }
+        setCalendarGrant();
+    }
+    else
+    {
+        if ( typeof( pFilter.user ) != "object" )  user = [user.trim()];
+        for (let i = 0; i < user.length; i++ )
+        for ( var z = 0; z < stati.length; z++ )
+            _addEntryCondition(conditions, ++conditioncount,
+            {
+                TYPE: calendars.VTODO,
+                START: pFilter.datefrom,
+                END: pFilter.dateto,
+                USER: user[i],
+                STATUS: stati[z]
+            });
+
+        conditions["COUNT"] = String(conditioncount);
+        entries = calendars.getEntries(conditions);
+    }
+
+    for (i = 0; i < entries.length; i++)
+    {
+        var entry = entries[i][0];
+        user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
+        if (user == null)  user = entry[calendars.USER2]["cn"];
+         else user = user[tools.TITLE]
+        if ( !(user != vars.getString("$sys.user") && entry[calendars.CLASSIFICATION] == calendars.CLASSIFICATION_PRIVATE) // no privat
+            && !( pFilter.delegated == "true" && ( isAffectedUser( entry, pFilter.user) || exists.indexOf(entry[calendars.ID]) > -1  ) ) // no duplicate
+            && ( pFilter.category == "" || text.decodeMS(entry[calendars.CATEGORIES]).indexOf( pFilter.category ) > -1 ) ) // Filter category
+            {
+            var entr = [];
+            var links =  entry[calendars.LINKS];
+            var due = entry[calendars.DUE] != "" ? getDate(entry[calendars.DUE]) : "";
+            entr[0] = text.encodeMS([entry[calendars.ID], user]);
+            if (due == today )      entr[1] = "-16744020" ;
+            else if(due == "")      entr[1] = "-13395712";
+            else if (due > today )  entr[1] = "-16777216";
+            else                    entr[1]	= "-1769402";
+            if (entry[calendars.PRIORITY] == "1") entr[2] = "-100";
+            entr[3] = entry[calendars.ATTENDEES].length;
+            entr[4] = entry[calendars.DUE];
+
+            if (pShortForm)
+            {
+                entr[5] = entry[calendars.SUMMARY];
+                entr[6] = entry[calendars.DESCRIPTION];
+            }
+            else
+            {
+                entr[5] = getCalendarStatus( entry[calendars.STATUS], pLanguage, "ToDo");
+                entr[6] = getCalendarPriority( entry[calendars.PRIORITY], pLanguage);
+                entr[7] = entry[calendars.SUMMARY];
+                entr[8] = getRealName( [ entry[calendars.ORGANIZER2] ] );
+                entr[9] = getRealName( entry[calendars.ATTENDEES] );
+                if (links == undefined) entr[10] = "";	else entr[10] = links;
+                entr[11] = entry[calendars.DESCRIPTION];
+                entr[12] = entry[calendars.CREATED];
+            }
+
+            tab.push(entr);
+            if ( pFilter.delegated == "true" )  exists.push(entry[calendars.ID]);
+        }
+    }
+
+    if (pShortForm)
+        sortArray(tab, -1, 4, 1, 5);
+    else
+        sortArray(tab, -1, 4, 1, 12 );
+
+    return tab;
+}
+
+/*
+ * Fügt eine Condition hinzu
+ *
+ * @param {[]} pConditions req die Conditions
+ * @param {Integer} pIndex req Index der Condition
+ * @param {Object} pValues req
+ *
+ * @return {void}
+ */
+function _addEntryCondition(pConditions, pIndex, pValues)
+{
+    var params = ["TYPE", "START", "END", "USER", "STATUS", "UID"];
+
+    for (var i = 0; i < params.length; i++)
+        if (pValues[params[i]] != undefined)    pConditions[params[i] + "_" + pIndex] = pValues[params[i]];
+}
+
+CalendarUtil.addEntryCondition = function(pConditions, pIndex, pValues)
+{
+    _addEntryCondition(pConditions, pIndex, pValues);
+}
+/*
+ * Liefert Events zu bestimmten Usern/Daten in einem Array.
+ *
+ * @param {Object} pFilter req
+ * @param {String} pLanguage opt
+ * @param {bool} pShortForm opt wenn true wird nur die kurzversion geladen
+ *
+ * @return {[]}
+ *				[0] ID
+ *				[1] Vordergrundfarbe
+ *				[2] Hintergrundfarbe
+ *				[3] Start
+ *				[4] Ende
+ *				[5] Betreff
+ *				[6] Inhalt
+ *				[7] User
+ *				[8] Anzahl Verknüpfungen
+ *				[9] Klassifikation (privat/öffentlich)
+ */
+function getEvents( pFilter, pLanguage, pShortForm )
+{
+    if ( pFilter == "" )  pFilter = reset_filterEvent();
+    var tab = [];
+    var conditions = [];
+    var today = getDate(vars.getString("$sys.date"));
+    var conditioncount = 0;
+    var stati = [];
+    var user = undefined;
+    if ( pFilter.tentative == "true" )    stati.push(calendars.STATUS_TENTATIVE);
+    if ( pFilter.cancelled == "true" )    stati.push(calendars.STATUS_CANCELLED);
+    if ( pFilter.confirmed == "true" )
+        stati.push(mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
+
+    if (getCalendarSystemType(calendars.VEVENT) == calendars.BACKEND_EXCHANGEWS && pFilter.free == "true")
+        stati.push(calendars.STATUS_FREE);
+
+    if ( pFilter.user != "" )	user = (pFilter.user).trim();
+
+    for ( var z = 0; z < stati.length; z++ )
+        _addEntryCondition(conditions, String(++conditioncount),
+        {
+            TYPE: calendars.VEVENT,
+            START: pFilter.datefrom,
+            END: pFilter.dateto,
+            USER: user,
+            STATUS: stati[z]
+        });
+
+    conditions["COUNT"] = String(conditioncount);
+
+    var entries = calendars.getExpandedEntries(conditions, pFilter.datefrom, pFilter.dateto);
+    for ( var i = 0;i < entries.length; i++)
+    {
+        for (var j = 0; j < entries[i].length; j++)
+        {
+            var entry = entries[i][j];
+            if( pFilter.category == "" || text.decodeMS(entry[calendars.CATEGORIES]).indexOf(pFilter.category) > -1 )
+            {
+                var entr = new Array;
+                var start = getDate(entry[calendars.DTSTART]);
+                var end = getDate(entry[calendars.DTEND]);
+
+                user = tools.getUserByAttribute(tools.CALENDARID, entry[calendars.USER2]["paramvalue"].substr("mailto:".length))
+                if(user == null) user = entry[calendars.USER2]["cn"];
+                else user = user[tools.TITLE]
+                entr[0] = text.encodeMS([ entry[calendars.ID], user, entry[calendars.RECURRENCEID]]);
+                if (end < today ) entr[1]	="-6710887" ;
+                else if (start > today) entr[1]	= "-16777216";
+                else entr[1]	= "-16744020" ;
+                entr[2] = "-1"
+                entr[3] = entry[calendars.ATTENDEES].length;
+                entr[4] = entry[calendars.DTSTART];
+                entr[5] = entry[calendars.DTEND];
+                entr[6] = entry[calendars.SUMMARY];
+
+                if (!pShortForm)
+                {
+                    entr[7] = getRealName([entry[calendars.ORGANIZER2]]);
+                    entr[8] = getRealName(entry[calendars.ATTENDEES]);
+                    entr[9] = getCalendarStatus( entry[calendars.STATUS], pLanguage );
+                    if (entry[calendars.LINKS] == undefined) entr[10] = "";
+                    else entr[10] = entry[calendars.LINKS];
+                    entr[11] = entry[calendars.DESCRIPTION];
+                }
+                tab.push( entr );
+            }
+        }
+    }
+    sortArray(tab, -1, 4, 1, 6 );
+    return tab;
+}
+
+/*
+ * Liefert den echten Namen anhand des Logins zurück
+ *
+ * @param {Array}[]} pUserMap req pUserMap
+ *
+ * @return String
+ */
+function getRealName(pUserMap)
+{
+    var resultName = [];
+    var RealNames = getRealNameObject(pUserMap);
+
+    for ( var realname in RealNames )   resultName.push(RealNames[realname]);
+    return resultName.join(", \n");
+}
+
+/*
+ * Liefert den echten Namen anhand des Logins zurück
+ *
+ * @param {Array}[]} pUserMap req pUserMap
+ *
+ * @return Object
+ */
+function getRealNameObject(pUserMap)
+{
+    var resultObject = {};
+    var realname = "";
+
+    for ( let i = 0; i < pUserMap.length; i++ )
+    {
+        let user = tools.getUserByAttribute(tools.CALENDARID, [pUserMap[i]["paramvalue"].substr("mailto:".length)])
+        if ( user != null )
+        {
+            if(vars.exists("$global.firstLastName") && vars.get("$global.firstLastName"))
+                realname = user[tools.PARAMS][tools.LASTNAME] + " " + user[tools.PARAMS][tools.FIRSTNAME];
+            else realname = user[tools.PARAMS][tools.FIRSTNAME] + " " + user[tools.PARAMS][tools.LASTNAME];
+        }
+        else //Der User existiert nicht im System
+        {
+            realname = pUserMap[i]["cn"] + " " + pUserMap[i]["paramvalue"];
+        }
+        resultObject[pUserMap[i]["cn"]] = realname;
+    }
+    return resultObject;
+}
+
+
+/*
+ * Gibt an ob der User im Calendarobject vorhanden ist
+ *
+ * @param {Object} pEntry req Calendarobject
+ * @param {String} pUser req Title
+ *
+ * @return Object
+ */
+function isAffectedUser( pEntry, pUser)
+{
+    var usermap = pEntry[calendars.ATTENDEES];
+
+    for ( var i = 0; i < usermap.length; i++ )
+        if( usermap[i]["cn"] == pUser )
+            return true;
+    return false;
+}
+
+/*
+ * Liefert das Datum ohne Urzeit zurück
+ *
+ * @param {String} datetimeIn req DatumZeit
+ *
+ * @return {date}
+ */
+function getDate( datetimeIn )
+{
+    if ( datetimeIn != "")
+        return datetime.clearTime(datetimeIn);
+    else return "";
+}
+
+/*
+ * Setzt den Aufgaben-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return {image}
+ */
+function filterToDo( pFilter )
+{
+    var error = true;
+    var von = pFilter.datefrom;
+    var bis = pFilter.dateto;
+    if ( pFilter == "" )	pFilter =  reset_filterToDo();
+    do
+    {
+        vars.set("$local.relation_id", pFilter.user);
+        vars.set("$local.edt_von", pFilter.datefrom);
+        vars.set("$local.edt_bis", pFilter.dateto);
+        vars.set("$local.category", pFilter.category);
+        vars.set("$local.delegated", pFilter.delegated);
+        vars.set("$local.needs_action", pFilter.needs_action);
+        vars.set("$local.in_process", pFilter.in_process);
+        vars.set("$local.completed", pFilter.completed);
+        vars.set("$local.cancelled", pFilter.cancelled);
+        var res = swing.askUserQuestion(translate.text("Bitte Filterbedingungen setzen"), "DLG_TASK_FILTER");
+        if( res != null )
+        {
+            pFilter.user =      res["DLG_TASK_FILTER.relation_id"];
+            pFilter.datefrom =  res["DLG_TASK_FILTER.edt_von"];
+            pFilter.dateto =    res["DLG_TASK_FILTER.edt_bis"];
+            pFilter.category =  res["DLG_TASK_FILTER.category"];
+            pFilter.delegated = res["DLG_TASK_FILTER.delegated"];
+            pFilter.needs_action = res["DLG_TASK_FILTER.needs_action"];
+            pFilter.in_process = res["DLG_TASK_FILTER.in_process"];
+            pFilter.completed = res["DLG_TASK_FILTER.completed"];
+            pFilter.cancelled = res["DLG_TASK_FILTER.cancelled"];
+            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
+            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
+        }
+        else
+        {
+            pFilter.datefrom = von;
+            pFilter.dateto = bis;
+            error = false;
+        }
+    }
+    while ( error )
+    return pFilter;
+}
+
+/*
+ * Setzt den Aufgaben-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return {image}
+ */
+function filterToDo_Neon( pFilter )
+{
+    var error = true;
+    var von = pFilter.datefrom;
+    var bis = pFilter.dateto;
+    if ( pFilter == "" )	pFilter =  reset_filterToDo();
+    do
+    {
+        var prompts = {
+            FILTER_TEXT: translate.text("Bitte Filterbedingungen setzen"),
+            RESPONSIBLE: pFilter.user,
+            DATE_FROM: pFilter.datefrom,
+            DATE_TO: pFilter.dateto,
+            CATEGORY_TODO: pFilter.category,
+            DELEGATED: pFilter.delegated,
+            NEEDS_ACTION: pFilter.needs_action,
+            IN_PROCESS: pFilter.in_process,
+            COMPLETED: pFilter.completed,
+            CANCELLED: pFilter.cancelled
+        }
+
+        var buttons = {
+            "ok" : translate.text("OK"),
+            "": translate.text("Abbrechen")
+            };
+        var defaultButton = "ok";
+
+        var res = question.openDialog("DLG_FILTER_TODO_Neon", prompts, buttons, defaultButton);
+
+        if( res.button != null )
+        {
+            pFilter.user =      res.RESPONSIBLE;
+            pFilter.datefrom =  res.DATE_FROM;
+            pFilter.dateto =    res.DATE_TO;
+            pFilter.category =  res.CATEGORY_TODO;
+            pFilter.delegated = res.DELEGATED;
+            pFilter.needs_action = res.NEEDS_ACTION;
+            pFilter.in_process = res.IN_PROCESS;
+            pFilter.completed = res.COMPLETED;
+            pFilter.cancelled = res.CANCELLED;
+            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
+            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
+        }
+        else
+        {
+            pFilter.datefrom = von;
+            pFilter.dateto = bis;
+            error = false;
+        }
+    }
+    while ( error )
+    return pFilter;
+}
+
+
+/*
+ * Anzeige des Aufgaben-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return string Anzeige
+ */
+function show_filterToDo(pFilter)
+{
+    var retstring = "";
+    var userp = tools.getUser( pFilter.user )[tools.PARAMS];
+    if (pFilter.user != "") retstring = (translate.text("Aufgaben von") + " " + userp[tools.FIRSTNAME] + " " + userp[tools.LASTNAME]);
+    if (pFilter.datefrom != "") retstring += ", " + datetime.toDate(pFilter.datefrom, translate.text("dd.MM.yyyy"));
+    if (pFilter.dateto != "") retstring += " - " + datetime.toDate(pFilter.dateto, translate.text("dd.MM.yyyy"));
+    if (pFilter.category != "") retstring += ", " + translate.text("Kategorie") + " " + pFilter.category;
+    if (pFilter.delegated == "true") retstring += ", " + translate.text("delegiert");
+    if (pFilter.needs_action == "true") retstring += ", " + translate.text("Nicht begonnen");
+    if (pFilter.in_process == "true") retstring += ", " + translate.text("In Bearbeitung");
+    if (pFilter.completed == "true") retstring += ", " + translate.text("Erledigt");
+    if (pFilter.cancelled == "true") retstring += ", " + translate.text("Zurückgestellt");
+
+    return retstring
+}
+
+/*
+ * Setzt den Aufgaben-Filter zurück
+ *
+ * @return {filter}
+ */
+function reset_filterToDo()
+{
+    var today = getDate (vars.getString("$sys.date"));
+
+    return pFilter =  {
+        user: vars.getString("$sys.user"),
+        datefrom: String(eMath.subInt(today, 720 * datetime.ONE_DAY)),
+        dateto: String(eMath.addInt(eMath.addInt(today, 3 * datetime.ONE_DAY)
+            ,datetime.ONE_DAY - datetime.ONE_MINUTE)),
+        category: "",
+        delegated: "",
+        needs_action: "true",
+        in_process: "true",
+        completed: "",
+        cancelled: ""
+    };
+}
+
+/*
+ * Setzt den Event-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return {image}
+ */
+function filterEvent( pFilter )
+{
+    var error = true;
+    var von = pFilter.datefrom;
+    var bis = pFilter.dateto;
+    if ( pFilter == "" )	pFilter =  reset_filterEvent();
+    do
+    {
+        vars.set("$local.relation_id", pFilter.user);
+        vars.set("$local.edt_von", pFilter.datefrom);
+        vars.set("$local.edt_bis", pFilter.dateto);
+        vars.set("$local.category", pFilter.category);
+        vars.set("$local.tentative", pFilter.tentative);
+        vars.set("$local.confirmed", pFilter.confirmed);
+        vars.set("$local.cancelled", pFilter.cancelled);
+        vars.set("$local.free", pFilter.free);
+        var res = swing.askUserQuestion(translate.text("Bitte Filterbedingungen setzen"), "DLG_EVENT_FILTER");
+        if( res != null )
+        {
+            pFilter.user =      res["DLG_EVENT_FILTER.relation_id"];
+            pFilter.datefrom =  res["DLG_EVENT_FILTER.edt_von"];
+            pFilter.dateto =    res["DLG_EVENT_FILTER.edt_bis"];
+            pFilter.category =  res["DLG_EVENT_FILTER.category"];
+            pFilter.tentative = res["DLG_EVENT_FILTER.tentative"];
+            pFilter.confirmed = res["DLG_EVENT_FILTER.confirmed"];
+            pFilter.cancelled = res["DLG_EVENT_FILTER.cancelled"];
+            pFilter.free      = res["DLG_EVENT_FILTER.free"];
+            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
+            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
+        }
+        else
+        {
+            pFilter.datefrom = von;
+            pFilter.dateto = bis;
+            error = false;
+        }
+    }
+    while ( error )
+    return pFilter;
+}
+
+/*
+ * Setzt den Event-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return {image}
+ */
+function filterEvent_Neon( pFilter )
+{
+    var error = true;
+    var von = pFilter.datefrom;
+    var bis = pFilter.dateto;
+    if ( pFilter == "" )	pFilter =  reset_filterEvent();
+    do
+    {
+        var buttons = {
+            "ok" : translate.text("OK"),
+            "": translate.text("Abbrechen")
+        };
+        var defaultButton = "ok";
+
+        var prompts = {
+            FILTER_TEXT: translate.text("Bitte Filterbedingungen setzen"),
+            RESPONSIBLE_APPOINTMENT: pFilter.user,
+            DATE_FROM: pFilter.datefrom,
+            DATE_TO: pFilter.dateto,
+            CATEGORY_APPOINTMENT: pFilter.category,
+            TENTATIVE: pFilter.tentative,
+            CONFIRMED: pFilter.confirmed,
+            CANCELLED: pFilter.cancelled
+        }
+        var res = question.openDialog("DLG_FILTER_APPOINTMENT_Neon", prompts, buttons, defaultButton);
+        if( res.button != null )
+        {
+            pFilter.user =      res.RESPONSIBLE_APPOINTMENT;
+            pFilter.datefrom =  res.DATE_FROM;
+            pFilter.dateto =    res.DATE_TO;
+            pFilter.category =  res.CATEGORY_APPOINTMENT;
+            pFilter.tentative = res.TENTATIVE;
+            pFilter.confirmed = res.CONFIRMED;
+            pFilter.cancelled = res.CANCELLED;
+            if (pFilter.datefrom != "" && pFilter.dateto != "" && pFilter.dateto >= pFilter.datefrom ) error = false;
+            else question.showMessage(translate.text("Bitte Datumseingabe prüfen!"))
+        }
+        else
+        {
+            pFilter.datefrom = von;
+            pFilter.dateto = bis;
+            error = false;
+        }
+    }
+    while ( error )
+    return pFilter;
+}
+
+/*
+ * Anzeige des Event-Filter
+ *
+ * @param {Object} pFilter req
+ *
+ * @return string Anzeige
+ */
+function show_filterEvent(pFilter)
+{
+    var retstring = "";
+
+    var userp = tools.getUser( pFilter.user )[tools.PARAMS];
+    if (pFilter.user != "") retstring = translate.text("Termine von") + " " + userp[tools.FIRSTNAME] + " " + userp[tools.LASTNAME];
+    if (pFilter.datefrom != "") retstring += ", " + datetime.toDate(pFilter.datefrom, translate.text("dd.MM.yyyy"));
+    if (pFilter.dateto != "") retstring += " - " + datetime.toDate(pFilter.dateto, translate.text("dd.MM.yyyy"));
+    if (pFilter.category == "true") retstring += ", " + translate.text("Kategorie") + " " + pFilter.category;
+    if (pFilter.tentative == "true") retstring += ", " + translate.text("Vorläufig");
+    if (pFilter.confirmed == "true") retstring += ", " + translate.text("Bestätigt");
+    if (pFilter.cancelled == "true") retstring += ", " + translate.text("Abgesagt");
+
+    return retstring
+}
+
+/*
+ * Setzt den Event-Filter zurück
+ *
+ * @return {filter}
+ */
+function reset_filterEvent()
+{
+    var today = getDate (vars.getString("$sys.date"));
+
+    return pFilter =  {
+        user: vars.getString("$sys.user"),
+        datefrom: String(today), //nur die Termine ab heute anzeigen,
+        //die von vor einer Woche sind uninteressant
+        dateto: String(eMath.addInt(eMath.addInt(today, datetime.ONE_WEEK)
+            ,datetime.ONE_DAY - datetime.ONE_MINUTE)),
+        category: "",
+        tentative: "true",
+        confirmed: "true",
+        cancelled: "",
+        free: "true"
+    };
+}
+
+/*
+ * Setzt den Aufgaben-Filter in Tab Aufgaben
+ *
+ * @return {image}
+ */
+function filterLinkedToDo()
+{
+    var filtervalues = ["", "false"];
+    vars.set("$local.CalenderUser", getCalenderUser( calendars.RIGHT_READ_TASK ));
+
+    //Vorbelegen der Werte, wenn bereits gewählt wurde:
+    if(vars.exists("$image.FilterValuesT"))
+    {
+        filtervalues = vars.get("$image.FilterValuesT");
+        vars.set("$local.relation_id", filtervalues[0]);
+        vars.set("$local.done", filtervalues[1]);
+    }
+
+    var res = swing.askUserQuestion(translate.text("Bitte Filterbedingungen setzen"), "DLG_TASK_DATE_LINKED_FILTER");
+
+    if( res != null && res != undefined && res != "")
+    {
+        filtervalues[0] = res["DLG_TASK_DATE_LINKED_FILTER.relation_id"];
+        filtervalues[1] = res["DLG_TASK_DATE_LINKED_FILTER.done"]
+    }
+    vars.set("$image.FilterValuesT", filtervalues );
+
+    return(filtervalues);
+}
+
+/*
+ * Setzt den Aufgabe-Filter zurück
+ *
+ * @return {image}
+ */
+function resetfilterLinkedToDo()
+{
+    var filtervalues = ["", "false"];
+
+    vars.set("$image.FilterValuesT", filtervalues );
+
+}
+
+/*
+ * setzt die Kalenderrechte
+ *
+ * @return {void}
+ */
+function setCalendarGrant()
+{
+    calendars.resetCalendarUser();
+    var user_read_todo = [];
+    var user_write_todo = [];   // ["Admin"]
+    var user_read_event = [];
+    var user_write_event = [];
+    var tree = {};
+    var data = db.table("select THEMEID, THEME.THEME_ID, LOGIN, STATUS from THEME "
+        + " left join EMPLOYEE on EMPLOYEE.THEME_ID = THEMEID left join RELATION on RELATION_ID = RELATIONID and STATUS = 1"
+        +" where KIND = 2");
+    for ( let i = 0; i < data.length; i++)
+    {
+        if ( tree[data[i][0]] == undefined )    tree[data[i][0]] = {
+            pid: data[i][1],
+            isuser: false
+        };
+        if ( data[i][2] != "" && data[i][3] != "" )     tree[data[i][2]] = {
+            pid: data[i][0],
+            isuser: true
+        };
+    }
+
+    var user = vars.getString("$sys.user");
+    // Lese- und Schreibrechte auf Kalender aus Datentabelle holen
+    data = db.table("select HASRIGHTFOR, TODO_RIGHTS, EVENT_RIGHTS from AOSYS_CALENDAR_RIGHTS where LOGIN = '" + user + "'");
+    for ( var i = 0; i < data.length; i++ )
+        if(tree[data[i][0]] != undefined)
+            tree[data[i][0]].grants = data[i].slice(1);
+
+    for ( login in tree )
+    {
+        if( tree[login].isuser )
+        {
+            var grantstodo = __getGrants( login, 0 );
+            var grantsevent = __getGrants( login, 1 );
+            if ( grantstodo.length + grantsevent.length > 0 )
+            {
+                if ( grantstodo == "1" || grantstodo == "3")  user_read_todo.push(login);
+                if ( grantstodo == "2" || grantstodo == "3")  user_write_todo.push(login);
+                if ( grantsevent == "1" || grantsevent == "3")  user_read_event.push(login);
+                if ( grantsevent == "2" || grantsevent == "3")  user_write_event.push(login);
+            }
+        }
+    }
+    calendars.setCalendarUser(user_read_todo, calendars.RIGHT_READ_TASK, true, calendars.SORTSTRATEGY_NATURAL );
+    calendars.setCalendarUser(user_write_todo, calendars.RIGHT_WRITE_TASK, true, calendars.SORTSTRATEGY_NATURAL );
+    calendars.setCalendarUser(user_read_event, calendars.RIGHT_READ_APPOINTMENT, true, calendars.SORTSTRATEGY_NATURAL );
+    calendars.setCalendarUser(user_write_event, calendars.RIGHT_WRITE_APPOINTMENT, true, calendars.SORTSTRATEGY_NATURAL );
+
+    //********** Ressourcen in Kalender einfügen ************
+    var ressource = tools.getUsersWithRole("PROJECT_Ressource");
+    calendars.setCalendarUser(  ressource, calendars.RIGHT_READ_APPOINTMENT | calendars.RIGHT_WRITE_APPOINTMENT  );
+
+    //add all users from support-role since support-action-tasks (sp_supportAktionen) generates tasks for all support-role members
+    //and if you're a member you are allowed to edit these
+    if (tools.hasRole(user, "PROJECT_Support"))
+    {
+        var support = tools.getUsersWithRole("PROJECT_Support");
+        calendars.setCalendarUser(  support, calendars.RIGHT_WRITE_TASK | calendars.RIGHT_READ_TASK  );
+    }
+
+    function __getGrants( pKey, pIndex )
+    {
+        var grants = [];
+        if ( tree[pKey].grants != undefined && tree[pKey].grants[pIndex]) grants = tree[pKey].grants[pIndex];
+        else if ( tree[pKey].pid != "" )   grants = __getGrants( tree[pKey].pid, pIndex );
+        return grants;
+    }
+}
+
+/*
+ * setzt Recht für alle Kalender
+ *
+ * @return {void}
+ */
+function setAllCalendarGrant()
+{
+    calendars.resetCalendarUser();
+    var users = tools.getStoredUsers();
+    var calendar_user = [];
+    for ( var i = 0; i < users.length; i++ )    calendar_user.push( users[i][1] );
+    calendars.setCalendarUser(calendar_user, calendars.RIGHT_READ_TASK | calendars.RIGHT_WRITE_TASK, false, calendars.SORTSTRATEGY_NATURAL );
+}
+
+/*
+ * gibt die Logins der user, die den übergebenen User als Attribute eingetragen haben, zurück
+ *
+ * @param {[]} pUsers req Logins
+ * @param {String []} pAttrName req AttributeName für Employee
+ * @param {String []} pFields opt
+ *
+ * @return {String []} Logins
+ */
+function getUsersbyAttr( pUsers, pAttrName, pFields )
+{
+    if (typeof(pAttrName) == "string") pAttrName = [pAttrName]
+
+    if ( pFields == undefined )
+    {
+        pFields = ["LOGIN"];
+    }
+
+    var sqlstr = "select " + pFields.join(", ") + " from ATTRLINK join ATTR on ATTRLINK.ATTR_ID = ATTRID and OBJECT_ID = 12 "
+    + "and ATTRNAME in ('" + pAttrName.join("','") + "') "
+    + " join EMPLOYEE on EMPLOYEEID = ATTRLINK.ROW_ID join RELATION on RELATION_ID = RELATIONID join PERS on PERS_ID = PERSID"
+    + " where VALUE_ID in (select EMPLOYEEID from EMPLOYEE where LOGIN in ('" + pUsers.join("','") + "'))"
+    + "";
+
+    if(pFields.length == 1)
+        return db.array(db.COLUMN, sqlstr);
+    else
+        return db.table(sqlstr);
+}
+
+/*
+ * Gibt die Anzahl der verknüpften Aufgaben und Termine zurück.
+ *
+ * @param {String} pID req
+ * @param {String} pFrame req
+ *
+ * @return {String} text
+ */
+function countLinkedTodoEvent(pID, pFrame)
+{
+    var today = getDate (vars.getString("$sys.date"));
+    var datefrom = String(today);
+    var dateto = String(eMath.addInt(today, datetime.ONE_WEEK));
+
+    var str = "select count(distinct ELEMENTUID) from ASYS_CALENDARLINK join ASYS_CALENDARBACKEND on ELEMENTUID = ASYS_CALENDARLINK.ENTRYID "
+    + " where FRAME = 'comp." + pFrame + "' and ELEMENTUID is not null and DBID = '" + pID + "'";
+    var rettask = db.cell(str + "and ENTRYTYPE = " + calendars.VTODO + " and STATUS in ('"
+        + mapCalendarStatus(calendars.STATUS_NEEDSACTION, calendars.getBackendTypeTasks() ) + "', '"
+        + mapCalendarStatus(calendars.STATUS_INPROCESS, calendars.getBackendTypeTasks() ) + "')");
+
+    var eventStatusList = [
+         mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() )
+        ,mapCalendarStatus(calendars.STATUS_TENTATIVE, calendars.getBackendType() )
+    ];
+
+    if (calendars.getBackendType() == calendars.BACKEND_EXCHANGEWS)
+        eventStatusList.push(calendars.STATUS_FREE);
+
+    var retevent = db.cell([str + " and ENTRYTYPE = " + calendars.VEVENT + " and STATUS in ('" + eventStatusList.join("', '") + "')"
+            + " and DTSTART >= ? and DTEND <= ?",
+        [ [ String(datefrom), SQLTYPES.DATE ],  [String(dateto), SQLTYPES.DATE ] ]]);
+
+    result.string(translate.withArguments("&Aufg / Term (%0/%1)", [rettask, retevent]));
+}
+
+/*
+ * Gibt die Anzahl der verknüpften Aufgaben zurück.
+ *
+ * @param {String} pID req
+ * @param {String} pFrame req
+ *
+ * @return {String} text
+ */
+function countLinkedTodo(pID, pFrame)
+{
+    var str = "select count(distinct ELEMENTUID) "
+    + "from ASYS_CALENDARLINK "
+    + "join ASYS_CALENDARBACKEND on ELEMENTUID = ASYS_CALENDARLINK.ENTRYID "
+    + " where FRAME = 'comp." + pFrame + "' "
+    + "and ELEMENTUID is not null and DBID = '" + pID + "'";
+
+    var rettask = db.cell(str + "and ENTRYTYPE = " + calendars.VTODO
+        + " and  STATUS in ('"
+        + mapCalendarStatus(calendars.STATUS_NEEDSACTION, calendars.getBackendTypeTasks() ) + "', '"
+        + mapCalendarStatus(calendars.STATUS_INPROCESS, calendars.getBackendTypeTasks() ) + "')"
+        + "");
+
+    result.string(translate.withArguments("&Aufgaben (%0)", [rettask]));
+}
+
+/*
+ * Gibt die Überschneidungen von Termine zurück.
+ *
+ * @param {Date} pStart req
+ * @param {Date} pEnd req
+ * @param {Array} pUsers req
+ *
+ * @return {String Array} Termine
+ */
+function getOverlappingEvents(pStart, pEnd, pUsers  )
+{
+    var resultEvents = new Array();
+    var users = pUsers;
+    if (calendars.getBackendType() == calendars.BACKEND_DB && pStart != "" && pEnd != "" && users.length > 0)
+    {
+        calendars.clearCache();
+        for (var u = 0; u < users.length; u++)
+        {
+            var localuid = vars.get("$image.entry")[calendars.ID]
+            var condition = new Array();
+            condition["COUNT"] = "1";
+            condition["TYPE_1"] = calendars.VFREEBUSY;
+            condition["USER_1"] = users[u][0];
+            condition["START_1"] = pStart;
+            condition["END_1"] = pEnd;
+
+            var fbsall = calendars.getEntries(condition);
+            for (var j = 0; j < fbsall.length; j++)
+            {
+                var fbs = fbsall[j];
+                for (var i = 0; i < fbs.length; i++)
+                {
+                    var next = fbs[i];
+                    var uid = next[calendars.ID];
+                    var sum = next[calendars.SUMMARY];
+                    if (uid != localuid)
+                    {
+                        var freebusy = next[calendars.FREEBUSY];
+                        var freebusyDec = text.decodeMS(freebusy);
+                        var match = false;
+                        for (var k = 0; k < freebusyDec.length; k++)
+                        {
+                            var freebusyInstance = text.decodeMS(freebusyDec[k]);
+                            if (!freebusyInstance[0].equals("FREE"))
+                            {
+                                match = true;
+                            }
+                        }
+                        if (match)  resultEvents.push([users[u][2], sum != null && sum.length > 0 ? sum : "?", uid]);
+                    }
+                }
+            }
+        }
+    }
+    return resultEvents;
+}
+
+/*
+ * Überprüft den Eintrag, wenn eine neue Aufgaben angelegt wird darauf, ob private Aufgaben für andere erstellt werden
+ *
+ * @param {String[]} pUser die Liste der User, denen die Aufgabe zugewiesen werden soll
+ * @param {String} pClassification die Klassifizierung der Aufgabe - "PRIVATE"
+ *
+ * @return {Boolean} ob der Eintrag in der Konstellation möglich ist, wenn nicht wird eine Meldung ausgegeben
+ */
+function checkEntry(pUser, pClassification )
+{
+    if( pClassification == "PRIVATE" &&
+        ( pUser.length > 1 || text.decodeMS(pUser[0][0])[1] != "CN:" + vars.getString("$sys.user")))
+        {
+        question.showMessage(translate.text("Eine private Aufgabe kann nicht jemand anderem zugewiesen werden."));
+        return false;
+    }
+    else
+    {
+        return true;
+    }
+}
+
+/*
+ * Verschiebt ein Calendareintrag
+ *
+ * @param {String[]} pIDs req die zu verschiebenden Ids mit den Calenderinformationen (Multistring)
+ * @param {String} pTblCompName  opt die Komponente die aktualisiert werden soll
+ *
+ * @return {void}
+ */
+function shiftEntry(pIDs, pTblCompName)
+{
+    var datenew = swing.askUserQuestion(translate.text("Verschieben auf Datum?"), "DLG_DATE");
+    if (datenew != null )
+    {
+        var grantedUsers = calendars.getDisplayCalendarUsers(calendars.RIGHT_WRITE_TASK);
+        var usermap = {};
+        var granted = true;
+        for (let i = 0; i < grantedUsers.length; i++)
+        {
+            usermap[grantedUsers[i][1]] = true;
+        }
+
+        datenew = datetime.clearTime(datenew["DLG_DATE.Edit_date"]);
+        if (datenew <= vars.getString("$sys.today"))
+            question.showMessage(translate.text("nur Verschiebung in die Zukunft erlaubt!"));
+        else
+        {
+            for (var i = 0, j = pIDs.length; i < j; i++)
+            {
+                var id = text.decodeMS(pIDs[i]);
+                var entry = calendars.getEntry(id[0], null, id [1], calendars.VTODO);
+                var affectedUsers = entry[calendars.ATTENDEES];
+
+                granted =  hasGrantForEntryByObject(affectedUsers, usermap);
+                if(granted)
+                {
+                    //Zeitdifferenz von Aufgabenstart und -ende
+                    var dateDiff  = eMath.subInt(entry[calendars.DUE], entry[calendars.DTSTART]);
+
+                    //Startzeit der Aufgabe
+                    var startTime = eMath.subInt(entry[calendars.DTSTART]
+                        , datetime.clearTime(entry[calendars.DTSTART]));
+
+                    entry[calendars.DTSTART] = eMath.addInt(datenew, startTime);
+                    entry[calendars.DUE] = eMath.addInt(entry[calendars.DTSTART], dateDiff);
+                    calendars.update( [ entry ] );
+                }
+                else
+                    question.showMessage(translate.text("Keine Berechtigung zum Verschieben der Aufgabe"));
+            }
+        }
+    }
+}
+
+/*
+ * Gibt eine Aufgabe weiter
+ *
+ * @param {String} pIDs die ID der Aufgabe, welche weitergegeben werden soll
+ * @param {String} pTblCompName die Komponente der Aufgaben, die aktualisiert werden soll
+ *
+ * @return {void}
+ */
+function handOverToDo(pIDs, pTblCompName)
+{
+    var calendar_user = "";
+    var users = getCalenderUser( calendars.RIGHT_WRITE_TASK );
+    var publicCount = 0;
+    var privateCount = 0;
+    var notGrantedCount = 0;
+
+    var grantedUsers = calendars.getDisplayCalendarUsers(calendars.RIGHT_WRITE_TASK);
+    var userMap = {};
+    var granted = true;
+    for (let i = 0; i < grantedUsers.length; i++)
+    {
+        userMap[grantedUsers[i][1]] = true;
+    }
+
+    if (pIDs.length == 1)  // only one todo and private
+    {
+        var id = text.decodeMS( pIDs[0] );
+        var entry = calendars.getEntry( id[0], null, id[1] );
+        if(entry[calendars.CLASSIFICATION] == calendars.CLASSIFICATION_PRIVATE)
+        {
+            question.showMessage(translate.text("Kein Weitergeben von privaten Aufgaben möglich!"));
+            return;
+        }
+    }
+
+    for ( let i = 0; i < users.length; i++)  if (pIDs.length > 0 || users[i][0] != id[1])   calendar_user += "|" + users[i][1];
+    var selection = swing.askQuestion(translate.text("Benutzer auswählen"), swing.QUESTION_COMBOBOX, calendar_user);
+    if (selection != null)
+    {
+        for ( let i = 0; i < users.length; i++)
+        {
+            if ( selection == users[i][1] )
+            {
+                selection = users[i];
+                break;
+            }
+        }
+        for( let i = 0; i < pIDs.length; i++)
+        {
+            let id = text.decodeMS( pIDs[i] );
+            let entry = calendars.getEntry( id[0], null, id[1] );
+            if(entry[calendars.CLASSIFICATION] == calendars.CLASSIFICATION_PRIVATE)  privateCount++;
+            else //Nur öffentliche Aufgabe kann weiter gegeben werden.
+            {
+                // User austauschen
+                var usermap = entry[calendars.ATTENDEES];
+                var affectedusers = [];
+
+                granted =  hasGrantForEntryByObject(usermap, userMap);
+
+                for (var ui = 0; ui < usermap.length; ui++)
+                {
+                    var login_cn = usermap[ui]["cn"];
+                    var user = tools.getUserByAttribute(tools.CALENDARID, usermap[ui]["paramvalue"].substr("mailto:".length))
+                    if (user == null)  user = login_cn;
+                    else user = user[tools.TITLE]
+
+                    if ( user == id[1] )   affectedusers.push(selection[0]);
+                    else  if ( user != selection[0] )  affectedusers.push(user);
+                }
+                if(granted)
+                {
+                    entry[calendars.AFFECTEDUSERS] = text.encodeMS(calendars.getCalendarUsers(affectedusers));
+                    calendars.update([entry]);
+                    publicCount++;
+                }
+                else notGrantedCount++
+            }
+        }
+        question.showMessage(translate.withArguments("%0 Aufgabe(n) erfolgreich weitergegeben an: %1"
+            + (privateCount == 0 ? "" : "\n%2 private Aufgabe(n) können nicht weitergegeben werden.")
+            +(notGrantedCount == 0 ? "" : "\n%3 Aufgabe(n) können aufgrund fehlender Berechtigung nicht weitergegeben werden."),
+            [publicCount, selection[1], privateCount, notGrantedCount]));
+
+    }
+}
+
+// ToDo prüfen !!
+/*
+ * Verschiebt die Kalendereinträge bei Login-Änderung
+ *
+ * @param {String} pNewlogin req
+ * @param {String} pOldlogin req
+ * @param {String} pNewCalendarID req
+ * @param {String} pOldCalendarID req
+ *
+ * @return {void}
+ */
+function moveCalendarData ( pNewlogin, pOldlogin, pNewCalendarID, pOldCalendarID )
+{
+    var newcaluser = text.encodeMS(["mailto:" + pNewCalendarID, "CN:" + pNewlogin]);
+    var oldcaluser = text.encodeMS(["mailto:" + pOldCalendarID, "CN:" + pOldlogin]);
+    db.runStatement("update ASYS_CALENDARBACKEND set OWNER = '" + newcaluser + "' where OWNER = '" + oldcaluser + "'");
+    db.runStatement("update ASYS_CALENDARBACKEND set ORGANIZER = '" + newcaluser + "' where ORGANIZER = '" + oldcaluser + "'");
+
+    if(pNewCalendarID != pOldCalendarID) //Nur wenn sich die E-Mailadresse geändert hat
+    {
+        //Messenger-Historien
+        db.runStatement("update ASYS_XMPP_HISTORY set JID_FROM = '" + pNewCalendarID +"' where JID_FROM = '" + pOldCalendarID +"'", "_____SYSTEMALIAS");
+        db.runStatement("update ASYS_XMPP_HISTORY set JID_TO = '" + pNewCalendarID +"' where JID_TO = '" + pOldCalendarID +"'", "_____SYSTEMALIAS");
+    }
+}
+
+/*
+ * Löst den CalenderUser in lesbarer From auf
+ *
+ * @param {String} pValue req
+ *
+ * @return {String} übersetzten Wert
+ */
+function getCalUser( pValue )
+{
+    var realname = pValue;
+    var user = tools.getUser( text.decodeMS(pValue)[1].split(":")[1] );
+    if ( user != null )
+    {
+        realname = user[tools.PARAMS][tools.FIRSTNAME] + " " + user[tools.PARAMS][tools.LASTNAME];
+    }
+    return realname;
+}
+
+/*
+ * Gibt den Login eines CalenderUser zurück
+ *
+ * @param {String} pCalendarUser req
+ *
+ * @return {String} Title
+ */
+function getTitleCalenderUser( pCalendarUser )
+{
+    var data = text.decodeMS(pCalendarUser)
+    for ( var i = 0; i < data.length; i++ )
+    {
+        //if login changes we have to check calendarid
+        if ( data[i].substr(0, "mailto:".length).toUpperCase() == "MAILTO:" )
+        {
+            var user = tools.getUserByAttribute(tools.CALENDARID, [data[i].substr("mailto:".length)]);
+            if (user != null )
+                return user[tools.TITLE];
+        }
+
+        if ( data[i].substr(0, 3).toUpperCase() == "CN:" )
+            return data[i].substr(3);
+    }
+    return "";
+}
+
+
+/*
+ * Gibt den richtigen Status zum Prüfen je nach Backend zurück
+ *
+ *
+ * @param {String} pStatus req die konstante für den zu prüfenden status,
+ *                             z.B. calendars.STATUS_INPROCESS
+ *
+ * @param {String} pCalendarType req die konstante für den typen des Termin- oder Aufgabenbackends,
+ *                             z.B. calendars.BACKEND_DB
+ *
+ * @return {String} Konstanten für den Kalender (Backend-Typen), gibt es den status im backend nicht
+ *                  wird null geliefert
+ */
+function mapCalendarStatus(pStatus, pCalendarType)
+{
+    switch (pCalendarType)
+    {
+        //case calendars.BACKEND_EXCHANGE:
+        case calendars.BACKEND_EXCHANGEWS:
+            if (pStatus == calendars.STATUS_CONFIRMED)
+                return calendars.STATUS_BUSY;
+            else
+                return pStatus;
+        default:
+            if (pStatus == calendars.STATUS_OOF)//nur bei exchange
+                return null;
+            else
+                return pStatus;
+    }
+}
+
+/*
+ * Sets the imagevariable with affectedusers
+ *
+ * @param {Object} pEntry req the Entry of Tasks or Appointments
+ *
+ * @return {void}
+ *
+ */
+function setAffectedUsersImage(pEntry)
+{
+    var affectedUsers = [];
+    var usermap = pEntry[calendars.ATTENDEES];
+    var realnames = getRealNameObject(usermap);
+
+    for ( var i = 0; i < usermap.length; i++ )
+    {
+        affectedUsers.push([ text.encodeMS( [usermap[i]["paramvalue"], "CN:" + usermap[i]["cn"]] ), realnames[usermap[i]["cn"]] ]);
+    }
+
+    vars.set("$image.affectedusers", affectedUsers);
+    return affectedUsers;
+}
+
+/*
+ * Opens calendar links
+ *
+ * @param {String} pEntryID req the ID of the link
+ *
+ * @return {void}
+ *
+ */
+function openCalendarLinks(pEntryID)
+{
+    var openFramesObj = {};
+    if (typeof(pEntryID) == "object")
+        openFramesObj = pEntryID;
+    else
+    {
+        var links = db.table("SELECT FRAME, DBIDCOLUMN, DBID FROM ASYS_CALENDARLINK WHERE ENTRYID = '" + pEntryID + "'");
+        for (var i = 0; i < links.length; i++)
+        {
+            var frame = links[i][0].substr( 5 );//remove comp. so the frame can be opened with openFrame
+            if ( openFramesObj[frame] == undefined ) openFramesObj[frame] = {
+                IDField: links[i][1],
+                IDs: []
+            };
+            openFramesObj[frame].IDs.push(links[i][2]);
+        }
+    }
+
+    for ( frame in openFramesObj)
+    {
+        var condition = openFramesObj[frame].IDField + " in ('" + openFramesObj[frame].IDs.join("', '") + "')";
+        var framemode = openFramesObj[frame].IDs.length > 1 ? swing.FRAMEMODE_TABLE_SELECTION : swing.FRAMEMODE_SHOW;
+
+        if ( vars.getString("$global.upwardLink") == "link")
+        {
+            swing.openLinkedFrame(frame, condition, swing.WINDOW_CURRENT, framemode, "", null, false, {
+                autoclose: true
+            } );
+        }
+        else
+        {
+            swing.openFrame(frame, condition, swing.WINDOW_CURRENT, framemode, null, false);
+        }
+    }
+}
+
+/**
+ * Returns the "real" calendar system/backend type (BackendType & SyncBackendType)
+ *
+ * @param {Number} pScope - The needed scope (e.g. "calendars.VEVENT", "calendars.VTODO")
+ * @return {Number} - The backend type (calendars.BACKEND_*)
+ */
+function getCalendarSystemType (pScope)
+{
+    // Check sync backend type
+    if (calendars.getSyncBackendType() != calendars.BACKEND_NONE && calendars.getSyncBackendType() != 3)
+    {
+        var scope = calendars.getSyncBackendTypeScope();
+        if (scope.length == 1 && scope[0] == pScope) // Scope.length = 1 -> VEVENT *OR* VTODO
+            return calendars.getSyncBackendType();
+        else if (scope.length == 2) // Scope.length = 2 -> Both
+            return calendars.getSyncBackendType();
+       // Scope.length = 0 -> Nothing selected -> Skip this block
+    }
+
+    // Fallback to backend type (event)
+    if (calendars.getBackendType() != calendars.BACKEND_NONE && pScope === calendars.VEVENT)
+        return calendars.getBackendType();
+
+    // Second fallback to backend type (todo)
+    if (calendars.getBackendTypeTasks() != calendars.BACKEND_NONE && pScope === calendars.VTODO)
+        return calendars.getBackendTypeTasks();
+
+    // Everything is none
+    return calendars.BACKEND_NONE;
+}
+
+function hasGrantForEntryByMS(pAffectedUsers, pUserMap)
+{
+    for (let i = 0; i < pAffectedUsers.length; i++)
+    {
+        var calUser = getTitleCalenderUser( pAffectedUsers[i][0]);
+        if(pUserMap[calUser] == undefined)
+        {
+            return false;
+            break;
+        }
+        else
+            return true;
+    }
+}
+
+function hasGrantForEntryByObject(pAffectedUsers, pUserMap)
+{
+    for (let i = 0; i < pAffectedUsers.length; i++)
+    {
+        calUser = tools.getUserByAttribute(tools.CALENDARID, pAffectedUsers[i]["paramvalue"].substr("mailto:".length))
+        if (calUser == null)  calUser = pAffectedUsers[i]["cn"];
+        else calUser = calUser[tools.TITLE]
+        if(pUserMap[calUser] == undefined)
+        {
+            return false;
+            break;
+        }
+        else
+            return true;
+    }
+}
diff --git a/process/Contact_lib/process.js b/process/Contact_lib/process.js
index 7539546b86e240ee05c0c28df960fec4ef92a420..f533b09e7c845e0beb0501277af23ea1a42e228b 100644
--- a/process/Contact_lib/process.js
+++ b/process/Contact_lib/process.js
@@ -332,6 +332,17 @@ ContactUtils.getFullContactString = function()
     + " left join ADDRESS on ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID";
 }
 
+/**
+ * get the addressid of the default address
+ *
+ * @return {String} the ID or "" if no default address exists
+ */
+ContactUtils.getDefaultAddressId = function(pContactId)
+{
+    return db.cell(SqlCondition.begin().andPrepare("CONTACT.CONTACTID", pContactId)
+                               .buildSql("select ADDRESS_ID from CONTACT", "1=2"));
+}
+
 /**
  * object for handling of a single contact
  * provides static- and instance-functions
diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js
index fc47c28f0d7196aee746ad9485ae0b6806cac1fb..59b73f68c2d941b49c16e821da95d5089a5f8628 100644
--- a/process/Context_lib/process.js
+++ b/process/Context_lib/process.js
@@ -42,30 +42,34 @@ ContextUtils.getContextName = function(pContextId)
 /**
  *
  * @param {Boolean} [pFilter=false] filter only for contexts which have a mapping in ContextUtils.getSelectMap 
- * @param {String[]} [pExcludeContexts] contextIds that shall not be included (so this is a additional filter to the pFiler param)
+ * @param {String[]} [pExclusiveContexts] contextIds that shall not be included (so this is a additional filter to the pFilter param)
+ * @param {Boolean} [pUseExclusives=false] decides whether the items in pExclusiveContexts are excluded (false) or
+ *                      everything that is not in pExclusiveContexts is excluded (true)
  *
  * @return {String[][]} the contexts [[contextId, contextName, contextTitle], [... ], ...]
  */
-ContextUtils.getContexts = function(pFilter, pExcludeContexts)
+ContextUtils.getContexts = function(pFilter, pExclusiveContexts, pUseExclusives)
 {
     if (pFilter == undefined)
         pFilter = false;
+    if (pUseExclusives == undefined)
+        pUseExclusives = false;
 
     var contexts = project.getDataModels(project.DATAMODEL_KIND_CONTEXT);
 
     if (pFilter)
     {
         contexts = contexts.filter(function(pContext) {
-            if (pExcludeContexts && pExcludeContexts.indexOf(pContext[0]) > -1)
+            if (pExclusiveContexts && pExclusiveContexts.indexOf(pContext[0]) > -1 != pUseExclusives)
                 return false;
             // filter only contexts which have defined mappings in Context_lib
             return ContextUtils.getSelectMap ()[pContext[0]] != undefined;
         });
     }
-    else if (pExcludeContexts)
+    else if (pExclusiveContexts)
     {
         contexts = contexts.filter(function(pContext) {
-            if (pExcludeContexts && pExcludeContexts.indexOf(pContext[0]) > -1)
+            if (pExclusiveContexts && pExclusiveContexts.indexOf(pContext[0]) > -1 != pUseExclusives)
                 return false;
             return true;
         });
@@ -370,7 +374,7 @@ ContextUtils.getNameSubselectSql = function(pContextIdDbField, pRowIdDbField)
     var selectMap = ContextUtils.getSelectMap ()
     for (let contextId in selectMap)
     {
-        select += "when '" + contextId + "' then (select " + selectMap[contextId].titleExpression + " from " + selectMap[contextId].getFullFromClause() + (pRowIdDbField ? " where " + selectMap[pContextId].getFullIdField() + " = " + pRowIdDbField : " ") + ") ";
+        select += "when '" + contextId + "' then (select " + selectMap[contextId].titleExpression + " from " + selectMap[contextId].getFullFromClause() + (pRowIdDbField ? " where " + selectMap[contextId].getFullIdField() + " = " + pRowIdDbField : " ") + ") ";
     }
 
     select += "else 'Not defined in ContextUtils.getNameSql()!'";
diff --git a/process/Employee_lib/process.js b/process/Employee_lib/process.js
index dac86b25c4f2515a8db0a6b58585a9026a6f1c46..1394a104183042a9a94d00947089892e44e2fb30 100644
--- a/process/Employee_lib/process.js
+++ b/process/Employee_lib/process.js
@@ -1,113 +1,116 @@
-import("system.db");
-import("Sql_lib");
-import("system.tools");
-
-/**
- * Provides functions for employees and users.j
- * 
- * Do not create an instance of this!
- * 
- * @class
- */
-function EmployeeUtils () {}
-
-/**
- * Returns the contact id of the current user
- * 
- * @return the contact id
- */
-EmployeeUtils.getCurrentContactId = function ()
-{
-    var user = tools.getCurrentUser();
-    return user ? user[tools.PARAMS][tools.CONTACTID] : null;
-}
-
-/**
- * Returns the username id of the current user
- * 
- * @return the username
- */
-EmployeeUtils.getCurrentUserName = function ()
-{
-    var user = tools.getCurrentUser();
-    return user ? user[tools.TITLE] : null;
-}
-
-EmployeeUtils.sliceUserId = function (pUserId)
-{
-    return pUserId.substr(10, 36);
-}
-
-/**
- * generates a username from the firstname and lastname with the given structure
- * 
- * @param {String} pFirstName
- * @param {String} pLastName
- * @param {String} pStructure the structure of the username, special characters:
- *      f - one letter of the firstname in lowercase
- *      F - one letter of the firstname in uppsercase
- *      l - one letter of the lastname in lowercase
- *      L - one letter of the lastname in uppsercase
- *      f+ - the complete firstname in lowercase
- *      F+ - the complete firstname
- *      l+ - the complete lastname in lowercae
- *      L+ - the complete lastname 
- * 
- * @return {String} the generated username
- */
-EmployeeUtils.generateUserName = function (pFirstName, pLastName, pStructure)
-{
-    if (!pStructure || (!pFirstName && !pLastName))
-        return null;
-    
-    var firstNameIndex = 0;
-    var lastNameIndex = 0;
-    var userName = pStructure.replace(/(f\+|l\+|f|l)/ig, function (type)
-    {
-        switch (type)
-        {
-            case "f+":
-            return pFirstName.toLowerCase() || "";
-            case "F+":
-                return pFirstName || "";
-            case "l+":
-                return pLastName.toLowerCase()  || "";
-            case "L+":
-                return pLastName || "";
-            case "f":
-                return pFirstName.charAt(firstNameIndex++).toLowerCase() || "";
-            case "F":
-                return pFirstName.charAt(firstNameIndex++).toUpperCase() || "";
-            case "l":
-                return pLastName.charAt(lastNameIndex++).toLowerCase() || "";
-            case "L":
-                return pLastName.charAt(lastNameIndex++).toUpperCase() || "";
-        }
-    });
-    
-    return userName;
-}
-
-/**
- * checks if an employee is used somewhere
- * 
- * @param {String} pContactId the contact id of the user
- * 
- * @return {boolean} if the employee has relations
- */
-EmployeeUtils.hasRelations = function (pContactId)
-{
-    //sql queries with selects on tables where an employee can be used
-    var queries = [
-        SqlCondition.begin()
-            .andPrepare("ACTIVITY.CREATOR", pContactId)
-            .buildSql("select 1 from ACTIVITY"),
-        SqlCondition.begin()
-            .andPrepare("TIMETRACKING.CONTACT_ID", pContactId)
-            .buildSql("select 1 from TIMETRACKING")
-    ];
-    return queries.some(function (sql)
-        {
-            return db.cell(sql) != "";
-        });
+import("system.db");
+import("Sql_lib");
+import("system.tools");
+
+/**
+ * Provides functions for employees and users.j
+ * 
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function EmployeeUtils () {}
+
+/**
+ * Returns the contact id of the current user
+ * 
+ * @return the contact id
+ */
+EmployeeUtils.getCurrentContactId = function ()
+{
+    var user = tools.getCurrentUser();
+    return user ? user[tools.PARAMS][tools.CONTACTID] : null;
+}
+
+/**
+ * Returns the username id of the current user
+ * 
+ * @return the username
+ */
+EmployeeUtils.getCurrentUserName = function ()
+{
+    var user = tools.getCurrentUser();
+    return user ? user[tools.TITLE] : null;
+}
+
+EmployeeUtils.sliceUserId = function (pUserId)
+{
+    return pUserId.substr(10, 36);
+}
+
+/**
+ * generates a username from the firstname and lastname with the given structure
+ * 
+ * @param {String} pFirstName
+ * @param {String} pLastName
+ * @param {String} pStructure the structure of the username, special characters:
+ *      f - one letter of the firstname in lowercase
+ *      F - one letter of the firstname in uppsercase
+ *      l - one letter of the lastname in lowercase
+ *      L - one letter of the lastname in uppsercase
+ *      f+ - the complete firstname in lowercase
+ *      F+ - the complete firstname
+ *      l+ - the complete lastname in lowercae
+ *      L+ - the complete lastname 
+ * 
+ * @return {String} the generated username
+ */
+EmployeeUtils.generateUserName = function (pFirstName, pLastName, pStructure)
+{
+    if (!pStructure || (!pFirstName && !pLastName))
+        return null;
+    
+    var firstNameIndex = 0;
+    var lastNameIndex = 0;
+    var userName = pStructure.replace(/(f\+|l\+|f|l)/ig, function (type)
+    {
+        switch (type)
+        {
+            case "f+":
+            return pFirstName.toLowerCase() || "";
+            case "F+":
+                return pFirstName || "";
+            case "l+":
+                return pLastName.toLowerCase()  || "";
+            case "L+":
+                return pLastName || "";
+            case "f":
+                return pFirstName.charAt(firstNameIndex++).toLowerCase() || "";
+            case "F":
+                return pFirstName.charAt(firstNameIndex++).toUpperCase() || "";
+            case "l":
+                return pLastName.charAt(lastNameIndex++).toLowerCase() || "";
+            case "L":
+                return pLastName.charAt(lastNameIndex++).toUpperCase() || "";
+        }
+    });
+    
+    return userName;
+}
+
+/**
+ * checks if an employee is used somewhere
+ * 
+ * @param {String} pContactId the contact id of the user
+ * 
+ * @return {boolean} if the employee has relations
+ */
+EmployeeUtils.hasRelations = function (pContactId)
+{
+    //sql queries with selects on tables where an employee can be used
+    var queries = [
+        SqlCondition.begin()
+            .andPrepare("ACTIVITY.RESPONSIBLE", pContactId)
+            .buildSql("select 1 from ACTIVITY"),
+        SqlCondition.begin()
+            .andPrepare("TASK.REQUESTOR_CONTACT_ID", pContactId)
+            .buildSql("select 1 from TASK"),
+        SqlCondition.begin()
+            .andPrepare("TIMETRACKING.CONTACT_ID", pContactId)
+            .buildSql("select 1 from TIMETRACKING")
+    ];
+    return queries.some(function (sql)
+        {
+            return db.cell(sql) != "";
+        });
 }
\ No newline at end of file
diff --git a/process/ImporterCustomMappingFunctions_lib/ImporterCustomMappingFunctions_lib.aod b/process/ImporterCustomMappingFunctions_lib/ImporterCustomMappingFunctions_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..6544d46839aa52bd3517add653f0eb0a8fb7e881
--- /dev/null
+++ b/process/ImporterCustomMappingFunctions_lib/ImporterCustomMappingFunctions_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>ImporterCustomMappingFunctions_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/ImporterCustomMappingFunctions_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/ImporterCustomMappingFunctions_lib/process.js b/process/ImporterCustomMappingFunctions_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..bbfd65d5d7dccccbb1ea6066c73a7df03aea68d8
--- /dev/null
+++ b/process/ImporterCustomMappingFunctions_lib/process.js
@@ -0,0 +1,4 @@
+///////////////////////////////////////////////////////////////////
+/// custom toolkit methods for the import handler               ///
+/// edit this, since this is serperate vor every project        ///
+///////////////////////////////////////////////////////////////////
diff --git a/process/ImporterMappingFunctions_lib/ImporterMappingFunctions_lib.aod b/process/ImporterMappingFunctions_lib/ImporterMappingFunctions_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..0e8acf1918c716ed3d774608965f64b1dba0d136
--- /dev/null
+++ b/process/ImporterMappingFunctions_lib/ImporterMappingFunctions_lib.aod
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>ImporterMappingFunctions_lib</name>
+  <comment></comment>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/ImporterMappingFunctions_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/ImporterMappingFunctions_lib/process.js b/process/ImporterMappingFunctions_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..05c4aa930bda24e17fd357797301b67bd8fce6d3
--- /dev/null
+++ b/process/ImporterMappingFunctions_lib/process.js
@@ -0,0 +1,1028 @@
+import("system.fileIO");
+import("system.SQLTYPES");
+import("system.text");
+import("system.db");
+import("system.vars");
+import("system.eMath");
+import("system.util");
+import("system.datetime");
+import("system.logging");
+import("Attribute_lib");
+import("Sql_lib");
+import("Importer_lib");
+
+/////////////////////////////////////////////////////////////////////
+/// toolkit methods for the import handler                      ///
+/// DO NOT TOUCH - use lib_importerCustomMappingFunctions       ///
+///////////////////////////////////////////////////////////////////
+
+/*
+* Values of the mapping line:
+* Keyword req -- the column index with the new keyword value
+* Container req -- the keyword container for the keyword lookup
+*
+* @name iKeyword
+* @param {Object} pObject req the mapping line
+* @return {Boolean} true
+**/
+function iKeyword(pObject) { 
+    if (!this.doIfCheck(pObject)) return true;
+
+    var keyword = this.InputRecord[pObject.Keyword];
+    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.Keyword);
+    var container = this.InputRecord[pObject.Container];
+    if(container == undefined) container = this.resolveSymbol(pObject, pObject.Container);
+
+    if(!keyword || !container)  return true;
+    
+    var sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
+    + this.getColumnCase("container") + " = ? and " + this.getColumnCase("title") + " = ?";
+    var id = db.cell([sql, [[container, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+    
+    if(id == "" || id == null) {
+        id = util.getNewUUID();
+        var columns = [this.getColumnCase("ab_keyword_entryid"), this.getColumnCase("keyid"), this.getColumnCase("container"),
+            this.getColumnCase("title"), this.getColumnCase("sorting"), this.getColumnCase("isactive"), this.getColumnCase("isessential")]; 
+        sql = "select max(coalesce(sorting, 0))+1 from ab_keyword_entry where container = ?";
+        var sort = db.cell([sql, [[container, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+        if(sort == "") sort = "0";
+        values = [id, util.getNewUUID(), container, keyword, sort, "1", "0"];
+        this.insertData(this.getTableCase("ab_keyword_entry"), columns, null, values, this.Config.AliasTo);
+    }
+    this.setOutput(pObject, id);
+    return true;
+}
+
+/*
+ * Values of the mapping line:
+ * Attribute req -- the new attribute name
+ * AType req -- the type of the attribute
+ * OType opt -- the type of the object (AB_ATTRIBUTEUSAGE)
+ * OID opt -- the row id for the object instance (AB_ATTRIBUTERELATION)
+ * Value opt -- the value for the object instance (AB_ATTRIBUTERELATION)
+ *
+ * @name iAttribute
+ * @param {Object} pObject req the mapping line
+ * @return {Boolean} true
+ * */
+function iAttribute(pObject) {
+    if (!this.doIfCheck(pObject)) return true;
+
+    var attribute = this.InputRecord[pObject.Attribute];
+    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.Attribute);
+    var atype = this.InputRecord[pObject.AType];
+    if(atype == undefined) atype = this.resolveSymbol(pObject, pObject.AType);
+    var otype = this.InputRecord[pObject.OType];
+    if(otype == undefined) otype = this.resolveSymbol(pObject, pObject.OType);
+    var oid = this.InputRecord[pObject.OID];
+    if(oid == undefined) oid = this.resolveSymbol(pObject, pObject.OID);
+    var value = this.InputRecord[pObject.Value];
+    if(value == undefined) value = this.resolveSymbol(pObject, pObject.Value);
+    
+    if (!attribute || !atype) return true;
+    atype = atype.toUpperCase();
+
+    var valueColumn = "";
+    var attributes = attribute.split(".");   
+    var columns = [this.getColumnCase("ab_attributeid"), this.getColumnCase("attribute_parent_id"), this.getColumnCase("attribute_name"), 
+        this.getColumnCase("attribute_type"), this.getColumnCase("attribute_level"), this.getColumnCase("attribute_active")];
+    var type = $AttributeTypes.GROUP.toString();
+    switch (atype) {
+        case $AttributeTypes.TEXT.toString():
+            valueColumn = this.getColumnCase("char_value");
+            break;
+        case $AttributeTypes.DATE.toString():
+            valueColumn = this.getColumnCase("date_value");
+            break;
+        case $AttributeTypes.NUMBER.toString():
+            valueColumn = this.getColumnCase("number_value");
+            break;
+        case $AttributeTypes.BOOLEAN.toString():
+            valueColumn = this.getColumnCase("bool_value");
+            break;
+        case $AttributeTypes.COMBO.toString():
+            valueColumn = this.getColumnCase("id_value");
+            type = $AttributeTypes.COMBO.toString();
+            break;
+        default:
+            return true;
+    }
+
+    if (this.FuncBuffer.iAttribute == undefined) this.FuncBuffer.iAttribute = {childs: {}};
+    var pathToFollow = this.FuncBuffer.iAttribute;
+    for (var i = 0; i < attributes.length; i++)  {
+        if (pathToFollow["childs"][attributes[i]] != undefined) {
+            var id = pathToFollow["childs"][attributes[i]]["id"];            
+        } else {
+            pathToFollow["childs"][attributes[i]] = {id: id, childs: {}};
+            if (i == 0) {
+                var parent = "NULL";  
+                var sql = "select " + this.getColumnCase("ab_attributeid") + " from  " + this.getTableCase("ab_attribute") + " where " 
+                + this.getColumnCase("attribute_name") + " = ? and " + this.getColumnCase("attribute_level") + " = 0";
+                id = db.cell([sql, [[attributes[i], SQLTYPES.VARCHAR]]], this.Config.AliasTo);                         
+            } else {
+                parent = pathToFollow["id"];
+                sql = "select " + this.getColumnCase("ab_attributeid") + " from " + this.getTableCase("ab_attribute") + " where " 
+                    + this.getColumnCase("attribute_name") + " = ? and " + this.getColumnCase("attribute_parent_id") + " = ?";
+                id = db.cell([sql, [[attributes[i], SQLTYPES.VARCHAR], [parent, SQLTYPES.CHAR]]], this.Config.AliasTo);                         
+            }       
+            if (id == "" || id == null) {
+                id = util.getNewUUID();
+                if (attributes.length == i+1) type = atype;
+                //TODO: add insertNoWait to instantly add AB_ATTRIBUTE records; this ensures that nothing is in the funcBuffer that does not exist in the database
+                //TODO: check: are COMOB-values added automatically?
+                this.insertData(this.getTableCase("ab_attribute"), columns, null, [id, parent, attributes[i], type, i.toString(), "1"], this.Config.AliasTo);
+            }
+            pathToFollow["childs"][attributes[i]]["id"] = id;
+        }
+        pathToFollow = pathToFollow["childs"][attributes[i]];
+    } 
+    
+    if (otype) {
+        var aid = id;
+        sql = "select " + this.getColumnCase("ab_attributeusageid") + " from " + this.getTableCase("ab_attributeusage") + " where "
+            + this.getColumnCase("ab_attribute_id") + " = ? and " + this.getColumnCase("object_type") + " = ?";
+        id = db.cell([sql, [[aid, SQLTYPES.CHAR], [otype, SQLTYPES.VARCHAR]]], this.Config.AliasTo);      
+        if (id == "" || id == null) {
+            columns = [this.getColumnCase("ab_attributeusageid"), this.getColumnCase("ab_attribute_id"), this.getColumnCase("object_type")];
+            this.insertData(this.getTableCase("ab_attributeusage"), columns, null, [util.getNewUUID(), aid, otype], this.Config.AliasTo);
+        } 
+        
+        if (value && oid) {
+            sql = "select " + this.getColumnCase("ab_attributerelationid") + " from " + this.getTableCase("ab_attributerelation") + " where " 
+                 + this.getColumnCase("ab_attribute_id") + " = ? and " + this.getColumnCase("object_rowid") + " = ? and "
+                 + this.getColumnCase("object_type") + " = ?";
+            id = db.cell([sql, [[aid, SQLTYPES.CHAR], [oid, SQLTYPES.CHAR], [otype, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+            if (id == "" || id == null) {
+                columns = [this.getColumnCase("ab_attributerelationid"), this.getColumnCase("ab_attribute_id"), this.getColumnCase("object_type"),
+                     this.getColumnCase("object_rowid"), valueColumn];
+                 this.insertData(this.getTableCase("ab_attributerelation"), columns, null, [util.getNewUUID(), aid, otype, oid, value], this.Config.AliasTo);
+            } else if (this.Config.ImportCommand.indexOf("update") != -1) {
+                cond = this.getColumnCase("ab_attributerelationid") + " = '" + id + "'";
+                this.updateData(this.getTableCase("ab_attributerelation"), [valueColumn], null, [value], cond, this.Config.AliasTo);
+            }
+        }
+    }    
+    return true;
+}
+
+/*
+ * Values of the mapping line:
+ * Attribute req -- the column index with the new attribute value
+ * AType req -- the type of the attribute
+ * Container req -- the container name of the keyword
+ * Keyword opt -- a new keyword name or an existing KeyId (AB_KEYWORD_ATTRIBUTERELATION)
+ * Value opt - the value of the relation (AB_KEYWORD_ATTRIBUTERELATION)
+ *
+ * @name iKeywordAttribute
+ * @param {Object} pObject req the mapping line
+ * @return {Boolean} true
+ * */
+function iKeywordAttribute(pObject) {
+    if (!this.doIfCheck(pObject)) return true;
+    
+    var attribute = this.InputRecord[pObject.Attribute];
+    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.Attribute);
+    var atype = this.InputRecord[pObject.AType];
+    if(atype == undefined) atype = this.resolveSymbol(pObject, pObject.AType);
+    var container = this.InputRecord[pObject.Container];
+    if(container == undefined) container = this.resolveSymbol(pObject, pObject.Container);
+    var keyword = this.InputRecord[pObject.Keyword];
+    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.Keyword);
+    var value = this.InputRecord[pObject.Value];
+    if(value == undefined) value = this.resolveSymbol(pObject, pObject.Value);
+    
+    if (!attribute || !container || !atype) return true;
+    atype = atype.toUpperCase();
+    
+    var valueColumn = "";
+    switch (atype) {
+        case $AttributeTypes.TEXT.toString():
+            valueColumn = this.getColumnCase("char_value");
+            break;
+        case $AttributeTypes.NUMBER.toString():
+            valueColumn = this.getColumnCase("number_value");           
+            break;
+        case $AttributeTypes.BOOLEAN.toString():
+            valueColumn = this.getColumnCase("bool_value");         
+            break;
+        default:
+            return true;
+    }
+    
+    var sql = "select " + this.getColumnCase("ab_keyword_attributeid") + " from  " + this.getTableCase("ab_keyword_attribute") 
+        + " where " + this.getColumnCase("name") + " = ? and " + this.getColumnCase("container") + " = ?";
+    var aid = db.cell([sql, [[attribute, SQLTYPES.VARCHAR], [container, SQLTYPES.VARCHAR]]], this.Config.AliasTo); 
+    if (aid == "" || aid == null) {
+        aid = util.getNewUUID();
+        var columns = [this.getColumnCase("ab_keyword_attributeid"), this.getColumnCase("name"), this.getColumnCase("container"), this.getColumnCase("type")];
+        this.insertData(this.getTableCase("ab_keyword_attribute"), columns, null, [aid, attribute, container, atype], this.Config.AliasTo);
+    }
+    
+    if (keyword && value) {   
+        sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
+            + this.getColumnCase("keyid") + " = ?";
+        var kid = db.cell([sql, [[keyword, SQLTYPES.CHAR]]], this.Config.AliasTo);      
+        
+        if (kid == "" || kid == null) {
+            sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
+                + this.getColumnCase("container") + " = ? and " + this.getColumnCase("title") + " = ?";
+            kid = db.cell([sql, [[container, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+            if (kid == "" || kid == null) {
+                columns = [this.getColumnCase("ab_keyword_entryid"), this.getColumnCase("keyid"), this.getColumnCase("container"),
+                    this.getColumnCase("title"), this.getColumnCase("sorting"), this.getColumnCase("isactive"), this.getColumnCase("isessential")]; 
+                sql = "select max(coalesce(sorting, 0))+1 from ab_keyword_entry where container = ?";
+                var sort = db.cell([sql, [[container, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+                if(sort == "") sort = "0";
+                kid = util.getNewUUID();
+                this.insertData(this.getTableCase("ab_keyword_entry"), columns, null, 
+                    [kid, util.getNewUUID(), container, keyword, sort, "1", "0"], this.Config.AliasTo);
+            }
+        }
+        
+        sql = "select " + this.getColumnCase("ab_keyword_attributerelationid") + " from " + this.getTableCase("ab_keyword_attributerelation") 
+            + " where " + this.getColumnCase("ab_keyword_entry_id") + " = ? and " + this.getColumnCase("ab_keyword_attribute_id") + " = ?";
+        id = db.cell([sql, [[kid, SQLTYPES.CHAR], [aid, SQLTYPES.CHAR]]], this.Config.AliasTo);
+        if (id == "" || id == null) {
+            columns = [this.getColumnCase("ab_keyword_attributerelationid"), this.getColumnCase("ab_keyword_entry_id"), 
+                this.getColumnCase("ab_keyword_attribute_id"), valueColumn];
+            id = util.getNewUUID();
+            this.insertData(this.getTableCase("ab_keyword_attributerelation"), columns, null, [id, kid, aid, value], this.Config.AliasTo);
+        } else {
+            if (this.Config.ImportCommand.indexOf("update") != -1) {
+                cond = this.getColumnCase("ab_keyword_attributerelationid") + " = '" + id + "'";
+                this.updateData(this.getTableCase("ab_keyword_attributerelation"), [valueColumn], null, [value], cond, this.Config.AliasTo);
+            }            
+        }       
+        this.setOutput(pObject, id);
+    } else {
+        this.setOutput(pObject, aid);
+    }
+    return true;  
+}
+
+/*
+ * Values of the mapping line:
+ * Address req -- the address for the communication entry
+ * Medium req -- the medium id
+ * ContactID req -- the id of the entry in the contact table
+ * Standard opt -- the standard value (boolean)
+ *
+ * @name iComm
+ * @param {Object} pObject req the mapping line
+ * @return {Boolean} true
+ * */
+function iComm(pObject) {
+    if (! this.doIfCheck(pObject)) return true;
+
+    var address = this.InputRecord[pObject.Address];
+    if(address == undefined) address = this.resolveSymbol(pObject, pObject.Address);
+    var medium = this.InputRecord[pObject.Medium];
+    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.Medium);
+    var contact = this.InputRecord[pObject.ContactID];
+    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
+    var standard = "0";
+    if(pObject.Standard) standard = "1";
+    
+    if(!address || !medium || !contact) return true;
+    
+    var sql = "select " + this.getColumnCase("communicationid") + " from " + this.getTableCase("communication")
+        +" where " + this.getColumnCase("contact_id") + " = ? and " + this.getColumnCase("medium_id") + " = ? and "
+        + this.getColumnCase("standard") + " = ? and " + this.getColumnCase("addr") + " = ?"
+    var id = db.cell([sql, [[contact, SQLTYPES.CHAR], [medium, SQLTYPES.INTEGER], 
+            [standard, SQLTYPES.SMALLINT], [address, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+    if (id == "" || id == null) {
+        var columns = [this.getColumnCase("communicationid"), this.getColumnCase("addr"), 
+            this.getColumnCase("medium_id"), this.getColumnCase("contact_id"), this.getColumnCase("standard")];
+        this.insertData(this.getTableCase("communication"), columns, null, [util.getNewUUID(), address, medium, contact, standard], this.Config.AliasTo);       
+    }    
+    return true;
+}
+
+/*
+ * Values of the mapping line:
+ * Reason opt -- the reason 
+ * Medium req -- the medium id
+ * ContactID req -- the id of the entry in the contact table
+ * Type req -- yes or no to communication
+ *
+ * @name iCommRestriction
+ * @param {Object} pObject req the mapping line
+ * @return {Boolean} true
+ * */
+function iCommRestriction(pObject) {
+    if (!this.doIfCheck(pObject)) return true;
+
+    var reason = this.InputRecord[pObject.Reason];
+    if(reason == undefined) reason = this.resolveSymbol(pObject, pObject.Reason);
+    var medium = this.InputRecord[pObject.Medium];
+    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.Medium);
+    var contact = this.InputRecord[pObject.ContactID];
+    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
+    var type = this.InputRecord[pObject.Type];
+    if(type == undefined) type = this.resolveSymbol(pObject, pObject.Type);
+    
+    if (!medium || !contact || !type) return true;
+
+    var sql = "select top 1 " + this.getColumnCase("type") + " from " + this.getTableCase("commrestriction")
+        +" where " + this.getColumnCase("contact_id") + " = ? and " + this.getColumnCase("medium") + " = ? order by " 
+        + this.getColumnCase("date_edit") + " desc, " + this.getColumnCase("date_new") + " desc";
+    var id = db.cell([sql, [[contact, SQLTYPES.CHAR], [medium, SQLTYPES.CHAR]]], this.Config.AliasTo);
+    if (id == "" || id == null || id != type) {
+        if(reason == undefined || reason == null) reason = "NULL";
+        var columns = [this.getColumnCase("commrestrictionid"), this.getColumnCase("medium"), this.getColumnCase("contact_id"), this.getColumnCase("type"), this.getColumnCase("reason")];
+        this.insertData(this.getTableCase("commrestriction"), columns, null, [util.getNewUUID(), medium, contact, type, reason], this.Config.AliasTo);       
+    } 
+    return true;
+}
+
+/*
+ * Values of the mapping line:
+ * ActivityID req -- the column specifier for the activity table
+ * OID req -- the id for a default object for object_rowid
+ * OType req -- the context name
+ *
+ * @name iActivityLink
+ * @param {Object} pObject req the mapping line
+ * @return {Boolean} true
+ * */
+function iActivityLink(pObject) {
+    if (!this.doIfCheck(pObject)) return true;
+
+    var aid = this.InputRecord[pObject.ActivityID];
+    if(aid == undefined) aid = this.resolveSymbol(pObject, pObject.ActivityID);
+    var otype = this.InputRecord[pObject.OType];
+    if(otype == undefined) otype = this.resolveSymbol(pObject, pObject.OType);
+    var oid = this.InputRecord[pObject.OID];
+    if(oid == undefined) oid = this.resolveSymbol(pObject, pObject.OID);
+    
+    if (!aid || !oid || !otype) return true; 
+    
+    var sql = "select " + this.getColumnCase("activitylinkid") + " from " + this.getTableCase("activitylink") + " where "
+        + this.getColumnCase("activity_id") + " = ? and " + this.getColumnCase("object_type") + " = ? and " + this.getColumnCase("object_rowid") + " = ?";
+    var id = db.cell([sql, [[aid, SQLTYPES.VARCHAR], [otype, SQLTYPES.VARCHAR], [oid, SQLTYPES.CHAR]]], this.Config.AliasTo);
+    if (id == "" || id == null) {
+        var columns = [this.getColumnCase("activitylinkid"), this.getColumnCase("activity_id"), this.getColumnCase("object_type"), this.getColumnCase("object_rowid")];
+        this.insertData(this.getTableCase("activitylink"), columns, null, [util.getNewUUID(), aid, otype, oid], this.Config.AliasTo);
+    }
+    return true;
+}
+
+/*
+* imports an document from a given path
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true, if import of the data was successful, otherwise false
+*/
+function iDocumentByPath(pObject){
+    var resultDocument = true;
+    if (! this.doIfCheck(pObject)) return true;
+
+    try {
+        if(pObject.Rowid != "" && pObject.Filename != "") {
+            if(pObject.Value && pObject.Rowid) {          
+                var wert = this.resolveSymbol(pObject, pObject.Value);
+                var row = this.resolveSymbol(pObject, pObject.Rowid);
+                var dateNew = this.resolveSymbol(pObject, pObject.DateNew);           
+                var filename = this.InputRecord[pObject.Filename];
+                var data = fileIO.getData(wert, util.DATA_BINARY);
+                var length = fileIO.getLength(wert);
+                logging.log(filename + " " + dateNew)
+            }       
+            var sql = "select count(" + this.getColumnCase("row_id") + ") from " + this.getTableCase("asys_binaries") 
+                + " where " + this.getColumnCase("row_id") + " = ? and " + this.getColumnCase("filename") + " = ?";
+            var count = db.cell([sql, [[row, SQLTYPES.CHAR], [filename, SQLTYPES.VARCHAR]]], this.Config. AliasSys);
+            if(count == 0) {            
+                var cols = [this.getColumnCase("Id"), this.getColumnCase("Tablename"), this.getColumnCase("Datasize"),
+                    this.getColumnCase("date_new"), this.getColumnCase("date_edit"), this.getColumnCase("user_new"),
+                    this.getColumnCase("bindata"), this.getColumnCase("containername"), this.getColumnCase("filename"),
+                    this.getColumnCase("row_id"), this.getColumnCase("mimetype")];
+                var vals = [util.getNewUUID(), "$!GENERIC!$", length, dateNew, dateNew, vars.getString("$sys.user"), data, 
+                    "DOCUMENT", filename, row, util.getMimeType(filename)];
+                db.insertData(this.getTableCase("asys_binaries"), cols, null, vals, this.Config. AliasSys);
+            }
+        }
+    } catch(ex) {
+        logging.log("Datei nicht gefunden!");
+        resultDocument = false;
+    }
+    return resultDocument;
+}
+
+/*
+* imports an document
+* draft: Container: "string", Row: "TBL.COLID", Source: index, Filename: index, Tablename: "string",
+* Description: "string", Keywords: "string"
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true, if import of the data was successful, otherwise false
+*/
+function iDocument(pObject)
+{
+    var resultDocument = true;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    // iDocument is insert-only
+    this.setDefaultAction(pObject);
+    if(pObject.Action != "I") return resultDocument;
+
+    try
+    {
+        var desc = "";
+        if(pObject.Description != undefined) desc = this.InputRecord[pObject.Description];
+        var keyw = "";
+        if(pObject.Keywords != undefined) desc = this.InputRecord[pObject.Keywords];
+
+        if(pObject.Rowid != "" && pObject.Filename != "")
+            db.insertBinary(
+                            pObject.Tablename, 
+                            pObject.Container, 
+                            this.getOutput(pObject, "Rowid"), 
+                            null, 
+                            this.InputRecord[pObject.Source], 
+                            this.InputRecord[pObject.Filename], 
+                            desc, 
+                            keyw, 
+                            this.Config.AliasTo);
+    }
+    catch(ex)
+    {
+        logging.log(ex);
+        resultDocument = false;
+    }
+
+    return resultDocument;
+}
+
+/*
+* move import data to target
+*
+* @param {Object} pObject req the mapping line
+*
+* @example: [iMove, { Source: 3, Target: "RELATION.ADDRESS" } ]
+*
+* @return {Boolean} false, if the import of the row is not possible. otherwise true
+*/
+function iMove(pObject)
+{
+    var resultMove = true;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    if(pObject.Blobfile != undefined && pObject.Blobfile == true)  // blobfile move
+    {
+        var pn = pObject.Pathname;
+        var fn = this.InputRecord[pObject.Source];
+
+        // s will be NULL is something went wrong (no file, access error, etc)
+        var s = this.getFileContent(pn.toString() + fn.toString(), util.DATA_TEXT);
+
+        // if blob file could be read, assign to output buffer,
+        // otherweise signal "no import for this row" by returning false as the function value
+        if(s != null && s != undefined)
+            this.setOutput(pObject, s);
+        else
+            resultMove = false;
+    }
+    else  // no blob file handling, just plan old move
+    {
+        var expr = "";
+        if(pObject.Source != undefined) expr = this.InputRecord[pObject.Source];
+        if(pObject.Value != undefined) expr = this.resolveSymbol(pObject, pObject.Value, pObject.Eval);
+        if(pObject.Map != undefined && pObject.Index) expr = pObject.Map[this.resolveSymbol(pObject, pObject.Index, pObject.Eval)];
+
+        //if expr is undefined, then do no replace
+        if(expr != undefined)
+        {
+            // check for trimming option
+            if(pObject.Trim != undefined && typeof(pObject.Trim) == "string")
+            {
+                switch(pObject.Trim.toLowerCase())
+                {
+                    case "left":
+                        expr = expr.replace(/^\s+/, "");
+                        break;
+                    case "right":
+                        expr = expr.replace(/\s+$/, "");
+                        break;
+                    case "both":
+                        expr = expr.replace(/^\s+|\s+$/g, "");
+                        break;
+                }
+            }
+
+            // chek for replacing option
+            if(pObject.Replace != undefined && typeof(pObject.Replace) == "string" && pObject.ReplaceTo != undefined)
+                expr = expr.replace(pObject.Replace, pObject.ReplaceTo);
+
+            // check for format conversion
+            if(pObject.HTML2Text)
+                expr = text.html2text(expr);
+            else if (pObject.RTF2Text)
+                expr = text.rtf2text(expr);
+        }
+        else
+            expr = "";
+
+        this.setOutput(pObject, expr);
+    }
+
+    return resultMove;
+}
+
+
+/*
+* Return word number "Index" from source column.
+*    Values of the mapping line:
+*    String Source the source column index
+*    String Regex the regular expression for the split
+*    Number Index the word number starting with 0
+*    String Substring "right" or "left"
+*    String Separator concatenation string, default is blank
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true
+*/
+function iWord(pObject)
+{
+    var resultWord = true;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    var mode = pObject.Substring;
+    var sep = pObject.Separator;
+    if(sep == undefined) sep = " ";  // default concat with blank
+
+    // split the input string with the regex and get the word number,
+    // negative values will count from the end of the string (e.g. -1 for the last word in a string)
+    if(pObject.Source != undefined) s = this.InputRecord[pObject.Source];
+    if(pObject.Value != undefined) s = this.resolveSymbol(pObject, pObject.Value);
+
+    s = s.split( pObject.Regex );
+    var len = s.length;
+    var num = Number(pObject.Index);
+    if(num < 0) num = len - eMath.absInt(num);
+
+    // just to be sure we are in a valid range
+    if((num >= 0) && (num < len))
+    {
+        if(mode != undefined)
+        {
+            var part = "";
+            // concatenate up the word
+            mode = mode.toString().toLowerCase();
+            if(mode == "left")
+            {
+                num++;
+                part = s.slice(0,num).join(sep);
+            }
+            else if(mode == "right")
+            {
+                part = s.slice(pObject.Index).join(sep);
+            }
+            this.setOutput(pObject, part);
+        }
+        else
+        {
+            // use the single word
+            this.setOutput(pObject, s[num]);
+        }
+    }
+
+    if(resultWord == undefined) resultWord = "";
+    return resultWord;
+}
+
+
+/*
+* return a new ID for a key field
+*			 	Value of the mapping line:
+*				String pColumn req the key column
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true
+*/
+function iNewID(pObject)
+{
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    if (pObject.Action == undefined)
+    {
+        pObject.Action = "I";
+    }
+
+    this.setOutput(pObject, util.getNewUUID());
+    return true;
+}
+
+
+/*
+* join the list of columns into the specified target column
+* Values of the mapping line:
+*			Array pList req array containing result set indexes with joinable columns
+*			String pDelimiter req the delimiter string
+*			String pColumn req target column name
+*
+* @param {Object} pObject req the mapping line
+*
+* @example1: [iJoin, {Source: [3, 5], Delimiter: "\n", Target: "RELATION.ADDRESS"}]
+* @example2: [iJoin, {Value: ["{3}", "{5}"], Delimiter: "\n", Target: "RELATION.ADDRESS"}]
+*
+* @return {Boolean} true
+*/
+function iJoin(pObject)
+{
+    var s = "";
+    var len;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    if(pObject.Source != undefined)
+        len = pObject.Source.length;
+    if(pObject.Value != undefined)
+        len = pObject.Value.length;
+
+    for(var i=0; i < len; i++)
+    {
+        if (pObject.Source != undefined)
+            if(this.InputRecord[pObject.Source[i]] != "")
+            {
+                if(i > 0 ) s += pObject.Delimiter;
+                s += this.InputRecord[pObject.Source[i]];
+            }
+
+        if(pObject.Value != undefined)
+            if(this.resolveSymbol(pObject, pObject.Value[i]) != "")
+            {
+                if(i > 0 ) s += pObject.Delimiter;
+                s += this.resolveSymbol(pObject, pObject.Value[i]);
+            }
+    }
+
+    this.setOutput(pObject, s);
+
+
+    return true;
+}
+
+/*
+* executes an sql statement with the data from input result set column in pIndex
+* Values of the mapping line:
+* Number pIndex req the index into the input result set
+* String Command req the sql command (use {0}..{n} to specify source indexes)
+* String Alias req the alias name
+* String Target req the target column
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true
+*/
+function iSql(pObject)
+{
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    var sql = this.resolveSymbol(pObject, pObject.Command);
+
+    if (pObject.Target != undefined)
+        this.setOutput(pObject, db.cell(sql, pObject.Alias));
+    else
+        db.cell(sql, pObject.Alias);
+
+
+    return true;
+}
+
+
+/*
+* inserts or updates an relation entry
+*
+* @param {Object} pObject req the mapping line
+*
+* @example: [iInsertUpdate, { Table: "RELATION", Alias: "AO_DATEN",
+*                      			Columns: ( {Name: "RELATIONID", Source: 4, Required: true },
+*                            			     {Name: "AOTYPE", Value: "2" },
+*                                 			 {Name: "PERS_ID", Column: "PERS.PERSID" })  } ]
+*
+* @return {Boolean} true, if insert and update are successful, otherwise false
+*/
+function iInsertUpdate(pObject)
+{
+    var resultUpdate = true;
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    this.setDefaultAction(pObject);
+
+    try
+    {
+        var spalten = [];
+        var typen = [];
+        var werte = [];
+        var coldef;
+        var data_ok = true; // be optimistic ...
+        var alias = this.Config.AliasTo;
+        var tableName = this.getTableCase(pObject.Table);
+        var condition = this.resolveSymbol(pObject, pObject.Condition);
+
+        if(pObject.Action == undefined)  // set reasonable defaults for Action, if not specified
+        {
+            if(this.Config.ImportCommand == "insert")
+                pObject.Action = "I";
+            else if(this.Config.ImportCommand == "update")
+                pObject.Action = "U";
+            else if(this.Config.ImportCommand == "insert+update")
+                pObject.Action = "I+U";
+        }
+
+        if(this.Config.ImportCommand == "insert+update")
+        {
+            if(pObject.Action == "I")
+                action = "insert";
+            else if (pObject.Action == "U")
+                action = "update";
+            else if(pObject.Action == "I+U")
+            {
+                //try to find an existing entry
+                var entryid = db.cell("select count(*) from " + tableName + " where " + condition, alias);
+
+                if(Number(entryid) > 0)
+                {
+                    //exist, do update
+                    action = "update";
+                }
+                else
+                {
+                    //no entry, do insert
+                    action = "insert";
+                }
+            }
+        }
+        else if (this.Config.ImportCommand == "update")
+        {
+            action = "update";
+        }
+        else
+        {
+            action = "insert";
+        }
+
+        // loop thru the column definitions
+        for(var i=0; i < pObject.Columns.length; i++)
+        {
+            var value = undefined;
+            coldef = pObject.Columns[i];
+
+            //be sure, that no keycolumn is pushed in the array, when action like insert
+            if(coldef.Key != true || (coldef.Key == true && action == "insert")) spalten.push(this.getColumnCase(coldef.Name));
+            if(coldef.Key != true || (coldef.Key == true && action == "insert")) typen.push( this.DataType[tableName][this.getColumnCase(coldef.Name)] );
+
+            if(value == undefined && coldef.Source != undefined) value = this.InputRecord[coldef.Source];
+            if(value == undefined && coldef.Value != undefined) value = this.resolveSymbol(coldef, coldef.Value, coldef.Eval);
+            if(value == undefined && coldef.Key == true && action == "insert") value = util.getNewUUID();
+
+            //value undefined should not be pushed
+            //only add value if column was pushed
+            if(value != undefined && (coldef.Key != true || (coldef.Key == true && action == "insert"))) werte.push(value);
+
+            // do not update data if any required field is empty
+            if(coldef.Required == true && (value == undefined || value == "")) data_ok = false;
+        }
+
+        if(data_ok == true)
+        {
+            switch(action)
+            {
+                case "insert":
+                    this.insertData(tableName, spalten, typen, werte, alias);
+                    break;
+                case "update":
+                    this.updateData(tableName, spalten, typen, werte, condition, alias);
+                    break;
+            }
+        }
+    }
+    catch(ex)
+    {
+        logging.log(ex);
+        resultUpdate = false;
+    }
+
+    return resultUpdate;
+}
+
+/*
+* import a timestamp string in a specified format into a date field
+*    Values of the mapping line:
+*    String Source req the column index for the current record
+*    String Target req target column name
+*    String Format opt The timestamp format, default is YYYY-MM-DD HH:MI:SS
+*    String Timezone opt The timezone string, default is UTC
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true, if the import of the timestamp was successfull, otherwise false
+*/
+function iTimestamp(pObject)
+{
+    var resultTimestamp = true;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    var fmt = pObject.Format;
+    var tz = pObject.Timezone;
+    if(fmt == undefined || fmt == "") fmt = "yyyy-MM-dd HH:mm:ss";
+    if(tz == undefined || tz == "") tz = "UTC";
+
+    var value = "";
+    if(pObject.Source != undefined) value = this.InputRecord[pObject.Source];
+    if(pObject.Value != undefined) value = this.resolveSymbol(pObject, pObject.Value);
+    try
+    {
+        this.setOutput(pObject, datetime.toLong(value, fmt, tz));
+    }
+    catch(ex)
+    {
+        logging.log(ex);
+        resultTimestamp = false;
+    }
+
+    return resultTimestamp;
+}
+
+
+/*
+* decode an input entry by searching thru a translation list
+*    Values of the mapping line:
+*    String Value -- the input data
+*    String Target -- the target column
+*    String List -- the decode list, format: data;replacement;data;replacement.....
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean} true, if the the decoding was successfull, otherwise false
+*/
+function iDecode(pObject)
+{
+    var resultDecode = true;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    var wert = "";
+    if(pObject.Source != undefined) wert = this.InputRecord[pObject.Source];
+    if(pObject.Value != undefined) wert = this.resolveSymbol(pObject, pObject.Value);
+
+    var list = pObject.List;
+    var map = new Object();
+    if(list != undefined)
+    {
+        // convert decode list into map
+        list = list.split(";");
+
+        //is the list complete?
+        if(list.length % 2 == 0)
+        {
+            for(var i=0; i < list.length; i=i+2)
+            {
+                map[list[i]] = list[i+1];
+            }
+
+            // use map entry to decode
+            if(wert != "") wert = map[wert];
+
+            //if not found, set default to empty
+            if(wert == undefined) wert = "";
+        }
+        else
+        {
+            //list is not correct, so wert = "" and log error message
+            wert = "";
+            this.writeLog(this.LogLevels.Error, "[iDecode] List is not correct!");
+        }
+
+        // write to output buffer
+        this.setOutput(pObject, wert);
+    }
+    else
+    {
+        resultDecode = false;
+    }
+
+    return resultDecode;
+}
+
+
+/*
+* save an input in a globalvar
+*    Values of the mapping line:
+*    String Value -- the input data
+*    String Name -- the name for the globalvar
+*
+* @param {Object} pObject req the mapping line
+*
+* @example [(iGlobalVar {Value: "{3}", Name: "importLogin"} )     -->  $global.importLogin]
+*
+* @return {void}
+*/
+function iGlobalVar(pObject)
+{
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    var value = "";
+    var name = "";
+    if(pObject.Source != undefined) value = this.InputRecord[pObject.Source];
+    if(pObject.Value != undefined) value = this.resolveSymbol(pObject, pObject.Value);
+    if(pObject.Name != undefined) name = pObject.Name;
+    vars.getString("$global." + name, value);
+}
+
+
+
+/*
+* do character set translation.
+* basically works like iMove, but allows to specify a conversion map
+* that will be used to process the input data.
+* conversion map is a map (directionary, associative array, whatever you call it).
+* declare a varaible like theMap = new Array(); theMap("a") = "X"; theMap("b") = "z"; etc. ...
+* and specify this a sthe value for the Parameter "Map"
+*
+* Important! Usage of "Method" parameter value "replaceall" requires ADITO online 3.0.3 or above!
+*
+* Values of the mapping line:
+* String Value -- the input data
+* String Target -- the target column
+* String Map -- the decode map
+* String Method -- which Method to use: "js", "replaceall" (default to "js")]
+*
+* @param {Object} pObject req the mapping line
+*
+* @return {Boolean}
+*/
+function iCharMap(pObject)
+{
+    var resultMap = true;
+
+    //is any DoIf-condition set?
+    if (! this.doIfCheck(pObject))
+        return true;
+
+    var wert = "";
+    if(pObject.Source != undefined) wert = this.InputRecord[pObject.Source];
+    if(pObject.Value != undefined) wert = this.resolveSymbol(pObject, pObject.Value);
+
+    var map = pObject.Map;
+
+    if(map != undefined)
+    {
+        if(pObject.Method == undefined) pObject.Method = "js";  // default to JavaScript
+        this.writeLog(this.LogLevels.Debug, "[iCharMap] Using mapping method '" + pObject.Method + "' for mapping in iCharMap");
+
+        switch(pObject.Method)
+        {
+            case "js" :
+                for (var i in map)
+                {
+                    wert = wert.replace(new RegExp(i, "gi"), map[i]);
+                }
+                break;
+
+            case "replaceall" :
+                wert = text.replaceAll(wert, map);
+                break;
+        }
+
+        // write to output buffer
+        this.setOutput(pObject, wert);
+
+    }
+    else
+    {
+        this.writeLog(this.LogLevels.Warning, "[iCharMap] Map for iCharMap missing or undefined/empty");
+        resultMap = false;
+    }
+
+    return resultMap;
+}
diff --git a/process/ImporterTest_lib/ImporterTest_lib.aod b/process/ImporterTest_lib/ImporterTest_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..e1204321106696757a47000f28e10cc890d73182
--- /dev/null
+++ b/process/ImporterTest_lib/ImporterTest_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>ImporterTest_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/ImporterTest_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/ImporterTest_lib/process.js b/process/ImporterTest_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..342d3997fd4c9de7c26706f028f61cb8f6ac1626
--- /dev/null
+++ b/process/ImporterTest_lib/process.js
@@ -0,0 +1,74 @@
+import("system.question");
+import("system.text");
+import("system.db");
+import("Importer_lib");
+
+function ImporterTest() {
+    this.startImporter = function (pTestCases) {
+        var parse = function (pElement, pPath) {
+            if (pElement.childs == undefined) {
+                return [{ 
+                    id: text.encodeMS(pPath.concat(pElement.name)), 
+                    element: pElement }];
+            }
+            var childs = [];
+            for (let i = 0; i < pElement.childs.length; i++) {
+                childs.push(parse(pElement.childs[i], pPath.concat(pElement.name))[0])
+            }
+            return [{
+                id: text.encodeMS(pPath.concat(pElement.name)),
+                element: {
+                    name: pElement.name,
+                    description: pElement.description,
+                    childs: childs.map(function (val) { return val.id })
+                }
+            }].concat(childs);
+        }.bind(this)
+
+        for (let i = 0 ; i < Object.keys(pTestCases).length; i++)  {
+            var res = parse(pTestCases[Object.keys(pTestCases)[i]], []);
+            if (res.length == 1) {
+                this.startProcess(res[0].element);
+            } else {
+                for (var j = 1; j< res.length; j++) {
+                    var testcase = res[j].element;
+                    this.startProcess(testcase);
+                }
+            }
+        }
+    }
+    
+    this.getBaseImporter = function (pConfig) {
+        var imp = new Importer(pConfig);
+        imp.Log = "CONSOLE";
+        imp.LogLevel = imp.LogLevels.Debug;
+        imp.ImportUser = "IMPORTER_TESTER";
+        imp.Preview = false;
+        imp.Debug = true;
+        imp.LogLevel = imp.LogLevels.Debug;
+        imp.BatchSize = 50;
+        imp.skipEmptyValue = false;
+        if (db.getDatabaseType(pConfig.AliasTo) == db.DBTYPE_MARIADB10) imp.TableCase = imp.Cases.Lower;
+        return imp;
+    }
+    
+    this.startProcess = function (testCase) {
+        if (testCase.fn != undefined)  {   
+            var cbFn = function (pConfig) {
+                return this.getBaseImporter(pConfig)
+            }.bind(this)
+
+            var testResult = testCase.fn.call(testCase, cbFn);
+            if (testResult instanceof Importer)  {
+                testResult = testResult.process();
+                question.showMessage("Successful: " + testCase.name +"\n" + JSON.stringify(testResult, null, " "))
+            } else {
+                question.showMessage("Successful\nResult:\n\n" + testResult)
+            }
+        } else {
+            question.showMessage("No test function defined!", question.WARNING)
+        }
+        return true;
+    }
+}
+
diff --git a/process/Importer_lib/Importer_lib.aod b/process/Importer_lib/Importer_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..0c29a1e97e07715224d80de8a9a3a4f803a5fcf0
--- /dev/null
+++ b/process/Importer_lib/Importer_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>Importer_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/Importer_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/Importer_lib/process.js b/process/Importer_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..a693e85cf7ed62c81e6dfed7f74471cd8b759a70
--- /dev/null
+++ b/process/Importer_lib/process.js
@@ -0,0 +1,1553 @@
+import("system.db");
+import("system.vars");
+import("system.translate");
+import("system.logging");
+import("system.datetime");
+import("system.fileIO");
+import("system.swing");
+import("system.util");
+import("system.text");
+import("ErrorHandling_lib");
+import("ImporterCustomMappingFunctions_lib");
+import("ImporterMappingFunctions_lib");
+
+/////////////////////////////////////////////////////////////////////
+/// importer module constructor function                        ///
+/// DO NOT TOUCH - use lib_importerCustomMappingFunctions       ///
+///////////////////////////////////////////////////////////////////
+/*
+* the importer class, main object
+* @param {String []} pConfig req ( Name, FunktionsArt, Details )
+*
+* @version 2.0
+*
+* @return {void}
+*/
+function Importer(pConfig)
+{
+    var batchNum = 0;
+    var batchStart = 0;
+    var batchList;
+    var mappingtimer = [];
+    var exectimer = {
+        insertData: 0,
+        updateData: 0,
+        outbuffer: 0,
+        logging: 0,
+        getdata: 0,
+        updateDecisionTime: 0,
+        insertUpdateActions: 0,
+        dbDataModifiedTime: 0,
+        dbInsertTime: 0,
+        dbUpdateTime: 0,
+        dataLoopTime: 0,
+        mapPerRecordTime: 0,
+        outputPerRecordTime: 0
+    };
+    var startTime = datetime.date();//this will be overwriten when starting the importing-process
+    var stopTime;
+    var logBuffer = [];
+    this.insertArray = [];
+    this.updateArray = [];
+
+    this.LogLevels = {
+        Minimal: 0,
+        Error : 1,
+        Warning : 2,
+        Info : 3,
+        Debug : 4,
+        Preview : 5
+    };
+
+    this.Cases = {
+        Lower: 0,
+        Upper: 1,
+        Unchanged: 2
+    };
+
+    this.Process = "";
+    this.Config = pConfig;
+    this.BatchSize = 50;
+    this.MaxRows = 0;
+    this.Preview = false;
+    this.Debug = false;
+    this.Log = "CONSOLE";
+    this.fileInputCharset = "UTF8";
+    this.LogLevel = this.LogLevels.Warning;
+    this.enableLogBuffer = false;
+    this.InputRecord = new Array();
+    this.OutputRecord = new Object();
+    this.ImportUser = "IMPORTER";
+    this.FuncBuffer = new Object();
+    this.CompleteUpdate = true;
+    this.ErrorLog = "";
+    this.DataType = null;
+    this.KeyColumn = new Object();  // contains key info as in KeyColumn["tbl.col"] = "I" | "U" | "I+U"
+    this.UseAOType = true; //default true, so that AOType will be uses (for older systems)
+    this.UseUUID = true; //default false, so that db.getNewID() instead of util.getNewUUID() would be uses
+    this.TableCase = this.Cases.Upper; //default is uppercase
+    this.ColumnCase = this.Cases.Upper; //default is uppercase
+    this.skipEmptyValue = true;
+
+    this.AttributeCache = undefined;
+    this.useAttributeCache = false;
+    this.attributeCacheLoadedSuccessfully = false;
+    this.loadAttributeCache = function(){
+        this.writeLog(this.LogLevels.Info, "[LoadAttributeCache]loading Attibute cache");
+        try
+        {
+            this.AttributeCache = {};
+            let TMP = 0;
+            var cD = {
+                 attrNameL1: TMP
+                ,attrNameL2: ++TMP
+                ,attrNameL3: ++TMP
+                ,attrIdL1: ++TMP
+                ,attrIdL2: ++TMP
+                ,attrIdL3: ++TMP
+                ,attrObjectL1: ++TMP
+                ,attrObjectL2: ++TMP
+                ,attrCompL1: ++TMP
+                ,attrCompL2: ++TMP
+                ,attrSqlIdFieldL1: ++TMP
+                ,attrSqlDisplayFieldL1: ++TMP
+                ,attrSqlFromFieldL1: ++TMP
+                ,attrSqlWhereFieldL1: ++TMP
+                ,attrSqlIdFieldL2: ++TMP
+                ,attrSqlDisplayFieldL2: ++TMP
+                ,attrSqlFromFieldL2: ++TMP
+                ,attrSqlWhereFieldL2: ++TMP
+            };
+
+            var sqlStr = "select "
+            + this.getColumnCase( "A.ATTRNAME, B.ATTRNAME, C.ATTRNAME "
+                + ",A.ATTRID, B.ATTRID, C.ATTRID "
+                + ",AO_A.ATTROBJECT, AO_B.ATTROBJECT "
+                + ",A.ATTRCOMPONENT, B.ATTRCOMPONENT "
+                + ",A.SQLIDCOLUMN, A.SQLSHOWCOLUMN, A.SQLFROMDEF, A.SQLWHERE "
+                + ",B.SQLIDCOLUMN, B.SQLSHOWCOLUMN, B.SQLFROMDEF, B.SQLWHERE "
+                + "")
+            + " from " + this.getTableCase("ATTR A")
+            + " left join " + this.getTableCase("ATTR B") + " on " + this.getColumnCase("A.ATTRID") + " = " + this.getColumnCase("B.ATTR_ID")
+            + " left join " + this.getTableCase("ATTR C") + " on " + this.getColumnCase("B.ATTRID") + " = " + this.getColumnCase("C.ATTR_ID")
+            + " left join " + this.getTableCase("ATTROBJECT AO_A") + " on " + this.getColumnCase("AO_A.ATTR_ID") + " = " + this.getColumnCase("A.ATTRID")
+            + " left join " + this.getTableCase("ATTROBJECT AO_B") + " on " + this.getColumnCase("AO_B.ATTR_ID") + " = " + this.getColumnCase("B.ATTRID")
+            + " where " + this.getColumnCase("A.ATTR_ID") + " is null "//if it has an attr_id it's level 2 an with that ATTR B (or ATTR C)
+            + "";
+            this.writeLog(this.LogLevels.Info, "[LoadAttributeCache]executed select is: " + sqlStr);
+            var data = db.table(sqlStr, this.Config.AliasTo);
+            var attributeTree = {};
+            for(var i = 0, j = data.length; i < j; i++)
+            {
+                let row = data[i];
+                if (attributeTree[row[cD.attrNameL1]] == undefined)
+                    attributeTree[row[cD.attrNameL1]] = {
+                         id: row[cD.attrIdL1]
+                        ,component: row[cD.attrCompL1]
+                        ,usedInFrames: {}
+                        ,children: {}
+                    };
+
+                if (row[cD.attrObjectL1] != "")
+                    attributeTree[row[cD.attrNameL1]].usedInFrames[row[cD.attrObjectL1]] = true;
+                else
+                    this.writeLog(this.LogLevels.Warning, '[loadAttributeCache]attribute "' + row[cD.attrNameL1] + '" has no ATTROBJECT');
+                //selectCombo, init for hybrid-cache (loaded once, when attribute is really needed):
+                if (row[cD.attrCompL1] == "7"
+                 && attributeTree[row[cD.attrNameL1]].loadedSelectCombo == undefined)
+                {
+                    attributeTree[row[cD.attrNameL1]].loadedSelectCombo = false;
+                    attributeTree[row[cD.attrNameL1]].selectComboSql = "select " + row[cD.attrSqlIdFieldL1]
+                        + " ," + row[cD.attrSqlDisplayFieldL1]
+                        + " from " + row[cD.attrSqlFromFieldL1]
+                        + (row[cD.attrSqlWhereFieldL1] != "" ? " where " : "") + row[cD.attrSqlWhereFieldL1];
+                }
+
+
+                if (row[cD.attrNameL2] != "")
+                {
+                    if (attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]] == undefined)
+                        attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]] = {
+                             id: row[cD.attrIdL2]
+                            ,component: row[cD.attrCompL2]
+                            ,usedInFrames: {}
+                            ,children: {}
+                        };
+
+                    if (row[cD.attrObjectL2] != "")
+                        attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]].usedInFrames[row[cD.attrObjectL2]] = true;
+                    else
+                        this.writeLog(this.LogLevels.Warning, '[loadAttributeCache]attribute "' + row[cD.attrNameL1] + "|" + row[cD.attrNameL2] + '" has no ATTROBJECT');
+
+                    //selectCombo, init for hybrid-cache:
+                    if (row[cD.attrCompL2] == "7"
+                        && attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]].loadedSelectCombo == undefined)
+                    {
+                        attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]].loadedSelectCombo = false;
+                        attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]].selectComboSql = "select " + row[cD.attrSqlIdFieldL2]
+                        + " ," + row[cD.attrSqlDisplayFieldL2]
+                        + " from " + row[cD.attrSqlFromFieldL2]
+                        + (row[cD.attrSqlWhereFieldL2] != "" ? " where " : "") + row[cD.attrSqlWhereFieldL2];
+                    }
+
+                    //this nomally happens only if component is combo
+                    if (row[cD.attrNameL3] != "")
+                    {
+                        if (attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]].children[row[cD.attrNameL3]] == undefined)
+                            attributeTree[row[cD.attrNameL1]].children[row[cD.attrNameL2]].children[row[cD.attrNameL3]] = {
+                                 id: row[cD.attrIdL3]
+                            };
+                    }
+                }
+//                        //jetzt muss geprüft werden ob sich die ATTRIDs unterscheiden, wenn ja bedeutet dass, das ein Attributname mehrfach vergeben wurde
+//                        //dann darf keiner der Daten in den Cache geladen werden, dass würde nur zu fehlerhaften daten führen
+//                        var existingAttrid = this.AttributeCache[ attrname ].ATTRID;
+//                        if( existingAttrid != attrid )
+//                        {
+//                            this.AttributeCache[ attrname ] = null; //cache sicherheitshalber erst freigeben
+//                            this.AttributeCache[ attrname ] = undefined;
+//                            this.writeLog(this.LogLevels.Error, "[LoadAttributeCache] Multiple Attributes were found for attribute: '" + attrname + "'."
+//                                + "\r\nNo Attribute with attrname '" + attrname + "' will be loaded into the cache. ");
+//                        }
+            }
+            this.AttributeCache = attributeTree;
+            this.attributeCacheLoadedSuccessfully = true;
+        }
+        catch(ex)
+        {
+            this.attributeCacheLoadedSuccessfully = false;
+            this.writeLog(this.LogLevels.Error, "[LoadAttributeCache]Error while loading Attributes:\r\n" + logging.toLogString(ex) );
+        }
+        if( this.attributeCacheLoadedSuccessfully )
+            this.writeLog(this.LogLevels.Info, "[LoadAttributeCache]Loaded Attibute cache successfully");
+        else
+            this.writeLog(this.LogLevels.Info, "[LoadAttributeCache]Failed loading Attibute cache");
+    }
+
+    this.recordCounts = {//is initialized with numbers in the this.process-function
+         total: null
+        ,skip: null
+        ,update: null
+        ,insert: null
+        ,unchanged: null
+    };
+    Object.defineProperty(this.recordCounts, 'unchanged', {
+        //"this" is here the passed object
+         get: function (){ return (this.total - this.insert - this.update - this.skip)}
+        ,set: function (){throw new Error("importers recordCounts cannot be set; it is read-only")}
+    });
+
+    this.process = function()
+    {
+        this.mappingLength = this.Config.Mapping.length;
+        var i;
+        var t;
+        var pkid;
+        var c;
+        var cond;
+        var s;
+
+        var pImporter = this;
+
+        this.recordCounts.total = 0;
+        this.recordCounts.skip = 0;
+        this.recordCounts.insert = 0;
+        this.recordCounts.update = 0;
+        
+        // Infoobject for Callbackfunction
+        var recordStack = {
+            sourceDataSet: [],
+            insertUpdate: "",
+            insertData: {
+                successful: true, 
+                array: []
+            },
+            updateData: {
+                successful: true, 
+                array: []
+            },
+            exception:  [],
+            pId: ""
+        };
+
+        var daten;
+        var skip;
+        var headercount = 0;
+        var batchlist = [];
+        var idcolumn;
+        var importtype = "S";        // F,S or M for "file", "single" or "multi" batch, default to single batch
+        batchStart = 0;              // current batch start index
+        var logstring = "";          // contains the log file, if not writing to server log
+        var requiredTargets = new Object();   // stores the required target columns
+        // prepare logging stuff
+        if(this.Log != "" && this.Log != undefined && this.Log.split(".")[0] == "$global") vars.set(this.Log, "");
+        if(this.Preview == true) this.LogLevel = this.LogLevels.Preview;
+
+        if (this.enableLogBuffer)
+            logBuffer = [];
+        else
+            logBuffer = ["logBuffer is not enabled; you cannot use getLogMessages(...)"];
+        startTime = datetime.date();
+        s = datetime.toDate(startTime, translate.text("yyyy-MM-dd HH:mm:ss"), "UTC");
+        this.writeLog(this.LogLevels.Minimal, "Started at " + s + " (UTC)");
+        logging.log("[IMPORT] Start at " + s + " UTC");
+        if(this.Preview) this.writeLog(this.LogLevels.Info, "======== import running in preview mode ========");
+        if (this.useAttributeCache)
+            this.loadAttributeCache();
+        this.writeLog(this.LogLevels.Debug, "Building mapping tables.");
+        // get all column type from all tables of the target alias
+        this.DataType = this.getDataTypes(this.Config.AliasTo);
+        // build an object with the data types for each column and
+        // check for key fields and collect them in parmObject.KeyRecord
+        for(i=0; i < this.mappingLength; i++)
+        {
+            mappingtimer[i] = 0;  // init mapping timer
+
+            var target = this.Config.Mapping[i][1]["Target"];
+            if(target != undefined && target.substr(0,4).toLowerCase() != "var.")  // exclude var storage
+            {
+                // collect a required target, if we find one (these columns must not be empty)
+                requiredTargets[target] = (this.Config.Mapping[i][1]["Required"] == true);
+                // collect all key columns in an object array
+                // KeyColumn[table ][column] = action1;action2...
+                var coldata = target.split(".");
+
+                if(this.Config.Mapping[i][1]["Key"] != undefined)  //2009-05-13  TR  changed, because on insertcommand "insert" or "update" there can be no Action
+                {
+                    if(this.KeyColumn[ this.getTableCase(coldata[0]) ] == undefined) this.KeyColumn[ this.getTableCase(coldata[0]) ] = new Object();
+                    if(this.KeyColumn[ this.getTableCase(coldata[0]) ][ this.getColumnCase(coldata[1]) ] == undefined) this.KeyColumn[ this.getTableCase(coldata[0]) ][ this.getColumnCase(coldata[1]) ] = "key";
+
+                    this.setDefaultAction(this.Config.Mapping[i][1]);
+
+                    this.KeyColumn[ this.getTableCase(coldata[0]) ][ this.getColumnCase(coldata[1]) ] = this.KeyColumn[ this.getTableCase(coldata[0]) ][ this.getColumnCase(coldata[1]) ] + ";" + this.Config.Mapping[i][1]["Action"];
+                }
+            }
+        }
+
+        batchNum = 0;
+        headercount = this.Config.HeaderLines;
+        if(headercount == undefined) headercount = 0;
+        this.writeLog(this.LogLevels.Warning, "Beginning data import.");
+        // main loop
+        while(daten = this.getNextBatch(this.Config), daten != null )
+        {
+            var dataLoopTimeStart = datetime.date();
+            this.writeLog(this.LogLevels.Info, "Processing batch #" + batchNum);
+
+            // import each row of the current batch
+            for(var bi=0; bi < daten.length; bi++)
+            {
+                recordStack.exception ="";
+                recordStack.sourceDataSet = daten[bi];
+                recordStack.insertData  = {
+                    successful: true, 
+                    array: []
+                }
+                recordStack.updateData  = {
+                    successful: true, 
+                    array: []
+                }
+
+                // skip empty data rows
+                if(daten[bi].length == 1 && daten[bi][0] == "")
+                {
+                    if(this.Debug == true) {
+                        this.writeLog(this.LogLevels.Debug, "Skipping empty row " + bi);
+                    }
+                    continue;
+                }
+
+                this.recordCounts.total++;
+                skip = false;
+
+                // skip header rows (usually file import only)
+                if(bi < headercount)
+                {
+                    if(this.Preview == true && this.Debug == true)
+                    {
+                        this.writeLog(this.LogLevels.Debug, "Skipping header row " + bi);
+                    }
+                    continue;
+                }
+                if (this.Debug)
+                    this.writeLog(this.LogLevels.Debug, "Row " + bi);
+
+                this.InputRecord = daten[bi];       // assign input fields for this record
+                this.OutputRecord = new Object();   // clear output fields for this record
+
+                var mapRecordMapTimeStart = datetime.date();
+                // call mapping functions
+                for(i=0, ml = this.mappingLength; i < ml; i++)
+                {
+                    try
+                    {
+                        var fname = this.Config.Mapping[i][0].name;//name is inherited function-property
+
+                        if (this.Debug)
+                            this.writeLog(this.LogLevels.Debug, "Calling mapping function " + fname);
+                        // call mapping function and time it
+                        t = datetime.date();
+                        var mapresult = this.Config.Mapping[i][0].call(this, this.Config.Mapping[i][1]);
+                        t = datetime.date() - t;
+                        mappingtimer[i] += t;
+                        // if the mapping did not succeed, log function and ID value
+                        if(mapresult == false)
+                        {
+                            this.writeLog(this.LogLevels.Error, "Mapping function " + fname + " failed for row " + this.recordCounts.total);
+                            recordStack.exception = "Fehler Zeile: " + this.recordCounts.total + " - Info:  Mapping function " + fname + " failed for row " + this.recordCounts.total + " Column: " + this.Config.Mapping[i][1]["Target"]; 
+                            skip = true;
+                        }
+                    }
+                    catch(ex)
+                    {
+                        logging.log(ex["rhinoException"] != undefined ? ex["rhinoException"] : ex)
+                        this.writeLog(this.LogLevels.Error, "Exception in mapping function [" + fname + "] for input row " + this.recordCounts.total+ " - " + this.Config.Mapping[i][1]["Target"]);                       
+                        recordStack.exception = errorHandling.getClearMessage(ex)+  " -  Column: " + this.Config.Mapping[i][1]["Target"];
+                        skip = true;
+
+                    }
+                }
+                exectimer.mapPerRecordTime += datetime.date() - mapRecordMapTimeStart;
+
+
+                if(skip == false)  // do we continue with this record?
+                {
+                    // if a debug callback function has been defined, call it
+                    if(this.DebugCallback != null && typeof(this.DebugCallback) == "function")
+                    {
+                        this.DebugCallback(this.OutputRecord);
+                    }
+
+
+                    var tt = datetime.date();
+
+                    var outdata = new Object();
+
+                    for(var tbl in this.OutputRecord)  // loop thru all output tables
+                    {
+                        for(var col in this.OutputRecord[ tbl ])  // loop thru all output columns
+                        {
+                            if(tbl.toLowerCase() != "var")   // exclude var storage
+                            {
+                                for(var action in this.OutputRecord[tbl][col])
+                                {
+                                    if(outdata[tbl] == undefined) outdata[tbl] = "";
+                                    outdata[tbl] = outdata[tbl] + ";" + action;
+
+                                    // check for required data mappings and set skip again, we check this later
+                                    skip = (requiredTargets[tbl + "." + col] == true && (this.OutputRecord[tbl][col][action] == undefined || this.OutputRecord[tbl][col][action] == ""));
+                                }
+                            }
+                        }
+                    }
+
+                    tt = datetime.date() - tt;
+                    exectimer["outbuffer"] += tt;
+
+                    var outputRecordTimeStart = datetime.date();
+                    // loop thru all distinct tables, maybe we have more than one record to write
+                    for(t in this.OutputRecord)
+                    {
+                        var spalten = [];
+                        var typen = [];
+                        var werte = [];
+
+                        // we do insert-for-new and update-for-existing
+                        if(skip == false && this.Config.ImportCommand == "insert+update")
+                        {
+                            var insertUpdateStart = datetime.date();
+                            pkid = "0";  // assume we do not find an existing record
+
+                            // if no key values have been specified, there is no need to check
+                            // so we do an insert
+                            if(this.KeyColumn[t] != undefined )
+                            {
+                                // check for existing data row based on key values
+                                cond = this.generateKeyCondition(t);
+                                var sql = "select count(*) from " + t + " where " + cond;
+                                this.writeLog(this.LogLevels.Debug, "Insert/Update decision for table " + t + " based on: " + cond);
+                                pkid = db.cell(sql, this.Config.AliasTo);
+                            }
+                            exectimer["updateDecisionTime"] += (datetime.date() - insertUpdateStart);
+
+                            if(t.toLowerCase() != "var")
+                            {
+                                if(this.DataType[t] == undefined) this.writeLog(this.LogLevels.Error, "Table " + t + " not exist in database");
+                                else
+                                {
+                                    for(c in this.OutputRecord[t])
+                                    {
+                                        if(this.OutputRecord[t][c]["I+U"] != undefined && (this.OutputRecord[t][c]["I+U"] != "" || !this.skipEmptyValue) && this.OutputRecord[t][c]["I+U"] != null)
+                                        {
+                                            if(this.DataType[t][c] != undefined)
+                                            {
+                                                spalten.push(c);
+                                                typen.push(this.DataType[t][c]);
+                                                werte.push(this.OutputRecord[t][c]["I+U"]);
+                                            }
+                                            else
+                                                this.writeLog(this.LogLevels.Error, "Column " + c + " not exist in table " + t);
+                                        }
+                                    }
+                                }
+                            }
+                            if(pkid != "0")  // exists
+                            {
+                                if(t.toLowerCase() != "var")
+                                {
+                                    if(this.DataType[t] == undefined) this.writeLog(this.LogLevels.Error, "Table " + t + " not exist in database");
+                                    else
+                                    {
+                                        for(c in this.OutputRecord[t])
+                                        {
+                                            if(this.OutputRecord[t][c]["U"] != undefined && (this.OutputRecord[t][c]["U"] != "" || !this.skipEmptyValue) && this.OutputRecord[t][c]["U"] != null
+                                                && this.OutputRecord[t][c]["I+U"] == undefined)
+                                                {
+                                                if(this.DataType[t][c] != undefined)
+                                                {
+                                                    spalten.push(c);
+                                                    typen.push(this.DataType[t][c]);
+                                                    werte.push(this.OutputRecord[t][c]["U"]);
+                                                }
+                                                else
+                                                    this.writeLog(this.LogLevels.Error, "Column " + c + " not exist in table " + t);
+                                            }
+                                        }
+                                    }
+                                }
+
+                                if(!this.updateData(t, spalten, typen, werte, cond, this.Config.AliasTo)) skip = true;
+                            }
+                            else
+                            {
+                                if(t.toLowerCase() != "var")
+                                {
+                                    if(this.DataType[t] == undefined) this.writeLog(this.LogLevels.Error, "Table " + t + " not exist in database");
+                                    else
+                                    {
+                                        for(c in this.OutputRecord[t])
+                                        {
+                                            if(this.OutputRecord[t][c]["I"] != undefined && this.OutputRecord[t][c]["I"] != "" && this.OutputRecord[t][c]["I"] != null
+                                                && this.OutputRecord[t][c]["I+U"] == undefined)
+                                                {
+                                                if(this.DataType[t][c] != undefined)
+                                                {
+                                                    spalten.push(c);
+                                                    typen.push(this.DataType[t][c]);
+                                                    werte.push(this.OutputRecord[t][c]["I"]);
+                                                }
+                                                else
+                                                    this.writeLog(this.LogLevels.Error, "Column " + c + " not exist in table " + t);
+                                            }
+                                        }
+                                    }
+                                }
+
+                                if(!this.insertData(t, spalten, typen, werte, this.Config.AliasTo)) skip = true;
+                            }
+                            exectimer["insertUpdateActions"] += (datetime.date() - insertUpdateStart);
+                        }
+
+                        // we do an insert
+                        if(skip == false && this.Config.ImportCommand == "insert")
+                        {
+                            if(t.toLowerCase() != "var")
+                            {
+                                if(this.DataType[t] == undefined) this.writeLog(this.LogLevels.Error, "Table " + t + " not exist in database");
+                                else
+                                {
+                                    for(c in this.OutputRecord[t])
+                                    {
+                                        if(this.DataType[t][c] != undefined)
+                                        {
+                                            spalten.push(c);
+                                            typen.push(this.DataType[t][c]);
+                                            werte.push(this.OutputRecord[t][c]["I"]);
+                                        }
+                                        else
+                                            this.writeLog(this.LogLevels.Error, "Column " + c + " not exist in table " + t);
+                                    }
+                                }
+                            }
+                            if(!this.insertData(t, spalten, typen, werte, this.Config.AliasTo)) skip = true;
+                        }
+
+                        // we do an update?
+                        if(skip == false && this.Config.ImportCommand == "update")
+                        {
+                            if(t.toLowerCase() != "var")
+                            {
+                                if(this.DataType[t] == undefined) this.writeLog(this.LogLevels.Error, "Table " + t + " not exist in database");
+                                else
+                                {
+                                    for(c in this.OutputRecord[t])
+                                    {
+                                        if(this.DataType[t][c] != undefined)
+                                        {
+                                            spalten.push(c);
+                                            typen.push(this.DataType[t][c]);
+                                            werte.push(this.OutputRecord[t][c]["U"]);
+                                        }
+                                        else
+                                            this.writeLog(this.LogLevels.Error, "Column " + c + " not exist in table " + t);
+                                    }
+                                }
+                            }
+
+                            // create condition by looking for key fields
+                            cond = this.generateKeyCondition(t);
+                            if(!this.updateData(t, spalten, typen, werte, cond, this.Config.AliasTo)) skip = true;
+                        }
+                    }
+                    exectimer.outputPerRecordTime += datetime.date() - outputRecordTimeStart;
+                }
+
+                // this is *not* the else-branch for the if above, because we may change the value for "skip"
+                // even it was false when comparing in the "if" above. so we check this here in a separate
+                // if to get all occurrences of skipped import rows.
+                if(skip == true) this.recordCounts.skip++;
+                //Now insert/update all Columns
+                if(!skip)
+                {
+                    var totalDBexecTime = datetime.date();
+                    let insertSuccessfull = true;
+                    let updateSuccessfull = true;
+                    try
+                    {
+                        if(this.insertArray.length > 0)
+                        {
+                            insertSuccessfull = false;
+                            var startInsert = datetime.date();
+                            db.inserts(this.insertArray, this.Config.AliasTo);
+                            exectimer.dbInsertTime += datetime.date() - startInsert;
+                            this.recordCounts.insert++;
+                            insertSuccessfull = true;
+                             // insert
+                            recordStack.insertUpdate = "insert";
+                            recordStack.insertData  = {
+                                successful: true, 
+                                array: this.insertArray
+                            };
+                        }
+                        if(this.updateArray.length > 0)
+                        {
+                            updateSuccessfull = false;
+                            var startUpdate = datetime.date();
+                            db.updates(this.updateArray, this.Config.AliasTo);
+                            exectimer.dbUpdateTime += datetime.date() - startUpdate;
+                            this.recordCounts.update++;
+                            updateSuccessfull = true;
+                            // update
+                            recordStack.insertUpdate = "update";
+                            recordStack.updateData  = {
+                                successful: true, 
+                                array: this.updateArray
+                            };
+                        }
+                    }
+                    catch(ex)
+                    {
+                        this.writeLog(this.LogLevels.Error, "Error at " + (insertSuccessfull ? "" : "Insert") + (updateSuccessfull ? "": "Update") + ":" + logging.toLogString(ex));
+                        logging.log(ex["rhinoException"] != undefined ? ex["rhinoException"] : ex)
+                        this.recordCounts.skip++;
+                        recordStack.exception = errorHandling.getClearMessage(ex);
+                        
+                        if(this.insertArray.length > 0 && !insertSuccessfull) {
+                            this.writeLog(this.LogLevels.Info, "Insert array: " + JSON.stringify(this.insertArray, null, " "));
+                            recordStack.insertData  = {
+                                successful: false, 
+                                array: this.updateArray
+                            };
+                        }
+                        if(this.updateArray.length > 0 && !updateSuccessfull) {
+                            this.writeLog(this.LogLevels.Info, "Update array: " + JSON.stringify(this.updateArray, null, " "));
+                            recordStack.updateData  = {
+                                successful: false, 
+                                array: this.updateArray
+                            };
+                        }
+                    }
+
+                    exectimer.dbDataModifiedTime += datetime.date() - totalDBexecTime;
+
+                    //Clear Arrays
+                    this.insertArray = [];
+                    this.updateArray = [];
+                }
+                // if a progress callback function has been defined, call it
+                if(this.ProgressCallback != null && typeof(this.ProgressCallback) == "function")
+                {
+                    this.ProgressCallback(skip, bi, recordStack, this.Config.AliasFrom, this.Config.Callback.TableFrom, this.Config.Callback.IDColumn, this.Config.Callback.IDColumnIndex);
+                }
+
+                if(this.MaxRows > 0 && this.recordCounts.total >= this.MaxRows)
+                {
+                    break;
+                }
+            }  // end for (row of current batch)
+            if(this.MaxRows > 0 && this.recordCounts.total >= this.MaxRows)
+            {
+                break;
+            }
+            exectimer.dataLoopTime += datetime.date() - dataLoopTimeStart;
+        }
+
+        this.showCounts();
+        stopTime = datetime.date();
+        this.showTimings();
+        s = datetime.toDate(stopTime, translate.text("yyyy-MM-dd HH:mm:ss"), "UTC");
+        this.writeLog(this.LogLevels.Minimal, "End at " + s + " UTC");
+        logging.log("[IMPORT] End at " + s + " UTC");
+
+        return {
+             totalCount: this.recordCounts.total
+            ,skipCount: this.recordCounts.skip
+            ,insertCount: this.recordCounts.insert
+            ,updateCount: this.recordCounts.update
+            ,unchangedCount: this.recordCounts.unchanged
+        };
+    }
+    //	show timing information
+    this.showTimings = function(pPrefix)
+    {
+        if (pPrefix == undefined)
+            pPrefix = "";
+
+        var mappingtotal = 0;
+        for(var i=0; i < this.Config.Mapping.length; i++)
+        {
+            mappingtotal += mappingtimer[i];
+        }
+        if (stopTime == undefined)
+            this.writeLog(this.LogLevels.Warning, pPrefix + "Total run time till now: " + ((datetime.date() - startTime) / 1000) + " seconds.");
+        else
+            this.writeLog(this.LogLevels.Warning, pPrefix + "Total run time: " + ((stopTime - startTime) / 1000) + " seconds.");
+
+        for(var k in exectimer)
+        {
+            this.writeLog(this.LogLevels.Info, pPrefix + "Total " + k + " time: " + (exectimer[k] == "0" ? "<1" : exectimer[k]) + " ms ");
+        }
+
+        this.writeLog(this.LogLevels.Warning, pPrefix + "Total map time: " + (mappingtotal / 1000) + " seconds.");
+
+        for(i=0; i < this.Config.Mapping.length; i++)
+        {
+            var fname =  this.Config.Mapping[i][0].name;//name is inherited function-property
+            this.writeLog(this.LogLevels.Info, pPrefix + "Mapping #" + i + " " + fname + ": " + (mappingtimer[i] == "0" ? "<1" : mappingtimer[i]) + " ms ");
+        }
+    }
+
+    this.showCounts = function(pPrefix)
+    {
+        if (pPrefix == undefined)
+            pPrefix = "";
+
+        this.writeLog(this.LogLevels.Minimal, pPrefix + "Total: " + this.recordCounts.total
+                    + ", Skipped: " + this.recordCounts.skip
+                    + ", Inserted: " + this.recordCounts.insert
+                    + ", Updated: " + this.recordCounts.update
+                    + ", Unchanged: " +  this.recordCounts.unchanged );
+    }
+
+    //		this function yields the next batch of data to import.
+    this.getNextBatch = function(pConfig){
+        var tt = datetime.date();  // exec timer
+        var resultBatch;
+        var bs;
+        var daten;
+
+        this.writeLog(this.LogLevels.Debug, "Executing getNextBatch()");
+        batchNum++;
+
+        var impmode;
+
+        if(pConfig.DataFunction != undefined)
+            impmode = "array";
+        else if(pConfig.DataFile != undefined)
+        {
+            if(pConfig.DataFile.substr(pConfig.DataFile.length-3, pConfig.DataFile.length) == 'xml') //is the file an xml file? then use xml-mode
+                impmode = "xml";
+            else
+                impmode = "file";
+        }
+        else if(pConfig.XMLObject != undefined)
+            impmode = "xml";
+        else
+            impmode = "table";
+
+
+        switch(impmode)
+        {
+            case "xml":
+                if(batchNum > 1) return null;	// we read files in one sweep
+
+                if(this.Debug == true) this.writeLog("Getting input xml " + pConfig.DataFile, false, 3);
+                // file import, which is always a single batch operation
+                importtype = "F";
+                var strXML;
+
+                // get xml-string directly or load from file?
+                if(pConfig.DataFile != "")
+                    strXML =	this.getFileContent(pConfig.DataFile, util.DATA_TEXT); //load from file
+                else
+                    strXML = pConfig.XMLObject; //get xml-string
+
+                if(strXML != "" && strXML != undefined)
+                {
+                    var xmlData = new XML(strXML);
+                    resultBatch = [];
+                    var xmlArr = [];
+
+                    //get every row-element
+                    for each(xmlItem in xmlData.data.row)
+                    {
+                        xmlArr = [];
+
+                        for each(xmlItem2 in xmlItem.column)
+                            xmlArr.push(xmlItem2);
+
+                        resultBatch.push(xmlArr);
+                    }
+                }
+                else
+                    this.writeLog("XML-Data is empty or undefined!", false, 0);
+
+                return resultBatch;
+                break;
+
+            case "file":
+                if(batchNum > 1) return null;	// we read files in one sweep
+                if(this.Debug == true) this.writeLog("Reading input file " + pConfig.DataFile, false, 3);
+                // file import, which is always a single batch operation
+                importtype = "F";
+
+                // otherwise, load the file
+                var filestring = this.getFileContent(pConfig.DataFile, util.DATA_TEXT);
+                var rs = pConfig.RowSeparator;
+                if(rs == undefined) rs = "\n";
+                var cs = pConfig.ColumnSeparator;
+                if(cs == undefined) cs = ",";
+                var sd = pConfig.StringDelimiter;
+                if(sd == undefined) sd = "";
+
+                resultBatch = text.parseCSV(filestring, rs, cs, sd);
+                tt = datetime.date() - tt;
+                exectimer["getdata"] += tt;
+                return resultBatch;
+                break;
+
+            case "array":
+                bs = this.BatchSize;
+                if(bs == undefined) bs = 0;
+
+                resultBatch = this.Config.DataFunction.call(this, batchNum, bs);
+                tt = datetime.date() - tt;
+                exectimer["getdata"] += tt;
+                return resultBatch;
+                break;
+
+            case "table":
+                // table import
+                bs = this.BatchSize;
+                if(bs == undefined)
+                    bs = 0;
+
+                //bs specified: read data in blocks to save memory
+                if(bs > 0 )
+                {
+                    if(this.Config.IdQuery == undefined || this.Config.IdColumn == undefined)
+                    {
+                        //new method for batch-processsing (paging)
+                        daten = db.tablePage(this.Config.DataQuery, this.Config.AliasFrom, batchStart, bs);
+                        batchStart += bs;
+
+                        //this happens when all-records % pBlockSize == 0
+                        //we do not want to call the callback-fn
+                        if (daten.length == 0)
+                            daten = null;
+                    }
+                    else
+                    {
+                        if (this.idList == undefined)
+                        {
+                            this.writeLog(this.LogLevels.Warning, "using \"IdQuery\" and \"IdColumn\" is an obsolte method for getting sql-data in blocks");
+                            this.idList = this.createIDList();
+                        }
+
+                        //legacy method for batch-processsing
+                        if(batchStart < this.idList.length)  // as long as we got something to do
+                        {
+                            batchList = this.idList.slice(batchStart, batchStart + bs);
+                            batchStart += bs;
+
+                            // get data of the next batch
+                            var sql = this.Config.DataQuery.replace(/\$\$id/i, idcolumn + " in ('" + batchList.join("','") + "')" );
+                            daten = db.table(sql, this.Config.AliasFrom);
+                        }
+                        else
+                        {
+                            this.idList = undefined;
+                            daten = null;
+                        }
+                    }
+                }
+                else
+                {
+                    // return complete result set
+                    if(batchNum > 1)
+                        daten = null;
+                    else
+                        daten = db.table(this.Config.DataQuery, this.Config.AliasFrom);
+                }
+                tt = datetime.date() - tt;
+                exectimer["getdata"] += tt;
+                return daten;
+                break;
+        }
+    }
+    this.createIDList = function()
+    {
+        var tt = datetime.date();   // exectimer
+        var resIDList;
+
+        if(pConfig.IdQuery != undefined && pConfig.DataQuery != undefined && pConfig.IdColumn != undefined)
+        {
+            // set the id column for the batch retrieval
+            idcolumn = this.Config.IdColumn;
+
+            // set multi-batch import
+            importtype = "M";
+
+            // get the list of primary keys
+            resIDList = db.array(db.COLUMN, pConfig.IdQuery, pConfig.AliasFrom);
+            tt = datetime.date() - tt;
+            exectimer["getdata"] += tt;
+        }
+        return resIDList;
+    }
+
+    //	@param String pMessage -- die Meldung, die geloggt werden soll
+    //	@param String pLevel
+    this.writeLog = function(pLevel, pMessage)
+    {
+        var tt = datetime.date();
+
+        // if logging has been "oursourced", just call the callback function and do nothing
+        if(this.LogCallback != null && typeof(this.LogCallback) == "function")
+        {
+            this.LogCallback(pLevel, pMessage);
+        }
+        else if(pLevel <= this.LogLevel) 		// shall we output this message?
+        {
+            var logprefix = "[IMPORTER]@" + datetime.toDate(datetime.date(), translate.text("yyyy-MM-dd HH:mm:ss"), "UTC") + " UTC: ";
+            var logline = logprefix + pMessage;
+            if (this.enableLogBuffer)
+                logBuffer.push(logline);
+
+            if(this.Log == "LOGFILE")
+            {
+                logging.log(logline);
+            }
+            else
+            {
+                if(this.Log == "CONSOLE")
+                {
+                    logging.log(logline);
+                }
+                else if(this.Log != "" && this.Log != undefined)
+                {
+                    // log in globalvar
+                    if(this.Log.split(".")[0].toLowerCase() == "$global")
+                    {
+                        var s = logline + "\r\n";
+                        vars.set(this.Log, vars.getString(this.Log) + s);
+                    }
+                }
+            }
+        }
+
+        tt = datetime.date() - tt;
+        exectimer["logging"] += tt;
+    }
+
+
+    //	retrieve all log messages currently in log buffer
+    this.getLogMessages = function(){
+        return logBuffer;
+    }
+    // return true, if running in client context, false for a server context
+    this.isClientProcess = function(){
+        return vars.getString("$sys.isclient") == "true";
+    }
+
+
+    this.getFileContent = function(pFilename, pDataType)
+    {
+        var resContent;
+        var cp;
+
+        if(this.isClientProcess() == true)   // use doClientIntermediate
+        {
+            try
+            {
+                resContent = swing.doClientIntermediate(swing.CLIENTCMD_GETDATA, [pFilename, pDataType, this.fileInputCharset]);
+            }
+            catch(ex)
+            {
+                logging.show(ex)
+                resContent = "";
+            }
+        }
+        else   // use fileIO
+        {
+            try
+            {
+                resContent = fileIO.getData(pFilename, util.DATA_TEXT, this.fileInputCharset);
+            }
+            catch(ex)
+            {
+                logging.log( ex );
+                resContent = "";
+            }
+        }
+        return resContent;
+    }
+
+
+    this.dumpRecord = function(pTable, pColumns, pTypes, pValues, pCondition)
+    {
+        var PADDING = "................................";
+        var s = "";
+        if(pCondition != undefined) s += "update " + pTable + " where " + pCondition; else s += "insert " + pTable;
+        s += "\n";
+        for(var i=0; i < pColumns.length; i++)
+        {
+            s += "  " + pColumns[i] + PADDING.substr(0, 32- pColumns[i].length) + ": |" + pValues[i] + "|\n";
+        }
+
+        s += "\n";
+
+        return s;
+    }
+
+
+    this.insertData = function(pTable, pColumns, pTypes, pValues, pAlias)
+    {
+        var tt = datetime.date();
+        var resData = true;
+        if(this.Preview == false)
+        {
+            //better safe than sorry ...
+            try
+            {
+                if(pTable.toLowerCase() != "var")
+                {
+                    if(this.DataType[pTable] == undefined) this.writeLog(this.LogLevels.Error, "Table " + pTable + " not exist in database");
+                    else
+                    {
+                        this.writeLog(this.LogLevels.Debug, "INSERT for [" + pAlias + "].[" + pTable + "]");
+                        this.writeLog(this.LogLevels.Preview, this.dumpRecord(pTable, pColumns, pTypes, pValues));
+                        //exist already "USER_NEW" and/or "DATE_NEW" in the columns resultset?
+                        var uNew = false;
+                        var dNew = false;
+                        for(var i = 0; i < pColumns.length; i++)
+                        {
+                            if(uNew == false && pColumns[i].toUpperCase() == "USER_NEW")
+                                uNew = true;
+
+                            if(dNew == false && pColumns[i].toUpperCase() == "DATE_NEW")
+                                dNew = true;
+                        }
+                        // process audit columns automagically
+                        if(uNew == false && this.DataType[this.getTableCase(pTable)][this.getColumnCase("USER_NEW")] != undefined)
+                        {
+                            pColumns.push(this.getColumnCase("USER_NEW"));
+                            if (pTypes != null) pTypes.push(this.DataType[this.getTableCase(pTable)][this.getColumnCase("USER_NEW")]);
+                            pValues.push(this.ImportUser);
+                        }
+                        if(dNew == false && this.DataType[pTable][this.getColumnCase("DATE_NEW")] != undefined)
+                        {
+                            pColumns.push(this.getColumnCase("DATE_NEW"));
+                            if(pTypes != null) pTypes.push(this.DataType[this.getTableCase(pTable)][this.getColumnCase("DATE_NEW")]);
+                            pValues.push(datetime.date());
+                        }
+
+                        this.insertArray.push([this.getTableCase(pTable), pColumns, pTypes, pValues, pAlias]);
+                    }
+                }
+            }
+            catch(ex)
+            {
+                this.writeLog(this.LogLevels.Error, "Exception at insertData for record: " + getRecordString(pColumns, pValues));
+                logging.log(ex);
+                resData = false;
+            }
+        }
+        else
+        {
+            this.writeLog(this.LogLevels.Preview, "Insert into table " + pTable);
+            this.writeLog(this.LogLevels.Preview, this.dumpRecord(pTable, pColumns, pTypes, pValues));
+        }
+
+        tt = datetime.date() - tt;
+        exectimer["insertData"] += tt;
+        return resData;
+    }
+
+    this.updateData = function(pTable, pColumns, pTypes, pValues, pCondition, pAlias)
+    {
+        var tt = datetime.date();
+        var theCols;
+        var theTypes;
+        var theValues;
+
+        var resultData = true;
+        if(this.Preview == false)
+        {
+            try
+            {
+                if(pTable.toLowerCase() != "var")
+                {
+                    if(this.DataType[pTable] == undefined) this.writeLog("Table " + pTable + " not exist in database");
+                    else
+                    {
+                        this.writeLog(this.LogLevels.Debug, "UPDATE for alias [" + pAlias + "].[" + pTable + "]");
+                        this.writeLog(this.LogLevels.Preview, this.dumpRecord(pTable, pColumns, pTypes, pValues, pCondition));
+
+                        if (this.CompleteUpdate == false)   // check for changed database values and use only changed columns for update
+                        {
+                            var uColumns = new Array();
+                            var uValues = new Array();
+                            var uTypes = new Array();
+                            var oldValues = db.array(db.ROW, "select " + pColumns.join(", ") + " from " + pTable + " where " + pCondition, pAlias);
+                            for (var dsi = 0; dsi < oldValues.length; dsi++)
+                            {
+                                if (oldValues[dsi] != pValues[dsi])
+                                {
+                                    //get the values from the validate target
+                                    uColumns.push(pColumns[dsi]);
+                                    uValues.push(pValues[dsi]);
+                                    if (pTypes != null) uTypes.push(pTypes[dsi]);
+                                }
+                            }
+                            theCols = uColumns;
+                            theTypes = uTypes;
+                            theValues = uValues;
+                        }
+                        else   // update all columns, so use default column set
+                        {
+                            theCols = pColumns;
+                            theTypes = pTypes;
+                            theValues = pValues;
+                        }
+
+                        if(theCols.length > 0)
+                        {
+                            //show the old and the new data only if anything changed
+                            this.writeLog(this.LogLevels.Preview, "New Data: " + pValues.join("|"));
+                            if (oldValues != undefined)
+                                this.writeLog(this.LogLevels.Preview, "Old Data: " + oldValues.join("|"));
+                        }
+
+                        var minchanges = 0;
+                        var dEdit = false;
+                        var uEdit = false;
+
+                        for(var i = 0; i < theCols.length; i++)
+                        {
+                            if(uEdit == false && theCols[i].toUpperCase() == "USER_EDIT")
+                                uEdit = true;
+
+                            if(dEdit == false && theCols[i].toUpperCase() == "DATE_EDIT")
+                                dEdit = true;
+                        }
+
+
+                        // process audit columns automagically
+                        if(uEdit == false && this.DataType[this.getTableCase(pTable)][this.getColumnCase("USER_EDIT")] != undefined)
+                        {
+                            theCols.push(this.getColumnCase("USER_EDIT"));
+                            if(pTypes != null) theTypes.push(this.DataType[this.getTableCase(pTable)][this.getColumnCase("USER_EDIT")]);
+                            theValues.push(this.ImportUser);
+                            minchanges++;
+                        }
+                        if(dEdit == false && this.DataType[this.getTableCase(pTable)][this.getColumnCase("DATE_EDIT")] != undefined)
+                        {
+                            theCols.push(this.getColumnCase("DATE_EDIT"));
+                            if(pTypes != null) theTypes.push(this.DataType[this.getTableCase(pTable)][this.getColumnCase("DATE_EDIT")]);
+                            theValues.push(datetime.date());
+                            minchanges++;
+                        }
+                        if(this.CompleteUpdate == false)
+                        {
+                            if(theCols.length > minchanges)
+                            {
+                                this.updateArray.push([this.getTableCase(pTable), theCols, theTypes, theValues, pCondition, pAlias]);
+                            }
+                        }
+                        else
+                        {
+                            this.updateArray.push([this.getTableCase(pTable), theCols, theTypes, theValues, pCondition, pAlias]);
+                        }
+                    }
+                }
+            }
+            catch(ex)
+            {
+                resultData = false;
+                this.writeLog(this.LogLevels.Error, "Exception at updateData for record: " + getRecordString(pColumns, pValues));
+                logging.log(ex);
+            }
+        }
+        else
+        {
+            this.writeLog(this.LogLevels.Preview, "Update table " + pTable);
+            this.writeLog(this.LogLevels.Preview, this.dumpRecord(pTable, pColumns, pTypes, pValues, pCondition));
+        }
+        tt = datetime.date() - tt;
+        exectimer["updateData"] += tt;
+        return resultData;
+    }
+
+    //		set default action for a mapping call, if action has not been specified
+    this.setDefaultAction = function(pObject)
+    {
+        if(pObject.Action == undefined)  // set reasonable defaults for Action, if not specified
+        {
+            if(this.Config.ImportCommand == "insert") pObject.Action = "I";
+            else
+            if(this.Config.ImportCommand == "update") pObject.Action = "U";
+            else
+            if(this.Config.ImportCommand == "insert+update") pObject.Action = "I+U";
+        }
+    }
+
+    //		ATTENTION!! This is the *new* version and not the same as resolveSymbols!!
+    //
+    //		resolve symbol to get import data
+    //		may contain literals string and {#} and {tbl.col} symbols
+    //		if undefined or empty expression is provided, return an empty string
+    this.resolveSymbol = function(pObject, pExpression, pEvalScript)
+    {
+        var expr;
+
+        if((pExpression != undefined) && (pExpression != ""))
+        {
+            var inp = this.InputRecord;
+            var out = this.OutputRecord;
+            var cCase = this.ColumnCase;
+            var tCase = this.TableCase;
+            var uCase = this.Cases.Upper;
+
+            this.setDefaultAction(pObject);
+            var obj = pObject;
+
+            let self = this;
+
+            expr = pExpression.toString();
+            expr = expr.replace(/\{([._a-zA-Z0-9]+)\}/ig,
+                function(pMatch, pNumber)
+                {
+                    if(isNaN(Number(pNumber)))
+                    {
+                        var varname = pNumber.split(".");
+                        var res;
+
+                        // action verwenden, wenn keine da => importcommand auslesen
+                        var action = obj.Action;
+                        if(out[ self.getTableCase(varname[0]) ] != undefined && out[ self.getTableCase(varname[0]) ][ self.getColumnCase(varname[1]) ] != undefined)
+                        {
+                            switch(obj.Action)
+                            {
+                                case "I":
+                                    res = out[ self.getTableCase(varname[0]) ][ self.getColumnCase(varname[1]) ]["I"];
+                                    break;
+                                case "U":
+                                    res = out[ self.getTableCase(varname[0]) ][ self.getColumnCase(varname[1]) ]["U"];
+                                    break;
+                                case "I+U":
+
+                                    res = out[ self.getTableCase(varname[0]) ][ self.getColumnCase(varname[1]) ]["U"];																					//2009-06-16  TR
+                                    if(res == undefined || res == "") res = out[ self.getTableCase(varname[0])][ self.getColumnCase(varname[1]) ]["I"];  //2009-06-16  TR
+
+                                    break;
+                            }
+                        }
+                        else  // varname does not exist as a property of out
+                        {
+                            res = undefined;
+                        }
+                        if(res == undefined) res = "";  // blank out NULL values
+
+                        //transform ' to \\u0027 which is in eval a \u0027; transform " to \\u0022 which is in eval a \u0022
+                        //needed for eval like: "'3'2' != ''"
+                        if(pEvalScript)
+                            return res.replace("'", "\\\\u0027", "g").replace("\"", "\\\\u0022", "g");
+                        else
+                            return res;
+                    }
+                    else
+                    {
+                        //transform ' to \\u0027 which is in eval a \u0027; transform " to \\u0022 which is in eval a \u0022
+                        //needed for eval like: "'3'2' != ''"
+                        if(pEvalScript)
+                            return inp[Number(pNumber)].replace("'", "\\\\u0027", "g").replace("\"", "\\\\u0022", "g");
+                        else
+                            return inp[Number(pNumber)];
+                    }
+                } );
+            if(pEvalScript == true)
+                expr = eval(expr);
+        }
+        else
+        {
+            expr = "";
+        }
+        return expr;
+    }
+
+    //	  read column type information for all columns in all tables of the alias specified
+    this.getDataTypes = function(pAlias)
+    {
+        var tables = db.getTables(pAlias);
+        var dataTypes = new Object();
+        for(var i=0; i < tables.length; i++)
+        {
+            if (tables[i] != "trace_xe_action_map" && tables[i] != "trace_xe_event_map")
+            {
+                var cols = db.getColumns(tables[i], pAlias);
+                var types = db.getColumnTypes(tables[i], cols, pAlias);
+                dataTypes[ tables[i] ] = new Object();  // create sub-object to hold columns
+                for(var j=0; j < cols.length; j++) dataTypes[tables[i]][cols[j]] = types[j];
+            }
+        }
+        return dataTypes;   // return object with type information
+    }
+
+    //		sets the output record buffer according to "Action" performed
+    this.setOutput = function(pObject, pValue)
+    {
+        try
+        {
+            var target = pObject.Target.split(".");
+            this.setDefaultAction(pObject);
+            // make sure we do have an output buffer
+            if(this.OutputRecord[ this.getTableCase(target[0]) ] == undefined) this.OutputRecord[ this.getTableCase(target[0]) ] = new Object();
+            if(this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ] == undefined) this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ] = new Object();
+            switch(pObject.Action)
+            {
+                case "I":
+                    this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["I"] = pValue;
+                    break;
+                case "U":
+                    this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["U"] = pValue;
+                    break;
+                case "I+U":
+                    this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["I"] = pValue;    //2009-06-16  TR
+                    this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["U"] = pValue;    //2009-06-16  TR
+                    this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["I+U"] = pValue;  //2009-06-16  TR
+                    break;
+            }
+        }
+        catch(ex)
+        {
+            this.writeLog(this.LogLevels.Error, "Property <Target> not set for mapping object!");
+            logging.log(ex);
+            logging.log("[IMPORTER] Property <Target> not set for mapping object!");
+        }
+    }
+    //		get the content of the output record buffer according to "Action" performed
+    this.getOutput = function(pObject, pTarget)
+    {
+        var target;
+        var action;
+
+        target = pTarget.split(".");
+        if(pObject != undefined) action = pObject.Action; else action = undefined;
+        if(action == undefined)  // set reasonable defaults for Action, if not specified
+        {
+            if(this.Config.ImportCommand == "insert") action = "I";
+            else
+            if(this.Config.ImportCommand == "update") action = "U";
+            else
+            if(this.Config.ImportCommand == "insert+update") action = "I+U";
+        }
+        var resAction;
+        switch(action)
+        {
+            case "I":
+                resAction = this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1])]["I"];
+                break;
+            case "U":
+                resAction = this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["U"];
+                break;
+            case "I+U":
+                resAction = this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["U"];
+                if(resAction == undefined || resAction == "") resAction = this.OutputRecord[ this.getTableCase(target[0]) ][ this.getColumnCase(target[1]) ]["I"];
+                break;
+        }
+        if(resAction == undefined) resAction = "";   // blank out undefined
+        return resAction;
+    }
+
+
+    //		generates condition clause (without "WHERE") to check for existing key column values
+    this.generateKeyCondition = function(pTable)
+    {
+        var whereclause = "";
+        for(var col in this.KeyColumn[pTable])
+        {
+            var tmp = this.KeyColumn[pTable][col];  // contains I | I;U | I+U
+            if(tmp != "")
+            {
+                var value = this.OutputRecord[pTable][col]["U"];
+                if(value == undefined || value == "")
+                    value = this.OutputRecord[pTable][col]["I+U"];
+                if(value == undefined || value == "")
+                    value = this.OutputRecord[pTable][col]["I"];
+
+                // we cannot distinguish between an empty string and NULL in Jdito,
+                // so if get an empty string for the value, we do a check for empty string OR NULL
+                if(value == "")
+                {
+                    whereclause += " and (" + col + " = '' OR " + col + " is null)";
+                }
+                else
+                {
+                    whereclause += " and " + col + " = '" + db.quote(value, this.Config.AliasTo) + "'";
+                }
+            }
+        }
+        // remove leading "and" from where clause
+        if(whereclause.substr(0, 4) == " and") whereclause = whereclause.substr(4, whereclause.length);
+
+        return whereclause;
+    }
+    /*
+    * yield a string representation of the record in pColumns and pValues for logging
+    * purposes and debugging.
+    *
+    * @param {String[]} pColumns req columns that are represented
+    * @param {String[]} pValues req values that are represented
+    *
+    * @return {String}
+    */
+    function getRecordString(pColumns, pValues)
+    {
+        var s = "";
+        for(var i=0; i < pColumns.length; i++)
+        {
+            var v = "";
+            if(pValues[i]) v = pValues[i].toString();
+            if(v.length > 40) v = v.substr(0,39) + "...";
+            s += "  COL: " + pColumns[i] + ": " + v + "\n";
+        }
+
+        return s;
+    }
+
+    //Converts a string with the tablename in upper or lower case
+    this.getTableCase = function(pName)
+    {
+        if(this.TableCase == this.Cases.Upper)
+            return pName.toUpperCase();
+        else if (this.TableCase == this.Cases.Lower)
+            return pName.toLowerCase();
+        else
+            return pName;
+    }
+
+    //Converts a string with the columnname in upper or lower case
+    this.getColumnCase = function(pName)
+    {
+        if (this.ColumnCase == this.Cases.Upper)
+            return pName.toUpperCase();
+        else if (this.ColumnCase == this.Cases.Lower)
+            return pName.toLowerCase();
+        else
+            return pName;
+    }
+
+    this.doIfCheck = function(pObject)
+    {
+        if (pObject.DoIf == undefined) return true;
+
+        if (typeof(pObject.DoIf) == "function")
+        {
+            var expr;
+            if(pObject.Source != undefined) expr = this.InputRecord[pObject.Source];
+            if(pObject.Value != undefined) expr = this.resolveSymbol(pObject, pObject.Value, pObject.Eval);
+            if(pObject.Map != undefined && pObject.Index) expr = pObject.Map[this.resolveSymbol(pObject, pObect.Index, pObject.Eval)];
+            return pObject.DoIf.call(this, this.InputRecord, expr, pObject);
+        }
+        
+        return (this.resolveSymbol(pObject, pObject.DoIf, true));
+    }
+}
+
+/**
+ * Data handler for csv paging
+ *
+ * @param pCurrentBatchNum
+ * @param pBatchSize
+ */
+function batchCsvLoad(pCurrentBatchNum, pBatchSize)
+{
+    if (this.BatchStart == undefined) this.BatchStart = 0;
+    if (this.Config.RowSeparator != undefined) this.writeLog(this.LogLevels.Warning, "'RowSeparator' option is currently not supported!")
+    var dataStr = "";
+    var fn = this.Config.DataFile;
+    var bs = pBatchSize;
+    var process = this.Config.Processname;
+    if (!fileIO.exists(fn))
+        throw new Error(translate.withArguments("file '%0' does not exist or you have got no permission on this file", [fn]));
+    else if (!fileIO.canRead(fn))
+        throw new Error(translate.withArguments("file '%0' cannot be read", [fn]));
+    const MAX_LOOP_SIZE = this.Config.BatchSize;
+    do
+    {
+        dataStr = null;
+        var loopSize = MAX_LOOP_SIZE;
+        try
+        {
+            dataStr = fileIO.getBulkData(fn, util.DATA_TEXT, this.fileInputCharset, this.BatchStart, bs);
+        }
+        catch(ex)
+        {
+            break;
+        }
+        this.BatchStart += bs;
+        whileMultiline: while (dataStr.slice(-2) != "\r\n" && (dataStr.slice(-1) == "\n" || dataStr.slice(-1) == "\r"))//we have to load more Data
+        {
+            try
+            {
+                dataStr += fileIO.getBulkData(fn, util.DATA_TEXT, this.fileInputCharset, this.BatchStart, 1);
+            }
+            catch(ex)
+            {
+                this.writeLog(this.LogLevels.Warning, ex);
+                break;
+            }
+            this.BatchStart++;
+            if (loopSize == 0)
+            {
+                this.writeLog(this.LogLevels.Error, "MAX_LOOP_SIZE reached; Abort");
+                break whileMultiline;
+            }
+            loopSize--;
+        }
+        if (dataStr.slice(-2) == "\r\n")
+            dataStr = dataStr.slice(0, -2);
+        var rs = this.Config.RowSeparator;
+        if(rs == undefined) rs = "\r\n";
+        var cs = this.Config.ColumnSeparator;
+        if(cs == undefined) cs = ";";
+        var sd = this.Config.StringDelimiter;
+        if(sd == undefined) sd = "";
+        return text.parseCSV(dataStr, rs, cs, sd);
+    }
+    while(dataStr != null);
+    return null;
+}
+
+
diff --git a/process/JditoFilter_lib/process.js b/process/JditoFilter_lib/process.js
index 64d5ea5a3107407acc64475b059ccb2a721858a7..4f27dfaec8b3cfe738feae91f9e1cea90f6b8320 100644
--- a/process/JditoFilter_lib/process.js
+++ b/process/JditoFilter_lib/process.js
@@ -1,112 +1,216 @@
-
-/**
- * object for filtering records
- * 
- * @param {Array} pColumns the column names
- * @param {String|Object} pFilter the filter object
- */
-function JditoFilter (pColumns, pFilter) 
-{
-    var columnMap = {};
-    pColumns.forEach(function (row, i)
-    {
-        columnMap[row] = i;
-    });
-    this._columnMap = columnMap;
-    
-    if (pFilter.length) //check if pFilter is a string
-        pFilter = JSON.parse(pFilter);
-    
-    this._operator = pFilter.operator;
-    this._filters = pFilter.childs;
-}
-
-/**
- * tests the given row if it matches the filter
- * 
- * @param {Array} pRow one record
- * 
- * @return {boolean} true, if it matches the condition
- */
-JditoFilter.prototype.checkRecord = function (pRow)
-{
-    if (this._filters.length == 0)
-        return true;
-    
-    if (this._operator == "AND")
-        return this._filters.every(_testFn, this);
-    
-    return this._filters.some(_testFn, this);
-    
-    function _testFn (pFilter)
-    {
-        let value = pRow[this._columnMap[pFilter.name]];
-        return this._testValue(value, (pFilter.key || pFilter.value), pFilter.operator);
-    }
-}
-
-/**
- * compares two values with the given operator
- */
-JditoFilter.prototype._testValue = function (pRowValue, pFilterValue, pOperator)
-{
-    switch (pOperator)
-    {
-        case "CONTAINS":
-            return (new RegExp(pFilterValue)).test(pRowValue);
-        case "CONTAINSNOT":
-            return !(new RegExp(pFilterValue)).test(pRowValue);
-        case "STARTSWITH":
-            return (new RegExp("^" + pFilterValue)).test(pRowValue);
-        case "ENDSWITH":
-            return (new RegExp(pFilterValue + "$")).test(pRowValue);
-        case "EQUAL":
-            return (new RegExp("^" + pFilterValue + "$")).test(pRowValue);
-        case "NOT_EQUAL":
-            return !(new RegExp("^" + pFilterValue + "$")).test(pRowValue);
-        case "LESS":
-            return pRowValue < pFilterValue;
-        case "LESS_OR_EQUAL":
-            return pRowValue <= pFilterValue;
-        case "GREATER":
-            return pRowValue > pFilterValue;
-        case "GREATER_OR_EQUAL":
-            return pRowValue >= pFilterValue;
-        case "ISNULL":
-            return pRowValue == "";
-        case "ISNOTNULL":
-            return pRowValue != "";
-    }
-}
-
-/**
- * Provides functions for using the filter with jdito recordcontainers. You should only use this
- * if there is no other, faster way to filter the records
- * 
- * Do not instanciate this!
- * 
- * @class
- */
-function JditoFilterUtils () {}
-
-/**
- * Filters the given records
- * 
- * @param {Array} pColumns one dimensional array with all column names, the order has to match the columns of pRecords
- * @param {Array} pRecords two dimensional array with all records
- * @param {String|Object} pFilter the value of $local.filter
- * 
- * @return {Array} the filtered records
- */
-JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter)
-{
-    if (!pFilter)
-        return pRecords;
-    
-    var filter = new JditoFilter(pColumns, pFilter);
-    
-    return pRecords.filter(function (row)
-        {
-            return this.checkRecord(row);
-        }, filter);
+import("Sql_lib");
+
+/**
+ * object for filtering records
+ * 
+ * @param {Array} pColumns the column names
+ * @param {String|Object} pFilter the filter object
+ */
+function JditoFilter (pColumns, pFilter) 
+{
+    var columnMap = {};
+    pColumns.forEach(function (row, i)
+    {
+        columnMap[row] = i;
+    });
+    this._columnMap = columnMap;
+    
+    if (pFilter.length) //check if pFilter is a string
+        pFilter = JSON.parse(pFilter);
+    
+    this._operator = pFilter.operator;
+    this._filters = pFilter.childs;
+}
+
+/**
+ * tests the given row if it matches the filter
+ * 
+ * @param {Array} pRow one record
+ * 
+ * @return {boolean} true, if it matches the condition
+ */
+JditoFilter.prototype.checkRecord = function (pRow)
+{
+    if (this._filters.length == 0)
+        return true;
+    
+    if (this._operator == "AND")
+        return this._filters.every(_testFn, this);
+    
+    return this._filters.some(_testFn, this);
+    
+    function _testFn (pFilter)
+    {
+        let value = pRow[this._columnMap[pFilter.name]];
+        return this._testValue(value, (pFilter.key || pFilter.value), pFilter.operator);
+    }
+}
+
+/**
+ * compares two values with the given operator
+ */
+JditoFilter.prototype._testValue = function (pRowValue, pFilterValue, pOperator)
+{
+    switch (pOperator)
+    {
+        case "CONTAINS":
+            return (new RegExp(pFilterValue)).test(pRowValue);
+        case "CONTAINSNOT":
+            return !(new RegExp(pFilterValue)).test(pRowValue);
+        case "STARTSWITH":
+            return (new RegExp("^" + pFilterValue)).test(pRowValue);
+        case "ENDSWITH":
+            return (new RegExp(pFilterValue + "$")).test(pRowValue);
+        case "EQUAL":
+            return (new RegExp("^" + pFilterValue + "$")).test(pRowValue);
+        case "NOT_EQUAL":
+            return !(new RegExp("^" + pFilterValue + "$")).test(pRowValue);
+        case "LESS":
+            return pRowValue < pFilterValue;
+        case "LESS_OR_EQUAL":
+            return pRowValue <= pFilterValue;
+        case "GREATER":
+            return pRowValue > pFilterValue;
+        case "GREATER_OR_EQUAL":
+            return pRowValue >= pFilterValue;
+        case "ISNULL":
+            return pRowValue == "";
+        case "ISNOTNULL":
+            return pRowValue != "";
+    }
+}
+
+/**
+ * Provides functions for using the filter with jdito recordcontainers. You should only use this
+ * if there is no other, faster way to filter the records
+ * 
+ * Do not instanciate this!
+ * 
+ * @class
+ */
+function JditoFilterUtils () {}
+
+/**
+ * Filters the given records
+ * 
+ * @param {Array} pColumns one dimensional array with all column names, the order has to match the columns of pRecords
+ * @param {Array} pRecords two dimensional array with all records
+ * @param {String|Object} pFilter the value of $local.filter
+ * 
+ * @return {Array} the filtered records
+ */
+JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter)
+{
+    if (!pFilter)
+        return pRecords;
+    
+    var filter = new JditoFilter(pColumns, pFilter);
+    
+    return pRecords.filter(function (row)
+        {
+            return this.checkRecord(row);
+        }, filter);
+}
+
+/**
+ * builds an sql condition from the given filter
+ * 
+ * @param {String|Object} pFilter the filter as JSON
+ * @param {String} pTable the database table
+ * @param {Object} pColumnMap custom mapping for the fields to the DB columns, this is necessary
+ *      if the fields are from different tables
+ *      
+ * @example
+ * if (vars.exists("$local.filter") && vars.get("$local.filter"))
+ * {
+ *     var filter = vars.get("$local.filter");
+ *     condition.andSqlCondition((JditoFilterUtils.getSqlCondition(filter, "AB_ATTRIBUTE")));
+ * }
+ *      
+ * @return {SqlCondition} the SqlCondition object
+ */
+JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pColumnMap)
+{
+    var condition = new SqlCondition();
+    
+    if (!pFilter)
+        return condition;
+    if (pFilter.length) //check if pFilter is a string
+        pFilter = JSON.parse(pFilter);
+    if (!pColumnMap)
+        pColumnMap = {};
+    
+    _addCondition.call(condition, pFilter, pFilter.operator);
+    
+    return condition;
+    
+    //recursive function (for compatibility with a condition tree) that
+    //builds the SqlCondition
+    function _addCondition (pCondition, pOperator)
+    {
+        if (pCondition.type == "row")
+        {
+            if (pCondition.name in pColumnMap)
+                pCondition.name = pColumnMap[pCondition.name];
+            else if (pTable)
+                pCondition.name =  pTable + "." + pCondition.name;
+            
+            pCondition.value = (pCondition.key || pCondition.value);
+            var condition = _getCondition.call(pCondition);
+            if (pOperator == "AND")
+                this.andPrepare(pCondition.name, pCondition.value, condition);
+            else if (pOperator == "OR")
+                this.orPrepare(pCondition.name, pCondition.value, condition);
+        }
+        else if (pCondition.type == "group")
+        {
+            let subCondition = new SqlCondition();
+            let operator = pCondition.operator;
+            pCondition.childs.forEach(function (cond)
+            {
+                _addCondition.call(subCondition, cond, operator);
+            });
+            if (pOperator == "AND")
+                this.andSqlCondition(subCondition);
+            else if (pOperator == "OR")
+                this.orSqlCondition(subCondition);
+        }
+    }
+    
+    //returns the condition depending on the operator and 
+    //adds wildcards to the value if necessary
+    function _getCondition ()
+    {
+        switch (this.operator)
+        {
+            case "CONTAINS":
+                this.value = "%" + this.value + "%";
+                return "# like ?";
+            case "CONTAINSNOT":
+                this.value = "%" + this.value + "%";
+                return "# not like ?";
+            case "STARTSWITH":
+                this.value = this.value + "%";
+                return "# like ?";
+            case "ENDSWITH":
+                this.value = "%" + this.value;
+                return "# like ?";
+            case "EQUAL":
+                return "# = ?";
+            case "NOT_EQUAL":
+                return "# != ?";
+            case "LESS":
+                return "# < ?";
+            case "LESS_OR_EQUAL":
+                return "# <= ?";
+            case "GREATER":
+                return "# > ?";
+            case "GREATER_OR_EQUAL":
+                return "# >= ?";
+            case "ISNULL":
+                return "# is null";
+            case "ISNOTNULL":
+                return "# is not null";
+        }
+    }
 }
\ No newline at end of file
diff --git a/process/Keyword_lib/process.js b/process/Keyword_lib/process.js
index 971a45c6306a22c4b6508ffbe6a0fd8cfc834aa3..a74c939dcfbcd1555009d27ff9f07618d548323f 100644
--- a/process/Keyword_lib/process.js
+++ b/process/Keyword_lib/process.js
@@ -257,6 +257,17 @@ function KeywordAttribute(pContainerName, pAttributeName)
     this.dbField = this.type.trim();
 }
 
+KeywordAttribute.prototype.getValue = function(pKeyId)
+{
+    var sql = SqlCondition.begin()
+                          .andPrepare("AB_KEYWORD_ENTRY.CONTAINER", this.container)
+                          .andPrepare("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", this.id)
+                          .andPrepare("AB_KEYWORD_ENTRY.KEYID", pKeyId)
+                          .buildSql("select " + this.dbField + " from AB_KEYWORD_ENTRY join AB_KEYWORD_ATTRIBUTERELATION on AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID");
+
+    return db.cell(sql);
+}
+
 /**
  * provides methods for interactions with the sepcial-keywords "LANGUAGE"
  * 
diff --git a/process/OfferOrder_lib/process.js b/process/OfferOrder_lib/process.js
index bb660ba440d2f9ebebe90fa4883372927b681d18..e052a9b674ad3a092df5ef1a8c94606ca2151e26 100644
--- a/process/OfferOrder_lib/process.js
+++ b/process/OfferOrder_lib/process.js
@@ -64,51 +64,6 @@ function ItemUtils(pOfferOrderId, pTableName) {
         }
     }
     
-    /**
-     * Deletes a node from an ItemTree Object within its subnodes. <br>
-     * If no ItemTree Object is passed, the class variable this.ItemTree will be used.
-     *
-     * @param {String} itemId req UID of item
-     * @param {Object} tree opt ItemTree Object to delete from
-     * @param {String[]} ids opt ids Array for all ItemIDs to save order
-     *
-     * @ignore
-     */
-    this._deleteNodes = function(itemId, tree, ids) {
-        if (tree == undefined)
-            tree = this.ItemTree;
-        if (ids == undefined)
-            ids = this.ItemIds;
-
-        __delete(tree[itemId]);
-
-        _deleteNode(itemId);
-
-        function __delete(pNode) {
-            for (var i = 0; i < pNode.ids.length; i++) {
-                __delete(tree[pNode.ids[i]]);
-                _deleteNode(pNode.ids[i]);
-            }
-        }
-        
-        function _deleteNode(itemId) {
-            //delete Object property
-            delete tree[itemId];
-
-            //delete id in global Array "ItemIds"
-            var idx = ids.indexOf(itemId);
-            if (idx > -1)
-                ids.splice(idx, 1);
-
-            //delete id in Array from property "ids" of Tree
-            for (var oiid in tree) {
-                idx = tree[oiid].ids.indexOf(itemId);
-                if (idx > -1)
-                    tree[oiid].ids.splice(idx, 1);
-            }
-        }
-    }
-    
     /**
      * Compares Positions & Sort of the passed ItemTree Object with the class variable this.ItemTree <br>
      * and updates differences in database.
@@ -346,23 +301,36 @@ ItemUtils.prototype.deletePartsList = function(itemId) {
     var statements = [];
 
     __itemDeleteStatement(itemId);
-
+    
     if (statements.length > 0)
         db.deletes(statements);
-
-    self._deleteNodes(itemId);
-
+    
+    // delete nodes from tree
+    _deleteNode(itemId)
+    deletedItemIds.forEach(_deleteNode);
+    
     return deletedItemIds;
     
+    function _deleteNode(pItemId) {
+        //delete Object property
+        delete self.ItemTree[pItemId];
+
+        //delete id in global Array "ItemIds"
+        var idx = self.ItemIds.indexOf(pItemId);
+        if (idx > -1)
+            self.ItemIds.splice(idx, 1);
+    }
+    
     //recursive function for building item delete statements 
     function __itemDeleteStatement(itemId) {        
         var itemsToDelete = self.ItemTree[itemId].ids;
         for (var i = 0; i < itemsToDelete.length; i++) {
+            
             //unshift due to foreign key constraints (Delete hierarchically starting at the bottom)                                           
             statements.unshift([self.tableName + "ITEM", SqlCondition.begin()
                                            .andPrepare(self.tableName + "ITEM." + self.tableName + "ITEMID", itemsToDelete[i])
                                            .build("1 = 2")]);
-                                           
+            
             deletedItemIds.push(itemsToDelete[i]);
             __itemDeleteStatement(itemsToDelete[i]);
         }
@@ -468,4 +436,4 @@ ItemUtils.prototype.reOrgItems = function() {
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/process/Organisation_lib/process.js b/process/Organisation_lib/process.js
index 7f7bba96f84861008454d5cd16c1b4243afe2177..e661ac0b18472e351423da60acb074d19e5e52db 100644
--- a/process/Organisation_lib/process.js
+++ b/process/Organisation_lib/process.js
@@ -121,8 +121,8 @@ OrgUtils.openOrgReport = function(pOrgId)
     });
     histData = ReportData.begin(["ENTRYDATE", "MEDIUM", "LOGIN", "INFO"]).add(histData);
     
-    var attr = AttributeRelationUtils.getAllAttributes(pOrgId, null, true)
-        .map(function (row) {return row.join(": ")})
+    var attr = AttributeRelationUtils.getAllAttributes(pOrgId)
+        .map(function (row) {return row[1] ? row.join(": ") : row[0]})
         .join("\n");
     
     //tasks
diff --git a/process/PostalAddress_lib/process.js b/process/PostalAddress_lib/process.js
index bee94a606c965fe9d760c7ada0475ece7858fd8a..71de1bb3d79977e237b5fe8f66d88bb33ed41af2 100644
--- a/process/PostalAddress_lib/process.js
+++ b/process/PostalAddress_lib/process.js
@@ -118,12 +118,17 @@ AddressUtils.getAddressById = function(pAddressId) {
         
     }
     var type = ContactUtils.getContactTypeByContactId(address[0]);   
-
-    var names = db.array(db.ROW, SqlCondition.begin()
+    
+    if (address[0])
+    {
+        var names = db.array(db.ROW, SqlCondition.begin()
                                              .andPrepare("CONTACT.CONTACTID", address[0])
-                                             .buildSql("select ORGANISATION.NAME, FIRSTNAME, LASTNAME, TITLE from CONTACT left join PERSON on PERSONID = PERSON_ID left join ORGANISATION on ORGANISATIONID = ORGANISATION_ID"
+                                             .buildSql("select ORGANISATION.NAME, FIRSTNAME, LASTNAME, TITLE from CONTACT left join PERSON on                                                           PERSONID = PERSON_ID left join ORGANISATION on ORGANISATIONID = ORGANISATION_ID"
                                                             , "1=0"));
-    return AddressUtils.formatAddress(type, address[1], address[2], address[3], address[4], names[0], names[1], names[2], names[3]);
+        return AddressUtils.formatAddress(type, address[1], address[2], address[3], address[4], names[0], names[1], names[2], names[3]);
+    }
+    
+    return "";
 }
 
 /**
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index 4c68f069fb8f6417e6ce3b78795cc4f0cc8b2091..082ba83b99f8234b2a0606420fd87a859ce21922 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -376,6 +376,11 @@ SqlCondition.prototype._checkVars = function(variable) {
  * @ignore
  */
 SqlCondition.prototype._prepare = function(field, value, cond, fieldType) {
+    if (value == undefined)
+    {
+        throw new Error(translate.withArguments("${SQL_LIB_UNDEFINED_VALUE} field: %0", [field]));
+    }
+    
     if (cond == undefined) {
         cond = "# = ?"
     }
diff --git a/process/_test_importer/_test_importer.aod b/process/_test_importer/_test_importer.aod
new file mode 100644
index 0000000000000000000000000000000000000000..054240e430569eceaeff6e6c6e1a7731a30a849d
--- /dev/null
+++ b/process/_test_importer/_test_importer.aod
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>_test_importer</name>
+  <title>Importer</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/_test_importer/process.js</process>
+  <variants>
+    <element>EXECUTABLE</element>
+  </variants>
+</process>
diff --git a/process/_test_importer/process.js b/process/_test_importer/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad51271dd609329d2675e3ecc01b8f153efabf40
--- /dev/null
+++ b/process/_test_importer/process.js
@@ -0,0 +1,444 @@
+import("system.text");
+import("system.logging");
+import("Util_lib");
+import("ImporterTest_lib");
+import("Importer_lib");
+import("ImporterMappingFunctions_lib");
+
+var testfunctions = {
+    iKeyword: {
+        "insertKeywordNew": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeyword, {Container: 0, Keyword: 1}]]
+            }
+            return runFn(config);
+        },
+        "insertKeywordContainer": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeyword, {Container: 0, Keyword: 1}]]
+            }
+            return runFn(config);
+        },
+        "insertKeywordSame": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeyword, {Container: 0, Keyword: 1}]]
+            }
+            return runFn(config);
+        },
+        "insertKeywordMissing": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeyword, {Container: 0, Keyword: 1}]]
+            }
+            return runFn(config);
+        }
+    },
+    iAttribute: {
+        "insertAttributeNew": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iAttribute, {Attribute: 0, AType: 1}]]
+            }
+            return runFn(config);
+        },
+        "insertAttributeUsage": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iAttribute, {Attribute: 0, AType: 1, OType: 2}]]
+            }
+            return runFn(config);
+        },
+        "insertAttributeRelation": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iAttribute, {Attribute: 0, AType: 1, OType: 2, OID: 3, Value: 4}]]
+            }
+            return runFn(config);
+        },
+        "insertAttributeMissing": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iAttribute, {Attribute: 0, AType: 1}]]
+            }
+            return runFn(config);
+        },
+        "insertAttributeSame": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iAttribute, {Attribute: 0, AType: 1, OType: 2, OID: 3, Value: 4}]]
+            }
+            return runFn(config);
+        }
+    },
+    iKeywordAttribute: {
+        "insertKeywordAttributeNew": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeywordAttribute, {Attribute: 0, AType: 1, Container: 2}]]
+            }
+            return runFn(config);
+        },
+        "insertKeywordAttributeRelation": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeywordAttribute, {Attribute: 0, AType: 1, Container: 2, Keyword: 3, Value: 4}]]
+            }
+            return runFn(config);
+        },
+        "insertKeywordAttributeMissing": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iKeywordAttribute, {Attribute: 0, AType: 1, Container: 2, Keyword: 3, Value: 4}]]
+            }
+            return runFn(config);
+        }
+    },
+    iComm: {
+        "insertCommNew": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iComm, {Address: 0, Medium: 1, ContactID: 2}]]
+            }
+            return runFn(config);
+        },
+        "insertCommMissing": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iComm, {Address: 0, Medium: 1, ContactID: 2}]]
+            }
+            return runFn(config);
+        }
+    },
+    iActivityLink: {
+        "insertActivityLinkNew": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iActivityLink, {ActivityID: 0, OID: 1, OType: 2}]]
+            }
+            return runFn(config);
+        },      
+        "insertActivityLinkMissing": function(runFn) {
+            var config = {
+                AliasTo: "Data_alias",
+                DataFunction: function(pBatchNum, pBatchSize) {
+                    if (pBatchNum > 1) return null;
+                    return this.fixtures;
+                }.bind(this),
+                ImportCommand: "insert+update",
+                Mapping: [[iActivityLink, {ActivityID: 0, OID: 1, OType: 2}]]
+            }
+            return runFn(config);
+        }
+    }
+}  
+
+var fixtures = {
+    iKeyword: {
+        "insertKeywordNew": function() {
+            return [
+                ["ContainerTest1", "KeywordTest1"]               
+            ];
+        },
+        "insertKeywordContainer": function() {
+            return [
+                ["ContainerTest1", "KeywordTest2"],
+                ["ContainerTest1", "KeywordTest3"],
+                ["ContainerTest1", "KeywordTest4"],
+                ["ContainerTest1", "KeywordTest5"]
+            ];
+        },
+        "insertKeywordSame": function() {
+            return [
+                ["ContainerTest1", "KeywordTest1"],
+                ["ContainerTest1", "KeywordTest2"],
+                ["ContainerTest1", "KeywordTest3"],
+            ];
+        },
+        "insertKeywordMissing": function() {
+            return [
+                ["", "KeywordTest2"],
+                [1234, ""],
+            ];
+        }
+    },
+    iAttribute: {
+        "insertAttributeNew": function() {
+            return [
+                ["TestString", $AttributeTypes.TEXT.toString()],
+                ["TestCombo1.TestCombo2.TestCombo3", $AttributeTypes.COMBOVALUE.toString()],
+                ["TestBool", $AttributeTypes.BOOLEAN.toString()],
+                ["TestNum", $AttributeTypes.NUMBER.toString()]
+            ];
+        },
+        "insertAttributeUsage": function() {
+            return [
+                ["TestUsage1", $AttributeTypes.NUMBER.toString(), "Organisation"],
+                ["TestUsage1", $AttributeTypes.NUMBER.toString(), "Person"]
+            ];
+        },
+        "insertAttributeRelation": function() {
+            return [
+                ["TestRel1", $AttributeTypes.TEXT.toString(), "Person", "666", "six hundred sixty six"],
+                ["TestRel1", $AttributeTypes.TEXT.toString(), "Person", "777", "seven hundred seventy seven"],
+                ["TestRel2", $AttributeTypes.NUMBER.toString(), "Organisation", "888", 888],
+                ["TestRel2", $AttributeTypes.NUMBER.toString(), "Organisation", "999", 999]
+            ];
+        },
+        "insertAttributeMissing": function() {
+            return [
+                ["", $AttributeTypes.TEXT.toString()],
+                ["TestNum", ""],
+                ["", 234]
+            ];
+        },
+        "insertAttributeSame": function() {
+            return [
+                ["TestRel1", $AttributeTypes.TEXT.toString(), "Person", "666", "six hundred sixty four"],
+                ["TestRel1", $AttributeTypes.TEXT.toString(), "Person", "777", "seven hundred seventy five"]               
+            ];
+        }
+    },
+    iKeywordAttribute: {
+        "insertKeywordAttributeNew": function() {
+            return [
+                ["KeyAttribute1", $AttributeTypes.TEXT.toString(), "ContainerTest2"],
+                ["KeyAttribute2", $AttributeTypes.NUMBER.toString(), "ContainerTest2"],
+                ["KeyAttribute3", $AttributeTypes.TEXT.toString(), "ContainerTest3"]
+            ];
+        },
+        "insertKeywordAttributeRelation": function() {
+            return [
+                ["KeyAttRel1", $AttributeTypes.TEXT.toString(), "ContainerTest2", "KeywordTest6", "test value"],
+                ["KeyAttRel2", $AttributeTypes.TEXT.toString(), "ContainerTest2", "KeywordTest7", "test value"],
+                ["KeyAttribute2", $AttributeTypes.NUMBER.toString(), "ContainerTest1", "KeywordTest8", 888]
+            ]
+        },
+        "insertKeywordAttributeMissing": function() {
+            return [
+                ["KeyAttRel", 7, 1],
+                ["KeyAttRel", "My Format", "wrong format"],
+                []
+            ]
+        }
+    },
+    iComm: {
+        "insertCommNew": function() {
+            return [
+                ["TestAddress1", "1", "TestContact1"],
+                ["TestAddress2", "2", "TestContact1"]
+            ];
+        },
+        "insertCommMissing": function() {
+            return [
+                ["TestAddress", ""],
+                ["", 2, ""]
+            ];
+        }
+    },
+    iActivityLink: {
+        "insertActivityLinkNew": function() {
+            return [
+                ["TestActivityId",  "rowTest1", "Person"],
+                ["TestActivityId", "rowTest2", "Organisation"],
+                ["TestActivityId", "rowTest2", "Person"]
+            ];
+        },
+        "insertActivityLinkMissing": function() {
+            return [
+                ["", "rowTest1", "Person"],
+                ["ActivityId", 6293, "Organisation"]
+            ];
+        }
+    }
+}
+
+var testCases = [
+    {
+        name: "Keyword Test",
+        childs: [
+            {
+                name: "Import new keywords",
+                fn: testfunctions.iKeyword.insertKeywordNew,
+                fixtures: fixtures.iKeyword.insertKeywordNew()
+            },
+            {
+                name: "Import keywords with already existing container",
+                fn: testfunctions.iKeyword.insertKeywordContainer,
+                fixtures: fixtures.iKeyword.insertKeywordContainer()
+            },
+            {
+                name: "Import already existing keywords",
+                fn: testfunctions.iKeyword.insertKeywordSame,
+                fixtures: fixtures.iKeyword.insertKeywordSame()
+            },
+            {   
+                name: "Import keywords with missing/wrong values",
+                fn: testfunctions.iKeyword.insertKeywordMissing,
+                fixtures: fixtures.iKeyword.insertKeywordMissing()
+            }
+            
+        ]       
+    },
+    {
+        name: "Attribute Test",
+        childs: [
+            {
+                name: "Import new attributes",
+                fn: testfunctions.iAttribute.insertAttributeNew,
+                fixtures: fixtures.iAttribute.insertAttributeNew()
+            },
+            {
+                name: "Import new attributes with usage",
+                fn: testfunctions.iAttribute.insertAttributeUsage,
+                fixtures: fixtures.iAttribute.insertAttributeUsage()
+            },
+            {
+                name: "Import new attributes with usage and relation",
+                fn: testfunctions.iAttribute.insertAttributeRelation,
+                fixtures: fixtures.iAttribute.insertAttributeRelation()
+            },
+            {
+                name: "Import attributes with missing/wrong values",
+                fn: testfunctions.iAttribute.insertAttributeMissing,
+                fixtures: fixtures.iAttribute.insertAttributeMissing()
+            },
+            {
+                name: "Import already existing attributes",
+                fn: testfunctions.iAttribute.insertAttributeSame,
+                fixtures: fixtures.iAttribute.insertAttributeSame()
+            }
+        ]
+    },
+    {
+        name: "Keyword Attribute Test",
+        childs: [
+            {
+                name: "Import new keyword attributes",
+                fn: testfunctions.iKeywordAttribute.insertKeywordAttributeNew,
+                fixtures: fixtures.iKeywordAttribute.insertKeywordAttributeNew()
+            },
+            {
+                name: "Import keyword attribute relations",
+                fn: testfunctions.iKeywordAttribute.insertKeywordAttributeRelation,
+                fixtures: fixtures.iKeywordAttribute.insertKeywordAttributeRelation()
+            },
+            {
+                name: "Import keyword attributes with missing/wrong values",
+                fn: testfunctions.iKeywordAttribute.insertKeywordAttributeMissing,
+                fixtures: fixtures.iKeywordAttribute.insertKeywordAttributeMissing()
+            }
+        ]
+    },
+    {
+        name: "Communication Test",
+        childs: [
+            {
+                name: "Import new communication entries",
+                fn: testfunctions.iComm.insertCommNew,
+                fixtures: fixtures.iComm.insertCommNew()
+            },
+            {
+                name: "Import communication entries with missing/wrong values",
+                fn: testfunctions.iComm.insertCommMissing,
+                fixtures: fixtures.iComm.insertCommMissing()
+            }
+        ]
+    },
+    {
+        name: "Activitylink Test",
+        childs: [
+            {
+                name: "Import new activity link entries",
+                fn: testfunctions.iActivityLink.insertActivityLinkNew,
+                fixtures: fixtures.iActivityLink.insertActivityLinkNew()
+            },
+            {
+                name: "Import activity link entries with missing/wrong values",
+                fn: testfunctions.iActivityLink.insertActivityLinkMissing,
+                fixtures: fixtures.iActivityLink.insertActivityLinkMissing()
+            }
+        ]
+    }
+]
+
+
+var impTest = new ImporterTest();
+impTest.startImporter(testCases);
\ No newline at end of file
diff --git a/process/autostartNeon/process.js b/process/autostartNeon/process.js
index 8b11f3faf4425162254f5c87493816f0cddb28ae..0d612f4106852032aaafe8518e8f1e3c9a834c43 100644
--- a/process/autostartNeon/process.js
+++ b/process/autostartNeon/process.js
@@ -1,5 +1,9 @@
-import("system.calendars")
-
-var users = ["Admin", "Birgit Leicht", "John Doe"]
-calendars.addPermissions(users, calendars.VEVENT, ["READ", "WRITE"], null, false, calendars.SORTSTRATEGY_NATURAL);
+import("system.logging");
+import("system.calendars")
+import("system.notification")
+import("system.text");
+import("system.util");
+
+var users = ["Admin", "Birgit Leicht", "John Doe"]
+calendars.addPermissions(users, calendars.VEVENT, ["READ", "WRITE"], null, false, calendars.SORTSTRATEGY_NATURAL);
 calendars.setCheckAttendeesOnWrite(false);
\ No newline at end of file
diff --git a/process/runIndexer_ws/runIndexer_ws.aod b/process/runIndexer_ws/runIndexer_ws.aod
index 3264bb28ba9b6c1c59d25074ff1f807ca770cbe8..2e40ae988b81f3efc48d1d7f0f3898f47fbe4ce0 100644
--- a/process/runIndexer_ws/runIndexer_ws.aod
+++ b/process/runIndexer_ws/runIndexer_ws.aod
@@ -8,4 +8,7 @@
   <loginTypeId>internal.none</loginTypeId>
   <restrictedRoles />
   <alias>Data_alias</alias>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
 </process>