diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod
index 87ddc6090f433510e27a7364e513d1f24c69346c..75bd8fc7562eac649112a569547aff19d685b216 100644
--- a/aliasDefinition/Data_alias/Data_alias.aod
+++ b/aliasDefinition/Data_alias/Data_alias.aod
@@ -5756,5 +5756,77 @@
       </affectedTables>
       <affectedIds>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/person/affectedIds.js</affectedIds>
     </indexSearchGroup>
+    <indexSearchGroup>
+      <name>OFFER</name>
+      <title>Offer</title>
+      <icon>VAADIN:CART</icon>
+      <active v="false" />
+      <idColumn>OFFERID</idColumn>
+      <titleColumn>TITLECOLUMN</titleColumn>
+      <descriptionColumn>DESCCOLUMN</descriptionColumn>
+      <query>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/offer/query.js</query>
+      <resultContextNeon>Offer</resultContextNeon>
+      <affectedTables>
+        <element>OFFER</element>
+      </affectedTables>
+      <affectedIds>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/offer/affectedIds.js</affectedIds>
+    </indexSearchGroup>
+    <indexSearchGroup>
+      <name>SALESORDER</name>
+      <title>Order</title>
+      <icon>VAADIN:DOLLAR</icon>
+      <active v="false" />
+      <idColumn>SALESORDERID</idColumn>
+      <titleColumn>TITLECOLUMN</titleColumn>
+      <descriptionColumn>DESCCOLUMN</descriptionColumn>
+      <query>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/salesorder/query.js</query>
+      <resultContextNeon>Order</resultContextNeon>
+      <affectedTables>
+        <element>SALESORDER</element>
+      </affectedTables>
+      <affectedIds>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/salesorder/affectedIds.js</affectedIds>
+    </indexSearchGroup>
+    <indexSearchGroup>
+      <name>CONTRACT</name>
+      <title>Contract</title>
+      <icon>VAADIN:FILE_TEXT</icon>
+      <active v="false" />
+      <idColumn>CONTRACT</idColumn>
+      <titleColumn>TITLECOLUMN</titleColumn>
+      <descriptionColumn>DESCCOLUMN</descriptionColumn>
+      <resultContextNeon>Contract</resultContextNeon>
+      <affectedTables>
+        <element>CONTRACT</element>
+      </affectedTables>
+      <affectedIds>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/contract/affectedIds.js</affectedIds>
+    </indexSearchGroup>
+    <indexSearchGroup>
+      <name>PRODUCT</name>
+      <title>Product</title>
+      <icon>VAADIN:HAMMER</icon>
+      <active v="false" />
+      <idColumn>PRODUCT</idColumn>
+      <titleColumn>TITLECOLUMN</titleColumn>
+      <descriptionColumn>DESCCOLUMN</descriptionColumn>
+      <resultContextNeon>Product</resultContextNeon>
+      <affectedTables>
+        <element>PRODUCT</element>
+      </affectedTables>
+      <affectedIds>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/product/affectedIds.js</affectedIds>
+    </indexSearchGroup>
+    <indexSearchGroup>
+      <name>SALESPROJECT</name>
+      <title>Salesproject</title>
+      <icon>VAADIN:BOOK_DOLLAR</icon>
+      <active v="false" />
+      <idColumn>SALESPROJECT</idColumn>
+      <titleColumn>TITLECOLUMN</titleColumn>
+      <descriptionColumn>DESCCOLUMN</descriptionColumn>
+      <resultContextNeon>Salesproject</resultContextNeon>
+      <affectedTables>
+        <element>SALESPROJECT</element>
+      </affectedTables>
+      <affectedIds>%aditoprj%/aliasDefinition/Data_alias/indexsearchgroups/salesproject/affectedIds.js</affectedIds>
+    </indexSearchGroup>
   </indexSearchGroups>
 </aliasDefinition>
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/contract/affectedIds.js b/aliasDefinition/Data_alias/indexsearchgroups/contract/affectedIds.js
new file mode 100644
index 0000000000000000000000000000000000000000..548f327a66b7b08252086a013c0152cd52f8da20
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/contract/affectedIds.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.object([vars.getString("$local.idvalue")]);
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/offer/affectedIds.js b/aliasDefinition/Data_alias/indexsearchgroups/offer/affectedIds.js
new file mode 100644
index 0000000000000000000000000000000000000000..548f327a66b7b08252086a013c0152cd52f8da20
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/offer/affectedIds.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.object([vars.getString("$local.idvalue")]);
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/offer/query.js b/aliasDefinition/Data_alias/indexsearchgroups/offer/query.js
new file mode 100644
index 0000000000000000000000000000000000000000..d8bff6962ee6476f616c9cb6a66304bfae3d35b2
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/offer/query.js
@@ -0,0 +1,22 @@
+import("system.result");
+import("system.vars");
+import("system.calendars");
+import("system.db");
+import("Sql_lib");
+
+var sqlQuery, sqlHelper, queryCondition, affectedIds;
+if (vars.exists("$local.idvalue")) {
+    affectedIds = vars.get("$local.idvalue");
+    queryCondition = "where OFFERID in ('" + affectedIds.map(function (v){return db.quote(v);}).join("', '") + "')";
+    //TODO: refactor this for incremental indexer (injections?)
+}
+sqlHelper = new SqlMaskingUtils();
+sqlQuery = "select OFFERID, " 
+    + "OFFERCODE as TITLECOLUMN, " 
+    + sqlHelper.concat(["ORGNAME", "'| Kd-Nr.: '", "CUSTOMERCODE"]) 
+    + " as DESCCOLUMN, OFFERCODE, ORGNAME, CUSTOMERCODE " 
+    + " from OFFER "
+    + " join CONTACT on OFFER.CONTACT_ID = CONTACTID "
+    + " join ORGANISATION on ORGANISATIONID = CONTACT.ORGANISATION_ID "
+    + queryCondition + " order by OFFERCODE ";
+result.string(sqlQuery);
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/product/affectedIds.js b/aliasDefinition/Data_alias/indexsearchgroups/product/affectedIds.js
new file mode 100644
index 0000000000000000000000000000000000000000..548f327a66b7b08252086a013c0152cd52f8da20
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/product/affectedIds.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.object([vars.getString("$local.idvalue")]);
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/salesorder/affectedIds.js b/aliasDefinition/Data_alias/indexsearchgroups/salesorder/affectedIds.js
new file mode 100644
index 0000000000000000000000000000000000000000..548f327a66b7b08252086a013c0152cd52f8da20
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/salesorder/affectedIds.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.object([vars.getString("$local.idvalue")]);
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/salesorder/query.js b/aliasDefinition/Data_alias/indexsearchgroups/salesorder/query.js
new file mode 100644
index 0000000000000000000000000000000000000000..39a1d15028db2e6dd488e391a63d6d3d51cc52de
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/salesorder/query.js
@@ -0,0 +1,22 @@
+import("system.result");
+import("system.vars");
+import("system.calendars");
+import("system.db");
+import("Sql_lib");
+
+var sqlQuery, sqlHelper, queryCondition, affectedIds;
+if (vars.exists("$local.idvalue")) {
+    affectedIds = vars.get("$local.idvalue");
+    queryCondition = "where OFFERID in ('" + affectedIds.map(function (v){return db.quote(v);}).join("', '") + "')";
+    //TODO: refactor this for incremental indexer (injections?)
+}
+sqlHelper = new SqlMaskingUtils();
+sqlQuery = "select SALESORDERID, " 
+    + " ORDERCODE as TITLECOLUMN, " 
+    + sqlHelper.concat(["ORGNAME", "'| Kd-Nr.: '", "CUSTOMERCODE"]) 
+    + " as DESCCOLUMN, ORDERCODE, ORGNAME, CUSTOMERCODE "
+    + " from SALESORDER "
+    + " join RELATION on SALESORDER.RELATION_ID = RELATIONID "
+    + " join ORG on ORGID = RELATION.ORG_ID "
+    + queryCondition + " order by ORDERCODE ";
+result.string(sqlQuery);
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/indexsearchgroups/salesproject/affectedIds.js b/aliasDefinition/Data_alias/indexsearchgroups/salesproject/affectedIds.js
new file mode 100644
index 0000000000000000000000000000000000000000..548f327a66b7b08252086a013c0152cd52f8da20
--- /dev/null
+++ b/aliasDefinition/Data_alias/indexsearchgroups/salesproject/affectedIds.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.object([vars.getString("$local.idvalue")]);
\ No newline at end of file
diff --git a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
index 4ca34f853b313081f74d2689ae331dbf806ab883..b476c1e2ecdd5a7cc7a2bb6aca80374bf93915fc 100644
--- a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
+++ b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
@@ -39,7 +39,6 @@
         <node name="Attribute" kind="10077" />
         <node name="KeywordEntry" kind="10077" />
         <node name="KeywordAttribute" kind="10077" />
-        <node name="Salutation" kind="10077" />
         <node name="INTERNAL_ADMINISTRATOR" kind="159" />
       </node>
     </node>
diff --git a/entity/360Degree_entity/360Degree_entity.aod b/entity/360Degree_entity/360Degree_entity.aod
index d46ac9f4dd1574d58bb6978c41038776058851b6..13f96a0d0a6eb7b15b908cd71ef830e36c9c1476 100644
--- a/entity/360Degree_entity/360Degree_entity.aod
+++ b/entity/360Degree_entity/360Degree_entity.aod
@@ -60,6 +60,73 @@
       <groupable v="true" />
       <valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/context_name/valueProcess.js</valueProcess>
     </entityField>
+    <entityField>
+      <name>DATE</name>
+      <title>Date</title>
+      <contentType>DATE</contentType>
+    </entityField>
+    <entityProvider>
+      <name>PersonObjects</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>1d931ae6-137a-4db3-b02c-eb8872d349c6</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>360DegreeObjects</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityField>
+      <name>YEAR</name>
+      <title>Year</title>
+      <groupable v="true" />
+      <valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/year/valueProcess.js</valueProcess>
+    </entityField>
+    <entityActionGroup>
+      <name>newModule</name>
+      <title>New module</title>
+      <iconId>VAADIN:PLUS_CIRCLE</iconId>
+      <children>
+        <entityActionField>
+          <name>newOffer</name>
+          <fieldType>ACTION</fieldType>
+          <title>Offer</title>
+          <onActionProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newoffer/onActionProcess.js</onActionProcess>
+          <iconId>VAADIN:CART</iconId>
+          <stateProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newoffer/stateProcess.js</stateProcess>
+        </entityActionField>
+        <entityActionField>
+          <name>newSalesproject</name>
+          <fieldType>ACTION</fieldType>
+          <title>Salesproject</title>
+          <onActionProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/onActionProcess.js</onActionProcess>
+          <iconId>VAADIN:BOOK_DOLLAR</iconId>
+          <stateProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/stateProcess.js</stateProcess>
+        </entityActionField>
+        <entityActionField>
+          <name>newContract</name>
+          <fieldType>ACTION</fieldType>
+          <title>Contract</title>
+          <onActionProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newcontract/onActionProcess.js</onActionProcess>
+          <iconId>VAADIN:FILE_TEXT</iconId>
+          <iconIdProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newcontract/iconIdProcess.js</iconIdProcess>
+          <stateProcess>%aditoprj%/entity/360Degree_entity/entityfields/newmodule/children/newcontract/stateProcess.js</stateProcess>
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityField>
+      <name>ICON</name>
+      <contentType>IMAGE</contentType>
+      <searchable v="false" />
+      <valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/icon/valueProcess.js</valueProcess>
+    </entityField>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
@@ -71,6 +138,7 @@
         <element>TARGET_ID.value</element>
         <element>TARGET_CONTEXT.value</element>
         <element>TITLE.value</element>
+        <element>DATE.value</element>
       </recordFields>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/360Degree_entity/entityfields/icon/valueProcess.js b/entity/360Degree_entity/entityfields/icon/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b0bb83e3c5e90e1fd2f90c044fb085ac09d4a35
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/icon/valueProcess.js
@@ -0,0 +1,17 @@
+import("system.vars");
+import("system.result");
+import("system.neon");
+
+var context = vars.getString("$field.TARGET_CONTEXT");
+switch (context)
+{
+    case "Salesproject":
+        result.string("VAADIN:BOOK_DOLLAR");
+        break; 
+    case "Offer":
+        result.string("VAADIN:CART");
+        break;    
+    case "Contract":
+        result.string("VAADIN:FILE_TEXT");
+        break;           
+}
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/newmodule/children/newcontract/onActionProcess.js b/entity/360Degree_entity/entityfields/newmodule/children/newcontract/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c441f436ac1b006d8c653a13d4095207a9752c56
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/newmodule/children/newcontract/onActionProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("Contract_lib");
+import("system.logging");
+
+ContractUtils.createNewContract(vars.getString("$param.ObjectRowId_param"));
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/newmodule/children/newcontract/stateProcess.js b/entity/360Degree_entity/entityfields/newmodule/children/newcontract/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..45d4c0d1cadf0fd4f0a44a660ff1a9a8e481e879
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/newmodule/children/newcontract/stateProcess.js
@@ -0,0 +1,16 @@
+import("system.result");
+import("system.vars");
+import("system.neon");
+import("system.logging");
+    
+var contextList = JSON.parse(vars.getString("$param.ObjectType_param"));
+var found = false;
+contextList.forEach(function (context) 
+{
+    if(context == "Contract")
+        found = true;        
+});
+if(found)
+    result.string(neon.COMPONENTSTATE_AUTO);
+else
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/newmodule/children/newoffer/onActionProcess.js b/entity/360Degree_entity/entityfields/newmodule/children/newoffer/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..0be1b35b781bca3828a99415c0d7dac475792176
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/newmodule/children/newoffer/onActionProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("Offer_lib");
+
+OfferUtils.createNewOffer(null, vars.getString("$param.ObjectRowId_param"));
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/newmodule/children/newoffer/stateProcess.js b/entity/360Degree_entity/entityfields/newmodule/children/newoffer/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..43eff24495608393dc02b1e5d9bfd2c0cae8e116
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/newmodule/children/newoffer/stateProcess.js
@@ -0,0 +1,15 @@
+import("system.vars");
+import("system.neon");
+import("system.result");
+
+var contextList = JSON.parse(vars.getString("$param.ObjectType_param"));
+var found = false;
+contextList.forEach(function (context) 
+{
+    if(context == "Offer")
+        found = true;        
+});
+if(found)
+    result.string(neon.COMPONENTSTATE_AUTO);
+else
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/onActionProcess.js b/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d7426e72df2caec7058f23a716c698e10a848a54
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/onActionProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("Salesproject_lib");
+
+Salesproject.createNewSalesproject(vars.getString("$param.ObjectRowId_param"));
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/stateProcess.js b/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..faec2ba794559373ea139bc95e18d782c01164d0
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/newmodule/children/newsalesproject/stateProcess.js
@@ -0,0 +1,15 @@
+import("system.vars");
+import("system.neon");
+import("system.result");
+
+var contextList = JSON.parse(vars.getString("$param.ObjectType_param"));
+var found = false;
+contextList.forEach(function (context) 
+{
+    if(context == "Salesproject")
+        found = true;        
+});
+if(found)
+    result.string(neon.COMPONENTSTATE_AUTO);
+else
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/AnyContact_entity/entityfields/organisation/children/contactid_param/valueProcess.js b/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
similarity index 52%
rename from entity/AnyContact_entity/entityfields/organisation/children/contactid_param/valueProcess.js
rename to entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
index 7b6137b4d105e9ba592cf8ef6e796fb838a32b09..15de0e1ae47eb721911420272e0952a8d0aab01c 100644
--- a/entity/AnyContact_entity/entityfields/organisation/children/contactid_param/valueProcess.js
+++ b/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.CONTACTID"));
\ No newline at end of file
+result.object(["Offer", "Contract"]);
\ No newline at end of file
diff --git a/entity/360Degree_entity/entityfields/year/valueProcess.js b/entity/360Degree_entity/entityfields/year/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c21dcc8cde6f3f27028dbb1844895cc55f093ff8
--- /dev/null
+++ b/entity/360Degree_entity/entityfields/year/valueProcess.js
@@ -0,0 +1,6 @@
+import("system.datetime");
+import("system.result");
+import("system.vars");
+
+var dateVal = vars.get("$field.DATE");
+result.string(datetime.toDate(dateVal, "yyyy"));
\ No newline at end of file
diff --git a/entity/360Degree_entity/recordcontainers/jdito/contentProcess.js b/entity/360Degree_entity/recordcontainers/jdito/contentProcess.js
index 1f70304a1c22d04dfb39405b9aa7f5d975842e3c..f85cd0bacff82c5ee19ec1f36601666434c9d1f6 100644
--- a/entity/360Degree_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/360Degree_entity/recordcontainers/jdito/contentProcess.js
@@ -11,14 +11,15 @@ if (vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param"
     var contextList = JSON.parse(vars.getString("$param.ObjectType_param"));
     contextList.forEach(function (context) 
     {
-        var data = db.table(ContextUtils.getContextDataSql(context, vars.get("$param.ObjectRowId_param")));
+        var data = db.table(ContextUtils.getContextDataSql(context, vars.get("$param.ObjectRowId_param"), true));
         data.forEach(function (row) 
         {
             var record = [];
-            record[0] = util.getNewUUID();
-            record[1] = row[0];
-            record[2] = context;
-            record[3] = row[1];
+            record[0] = util.getNewUUID(); // UID
+            record[1] = row[0]; // TARGET_ID
+            record[2] = context; // TARGET_CONTEXT
+            record[3] = row[1]; // TITLE
+            record[4] = row[2]; //DATE
             resultList.push(record);
         });       
                   
diff --git a/entity/ActivityLink_entity/ActivityLink_entity.aod b/entity/ActivityLink_entity/ActivityLink_entity.aod
index 34b9c2ad504abfa630a745fbe5f9282db64cfd2a..38ceb851f59ac65172af94abf8c283bfa356914c 100644
--- a/entity/ActivityLink_entity/ActivityLink_entity.aod
+++ b/entity/ActivityLink_entity/ActivityLink_entity.aod
@@ -20,7 +20,7 @@
     </entityField>
     <entityField>
       <name>OBJECT_ROWID</name>
-      <title>Beziehung</title>
+      <title>Relation</title>
       <consumer>Objects</consumer>
       <linkedContextProcess>%aditoprj%/entity/ActivityLink_entity/entityfields/object_rowid/linkedContextProcess.js</linkedContextProcess>
       <displayValueProcess>%aditoprj%/entity/ActivityLink_entity/entityfields/object_rowid/displayValueProcess.js</displayValueProcess>
diff --git a/entity/Activity_entity/Activity_entity.aod b/entity/Activity_entity/Activity_entity.aod
index dc0e95ce40aa8b214bf9f13f02cca8a647aabf06..3f998199e73bd8addc2b6b5bf9a945d68533dcee 100644
--- a/entity/Activity_entity/Activity_entity.aod
+++ b/entity/Activity_entity/Activity_entity.aod
@@ -263,7 +263,7 @@
       <consumer>Contacts</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>
     </entityField>
     <entityConsumer>
       <name>ModuleTrees</name>
diff --git a/entity/Activity_entity/entityfields/creator/displayValueProcess.js b/entity/Activity_entity/entityfields/creator/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..0dde82e7728286629b1c210326725aac2ebb92c5
--- /dev/null
+++ b/entity/Activity_entity/entityfields/creator/displayValueProcess.js
@@ -0,0 +1,8 @@
+import("system.result");
+import("system.vars");
+import("Contact_lib");
+
+var id = vars.get("$this.value");
+//show the simpel title since this will be later an employee-entry and therefore no organisation is needed
+var title = ContactUtils.getTitleByContactId(id);
+result.string(title);
\ No newline at end of file
diff --git a/entity/Activity_entity/entityfields/creator/valueProcess.js b/entity/Activity_entity/entityfields/creator/valueProcess.js
deleted file mode 100644
index fbf6105a85aaeeb73fa5784afaf603d6d650a770..0000000000000000000000000000000000000000
--- a/entity/Activity_entity/entityfields/creator/valueProcess.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import("system.result");
-import("system.vars");
-import("system.neon");
-
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-{
-    result.string(vars.get("$sys.user"));
-}
\ No newline at end of file
diff --git a/entity/Activity_entity/recordcontainers/db/onDBDelete.js b/entity/Activity_entity/recordcontainers/db/onDBDelete.js
index 787c4614c1462768ec4b375d47ef1a79eb2d57d3..3ede97828741f9baed6f5ef05de7d3913953e3fc 100644
--- a/entity/Activity_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Activity_entity/recordcontainers/db/onDBDelete.js
@@ -1,11 +1,8 @@
 import("system.vars");
 import("system.db");
 import("Sql_lib");
-import("Context_lib");
 
 var activityObjectsCondition = SqlCondition.begin()
-                                           .andPrepare("AB_OBJECTRELATION.OBJECT1_TYPE", ContextUtils.getCurrentContextId())
-                                           .andPrepareVars("AB_OBJECTRELATION.OBJECT1_ROWID", "$field.ACTIVITYID");
-
-db.deleteData("AB_OBJECTRELATION", activityObjectsCondition.build("1=2"));
+                                           .andPrepareVars("ACTIVITYLINK.ACTIVITY_ID", "$field.ACTIVITYID");
 
+db.deleteData("ACTIVITYLINK", activityObjectsCondition.build("1=2"));
\ No newline at end of file
diff --git a/entity/AnyContact_entity/AnyContact_entity.aod b/entity/AnyContact_entity/AnyContact_entity.aod
index bd84a0459439912929c80568adf8f0c59af700bc..ef3c7122fe47dc58830ac0cae0f16a7d2a668e72 100644
--- a/entity/AnyContact_entity/AnyContact_entity.aod
+++ b/entity/AnyContact_entity/AnyContact_entity.aod
@@ -88,7 +88,7 @@ See ContactUtils.getRelationTypeByPersOrg for possible values</description>
       <children>
         <entityParameter>
           <name>ContactId_param</name>
-          <valueProcess>%aditoprj%/entity/AnyContact_entity/entityfields/organisation/children/ContactId_param/valueProcess.js</valueProcess>
+          <valueProcess>%aditoprj%/entity/AnyContact_entity/entityfields/organisations/children/contactid_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
     </entityConsumer>
@@ -177,6 +177,7 @@ See ContactUtils.getRelationTypeByPersOrg for possible values</description>
       <name>db</name>
       <alias>Data_alias</alias>
       <fromClauseProcess>%aditoprj%/entity/AnyContact_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
+      <conditionProcess>%aditoprj%/entity/AnyContact_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
       <linkInformation>
         <linkInformation>
           <name>7b3fa460-44a1-40f3-89e3-1625ce9c6bb3</name>
diff --git a/entity/AnyContact_entity/entityfields/contacttype/valueProcess.js b/entity/AnyContact_entity/entityfields/contacttype/valueProcess.js
index 32bb8ca1976dad71cedfc90616c378fce1d9ccde..1974bb4d5a7c88145de2d44d53a22c00ece7aab3 100644
--- a/entity/AnyContact_entity/entityfields/contacttype/valueProcess.js
+++ b/entity/AnyContact_entity/entityfields/contacttype/valueProcess.js
@@ -2,4 +2,4 @@ import("system.result");
 import("system.vars");
 import("Contact_lib")
 
-result.object(ContactUtils.getRelationType(vars.get("$field.CONTACTID"), vars.get("$field.PERSON_ID"), vars.get("$field.ORGANISATION_ID")));
\ No newline at end of file
+result.object(ContactUtils.getContactType(vars.get("$field.CONTACTID"), vars.get("$field.PERSON_ID"), vars.get("$field.ORGANISATION_ID")));
\ No newline at end of file
diff --git a/entity/AnyContact_entity/recordcontainers/db/conditionProcess.js b/entity/AnyContact_entity/recordcontainers/db/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e3e997905f8c97b4a21ca506627746a2b93dbde1
--- /dev/null
+++ b/entity/AnyContact_entity/recordcontainers/db/conditionProcess.js
@@ -0,0 +1,14 @@
+import("system.db");
+import("system.result");
+import("Sql_lib");
+
+//exclude private organisation
+var cond = SqlCondition.begin()
+                       .andPrepare("CONTACT.ORGANISATION_ID", "0", "# != ?")
+                       .orSqlCondition(SqlCondition.begin()
+                                                     .andPrepare("CONTACT.ORGANISATION_ID", "0")
+                                                     .and("CONTACT.PERSON_ID is not null")
+                       );
+                       
+
+result.string(db.translateCondition(cond.build()));
\ No newline at end of file
diff --git a/entity/AnyContact_entity/recordcontainers/db/fromClauseProcess.js b/entity/AnyContact_entity/recordcontainers/db/fromClauseProcess.js
index c2008fc0d19dfe96ca7074d6f2ceddf2c5941f78..7dc4c1aa3f7ef16b0515795e0db3bfd3aabff75a 100644
--- a/entity/AnyContact_entity/recordcontainers/db/fromClauseProcess.js
+++ b/entity/AnyContact_entity/recordcontainers/db/fromClauseProcess.js
@@ -1,4 +1,4 @@
 import("system.result");
 import("Contact_lib")
 
-result.string(ContactUtils.getFullRelationString());
\ No newline at end of file
+result.string(ContactUtils.getFullContactString());
\ No newline at end of file
diff --git a/entity/AppointmentLink_entity/AppointmentLink_entity.aod b/entity/AppointmentLink_entity/AppointmentLink_entity.aod
index 47911cce2a6a948fc2303ff76b18693c7cab17cc..85253e14442fa406698eee283d0fbb431d56c75c 100644
--- a/entity/AppointmentLink_entity/AppointmentLink_entity.aod
+++ b/entity/AppointmentLink_entity/AppointmentLink_entity.aod
@@ -1,121 +1,132 @@
-<?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
-  <name>AppointmentLink_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-      <recordContainer>db</recordContainer>
-    </entityProvider>
-    <entityField>
-      <name>AB_APPOINTMENTLINKID</name>
-      <valueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/ab_appointmentlinkid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>APPOINTMENT_ID</name>
-      <valueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/appointment_id/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>OBJECTID</name>
-      <consumer>Objects</consumer>
-      <linkedContext>Object_context</linkedContext>
-    </entityField>
-    <entityField>
-      <name>OBJECTTYPE</name>
-      <consumer>Context</consumer>
-      <linkedContext>Context_context</linkedContext>
-      <displayValueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/objecttype/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityParameter>
-      <name>AppointmentId_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityProvider>
-      <name>Links</name>
-      <fieldType>DEPENDENCY_IN</fieldType>
-      <targetContextField>OBJECTTYPE</targetContextField>
-      <targetIdField>OBJECTID</targetIdField>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>3dde1745-18a1-4499-83d0-61e414086997</name>
-          <entityName>Appointment_entity</entityName>
-          <fieldName>AppointmentLinks</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>AppointmentId_param</name>
-          <expose v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityConsumer>
-      <name>Context</name>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Context_entity</entityName>
-        <fieldName>#PROVIDER</fieldName>
-      </dependency>
-    </entityConsumer>
-    <entityConsumer>
-      <name>Objects</name>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Object_entity</entityName>
-        <fieldName>AllObjects</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>ObjectType_param</name>
-          <valueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/objects/children/objecttype_param/valueProcess.js</valueProcess>
-          <expose v="true" />
-          <triggerRecalculation v="true" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <conditionProcess>%aditoprj%/entity/AppointmentLink_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <linkInformation>
-        <linkInformation>
-          <name>211047ab-be9d-401b-a2d9-3dd1e048c5c5</name>
-          <tableName>AB_APPOINTMENTLINK</tableName>
-          <primaryKey>AB_APPOINTMENTLINK_ID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>APPOINTMENT_ID.value</name>
-          <recordfield>AB_APPOINTMENTLINK.APPOINTMENT_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>OBJECTID.value</name>
-          <recordfield>AB_APPOINTMENTLINK.OBJECT_ROWID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>OBJECTTYPE.value</name>
-          <recordfield>AB_APPOINTMENTLINK.OBJECT_TYPE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>OBJECTID.displayValue</name>
-          <expression>%aditoprj%/entity/AppointmentLink_entity/recordcontainers/db/recordfieldmappings/objectid.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>AB_APPOINTMENTLINKID.value</name>
-          <recordfield>AB_APPOINTMENTLINK.AB_APPOINTMENTLINK_ID</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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
+  <name>AppointmentLink_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+      <recordContainer>db</recordContainer>
+    </entityProvider>
+    <entityField>
+      <name>AB_APPOINTMENTLINKID</name>
+      <valueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/ab_appointmentlinkid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>APPOINTMENT_ID</name>
+      <valueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/appointment_id/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>OBJECTID</name>
+      <consumer>Objects</consumer>
+      <linkedContext>Object</linkedContext>
+      <displayValueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/objectid/displayValueProcess.js</displayValueProcess>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>OBJECTTYPE</name>
+      <consumer>Context</consumer>
+      <linkedContext>Context</linkedContext>
+      <displayValueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/objecttype/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityParameter>
+      <name>AppointmentId_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>Links</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <targetContextField>OBJECTTYPE</targetContextField>
+      <targetIdField>OBJECTID</targetIdField>
+      <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>3dde1745-18a1-4499-83d0-61e414086997</name>
+          <entityName>Appointment_entity</entityName>
+          <fieldName>AppointmentLinks</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>AppointmentId_param</name>
+          <expose v="true" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityConsumer>
+      <name>Context</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Context_entity</entityName>
+        <fieldName>#PROVIDER</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>Objects</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Object_entity</entityName>
+        <fieldName>AllObjects</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <valueProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/objects/children/objecttype_param/valueProcess.js</valueProcess>
+          <expose v="true" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityActionField>
+      <name>opencontext</name>
+      <fieldType>ACTION</fieldType>
+      <onActionProcess>%aditoprj%/entity/AppointmentLink_entity/entityfields/opencontext/onActionProcess.js</onActionProcess>
+    </entityActionField>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <conditionProcess>%aditoprj%/entity/AppointmentLink_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <linkInformation>
+        <linkInformation>
+          <name>211047ab-be9d-401b-a2d9-3dd1e048c5c5</name>
+          <tableName>AB_APPOINTMENTLINK</tableName>
+          <primaryKey>AB_APPOINTMENTLINK_ID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>APPOINTMENT_ID.value</name>
+          <recordfield>AB_APPOINTMENTLINK.APPOINTMENT_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECTID.value</name>
+          <recordfield>AB_APPOINTMENTLINK.OBJECT_ROWID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECTTYPE.value</name>
+          <recordfield>AB_APPOINTMENTLINK.OBJECT_TYPE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECTID.displayValue</name>
+          <expression>%aditoprj%/entity/AppointmentLink_entity/recordcontainers/db/recordfieldmappings/objectid.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>AB_APPOINTMENTLINKID.value</name>
+          <recordfield>AB_APPOINTMENTLINK.AB_APPOINTMENTLINK_ID</recordfield>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/AppointmentLink_entity/entityfields/objectid/displayValueProcess.js b/entity/AppointmentLink_entity/entityfields/objectid/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..48efd9fecbbd7b0c6e7b15e44e1269dc2eb976a4
--- /dev/null
+++ b/entity/AppointmentLink_entity/entityfields/objectid/displayValueProcess.js
@@ -0,0 +1,8 @@
+import("system.logging");
+import("system.db");
+import("system.vars");
+import("system.result");
+import("Context_lib")
+
+logging.log("name??")
+result.string(db.cell(ContextUtils.getNameSql(vars.get("$field.OBJECTTYPE"), vars.get("$field.OBJECTID"))));
\ No newline at end of file
diff --git a/entity/AppointmentLink_entity/entityfields/objecttype/displayValueProcess.js b/entity/AppointmentLink_entity/entityfields/objecttype/displayValueProcess.js
index bc84d07a9f8ab6e9bbfde0de443cd0322a26a69b..9e7fb9a949fc371e06d22408fb69bf998b9488e7 100644
--- a/entity/AppointmentLink_entity/entityfields/objecttype/displayValueProcess.js
+++ b/entity/AppointmentLink_entity/entityfields/objecttype/displayValueProcess.js
@@ -1,9 +1,11 @@
-import("system.result");
-import("system.neon");
-import("system.vars");
-import("system.project");
-
-if (vars.exists("$field.OBJECTTYPE") && vars.get("$field.OBJECTTYPE"))
-{
-    result.string(project.getDataModel(project.DATAMODEL_KIND_CONTEXT, vars.get("$field.OBJECTTYPE"))[1]);
+import("system.logging");
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("system.project");
+
+if (vars.exists("$field.OBJECTTYPE") && vars.get("$field.OBJECTTYPE"))
+{
+    logging.log("objecttype value: " + project.getDataModel(project.DATAMODEL_KIND_CONTEXT, vars.get("$field.OBJECTTYPE"))[1]);
+    result.string(project.getDataModel(project.DATAMODEL_KIND_CONTEXT, vars.get("$field.OBJECTTYPE"))[1]);
 }
\ No newline at end of file
diff --git a/entity/AppointmentLink_entity/entityfields/opencontext/onActionProcess.js b/entity/AppointmentLink_entity/entityfields/opencontext/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..961eba99f12d553ebe624d8a5e8aa2adb588da7f
--- /dev/null
+++ b/entity/AppointmentLink_entity/entityfields/opencontext/onActionProcess.js
@@ -0,0 +1,5 @@
+import("system.logging");
+
+
+
+logging.log("derp");
\ No newline at end of file
diff --git a/entity/Appointment_entity/Appointment_entity.aod b/entity/Appointment_entity/Appointment_entity.aod
index afc0d976212f4f029d428c480c6c525e1aec5161..e3b7b3400b609b86fe891656b8e27eb602407f90 100644
--- a/entity/Appointment_entity/Appointment_entity.aod
+++ b/entity/Appointment_entity/Appointment_entity.aod
@@ -1,200 +1,206 @@
-<?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
-  <name>Appointment_entity</name>
-  <title>Termin</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/Appointment_entity/documentation.adoc</documentation>
-  <recordContainer>jdito</recordContainer>
-  <entityFields>
-    <entityField>
-      <name>SUMMARY</name>
-      <title>Betreff</title>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/summary/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>DESCRIPTION</name>
-    </entityField>
-    <entityField>
-      <name>CLASSIFICATION</name>
-      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/classification/possibleItemsProcess.js</possibleItemsProcess>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/classification/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>BEGIN</name>
-      <selectionMode>SINGLE</selectionMode>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/begin/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>END</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/end/valueProcess.js</valueProcess>
-    </entityField>
-    <entityFieldGroup>
-      <name>STARTEND</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/startend/valueProcess.js</valueProcess>
-      <description>FIELDGROUP</description>
-      <fields>
-        <element>BEGIN</element>
-        <element>END</element>
-      </fields>
-    </entityFieldGroup>
-    <entityField>
-      <name>STATUS</name>
-      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/status/possibleItemsProcess.js</possibleItemsProcess>
-    </entityField>
-    <entityField>
-      <name>LOCATION</name>
-    </entityField>
-    <entityField>
-      <name>REMINDER_CHECK</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/reminder_check/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>REMINDER</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/reminder/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>CATEGORIES</name>
-      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/categories/possibleItemsProcess.js</possibleItemsProcess>
-    </entityField>
-    <entityField>
-      <name>ATTENDEES</name>
-      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/attendees/possibleItemsProcess.js</possibleItemsProcess>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/attendees/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>TRANSPARENCY</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/transparency/valueProcess.js</valueProcess>
-    </entityField>
-    <entityActionGroup>
-      <name>PartStatActionGroup</name>
-      <children>
-        <entityActionField>
-          <name>accept</name>
-          <fieldType>ACTION</fieldType>
-          <title>accept</title>
-          <onActionProcess>%aditoprj%/entity/Appointment_entity/entityfields/partstatactiongroup/children/accept/onActionProcess.js</onActionProcess>
-          <actionOrder v="0" />
-          <iconId>VAADIN:CHECK</iconId>
-        </entityActionField>
-        <entityActionField>
-          <name>decline</name>
-          <fieldType>ACTION</fieldType>
-          <title>decline</title>
-          <description></description>
-          <onActionProcess>%aditoprj%/entity/Appointment_entity/entityfields/partstatactiongroup/children/decline/onActionProcess.js</onActionProcess>
-          <iconId>VAADIN:CLOSE</iconId>
-        </entityActionField>
-        <entityActionField>
-          <name>tentative</name>
-          <fieldType>ACTION</fieldType>
-          <title>tentative</title>
-          <onActionProcess>%aditoprj%/entity/Appointment_entity/entityfields/partstatactiongroup/children/tentative/onActionProcess.js</onActionProcess>
-          <iconId>VAADIN:QUESTION</iconId>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
-    <entityProvider>
-      <name>#PROVIDER</name>
-      <recordContainer>jdito</recordContainer>
-    </entityProvider>
-    <entityParameter>
-      <name>MasterEntry_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityField>
-      <name>ORGANIZER</name>
-    </entityField>
-    <entityField>
-      <name>RRULE</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/rrule/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>RECURRENCEID</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/recurrenceid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>SAFESCOPEFIELD</name>
-    </entityField>
-    <entityField>
-      <name>MASTERBEGIN</name>
-    </entityField>
-    <entityField>
-      <name>MASTEREND</name>
-    </entityField>
-    <entityField>
-      <name>UID</name>
-      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/uid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>ATTENDEESLENGTH</name>
-    </entityField>
-    <entityField>
-      <name>ICON</name>
-    </entityField>
-    <entityParameter>
-      <name>Entry_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>AnyObjectRowid_param</name>
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>AnyObjectType_param</name>
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityConsumer>
-      <name>AppointmentLinks</name>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>AppointmentLink_entity</entityName>
-        <fieldName>Links</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>AppointmentId_param</name>
-          <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/appointmentlinks/children/appointmentid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-  </entityFields>
-  <recordContainers>
-    <jDitoRecordContainer>
-      <name>jdito</name>
-      <title>jdito</title>
-      <description></description>
-      <jDitoRecordAlias>_____SYSTEMALIAS</jDitoRecordAlias>
-      <contentProcess>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
-      <onInsert>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onInsert.js</onInsert>
-      <onUpdate>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
-      <onDelete>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onDelete.js</onDelete>
-      <recordFields>
-        <element>UID.value</element>
-        <element>ATTENDEESLENGTH.value</element>
-        <element>BEGIN.value</element>
-        <element>END.value</element>
-        <element>SUMMARY.value</element>
-        <element>ORGANIZER.value</element>
-        <element>ATTENDEES.value</element>
-        <element>STATUS.value</element>
-        <element>LINKS.value</element>
-        <element>DESCRIPTION.value</element>
-        <element>LOCATION.value</element>
-        <element>ICON.value</element>
-        <element>CLASSIFICATION.value</element>
-        <element>TRANSPARENCY.value</element>
-        <element>CATEGORIES.value</element>
-        <element>REMINDER.value</element>
-        <element>REMINDER_CHECK.value</element>
-        <element>RRULE.value</element>
-        <element>RECURRENCEID.value</element>
-        <element>SAFESCOPEFIELD.value</element>
-        <element>MASTERBEGIN.value</element>
-        <element>MASTEREND.value</element>
-      </recordFields>
-    </jDitoRecordContainer>
-  </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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
+  <name>Appointment_entity</name>
+  <title>Termin</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/Appointment_entity/documentation.adoc</documentation>
+  <afterUiInit>%aditoprj%/entity/Appointment_entity/afterUiInit.js</afterUiInit>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityField>
+      <name>SUMMARY</name>
+      <title>Betreff</title>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/summary/valueProcess.js</valueProcess>
+      <onValueChange>%aditoprj%/entity/Appointment_entity/entityfields/summary/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>DESCRIPTION</name>
+    </entityField>
+    <entityField>
+      <name>CLASSIFICATION</name>
+      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/classification/possibleItemsProcess.js</possibleItemsProcess>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/classification/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>BEGIN</name>
+      <selectionMode>SINGLE</selectionMode>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/begin/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>END</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/end/valueProcess.js</valueProcess>
+    </entityField>
+    <entityFieldGroup>
+      <name>STARTEND</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/startend/valueProcess.js</valueProcess>
+      <description>FIELDGROUP</description>
+      <fields>
+        <element>BEGIN</element>
+        <element>END</element>
+      </fields>
+    </entityFieldGroup>
+    <entityField>
+      <name>STATUS</name>
+      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/status/possibleItemsProcess.js</possibleItemsProcess>
+    </entityField>
+    <entityField>
+      <name>LOCATION</name>
+    </entityField>
+    <entityField>
+      <name>REMINDER_CHECK</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/reminder_check/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>REMINDER</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/reminder/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>CATEGORIES</name>
+      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/categories/possibleItemsProcess.js</possibleItemsProcess>
+    </entityField>
+    <entityField>
+      <name>ATTENDEES</name>
+      <possibleItemsProcess>%aditoprj%/entity/Appointment_entity/entityfields/attendees/possibleItemsProcess.js</possibleItemsProcess>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/attendees/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>TRANSPARENCY</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/transparency/valueProcess.js</valueProcess>
+    </entityField>
+    <entityActionGroup>
+      <name>PartStatActionGroup</name>
+      <children>
+        <entityActionField>
+          <name>accept</name>
+          <fieldType>ACTION</fieldType>
+          <title>accept</title>
+          <onActionProcess>%aditoprj%/entity/Appointment_entity/entityfields/partstatactiongroup/children/accept/onActionProcess.js</onActionProcess>
+          <actionOrder v="0" />
+          <iconId>VAADIN:CHECK</iconId>
+        </entityActionField>
+        <entityActionField>
+          <name>decline</name>
+          <fieldType>ACTION</fieldType>
+          <title>decline</title>
+          <description></description>
+          <onActionProcess>%aditoprj%/entity/Appointment_entity/entityfields/partstatactiongroup/children/decline/onActionProcess.js</onActionProcess>
+          <iconId>VAADIN:CLOSE</iconId>
+        </entityActionField>
+        <entityActionField>
+          <name>tentative</name>
+          <fieldType>ACTION</fieldType>
+          <title>tentative</title>
+          <onActionProcess>%aditoprj%/entity/Appointment_entity/entityfields/partstatactiongroup/children/tentative/onActionProcess.js</onActionProcess>
+          <iconId>VAADIN:QUESTION</iconId>
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityProvider>
+      <name>#PROVIDER</name>
+      <recordContainer>jdito</recordContainer>
+    </entityProvider>
+    <entityParameter>
+      <name>MasterEntry_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>ORGANIZER</name>
+    </entityField>
+    <entityField>
+      <name>RRULE</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/rrule/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>RECURRENCEID</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/recurrenceid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>SAFESCOPEFIELD</name>
+    </entityField>
+    <entityField>
+      <name>MASTERBEGIN</name>
+    </entityField>
+    <entityField>
+      <name>MASTEREND</name>
+    </entityField>
+    <entityField>
+      <name>UID</name>
+      <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/uid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>ATTENDEESLENGTH</name>
+    </entityField>
+    <entityField>
+      <name>ICON</name>
+    </entityField>
+    <entityParameter>
+      <name>Entry_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>AnyObjectRowid_param</name>
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>AnyObjectType_param</name>
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityConsumer>
+      <name>AppointmentLinks</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AppointmentLink_entity</entityName>
+        <fieldName>Links</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>AppointmentId_param</name>
+          <valueProcess>%aditoprj%/entity/Appointment_entity/entityfields/appointmentlinks/children/appointmentid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <title>jdito</title>
+      <description></description>
+      <jDitoRecordAlias>_____SYSTEMALIAS</jDitoRecordAlias>
+      <contentProcess>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
+      <onInsert>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onInsert.js</onInsert>
+      <onUpdate>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
+      <onDelete>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onDelete.js</onDelete>
+      <recordFields>
+        <element>UID.value</element>
+        <element>ATTENDEESLENGTH.value</element>
+        <element>BEGIN.value</element>
+        <element>END.value</element>
+        <element>SUMMARY.value</element>
+        <element>ORGANIZER.value</element>
+        <element>ATTENDEES.value</element>
+        <element>STATUS.value</element>
+        <element>LINKS.value</element>
+        <element>DESCRIPTION.value</element>
+        <element>LOCATION.value</element>
+        <element>ICON.value</element>
+        <element>CLASSIFICATION.value</element>
+        <element>TRANSPARENCY.value</element>
+        <element>CATEGORIES.value</element>
+        <element>REMINDER.value</element>
+        <element>REMINDER_CHECK.value</element>
+        <element>RRULE.value</element>
+        <element>RECURRENCEID.value</element>
+        <element>SAFESCOPEFIELD.value</element>
+        <element>MASTERBEGIN.value</element>
+        <element>MASTEREND.value</element>
+      </recordFields>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/Appointment_entity/afterUiInit.js b/entity/Appointment_entity/afterUiInit.js
new file mode 100644
index 0000000000000000000000000000000000000000..c47e48d2310d87c55d94dc8b4a9632fca4bc4fb4
--- /dev/null
+++ b/entity/Appointment_entity/afterUiInit.js
@@ -0,0 +1,23 @@
+import("system.util");
+import("system.neon");
+import("system.logging");
+import("system.vars");
+
+
+
+
+if(vars.exists("$param.Entry_param") && vars.get("$param.Entry_param"))
+{
+    var entry = JSON.parse(vars.getString("$param.Entry_param"));
+   
+    if(entry["AppLinkContext"] && entry["AppLinkId"])
+    {
+        logging.log("hier geht lohos... " + vars.get("$field.UID") + " id");
+        neon.addRecord(null, "AppointmentLinks",
+        {
+            "AB_APPOINTMENTLINKID" : util.getNewUUID(),
+            "OBJECTID" : entry["AppLinkId"],
+            "OBJECTTYPE" : entry["AppLinkContext"]
+        });
+    }
+}
\ No newline at end of file
diff --git a/entity/Appointment_entity/entityfields/classification/valueProcess.js b/entity/Appointment_entity/entityfields/classification/valueProcess.js
index a4056b88346388dc049b7dbcf191192c0ce66b57..a0ff98e63f4682ef482963598bde2d3efc7bf7ac 100644
--- a/entity/Appointment_entity/entityfields/classification/valueProcess.js
+++ b/entity/Appointment_entity/entityfields/classification/valueProcess.js
@@ -1,15 +1,16 @@
-import("system.neon");
-import("system.vars");
-import("system.calendars");
-import("system.result");
-
-/**
- * Following if() is only for passing param-parts from "new Appointment"-Dialog to AppointmentEditViewTemplate
- */
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.Entry_param"))
-{
-    var event = JSON.parse(vars.getString("$param.Entry_param"));
-
-    if(event[calendars.CLASSIFICATION])
-        result.string(event[calendars.CLASSIFICATION]);
+import("system.logging");
+import("system.neon");
+import("system.vars");
+import("system.calendars");
+import("system.result");
+
+/**
+ * Following if() is only for passing param-parts from "new Appointment"-Dialog to AppointmentEditViewTemplate
+ */
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.Entry_param"))
+{
+    var event = JSON.parse(vars.getString("$param.Entry_param"));
+
+    if(event[calendars.CLASSIFICATION])
+        result.string(event[calendars.CLASSIFICATION]);
 }
\ No newline at end of file
diff --git a/entity/Appointment_entity/entityfields/contexts/children/contextid_param/valueProcess.js b/entity/Appointment_entity/entityfields/contexts/children/contextid_param/valueProcess.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/Appointment_entity/entityfields/objects/children/objecttype_param/valueProcess.js b/entity/Appointment_entity/entityfields/objects/children/objecttype_param/valueProcess.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/Appointment_entity/entityfields/summary/onValueChange.js b/entity/Appointment_entity/entityfields/summary/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c77a90fc3af3a8375d03d5fe6e2ca4634f0027a
--- /dev/null
+++ b/entity/Appointment_entity/entityfields/summary/onValueChange.js
@@ -0,0 +1,10 @@
+import("system.neon");
+import("system.vars");
+import("system.calendars");
+
+
+//var entry = JSON.parse(vars.get("$param.Entry_param"));
+//
+//entry[calendars.SUMMARY] = vars.get("$field.SUMMARY");
+//
+//neon.setFieldValue("$param.Entry_param", JSON.stringify(entry));
\ No newline at end of file
diff --git a/entity/Appointment_entity/entityfields/summary/valueProcess.js b/entity/Appointment_entity/entityfields/summary/valueProcess.js
index 432475ace31148f4466c021837b49896e0a6fc45..72d7fc725df6d67b5d6a30d236fb0b87094d287f 100644
--- a/entity/Appointment_entity/entityfields/summary/valueProcess.js
+++ b/entity/Appointment_entity/entityfields/summary/valueProcess.js
@@ -1,15 +1,18 @@
-import("system.neon");
-import("system.vars");
-import("system.calendars");
-import("system.result");
-
-/**
- * Following if() is only for passing param-parts from "new Appointment"-Dialog to AppointmentEditViewTemplate
- */
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.Entry_param"))
-{
-    var event = JSON.parse(vars.getString("$param.Entry_param"));
-
-    if(event[calendars.SUMMARY])
-        result.string(event[calendars.SUMMARY]);
+import("system.logging");
+import("system.neon");
+import("system.vars");
+import("system.calendars");
+import("system.result");
+
+/**
+ * Following if() is only for passing param-parts from "new Appointment"-Dialog to AppointmentEditViewTemplate
+ */
+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])
+        result.string(event[calendars.SUMMARY]);
 }
\ No newline at end of file
diff --git a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
index 89cded5903cc0c176708c92758c37d19b9f8191a..af31672dba1ba87218dc4487e0e379d5dd731dee 100644
--- a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
@@ -1,73 +1,87 @@
-import("system.result");
-import("system.vars");
-import("system.calendars");
-import("system.datetime");
-import("system.eMath");
-import("system.util");
-
-if(vars.exists("$param.Entry_param") && vars.get("$param.Entry_param"))
-{
-
-    var entry = JSON.parse(vars.getString("$param.Entry_param"));
-
-    var masterEntry = null;
-    if (vars.exists("$param.MasterEntry_param") && vars.get("$param.MasterEntry_param") != "") {
-        masterEntry = JSON.parse(vars.get("$param.MasterEntry_param"));
-    }
-
-    var uid = entry[calendars.ID];    
-    var summary = entry[calendars.SUMMARY];
-    var attendees = entry[calendars.AFFECTEDUSERS];
-    var startdate = entry[calendars.DTSTART];
-    var enddate = entry[calendars.DTEND];
-    var links = entry[calendars.LINKS];
-    var description = entry[calendars.DESCRIPTION];
-    var organizer = entry[calendars.ORGANIZER2]["paramvalue"];
-    var status = entry[calendars.STATUS];
-    var location = entry[calendars.LOCATION];
-    var reminder = entry[calendars.REMINDER_DURATION];
-    var remindercheck = entry[calendars.HASREMINDER]
-    var classification = entry[calendars.CLASSIFICATION];
-    var transparency = entry[calendars.TRANSPARENCY];
-    var categories = entry[calendars.CATEGORIES];
-    
-    var masterBegin = masterEntry != null ? masterEntry[calendars.DTSTART] : null
-    var masterEnd = masterEntry != null ? masterEntry[calendars.DTEND] : null
-    
-    // Recurrence
-    var recurrenceID = entry[calendars.RECURRENCEID];
-    var rrule = null;
-    if (masterEntry != null) { // Entry is a recurrence exception, therefore get rrule from master
-        rrule = masterEntry[calendars.RRULE] != null ? masterEntry[calendars.RRULE][0] : null;
-    } else {
-        rrule = entry[calendars.RRULE] != null ? entry[calendars.RRULE][0] : null;
-    }
-   
-    //@TODO Icon 
-    result.object([
-        [
-            uid, 
-            attendees.length, 
-            startdate, 
-            enddate, 
-            summary, 
-            organizer,
-            attendees, 
-            status, 
-            links, 
-            description, 
-            location, 
-            '', 
-            classification,
-            transparency, 
-            categories, 
-            reminder, 
-            remindercheck, 
-            rrule, 
-            recurrenceID, 
-            null, 
-            masterBegin, 
-            masterEnd
-        ]
-    ]);
-}
+import("system.result");
+import("system.vars");
+import("system.calendars");
+import("system.datetime");
+import("system.eMath");
+import("system.util");
+import("system.neon");
+
+if(vars.exists("$param.Entry_param") && vars.get("$param.Entry_param"))
+{
+
+    var entry = JSON.parse(vars.getString("$param.Entry_param"));
+
+    var masterEntry = null;
+    if (vars.exists("$param.MasterEntry_param") && vars.get("$param.MasterEntry_param") != "") {
+        masterEntry = JSON.parse(vars.get("$param.MasterEntry_param"));
+    }
+
+    var uid = entry[calendars.ID];    
+    var summary = entry[calendars.SUMMARY];
+    var attendees = entry[calendars.AFFECTEDUSERS];
+    var startdate = entry[calendars.DTSTART];
+    var enddate = entry[calendars.DTEND];
+    var links = entry[calendars.LINKS];
+    var description = entry[calendars.DESCRIPTION];
+    if(entry[calendars.ORGANIZER2] != undefined)
+        var organizer = entry[calendars.ORGANIZER2]["paramvalue"];
+    var status = entry[calendars.STATUS];
+    var location = entry[calendars.LOCATION];
+    var reminder = entry[calendars.REMINDER_DURATION];
+    var remindercheck = entry[calendars.HASREMINDER]
+    var classification = entry[calendars.CLASSIFICATION];
+    var transparency = entry[calendars.TRANSPARENCY];
+    var categories = entry[calendars.CATEGORIES];
+    
+    var masterBegin = masterEntry != null ? masterEntry[calendars.DTSTART] : null
+    var masterEnd = masterEntry != null ? masterEntry[calendars.DTEND] : null
+    
+    // Recurrence
+    var recurrenceID = entry[calendars.RECURRENCEID];
+    var rrule = null;
+    if (masterEntry != null) { // Entry is a recurrence exception, therefore get rrule from master
+        rrule = masterEntry[calendars.RRULE] != null ? masterEntry[calendars.RRULE][0] : null;
+    } else {
+        rrule = entry[calendars.RRULE] != null ? entry[calendars.RRULE][0] : null;
+    }
+    
+//    if(entry["AppLinkContext"] && entry["AppLinkId"])
+//    {
+//        logging.log("hier geht lohos... " + uid + " id");
+//        neon.addRecord(null, "AppointmentLinks",
+//        {
+//            "AB_APPOINTMENTLINKID" : util.getNewUUID(),
+//            "APPOINTMENT_ID" : vars.get("$field.UID"),
+//            "OBJECTID" : entry["AppLinkId"],
+//            "OBJECTTYPE" : entry["AppLinkContext"]
+//        });
+//    }
+   
+    //@TODO Icon 
+    result.object([
+        [
+            uid, 
+            attendees.length, 
+            startdate, 
+            enddate, 
+            summary, 
+            organizer,
+            attendees, 
+            status, 
+            links, 
+            description, 
+            location, 
+            '', 
+            classification,
+            transparency, 
+            categories, 
+            reminder, 
+            remindercheck, 
+            rrule, 
+            recurrenceID, 
+            null, 
+            masterBegin, 
+            masterEnd
+        ]
+    ]);
+}
diff --git a/entity/Appointment_entity/recordcontainers/jdito/onInsert.js b/entity/Appointment_entity/recordcontainers/jdito/onInsert.js
index d6ebfc2d5a16e8c2688ca133370cfeef3821a1e7..5c063693c6fe59f12d0b9c64fb27fbbfdb91856f 100644
--- a/entity/Appointment_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/Appointment_entity/recordcontainers/jdito/onInsert.js
@@ -1,291 +1,293 @@
-import("system.neon");
-import("system.calendars");
-import("system.vars");
-import("system.question");
-import("system.translate");
-import("system.text");
-import("system.datetime");
-import("system.db");
-import("system.result");
-import("system.tools");
-
-var event = JSON.parse(vars.getString("$param.Entry_param"));
-
-event[calendars.TYPE] = calendars.VEVENT;
-event[calendars.ID] = ""; //wenn hier neue id erstellt und mitgegeben wird, wird versucht einen termin mit dieser id zu finden, den es nicht gibt. also leer.
-event[calendars.AFFECTEDUSERS] = vars.get("$field.ATTENDEES");
-event[calendars.STATUS] = vars.getString("$field.STATUS");
-event[calendars.SUMMARY] = vars.getString("$field.SUMMARY");
-event[calendars.LOCATION] = vars.get("$field.LOCATION");
-event[calendars.DESCRIPTION] = vars.get("$field.DESCRIPTION");
-event[calendars.DTSTART] = vars.get("$field.BEGIN");
-event[calendars.DTEND] = vars.get("$field.END");
-event[calendars.CLASSIFICATION] = vars.get("$field.CLASSIFICATION");
-event[calendars.TRANSPARENCY] = vars.get("$field.TRANSPARENCY"); 
-event[calendars.CATEGORIES] = vars.get("$field.CATEGORIES");
-if(vars.get("$field.RRULE"))
-    event[calendars.RRULE] = [vars.get("$field.RRULE")];
-if (vars.get("$field.REMINDER") != undefined && vars.get("$field.REMINDER") != "")
-{
-    event[calendars.HASREMINDER] = "true";
-    event[calendars.REMINDER_DURATION] = vars.get("$field.REMINDER");
-}
-var idstringarray = calendars.insert([event]);
-event[calendars.ID] = idstringarray[0];
-vars.set("$context.editmode", calendars.MODE_UPDATE);
-
-
-
-// Liefert die Benutzer zurück, auf die keine Schreibrechte bestehen
-function getReadOnlyUser()
-{
-    var writeable = calendars.getFullCalendarUsers(calendars.RIGHT_WRITE);	
-    var affectedusers = vars.get("$context.affectedusers");
-    var readonly = new Array();
-
-    for ( i = 0; i < affectedusers.length; i++)
-    {
-        var user = affectedusers[i][0];
-        if (!isWriteable(user, writeable))
-            readonly.push(affectedusers[i][3]);
-    }	
-    return readonly;	
-}
-
-// Liefert TRUE, wenn der Benutzer bei denen mit Schreibberechtigungen enthalten ist
-function isWriteable(user, writeable)
-{
-    for (var i = 0; i < writeable.length; i++)
-    {
-        if (writeable[i][0] == calendars.getCalendarUser(user))		
-            return true;
-    }	
-    return false;
-}
-
-// Berechnet das Ende der Recurrence
-function recurrencend(event)
-{
-    var rec_end = vars.getString("$field.rec_end");
-
-    // Automatische Erkennung, was gewollt ist
-    if (rec_end == "")
-    {
-        if (vars.get("$field.rec_end_count") != "")
-            rec_end = "Endet nach Anzahl Terminen";
-        else if (vars.get("$field.rec_end_date") != "")
-            rec_end = "Endet am";
-    }
-
-    if (rec_end == "" || rec_end == "Kein Enddatum")
-    {
-    // Nichts
-    }
-    else if (rec_end == "Endet nach Anzahl Terminen")
-    {
-        event[calendars.RRULE][0] += (";COUNT=" + vars.get("$field.rec_end_count"));
-    }
-    else if (rec_end == "Endet am")
-    {
-        var dat = vars.get("$field.rec_end_date");
-        var start = vars.get("$field.start_date");
-        var localTime = datetime.toDate(dat, translate.text("yyyyMMdd")) + datetime.toDate(start, "HHmmss");
-        var utcTime = datetime.toLong(localTime, "yyyyMMddHHmmss");
-        event[calendars.RRULE][0] += (";UNTIL=" + datetime.toDate(utcTime, "yyyyMMdd\'T\'HHmmss\'Z\'", "UTC"));
-    }
-}
-
-/**
- * Berechnet die Wiederholung
- *
- * @param event Das fertige Event. Hier die Reccurrence speichern
- */
-function calcrecurrence(event)
-{
-    var rec_type = vars.get("$field.rec_type");
-
-    if (rec_type == "")
-    {
-    // Nichts
-    }
-    else if (rec_type == "Keine")
-    {
-    }
-    else if (rec_type == "Täglich")
-    {
-        rec_daily(event);
-    }
-    else if (rec_type == "Wöchentlich")
-    {
-        rec_weekly(event);
-    }
-    else if (rec_type == "Monatlich")
-    {
-        rec_monthly(event);
-    }
-    else if (rec_type == "Jährlich")
-    {
-        rec_yearly(event);
-    }
-    else
-    {
-        question.showMessage("Internal (1) " + rec_type);
-    }
-}
-/***********************/
-function rec_yearly(event)
-{
-    var rec_year = vars.get("$field.rec_yearly");
-    var rec_yearly_month = vars.get("$field.rec_yearly_month");
-    var rec_yearly_day = vars.get("$field.rec_yearly_day");
-    var month;
-    var day;
-
-    if (rec_year == "")
-    {
-        if (rec_yearly_month != "" && rec_yearly_day != "")
-            rec_year = "Jeden # #";
-        else if (rec_yearly_month != "" && vars.get("$field.rec_yearly_day2") != "" && vars.get("$field.rec_yearly_number2") != "")
-            rec_year = "Am #. # im #";
-    }
-
-    if (rec_year == "" || (rec_yearly_month == "" && rec_yearly_day == "" ))
-    {
-        question.showMessage(translate.text("yearly series not specified"));
-    }
-    else if (rec_year == "Jeden # #")
-    {
-        month = rec_yearly_month;
-        day = rec_yearly_day;
-        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTHDAY="+day+";BYMONTH="+month);
-    }
-    else if (rec_year == "Am #. # im #")
-    {
-        month = vars.get("$field.rec_yearly_month2");
-        day = vars.get("$field.rec_yearly_day2");
-        var number = vars.get("$field.rec_yearly_number2");
-        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTH="+month+";BYDAY="+number+day);
-    }
-}
-/***********************/
-function rec_monthly(event)
-{
-    var rec_month = vars.get("$field.rec_month");
-    var rec_monthly_day = vars.get("$field.rec_monthly_day");
-    var rec_monthly_interval = vars.get("$field.rec_monthly_interval");
-    var day;
-    var interval;
-
-    if (rec_month == "")
-
-    {
-        if (rec_monthly_day != "" && rec_monthly_interval != "")
-            rec_month = "Am #. jedes #. Monat";
-        else if (vars.get("$field.rec_monthly_day2") != "" && vars.get("$field.rec_monthly_interval2") != "" && vars.get("$field.rec_monthly_weekday2") != "")
-            rec_month = "Am #. # jeden #. Monat";
-    }
-
-    if (rec_month == "" || (rec_monthly_day == "" && rec_monthly_interval != ""))
-    {
-        question.showMessage(translate.text("Ignore series"));
-    }
-    else if (rec_month == "Am #. jedes #. Monat")
-    {
-        day = rec_monthly_day;
-        interval = rec_monthly_interval;
-        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYMONTHDAY=" + day);
-    }
-    else if(rec_month == "Am #. # jeden #. Monat")
-    {
-        day = vars.get("$field.rec_monthly_day2");
-        interval = vars.get("$field.rec_monthly_interval2");
-        var weekday = vars.get("$field.rec_monthly_weekday2");
-        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYDAY=" + day + weekday);
-    }
-}
-/***********************/
-function rec_weekly(event)
-{
-
-    var rec_weekly_intervall = vars.get("$field.rec_weekly_intervall");
-    if (rec_weekly_intervall == "")
-        rec_weekly_intervall = "1";
-
-    var days = new Array();
-    var count = 0;
-    if (vars.get("$field.rec_weekly_mo") == "true")
-    {
-        days[count] = "MO";
-        count++;
-    }
-    if (vars.get("$field.rec_weekly_di") == "true")
-    {
-        days[count] = "TU";
-        count++;
-    }
-    if (vars.get("$field.rec_weekly_mi") == "true")
-    {
-        days[count] = "WE";
-        count++;
-    }
-    if (vars.get("$field.rec_weekly_do") == "true")
-    {
-        days[count] = "TH";
-        count++;
-    }
-    if (vars.get("$field.rec_weekly_fr") == "true")
-    {
-        days[count] = "FR";
-        count++;
-    }
-    if (vars.get("$field.rec_weekly_sa") == "true")
-    {
-        days[count] = "SA";
-        count++;
-    }
-    if (vars.get("$field.rec_weekly_so") == "true")
-    {
-        days[count] = "SU";
-        count++;
-    }
-    if (count > 0)
-    {
-        event[calendars.RRULE] = new Array("FREQ=WEEKLY;INTERVAL=" + rec_weekly_intervall + ";WKST=MO;BYDAY=");
-        for (var i = 0; i < count; i++)
-        {
-            event[calendars.RRULE][0] += days[i];
-            if (i+1 < count)
-            {
-                event[calendars.RRULE][0] += ",";
-            }
-        }
-    }
-}
-/***********************/
-function rec_daily(event)
-{
-    var rec_dailytype = vars.get("$field.rec_dailytype");
-    var rec_dailydays = vars.get("$field.rec_daily_days");
-    if (rec_dailytype == "")
-    {
-        if (rec_dailydays != "")
-            rec_dailytype = "Alle # Tage";
-    }
-
-    if (rec_dailytype == "" || rec_dailydays == "")
-    {
-        question.showMessage(translate.text("Ignore daily series"));
-    }
-    else if (rec_dailytype == "Alle # Tage")
-    {
-        event[calendars.RRULE] = new Array("FREQ=DAILY;INTERVAL=" + rec_dailydays);
-    }
-    else if (rec_dailytype == "Jeden Arbeitstag")
-    {
-        event[calendars.RRULE][0] = new Array("FREQ=WEEKLY;WKST=MO;BYDAY=MO,TU,WE,TH,FR");
-    }
-    else
-    {
-        question.showMessage(translate.text("Internal (2)") + " " + rec_dailytype);
-    }
+import("system.neon");
+import("system.calendars");
+import("system.vars");
+import("system.question");
+import("system.translate");
+import("system.text");
+import("system.datetime");
+import("system.db");
+import("system.result");
+import("system.tools");
+
+var event = JSON.parse(vars.getString("$param.Entry_param"));
+
+event[calendars.TYPE] = calendars.VEVENT;
+event[calendars.ID] = ""; //wenn hier neue id erstellt und mitgegeben wird, wird versucht einen termin mit dieser id zu finden, den es nicht gibt. also leer.
+event[calendars.AFFECTEDUSERS] = vars.get("$field.ATTENDEES");
+event[calendars.STATUS] = vars.getString("$field.STATUS");
+//event[calendars.SUMMARY] = vars.getString("$field.SUMMARY");
+event[calendars.LOCATION] = vars.get("$field.LOCATION");
+event[calendars.DESCRIPTION] = vars.get("$field.DESCRIPTION");
+event[calendars.DTSTART] = vars.get("$field.BEGIN");
+event[calendars.DTEND] = vars.get("$field.END");
+event[calendars.CLASSIFICATION] = vars.get("$field.CLASSIFICATION");
+event[calendars.TRANSPARENCY] = vars.get("$field.TRANSPARENCY"); 
+event[calendars.CATEGORIES] = vars.get("$field.CATEGORIES");
+if(vars.get("$field.RRULE"))
+    event[calendars.RRULE] = [vars.get("$field.RRULE")];
+if (vars.get("$field.REMINDER") != undefined && vars.get("$field.REMINDER") != "")
+{
+    event[calendars.HASREMINDER] = "true";
+    event[calendars.REMINDER_DURATION] = vars.get("$field.REMINDER");
+}
+var idstringarray = calendars.insert([event]);
+event[calendars.ID] = idstringarray[0];
+neon.setFieldValue("$field.UID", event[calendars.ID]);
+
+vars.set("$context.editmode", calendars.MODE_UPDATE);
+
+
+
+// Liefert die Benutzer zurück, auf die keine Schreibrechte bestehen
+function getReadOnlyUser()
+{
+    var writeable = calendars.getFullCalendarUsers(calendars.RIGHT_WRITE);	
+    var affectedusers = vars.get("$context.affectedusers");
+    var readonly = new Array();
+
+    for ( i = 0; i < affectedusers.length; i++)
+    {
+        var user = affectedusers[i][0];
+        if (!isWriteable(user, writeable))
+            readonly.push(affectedusers[i][3]);
+    }	
+    return readonly;	
+}
+
+// Liefert TRUE, wenn der Benutzer bei denen mit Schreibberechtigungen enthalten ist
+function isWriteable(user, writeable)
+{
+    for (var i = 0; i < writeable.length; i++)
+    {
+        if (writeable[i][0] == calendars.getCalendarUser(user))		
+            return true;
+    }	
+    return false;
+}
+
+// Berechnet das Ende der Recurrence
+function recurrencend(event)
+{
+    var rec_end = vars.getString("$field.rec_end");
+
+    // Automatische Erkennung, was gewollt ist
+    if (rec_end == "")
+    {
+        if (vars.get("$field.rec_end_count") != "")
+            rec_end = "Endet nach Anzahl Terminen";
+        else if (vars.get("$field.rec_end_date") != "")
+            rec_end = "Endet am";
+    }
+
+    if (rec_end == "" || rec_end == "Kein Enddatum")
+    {
+    // Nichts
+    }
+    else if (rec_end == "Endet nach Anzahl Terminen")
+    {
+        event[calendars.RRULE][0] += (";COUNT=" + vars.get("$field.rec_end_count"));
+    }
+    else if (rec_end == "Endet am")
+    {
+        var dat = vars.get("$field.rec_end_date");
+        var start = vars.get("$field.start_date");
+        var localTime = datetime.toDate(dat, translate.text("yyyyMMdd")) + datetime.toDate(start, "HHmmss");
+        var utcTime = datetime.toLong(localTime, "yyyyMMddHHmmss");
+        event[calendars.RRULE][0] += (";UNTIL=" + datetime.toDate(utcTime, "yyyyMMdd\'T\'HHmmss\'Z\'", "UTC"));
+    }
+}
+
+/**
+ * Berechnet die Wiederholung
+ *
+ * @param event Das fertige Event. Hier die Reccurrence speichern
+ */
+function calcrecurrence(event)
+{
+    var rec_type = vars.get("$field.rec_type");
+
+    if (rec_type == "")
+    {
+    // Nichts
+    }
+    else if (rec_type == "Keine")
+    {
+    }
+    else if (rec_type == "Täglich")
+    {
+        rec_daily(event);
+    }
+    else if (rec_type == "Wöchentlich")
+    {
+        rec_weekly(event);
+    }
+    else if (rec_type == "Monatlich")
+    {
+        rec_monthly(event);
+    }
+    else if (rec_type == "Jährlich")
+    {
+        rec_yearly(event);
+    }
+    else
+    {
+        question.showMessage("Internal (1) " + rec_type);
+    }
+}
+/***********************/
+function rec_yearly(event)
+{
+    var rec_year = vars.get("$field.rec_yearly");
+    var rec_yearly_month = vars.get("$field.rec_yearly_month");
+    var rec_yearly_day = vars.get("$field.rec_yearly_day");
+    var month;
+    var day;
+
+    if (rec_year == "")
+    {
+        if (rec_yearly_month != "" && rec_yearly_day != "")
+            rec_year = "Jeden # #";
+        else if (rec_yearly_month != "" && vars.get("$field.rec_yearly_day2") != "" && vars.get("$field.rec_yearly_number2") != "")
+            rec_year = "Am #. # im #";
+    }
+
+    if (rec_year == "" || (rec_yearly_month == "" && rec_yearly_day == "" ))
+    {
+        question.showMessage(translate.text("yearly series not specified"));
+    }
+    else if (rec_year == "Jeden # #")
+    {
+        month = rec_yearly_month;
+        day = rec_yearly_day;
+        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTHDAY="+day+";BYMONTH="+month);
+    }
+    else if (rec_year == "Am #. # im #")
+    {
+        month = vars.get("$field.rec_yearly_month2");
+        day = vars.get("$field.rec_yearly_day2");
+        var number = vars.get("$field.rec_yearly_number2");
+        event[calendars.RRULE] = new Array("FREQ=YEARLY;BYMONTH="+month+";BYDAY="+number+day);
+    }
+}
+/***********************/
+function rec_monthly(event)
+{
+    var rec_month = vars.get("$field.rec_month");
+    var rec_monthly_day = vars.get("$field.rec_monthly_day");
+    var rec_monthly_interval = vars.get("$field.rec_monthly_interval");
+    var day;
+    var interval;
+
+    if (rec_month == "")
+
+    {
+        if (rec_monthly_day != "" && rec_monthly_interval != "")
+            rec_month = "Am #. jedes #. Monat";
+        else if (vars.get("$field.rec_monthly_day2") != "" && vars.get("$field.rec_monthly_interval2") != "" && vars.get("$field.rec_monthly_weekday2") != "")
+            rec_month = "Am #. # jeden #. Monat";
+    }
+
+    if (rec_month == "" || (rec_monthly_day == "" && rec_monthly_interval != ""))
+    {
+        question.showMessage(translate.text("Ignore series"));
+    }
+    else if (rec_month == "Am #. jedes #. Monat")
+    {
+        day = rec_monthly_day;
+        interval = rec_monthly_interval;
+        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYMONTHDAY=" + day);
+    }
+    else if(rec_month == "Am #. # jeden #. Monat")
+    {
+        day = vars.get("$field.rec_monthly_day2");
+        interval = vars.get("$field.rec_monthly_interval2");
+        var weekday = vars.get("$field.rec_monthly_weekday2");
+        event[calendars.RRULE] = new Array("FREQ=MONTHLY;INTERVAL=" + interval + ";BYDAY=" + day + weekday);
+    }
+}
+/***********************/
+function rec_weekly(event)
+{
+
+    var rec_weekly_intervall = vars.get("$field.rec_weekly_intervall");
+    if (rec_weekly_intervall == "")
+        rec_weekly_intervall = "1";
+
+    var days = new Array();
+    var count = 0;
+    if (vars.get("$field.rec_weekly_mo") == "true")
+    {
+        days[count] = "MO";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_di") == "true")
+    {
+        days[count] = "TU";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_mi") == "true")
+    {
+        days[count] = "WE";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_do") == "true")
+    {
+        days[count] = "TH";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_fr") == "true")
+    {
+        days[count] = "FR";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_sa") == "true")
+    {
+        days[count] = "SA";
+        count++;
+    }
+    if (vars.get("$field.rec_weekly_so") == "true")
+    {
+        days[count] = "SU";
+        count++;
+    }
+    if (count > 0)
+    {
+        event[calendars.RRULE] = new Array("FREQ=WEEKLY;INTERVAL=" + rec_weekly_intervall + ";WKST=MO;BYDAY=");
+        for (var i = 0; i < count; i++)
+        {
+            event[calendars.RRULE][0] += days[i];
+            if (i+1 < count)
+            {
+                event[calendars.RRULE][0] += ",";
+            }
+        }
+    }
+}
+/***********************/
+function rec_daily(event)
+{
+    var rec_dailytype = vars.get("$field.rec_dailytype");
+    var rec_dailydays = vars.get("$field.rec_daily_days");
+    if (rec_dailytype == "")
+    {
+        if (rec_dailydays != "")
+            rec_dailytype = "Alle # Tage";
+    }
+
+    if (rec_dailytype == "" || rec_dailydays == "")
+    {
+        question.showMessage(translate.text("Ignore daily series"));
+    }
+    else if (rec_dailytype == "Alle # Tage")
+    {
+        event[calendars.RRULE] = new Array("FREQ=DAILY;INTERVAL=" + rec_dailydays);
+    }
+    else if (rec_dailytype == "Jeden Arbeitstag")
+    {
+        event[calendars.RRULE][0] = new Array("FREQ=WEEKLY;WKST=MO;BYDAY=MO,TU,WE,TH,FR");
+    }
+    else
+    {
+        question.showMessage(translate.text("Internal (2)") + " " + rec_dailytype);
+    }
 }
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/AttributeRelation_entity.aod b/entity/AttributeRelation_entity/AttributeRelation_entity.aod
index cabd4f0e481e979f64fc0a81d86a0e0ec125941a..e257ce32b6f4ecc06cfc62b9e8b5ca5f84d8b1fc 100644
--- a/entity/AttributeRelation_entity/AttributeRelation_entity.aod
+++ b/entity/AttributeRelation_entity/AttributeRelation_entity.aod
@@ -99,6 +99,7 @@
     <entityParameter>
       <name>ObjectRowId_param</name>
       <expose v="true" />
+      <triggerRecalculation v="true" />
       <description>PARAMETER</description>
     </entityParameter>
     <entityField>
diff --git a/entity/AttributeRelation_entity/entityfields/ab_attribute_id/displayValueProcess.js b/entity/AttributeRelation_entity/entityfields/ab_attribute_id/displayValueProcess.js
index 7375ee03d22b48d48e19926a0ad891be06cc2aec..acda6626ab40309e259438b0dca6da54219b99ec 100644
--- a/entity/AttributeRelation_entity/entityfields/ab_attribute_id/displayValueProcess.js
+++ b/entity/AttributeRelation_entity/entityfields/ab_attribute_id/displayValueProcess.js
@@ -2,4 +2,6 @@ import("system.vars");
 import("system.result");
 import("Attribute_lib");
 
-result.string(AttributeUtil.getFullAttributeName(vars.get("$field.AB_ATTRIBUTE_ID")));
\ No newline at end of file
+result.string(AttributeUtil.getFullAttributeName(
+        vars.get("$field.AB_ATTRIBUTE_ID"),
+        vars.exists("$param.DisplaySimpleName_param") ? vars.get("$param.DisplaySimpleName_param") : false ));
\ No newline at end of file
diff --git a/entity/AttributeRelation_entity/recordcontainers/db/conditionProcess.js b/entity/AttributeRelation_entity/recordcontainers/db/conditionProcess.js
index aee41089141ec40518d13418f789ecc3a54b5e2e..623fac4157f0adf965683447e178916aedffc2a6 100644
--- a/entity/AttributeRelation_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/AttributeRelation_entity/recordcontainers/db/conditionProcess.js
@@ -1,14 +1,17 @@
+import("system.logging");
 import("system.vars");
 import("system.db");
 import("system.result");
 import("Sql_lib");
 
-
-
 var cond = SqlCondition.begin()
                    .andPrepareVars("AB_ATTRIBUTERELATION.OBJECT_ROWID", "$param.ObjectRowId_param");
 
-if (vars.exists("$param.FilteredAttributeIds_param") && vars.get("$param.FilteredAttributeIds_param"))
+if (vars.exists("$param.ObjectRowId_param"))
+    logging.log(vars.get("$param.ObjectRowId_param"))
+
+if (vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param")
+    && vars.exists("$param.FilteredAttributeIds_param") && vars.get("$param.FilteredAttributeIds_param"))
 {
     var filteredIds = JSON.parse(vars.get("$param.FilteredAttributeIds_param"));
     var filteredIdsCondition = new SqlCondition();
diff --git a/entity/AttributeUsage_entity/AttributeUsage_entity.aod b/entity/AttributeUsage_entity/AttributeUsage_entity.aod
index 18af22e8347ed37d6c604134d7aab2e9c3e12216..db802200adca400fc289e7fa8cdbe26d38fcf352 100644
--- a/entity/AttributeUsage_entity/AttributeUsage_entity.aod
+++ b/entity/AttributeUsage_entity/AttributeUsage_entity.aod
@@ -13,7 +13,12 @@
       <name>OBJECT_TYPE</name>
       <title>Module</title>
       <consumer>Context</consumer>
+      <valueProcess>%aditoprj%/entity/AttributeUsage_entity/entityfields/object_type/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/AttributeUsage_entity/entityfields/object_type/displayValueProcess.js</displayValueProcess>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+      </onValueChangeTypes>
     </entityField>
     <entityField>
       <name>AB_ATTRIBUTEUSAGEID</name>
@@ -71,6 +76,9 @@
       <name>db</name>
       <alias>Data_alias</alias>
       <conditionProcess>%aditoprj%/entity/AttributeUsage_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <onDBInsert>%aditoprj%/entity/AttributeUsage_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
+      <onDBUpdate>%aditoprj%/entity/AttributeUsage_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
+      <onDBDelete>%aditoprj%/entity/AttributeUsage_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
         <linkInformation>
           <name>c30f5670-580e-4621-95dd-0fec4a99190f</name>
diff --git a/entity/AttributeUsage_entity/entityfields/ab_attribute_id/valueProcess.js b/entity/AttributeUsage_entity/entityfields/ab_attribute_id/valueProcess.js
index c3a2248b66e14317873bfcff446f25abac69686a..9efed36fc2699e14e3c6f4baa4cd4c62ceef938e 100644
--- a/entity/AttributeUsage_entity/entityfields/ab_attribute_id/valueProcess.js
+++ b/entity/AttributeUsage_entity/entityfields/ab_attribute_id/valueProcess.js
@@ -3,4 +3,6 @@ import("system.result");
 import("system.neon");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.AttributeId_param") && vars.get("$param.AttributeId_param") != null)
-    result.string(vars.get("$param.AttributeId_param"));
\ No newline at end of file
+    result.string(vars.get("$param.AttributeId_param"));
+else if (vars.get("$field.AB_ATTRIBUTE_ID"))
+    result.string(vars.get("$field.AB_ATTRIBUTE_ID"));
\ No newline at end of file
diff --git a/entity/AttributeUsage_entity/entityfields/object_type/valueProcess.js b/entity/AttributeUsage_entity/entityfields/object_type/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..40b7c76fc5515aeb4d2e88c54f0bbe9daf403618
--- /dev/null
+++ b/entity/AttributeUsage_entity/entityfields/object_type/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+
+//this is a workaround to get the old value in the onDBUpdate process
+//@TODO replace this when it's possible to get the old value in onDBUpdate
+vars.set("$context.originalObjectType", vars.get("$field.OBJECT_TYPE"));
\ No newline at end of file
diff --git a/entity/AttributeUsage_entity/recordcontainers/db/onDBDelete.js b/entity/AttributeUsage_entity/recordcontainers/db/onDBDelete.js
new file mode 100644
index 0000000000000000000000000000000000000000..b41e99cd82af7be8fd94faddd41fda7feb3e733e
--- /dev/null
+++ b/entity/AttributeUsage_entity/recordcontainers/db/onDBDelete.js
@@ -0,0 +1,7 @@
+import("system.vars");
+import("Attribute_lib");
+
+var attributeId = vars.get("$field.AB_ATTRIBUTE_ID");
+var objectType = vars.get("$field.OBJECT_TYPE");
+
+AttributeUsageUtil.deleteChildrenUsages(attributeId, objectType);
\ No newline at end of file
diff --git a/entity/AttributeUsage_entity/recordcontainers/db/onDBInsert.js b/entity/AttributeUsage_entity/recordcontainers/db/onDBInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..73c28f291697502a3d36b35e3b5878ecefdf14a1
--- /dev/null
+++ b/entity/AttributeUsage_entity/recordcontainers/db/onDBInsert.js
@@ -0,0 +1,8 @@
+import("system.vars");
+import("Attribute_lib");
+
+var attributeId = vars.get("$field.AB_ATTRIBUTE_ID");
+var objectType = vars.get("$field.OBJECT_TYPE");
+
+AttributeUsageUtil.insertChildrenUsages(attributeId, objectType);
+AttributeUsageUtil.removeDuplicates(attributeId);
\ No newline at end of file
diff --git a/entity/AttributeUsage_entity/recordcontainers/db/onDBUpdate.js b/entity/AttributeUsage_entity/recordcontainers/db/onDBUpdate.js
new file mode 100644
index 0000000000000000000000000000000000000000..02890f1b92c8da2fd1f5849ad7855337ba6148ed
--- /dev/null
+++ b/entity/AttributeUsage_entity/recordcontainers/db/onDBUpdate.js
@@ -0,0 +1,9 @@
+import("system.vars");
+import("Attribute_lib");
+
+var attributeId = vars.get("$field.AB_ATTRIBUTE_ID");
+var oldObjectType = vars.get("$context.originalObjectType");
+var newObjectType = vars.get("$field.OBJECT_TYPE");
+
+AttributeUsageUtil.updateChildrenUsages(attributeId, oldObjectType, newObjectType);
+AttributeUsageUtil.removeDuplicates(attributeId);
\ No newline at end of file
diff --git a/entity/Attribute_entity/afterUiInit.js b/entity/Attribute_entity/afterUiInit.js
index f36f9fbc0eb68caa31ed5b1e78c6508976364ffb..87febc93d555370828def178d66937ba02b37a7e 100644
--- a/entity/Attribute_entity/afterUiInit.js
+++ b/entity/Attribute_entity/afterUiInit.js
@@ -3,13 +3,15 @@ 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");
diff --git a/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js b/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
index b768fb2fba7336e45a6e5c99d6224d9e623d4e5b..f663dddf570f4246c8ae5babd6035026d2bc2ffc 100644
--- a/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
+++ b/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
@@ -3,10 +3,29 @@ import("system.neon");
 import("system.result");
 import("system.vars");
 import("Attribute_lib");
+import("Sql_lib");
 
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$field.ATTRIBUTE_PARENT_ID") != "")
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+var state = neon.COMPONENTSTATE_AUTO
+if (type == $AttributeTypes.COMBOVALUE)
 {
-    var type = AttributeHandler.begin(vars.get("$field.ATTRIBUTE_PARENT_ID")).getAttributeType();
-    if (type == $AttributeTypes.COMBO)
-        result.string(neon.COMPONENTSTATE_INVISIBLE);
-}
\ No newline at end of file
+    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;
+
+result.string(state)
\ No newline at end of file
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 f2318723e88440808277d20753657fb7674a0d0f..b68489b6e02b29d34ae67b14c7371f985305f014 100644
--- a/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attributechildren/children/attrparentid_param/valueProcess.js
@@ -1,4 +1,7 @@
 import("system.vars");
 import("system.result");
+import("Attribute_lib");
 
-result.string(vars.getString("$field.AB_ATTRIBUTEID"));
+var type = vars.get("$field.ATTRIBUTE_TYPE").trim();
+if (type == $AttributeTypes.GROUP || type == $AttributeTypes.COMBO)
+    result.string(vars.getString("$field.AB_ATTRIBUTEID"));
diff --git a/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js b/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js
index 372decd8620b90d3e722f96f362c01b947eb6a32..fe18eca06c7f87d798bd3e58c7726058b5bf049f 100644
--- a/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/attributechildren/children/attrparenttype_param/valueProcess.js
@@ -1,10 +1,4 @@
-import("system.neon");
 import("system.vars");
 import("system.result");
 
-var type;
-if (vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW)
-    type = "GETGROUPS";
-else
-    type = vars.getString("$field.ATTRIBUTE_TYPE").trim()
-result.string(type);
+result.string(vars.getString("$field.ATTRIBUTE_TYPE").trim());
diff --git a/entity/Attribute_entity/entityfields/keyword_container/stateProcess.js b/entity/Attribute_entity/entityfields/keyword_container/stateProcess.js
index 9ce13917b56c5c8e51f01876f47c5cb1f625ec85..67de95ea15b0707ce1a44627ba5a60b92cb5e917 100644
--- a/entity/Attribute_entity/entityfields/keyword_container/stateProcess.js
+++ b/entity/Attribute_entity/entityfields/keyword_container/stateProcess.js
@@ -4,9 +4,9 @@ import("system.result");
 import("Attribute_lib");
 
 var fieldState;
-if (vars.get("$field.ATTRIBUTE_TYPE").trim() == $AttributeTypes.KEYWORD)
+if (vars.get("$field.ATTRIBUTE_TYPE").trim() == $AttributeTypes.KEYWORD && !AttributeUtil.hasRelations(vars.get("$field.AB_ATTRIBUTEID")))
     fieldState = neon.COMPONENTSTATE_EDITABLE;
 else
-    fieldState = neon.COMPONENTSTATE_DISABLED;
+    fieldState = neon.COMPONENTSTATE_READONLY;
 
 result.string(fieldState);
\ 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 0192da48ac5fb006f40737067207ddf9043604a0..675da9521dc245e23992c051dc34239c6f262963 100644
--- a/entity/Attribute_entity/entityfields/usagelist/valueProcess.js
+++ b/entity/Attribute_entity/entityfields/usagelist/valueProcess.js
@@ -3,10 +3,16 @@ import("system.result");
 import("system.db");
 import("system.vars");
 import("Sql_lib");
+import("Attribute_lib");
 
-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"));
-var usageStr = translate.text("Usage");
+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(", ");
+}
 
-result.string(usages.length ? usageStr + ": " + usages.join(", ") : "\u00A0"); // \u00A0 -> space character that doesn't get trimmed 
\ No newline at end of file
+result.string(retStr);
\ No newline at end of file
diff --git a/entity/Contact_entity/Contact_entity.aod b/entity/Contact_entity/Contact_entity.aod
index 7174d343ea4d734b05ba63093bb5c090fe9e21dc..866f81d40bdb74084bd1dd7933b0ab590bd7e960 100644
--- a/entity/Contact_entity/Contact_entity.aod
+++ b/entity/Contact_entity/Contact_entity.aod
@@ -19,6 +19,7 @@
       <consumer>Organisations</consumer>
       <mandatory v="true" />
       <displayValueProcess>%aditoprj%/entity/Contact_entity/entityfields/organisation_id/displayValueProcess.js</displayValueProcess>
+      <onValidation>%aditoprj%/entity/Contact_entity/entityfields/organisation_id/onValidation.js</onValidation>
       <onValueChange>%aditoprj%/entity/Contact_entity/entityfields/organisation_id/onValueChange.js</onValueChange>
     </entityField>
     <entityField>
@@ -31,14 +32,20 @@
     <entityField>
       <name>DEPARTMENT</name>
       <title>Department</title>
+      <possibleItemsProcess>%aditoprj%/entity/Contact_entity/entityfields/department/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
     </entityField>
     <entityField>
       <name>POSITION</name>
       <title>Position</title>
+      <possibleItemsProcess>%aditoprj%/entity/Contact_entity/entityfields/position/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
     </entityField>
     <entityField>
       <name>CONTACTROLE</name>
       <title>Contactrole</title>
+      <possibleItemsProcess>%aditoprj%/entity/Contact_entity/entityfields/contactrole/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
     </entityField>
     <entityConsumer>
       <name>Organisations</name>
@@ -46,13 +53,17 @@
       <dependency>
         <name>dependency</name>
         <entityName>Organisation_entity</entityName>
-        <fieldName>Organisations</fieldName>
+        <fieldName>WithPersonIdFilter</fieldName>
       </dependency>
       <children>
         <entityParameter>
           <name>WithPrivate_param</name>
           <valueProcess>%aditoprj%/entity/Contact_entity/entityfields/organisations/children/withprivate_param/valueProcess.js</valueProcess>
         </entityParameter>
+        <entityParameter>
+          <name>ExcludeOrganisationsByPersonId</name>
+          <valueProcess>%aditoprj%/entity/Contact_entity/entityfields/organisations/children/excludeorganisationsbypersonid/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
     </entityConsumer>
     <entityParameter>
diff --git a/entity/Contact_entity/entityfields/contactrole/possibleItemsProcess.js b/entity/Contact_entity/entityfields/contactrole/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..96627ddf00215d0598ae85d2452acfd248cbe52a
--- /dev/null
+++ b/entity/Contact_entity/entityfields/contactrole/possibleItemsProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var res = KeywordUtils.getEntryNamesByContainer($KeywordRegistry.contactContactrole()).map(function (e){
+    return [e, e]; //currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+});
+
+result.object(res);
\ No newline at end of file
diff --git a/entity/Contact_entity/entityfields/department/possibleItemsProcess.js b/entity/Contact_entity/entityfields/department/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..77d99fa219eb36618f38dbb344e4a345bb71d331
--- /dev/null
+++ b/entity/Contact_entity/entityfields/department/possibleItemsProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var res = KeywordUtils.getEntryNamesByContainer($KeywordRegistry.contactDepartment()).map(function (e){
+    return [e, e]; //currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+});
+
+result.object(res);
\ No newline at end of file
diff --git a/entity/Contact_entity/entityfields/organisation_id/onValidation.js b/entity/Contact_entity/entityfields/organisation_id/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..1f8c6d2abee5ca29256187efa14767677a418d7b
--- /dev/null
+++ b/entity/Contact_entity/entityfields/organisation_id/onValidation.js
@@ -0,0 +1,25 @@
+import("system.translate");
+import("system.result");
+import("system.db");
+import("system.vars");
+import("Entity_lib");
+import("Sql_lib");
+
+var personId = vars.get("$field.PERSON_ID");
+var organisationId = ProcessHandlingUtils.getOnValidationValue("$field.ORGANISATION_ID");
+
+//workaround for organisationId: $local.value will return the name of the organisation which is not what we want
+//but the field already contains the changed value; so let's load the field instead of the $local.value-variable
+//this is a bug within the ADITO-kernel
+//TODO: change the workaround behaviour when $local.value is retrieved correct
+organisationId = vars.get("$field.ORGANISATION_ID")
+
+if (personId && organisationId)
+{    
+    var alreadyExistantContactId = db.cell(SqlCondition.begin()
+                                                       .andPrepare("CONTACT.PERSON_ID", personId)
+                                                       .andPrepare("CONTACT.ORGANISATION_ID", organisationId)
+                                                       .buildSql("select CONTACT.CONTACTID from CONTACT"));
+    if (alreadyExistantContactId != "")
+        result.string(translate.text("This combination of person and organisation does already exist and can not be created once more."));
+}
\ No newline at end of file
diff --git a/entity/Contact_entity/entityfields/organisations/children/excludeorganisationsbypersonid/valueProcess.js b/entity/Contact_entity/entityfields/organisations/children/excludeorganisationsbypersonid/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b273dc66b2666ffe2198c68cf38f00e4b7817cc2
--- /dev/null
+++ b/entity/Contact_entity/entityfields/organisations/children/excludeorganisationsbypersonid/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+
+var personId = vars.get("$field.PERSON_ID");
+result.string(personId);
\ No newline at end of file
diff --git a/entity/Contact_entity/entityfields/position/possibleItemsProcess.js b/entity/Contact_entity/entityfields/position/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..a86d6820913b759ac976779f9c045378095b6d24
--- /dev/null
+++ b/entity/Contact_entity/entityfields/position/possibleItemsProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var res = KeywordUtils.getEntryNamesByContainer($KeywordRegistry.contactPosition()).map(function (e){
+    return [e, e]; //currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+});
+
+result.object(res);
\ No newline at end of file
diff --git a/entity/Contract_entity/entityfields/contact_id/linkedContextProcess.js b/entity/Contract_entity/entityfields/contact_id/linkedContextProcess.js
index e678b842c5b6cf510473693a355fa7833dcf28e8..2e504d63e3b5a3f71b54b072798b3ad09c50984b 100644
--- a/entity/Contract_entity/entityfields/contact_id/linkedContextProcess.js
+++ b/entity/Contract_entity/entityfields/contact_id/linkedContextProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.result");
 import("Contact_lib");
 
-result.string(ContactUtils.getContextByRelationId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
+result.string(ContactUtils.getContextByContactId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index 4c20b161996addab74b850da340092502fe0ab46..2d451370f2889a9f80d334f7d59f87999c032061 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -21,6 +21,7 @@
       <title>Container</title>
       <mandatory v="true" />
       <possibleItemsProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
       <groupable v="true" />
       <state>READONLY</state>
       <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/stateProcess.js</stateProcess>
diff --git a/entity/ModuleTree_entity/recordcontainers/jdito/contentProcess.js b/entity/ModuleTree_entity/recordcontainers/jdito/contentProcess.js
index 4880654df03ad3c456f15872c6e3a06c5e1bbc59..061d2085b3a286c7af1ab0a50546f54f7d18e15a 100644
--- a/entity/ModuleTree_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/ModuleTree_entity/recordcontainers/jdito/contentProcess.js
@@ -9,7 +9,7 @@ var fixedID = vars.get("$param.ID_param");
 let resArray = [];
 
 // Query root element
-var root = queryRootElement(fixedContextName, fixedID);
+var root = queryRootElement(fixedContextName, fixedID, true);
 if (root !== null) {
     // Push root element
     resArray.push(root);
@@ -73,23 +73,36 @@ function queryChildrenElements (pContextName, pID) {
  * 
  * @param pContextName Context name of the root element.
  * @param pID ID of the root element.
+ * @param pGetFirst start from the first element
  */
-function queryRootElement (pContextName, pID) {
+function queryRootElement (pContextName, pID, pGetFirst) {
     var resultArray;
     if (pContextName === "Task") {
-        resultArray = db.table("select TASKID, PARENT_ID, PARENT_CONTEXT, SUBJECT, DESCRIPTION from TASK where TASKID = '" + pID + "'");
+        resultArray = db.array(db.ROW, "select TASKID, PARENT_ID, PARENT_CONTEXT, SUBJECT, DESCRIPTION from TASK where TASKID = '" + pID + "'");
         if (resultArray.length === 0) {
             return null;
         }
-        
-        return augmentData(resultArray[0], "Task");
+        if (pGetFirst && resultArray[1] && resultArray[2])
+            return queryRootElement(resultArray[2], resultArray[1], pGetFirst);
+        if (pGetFirst)
+        {
+            fixedContextName = "Task";
+            fixedID = resultArray[0];
+        }
+        return augmentData(resultArray, "Task");
     } else if (pContextName === "Activity") {
-        resultArray = db.table("select ACTIVITYID, PARENT_ID, PARENT_CONTEXT, SUBJECT, INFO from ACTIVITY where ACTIVITYID = '" + pID +"'");
+        resultArray = db.array(db.ROW, "select ACTIVITYID, PARENT_ID, PARENT_CONTEXT, SUBJECT, INFO from ACTIVITY where ACTIVITYID = '" + pID +"'");
         if (resultArray.length === 0) {
             return null;
         }
-        
-        return augmentData(resultArray[0], "Activity");
+        if (pGetFirst && resultArray[1] && resultArray[2])
+            return queryRootElement(resultArray[2], resultArray[1], pGetFirst);
+        if (pGetFirst)
+        {
+            fixedContextName = "Activity";
+            fixedID = resultArray[0];
+        }
+        return augmentData(resultArray, "Activity");
     } else {
         return null;
     }
diff --git a/entity/ObjectRelation_entity/entityfields/objects1/children/objecttype_param/code.js b/entity/ObjectRelation_entity/entityfields/objects1/children/objecttype_param/code.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/ObjectRelation_entity/entityfields/targetobjectrowid/valueProcess.js b/entity/ObjectRelation_entity/entityfields/targetobjectrowid/valueProcess.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/ObjectRelation_entity/entityfields/targetobjecttype/valueProcess.js b/entity/ObjectRelation_entity/entityfields/targetobjecttype/valueProcess.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/ObjectTree_entity/recordcontainers/jdito/contentProcess.js b/entity/ObjectTree_entity/recordcontainers/jdito/contentProcess.js
index 19b4227d9653b2fea12ec49da0a70b90b50aa3a5..34ef78477331f19dc8f0ebb899c3b97bfb14454d 100644
--- a/entity/ObjectTree_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/ObjectTree_entity/recordcontainers/jdito/contentProcess.js
@@ -81,7 +81,7 @@ function buildTreeData (pObjectRelations) {
    
    var i = 0;
    for (i = 0; i < pObjectRelations.length; i++) {
-       var currentRelation = pObjectRelations[i];
+       let currentRelation = pObjectRelations[i];
        
        if (relationTypeMapping[currentRelation[0]] === undefined)
            relationTypeMapping[currentRelation[0]] = currentRelation[2];
@@ -89,7 +89,7 @@ function buildTreeData (pObjectRelations) {
    
    var treeRows = []
    for (i = 0; i < pObjectRelations.length; i++) {
-       var currentRelation = pObjectRelations[i];
+       let currentRelation = pObjectRelations[i];
               
        treeRows.push([currentRelation[3], currentRelation[0], currentRelation[4]]);
    }
diff --git a/entity/Object_entity/recordcontainers/jdito/contentProcess.js b/entity/Object_entity/recordcontainers/jdito/contentProcess.js
index fa1404cf0aa5adb9dd28c57581124986ae7deaf5..49ee3565f7153850a52fd919d0ab1e01a1880693 100644
--- a/entity/Object_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Object_entity/recordcontainers/jdito/contentProcess.js
@@ -7,11 +7,11 @@ if (vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param"
 {
     if (vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param"))
     {
-        result.object(db.table(vars.get("$param.ObjectRowId_param"), ContextUtils.getContextDataSql(vars.get("$param.ObjectType_param"), vars.get("$param.ObjectRowId_param"))));
+        result.object(db.table(vars.get("$param.ObjectRowId_param"), ContextUtils.getContextDataSql(vars.get("$param.ObjectType_param"), vars.get("$param.ObjectRowId_param"), false)));
     }
     else
     {
-        result.object(db.table(ContextUtils.getContextDataSql(vars.get("$param.ObjectType_param"))))
+        result.object(db.table(ContextUtils.getContextDataSql(vars.get("$param.ObjectType_param"), undefined, false)))
     }
 } 
 else
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index 92d1a1ff772a548a2f0d3c1ec6386c40b9f633ad..ff52a60e35baa21a25c026c374bfe31f801059e4 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -59,6 +59,7 @@
       <onValueChange>%aditoprj%/entity/Offer_entity/entityfields/contact_id/onValueChange.js</onValueChange>
       <onValueChangeTypes>
         <element>MASK</element>
+        <element>PROCESS</element>
       </onValueChangeTypes>
     </entityField>
     <entityField>
@@ -77,6 +78,7 @@
       <title>Status</title>
       <consumer>KeywordOfferStates</consumer>
       <state>EDITABLE</state>
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/status/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/status/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
diff --git a/entity/Offer_entity/entityfields/activities/children/presetlinks_param/valueProcess.js b/entity/Offer_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
index db35a547ac2cbf60774b6ddb9be4781b81196a68..e4c6c134df6be187331e47d8c2c4d5a9871b7c2b 100644
--- a/entity/Offer_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
+++ b/entity/Offer_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Offer_entity/entityfields/contact_id/linkedContextProcess.js b/entity/Offer_entity/entityfields/contact_id/linkedContextProcess.js
index e678b842c5b6cf510473693a355fa7833dcf28e8..2e504d63e3b5a3f71b54b072798b3ad09c50984b 100644
--- a/entity/Offer_entity/entityfields/contact_id/linkedContextProcess.js
+++ b/entity/Offer_entity/entityfields/contact_id/linkedContextProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.result");
 import("Contact_lib");
 
-result.string(ContactUtils.getContextByRelationId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
+result.string(ContactUtils.getContextByContactId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/language/displayValueProcess.js b/entity/Offer_entity/entityfields/language/displayValueProcess.js
index ac73db4489233522317e7c652d62dd92214388d6..bcbf2118161a42f079dfa6ece4df7fb4d6b6774e 100644
--- a/entity/Offer_entity/entityfields/language/displayValueProcess.js
+++ b/entity/Offer_entity/entityfields/language/displayValueProcess.js
@@ -1,15 +1,12 @@
-import("system.db");
-import("system.translate");
-import("system.result");
-import("system.vars");
-import("Sql_lib");
-
-//if (vars.exists("$param.OfferLanguage_param") && vars.get("$param.OfferLanguage_param")) 
-{
-    var iso3 = vars.get("$field.LANGUAGE");
-    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
+import("system.db");
+import("system.translate");
+import("system.result");
+import("system.vars");
+import("Sql_lib");
+
+var iso3 = vars.get("$field.LANGUAGE");
+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);
diff --git a/entity/Offer_entity/entityfields/newactivity/onActionProcess.js b/entity/Offer_entity/entityfields/newactivity/onActionProcess.js
index d0e6ebcf2bdd9a61c92ebde5728203de9d3f0c99..4be677edd52ad21e51db57a867790397f1fe35bc 100644
--- a/entity/Offer_entity/entityfields/newactivity/onActionProcess.js
+++ b/entity/Offer_entity/entityfields/newactivity/onActionProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Offer_entity/entityfields/newtask/onActionProcess.js b/entity/Offer_entity/entityfields/newtask/onActionProcess.js
index b77c8343aa0def1afccab6e7c4a4dc5558da7e9b..f0165851eda69a6c3a0187d29f05c133b4118ed3 100644
--- a/entity/Offer_entity/entityfields/newtask/onActionProcess.js
+++ b/entity/Offer_entity/entityfields/newtask/onActionProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Offer_entity/entityfields/printoffer/stateProcess.js b/entity/Offer_entity/entityfields/printoffer/stateProcess.js
index b6ef75cff77e2ad3ff7423b297ecb8fa6cac1aa1..bb8a76fc6373e23f7ea9e562c2bcedad4c6b5bdb 100644
--- a/entity/Offer_entity/entityfields/printoffer/stateProcess.js
+++ b/entity/Offer_entity/entityfields/printoffer/stateProcess.js
@@ -10,4 +10,4 @@ var itemcount = db.cell(SqlCondition.begin()
 if(itemcount == "0")
     result.string(neon.COMPONENTSTATE_DISABLED);
 else
-    result.string(neon.COMPONENTSTATE_AUTO);
\ No newline at end of file
+    result.string(neon.COMPONENTSTATE_EDITABLE);
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/salesproject_id/mandatoryProcess.js b/entity/Offer_entity/entityfields/salesproject_id/mandatoryProcess.js
index 05b1f9bd5c0c54e2c707e0ac6f2fce2ea12850e0..3bd7da35b29fe62a814c8f4562736441d1b99708 100644
--- a/entity/Offer_entity/entityfields/salesproject_id/mandatoryProcess.js
+++ b/entity/Offer_entity/entityfields/salesproject_id/mandatoryProcess.js
@@ -2,7 +2,7 @@ import("system.vars");
 import("system.result");
 import("Contact_lib");
 
-var type = ContactUtils.getRelationType(vars.get("$field.CONTACT_ID"), vars.get("$field.CONTACT_PERSON_ID"), vars.get("$field.CONTACT_ORG_ID"));
+var type = ContactUtils.getContactType(vars.get("$field.CONTACT_ID"), vars.get("$field.CONTACT_PERSON_ID"), vars.get("$field.CONTACT_ORG_ID"));
 
 result.string(type != 2);
 
diff --git a/entity/Offer_entity/entityfields/status/valueProcess.js b/entity/Offer_entity/entityfields/status/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ea5cc54c968466314db57e5c44b01453da4ff861
--- /dev/null
+++ b/entity/Offer_entity/entityfields/status/valueProcess.js
@@ -0,0 +1,6 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+if (vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value"))
+    result.string("25b0ac77-ef92-4809-802e-bb9d8782f865"); //Open
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js b/entity/Offer_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
index db35a547ac2cbf60774b6ddb9be4781b81196a68..e4c6c134df6be187331e47d8c2c4d5a9871b7c2b 100644
--- a/entity/Offer_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
+++ b/entity/Offer_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Offeritem_entity/Offeritem_entity.aod b/entity/Offeritem_entity/Offeritem_entity.aod
index f330271f5df7b0e14acc63c21452e51cb73e9fe6..236c205986cbdc9106c1762473cc0b5b4e177a92 100644
--- a/entity/Offeritem_entity/Offeritem_entity.aod
+++ b/entity/Offeritem_entity/Offeritem_entity.aod
@@ -81,6 +81,7 @@
       <contentType>NUMBER</contentType>
       <outputFormat>#</outputFormat>
       <valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/quantity/valueProcess.js</valueProcess>
+      <onValidation>%aditoprj%/entity/Offeritem_entity/entityfields/quantity/onValidation.js</onValidation>
       <onValueChange>%aditoprj%/entity/Offeritem_entity/entityfields/quantity/onValueChange.js</onValueChange>
       <onValueChangeTypes>
         <element>MASK</element>
@@ -100,7 +101,7 @@
     </entityField>
     <entityField>
       <name>VAT</name>
-      <title>VAT</title>
+      <title>VAT in %</title>
       <contentType>NUMBER</contentType>
       <outputFormat>#,##0.00</outputFormat>
       <state>READONLY</state>
@@ -163,7 +164,6 @@
         </entityParameter>
         <entityParameter>
           <name>Currency_param</name>
-          <valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/offeritems/children/currency_param/valueProcess.js</valueProcess>
           <expose v="true" />
         </entityParameter>
         <entityParameter>
diff --git a/entity/Offeritem_entity/entityfields/offeritems/children/currency_param/valueProcess.js b/entity/Offeritem_entity/entityfields/offeritems/children/currency_param/valueProcess.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/Offeritem_entity/entityfields/quantity/onValidation.js b/entity/Offeritem_entity/entityfields/quantity/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..aa24a80d84388aa03c991aec88bafe3333d5b990
--- /dev/null
+++ b/entity/Offeritem_entity/entityfields/quantity/onValidation.js
@@ -0,0 +1,16 @@
+import("system.logging");
+import("system.translate");
+import("system.result");
+import("system.vars");
+import("Entity_lib");
+
+logging.log("valid test 1: " + vars.get("$field.QUANTITY"));
+
+var quatity = vars.exists("$field.QUANTITY") ? vars.get("$field.QUANTITY") : "";
+quatity = ProcessHandlingUtils.getOnValidationValue(quatity);
+
+if (parseInt(quatity) <= 0)
+{
+    logging("valid test 2: " +  vars.get("$field.QUANTITY"));
+    result.string(translate.text("${QUANTITY_LOWER_THAN_1}"));
+}
diff --git a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js
index e0c1c63a3dca485b2e7d8de80afaddec55d5ee15..dea8c2c6691264867d11dadaec837f3fc8473c28 100644
--- a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js
+++ b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js
@@ -1,25 +1,37 @@
-import("system.vars");
-import("system.neon");
-import("Product_lib");
-import("Util_lib");
-import("Entity_lib");
-import("Attribute_lib");
-
-var pid = vars.get("$field.PRODUCT_ID");
-var newQuantity = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.QUANTITY"));
-if(pid != "" && newQuantity != "")
-{
-    var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
-    var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
-    var pricelist = AttributeRelationUtils.getAttribute("97b449a5-d9b4-42ff-b9b0-4f8b27b8a9ec", contactid) || "";
-    
-    var PriceListFilter = { currency: curr, quantity: newQuantity, relationId: contactid, priceList: pricelist };
-    
-    var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter);
-    
-    if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null)
-    {
-        vars.set("$field.PRICE", ProductDetails.PriceListToUse.price);
-        vars.set("$field.VAT", ProductDetails.PriceListToUse.vat);
-    }
-}
\ No newline at end of file
+import("system.logging");
+import("system.vars");
+import("system.neon");
+import("Product_lib");
+import("Util_lib");
+import("Entity_lib");
+import("Attribute_lib");
+
+var pid = vars.get("$field.PRODUCT_ID");
+var newQuantity = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.QUANTITY"));
+if(pid != "" && newQuantity != "")
+{
+    var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
+    var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
+    var pricelist = AttributeRelationUtils.getAttribute("97b449a5-d9b4-42ff-b9b0-4f8b27b8a9ec", contactid) || "";
+    
+    var PriceListFilter = { currency: curr, quantity: newQuantity, relationId: contactid, priceList: pricelist };
+    
+    var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter);
+    
+    if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null)
+    {
+        vars.set("$field.PRICE", ProductDetails.PriceListToUse.price);
+        vars.set("$field.VAT", ProductDetails.PriceListToUse.vat);
+    }
+}
+
+
+//checks if the value is <= 0, if so fallback to 1
+var quatity = vars.exists("$field.QUANTITY") ? vars.get("$field.QUANTITY") : "";
+quatity = ProcessHandlingUtils.getOnValidationValue(quatity);
+
+if (parseInt(quatity) <= 0)
+{
+    neon.setFieldValue("$field.QUANTITY", "1");
+}
+    
\ No newline at end of file
diff --git a/entity/Offeritem_entity/entityfields/quantity/valueProcess.js b/entity/Offeritem_entity/entityfields/quantity/valueProcess.js
index 801a9cf46f6d06604ab06e1a2de3086dd3fd4be4..ebd4664e6124e2b62ca40d0d0e97e43003cf22f0 100644
--- a/entity/Offeritem_entity/entityfields/quantity/valueProcess.js
+++ b/entity/Offeritem_entity/entityfields/quantity/valueProcess.js
@@ -2,7 +2,7 @@ import("system.vars");
 import("system.result");
 import("system.neon");
 
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value"))
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
 {
     result.string("1");
 }
\ No newline at end of file
diff --git a/entity/Order_entity/entityfields/activities/children/presetlinks_param/valueProcess.js b/entity/Order_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
index db35a547ac2cbf60774b6ddb9be4781b81196a68..e4c6c134df6be187331e47d8c2c4d5a9871b7c2b 100644
--- a/entity/Order_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
+++ b/entity/Order_entity/entityfields/activities/children/presetlinks_param/valueProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Order_entity/entityfields/contact_id/linkedContextProcess.js b/entity/Order_entity/entityfields/contact_id/linkedContextProcess.js
index e678b842c5b6cf510473693a355fa7833dcf28e8..2e504d63e3b5a3f71b54b072798b3ad09c50984b 100644
--- a/entity/Order_entity/entityfields/contact_id/linkedContextProcess.js
+++ b/entity/Order_entity/entityfields/contact_id/linkedContextProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.result");
 import("Contact_lib");
 
-result.string(ContactUtils.getContextByRelationId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
+result.string(ContactUtils.getContextByContactId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
diff --git a/entity/Order_entity/entityfields/newactivity/onActionProcess.js b/entity/Order_entity/entityfields/newactivity/onActionProcess.js
index 52c2254f6fb64e4784e400dfe61d00e2f2013197..1a27d3d454d20447d05ec6064c1852a7d9e49d01 100644
--- a/entity/Order_entity/entityfields/newactivity/onActionProcess.js
+++ b/entity/Order_entity/entityfields/newactivity/onActionProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Order_entity/entityfields/newtask/onActionProcess.js b/entity/Order_entity/entityfields/newtask/onActionProcess.js
index a2fb8e983a3a08d7bda6b2a66f520f4fdc2ba719..3d0aeaf0beab976054701f3a58a709df8e67de92 100644
--- a/entity/Order_entity/entityfields/newtask/onActionProcess.js
+++ b/entity/Order_entity/entityfields/newtask/onActionProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Order_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js b/entity/Order_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
index db35a547ac2cbf60774b6ddb9be4781b81196a68..e4c6c134df6be187331e47d8c2c4d5a9871b7c2b 100644
--- a/entity/Order_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
+++ b/entity/Order_entity/entityfields/tasks/children/presetlinks_param/valueProcess.js
@@ -7,7 +7,7 @@ var links = [];
 
 if (contactId)
 {
-    links.push([ContactUtils.getContextByRelationId(contactId), contactId]);
+    links.push([ContactUtils.getContextByContactId(contactId), contactId]);
 }
 
 if (vars.get("$field.SALESPROJECT_ID"))
diff --git a/entity/Orderitem_entity/Orderitem_entity.aod b/entity/Orderitem_entity/Orderitem_entity.aod
index c7e1d5c6d7b3f17afe96dcb2d86fad6f0c531636..de79c9ea430cd72be69e87ace155b9233ed98b1c 100644
--- a/entity/Orderitem_entity/Orderitem_entity.aod
+++ b/entity/Orderitem_entity/Orderitem_entity.aod
@@ -1,311 +1,311 @@
-<?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
-  <name>Orderitem_entity</name>
-  <title>Orderitem</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/Orderitem_entity/documentation.adoc</documentation>
-  <afterOperatingState>%aditoprj%/entity/Orderitem_entity/afterOperatingState.js</afterOperatingState>
-  <recordContainer>db</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>ASSIGNEDTO</name>
-    </entityField>
-    <entityField>
-      <name>DISCOUNT</name>
-      <title>Discount</title>
-    </entityField>
-    <entityField>
-      <name>GROUPCODEID</name>
-      <title>Commodity group</title>
-      <consumer>KeywordProductGroupcodes</consumer>
-      <state>READONLY</state>
-      <displayValueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/groupcodeid/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityField>
-      <name>ITEMNAME</name>
-      <title>Designation</title>
-    </entityField>
-    <entityField>
-      <name>ITEMPOSITION</name>
-      <title>Position</title>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/itemposition/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>ITEMSORT</name>
-    </entityField>
-    <entityField>
-      <name>SALESORDERITEMID</name>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/salesorderitemid/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>SALESORDER_ID</name>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/salesorder_id/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>OPTIONAL</name>
-      <title>Optional</title>
-      <contentType>BOOLEAN</contentType>
-      <mandatory v="true" />
-      <possibleItemsProcess>%aditoprj%/entity/Orderitem_entity/entityfields/optional/possibleItemsProcess.js</possibleItemsProcess>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/optional/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>PRICE</name>
-      <title>Unit price</title>
-    </entityField>
-    <entityField>
-      <name>PRODUCT_ID</name>
-      <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/product_id/documentation.adoc</documentation>
-      <title>Article</title>
-      <consumer>Products</consumer>
-      <linkedContext>Product</linkedContext>
-      <onValueChange>%aditoprj%/entity/Orderitem_entity/entityfields/product_id/onValueChange.js</onValueChange>
-      <onValueChangeTypes>
-        <element>MASK</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityField>
-      <name>QUANTITY</name>
-      <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/quantity/documentation.adoc</documentation>
-      <title>Quantity</title>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/quantity/valueProcess.js</valueProcess>
-      <onValidation></onValidation>
-      <onValueChange>%aditoprj%/entity/Orderitem_entity/entityfields/quantity/onValueChange.js</onValueChange>
-      <onValueChangeTypes>
-        <element>MASK</element>
-      </onValueChangeTypes>
-    </entityField>
-    <entityField>
-      <name>UNIT</name>
-      <title>Unit</title>
-      <consumer>KeywordQuantityUnits</consumer>
-      <displayValueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/unit/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityField>
-      <name>VAT</name>
-      <title>VAT</title>
-      <state>AUTO</state>
-    </entityField>
-    <entityParameter>
-      <name>OrderId_param</name>
-      <expose v="true" />
-      <triggerRecalculation v="true" />
-      <mandatory v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>ContactId_param</name>
-      <expose v="true" />
-      <triggerRecalculation v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>Currency_param</name>
-      <expose v="true" />
-      <triggerRecalculation v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityField>
-      <name>TotalPrice</name>
-      <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/totalprice/documentation.adoc</documentation>
-      <title>Sum</title>
-      <contentType>NUMBER</contentType>
-      <outputFormat>#,##0.00</outputFormat>
-      <state>READONLY</state>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/totalprice/valueProcess.js</valueProcess>
-      <onValidation></onValidation>
-    </entityField>
-    <entityField>
-      <name>IMAGE</name>
-      <contentType>IMAGE</contentType>
-      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/image/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>OrderStatus_param</name>
-      <expose v="true" />
-      <triggerRecalculation v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityProvider>
-      <name>Orderitems</name>
-      <fieldType>DEPENDENCY_IN</fieldType>
-      <recordContainer>db</recordContainer>
-      <dependencies>
-        <entityDependency>
-          <name>7810e350-d011-4d95-8d0b-883f3a0e519c</name>
-          <entityName>Order_entity</entityName>
-          <fieldName>Orderitems</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>911de4a4-0e85-4d50-93ee-6f8f2308589e</name>
-          <entityName>Order_entity</entityName>
-          <fieldName>Orderitems</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>ContactId_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>Currency_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>OrderId_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>OrderStatus_param</name>
-          <expose v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityField>
-      <name>INFO</name>
-      <title>Note</title>
-    </entityField>
-    <entityConsumer>
-      <name>KeywordProductGroupcodes</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/Orderitem_entity/entityfields/keywordproductgroupcodes/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityConsumer>
-      <name>KeywordQuantityUnits</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/Orderitem_entity/entityfields/keywordquantityunits/children/containername_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityConsumer>
-      <name>Products</name>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Product_entity</entityName>
-        <fieldName>#PROVIDER</fieldName>
-      </dependency>
-    </entityConsumer>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>db</name>
-      <alias>Data_alias</alias>
-      <maximumDbRows v="0" />
-      <conditionProcess>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
-      <orderClauseProcess>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
-      <onDBInsert>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
-      <onDBUpdate>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
-      <onDBDelete>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
-      <linkInformation>
-        <linkInformation>
-          <name>cb0f1bfa-92eb-4ee9-bb02-8ac0ef3f987d</name>
-          <tableName>SALESORDERITEM</tableName>
-          <primaryKey>SALESORDERITEMID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>ASSIGNEDTO.value</name>
-          <recordfield>SALESORDERITEM.ASSIGNEDTO</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DISCOUNT.value</name>
-          <recordfield>SALESORDERITEM.DISCOUNT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>GROUPCODEID.value</name>
-          <recordfield>SALESORDERITEM.GROUPCODEID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ITEMNAME.value</name>
-          <recordfield>SALESORDERITEM.ITEMNAME</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ITEMPOSITION.value</name>
-          <recordfield>SALESORDERITEM.ITEMPOSITION</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ITEMSORT.value</name>
-          <recordfield>SALESORDERITEM.ITEMSORT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>SALESORDERITEMID.value</name>
-          <recordfield>SALESORDERITEM.SALESORDERITEMID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>SALESORDER_ID.value</name>
-          <recordfield>SALESORDERITEM.SALESORDER_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>OPTIONAL.value</name>
-          <recordfield>SALESORDERITEM.OPTIONAL</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>PRICE.value</name>
-          <recordfield>SALESORDERITEM.PRICE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>PRODUCT_ID.value</name>
-          <recordfield>SALESORDERITEM.PRODUCT_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>QUANTITY.value</name>
-          <recordfield>SALESORDERITEM.QUANTITY</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>UNIT.value</name>
-          <recordfield>SALESORDERITEM.UNIT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>VAT.value</name>
-          <recordfield>SALESORDERITEM.VAT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>GROUPCODEID.displayValue</name>
-          <expression>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/recordfieldmappings/groupcodeid.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>UNIT.displayValue</name>
-          <expression>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/recordfieldmappings/unit.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>PRODUCT_ID.displayValue</name>
-          <expression>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/recordfieldmappings/product_id.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>INFO.value</name>
-          <recordfield>SALESORDERITEM.INFO</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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
+  <name>Orderitem_entity</name>
+  <title>Orderitem</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/entity/Orderitem_entity/documentation.adoc</documentation>
+  <afterOperatingState>%aditoprj%/entity/Orderitem_entity/afterOperatingState.js</afterOperatingState>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>ASSIGNEDTO</name>
+    </entityField>
+    <entityField>
+      <name>DISCOUNT</name>
+      <title>Discount</title>
+    </entityField>
+    <entityField>
+      <name>GROUPCODEID</name>
+      <title>Commodity group</title>
+      <consumer>KeywordProductGroupcodes</consumer>
+      <state>READONLY</state>
+      <displayValueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/groupcodeid/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityField>
+      <name>ITEMNAME</name>
+      <title>Designation</title>
+    </entityField>
+    <entityField>
+      <name>ITEMPOSITION</name>
+      <title>Position</title>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/itemposition/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>ITEMSORT</name>
+    </entityField>
+    <entityField>
+      <name>SALESORDERITEMID</name>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/salesorderitemid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>SALESORDER_ID</name>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/salesorder_id/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>OPTIONAL</name>
+      <title>Optional</title>
+      <contentType>BOOLEAN</contentType>
+      <mandatory v="true" />
+      <possibleItemsProcess>%aditoprj%/entity/Orderitem_entity/entityfields/optional/possibleItemsProcess.js</possibleItemsProcess>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/optional/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>PRICE</name>
+      <title>Unit price</title>
+    </entityField>
+    <entityField>
+      <name>PRODUCT_ID</name>
+      <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/product_id/documentation.adoc</documentation>
+      <title>Article</title>
+      <consumer>Products</consumer>
+      <linkedContext>Product</linkedContext>
+      <onValueChange>%aditoprj%/entity/Orderitem_entity/entityfields/product_id/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>QUANTITY</name>
+      <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/quantity/documentation.adoc</documentation>
+      <title>Quantity</title>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/quantity/valueProcess.js</valueProcess>
+      <onValidation></onValidation>
+      <onValueChange>%aditoprj%/entity/Orderitem_entity/entityfields/quantity/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
+    </entityField>
+    <entityField>
+      <name>UNIT</name>
+      <title>Unit</title>
+      <consumer>KeywordQuantityUnits</consumer>
+      <displayValueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/unit/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityField>
+      <name>VAT</name>
+      <title>VAT in %</title>
+      <state>AUTO</state>
+    </entityField>
+    <entityParameter>
+      <name>OrderId_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>ContactId_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>Currency_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>TotalPrice</name>
+      <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/totalprice/documentation.adoc</documentation>
+      <title>Sum</title>
+      <contentType>NUMBER</contentType>
+      <outputFormat>#,##0.00</outputFormat>
+      <state>READONLY</state>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/totalprice/valueProcess.js</valueProcess>
+      <onValidation></onValidation>
+    </entityField>
+    <entityField>
+      <name>IMAGE</name>
+      <contentType>IMAGE</contentType>
+      <valueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/image/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>OrderStatus_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>Orderitems</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>7810e350-d011-4d95-8d0b-883f3a0e519c</name>
+          <entityName>Order_entity</entityName>
+          <fieldName>Orderitems</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>911de4a4-0e85-4d50-93ee-6f8f2308589e</name>
+          <entityName>Order_entity</entityName>
+          <fieldName>Orderitems</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ContactId_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>Currency_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>OrderId_param</name>
+          <expose v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>OrderStatus_param</name>
+          <expose v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityField>
+      <name>INFO</name>
+      <title>Note</title>
+    </entityField>
+    <entityConsumer>
+      <name>KeywordProductGroupcodes</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/Orderitem_entity/entityfields/keywordproductgroupcodes/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityConsumer>
+      <name>KeywordQuantityUnits</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/Orderitem_entity/entityfields/keywordquantityunits/children/containername_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityConsumer>
+      <name>Products</name>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Product_entity</entityName>
+        <fieldName>#PROVIDER</fieldName>
+      </dependency>
+    </entityConsumer>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <maximumDbRows v="0" />
+      <conditionProcess>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <orderClauseProcess>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
+      <onDBInsert>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
+      <onDBUpdate>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
+      <onDBDelete>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
+      <linkInformation>
+        <linkInformation>
+          <name>cb0f1bfa-92eb-4ee9-bb02-8ac0ef3f987d</name>
+          <tableName>SALESORDERITEM</tableName>
+          <primaryKey>SALESORDERITEMID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>ASSIGNEDTO.value</name>
+          <recordfield>SALESORDERITEM.ASSIGNEDTO</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DISCOUNT.value</name>
+          <recordfield>SALESORDERITEM.DISCOUNT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>GROUPCODEID.value</name>
+          <recordfield>SALESORDERITEM.GROUPCODEID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ITEMNAME.value</name>
+          <recordfield>SALESORDERITEM.ITEMNAME</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ITEMPOSITION.value</name>
+          <recordfield>SALESORDERITEM.ITEMPOSITION</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ITEMSORT.value</name>
+          <recordfield>SALESORDERITEM.ITEMSORT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>SALESORDERITEMID.value</name>
+          <recordfield>SALESORDERITEM.SALESORDERITEMID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>SALESORDER_ID.value</name>
+          <recordfield>SALESORDERITEM.SALESORDER_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OPTIONAL.value</name>
+          <recordfield>SALESORDERITEM.OPTIONAL</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PRICE.value</name>
+          <recordfield>SALESORDERITEM.PRICE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PRODUCT_ID.value</name>
+          <recordfield>SALESORDERITEM.PRODUCT_ID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>QUANTITY.value</name>
+          <recordfield>SALESORDERITEM.QUANTITY</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>UNIT.value</name>
+          <recordfield>SALESORDERITEM.UNIT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>VAT.value</name>
+          <recordfield>SALESORDERITEM.VAT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>GROUPCODEID.displayValue</name>
+          <expression>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/recordfieldmappings/groupcodeid.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>UNIT.displayValue</name>
+          <expression>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/recordfieldmappings/unit.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PRODUCT_ID.displayValue</name>
+          <expression>%aditoprj%/entity/Orderitem_entity/recordcontainers/db/recordfieldmappings/product_id.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>INFO.value</name>
+          <recordfield>SALESORDERITEM.INFO</recordfield>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 1c9253f9ce066a6edf0d3b8fa50a36f517d8f4c7..64f7d41a88060b949915c7b4b3414ff21ab22103 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -140,12 +140,6 @@
           <fieldName>Organisations</fieldName>
           <isConsumer v="false" />
         </entityDependency>
-        <entityDependency>
-          <name>7aa5f9b4-6986-4593-a6d8-c4fb03da9c68</name>
-          <entityName>Contact_entity</entityName>
-          <fieldName>Organisations</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
       </dependencies>
       <children>
         <entityParameter>
@@ -156,6 +150,10 @@
           <name>WithPrivate_param</name>
           <expose v="true" />
         </entityParameter>
+        <entityParameter>
+          <name>ExcludeOrganisationsByPersonId</name>
+          <expose v="false" />
+        </entityParameter>
       </children>
     </entityProvider>
     <entityConsumer>
@@ -187,6 +185,7 @@
       <consumer>Addresses</consumer>
       <searchable v="false" />
       <state>AUTO</state>
+      <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/address_id/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Organisation_entity/entityfields/address_id/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityConsumer>
@@ -590,6 +589,7 @@
       <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/withprivate_param/valueProcess.js</valueProcess>
       <expose v="true" />
       <triggerRecalculation v="true" />
+      <documentation>%aditoprj%/entity/Organisation_entity/entityfields/withprivate_param/documentation.adoc</documentation>
       <description>PARAMETER</description>
     </entityParameter>
     <entityConsumer>
@@ -632,6 +632,41 @@
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityParameter>
+      <name>ExcludeOrganisationsByPersonId</name>
+      <expose v="true" />
+      <documentation>%aditoprj%/entity/Organisation_entity/entityfields/excludeorganisationsbypersonid/documentation.adoc</documentation>
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>WithPersonIdFilter</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <documentation>%aditoprj%/entity/Organisation_entity/entityfields/withpersonidfilter/documentation.adoc</documentation>
+      <dependencies>
+        <entityDependency>
+          <name>5a456b04-f0ca-4a45-9c1f-bdfdf074434a</name>
+          <entityName>Contact_entity</entityName>
+          <fieldName>Organisations</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ContactId_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>ExcludeOrganisationsByPersonId</name>
+          <title></title>
+          <expose v="true" />
+          <mandatory v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>WithPrivate_param</name>
+          <expose v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -639,6 +674,7 @@
       <alias>Data_alias</alias>
       <fromClauseProcess>%aditoprj%/entity/Organisation_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Organisation_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <onDBInsert>%aditoprj%/entity/Organisation_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <onDBUpdate>%aditoprj%/entity/Organisation_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
       <linkInformation>
         <linkInformation>
diff --git a/entity/Organisation_entity/entityfields/excludeorganisationsbypersonid/documentation.adoc b/entity/Organisation_entity/entityfields/excludeorganisationsbypersonid/documentation.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..df350126c674f699847049d6e70d2147c0e61432
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/excludeorganisationsbypersonid/documentation.adoc
@@ -0,0 +1,2 @@
+A param used to filter Organisations where a specific PersonId does already exist as contact-entry.
+In other words: The list of orgs is reduced by those where a Contact-entry does exist for the given Personid
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/newappointment/onActionProcess.js b/entity/Organisation_entity/entityfields/newappointment/onActionProcess.js
index d5e0f5adb9322430a6bceaab1acc90c5634fdd54..475936e13803b10cfb274cf925f189ffbc54049c 100644
--- a/entity/Organisation_entity/entityfields/newappointment/onActionProcess.js
+++ b/entity/Organisation_entity/entityfields/newappointment/onActionProcess.js
@@ -1,10 +1,14 @@
-import("system.neon");
-import("system.calendars");
-import("Calendar_lib");
-import("system.date");
-
-
-var params = {};
-params["Entry_param"] = CalendarUtil.createEntry(calendars.VEVENT, "neue Termin weissu", "", false);
-
-neon.openContext("Appointment", "AppointmentEdit_view", null, neon.OPERATINGSTATE_NEW, params);
\ No newline at end of file
+import("system.vars");
+import("system.logging");
+import("system.neon");
+import("system.calendars");
+import("Calendar_lib");
+import("system.date");
+import("Context_lib");
+
+
+var params = {};
+params["Entry_param"] = JSON.stringify(CalendarUtil.createEntry(calendars.VEVENT, "neue Termin weissu", "", false, ContextUtils.getCurrentContextId(), vars.get("$field.ORGANISATIONID")));
+
+neon.openContext("Appointment", "AppointmentEdit_view", null, neon.OPERATINGSTATE_NEW, params);
+
diff --git a/entity/Organisation_entity/entityfields/withpersonidfilter/documentation.adoc b/entity/Organisation_entity/entityfields/withpersonidfilter/documentation.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..417ca5b40f81dfc38a15d5f7c48274d962d942c1
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/withpersonidfilter/documentation.adoc
@@ -0,0 +1,2 @@
+Provides Organisations where a filter is applied:
+The list of Organisations is reduced by those where a Contact-entry does exist for a given PersonId.
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/withprivate_param/documentation.adoc b/entity/Organisation_entity/entityfields/withprivate_param/documentation.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..6465a654b7694320706cbe5bd8aa25e300133642
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/withprivate_param/documentation.adoc
@@ -0,0 +1,9 @@
+Param that describes if the "private"-dummy-Organisation shall be returned or not.
+Possible values are:
+
+- `true`
+- `false`
+
+The Default value is `false`.
+
+If the value `true` is passed the "private"-dummy-Organisation will be returned. Otherwise the "private"-dummy-Organisation is filtered.
\ No newline at end of file
diff --git a/entity/Organisation_entity/recordcontainers/db/conditionProcess.js b/entity/Organisation_entity/recordcontainers/db/conditionProcess.js
index 2f923bd91f690aa3b87a16540bce1ea11bdcbed7..d8f6c2d5a839058a05dd2dc58d9c128a39398c12 100644
--- a/entity/Organisation_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Organisation_entity/recordcontainers/db/conditionProcess.js
@@ -10,5 +10,11 @@ var cond = SqlCondition.begin()
 if (vars.getString("$param.WithPrivate_param") != "true")
     cond.andPrepare("ORGANISATION.ORGANISATIONID", "0", "# <> ?");
 
+var excludeOrgsWithPersonId = vars.get("$param.ExcludeOrganisationsByPersonId")
+if (excludeOrgsWithPersonId)
+    cond.andAttachPrepared(SqlCondition.begin()
+                                       .andPrepare("CONTACT.PERSON_ID", excludeOrgsWithPersonId)
+                                       .buildSql("ORGANISATION.ORGANISATIONID not in (select CONTACT.ORGANISATION_ID from CONTACT", null, ")"));
+
 //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/Organisation_entity/recordcontainers/db/onDBInsert.js b/entity/Organisation_entity/recordcontainers/db/onDBInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba0e67422c062558e49b062c65e43e35fa5e2b95
--- /dev/null
+++ b/entity/Organisation_entity/recordcontainers/db/onDBInsert.js
@@ -0,0 +1,3 @@
+import("system.logging");
+import("system.vars");
+
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 8d3077b91f354a263660464dd72b1644efb44c3f..e550ec716d261d4d512ed21c443013523e6b5835 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -16,6 +16,7 @@
       <contentType>DATE</contentType>
       <resolution>DAY</resolution>
       <outputFormat>dd.MM.yyyy</outputFormat>
+      <onValidation>%aditoprj%/entity/Person_entity/entityfields/dateofbirth/onValidation.js</onValidation>
     </entityField>
     <entityField>
       <name>FIRSTNAME</name>
@@ -372,6 +373,10 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
           <expose v="true" />
           <mandatory v="true" />
         </entityParameter>
+        <entityParameter>
+          <name>ExcludedContactIds_param</name>
+          <expose v="false" />
+        </entityParameter>
       </children>
     </entityProvider>
     <entityConsumer>
@@ -691,14 +696,20 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
     <entityField>
       <name>DEPARTMENT</name>
       <title>Department</title>
+      <possibleItemsProcess>%aditoprj%/entity/Person_entity/entityfields/department/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
     </entityField>
     <entityField>
       <name>POSITION</name>
       <title>Position</title>
+      <possibleItemsProcess>%aditoprj%/entity/Person_entity/entityfields/position/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
     </entityField>
     <entityField>
       <name>CONTACTROLE</name>
       <title>Contactrole</title>
+      <possibleItemsProcess>%aditoprj%/entity/Person_entity/entityfields/contactrole/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
     </entityField>
     <entityConsumer>
       <name>OtherContacts</name>
@@ -716,17 +727,20 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityField>
+      <name>ORGANISATION_NAME</name>
+    </entityField>
     <entityParameter>
-      <name>SalesprojectId_param</name>
+      <name>ExcludedContactIds_param</name>
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
     <entityProvider>
-      <name>SalesprojectMemberContact</name>
+      <name>Contacts</name>
       <fieldType>DEPENDENCY_IN</fieldType>
       <dependencies>
         <entityDependency>
-          <name>a6372a65-6cbe-4a8e-b428-f77b7f1ea4db</name>
+          <name>75f0e309-8b3f-4224-b599-a203405f1bff</name>
           <entityName>SalesprojectMember_entity</entityName>
           <fieldName>Contacts</fieldName>
           <isConsumer v="false" />
@@ -734,11 +748,35 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
       </dependencies>
       <children>
         <entityParameter>
-          <name>SalesprojectId_param</name>
+          <name>ContactId_param</name>
+          <expose v="false" />
+        </entityParameter>
+        <entityParameter>
+          <name>ExcludedContactIds_param</name>
           <expose v="true" />
         </entityParameter>
+        <entityParameter>
+          <name>OrgId_param</name>
+          <expose v="false" />
+        </entityParameter>
       </children>
     </entityProvider>
+    <entityConsumer>
+      <name>360DegreeObjects</name>
+      <title>360 Degree</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>360Degree_entity</entityName>
+        <fieldName>PersonObjects</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ObjectRowId_param</name>
+          <valueProcess>%aditoprj%/entity/Person_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -877,6 +915,10 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
           <name>CONTACTROLE.value</name>
           <recordfield>CONTACT.CONTACTROLE</recordfield>
         </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ORGANISATION_NAME.value</name>
+          <recordfield>ORGANISATION.NAME</recordfield>
+        </dbRecordFieldMapping>
       </recordFieldMappings>
     </dbRecordContainer>
   </recordContainers>
diff --git a/entity/Person_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js b/entity/Person_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..bdc67e9f840a599793a8fc7d1dd7b9c88d193af4
--- /dev/null
+++ b/entity/Person_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.getString("$field.PERSONID"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/contactrole/possibleItemsProcess.js b/entity/Person_entity/entityfields/contactrole/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..96627ddf00215d0598ae85d2452acfd248cbe52a
--- /dev/null
+++ b/entity/Person_entity/entityfields/contactrole/possibleItemsProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var res = KeywordUtils.getEntryNamesByContainer($KeywordRegistry.contactContactrole()).map(function (e){
+    return [e, e]; //currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+});
+
+result.object(res);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/dateofbirth/onValidation.js b/entity/Person_entity/entityfields/dateofbirth/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..9da0a7497bd26a10627d66a89a67f3b863cde608
--- /dev/null
+++ b/entity/Person_entity/entityfields/dateofbirth/onValidation.js
@@ -0,0 +1,9 @@
+import("system.datetime");
+import("system.translate");
+import("system.vars");
+import("system.result");
+import("Entity_lib");
+
+var dob = ProcessHandlingUtils.getOnValidationValue();
+if (Number(datetime.clearTime(dob)) > Number(vars.get("$sys.today")))
+    result.string(translate.text("date of birth must not be in the future"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/department/possibleItemsProcess.js b/entity/Person_entity/entityfields/department/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..77d99fa219eb36618f38dbb344e4a345bb71d331
--- /dev/null
+++ b/entity/Person_entity/entityfields/department/possibleItemsProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var res = KeywordUtils.getEntryNamesByContainer($KeywordRegistry.contactDepartment()).map(function (e){
+    return [e, e]; //currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+});
+
+result.object(res);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/full_name_fieldgroup/valueProcess.js b/entity/Person_entity/entityfields/full_name_fieldgroup/valueProcess.js
index b3a098ff143cffbd6bd95e276a5b5c0ba689d3d7..778c203ff13f6bc2955db27cc8c7ec6544de380d 100644
--- a/entity/Person_entity/entityfields/full_name_fieldgroup/valueProcess.js
+++ b/entity/Person_entity/entityfields/full_name_fieldgroup/valueProcess.js
@@ -3,6 +3,7 @@ import("system.result");
 import("Util_lib");
 import("Contact_lib");
 
+//no orgname here since the org-field is in the card-template as separate field
 var contact = new Contact();
 contact.salutation = vars.get("$field.SALUTATION");
 contact.title = vars.get("$field.TITLE");
diff --git a/entity/Person_entity/entityfields/position/possibleItemsProcess.js b/entity/Person_entity/entityfields/position/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..a86d6820913b759ac976779f9c045378095b6d24
--- /dev/null
+++ b/entity/Person_entity/entityfields/position/possibleItemsProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var res = KeywordUtils.getEntryNamesByContainer($KeywordRegistry.contactPosition()).map(function (e){
+    return [e, e]; //currently the first column is ID, second view value - which is the same because there is no ID for keyword-containers
+});
+
+result.object(res);
\ No newline at end of file
diff --git a/entity/Person_entity/recordcontainers/db/conditionProcess.js b/entity/Person_entity/recordcontainers/db/conditionProcess.js
index 77acb02a09f3d362a1d26dde8ecf05ee28a2d291..47f1ee35510663ddbb914ef4dd4f25988d323560 100644
--- a/entity/Person_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Person_entity/recordcontainers/db/conditionProcess.js
@@ -4,13 +4,27 @@ import("system.result");
 import("Sql_lib");
 
 var cond = new SqlCondition();
-cond.andPrepareVars("CONTACT.ORGANISATION_ID", "$param.OrgId_param");
-cond.andPrepareVars("PERSON.CONTACT_ID", "$param.ContactId_param");
+cond.andPrepareVars("CONTACT.ORGANISATION_ID", "$param.OrgId_param")
+    .andPrepareVars("PERSON.CONTACT_ID", "$param.ContactId_param");
 
+if (vars.exists("$param.ExcludedContactIds_param") && vars.get("$param.ExcludedContactIds_param"))
+{
+    var excludedContacts = JSON.parse(vars.get("$param.ExcludedContactIds_param"));
+    var excludedCond = SqlCondition.begin();
+    
+    excludedContacts.forEach(function(pContactId)
+    {
+        excludedCond.andPrepare("CONTACT.CONTACTID", pContactId, "#<>?");
+    });
+    
+    cond.andSqlCondition(excludedCond, "1=1");
+}
+
+/*
 //in salesprojectMember, only people that aren't already in the salesproject should be selectable
 cond.andPrepareVars("PERSON.PERSONID", "$param.SalesprojectId_param", 
     "# not in (select CONTACT.PERSON_ID from SALESPROJECT_MEMBER join CONTACT on SALESPROJECT_MEMBER.CONTACT_ID = CONTACT.CONTACTID "
         + " where SALESPROJECT_MEMBER.SALESPROJECT_ID = ?)");
-
+*/
 //TODO: use a preparedCondition when available #1030812 #1034026
-result.string(db.translateCondition(cond.build("1 = 1")));
\ No newline at end of file
+result.string(db.translateCondition(cond.build("1 = 1")));
diff --git a/entity/Person_entity/titleProcess.js b/entity/Person_entity/titleProcess.js
index 29d40a6e1fdb032e2b43305953caa46655c58638..abaa3df1566528e8dc3e5aad91ac26ab26fe5418 100644
--- a/entity/Person_entity/titleProcess.js
+++ b/entity/Person_entity/titleProcess.js
@@ -1,4 +1,16 @@
 import("system.vars");
 import("system.result");
+import("Util_lib");
+import("Contact_lib");
 
-result.string(vars.get("$field.NAME_fieldGroup"));
\ No newline at end of file
+//do not use "FULL_NAME_fieldGroup" here since the field group must not include the orgname
+var contact = new Contact();
+contact.salutation = vars.get("$field.SALUTATION");
+contact.title = vars.get("$field.TITLE");
+contact.firstname = vars.get("$field.FIRSTNAME");
+contact.middlename = vars.get("$field.MIDDLENAME");
+contact.lastname = vars.get("$field.LASTNAME");
+contact.organisationName = vars.get("$field.ORGANISATION_NAME");
+
+var renderer = new ContactTitleRenderer(contact, null);
+result.string(renderer.asString());
\ No newline at end of file
diff --git a/entity/Prod2prod_entity/Prod2prod_entity.aod b/entity/Prod2prod_entity/Prod2prod_entity.aod
index 8826f3b29a8e6e93e601211370b3f5eac45da06c..78d288fbd064f2aa42f6a4d8823fb3362f34dfeb 100644
--- a/entity/Prod2prod_entity/Prod2prod_entity.aod
+++ b/entity/Prod2prod_entity/Prod2prod_entity.aod
@@ -1,6 +1,7 @@
 <?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.0">
   <name>Prod2prod_entity</name>
+  <title>Parts list</title>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Prod2prod_entity/documentation.adoc</documentation>
   <recordContainer>jdito</recordContainer>
@@ -27,6 +28,8 @@
     <entityField>
       <name>QUANTITY</name>
       <title>Quantity</title>
+      <contentType>NUMBER</contentType>
+      <outputFormat>#</outputFormat>
       <valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/quantity/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
@@ -49,11 +52,6 @@
       <triggerRecalculation v="true" />
       <description>PARAMETER</description>
     </entityParameter>
-    <entityField>
-      <name>PARENTID</name>
-      <title>Parent</title>
-      <groupable v="true" />
-    </entityField>
     <entityField>
       <name>PROD2PRODID</name>
       <valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/prod2prodid/valueProcess.js</valueProcess>
@@ -137,15 +135,14 @@
       <onDelete>%aditoprj%/entity/Prod2prod_entity/recordcontainers/jdito/onDelete.js</onDelete>
       <recordFields>
         <element>UID.value</element>
-        <element>PARENTID.value</element>
-        <element>PROD2PRODID.value</element>
+        <element>SOURCE_ID.value</element>
+        <element>DEST_ID.value</element>
         <element>QUANTITY.value</element>
-        <element>OPTIONAL.value</element>
-        <element>TAKEPRICE.value</element>
         <element>PRODUCTCODE.value</element>
         <element>PRODUCTID.value</element>
-        <element>SOURCE_ID.value</element>
-        <element>DEST_ID.displayValue</element>
+        <element>PROD2PRODID.value</element>
+        <element>OPTIONAL.value</element>
+        <element>TAKEPRICE.value</element>
       </recordFields>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/Prod2prod_entity/entityfields/quantity/valueProcess.js b/entity/Prod2prod_entity/entityfields/quantity/valueProcess.js
index 66e7d5877cff30feb8edc57c25a252f286892c3d..1adf62b3fab0c83c0f9ff455506257b815098393 100644
--- a/entity/Prod2prod_entity/entityfields/quantity/valueProcess.js
+++ b/entity/Prod2prod_entity/entityfields/quantity/valueProcess.js
@@ -1,10 +1,8 @@
-//import("system.vars");
-//import("system.result");
-//import("system.neon");
-//
-//if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == "")
-//{
-//    result.string("1");
-//}
-//else
-//    result.string(vars.get("$this.value"));
\ No newline at end of file
+import("system.vars");
+import("system.result");
+import("system.neon");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.get("$field.QUANTITY"))
+{
+    result.string("1");
+}
\ No newline at end of file
diff --git a/entity/Prod2prod_entity/recordcontainers/jdito/contentProcess.js b/entity/Prod2prod_entity/recordcontainers/jdito/contentProcess.js
index 1eca5fb315ce03cf0f9cd20ce70f3b869cddd834..eeef1e962f6196a9eb632698f6860c216068cb51 100644
--- a/entity/Prod2prod_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Prod2prod_entity/recordcontainers/jdito/contentProcess.js
@@ -1,3 +1,4 @@
+import("system.logging");
 import("system.neon");
 import("system.result");
 import("system.vars");
@@ -5,17 +6,138 @@ import("system.db");
 import("system.util");
 import("Product_lib");
 
+/**
+ * Calculate the root elements for this tree.
+ * 
+ * @param productRootID string
+ * @param rows TreeData[]
+ * @return string[]
+ */
+function calculateRootElements (productRootID, rows) {
+   return rows.filter(function (row) {
+       // Filter predicate if the DIST_ID matches.
+      return row[2] === productRootID;
+   }).map(function (row) {
+       // Map to PROD2PROD_ID.
+       return row[0];
+   });
+}
+
+/**
+* Calculates a mapping object which has the PROD2PROD_ID as
+* key and the full TreeData array as value.
+* 
+* @param rows TreeData[]
+* @return {[key: TreeData]}
+*/
+function buildProd2ProdIDMapping (rows) {
+    var mapping = {}
+    
+    rows.forEach(function(row) {
+        // Create new property which PROD2PROD_ID as key and data
+        // as value.
+       mapping[row[0]] = row;
+    });
+    
+    return mapping;
+}
+
+/**
+ * Calcualtes the children mapping structure which has the DIST_ID
+ * as key and an array of PROD2PROD_IDs as value.
+ *
+ * @param rows TreeData[]
+ * @return {[key: string[]]}
+ */
+function buildChildrenMapping(rows) {
+    var parrentMapping = {}
+    
+    rows.forEach(function (row) {
+        // Create empty array if not created previously.
+        if (parrentMapping[row[2]] === undefined)
+          parrentMapping[row[2]] = []
+      
+      // Push with DIST_ID as key and PROD2PROD_ID as value.
+      parrentMapping[row[2]].push(row[0]);
+    })
+    
+    return parrentMapping
+}
+
+/**
+ * Calculates the graph starting from the given elementID.
+ */
+function buildGraph (elementID, parentElementID, mappingStructure, prod2prodIdMapping) {
+    var elements = []
+ 
+    // Get the PROD2PROD data array and copy it.
+    // Copying is requried due to mutability of arrays.
+    var elementData = prod2prodIdMapping[elementID].slice(0);
+    
+    // Just as an error prevention.
+    if (elementData === undefined)
+        return elements;
+    
+    // Generate new PROD2PROD_ID to create a uniqueness between the PROD2PROD objects.
+    var virtualProd2ProdId = util.getNewUUID();
+    
+    // Override actual PROD2PROD_ID with new ID.
+    elementData[0] = virtualProd2ProdId;
+ 
+    // Override parent id to match overriden prod2prodId of parent
+    if (parentElementID === null || parentElementID === undefined)
+        // Describes an root element
+        elementData[2] = null;
+    else
+        elementData[2] = parentElementID;
+ 
+    // Push element data to elements array of this graph.
+    elements.push(elementData);
+
+    // Search for children
+    var childrens = mappingStructure[elementData[1]];
+
+    if (childrens !== undefined && childrens.length > 0) {
+        // Build graph for each children
+
+        childrens.forEach(function(children) {
+            // Recursive function call (!)
+            
+            var graphResult = buildGraph(children, elementData[0], mappingStructure, prod2prodIdMapping);
+            
+            graphResult.forEach(function(res) {elements.push(res)})
+        });
+    }
+
+    return elements;
+}
+
 if (vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW)
 {
     var prodid = vars.exists("$param.ProductId_param") 
                  && vars.get("$param.ProductId_param") != null ? vars.get("$param.ProductId_param") : "";
     if(prodid != "")
     {
-        var p2pUtils = new Prod2ProdUtils(prodid);
-        result.object(p2pUtils.getPartsListForRecordContainer());
+        // First 3 columns are crucial, the rest is optional.
+        var data = db.table("select PROD2PRODID, SOURCE_ID, DEST_ID, QUANTITY, PRODUCTCODE, PRODUCTID, PROD2PRODID, OPTIONAL, TAKEPRICE "
+                    + "from PROD2PROD join PRODUCT on PROD2PROD.SOURCE_ID = PRODUCTID "
+                    + "order by PRODUCTCODE");
+                
+        var prod2prodIdMapping = buildProd2ProdIDMapping(data);
+        var childrenMapping = buildChildrenMapping(data);
+        var rootElements = calculateRootElements(prodid, data);
+        
+        var allData = []
+        
+        rootElements.forEach(function(rg) {
+            var graphData = buildGraph(rg, null, childrenMapping, prod2prodIdMapping)
+            graphData.forEach(function (gd) { allData.push(gd); })
+        })
+                
+        result.object(allData);
     }
 }
 else
 {
     result.object([]);
-}
\ No newline at end of file
+}
diff --git a/entity/Prod2prod_entity/recordcontainers/jdito/onDelete.js b/entity/Prod2prod_entity/recordcontainers/jdito/onDelete.js
index 75472b57594f5b0bfac9304d844e36c49cd92f69..3f5b37d8a09c58c04eb400f106a90a33be140cdd 100644
--- a/entity/Prod2prod_entity/recordcontainers/jdito/onDelete.js
+++ b/entity/Prod2prod_entity/recordcontainers/jdito/onDelete.js
@@ -1,3 +1,4 @@
+import("system.vars");
 import("system.neon");
 import("system.db");
 import("Sql_lib");
@@ -7,4 +8,4 @@ db.deleteData("PROD2PROD", SqlCondition.begin()
                                        .build("1=2"));
 
 // Refresh otherwise the children of the deleted node would be moved to the root.
-neon.refresh()
\ No newline at end of file
+neon.refresh();
\ No newline at end of file
diff --git a/entity/Product_entity/Product_entity.aod b/entity/Product_entity/Product_entity.aod
index 817b35a0aaeb52d7568a803a4849315b561b2ece..5501274d1007cf1bd90afb2048a712f93ed4734e 100644
--- a/entity/Product_entity/Product_entity.aod
+++ b/entity/Product_entity/Product_entity.aod
@@ -279,8 +279,10 @@
     </entityConsumer>
     <entityField>
       <name>LANGUAGE</name>
-      <title>Language</title>
       <consumer>Languages</consumer>
+      <searchable v="false" />
+      <titleProcess>%aditoprj%/entity/Product_entity/entityfields/language/titleProcess.js</titleProcess>
+      <displayValueProcess>%aditoprj%/entity/Product_entity/entityfields/language/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityConsumer>
       <name>Languages</name>
diff --git a/entity/Product_entity/entityfields/language/displayValueProcess.js b/entity/Product_entity/entityfields/language/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..de5246774faf8a3f68bea969823cf3fe462d1504
--- /dev/null
+++ b/entity/Product_entity/entityfields/language/displayValueProcess.js
@@ -0,0 +1,10 @@
+import("system.db");
+import("system.translate");
+import("system.vars");
+import("system.result");
+import("KeywordRegistry_basic");
+import("Keyword_lib");
+import("Sql_lib");
+
+result.string(translate.text(db.cell(SqlCondition.begin().andPrepareVars("AB_LANGUAGE.ISO3", "$field.LANGUAGE")
+                                   .buildSql("select NAME_LATIN from AB_LANGUAGE", "1=2"))));
diff --git a/entity/Product_entity/entityfields/language/titleProcess.js b/entity/Product_entity/entityfields/language/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..04be2c545b0879ee1106eeb333161b65e5520edf
--- /dev/null
+++ b/entity/Product_entity/entityfields/language/titleProcess.js
@@ -0,0 +1,4 @@
+import("system.translate");
+import("system.result");
+
+result.string(translate.text("Language") + " (" + translate.text("Description") + ")");
\ No newline at end of file
diff --git a/entity/SalesprojectCompetition_entity/SalesprojectCompetition_entity.aod b/entity/SalesprojectCompetition_entity/SalesprojectCompetition_entity.aod
index bdd5fa2a86d27e88650268b235c03f7846d46d3a..0df2e74d7c286b06191944b2c34905f90ccf6324 100644
--- a/entity/SalesprojectCompetition_entity/SalesprojectCompetition_entity.aod
+++ b/entity/SalesprojectCompetition_entity/SalesprojectCompetition_entity.aod
@@ -219,6 +219,7 @@
       <name>Attributes</name>
       <title>Attributes</title>
       <fieldType>DEPENDENCY_OUT</fieldType>
+      <state>DISABLED</state>
       <dependency>
         <name>dependency</name>
         <entityName>AttributeRelation_entity</entityName>
@@ -228,17 +229,15 @@
         <entityParameter>
           <name>FilteredAttributeIds_param</name>
           <valueProcess>%aditoprj%/entity/SalesprojectCompetition_entity/entityfields/attributes/children/filteredattributeids_param/valueProcess.js</valueProcess>
-          <expose v="false" />
         </entityParameter>
         <entityParameter>
           <name>ObjectRowId_param</name>
           <valueProcess>%aditoprj%/entity/SalesprojectCompetition_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js</valueProcess>
-          <expose v="false" />
+          <triggerRecalculation v="true" />
         </entityParameter>
         <entityParameter>
           <name>ObjectType_param</name>
           <valueProcess>%aditoprj%/entity/SalesprojectCompetition_entity/entityfields/attributes/children/objecttype_param/valueProcess.js</valueProcess>
-          <expose v="false" />
         </entityParameter>
         <entityParameter>
           <name>DisplaySimpleName_param</name>
diff --git a/entity/SalesprojectCompetition_entity/entityfields/attributes/children/objecttype_param/valueProcess.js b/entity/SalesprojectCompetition_entity/entityfields/attributes/children/objecttype_param/valueProcess.js
index 41202c0153c75fda1c5eb90ea3a2f09178ba6df9..9acfa14adab3e82729a6f5f57b0aa1b4b1bbadad 100644
--- a/entity/SalesprojectCompetition_entity/entityfields/attributes/children/objecttype_param/valueProcess.js
+++ b/entity/SalesprojectCompetition_entity/entityfields/attributes/children/objecttype_param/valueProcess.js
@@ -1,3 +1,7 @@
+import("system.vars");
 import("system.result");
 
-result.string("Organisation");
+if (vars.get("$field.CONTACT_ID"))
+    result.string("Organisation");
+else
+    result.string("true");
\ No newline at end of file
diff --git a/entity/SalesprojectMember_entity/SalesprojectMember_entity.aod b/entity/SalesprojectMember_entity/SalesprojectMember_entity.aod
index c3eb99ba47e7650aee1aa15b0a8041597ab9a5f7..34540f9d1108c7c08cfefad0eaf52bb364a250b3 100644
--- a/entity/SalesprojectMember_entity/SalesprojectMember_entity.aod
+++ b/entity/SalesprojectMember_entity/SalesprojectMember_entity.aod
@@ -13,6 +13,7 @@
       <title>Person</title>
       <consumer>Contacts</consumer>
       <linkedContext>Person</linkedContext>
+      <mandatory v="true" />
     </entityField>
     <entityField>
       <name>SALESPROJECT_ID</name>
@@ -136,12 +137,12 @@ TODO: intuitive möglichkeit, auf dend Stand aus Relation zurückzusetzen... akt
       <dependency>
         <name>dependency</name>
         <entityName>Person_entity</entityName>
-        <fieldName>SalesprojectMemberContact</fieldName>
+        <fieldName>Contacts</fieldName>
       </dependency>
       <children>
         <entityParameter>
-          <name>SalesprojectId_param</name>
-          <valueProcess>%aditoprj%/entity/SalesprojectMember_entity/entityfields/contacts/children/salesprojectid_param/valueProcess.js</valueProcess>
+          <name>ExcludedContactIds_param</name>
+          <valueProcess>%aditoprj%/entity/SalesprojectMember_entity/entityfields/contacts/children/excludedcontactids_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
     </entityConsumer>
diff --git a/entity/SalesprojectMember_entity/entityfields/contacts/children/excludedcontactids_param/valueProcess.js b/entity/SalesprojectMember_entity/entityfields/contacts/children/excludedcontactids_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..35ca5d0cce0f248a842d75e8ee8d987dee71646c
--- /dev/null
+++ b/entity/SalesprojectMember_entity/entityfields/contacts/children/excludedcontactids_param/valueProcess.js
@@ -0,0 +1,13 @@
+import("system.logging");
+import("system.result");
+import("system.vars");
+import("system.db");
+import("Sql_lib");
+
+logging.log(db.array(db.COLUMN, SqlCondition.begin()
+                                .andPrepare("SALESPROJECT_MEMBER.SALESPROJECT_ID", vars.get("$field.SALESPROJECT_ID"))
+                                .buildSql("select CONTACT_ID from SALESPROJECT_MEMBER", "1=2")).toSource())
+result.object(db.array(db.COLUMN, SqlCondition.begin()
+                                .andPrepare("SALESPROJECT_MEMBER.SALESPROJECT_ID", vars.get("$field.SALESPROJECT_ID"))
+                                .buildSql("select CONTACT_ID from SALESPROJECT_MEMBER", "1=2")));
+                     
\ No newline at end of file
diff --git a/entity/SalesprojectMember_entity/entityfields/contacts/children/salesprojectid_param/valueProcess.js b/entity/SalesprojectMember_entity/entityfields/contacts/children/salesprojectid_param/valueProcess.js
deleted file mode 100644
index 0456b23233a1ace988306c88ab36b7a26030d519..0000000000000000000000000000000000000000
--- a/entity/SalesprojectMember_entity/entityfields/contacts/children/salesprojectid_param/valueProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.SALESPROJECT_ID"));
\ No newline at end of file
diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod
index 0afca7b3a76b9976286d0fe1a8a0ae547bc69947..17fe6bc790f4cf96f24b1123de3666778a4a361b 100644
--- a/entity/Salesproject_entity/Salesproject_entity.aod
+++ b/entity/Salesproject_entity/Salesproject_entity.aod
@@ -63,6 +63,8 @@
       <consumer>Organisations</consumer>
       <linkedContext>Organisation</linkedContext>
       <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/contact_id/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/contact_id/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>SALESPROJECTID</name>
diff --git a/entity/Salesproject_entity/entityfields/contact_id/displayValueProcess.js b/entity/Salesproject_entity/entityfields/contact_id/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..85822946ab4fe0ba7730ca93fd6fca69250a5b33
--- /dev/null
+++ b/entity/Salesproject_entity/entityfields/contact_id/displayValueProcess.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("system.vars");
+import("Contact_lib");
+import("system.neon");
+
+result.string(ContactUtils.getFullTitleByContactId(vars.getString("$field.CONTACT_ID")));
\ No newline at end of file
diff --git a/entity/Salesproject_entity/entityfields/contact_id/valueProcess.js b/entity/Salesproject_entity/entityfields/contact_id/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1127220726ee436e1f878c4467fa29d976d6af80
--- /dev/null
+++ b/entity/Salesproject_entity/entityfields/contact_id/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.vars");
+
+if (vars.exists("$param.ContactId_param")) 
+{
+    result.string(vars.get("$param.ContactId_param"));
+}
\ No newline at end of file
diff --git a/entity/TaskLink_entity/TaskLink_entity.aod b/entity/TaskLink_entity/TaskLink_entity.aod
index b344727738c868237ab4e2d86201d6271f317278..2ed05178f41345dccfc5ad0bcbac2b6c96de1635 100644
--- a/entity/TaskLink_entity/TaskLink_entity.aod
+++ b/entity/TaskLink_entity/TaskLink_entity.aod
@@ -19,7 +19,6 @@
       <name>OBJECT_TYPE</name>
       <title>Object type</title>
       <consumer>Contexts</consumer>
-      <linkedContext>Context</linkedContext>
       <displayValueProcess>%aditoprj%/entity/TaskLink_entity/entityfields/object_type/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
diff --git a/entity/Task_entity/entityfields/editor_contact_id/displayValueProcess.js b/entity/Task_entity/entityfields/editor_contact_id/displayValueProcess.js
index ee76682f8edea5a240eab30e4a8dffdfe66ac907..0dde82e7728286629b1c210326725aac2ebb92c5 100644
--- a/entity/Task_entity/entityfields/editor_contact_id/displayValueProcess.js
+++ b/entity/Task_entity/entityfields/editor_contact_id/displayValueProcess.js
@@ -3,5 +3,6 @@ import("system.vars");
 import("Contact_lib");
 
 var id = vars.get("$this.value");
-var title = ContactUtils.getFullTitleByContactId(id);
+//show the simpel title since this will be later an employee-entry and therefore no organisation is needed
+var title = ContactUtils.getTitleByContactId(id);
 result.string(title);
\ No newline at end of file
diff --git a/entity/Task_entity/entityfields/requestor_contact_id/displayValueProcess.js b/entity/Task_entity/entityfields/requestor_contact_id/displayValueProcess.js
index ee76682f8edea5a240eab30e4a8dffdfe66ac907..0dde82e7728286629b1c210326725aac2ebb92c5 100644
--- a/entity/Task_entity/entityfields/requestor_contact_id/displayValueProcess.js
+++ b/entity/Task_entity/entityfields/requestor_contact_id/displayValueProcess.js
@@ -3,5 +3,6 @@ import("system.vars");
 import("Contact_lib");
 
 var id = vars.get("$this.value");
-var title = ContactUtils.getFullTitleByContactId(id);
+//show the simpel title since this will be later an employee-entry and therefore no organisation is needed
+var title = ContactUtils.getTitleByContactId(id);
 result.string(title);
\ No newline at end of file
diff --git a/entity/Task_entity/recordcontainers/db/onDBDelete.js b/entity/Task_entity/recordcontainers/db/onDBDelete.js
index 7857f671302c87c59f3123e3329ff7057a6b0e20..d19d38f6e972d7759782100f4a94d41fd3dd7944 100644
--- a/entity/Task_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Task_entity/recordcontainers/db/onDBDelete.js
@@ -5,5 +5,4 @@ import("Sql_lib");
 var condition = SqlCondition.begin()
     .andPrepareVars("TASKLINK.TASK_ID", "$field.TASKID");
 
-db.deleteData("TASKLINK", condition.build("1=2"));
-
+db.deleteData("TASKLINK", condition.build("1=2"));
\ No newline at end of file
diff --git a/entity/Timetracking_entity/Timetracking_entity.aod b/entity/Timetracking_entity/Timetracking_entity.aod
index 2030ef770a552d169b3996289c96c71cc605ace7..2ed0a5850b828c3e17503207bf87fe18c4cb5c9b 100644
--- a/entity/Timetracking_entity/Timetracking_entity.aod
+++ b/entity/Timetracking_entity/Timetracking_entity.aod
@@ -18,6 +18,7 @@
       <title>Time</title>
       <contentType>TEXT</contentType>
       <mandatory v="true" />
+      <titleProcess>%aditoprj%/entity/Timetracking_entity/entityfields/minutes/titleProcess.js</titleProcess>
       <displayValueProcess>%aditoprj%/entity/Timetracking_entity/entityfields/minutes/displayValueProcess.js</displayValueProcess>
       <onValidation>%aditoprj%/entity/Timetracking_entity/entityfields/minutes/onValidation.js</onValidation>
     </entityField>
diff --git a/entity/Timetracking_entity/entityfields/minutes/titleProcess.js b/entity/Timetracking_entity/entityfields/minutes/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c089b7246e8008c3b2c13874ed0f7b0cc8079cf1
--- /dev/null
+++ b/entity/Timetracking_entity/entityfields/minutes/titleProcess.js
@@ -0,0 +1,9 @@
+import("system.translate");
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+{
+    result.string(translate.text("Time in minutes"));
+}
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index bc8d9ae3becdd761b205365142fc771c72e3f5e7..8d92eabcd3e807ee82347555d8cd9a695bc98963 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -1164,9 +1164,6 @@
     <entry>
       <key>Attribute Usage</key>
     </entry>
-    <entry>
-      <key>Beziehung</key>
-    </entry>
     <entry>
       <key>Key</key>
     </entry>
@@ -2637,6 +2634,66 @@
     <entry>
       <key>Beginn</key>
     </entry>
+    <entry>
+      <key>${QUANTITY_LOWER_THAN_1}</key>
+    </entry>
+    <entry>
+      <key>This combination of person and organisation does already exist and can not be created once more.</key>
+    </entry>
+    <entry>
+      <key>New module</key>
+    </entry>
+    <entry>
+      <key>Time in minutes</key>
+    </entry>
+    <entry>
+      <key>Sales manager</key>
+    </entry>
+    <entry>
+      <key>IT</key>
+    </entry>
+    <entry>
+      <key>Administrator</key>
+    </entry>
+    <entry>
+      <key>Managing director</key>
+    </entry>
+    <entry>
+      <key>Production manager</key>
+    </entry>
+    <entry>
+      <key>Production</key>
+    </entry>
+    <entry>
+      <key>CEO</key>
+    </entry>
+    <entry>
+      <key>Purchasing manager</key>
+    </entry>
+    <entry>
+      <key>Marketing manager</key>
+    </entry>
+    <entry>
+      <key>IT manager</key>
+    </entry>
+    <entry>
+      <key>Marketing</key>
+    </entry>
+    <entry>
+      <key>CSO</key>
+    </entry>
+    <entry>
+      <key>Executive board</key>
+    </entry>
+    <entry>
+      <key>Supervisory board</key>
+    </entry>
+    <entry>
+      <key>Management</key>
+    </entry>
+    <entry>
+      <key>date of birth must not be in the future</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 f2cbdb9e35f964542393205a5ea8b9c0b990cfed..1b2d85edeefc137e190bca2afc45070c11a7d78e 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -50,10 +50,18 @@
       <key>${ADDRESS_STATE}</key>
       <value>Staat</value>
     </entry>
+    <entry>
+      <key>New module</key>
+      <value>Neuanlage</value>
+    </entry>
     <entry>
       <key>Show all contracts</key>
       <value>Alle Verträge anzeigen</value>
     </entry>
+    <entry>
+      <key>This combination of person and organisation does already exist and can not be created once more.</key>
+      <value>Diese Kombination aus Person und Organisation existiert bereits und kann daher nicht nocht ein mal angelegt werden.</value>
+    </entry>
     <entry>
       <key>Communication data</key>
       <value>Kommunikationsdaten</value>
@@ -110,6 +118,14 @@
       <key>${SALESPROJECT_MEMBER}</key>
       <value>Projektteam</value>
     </entry>
+    <entry>
+      <key>${QUANTITY_LOWER_THAN_1}</key>
+      <value>Die Menge muss mindestens 1 sein.</value>
+    </entry>
+    <entry>
+      <key>date of birth must not be in the future</key>
+      <value>Geburtsdatum darf nicht in der Zukunft liegen</value>
+    </entry>
     <entry>
       <key>Days inactive</key>
       <value>Tage inaktiv</value>
@@ -1325,7 +1341,7 @@
     </entry>
     <entry>
       <key>Attributes</key>
-      <value>Attribute</value>
+      <value>Eigenschaften</value>
     </entry>
     <entry>
       <key>Facebook</key>
@@ -1605,7 +1621,7 @@
     </entry>
     <entry>
       <key>Attribute Relation</key>
-      <value>Attributbeziehung</value>
+      <value>Eigenschaftsbeziehung</value>
     </entry>
     <entry>
       <key>My Dashboard</key>
@@ -1613,17 +1629,14 @@
     </entry>
     <entry>
       <key>Attribute Usage</key>
-      <value>Attributverwendung</value>
-    </entry>
-    <entry>
-      <key>Beziehung</key>
+      <value>Eigenschaftsverwendung</value>
     </entry>
     <entry>
       <key>Key</key>
     </entry>
     <entry>
       <key>Attribute</key>
-      <value>Attribut</value>
+      <value>Eigenschaft</value>
     </entry>
     <entry>
       <key>Container</key>
@@ -1931,7 +1944,7 @@
     </entry>
     <entry>
       <key>Superordinate Attribute</key>
-      <value>Ãœbergeordnetes Attribut</value>
+      <value>Ãœbergeordnete Eigenschaft</value>
     </entry>
     <entry>
       <key>Kyrgyzstan</key>
@@ -3328,6 +3341,68 @@
       <key>Price policy</key>
       <value>Preispolitik</value>
     </entry>
+    <entry>
+      <key>VAT in %</key>
+      <value>UmsSt. in %</value>
+    </entry>
+    <entry>
+      <key>Time in minutes</key>
+      <value>Zeit in Minuten</value>
+    </entry>
+    <entry>
+      <key>Sales manager</key>
+      <value>Vertriebsleiter</value>
+    </entry>
+    <entry>
+      <key>IT</key>
+    </entry>
+    <entry>
+      <key>Administrator</key>
+    </entry>
+    <entry>
+      <key>Managing director</key>
+      <value>Geschäftsführer</value>
+    </entry>
+    <entry>
+      <key>Production manager</key>
+      <value>Produktionsleiter</value>
+    </entry>
+    <entry>
+      <key>Production</key>
+      <value>Produktion</value>
+    </entry>
+    <entry>
+      <key>CEO</key>
+    </entry>
+    <entry>
+      <key>Purchasing manager</key>
+      <value>Einkaufsleiter</value>
+    </entry>
+    <entry>
+      <key>Marketing manager</key>
+      <value>Marketingleiter</value>
+    </entry>
+    <entry>
+      <key>IT manager</key>
+      <value>IT-Leiter</value>
+    </entry>
+    <entry>
+      <key>Marketing</key>
+    </entry>
+    <entry>
+      <key>CSO</key>
+    </entry>
+    <entry>
+      <key>Executive board</key>
+      <value>Vorstand</value>
+    </entry>
+    <entry>
+      <key>Supervisory board</key>
+      <value>Aufsichtsrat</value>
+    </entry>
+    <entry>
+      <key>Management</key>
+    </entry>
     <entry>
       <key>Approved</key>
       <value>Freigegeben</value>
@@ -3355,18 +3430,12 @@
     <entry>
       <key>Teilnehmer</key>
     </entry>
-    <entry>
-      <key>VAT in %</key>
-    </entry>
     <entry>
       <key>Kampagnen Schritte</key>
     </entry>
     <entry>
       <key>Kampagnenschritte</key>
     </entry>
-    <entry>
-      <key>Marketing</key>
-    </entry>
     <entry>
       <key>Die maximale Anzahl Teilnehmer ist erreicht!</key>
     </entry>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index e860ccd032dce35da10f7735638cee1e68909357..e005a417e7dca0974e0fc1a89a3bd144ad36df40 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -521,7 +521,7 @@
     </entry>
     <entry>
       <key>${EURO_SIGN}</key>
-      <value>�</value>
+      <value>?</value>
     </entry>
     <entry>
       <key>Planned</key>
@@ -1184,9 +1184,6 @@
     <entry>
       <key>Attribute Usage</key>
     </entry>
-    <entry>
-      <key>Beziehung</key>
-    </entry>
     <entry>
       <key>Key</key>
     </entry>
@@ -1217,9 +1214,6 @@
     <entry>
       <key>Context name</key>
     </entry>
-    <entry>
-      <key>Schlüsselwort</key>
-    </entry>
     <entry>
       <key>Cambodia</key>
     </entry>
@@ -1307,9 +1301,6 @@
     <entry>
       <key>Jordan</key>
     </entry>
-    <entry>
-      <key>Côte d'Ivoire</key>
-    </entry>
     <entry>
       <key>United Arab Emirates</key>
     </entry>
@@ -1677,9 +1668,6 @@
     <entry>
       <key>Kazakhstan</key>
     </entry>
-    <entry>
-      <key>Ã…land Islands</key>
-    </entry>
     <entry>
       <key>Bahamas</key>
     </entry>
@@ -1958,9 +1946,6 @@
     <entry>
       <key>Ukraine</key>
     </entry>
-    <entry>
-      <key>Curaçao</key>
-    </entry>
     <entry>
       <key>Anguilla</key>
     </entry>
@@ -2057,9 +2042,6 @@
     <entry>
       <key>ended</key>
     </entry>
-    <entry>
-      <key>Saint Barthélemy</key>
-    </entry>
     <entry>
       <key>Wallis and Futuna</key>
     </entry>
@@ -2075,9 +2057,6 @@
     <entry>
       <key>Hungary</key>
     </entry>
-    <entry>
-      <key>Réunion</key>
-    </entry>
     <entry>
       <key>Japan</key>
     </entry>
@@ -2484,9 +2463,6 @@
     <entry>
       <key>Other Contactroles</key>
     </entry>
-    <entry>
-      <key>Bitte Datumseingabe prüfen!</key>
-    </entry>
     <entry>
       <key>In Bearbeitung</key>
     </entry>
@@ -2499,12 +2475,6 @@
     <entry>
       <key>Bitte Filterbedingungen setzen</key>
     </entry>
-    <entry>
-      <key>Bestätigt</key>
-    </entry>
-    <entry>
-      <key>Vorläufig</key>
-    </entry>
     <entry>
       <key>keine</key>
     </entry>
@@ -2517,18 +2487,12 @@
     <entry>
       <key>&amp;Aufgaben (%0)</key>
     </entry>
-    <entry>
-      <key>erledigt / zurückgestellt</key>
-    </entry>
     <entry>
       <key>hoch</key>
     </entry>
     <entry>
       <key>Keine Berechtigung zum Verschieben der Aufgabe</key>
     </entry>
-    <entry>
-      <key>Zurückgestellt</key>
-    </entry>
     <entry>
       <key>Erledigt</key>
     </entry>
@@ -2538,24 +2502,15 @@
     <entry>
       <key>Abgesagt</key>
     </entry>
-    <entry>
-      <key>Außer Haus</key>
-    </entry>
     <entry>
       <key>Abbrechen</key>
     </entry>
-    <entry>
-      <key>Benutzer auswählen</key>
-    </entry>
     <entry>
       <key>delegiert</key>
     </entry>
     <entry>
       <key>frei</key>
     </entry>
-    <entry>
-      <key>Kein Weitergeben von privaten Aufgaben möglich!</key>
-    </entry>
     <entry>
       <key>%0 Aufgabe(n) erfolgreich weitergegeben an: %1</key>
     </entry>
@@ -2661,6 +2616,109 @@
     <entry>
       <key>Beginn</key>
     </entry>
+    <entry>
+      <key>${QUANTITY_LOWER_THAN_1}</key>
+      <value>Quantity should be greater than 0.</value>
+    </entry>
+    <entry>
+      <key>This combination of person and organisation does already exist and can not be created once more.</key>
+    </entry>
+    <entry>
+      <key>Time in minutes</key>
+    </entry>
+    <entry>
+      <key>Sales manager</key>
+    </entry>
+    <entry>
+      <key>IT</key>
+    </entry>
+    <entry>
+      <key>Administrator</key>
+    </entry>
+    <entry>
+      <key>Managing director</key>
+    </entry>
+    <entry>
+      <key>Production manager</key>
+    </entry>
+    <entry>
+      <key>Production</key>
+    </entry>
+    <entry>
+      <key>CEO</key>
+    </entry>
+    <entry>
+      <key>Purchasing manager</key>
+    </entry>
+    <entry>
+      <key>Marketing manager</key>
+    </entry>
+    <entry>
+      <key>IT manager</key>
+    </entry>
+    <entry>
+      <key>Marketing</key>
+    </entry>
+    <entry>
+      <key>CSO</key>
+    </entry>
+    <entry>
+      <key>Executive board</key>
+    </entry>
+    <entry>
+      <key>Supervisory board</key>
+    </entry>
+    <entry>
+      <key>Management</key>
+    </entry>
+    <entry>
+      <key>New module</key>
+    </entry>
+    <entry>
+      <key>Côte d'Ivoire</key>
+    </entry>
+    <entry>
+      <key>Bitte Datumseingabe prüfen!</key>
+    </entry>
+    <entry>
+      <key>Bestätigt</key>
+    </entry>
+    <entry>
+      <key>Vorläufig</key>
+    </entry>
+    <entry>
+      <key>Saint Barthélemy</key>
+    </entry>
+    <entry>
+      <key>erledigt / zurückgestellt</key>
+    </entry>
+    <entry>
+      <key>Zurückgestellt</key>
+    </entry>
+    <entry>
+      <key>Außer Haus</key>
+    </entry>
+    <entry>
+      <key>Benutzer auswählen</key>
+    </entry>
+    <entry>
+      <key>Ã…land Islands</key>
+    </entry>
+    <entry>
+      <key>Kein Weitergeben von privaten Aufgaben möglich!</key>
+    </entry>
+    <entry>
+      <key>Curaçao</key>
+    </entry>
+    <entry>
+      <key>Schlüsselwort</key>
+    </entry>
+    <entry>
+      <key>Réunion</key>
+    </entry>
+    <entry>
+      <key>date of birth must not be in the future</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/ActivityLink/ActivityLink.aod b/neonContext/ActivityLink/ActivityLink.aod
index bbb417a30f5b1f49440db45754f0771793adb440..dfc2613a966bd617ce4d43c74b82624fadb3222d 100644
--- a/neonContext/ActivityLink/ActivityLink.aod
+++ b/neonContext/ActivityLink/ActivityLink.aod
@@ -18,5 +18,9 @@
       <name>0960878d-9077-4707-8239-b48f1b55a5e8</name>
       <view>ActivityLinkMultiEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>e814dfa7-68da-485f-aea1-462197b33f67</name>
+      <view>ActivityLinkPreviewList_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonContext/AppointmentLink/AppointmentLink.aod b/neonContext/AppointmentLink/AppointmentLink.aod
index b94adc147f351d19022f3bf95be805d1a4296c4f..bfe84c66b362cdc82cee99227b0332604b78af00 100644
--- a/neonContext/AppointmentLink/AppointmentLink.aod
+++ b/neonContext/AppointmentLink/AppointmentLink.aod
@@ -1,13 +1,19 @@
-<?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>AppointmentLink</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <filterview>AppointmentLinkFilter_view</filterview>
-  <entity>AppointmentLink_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>015bf8e9-621a-423d-8fd3-17ef264cc919</name>
-      <view>AppointmentLinkFilter_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>AppointmentLink</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <mainview>AppointmentLinkFilter_view</mainview>
+  <filterview>AppointmentLinkFilter_view</filterview>
+  <editview>AppointmentLinkEdit_view</editview>
+  <entity>AppointmentLink_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>015bf8e9-621a-423d-8fd3-17ef264cc919</name>
+      <view>AppointmentLinkEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>f0f803a8-74a4-4a96-a989-d3923b994280</name>
+      <view>AppointmentLinkFilter_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/TaskLink/TaskLink.aod b/neonContext/TaskLink/TaskLink.aod
index 5e6273ddc3888e299586124b1da02845f2a1a83d..4ac1b80b124d0f35484bae8ee83160581f5ca6dd 100644
--- a/neonContext/TaskLink/TaskLink.aod
+++ b/neonContext/TaskLink/TaskLink.aod
@@ -16,5 +16,9 @@
       <name>cd180425-6562-49d9-99be-f3a47a88f427</name>
       <view>TaskLinkMultiEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>8799454a-92af-4604-8e6c-9323f745a258</name>
+      <view>TaskLinkPreviewList_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonView/360DegreeFilter_view/360DegreeFilter_view.aod b/neonView/360DegreeFilter_view/360DegreeFilter_view.aod
index ae98a9499c021eaa9fbf4c39dbbc700a1e4dfb7c..49cd28ef684616c9a327bb3154b7a50ecf026c02 100644
--- a/neonView/360DegreeFilter_view/360DegreeFilter_view.aod
+++ b/neonView/360DegreeFilter_view/360DegreeFilter_view.aod
@@ -11,9 +11,21 @@
   <children>
     <treetableViewTemplate>
       <name>Treetable</name>
+      <favoriteActionGroup2>newModule</favoriteActionGroup2>
       <titleField>TITLE</titleField>
-      <descriptionField>CONTEXT_NAME</descriptionField>
+      <descriptionField>DATE</descriptionField>
+      <iconField>ICON</iconField>
+      <defaultGroupFields>
+        <element>CONTEXT_NAME</element>
+      </defaultGroupFields>
       <entityField>#ENTITY</entityField>
     </treetableViewTemplate>
+    <timelineViewTemplate>
+      <name>Timeline</name>
+      <dateField>DATE</dateField>
+      <titleField>TITLE</titleField>
+      <descriptionField>CONTEXT_NAME</descriptionField>
+      <entityField>#ENTITY</entityField>
+    </timelineViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/ActivityLinkMultiEdit_view/ActivityLinkMultiEdit_view.aod b/neonView/ActivityLinkMultiEdit_view/ActivityLinkMultiEdit_view.aod
index dbb50a2c7e82b3a4502739261b0063347836bdd6..4a89c482527271f87e892a06102a45a2059fa55c 100644
--- a/neonView/ActivityLinkMultiEdit_view/ActivityLinkMultiEdit_view.aod
+++ b/neonView/ActivityLinkMultiEdit_view/ActivityLinkMultiEdit_view.aod
@@ -3,13 +3,13 @@
   <name>ActivityLinkMultiEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <noneLayout>
       <name>layout</name>
-    </boxLayout>
+    </noneLayout>
   </layout>
   <children>
     <genericMultipleViewTemplate>
-      <name>GenericMultiple</name>
+      <name>MultipleEdit</name>
       <entityField>#ENTITY</entityField>
       <title></title>
       <columns>
diff --git a/neonView/ActivityLinkPreviewList_view/ActivityLinkPreviewList_view.aod b/neonView/ActivityLinkPreviewList_view/ActivityLinkPreviewList_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..283d81b544b269270250d9876510cd019e090a23
--- /dev/null
+++ b/neonView/ActivityLinkPreviewList_view/ActivityLinkPreviewList_view.aod
@@ -0,0 +1,26 @@
+<?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
+  <name>ActivityLinkPreviewList_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <titledListViewTemplate>
+      <name>ActivityLinks</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>7db98c3e-2203-4af1-a155-5f4d62bd0ef8</name>
+          <entityField>OBJECT_TYPE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>063acc6e-1a7f-48a2-8204-a2adaf6ffdb4</name>
+          <entityField>OBJECT_ROWID</entityField>
+        </neonTableColumn>
+      </columns>
+    </titledListViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/ActivityPreview_view/ActivityPreview_view.aod b/neonView/ActivityPreview_view/ActivityPreview_view.aod
index 9d177fb190408712e29818f436561a90a0ac2f14..6604909f9efe863e8ca0d180006ae49fa12388c7 100644
--- a/neonView/ActivityPreview_view/ActivityPreview_view.aod
+++ b/neonView/ActivityPreview_view/ActivityPreview_view.aod
@@ -39,6 +39,11 @@
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
+    <neonViewReference>
+      <name>4c365613-81c5-4518-8953-751b5ae35cc2</name>
+      <entityField>Links</entityField>
+      <view>ActivityLinkPreviewList_view</view>
+    </neonViewReference>
     <neonViewReference>
       <name>43167618-e4dc-429b-a264-3ea95bd647f9</name>
       <entityField>MainDocuments</entityField>
diff --git a/neonView/AppointmentEdit_view/AppointmentEdit_view.aod b/neonView/AppointmentEdit_view/AppointmentEdit_view.aod
index be63a39d838da91006a0f8693183a6262a809130..e79161768321a1e2a543538a1c40101a9a6720d4 100644
--- a/neonView/AppointmentEdit_view/AppointmentEdit_view.aod
+++ b/neonView/AppointmentEdit_view/AppointmentEdit_view.aod
@@ -1,41 +1,41 @@
-<?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
-  <name>AppointmentEdit_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/neonView/AppointmentEdit_view/documentation.adoc</documentation>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <appointmentEditViewTemplate>
-      <name>Edit</name>
-      <summaryField>SUMMARY</summaryField>
-      <descriptionField>DESCRIPTION</descriptionField>
-      <beginField>BEGIN</beginField>
-      <endField>END</endField>
-      <attendeesField>ATTENDEES</attendeesField>
-      <privateField>CLASSIFICATION</privateField>
-      <statusField>STATUS</statusField>
-      <locationField>LOCATION</locationField>
-      <categoriesField>CATEGORIES</categoriesField>
-      <alldayField>ALLDAY</alldayField>
-      <transparencyField>TRANSPARENCY</transparencyField>
-      <organizerField>ORGANIZER</organizerField>
-      <favoriteActionGroup1>PartStatActionGroup</favoriteActionGroup1>
-      <rruleField>RRULE</rruleField>
-      <recurrenceIdField>RECURRENCEID</recurrenceIdField>
-      <saveScopeField>SAFESCOPEFIELD</saveScopeField>
-      <masterBeginField>MASTERBEGIN</masterBeginField>
-      <masterEndField>MASTEREND</masterEndField>
-      <reminderField>REMINDER</reminderField>
-      <entityField>#ENTITY</entityField>
-    </appointmentEditViewTemplate>
-    <neonViewReference>
-      <name>39802b49-f67c-4796-ba05-105aa073d60c</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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
+  <name>AppointmentEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <documentation>%aditoprj%/neonView/AppointmentEdit_view/documentation.adoc</documentation>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <appointmentEditViewTemplate>
+      <name>Edit</name>
+      <summaryField>SUMMARY</summaryField>
+      <descriptionField>DESCRIPTION</descriptionField>
+      <beginField>BEGIN</beginField>
+      <endField>END</endField>
+      <attendeesField>ATTENDEES</attendeesField>
+      <privateField>CLASSIFICATION</privateField>
+      <statusField>STATUS</statusField>
+      <locationField>LOCATION</locationField>
+      <categoriesField>CATEGORIES</categoriesField>
+      <alldayField>ALLDAY</alldayField>
+      <transparencyField>TRANSPARENCY</transparencyField>
+      <organizerField>ORGANIZER</organizerField>
+      <favoriteActionGroup1>PartStatActionGroup</favoriteActionGroup1>
+      <rruleField>RRULE</rruleField>
+      <recurrenceIdField>RECURRENCEID</recurrenceIdField>
+      <saveScopeField>SAFESCOPEFIELD</saveScopeField>
+      <masterBeginField>MASTERBEGIN</masterBeginField>
+      <masterEndField>MASTEREND</masterEndField>
+      <reminderField>REMINDER</reminderField>
+      <entityField>#ENTITY</entityField>
+    </appointmentEditViewTemplate>
+    <neonViewReference>
+      <name>39802b49-f67c-4796-ba05-105aa073d60c</name>
+      <entityField>AppointmentLinks</entityField>
+      <view>AppointmentLinkEdit_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/neonView/AppointmentLinkEdit_view/AppointmentLinkEdit_view.aod b/neonView/AppointmentLinkEdit_view/AppointmentLinkEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..67f76f8509ea4c9d949beb3501f33aa7cf66648b
--- /dev/null
+++ b/neonView/AppointmentLinkEdit_view/AppointmentLinkEdit_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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
+  <name>AppointmentLinkEdit_view</name>
+  <title>relations</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <genericMultipleViewTemplate>
+      <name>GenericMultiple</name>
+      <autoNewRow v="true" />
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>539c9844-8f4b-49e8-8974-30bdf127f47c</name>
+          <entityField>OBJECTTYPE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>eba00f45-cd7e-43c0-9dea-559293ca7d49</name>
+          <entityField>OBJECTID</entityField>
+        </neonTableColumn>
+      </columns>
+    </genericMultipleViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/AppointmentLinkFilter_view/AppointmentLinkFilter_view.aod b/neonView/AppointmentLinkFilter_view/AppointmentLinkFilter_view.aod
index b08bd63a17172ab61584ea63a6547f286f1e91ca..617858db80891671276f960511b634c5558fc71b 100644
--- a/neonView/AppointmentLinkFilter_view/AppointmentLinkFilter_view.aod
+++ b/neonView/AppointmentLinkFilter_view/AppointmentLinkFilter_view.aod
@@ -10,7 +10,7 @@
   </layout>
   <children>
     <genericMultipleViewTemplate>
-      <name>GenericMultiple</name>
+      <name>MultipleEdit</name>
       <autoNewRow v="true" />
       <entityField>#ENTITY</entityField>
       <columns>
diff --git a/neonView/AppointmentPreview_view/AppointmentPreview_view.aod b/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
index 18b38cef92009cd7959d260a5d5eb1a3fd54a75d..f35b4d193702ad30b3710b388d83e2f6e6bd2b81 100644
--- a/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
+++ b/neonView/AppointmentPreview_view/AppointmentPreview_view.aod
@@ -1,31 +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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
-  <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>
-  </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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
+  <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>
diff --git a/neonView/ContactEdit_view/ContactEdit_view.aod b/neonView/ContactEdit_view/ContactEdit_view.aod
index 861b5da3b0759316b1599cc08905dcd7cf205ee7..7e82ca816b891919c2950d31c1a5ba4e24480d73 100644
--- a/neonView/ContactEdit_view/ContactEdit_view.aod
+++ b/neonView/ContactEdit_view/ContactEdit_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>data</name>
+      <name>Edit</name>
       <editMode v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
diff --git a/neonView/ContactList_view/ContactList_view.aod b/neonView/ContactList_view/ContactList_view.aod
index c52c92ef4741d91032467412dfa1469157f82f3a..f950d771e5d8211a6471d32ae89639f7e954edf6 100644
--- a/neonView/ContactList_view/ContactList_view.aod
+++ b/neonView/ContactList_view/ContactList_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <tableViewTemplate>
-      <name>main</name>
+      <name>Contacts</name>
       <hideContentSearch v="true" />
       <isEditable v="false" />
       <entityField>#ENTITY</entityField>
diff --git a/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod b/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod
index 6f70290d7787093b3f9fd0bb651184b69a4ce89b..c3d91906c2b7d851a3dd5eb4453a6bddbc1fb7d8 100644
--- a/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod
+++ b/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod
@@ -9,6 +9,15 @@
     </groupLayout>
   </layout>
   <children>
+    <treetableViewTemplate>
+      <name>EntriesTreetable</name>
+      <titleField>TITLE</titleField>
+      <descriptionField>KEYID</descriptionField>
+      <defaultGroupFields>
+        <element>CONTAINER</element>
+      </defaultGroupFields>
+      <entityField>#ENTITY</entityField>
+    </treetableViewTemplate>
     <tableViewTemplate>
       <name>EntriesTable</name>
       <entityField>#ENTITY</entityField>
@@ -40,11 +49,5 @@
         </neonTableColumn>
       </columns>
     </tableViewTemplate>
-    <treetableViewTemplate>
-      <name>EntriesTreetable</name>
-      <titleField>TITLE</titleField>
-      <descriptionField>KEYID</descriptionField>
-      <entityField>#ENTITY</entityField>
-    </treetableViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/OfferFilter_view/OfferFilter_view.aod b/neonView/OfferFilter_view/OfferFilter_view.aod
index 8bd1c5f25d7e107d260c2752f565a3fa913f71ac..edf7596f2f4c18361445c97edeffb08b8f034e8d 100644
--- a/neonView/OfferFilter_view/OfferFilter_view.aod
+++ b/neonView/OfferFilter_view/OfferFilter_view.aod
@@ -27,7 +27,7 @@
       <name>SendOffersDashlet</name>
       <title>Sent offers</title>
       <description>Show all sent offers</description>
-      <fragment>Offer/filter?search=W3sibmFtZSI6IlNUQVRVUyIsIm9wZXJhdG9yIjoiRVFVQUwiLCJ2YWx1ZUtleSI6IjIiLCJ2YWx1ZSI6IlZlcnNlbmRldCIsImNvbnRlbnRUeXBlIjoiVEVYVCJ9XQ%253D%253D</fragment>
+      <fragment>Offer/filter?search=W3sibmFtZSI6IlNUQVRVUyIsIm9wZXJhdG9yIjoiRVFVQUwiLCJ2YWx1ZSI6ImU1ZDZiNWE0LTc1NzYtNDQwZi04MzMyLWJjNDAxNDdjMDMzNSIsImNvbnRlbnRUeXBlIjoiVEVYVCJ9XQ%253D%253D</fragment>
       <singleton v="true" />
       <requiresConfiguration v="false" />
       <icon>vaadin:cart</icon>
diff --git a/neonView/OrderDetail_view/OrderDetail_view.aod b/neonView/OrderDetail_view/OrderDetail_view.aod
index 47464d32f38fa46162c2a201c54c8955058c50de..8af0f327beedd58192253d3a037bc651bdc95f32 100644
--- a/neonView/OrderDetail_view/OrderDetail_view.aod
+++ b/neonView/OrderDetail_view/OrderDetail_view.aod
@@ -10,7 +10,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>OrderDetail_template</name>
+      <name>Details</name>
       <showDrawer v="true" />
       <drawerCaption>Detail</drawerCaption>
       <entityField>#ENTITY</entityField>
diff --git a/neonView/OrganisationEdit_view/OrganisationEdit_view.aod b/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
index 812914dec3dc2f45baedc4f12e8e05917b4f9e73..4a26e105858fe0e8c020f908c761467558a768e4 100644
--- a/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
+++ b/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
@@ -44,7 +44,7 @@
     </genericViewTemplate>
     <neonViewReference>
       <name>148e3a6c-d30b-470c-84e5-273293348611</name>
-      <entityField>OrganisationAddresses</entityField>
+      <entityField>Addresses</entityField>
       <view>AdressMultiEdit_view</view>
     </neonViewReference>
     <neonViewReference>
diff --git a/neonView/OrganisationMain_view/OrganisationMain_view.aod b/neonView/OrganisationMain_view/OrganisationMain_view.aod
index 7a18c8683f39a1eecf774323977a942b8a94aafa..3e7ccf4980fd9dbc0b4cf0a6d79e67e4daba73ec 100644
--- a/neonView/OrganisationMain_view/OrganisationMain_view.aod
+++ b/neonView/OrganisationMain_view/OrganisationMain_view.aod
@@ -45,16 +45,6 @@
       <entityField>Documents</entityField>
       <view>DocumentFilter_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>50f61cda-5f85-4212-b3b2-3a55b9fae54d</name>
-      <entityField>Offers</entityField>
-      <view>OfferFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>fd099297-e87d-4ada-b7e7-e04afafbd8b0</name>
-      <entityField>Contracts</entityField>
-      <view>ContractFilter_view</view>
-    </neonViewReference>
     <neonViewReference>
       <name>ab7d3db4-af9d-4903-b28a-6347f2512a54</name>
       <entityField>ObjectRelations</entityField>
@@ -70,10 +60,5 @@
       <entityField>Attributes</entityField>
       <view>AttributeRelationFilter_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>dc1aa0ca-d0bd-45fd-84dc-55cfcf3ca430</name>
-      <entityField>Salesprojects</entityField>
-      <view>SalesprojectFilter_view</view>
-    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/PersonEdit_view/PersonEdit_view.aod b/neonView/PersonEdit_view/PersonEdit_view.aod
index 55ea2a761ba85c258981ef0ce2ca8c6e21d23f12..97dfc7bb74265146568a0df9e75d2a15833e6f8b 100644
--- a/neonView/PersonEdit_view/PersonEdit_view.aod
+++ b/neonView/PersonEdit_view/PersonEdit_view.aod
@@ -57,6 +57,18 @@
           <name>f8ec0e41-7ead-4c80-878c-df75ce5fce34</name>
           <entityField>STATUS</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>16b3b029-eed3-45b7-94b0-446c89d70594</name>
+          <entityField>DEPARTMENT</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>720ba110-faa2-4c64-823b-82a2089f337c</name>
+          <entityField>CONTACTROLE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>7bad6e30-fda3-4ee4-858c-712a60437397</name>
+          <entityField>POSITION</entityField>
+        </entityFieldLink>
       </fields>
     </genericViewTemplate>
     <neonViewReference>
diff --git a/neonView/PersonMain_view/PersonMain_view.aod b/neonView/PersonMain_view/PersonMain_view.aod
index c27980a4d2bd69fc3363fc3246522c1e9dab783c..afe8033aeea91388e82572f75e0c350f0524b51b 100644
--- a/neonView/PersonMain_view/PersonMain_view.aod
+++ b/neonView/PersonMain_view/PersonMain_view.aod
@@ -19,6 +19,11 @@
       <entityField>Activities</entityField>
       <view>ActivityFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>e7b8c90f-dc8d-40f1-b4db-1493f845026f</name>
+      <entityField>360DegreeObjects</entityField>
+      <view>360DegreeFilter_view</view>
+    </neonViewReference>
     <neonViewReference>
       <name>573d2b77-f948-47bc-bac1-621dd824c697</name>
       <entityField>Tasks</entityField>
@@ -29,16 +34,6 @@
       <entityField>Documents</entityField>
       <view>DocumentFilter_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>0cb8f431-0377-45cb-a41b-a5716efb0fd0</name>
-      <entityField>Offers</entityField>
-      <view>OfferFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>ec344a07-7b82-4c54-b06b-30ac5b8599f9</name>
-      <entityField>Contracts</entityField>
-      <view>ContractFilter_view</view>
-    </neonViewReference>
     <neonViewReference>
       <name>a713a58e-eae0-4657-9cb0-ffffbd41d4ab</name>
       <entityField>ObjectRelations</entityField>
diff --git a/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod b/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod
index e1258b43a52bae03fc2ade6bda6bfda3d03269e0..9b2cb02c7a09f21a2b096bbd60404deb67971bd0 100644
--- a/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod
+++ b/neonView/Prod2ProdEdit_view/Prod2ProdEdit_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>linkData</name>
+      <name>Edit</name>
       <editMode v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
diff --git a/neonView/Prod2prodFilter_view/Prod2prodFilter_view.aod b/neonView/Prod2prodFilter_view/Prod2prodFilter_view.aod
index b22717b6dc3e85d0af6f3d8b88d740f7f67ceb3c..eeaf321c7d4fb8abf36121ada2ec9a394a9c7aa2 100644
--- a/neonView/Prod2prodFilter_view/Prod2prodFilter_view.aod
+++ b/neonView/Prod2prodFilter_view/Prod2prodFilter_view.aod
@@ -11,7 +11,7 @@
   <children>
     <treetableViewTemplate>
       <name>Partlist</name>
-      <parentField>PARENTID</parentField>
+      <parentField>DEST_ID</parentField>
       <favoriteActionGroup1>alter</favoriteActionGroup1>
       <titleField>PRODUCTCODE</titleField>
       <descriptionField>QUANTITY</descriptionField>
diff --git a/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod b/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod
index badeadd20fbc20a68526aec3aa629834da7c35d5..16ddeeaa248d7712b685e16dc2f590662dfe4796 100644
--- a/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod
+++ b/neonView/SalesprojectCompetitionEdit_view/SalesprojectCompetitionEdit_view.aod
@@ -51,10 +51,5 @@
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
-    <neonViewReference>
-      <name>cba34c27-9abf-416b-99fc-f7e91bd3669c</name>
-      <entityField>Attributes</entityField>
-      <view>AttributeRelationEdit_view</view>
-    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod b/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod
index 5baa8af9d1972faee567f460d1e03c380063d9f2..1ea48c8e825f65023b66ea0231761b4a8747a445 100644
--- a/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod
+++ b/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod
@@ -27,7 +27,7 @@
       <name>OpenSalesprojectsDashlet</name>
       <title>Open salesprojects</title>
       <description>Show open salesprojects</description>
-      <fragment>Salesproject/filter?search=W3sibmFtZSI6IlNUQVRFIiwib3BlcmF0b3IiOiJFUVVBTCIsInZhbHVlS2V5IjoiMSIsInZhbHVlIjoiT2ZmZW4iLCJjb250ZW50VHlwZSI6IlRFWFQifV0%253D</fragment>
+      <fragment>Salesproject/filter?search=W3sibmFtZSI6IlNUQVRFIiwib3BlcmF0b3IiOiJFUVVBTCIsInZhbHVlIjoiMjViMGFjNzctZWY5Mi00ODA5LTgwMmUtYmI5ZDg3ODJmODY1IiwiY29udGVudFR5cGUiOiJURVhUIn1d</fragment>
       <singleton v="true" />
       <requiresConfiguration v="false" />
       <icon>vaadin:filter</icon>
diff --git a/neonView/StockCount_view/StockCount_view.aod b/neonView/StockCount_view/StockCount_view.aod
index e5107840018f92d1debbb8cccd4e1735e40c891b..8e8ede676aed30d4071e15d40f1a9047fe97dcc7 100644
--- a/neonView/StockCount_view/StockCount_view.aod
+++ b/neonView/StockCount_view/StockCount_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>Generic</name>
+      <name>Stocks</name>
       <showDrawer v="true" />
       <drawerCaption>Stock</drawerCaption>
       <entityField>#ENTITY</entityField>
diff --git a/neonView/StockEdit_view/StockEdit_view.aod b/neonView/StockEdit_view/StockEdit_view.aod
index 51a44973a299e354851866f91d7accff4661b432..ea63dc4bbf98903eb999a062337965f7959e38ea 100644
--- a/neonView/StockEdit_view/StockEdit_view.aod
+++ b/neonView/StockEdit_view/StockEdit_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>Generic_template</name>
+      <name>Edit</name>
       <editMode v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
diff --git a/neonView/StockFilter_view/StockFilter_view.aod b/neonView/StockFilter_view/StockFilter_view.aod
index 50d23d9240555ebaf4ce5bca87f68c127640a377..b715a7f6186055abb99750d11d723ced654d2a16 100644
--- a/neonView/StockFilter_view/StockFilter_view.aod
+++ b/neonView/StockFilter_view/StockFilter_view.aod
@@ -10,7 +10,7 @@
   </layout>
   <children>
     <tableViewTemplate>
-      <name>Table_template</name>
+      <name>Stocks</name>
       <autoNewRow v="true" />
       <entityField>#ENTITY</entityField>
       <columns>
diff --git a/neonView/TaskEdit_view/TaskEdit_view.aod b/neonView/TaskEdit_view/TaskEdit_view.aod
index 1d122a0c8cc59e662ced8398417c467216d7f0cc..f43c9f7a1c7dc48fd6766376df5447b74cfe89a1 100644
--- a/neonView/TaskEdit_view/TaskEdit_view.aod
+++ b/neonView/TaskEdit_view/TaskEdit_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>main</name>
+      <name>Edit</name>
       <editMode v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
diff --git a/neonView/TaskFilter_view/TaskFilter_view.aod b/neonView/TaskFilter_view/TaskFilter_view.aod
index 76dbda0d0642303ff9e62416707592d8563f6fe3..558120366953c001d13c2d2dbde7d588f3ec0b0e 100644
--- a/neonView/TaskFilter_view/TaskFilter_view.aod
+++ b/neonView/TaskFilter_view/TaskFilter_view.aod
@@ -27,7 +27,7 @@
   </layout>
   <children>
     <timelineViewTemplate>
-      <name>mainTimeline</name>
+      <name>TasksTimeline</name>
       <dateField>START_DATE</dateField>
       <titleField>SUBJECT</titleField>
       <descriptionField>DESCRIPTION</descriptionField>
@@ -35,7 +35,7 @@
       <entityField>#ENTITY</entityField>
     </timelineViewTemplate>
     <tableViewTemplate>
-      <name>mainTable</name>
+      <name>TasksTable</name>
       <entityField>#ENTITY</entityField>
       <title></title>
       <columns>
@@ -63,7 +63,7 @@
       </columns>
     </tableViewTemplate>
     <treetableViewTemplate>
-      <name>mainTreetable</name>
+      <name>TasksTreetable</name>
       <titleField>SUBJECT</titleField>
       <descriptionField>DESCRIPTION</descriptionField>
       <iconField>#ICON</iconField>
diff --git a/neonView/TaskLinkFilter_view/TaskLinkFilter_view.aod b/neonView/TaskLinkFilter_view/TaskLinkFilter_view.aod
index 17d77bee5033e72939c23224c989baeb3781f52a..d947ac5f4a1c1b4afb865476bd8415677fbe9839 100644
--- a/neonView/TaskLinkFilter_view/TaskLinkFilter_view.aod
+++ b/neonView/TaskLinkFilter_view/TaskLinkFilter_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <tableViewTemplate>
-      <name>Table</name>
+      <name>TaskLinks</name>
       <autoNewRow v="true" />
       <entityField>#ENTITY</entityField>
       <columns>
diff --git a/neonView/TaskLinkMultiEdit_view/TaskLinkMultiEdit_view.aod b/neonView/TaskLinkMultiEdit_view/TaskLinkMultiEdit_view.aod
index 5a43d5672c07c5262158438add274ca92ae9215a..d6b9737c69a17af9076faaf002aaba7867d0485f 100644
--- a/neonView/TaskLinkMultiEdit_view/TaskLinkMultiEdit_view.aod
+++ b/neonView/TaskLinkMultiEdit_view/TaskLinkMultiEdit_view.aod
@@ -3,13 +3,13 @@
   <name>TaskLinkMultiEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <noneLayout>
       <name>layout</name>
-    </boxLayout>
+    </noneLayout>
   </layout>
   <children>
     <genericMultipleViewTemplate>
-      <name>GenericMultiple</name>
+      <name>MultipleEdit</name>
       <entityField>#ENTITY</entityField>
       <columns>
         <neonTableColumn>
diff --git a/neonView/TaskLinkPreviewList_view/TaskLinkPreviewList_view.aod b/neonView/TaskLinkPreviewList_view/TaskLinkPreviewList_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..a009b2b1c349de4173593dcf954ead9180cc99d8
--- /dev/null
+++ b/neonView/TaskLinkPreviewList_view/TaskLinkPreviewList_view.aod
@@ -0,0 +1,26 @@
+<?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.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.0">
+  <name>TaskLinkPreviewList_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <titledListViewTemplate>
+      <name>TaskLinks</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>280359fa-e38a-49b1-9dc7-84cb670e43c3</name>
+          <entityField>OBJECT_TYPE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>d5d86e34-16a0-4dd9-acfd-f1a2f031d750</name>
+          <entityField>OBJECT_ROWID</entityField>
+        </neonTableColumn>
+      </columns>
+    </titledListViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/TaskLinkPreview_view/TaskLinkPreview_view.aod b/neonView/TaskLinkPreview_view/TaskLinkPreview_view.aod
index 04901356207c43d3494152cf0fd797412d6a9a20..1ab3daed2f48ef4d4de53ea3a758be715f598b6b 100644
--- a/neonView/TaskLinkPreview_view/TaskLinkPreview_view.aod
+++ b/neonView/TaskLinkPreview_view/TaskLinkPreview_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>Generic</name>
+      <name>Info</name>
       <entityField>#ENTITY</entityField>
       <fields>
         <entityFieldLink>
diff --git a/neonView/TaskMainPreview_view/TaskMainPreview_view.aod b/neonView/TaskMainPreview_view/TaskMainPreview_view.aod
index b90cedaa55f0de2ea004104758fd8ad3facbf0bf..21a1ad13fa5ab1c75199e0122fffaec3dd27c8d1 100644
--- a/neonView/TaskMainPreview_view/TaskMainPreview_view.aod
+++ b/neonView/TaskMainPreview_view/TaskMainPreview_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <cardViewTemplate>
-      <name>head</name>
+      <name>Header</name>
       <iconField>#ICON</iconField>
       <titleField>SUBJECT</titleField>
       <descriptionField>STATUS</descriptionField>
@@ -17,7 +17,7 @@
       <entityField>#ENTITY</entityField>
     </cardViewTemplate>
     <genericViewTemplate>
-      <name>extendedData</name>
+      <name>Info</name>
       <showDrawer v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
diff --git a/neonView/TaskPreview_view/TaskPreview_view.aod b/neonView/TaskPreview_view/TaskPreview_view.aod
index 02f4fbcea5b422a6209fd224f8d1bb19f3fcbd52..11ab7e15bd84199d86792fa9b45577527005c5b3 100644
--- a/neonView/TaskPreview_view/TaskPreview_view.aod
+++ b/neonView/TaskPreview_view/TaskPreview_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <cardViewTemplate>
-      <name>head</name>
+      <name>Header</name>
       <iconField>#ICON</iconField>
       <titleField>SUBJECT</titleField>
       <descriptionField>STATUS</descriptionField>
@@ -17,7 +17,7 @@
       <entityField>#ENTITY</entityField>
     </cardViewTemplate>
     <genericViewTemplate>
-      <name>extendedData</name>
+      <name>Info</name>
       <showDrawer v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
@@ -51,6 +51,11 @@
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
+    <neonViewReference>
+      <name>8cf85386-d25f-459a-a2a1-991c9e3287b6</name>
+      <entityField>Links</entityField>
+      <view>TaskLinkPreviewList_view</view>
+    </neonViewReference>
     <neonViewReference>
       <name>2941084f-b72c-4cb2-9d73-5e6827795be2</name>
       <entityField>MainDocuments</entityField>
diff --git a/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod b/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod
index ae77a626db4aeb207c78d4f8c80e2877610b4223..7f4c05f9fc8514c2485931547bf18cad61fd2717 100644
--- a/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod
+++ b/neonView/TimetrackingEdit_view/TimetrackingEdit_view.aod
@@ -9,7 +9,7 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>TimetrackingEdit_template</name>
+      <name>Edit</name>
       <editMode v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
diff --git a/neonView/TimetrackingFilter_view/TimetrackingFilter_view.aod b/neonView/TimetrackingFilter_view/TimetrackingFilter_view.aod
index 141e746d2c5260f0bb3f9e00201104fa9bb36325..e923bf38eab937f2ad84016a6aa801ab7d35973d 100644
--- a/neonView/TimetrackingFilter_view/TimetrackingFilter_view.aod
+++ b/neonView/TimetrackingFilter_view/TimetrackingFilter_view.aod
@@ -10,7 +10,7 @@
   </layout>
   <children>
     <tableViewTemplate>
-      <name>TimetrackingFilter_template</name>
+      <name>Timetrackings</name>
       <entityField>#ENTITY</entityField>
       <columns>
         <neonTableColumn>
diff --git a/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactContactrole.xml b/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactContactrole.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e63bb7ba7d4a32faf22bc6e1f01365c7672d7b33
--- /dev/null
+++ b/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactContactrole.xml
@@ -0,0 +1,135 @@
+<?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="88938510-188f-4814-b25d-0b5e393cd837">
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="767b89c6-2461-4d0e-9b7a-dda33e5090c9"/>
+
+            <column name="KEYID" value="47abd1f8-d449-4d81-9e6d-c48783119b0b"/>
+            <column name="TITLE" value="Managing director"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="0"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="2fa7cddb-1e2c-438f-8f16-92f245af09f4"/>
+
+            <column name="KEYID" value="07ec8a18-c830-4982-a4c6-d2795841b07a"/>
+            <column name="TITLE" value="Purchasing manager"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="1"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="67ea4d33-b683-4a04-b2e3-4af54d6debcb"/>
+
+            <column name="KEYID" value="91411987-8700-43d7-a101-4bd375c6e3af"/>
+            <column name="TITLE" value="Executive board"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="2"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="d7be200e-ffc0-47a7-b0bb-3da92f39b993"/>
+
+            <column name="KEYID" value="bd0c1b58-6c8c-42a4-b68b-7099ef05bc0e"/>
+            <column name="TITLE" value="Marketing manager"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="3"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="3b836d42-9ecf-49b9-8df9-570c27860c01"/>
+
+            <column name="KEYID" value="97d0d10d-14a2-4d85-908d-ea14624b2bfd"/>
+            <column name="TITLE" value="Sales manager"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="4"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="2a4e6516-8493-4dde-a9df-bf2efd4db0c8"/>
+
+            <column name="KEYID" value="9c3aea50-b402-4e51-b48d-bfc50c107232"/>
+            <column name="TITLE" value="Supervisory board"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="5"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="3e7f2a42-ad8b-48da-aa11-95525ca36d01"/>
+
+            <column name="KEYID" value="7b71b7e0-fb4a-4557-a4ab-7122574b292b"/>
+            <column name="TITLE" value="Administrator"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="6"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="11c05d41-78ec-4d7c-acbe-f94912f2386c"/>
+
+            <column name="KEYID" value="6d6f2261-2dbd-445a-9189-18418e7c44ef"/>
+            <column name="TITLE" value="IT manager"/>
+            <column name="CONTAINER" value="ContactContactrole"/>
+            <column name="SORTING" valueNumeric="7"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <rollback>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="767b89c6-2461-4d0e-9b7a-dda33e5090c9" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="2fa7cddb-1e2c-438f-8f16-92f245af09f4" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="67ea4d33-b683-4a04-b2e3-4af54d6debcb" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="d7be200e-ffc0-47a7-b0bb-3da92f39b993" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="3b836d42-9ecf-49b9-8df9-570c27860c01" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="2a4e6516-8493-4dde-a9df-bf2efd4db0c8" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="3e7f2a42-ad8b-48da-aa11-95525ca36d01" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="11c05d41-78ec-4d7c-acbe-f94912f2386c" />
+                </whereParams>
+            </delete>
+        </rollback>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactDepartment.xml b/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactDepartment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15f81f525dd0bcdd343a3849029af4d14c32df4b
--- /dev/null
+++ b/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactDepartment.xml
@@ -0,0 +1,87 @@
+<?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="88938510-188f-4814-b25d-0b5e393cd837">
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="75bd97bc-56f3-4ea3-a132-df3cb9cda071"/>
+
+            <column name="KEYID" value="c58a028c-772a-444f-8109-37cfde3f60a0"/>
+            <column name="TITLE" value="Management"/>
+            <column name="CONTAINER" value="ContactDepartment"/>
+            <column name="SORTING" valueNumeric="0"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="6e30d397-e31f-4ccb-96e9-51cf71d259fa"/>
+
+            <column name="KEYID" value="afc7a9b8-895d-41b9-b68c-e1bdb8ba878f"/>
+            <column name="TITLE" value="Sales"/>
+            <column name="CONTAINER" value="ContactDepartment"/>
+            <column name="SORTING" valueNumeric="1"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="722e83bc-148a-4762-abda-d491bf590bd5"/>
+
+            <column name="KEYID" value="e00eb3fc-2c8d-46a9-990a-ed2bf1948ffe"/>
+            <column name="TITLE" value="Production"/>
+            <column name="CONTAINER" value="ContactDepartment"/>
+            <column name="SORTING" valueNumeric="2"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="191617b2-09cc-4fe6-bc02-1cee746285d5"/>
+
+            <column name="KEYID" value="bde6d083-517e-45bd-8326-d84e7f8aeba0"/>
+            <column name="TITLE" value="Marketing"/>
+            <column name="CONTAINER" value="ContactDepartment"/>
+            <column name="SORTING" valueNumeric="3"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="87f97554-c335-4328-911a-345d8a9abd7d"/>
+
+            <column name="KEYID" value="b1113c19-2f1f-4d0a-806e-b0165ecc1b4a"/>
+            <column name="TITLE" value="IT"/>
+            <column name="CONTAINER" value="ContactDepartment"/>
+            <column name="SORTING" valueNumeric="4"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <rollback>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="75bd97bc-56f3-4ea3-a132-df3cb9cda071" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="6e30d397-e31f-4ccb-96e9-51cf71d259fa" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="722e83bc-148a-4762-abda-d491bf590bd5" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="191617b2-09cc-4fe6-bc02-1cee746285d5" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="87f97554-c335-4328-911a-345d8a9abd7d" />
+                </whereParams>
+            </delete>
+        </rollback>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactPosition.xml b/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactPosition.xml
new file mode 100644
index 0000000000000000000000000000000000000000..136f8bbd47dc2b9753b1cdb8d7d98cb2aa853673
--- /dev/null
+++ b/others/db_changes/data_alias/basic/2019.2/AditoBasic/init_ContactPosition.xml
@@ -0,0 +1,55 @@
+<?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="88938510-188f-4814-b25d-0b5e393cd837">
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="ba369295-c717-48eb-ae76-314087375e06"/>
+
+            <column name="KEYID" value="3308c1e5-cf4d-4934-86b7-981b8f026369"/>
+            <column name="TITLE" value="CEO"/>
+            <column name="CONTAINER" value="ContactPosition"/>
+            <column name="SORTING" valueNumeric="0"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="dcacb175-4c8a-4941-a417-69a971f52583"/>
+
+            <column name="KEYID" value="a4952791-73e4-41a1-8a78-5a27640ff0fd"/>
+            <column name="TITLE" value="CSO"/>
+            <column name="CONTAINER" value="ContactPosition"/>
+            <column name="SORTING" valueNumeric="1"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="1a508899-e2bf-409d-8a57-3ca31c9c832d"/>
+
+            <column name="KEYID" value="77dcf148-112e-4251-8a0e-9e8bd811f0b7"/>
+            <column name="TITLE" value="Production manager"/>
+            <column name="CONTAINER" value="ContactPosition"/>
+            <column name="SORTING" valueNumeric="2"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="0"/>
+        </insert>
+        <rollback>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="ba369295-c717-48eb-ae76-314087375e06" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="dcacb175-4c8a-4941-a417-69a971f52583" />
+                </whereParams>
+            </delete>
+            <delete tableName="AB_KEYWORD_ENTRY">
+                <where>AB_KEYWORD_ENTRYID = ?</where>
+                <whereParams>
+                    <param value="1a508899-e2bf-409d-8a57-3ca31c9c832d" />
+                </whereParams>
+            </delete>
+        </rollback>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/others/db_changes/data_alias/basic/2019.2/changelog.xml b/others/db_changes/data_alias/basic/2019.2/changelog.xml
index 3e279f116e5dc3dd5d675ce956cc60f8d8f970ce..a0cf8db3d8508bcfe094aec981dc2fed89d7bffb 100644
--- a/others/db_changes/data_alias/basic/2019.2/changelog.xml
+++ b/others/db_changes/data_alias/basic/2019.2/changelog.xml
@@ -105,7 +105,10 @@
     <include relativeToChangelogFile="true" file="Salesproject_add_column.xml"/>
     
     <include relativeToChangelogFile="true" file="AditoBasic/update_Strength_Weakness.xml"/>
-    
+    <include relativeToChangelogFile="true" file="AditoBasic/init_ContactDepartment.xml"/>
+    <include relativeToChangelogFile="true" file="AditoBasic/init_ContactContactrole.xml"/>
+    <include relativeToChangelogFile="true" file="AditoBasic/init_ContactPosition.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/others/db_changes/data_alias/basic/2019.2/data/AditoBasic/ObjectRelation_exampleData.xml b/others/db_changes/data_alias/basic/2019.2/data/AditoBasic/ObjectRelation_exampleData.xml
index db8fa70a9c5427c29c02f22db8e08f93f8fa83b5..448f72ab561a6f45d401d58e19b8f186882c1610 100644
--- a/others/db_changes/data_alias/basic/2019.2/data/AditoBasic/ObjectRelation_exampleData.xml
+++ b/others/db_changes/data_alias/basic/2019.2/data/AditoBasic/ObjectRelation_exampleData.xml
@@ -6,14 +6,14 @@
         <insert tableName="AB_OBJECTRELATION">
             <column name="AB_OBJECTRELATIONID" value="1a67eaa7-21da-4a18-97ab-755ac5cb74f7"/>
             <column name="OBJECT1_ROWID" value="ef345d11-a40d-59e0-a24c-afcb6095d2cb"/>
-            <column name="OBJECT2_ROWID" value="73d72702-e7f5-11e8-9f32-f2801f1b9fd1"/>
+            <column name="OBJECT2_ROWID" value="f0fb7676-8183-4bc7-beca-ca32c1e11c10"/>
             <column name="AB_OBJECTRELATIONTYPE1" value="c74ad02c-1db9-4f47-8691-aba349dbe316"/>
             <column name="AB_OBJECTRELATIONTYPE2" value="b3b85332-1c86-4cd8-a3b9-34c49c51f01a"/>
         </insert>
         <insert tableName="AB_OBJECTRELATION">
             <column name="AB_OBJECTRELATIONID" value="85ad4578-dce2-49df-a844-d162f1bd9f2f"/>
             <column name="OBJECT1_ROWID" value="ef345d11-a40d-59e0-a24c-afcb6095d2cb"/>
-            <column name="OBJECT2_ROWID" value="73d7306c-e7f5-11e8-9f32-f2801f1b9fd1"/>
+            <column name="OBJECT2_ROWID" value="4a55726c-4ca6-43cb-9d3f-8e55d97b7aaf"/>
             <column name="AB_OBJECTRELATIONTYPE1" value="090f6adc-c2b8-44b7-8c61-39dbb5660aa0"/>
             <column name="AB_OBJECTRELATIONTYPE2" value="090f6adc-c2b8-44b7-8c61-39dbb5660aa0"/>
         </insert>
diff --git a/others/db_changes/data_alias/basic/2019.2/data/example_attribute/Attribute.xml b/others/db_changes/data_alias/basic/2019.2/data/example_attribute/Attribute.xml
index 7ad3f95ced078aeeab93939d4abdade69125db82..6c2c36f53f66220455360656060c7872fe02d862 100644
--- a/others/db_changes/data_alias/basic/2019.2/data/example_attribute/Attribute.xml
+++ b/others/db_changes/data_alias/basic/2019.2/data/example_attribute/Attribute.xml
@@ -889,12 +889,20 @@
 </insert>
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="97b449a5-d9b4-42ff-b9b0-4f8b27b8a9ec"/>
-	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
+	<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                             "/>
 </insert>
+<insert tableName="AB_ATTRIBUTEUSAGE">
+        <column name="AB_ATTRIBUTEUSAGEID" value="3234f4e2-0ee7-4782-9b10-c953b7b1be29"/>
+        <column name="AB_ATTRIBUTE_ID" value="97b449a5-d9b4-42ff-b9b0-4f8b27b8a9ec"/>
+        <column name="OBJECT_TYPE" value="Organisation"/>
+        <column name="MIN_COUNT"/>
+        <column name="MAX_COUNT"/>
+</insert>
+
 <insert tableName="AB_ATTRIBUTE">
 	<column name="AB_ATTRIBUTEID" value="e7886e41-252e-414c-a169-5d1481d010c8"/>
 	<column name="ATTRIBUTE_ACTIVE" valueNumeric="0"/>
diff --git a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_gruener.xml b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_gruener.xml
index 4c56d28a9fe6ffa708e17108b8a9e735ab4c999b..3d748a734c6d1c673e12d7edc2ef9afe85c11aa8 100644
--- a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_gruener.xml
+++ b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_gruener.xml
@@ -2,7 +2,7 @@
 <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="m.escher" id="efc45d2-a40d-49e0-a24c-afab6095d1cb">
 	<insert tableName="PERSON">
-		<column name="PERSONID" value="73d732ce-e7f5-11e8-9f32-f2801f1b9fd1"/>
+		<column name="PERSONID" value="7c1efe4c-cc73-4e95-bdf0-208a3ff699b5"/>
             <column name="FIRSTNAME" value="Jerome"/>
             <column name="MIDDLENAME"/>
             <column name="LASTNAME" value="Grüner"/>
@@ -13,7 +13,7 @@
 	<insert tableName="CONTACT">
                 <column name="RELATIONSHIP" valueNumeric="1"/>
                 <column name="LANGUAGE" value="deu"/>
-		<column name="PERSON_ID" value="73d732ce-e7f5-11e8-9f32-f2801f1b9fd1"/>
+		<column name="PERSON_ID" value="7c1efe4c-cc73-4e95-bdf0-208a3ff699b5"/>
 		<column name="CONTACTID" value="73d73404-e7f5-11e8-9f32-f2801f1b9fd1"/>
 		<column name="ORGANISATION_ID" value="0"/>
 		<column name="STATUS" value="BSIC0rel-stat-actv-ae03-b6b04430e90b"/>
@@ -28,7 +28,7 @@
 		<delete tableName="PERSON">
 			<where>PERSONID = ?</where>
 			<whereParams>
-				<param value="73d732ce-e7f5-11e8-9f32-f2801f1b9fd1" />
+				<param value="7c1efe4c-cc73-4e95-bdf0-208a3ff699b5" />
 			</whereParams>
 		</delete>
 	</rollback>
diff --git a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_kanzler.xml b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_kanzler.xml
index 8b82284ee002bdc39792f40c57c34ec6e7f5e9d6..6eade59392e5f2120e1405d4e5d74cffa4bf68b6 100644
--- a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_kanzler.xml
+++ b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_kanzler.xml
@@ -2,7 +2,7 @@
 <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="m.escher" id="efc45d2-a40d-49e0-a24c-afab6095d1cb">
 	<insert tableName="PERSON">
-		<column name="PERSONID" value="73d7306c-e7f5-11e8-9f32-f2801f1b9fd1"/>
+		<column name="PERSONID" value="4a55726c-4ca6-43cb-9d3f-8e55d97b7aaf"/>
         <column name="FIRSTNAME" value="Ludwig"/>
         <column name="MIDDLENAME"/>
         <column name="LASTNAME" value="Kanzler"/>
@@ -13,7 +13,7 @@
 	<insert tableName="CONTACT">
                 <column name="RELATIONSHIP" valueNumeric="1"/>
                 <column name="LANGUAGE" value="deu"/>
-		<column name="PERSON_ID" value="73d7306c-e7f5-11e8-9f32-f2801f1b9fd1"/>
+		<column name="PERSON_ID" value="4a55726c-4ca6-43cb-9d3f-8e55d97b7aaf"/>
 		<column name="CONTACTID" value="73d731a2-e7f5-11e8-9f32-f2801f1b9fd1"/>
 		<column name="ORGANISATION_ID" value="0"/>
 		<column name="STATUS" value="BSIC0rel-stat-actv-ae03-b6b04430e90b"/>
@@ -28,7 +28,7 @@
 		<delete tableName="PERSON">
 			<where>PERSONID = ?</where>
 			<whereParams>
-				<param value="73d7306c-e7f5-11e8-9f32-f2801f1b9fd1" />
+				<param value="4a55726c-4ca6-43cb-9d3f-8e55d97b7aaf" />
 			</whereParams>
 		</delete>
 	</rollback>
diff --git a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_leicht.xml b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_leicht.xml
index 286d335285d3ba16b61bbc1137c9686c95e6842a..d14a4606b8a5cad89c9dff0ab250f2b61569d7f4 100644
--- a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_leicht.xml
+++ b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_leicht.xml
@@ -2,7 +2,7 @@
 <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="m.escher" id="efc45d2-a40d-49e0-a24c-afab6095d1cb">
     <insert tableName="PERSON">
-        <column name="PERSONID" value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1"/>
+        <column name="PERSONID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
         <column name="FIRSTNAME" value="Birgit"/>
         <column name="MIDDLENAME"/>
         <column name="LASTNAME" value="Leicht"/>
@@ -13,8 +13,8 @@
     <insert tableName="CONTACT">
         <column name="RELATIONSHIP" valueNumeric="1"/>
         <column name="LANGUAGE" value="deu"/>
-        <column name="PERSON_ID" value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1"/>
-        <column name="CONTACTID" value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1"/>
+        <column name="PERSON_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
+        <column name="CONTACTID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
         <column name="ORGANISATION_ID" value="b219b58a-f120-42d8-9a64-0b176501eac7"/>
         <column name="STATUS" value="BSIC0rel-stat-actv-ae03-b6b04430e90b"/>
     </insert>
@@ -23,7 +23,7 @@
         <column name="ADDR_TYPE" valueNumeric="2"/>
         <column name="CITY" value="Landshut"/>
         <column name="COUNTRY" value="DE"/>
-        <column name="CONTACT_ID" value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1"/>
+        <column name="CONTACT_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
         <column name="ADDRIDENTIFIER" value=""/>
         <column name="REGION" value="Niederbayern"/>
         <column name="ADDRESSID" value="ce990566-3b86-48fe-bd0c-1167142e584b"/>
@@ -38,7 +38,7 @@
         <column name="ADDR_TYPE" valueNumeric="3"/>
         <column name="CITY" value="Landshut"/>
         <column name="COUNTRY" value="DE"/>
-        <column name="CONTACT_ID" value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1"/>
+        <column name="CONTACT_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
         <column name="ADDRIDENTIFIER" value=""/>
         <column name="REGION" value="Niederbayern"/>
         <column name="ADDRESSID" value="43b8aea1-2444-448f-87c5-f12fe1ef4ca0"/>
@@ -52,19 +52,19 @@
         <delete tableName="CONTACT">
             <where>CONTACTID = ?</where>
             <whereParams>
-                <param value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1" />
+                <param value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87" />
             </whereParams>
         </delete>
         <delete tableName="PERSON">
             <where>PERSONID = ?</where>
             <whereParams>
-                <param value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1" />
+                <param value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87" />
             </whereParams>
         </delete>
         <delete tableName="ADDRESS">
             <where>CONTACT_ID = ?</where>
             <whereParams>
-                <param value="73d72f18-e7f5-11e8-9f32-f2801f1b9fd1" />
+                <param value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87" />
             </whereParams>
         </delete>
     </rollback>
diff --git a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_muller.xml b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_muller.xml
index 92325841d488cb250e60837236ed62834513e74e..a647b15464c1a77feaf6e539c5b0c6b9a6eec364 100644
--- a/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_muller.xml
+++ b/others/db_changes/data_alias/basic/2019.2/data/example_person/PERSON_muller.xml
@@ -2,7 +2,7 @@
 <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="m.escher" id="efc45d2-a40d-49e0-a24c-afab6095d1cb">
 	<insert tableName="PERSON">
-		<column name="PERSONID" value="73d72702-e7f5-11e8-9f32-f2801f1b9fd1"/>
+		<column name="PERSONID" value="f0fb7676-8183-4bc7-beca-ca32c1e11c10"/>
         <column name="FIRSTNAME" value="Franz"/>
         <column name="MIDDLENAME"/>
         <column name="LASTNAME" value="Müller"/>
@@ -13,8 +13,8 @@
 	<insert tableName="CONTACT">
                 <column name="RELATIONSHIP" valueNumeric="1"/>
                 <column name="LANGUAGE" value="deu"/>
-		<column name="CONTACTID" value="73d72702-e7f5-11e8-9f32-f2801f1b9fd1"/>
-		<column name="PERSON_ID" value="73d72702-e7f5-11e8-9f32-f2801f1b9fd1"/>
+		<column name="CONTACTID" value="f0fb7676-8183-4bc7-beca-ca32c1e11c10"/>
+		<column name="PERSON_ID" value="f0fb7676-8183-4bc7-beca-ca32c1e11c10"/>
 		<column name="ORGANISATION_ID" value="b219b58a-f120-42d8-9a64-0b176501eac7"/>
 		<column name="STATUS" value="BSIC0rel-stat-actv-ae03-b6b04430e90b"/>
 	</insert>
@@ -22,13 +22,13 @@
 		<delete tableName="CONTACT">
 			<where>CONTACTID = ?</where>
 			<whereParams>
-				<param value="73d72702-e7f5-11e8-9f32-f2801f1b9fd1" />
+				<param value="f0fb7676-8183-4bc7-beca-ca32c1e11c10" />
 			</whereParams>
 		</delete>
 		<delete tableName="PERSON">
 			<where>PERSONID = ?</where>
 			<whereParams>
-				<param value="73d72702-e7f5-11e8-9f32-f2801f1b9fd1" />
+				<param value="f0fb7676-8183-4bc7-beca-ca32c1e11c10" />
 			</whereParams>
 		</delete>
 	</rollback>
diff --git a/process/ActivityTask_lib/process.js b/process/ActivityTask_lib/process.js
index 421a419f4f090246ef1b6aefa40a865e54c1b3ba..4228e5d38db37b07d9a0329cc3577b69893815c2 100644
--- a/process/ActivityTask_lib/process.js
+++ b/process/ActivityTask_lib/process.js
@@ -165,7 +165,7 @@ _ActivityTaskUtils._addLinkRecords = function(pObjectIdField, pRowIdField, pAddi
                 break;
             case "Task":
                 presetLinks = presetLinks.concat(db.table(SqlCondition.begin()
-                             .andPrepare("TASKLINK.ACTIVITY_ID", vars.get(pParentIdField))
+                             .andPrepare("TASKLINK.TASK_ID", vars.get(pParentIdField))
                              .buildSql("select OBJECT_TYPE, OBJECT_ROWID from TASKLINK", "1=2")));
                 break;
         }
diff --git a/process/Attribute_lib/process.js b/process/Attribute_lib/process.js
index fcd1ba99fa423c020c228d00f0d988c7f4ae650d..6614f1c74149370b5d9309558f6f797f8d6a5031 100644
--- a/process/Attribute_lib/process.js
+++ b/process/Attribute_lib/process.js
@@ -1,3 +1,5 @@
+import("system.logging");
+import("system.util");
 import("system.datetime");
 import("system.translate");
 import("system.neon");
@@ -61,11 +63,15 @@ AttributeUtil.getPossibleAttributes = function (pObjectType, pIncludeGroups, pFi
  * returns the name of an attribute with all parent attribute names
  * 
  * @param {String} pAttributeId the id of the attribute
+ * @param {Boolean} [pSimpleName=false] Use only the name of the attribute and not the names of the parents.
  * 
  * @return {String} the name of the attribute
  */
-AttributeUtil.getFullAttributeName = function (pAttributeId) 
+AttributeUtil.getFullAttributeName = function (pAttributeId, pSimpleName) 
 {
+    if (pSimpleName == undefined)
+        pSimpleName = false;
+    
     if (!pAttributeId)
         return "";
     var attributeNames = [];
@@ -83,8 +89,8 @@ AttributeUtil.getFullAttributeName = function (pAttributeId)
         }
         else
             pAttributeId = "";
-    } while (pAttributeId);
-
+    } while (pAttributeId && !pSimpleName);
+    
     return attributeNames.reverse().join(" / ");
 }
 
@@ -128,6 +134,28 @@ AttributeUtil.getAllChildren = function (pAttributeId)
     return childIds;
 }
 
+/**
+ * checks if an attribute has attribute relations
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * 
+ * @result {boolean} true if it has relations
+ */
+AttributeUtil.hasRelations = function (pAttributeId)
+{
+    if (!pAttributeId)
+        return false;
+    return db.cell(SqlCondition.begin()
+        .andPrepare("AB_ATTRIBUTE.AB_ATTRIBUTEID", pAttributeId)
+        .buildSql(
+            "select exists ("
+            +    "select AB_ATTRIBUTERELATIONID from AB_ATTRIBUTERELATION "
+            +    "where AB_ATTRIBUTE_ID = AB_ATTRIBUTEID"
+            + ") from AB_ATTRIBUTE", "1=2"
+        )
+    ) == "true";
+}
+
 /*********************************************************************************************************************/
 
 /**
@@ -482,3 +510,168 @@ AttributeTypeUtil.getTypeColumnIndex = function (pAttributeType)
         AttributeTypeUtil._initTypeColumnData();
     return this._typeColumnMap[pAttributeType.trim()];
 }
+
+/*********************************************************************************************************************/
+
+/**
+ * Functions for AttributeUsages.
+ * Do not instanciate this!
+ * 
+ * @class
+ */
+function AttributeUsageUtil () {}
+
+/**
+ * Creates AttributeUsages for all subordinate attributes of an attribute.
+ * This is required when an usage is added to a superordinate attribute.
+ * 
+ * @param {String} pAttributeId the id of the superordinate attribute
+ * @param {String} pObjectType the context
+ */
+AttributeUsageUtil.insertChildrenUsages = function (pAttributeId, pObjectType)
+{
+    var table = "AB_ATTRIBUTEUSAGE";
+    var columns = ["AB_ATTRIBUTEUSAGEID", "AB_ATTRIBUTE_ID", "OBJECT_TYPE"];
+    var types = db.getColumnTypes(table, columns);
+    
+    var sqlSelect = "select AB_ATTRIBUTEID, "
+            + " exists (select AB_ATTRIBUTEUSAGEID from AB_ATTRIBUTEUSAGE where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID and OBJECT_TYPE = '" 
+            + pObjectType + "') from AB_ATTRIBUTE";
+    
+    var inserts = [];
+    _addInserts(pAttributeId, pObjectType);
+    db.inserts(inserts);
+    
+    function _addInserts (pAttributeId, pObjectType)
+    {
+        var condition = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
+        var attributes = db.table(condition.buildSql(sqlSelect));
+        
+        attributes.forEach(function (row)
+        {
+            if (row[1] != "true")
+            {
+                let values = [util.getNewUUID(), row[0], pObjectType];
+                inserts.push([table, columns, types, values]);
+            }
+            _addInserts(row[0], pObjectType);
+        });
+    }
+}
+
+/**
+ * Updates AttributeUsages for all subordinate attributes of an attribute.
+ * This is required when an usage of a superordinate attribute is changed.
+ * 
+ * @param {String} pAttributeId the id of the superordinate attribute
+ * @param {String} pOldObjectType ye olde context
+ * @param {String} pNewObjectType the new context
+ */
+AttributeUsageUtil.updateChildrenUsages = function (pAttributeId, pOldObjectType, pNewObjectType)
+{
+    if (!pNewObjectType)
+        return;
+    
+    var table = "AB_ATTRIBUTEUSAGE";
+    
+    var sqlSelect = "select AB_ATTRIBUTEID, AB_ATTRIBUTEUSAGEID, "
+        + " exists (select AB_ATTRIBUTEUSAGEID from AB_ATTRIBUTEUSAGE where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID and OBJECT_TYPE = '" 
+        + pNewObjectType + "')"
+        + " from AB_ATTRIBUTE left join AB_ATTRIBUTEUSAGE on AB_ATTRIBUTEID = AB_ATTRIBUTE_ID and OBJECT_TYPE = '" + pOldObjectType + "'";
+    
+    var updateCond = SqlCondition.begin();
+    
+    //it is possible that the new objectType is already in a subordinate attribute 
+    //and an update could cause a duplicate entry so one has to be deleted
+    var deleteCond = SqlCondition.begin();
+    
+    _addUpdateIds(pAttributeId, pOldObjectType);
+        
+    if (updateCond.isSet())
+        db.updateData(table, ["OBJECT_TYPE"], null, [pNewObjectType], updateCond.build("1=2"));
+    if (deleteCond.isSet())
+        db.deleteData(table, deleteCond.build("1=2"));
+    
+    function _addUpdateIds (pAttributeId)
+    {
+        var condition = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
+        var attributes = db.table(condition.buildSql(sqlSelect));
+        
+        attributes.forEach(function (row)
+        {
+            if (row[1] && row[2] == "true")
+                deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1]);
+            else if (row[1])
+                updateCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1]);
+            _addUpdateIds(row[0]);
+        });
+    }
+}
+
+/**
+ * Deletes AttributeUsages for all subordinate attributes of an attribute.
+ * This is required when an usage is removed from a superordinate attribute.
+ * 
+ * @param {String} pAttributeId the id of the superordinate attribute
+ * @param {String} pObjectType the context
+ */
+AttributeUsageUtil.deleteChildrenUsages = function (pAttributeId, pObjectType)
+{
+    var table = "AB_ATTRIBUTEUSAGE";
+    
+    var sqlSelect = "select AB_ATTRIBUTEID, AB_ATTRIBUTEUSAGEID "
+        + " from AB_ATTRIBUTE left join AB_ATTRIBUTEUSAGE on AB_ATTRIBUTEID = AB_ATTRIBUTE_ID and OBJECT_TYPE = '" + pObjectType + "'";
+    
+    var deleteCond = SqlCondition.begin();
+    _addDeleteIds(pAttributeId, pObjectType);
+    if (deleteCond.isSet())
+        db.deleteData(table, deleteCond.build("1=2"));
+    
+    function _addDeleteIds (pAttributeId)
+    {
+        var condition = SqlCondition.begin()
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_TYPE", $AttributeTypes.COMBOVALUE, "# != ?")
+            .andPrepare("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", pAttributeId);
+        var attributes = db.table(condition.buildSql(sqlSelect));
+        
+        attributes.forEach(function (row)
+        {
+            if (row[1])
+                deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[1])
+            _addDeleteIds(row[0]);
+        });
+    }
+}
+
+/**
+ * Deletes duplicate attribute usages.
+ * 
+ * @param {String} [pAttributeId=null] attribute id, if omitted, all duplicates will be deleted 
+ */
+AttributeUsageUtil.removeDuplicates = function (pAttributeId)
+{
+    var condition = SqlCondition.begin()
+        .and("exists (select AB_ATTRIBUTEUSAGEID from AB_ATTRIBUTEUSAGE AU where AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AU.AB_ATTRIBUTE_ID "
+            + "and AB_ATTRIBUTEUSAGE.OBJECT_TYPE = AU.OBJECT_TYPE and AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID != AU.AB_ATTRIBUTEUSAGEID)");
+    if (pAttributeId)
+        condition.andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", pAttributeId);
+    
+    var duplicates = db.table(condition.buildSql("select AB_ATTRIBUTEUSAGEID, AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE"));
+    var usageObj = {};
+    var deleteCond = SqlCondition.begin();
+    
+    duplicates.forEach(function (row)
+    {
+        if (!(row[1] in this))
+            this[row[1]] = {};
+        if (row[2] in this[row[1]])
+            deleteCond.orPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTEUSAGEID", row[0]);
+        this[row[1]][row[2]] = true;
+    }, usageObj);
+    if (deleteCond.isSet())
+        db.deleteData("AB_ATTRIBUTEUSAGE", deleteCond.build("1=2"));
+}
\ No newline at end of file
diff --git a/process/Calendar_lib/process.js b/process/Calendar_lib/process.js
index 81b9333190f472a6fd60abc1fb1815c617a27e55..232cf4c3be3db1c4c5a3f0dc30769600b30cd180 100644
--- a/process/Calendar_lib/process.js
+++ b/process/Calendar_lib/process.js
@@ -1,1891 +1,1903 @@
-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, 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;
-    }
-
-    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;
-        }
-    }
-    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]];
+}
+
+/*
+ * 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 b3e659f848a3d5c46b8376121477ea329ebbffac..f4d50682682ea63b11f722b56ea83c21de72c396 100644
--- a/process/Contact_lib/process.js
+++ b/process/Contact_lib/process.js
@@ -50,7 +50,7 @@ function ContactUtils() {}
  * This saves an extra select from CONTACT. <br>
  *  <br>
  *  <br>
- * @param {String} pRelationId
+ * @param {String} pContactId
  * @param {String} pPersId selected from the CONTACT table
  * @param {String} pOrgId selected from the CONTACT table
  *  <br>
@@ -59,34 +59,34 @@ function ContactUtils() {}
  *                      2 if privat person <br>
  *                      3 if person of an organisation <br>
  */
-ContactUtils.getRelationType = function(pRelationId, pPersId, pOrgId)
+ContactUtils.getContactType = function(pContactId, pPersId, pOrgId)
 {
     if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
     {
-        return ContactUtils.getRelationTypeByRelation(pRelationId);
+        return ContactUtils.getContactTypeByContactId(pContactId);
     }
     else
     {
-        return ContactUtils.getRelationTypeByPersOrg(pPersId, pOrgId);
+        return ContactUtils.getContactTypeByPersOrg(pPersId, pOrgId);
     }
 }
 
 /**
  * get the type of contact for a relationId <br>
- * If you already have persId and orgId from the CONTACT table, use getRelationTypeByPersOrg() <br>
- * @param {String} pRelationId
+ * If you already have persId and orgId from the CONTACT table, use getContactTypeByPersOrg() <br>
+ * @param {String} pContactId
  * <br>
  * @return {Integer} 0 if relationId not found <br>
  *                  1 if organisation <br>
  *                  2 if privat person <br>
  *                  3 if person of an organisation <br>
  */
-ContactUtils.getRelationTypeByRelation = function(pRelationId)
+ContactUtils.getContactTypeByContactId = function(pContactId)
 {
-    var relationData = ContactUtils.getPersOrgIds(pRelationId);
+    var relationData = ContactUtils.getPersOrgIds(pContactId);
     if (relationData[0]) 
     {
-        return this.getRelationTypeByPersOrg(relationData[1], relationData[2]);
+        return this.getContactTypeByPersOrg(relationData[1], relationData[2]);
     }
     else
     {
@@ -102,7 +102,7 @@ ContactUtils.getRelationTypeByRelation = function(pRelationId)
  * !!It does not check if the person / org ids really exist!! <br>
  * !!And it does not check if really any contact with this person / org ids exist!! <br>
  *  <br>
- * This function is more performant than getRelationTypeByRelation, <br>
+ * This function is more performant than getContactTypeByContactId, <br>
  * because it doesn't load something from the db. <br>
  *  <br>
  * It is meant to be used by entitys, where you can load person and org with the DataRecord. <br>
@@ -116,7 +116,7 @@ ContactUtils.getRelationTypeByRelation = function(pRelationId)
  *                      2 if privat person <br>
  *                      3 if person of an organisation <br>
  */
-ContactUtils.getRelationTypeByPersOrg = function(pPersId, pOrgId)
+ContactUtils.getContactTypeByPersOrg = function(pPersId, pOrgId)
 {
     if (!pPersId)
     {
@@ -147,7 +147,7 @@ ContactUtils.getRelationTypeByPersOrg = function(pPersId, pOrgId)
  * !!It does not check if the person / org ids really exist!! <br>
  * !!And it does not check if really any contact with this person / org ids exist!! <br>
  *  <br>
- * This function is more performant than getContextByRelationId, <br>
+ * This function is more performant than getContextByContactId, <br>
  * because it doesn't load something from the db. <br>
  *  <br>
  * It is meant to be used by entitys, where you can load person and org with the DataRecord. <br>
@@ -161,7 +161,7 @@ ContactUtils.getRelationTypeByPersOrg = function(pPersId, pOrgId)
  */
 ContactUtils.getContextByPersOrg = function(pPersId, pOrgId)
 {
-    switch (ContactUtils.getRelationTypeByPersOrg(pPersId, pOrgId))
+    switch (ContactUtils.getContactTypeByPersOrg(pPersId, pOrgId))
     {
         case 1: // Org
             return ContextUtils.getContextName("Organisation");
@@ -177,27 +177,27 @@ ContactUtils.getContextByPersOrg = function(pPersId, pOrgId)
  * return the corresponding context of the contact <br>
  * If you already have persId and orgId from the CONTACT table, use getContextByPersOrg() <br>
  * 
- * @param {String} pRelationId
+ * @param {String} pContactId
  * @return {String} contextname or "" if contact not found
  */
-ContactUtils.getContextByRelationId = function(pRelationId)
+ContactUtils.getContextByContactId = function(pContactId)
 {
-    var relationData = ContactUtils.getPersOrgIds(pRelationId);
+    var relationData = ContactUtils.getPersOrgIds(pContactId);
     return ContactUtils.getContextByPersOrg(relationData[1], relationData[2])
 }
 
 /**
  * get the person- and org-id from a contact as array
  * 
- * @param {String} pRelationId
+ * @param {String} pContactId
  * @return {String[]} result as [persid, orgid] if one of them is null in the db, "" will be returned as the id.
  */
-ContactUtils.getPersOrgIds = function(pRelationId)
+ContactUtils.getPersOrgIds = function(pContactId)
 {
-    if (pRelationId) {
+    if (pContactId) {
         return db.array(db.ROW, 
             SqlCondition.begin()
-                        .andPrepare("CONTACT.CONTACTID", pRelationId)
+                        .andPrepare("CONTACT.CONTACTID", pContactId)
                         .buildSql("select CONTACTID, PERSON_ID, ORGANISATION_ID from CONTACT", "1=0"));
     }
     
@@ -235,6 +235,7 @@ ContactUtils.getFullTitleByContactId = function(pContactId)
 
 /**
  * get the name of the person
+ * do not use this for a mass of data (e.g. in a loop) since this will be slow due to select-time
  * 
  * @param {String} pPersonId the id of the person where the data shall be loaded
  * 
@@ -259,19 +260,40 @@ ContactUtils.getTitleByPersonId = function(pPersonId)
     return "";
 }
 
+/**
+ * get the name of the person
+ * do not use this for a mass of data (e.g. in a loop) since this will be slow due to select-time
+ * 
+ * @param {String} pContactId the id of the contact entry with the person where the data shall be loaded
+ * 
+ * @return {String} the name or ""
+ */
+ContactUtils.getTitleByContactId = function(pContactId)
+{
+    if (pContactId) 
+    {
+        var personId = db.cell(SqlCondition.begin()
+                                           .andPrepare("CONTACT.CONTACTID", pContactId)
+                                            .buildSql("select CONTACT.PERSON_ID from CONTACT ", "1 = 2"));
+        if (personId)
+            return ContactUtils.getTitleByPersonId(personId);
+    }
+    
+    return "";
+}
+
 /**
  * returns the from string for the contact joined with org, person, address 
  *
  * @return {String}
  */
-ContactUtils.getFullRelationString = function()
+ContactUtils.getFullContactString = function()
 {
     return " CONTACT join ORGANISATION on ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID"
     + " left join PERSON on PERSON.PERSONID = CONTACT.PERSON_ID"
     + " left join ADDRESS on ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID";
 }
 
-
 /**
  * object for handling of a single contact
  * provides static- and instance-functions
@@ -369,7 +391,7 @@ Contact.createWithColumnPreset = function()
 function ContactTitleRenderer(pContact, pOptions)
 {
     this.contact = pContact;
-    if (pOptions !== undefined)//null means null which is "no option"; so check exactly for undefined
+    if (pOptions !== undefined)//null means null which is "no option"; so check exactly for undefined to check if default option has to be set
         this._options = pOptions;
     else 
         this._options = ContactTitleRenderer.OPTIONS.IncludeOrganisation;
@@ -402,6 +424,7 @@ function ContactTitleRenderer(pContact, pOptions)
  * @static
  */
 ContactTitleRenderer.OPTIONS = {
+    NoOption: 0,
     IncludeOrganisation: 1
 };
 
diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js
index 08fbf7aaaa4e102481b7ea1d28e6cebb3e3b007d..7eee3571dbc1a681d7989b1a7aac05129c227cee 100644
--- a/process/Context_lib/process.js
+++ b/process/Context_lib/process.js
@@ -2,23 +2,25 @@ import("system.translate");
 import("system.project");
 import("system.vars");
 import("system.SQLTYPES");
+import("Keyword_lib");
 import("Sql_lib");
+import("Contact_lib");
 
 /**
  * Methods to manage contexts.
  * Do not create an instance of this!
- * 
+ *
  * @class
  */
 function ContextUtils() {}
-   
+
 /**
  * Get the id of the current context
  * TODO: use a UUID of the current context which doesn't change
- * 
+ *
  * @return {String} Id of the current context
  */
-ContextUtils.getCurrentContextId = function() 
+ContextUtils.getCurrentContextId = function()
 {
     return vars.getString("$sys.currentcontextname");
 }
@@ -26,40 +28,40 @@ ContextUtils.getCurrentContextId = function()
 /**
  * TODO: use System function. Currently the Name is also the id.
  * Returns the Name of a context by the Id
- * 
+ *
  * @param {String} pContextId the id of a context
  * @return {String} Name of the current context
  */
-ContextUtils.getContextName = function(pContextId) 
+ContextUtils.getContextName = function(pContextId)
 {
     // TODO: currently the Id is the context name. This will be changed maybe
     return pContextId;
 }
 
 /**
- * 
+ *
  * @param {Boolean} [pFilter=false] filter only for contexts which have a mapping in ContextUtils._getSelectMap
- * 
+ *
  * @return {String[][]} the contexts [[contextId, contextName, contextTitle], [... ], ...]
  */
 ContextUtils.getContexts = function(pFilter)
 {
-    if (pFilter == undefined) 
+    if (pFilter == undefined)
         pFilter = false;
-    
+
     var contexts = project.getDataModels(project.DATAMODEL_KIND_CONTEXT);
-    
+
     if (pFilter)
     {
-        contexts = contexts.filter(function(pContext) 
+        contexts = contexts.filter(function(pContext)
         {
             // filter only contexts which have defined mappings in Context_lib
             return ContextUtils._getSelectMap()[pContext[0]] != undefined;
         });
     }
-    
-    
-    return contexts.map(ContextUtils._contextDataMapping).sort(function(pContext1, pContext2) 
+
+
+    return contexts.map(ContextUtils._contextDataMapping).sort(function(pContext1, pContext2)
         {
             // sort after ContextTitle
             if (pContext1[2] > pContext2[2])
@@ -74,9 +76,9 @@ ContextUtils.getContexts = function(pFilter)
 
 /**
  * get the data of a context
- * 
+ *
  * @param {String} pContextId the id of the context
- * 
+ *
  * @return {String[]} the contextdata [contextId, contextName, contextTitle]
  */
 ContextUtils.getContext = function(pContextId)
@@ -86,9 +88,9 @@ ContextUtils.getContext = function(pContextId)
 
 /**
  * map the contextData from the system.project-lib to [contextId, contextName, contextTitle]
- * 
+ *
  * @param {String[]} pContext the data of a context (e.g. from project.getDataModel())
- * 
+ *
  * @return {String[]} the contextdata [contextId, contextName, contextTitle]
  * @ignore
  */
@@ -106,19 +108,103 @@ ContextUtils._getSelectMap = function()
 {
     var maskingUtils = new SqlMaskingUtils();
     return {
-          // contextId             nameField  Tablename, IDField, RelationField
-        "Organisation": ["\"NAME\"", "ORGANISATION", "ORGANISATIONID", ""],
-        "Person": [maskingUtils.concat(["FIRSTNAME", "LASTNAME"]), "PERSON", "PERSONID", ""],
-        "Activity": ["SUBJECT", "ACTIVITY", "ACTIVITYID", ""],
-        "Salesproject": [maskingUtils.concat([maskingUtils.cast("PROJECTCODE", SQLTYPES.VARCHAR, 10), "':'", "PROJECTTITLE"]), "SALESPROJECT", "SALESPROJECTID", "CONTACT_ID"],
-        // TODO: keywords sind noch nicht in der DB somit gibt es nichts ähnliches zu getKeySQL.
-        // maskingUtils.concat([SqlMaskingUtils.cast("CONTRACTCODE", "varchar", 10), getKeySQL("CONTRACTTYPE", "CONTRACTTYPE" )])
-        "Contract": [maskingUtils.cast("CONTRACTCODE", SQLTYPES.VARCHAR, 10), "CONTRACT", "CONTRACTID", "CONTACT_ID"],
-//        "Appointment": ["SUMMARY", "ASYS_CALENDARBACKEND", "UID"]
-        "Offer": [maskingUtils.cast("OFFERCODE", SQLTYPES.VARCHAR, 10), "OFFER", "OFFERID", "CONTACT_ID"],
-        "Order": [maskingUtils.cast("SALESORDERCODE", SQLTYPES.VARCHAR, 10), "SALESORDER", "SALESORDERID", "CONTACT_ID"],
-        "Product": ["PRODUCTNAME", "PRODUCT", "PRODUCTID", ""],
-        "Task": ["SUBJECT", "TASK", "TASKID", translate.text("Task"), ""]
+        // contextId,
+        // nameField,
+        // Tablename (or from-part inc, joins),
+        // IDField,
+        // RelationField,
+        // CreationDate override Tablename (needed if Tablename is a join clause)
+        
+        // "Appointment": ["SUMMARY", "ASYS_CALENDARBACKEND", "UID"]
+        "Organisation": [
+            "\"NAME\"",
+            "ORGANISATION",
+            "ORGANISATIONID",
+            "",
+            ""
+        ],
+        "Person": [
+            (new ContactTitleRenderer(Contact.createWithColumnPreset()).asSql()),
+            "PERSON join CONTACT on PERSON.PERSONID = CONTACT.PERSON_ID join ORGANISATION on ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID ",
+            "CONTACTID",
+            "CONTACT",
+            ""
+        ],
+        "Activity": [
+            "SUBJECT",
+            "ACTIVITY",
+            "ACTIVITYID",
+            "",
+            ""
+        ],
+        "Salesproject": [
+            maskingUtils.concat([
+                "'" + translate.text("Salesproject") + "'",
+                "' '",
+                maskingUtils.cast("PROJECTCODE", SQLTYPES.VARCHAR, 10),
+                "' | '",
+                "PROJECTTITLE"
+            ], "", false),
+            "SALESPROJECT",
+            "SALESPROJECTID",
+            "CONTACT_ID",
+            "STARTDATE"
+        ],
+        "Contract": [
+            maskingUtils.concat([
+                KeywordUtils.getResolvedTitleSqlPart("ContractType", "CONTRACTTYPE"),
+                maskingUtils.cast("CONTRACTCODE", SQLTYPES.VARCHAR, 10)
+            ], " "),
+            "CONTRACT",
+            "CONTRACTID",
+            "CONTACT_ID",
+            "CONTRACTSTART"
+        ],
+        "Offer": [
+            maskingUtils.concat([
+                "'" + translate.text("Offer") + "'",
+                "' '",
+                maskingUtils.cast("OFFERCODE", SQLTYPES.VARCHAR, 10),
+                "'-'",
+                maskingUtils.cast("VERSNR", SQLTYPES.VARCHAR, 10)
+            ], "", false),
+            "OFFER",
+            "OFFERID",
+            "CONTACT_ID",
+            "OFFERDATE"
+        ],
+        "Order": [
+            maskingUtils.concat([
+                "'" + translate.text("Order") + "'",
+                "' '",
+                maskingUtils.cast("SALESORDERCODE", SQLTYPES.VARCHAR, 10),
+                "'-'",
+                maskingUtils.cast("VERSNR", SQLTYPES.VARCHAR, 10)
+            ], "", false),
+            "SALESORDER",
+            "SALESORDERID",
+            "CONTACT_ID",
+            "ORDERDATE"
+        ],
+        "Product": [
+            maskingUtils.concat([
+                "PRODUCTCODE",
+                "' | '",
+                "PRODUCTNAME"
+            ], "", false),
+            "PRODUCT",
+            "PRODUCTID",
+            "",
+            ""
+        ],
+        "Task": [
+            "SUBJECT",
+            "TASK",
+            "TASKID",
+            translate.text("Task"),
+            "",
+            ""
+        ]
     }
 }
 
@@ -126,7 +212,7 @@ ContextUtils.getFieldTitle = function(pContextId, pDefault)
 {
     if (ContextUtils._getSelectMap()[pContextId] != undefined && ContextUtils._getSelectMap()[pContextId].length >= 3)
         return ContextUtils._getSelectMap()[pContextId][3];
-    
+
     return pDefault;
 }
 
@@ -137,16 +223,16 @@ ContextUtils.getFieldTitle = function(pContextId, pDefault)
 ContextUtils.getNameSubselectSql = function(pContextIdDbField, pRowIdDbField)
 {
     var select = "(case " + pContextIdDbField + " ";
-    
+
     var selectMap = ContextUtils._getSelectMap()
-    for (let contextId in selectMap) 
+    for (let contextId in selectMap)
     {
         select += "when '" + contextId + "' then (select " + selectMap[contextId][0] + " from " + selectMap[contextId][1] + (pRowIdDbField ? " where " + selectMap[contextId][2] + " = " + pRowIdDbField : " ") + ") ";
     }
-    
+
     select += "else 'Not defined in ContextUtils.getNameSql()!'";
     select += "end)";
-    
+
     return select;
 }
 
@@ -157,7 +243,7 @@ ContextUtils.getNameSql = function(pContextId, pRowId)
 {
     var selectMap = ContextUtils._getSelectMap()
     if (selectMap[pContextId] != undefined)
-        return SqlCondition.begin().andPrepare(selectMap[pContextId][1] + "." + selectMap[pContextId][2], pRowId).buildSql("select " + selectMap[pContextId][0] + " from " + selectMap[pContextId][1], "1=2");
+        return SqlCondition.begin().andPrepare((selectMap[pContextId][4] ? selectMap[pContextId][4] : selectMap[pContextId][1]) + "." + selectMap[pContextId][2], pRowId).buildSql("select " + selectMap[pContextId][0] + " from " + selectMap[pContextId][1], "1=2");
     else
         return "select 1 from person where 1=2";
 }
@@ -165,7 +251,7 @@ ContextUtils.getNameSql = function(pContextId, pRowId)
 /**
  * TODO: !!!temporary function until you can get fields from another Entity!!!
  */
-ContextUtils.getContextDataSql = function(pContextId, pRowId)
+ContextUtils.getContextDataSql = function(pContextId, pRowId, pWithDate)
 {
     var selectMap = ContextUtils._getSelectMap()
     var cond = SqlCondition.begin();
@@ -173,6 +259,10 @@ ContextUtils.getContextDataSql = function(pContextId, pRowId)
     {
         cond.andPrepare(selectMap[pContextId][1] + "." + selectMap[pContextId][3], pRowId)
     }
-    
-    return cond.buildSql("select " + selectMap[pContextId][2] + ", " + selectMap[pContextId][0] + " from " + selectMap[pContextId][1], "1=1");
+
+    var dateColumn = "";
+    if (pWithDate === true)
+        dateColumn = ", " + selectMap[pContextId][4];
+
+    return cond.buildSql("select " + selectMap[pContextId][2] + ", " + selectMap[pContextId][0] + dateColumn + " from " + selectMap[pContextId][1], "1=1");
 }
diff --git a/process/Contract_lib/process.js b/process/Contract_lib/process.js
index 292b26d66dff5ea3839086e8448b03b8644dd5b0..ad766aa91e67481ec5c1c76d56146a74943b22ca 100644
--- a/process/Contract_lib/process.js
+++ b/process/Contract_lib/process.js
@@ -43,4 +43,18 @@ ContractUtils.validateContractNumber = function(pContractNumber) {
     
 ContractUtils.getContractNumberValidationFailString = function() {
     return translate.text("The contract number already exists!");
+}
+
+/**
+ * Create a new contract and open the contract context in NEW-mode
+ */
+ContractUtils.createNewContract = function(pRelationId)
+{
+    var params = {};
+    
+    if (pRelationId)
+        params["ContactId_param"] = pRelationId;
+    
+ 
+    neon.openContext("Contract", null, null, neon.OPERATINGSTATE_NEW, params);
 }
\ No newline at end of file
diff --git a/process/KeywordRegistry_basic/process.js b/process/KeywordRegistry_basic/process.js
index aec2b56a9c1bec9e874948f2322834b0a2b09996..d5511a1569abbccbefbfe9ca8cec408e92ca7d8a 100644
--- a/process/KeywordRegistry_basic/process.js
+++ b/process/KeywordRegistry_basic/process.js
@@ -17,49 +17,52 @@
  */
 function $KeywordRegistry(){}
 
-$KeywordRegistry.attributeType = function(){return "AttributeType"};
-$KeywordRegistry.keywordAttributeType = function(){return "KeywordAttributeType"};
-$KeywordRegistry.contractPayment = function(){return "ContractPayment"};
-$KeywordRegistry.contractStatus = function(){return "ContractStatus"};
-$KeywordRegistry.contractType = function(){return "ContractType"};
-$KeywordRegistry.activityDirection = function(){return "ActivityDirection"};
+$KeywordRegistry.attributeType = function(){return "AttributeType";};
+$KeywordRegistry.keywordAttributeType = function(){return "KeywordAttributeType";};
+$KeywordRegistry.contractPayment = function(){return "ContractPayment";};
+$KeywordRegistry.contractStatus = function(){return "ContractStatus";};
+$KeywordRegistry.contractType = function(){return "ContractType";};
+$KeywordRegistry.activityDirection = function(){return "ActivityDirection";};
 
-$KeywordRegistry.contactStatus = function(){return "ContactStatus"};
-$KeywordRegistry.contactStatus$active = function(){return "BSIC0rel-stat-actv-ae03-b6b04430e90b"};
+$KeywordRegistry.contactStatus = function(){return "ContactStatus";};
+$KeywordRegistry.contactStatus$active = function(){return "BSIC0rel-stat-actv-ae03-b6b04430e90b";};
 
-$KeywordRegistry.currency = function(){return "Currency"};
-$KeywordRegistry.productGroupcode = function(){return "ProductGroupcode"};
-$KeywordRegistry.offerStatus = function(){return "OfferStatus"};
-$KeywordRegistry.organisationType = function(){return "OrganisationType"};
-$KeywordRegistry.personGender = function(){return "PersonGender"};
-$KeywordRegistry.taskStatus = function(){return "TaskStatus"};
-$KeywordRegistry.taskType = function(){return "TaskType"};
+$KeywordRegistry.currency = function(){return "Currency";};
+$KeywordRegistry.productGroupcode = function(){return "ProductGroupcode";};
+$KeywordRegistry.offerStatus = function(){return "OfferStatus";};
+$KeywordRegistry.organisationType = function(){return "OrganisationType";};
+$KeywordRegistry.personGender = function(){return "PersonGender";};
+$KeywordRegistry.taskStatus = function(){return "TaskStatus";};
+$KeywordRegistry.taskType = function(){return "TaskType";};
 
-$KeywordRegistry.productPricelist = function(){return "ProductPricelist"};
-$KeywordRegistry.productPricelist$standardList = function(){return "02553fc7-4611-4914-8ff5-0b7c4e7531c9"};
+$KeywordRegistry.productPricelist = function(){return "ProductPricelist";};
+$KeywordRegistry.productPricelist$standardList = function(){return "02553fc7-4611-4914-8ff5-0b7c4e7531c9";};
 
-$KeywordRegistry.quantityUnit = function(){return "QuantityUnit"};
-$KeywordRegistry.salesprojectMemberRole = function(){return "SalesprojectMemberRole"};
-$KeywordRegistry.salesprojectSource = function(){return "SalesprojectSource"};
-$KeywordRegistry.salesorderState = function(){return "SalesorderState"};
-$KeywordRegistry.salesprojectWonLost = function(){return "SalesprojectWonLost"};
-$KeywordRegistry.stockWarehouse = function(){return "StockWarehouse"};
-$KeywordRegistry.salesprojectProbability = function(){return "SalesprojectProbability"};
-$KeywordRegistry.activityCategory = function(){return "ActivityCategory"};
-$KeywordRegistry.addressType = function(){return "AddressType"};
-$KeywordRegistry.offerProbability = function(){return "OfferProbability"};
-$KeywordRegistry.communicationMedium = function(){return "CommunicationMedium"};
-$KeywordRegistry.salesprojectPricePolitics = function(){return "SalesprojectPricePolitics"};
-$KeywordRegistry.salesprojectWeakness = function(){return "SalesprojectWeakness"};
-$KeywordRegistry.salesprojectStrenght = function(){return "SalesprojectStrenght"};
-$KeywordRegistry.salesprojectState = function(){return "SalesprojectState"};
-$KeywordRegistry.salesprojectPhase = function(){return "SalesprojectPhase"};
-$KeywordRegistry.taskPriority = function(){return "TaskPriority"};
-$KeywordRegistry.taskProgress = function(){return "TaskProgress"};
-$KeywordRegistry.salesprojectCompetitionState = function(){return "SalesprojectCompetitionState"};
-$KeywordRegistry.objectRelationType = function(){return "ObjectRelationType"};
-$KeywordRegistry.deliveryTerm = function(){return "DeliveryTerm"};
-$KeywordRegistry.paymentTerm = function(){return "PaymentTerm"};
-$KeywordRegistry.campaignState = function(){return "CampaignManagementStates"};
-$KeywordRegistry.campaignStepState = function(){return "CampaignManagementStepStates"};
+$KeywordRegistry.quantityUnit = function(){return "QuantityUnit";};
+$KeywordRegistry.salesprojectMemberRole = function(){return "SalesprojectMemberRole";};
+$KeywordRegistry.salesprojectSource = function(){return "SalesprojectSource";};
+$KeywordRegistry.salesorderState = function(){return "SalesorderState";};
+$KeywordRegistry.salesprojectWonLost = function(){return "SalesprojectWonLost";};
+$KeywordRegistry.stockWarehouse = function(){return "StockWarehouse";};
+$KeywordRegistry.salesprojectProbability = function(){return "SalesprojectProbability";};
+$KeywordRegistry.activityCategory = function(){return "ActivityCategory";};
+$KeywordRegistry.addressType = function(){return "AddressType";};
+$KeywordRegistry.offerProbability = function(){return "OfferProbability";};
+$KeywordRegistry.communicationMedium = function(){return "CommunicationMedium";};
+$KeywordRegistry.salesprojectPricePolitics = function(){return "SalesprojectPricePolitics";};
+$KeywordRegistry.salesprojectWeakness = function(){return "SalesprojectWeakness";};
+$KeywordRegistry.salesprojectStrenght = function(){return "SalesprojectStrenght";};
+$KeywordRegistry.salesprojectState = function(){return "SalesprojectState";};
+$KeywordRegistry.salesprojectPhase = function(){return "SalesprojectPhase";};
+$KeywordRegistry.taskPriority = function(){return "TaskPriority";};
+$KeywordRegistry.taskProgress = function(){return "TaskProgress";};
+$KeywordRegistry.salesprojectCompetitionState = function(){return "SalesprojectCompetitionState";};
+$KeywordRegistry.objectRelationType = function(){return "ObjectRelationType";};
+$KeywordRegistry.deliveryTerm = function(){return "DeliveryTerm";};
+$KeywordRegistry.paymentTerm = function(){return "PaymentTerm";};
+$KeywordRegistry.contactDepartment = function(){return "ContactDepartment";};
+$KeywordRegistry.contactPosition = function(){return "ContactPosition";};
+$KeywordRegistry.contactContactrole = function(){return "ContactContactrole";};
+$KeywordRegistry.campaignState = function(){return "CampaignManagementStates";};
+$KeywordRegistry.campaignStepState = function(){return "CampaignManagementStepStates";};
 
diff --git a/process/Keyword_lib/process.js b/process/Keyword_lib/process.js
index 273862a3072e83e7c6d7645f5ba060890b9e7b32..3c150d05ed7e111d2531dc3ef03177a27a88a082 100644
--- a/process/Keyword_lib/process.js
+++ b/process/Keyword_lib/process.js
@@ -147,6 +147,25 @@ KeywordUtils.getContainerNames = function()
     return list;
 };
 
+/**
+* provides a translated list of keyword-entry-titles in the system filtered by a containerName;
+* usefull for lists where the key is the name which is then a editable displayValue
+* 
+* @param {String} pContainerName name of the keyword container for filtering
+* 
+* @return {String[]} translated titles as 1D-Array
+*/
+KeywordUtils.getEntryNamesByContainer = function(pContainerName)
+{
+    var sql = SqlCondition.begin()
+                          .andPrepare("AB_KEYWORD_ENTRY.CONTAINER", pContainerName)
+                          .buildSql("select AB_KEYWORD_ENTRY.TITLE from AB_KEYWORD_ENTRY", null, "order by AB_KEYWORD_ENTRY.SORTING asc, AB_KEYWORD_ENTRY.TITLE asc")
+    var list = db.array(db.COLUMN, sql).map(function (v){
+        return translate.text(v);
+    });
+    return list;
+};
+
 /**
  * object that provides featrues for a single keyword attribute; initalizes itself on creation with a specific keyword-attribute
  * 
diff --git a/process/OfferOrder_lib/process.js b/process/OfferOrder_lib/process.js
index 1b286d5154d3bec99a17fff08da8f70ef755b303..bb660ba440d2f9ebebe90fa4883372927b681d18 100644
--- a/process/OfferOrder_lib/process.js
+++ b/process/OfferOrder_lib/process.js
@@ -272,10 +272,9 @@ ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, c
         columns = columns.concat(additionalProductInfo.map(function(item) {return item[0]}));
         var colTypes = db.getColumnTypes(table, columns);
         
-        // partsList[rootProdId] = root node
-        if (partsList[rootProdId] != undefined) // if product has a parts list
+        if (partsList.root != undefined) // if product has a parts list
         {
-            __itemInsertStatement(partsList[rootProdId], assignedTo, currency, contactId);
+            __itemInsertStatement(partsList.root, assignedTo, currency, contactId);
         }
 
         if (statements.length > 0)
diff --git a/process/Offer_lib/process.js b/process/Offer_lib/process.js
index aa218c4ff40b8ddab1b07189daa24b501e820026..b4c8bea33f50080dfcb04b1b1d98a38ef64ec7dc 100644
--- a/process/Offer_lib/process.js
+++ b/process/Offer_lib/process.js
@@ -148,6 +148,8 @@ OfferUtils.openOfferReport = function (pOfferID)
         );
     var itemData = db.table(offerItemSql);
     
+    if (itemData.length == 0)
+        return;
     
     // TODO: AddrObject implementieren
     //var addrobj = new AddrObject(contactId);
diff --git a/process/PostalAddress_lib/process.js b/process/PostalAddress_lib/process.js
index 40445e11ecbd90447ef35c2df80f330ee39473fc..f3f2b67f1bd8e6dd44e583a7c2a9052d2e6ee5d7 100644
--- a/process/PostalAddress_lib/process.js
+++ b/process/PostalAddress_lib/process.js
@@ -63,8 +63,8 @@ AddressUtils.getFormattedOnlineAddressById = function(pAddressId)
  * 
  * @return {String}
  */
-AddressUtils.getAddress = function(pRelationId) {
-    var address = db.array(db.ROW, SqlCondition.begin().andPrepare("CONTACT.CONTACTID", pRelationId).buildSql('select CONTACTID, ADDRESS, BUILDINGNO, ZIP, CITY, "NAME", FIRSTNAME, LASTNAME, TITLE from' + ContactUtils.getFullRelationString(), "1=0"));
+AddressUtils.getAddress = function(pContactId) {
+    var address = db.array(db.ROW, SqlCondition.begin().andPrepare("CONTACT.CONTACTID", pContactId).buildSql('select CONTACTID, ADDRESS, BUILDINGNO, ZIP, CITY, "NAME", FIRSTNAME, LASTNAME, TITLE from' + ContactUtils.getFullContactString(), "1=0"));
     
     // TODO: currently there are some relations without standard address. Use Hardcoded one.
     if (!address[1]) {
@@ -75,7 +75,7 @@ AddressUtils.getAddress = function(pRelationId) {
         address[4] = dummyAddress[3];
         
     }
-    var type = ContactUtils.getRelationTypeByRelation(pRelationId);
+    var type = ContactUtils.getContactTypeByContactId(pContactId);
     
     return AddressUtils.formatAddress(type, address[1], address[2], address[3], address[4], address[5], address[6], address[7], address[8]);
 }
@@ -103,7 +103,7 @@ AddressUtils.getAddressById = function(pAddressId) {
         address[4] = dummyAddress[4];
         
     }
-    var type = ContactUtils.getRelationTypeByRelation(address[0]);   
+    var type = ContactUtils.getContactTypeByContactId(address[0]);   
 
     var names = db.array(db.ROW, SqlCondition.begin()
                                              .andPrepare("CONTACT.CONTACTID", address[0])
diff --git a/process/Product_lib/process.js b/process/Product_lib/process.js
index 6ee4f51c5dd21b8a37604f9d4e22269358babdee..2b863fc27e1cbffa29454100b5f8c97af05bebeb 100644
--- a/process/Product_lib/process.js
+++ b/process/Product_lib/process.js
@@ -1,579 +1,607 @@
-import("system.logging");
-import("system.util");
-import("system.SQLTYPES");
-import("system.datetime");
-import("system.db");
-import("system.vars");
-import("system.translate");
-import("KeywordRegistry_basic");
-import("Util_lib");
-import("Binary_lib");
-import("Sql_lib");
-import("Keyword_lib");
-import("Data_lib");
-
-/**
- * utility functions for products
- * Do not create an instance of this!
- * 
- * @class
- */
-function ProductUtils() {}
-
-/**
- * Delivers the currently valid product price 
- * 
- * @param {String} pid ProductID
- * @param {String} buySell possible values: PP, SP
- * 
- * @example productUtils.getCurrentProductPrice(vars.get("$field.PRODUCTID"), "PP")
- * 
- * @return {Array[]} currently valid product price with currency: [price, "CURRENCY"] or [] if no price found
- */
-ProductUtils.getCurrentProductPrice = function(pid, buySell) {
-    if (pid != undefined && pid != "" && buySell != undefined && buySell != "")
-    {
-        var today = datetime.clearTime(vars.get("sys.date"), "utc");
-        var actualPriceCondition = SqlCondition.begin()
-                    .andPrepare("PRODUCTPRICE.BUYSELL", buySell)
-                    .andPrepare("PRODUCTPRICE.PRODUCT_ID", pid)
-                    .andPrepare("PRODUCTPRICE.VALID_FROM", today, "# <= ?")
-                    .andSqlCondition(SqlCondition.begin()
-                        .orPrepare("PRODUCTPRICE.VALID_TO", today, "# >= ?")
-                        .or("PRODUCTPRICE.VALID_TO is null"), "1 = 2");
-                            
-        var productPriceData = db.array(db.ROW, actualPriceCondition.buildSql("select PRICE, CURRENCY from PRODUCTPRICE", "1 = 2", "order by VALID_FROM desc"));
-
-        if (productPriceData[0] && productPriceData[1])
-            return  [productPriceData[0], KeywordUtils.getViewValue($KeywordRegistry.currency(), productPriceData[1])];
-        else
-            return [];
-    } else {
-        return [];
-    }
-}
-
-/**
- * Delivers the stock
- * 
- * @param {String} pid ProductID
- * 
- * @example productUtils.getStockCount(vars.get("$field.PRODUCTID"))
- * 
- * @return {String} stock count
- */
-ProductUtils.getStockCount = function(pid) {
-    if (pid != undefined && pid != "")
-    {
-        var sum = db.cell(SqlCondition.begin()
-                                      .andPrepare("STOCK.PRODUCT_ID", pid)
-                                      .buildSql("select sum(QUANTITY * case IN_OUT when 0 then -1 else 1)"
-                                                 + " from STOCK"));
-        
-        if (sum == "")
-            sum = "0";
-
-        return sum;
-    }
-    else
-    {
-        throw new Error(translate.withArguments("${PRODUCT_LIB_NO_PRODUCT_ID} function: %0", ["ProductUtils.getStockCount"]));
-    }
-}
-
-/**
- * Delivers metadata and price lists of the passed product. 
- * If parameter "priceListFilter" is passed valid price lists and the 
- * current price list to use for offer/order are delivered.
- * 
- * @param {String} pid req ProductID
- * @param {Object} priceListFilter opt { currency: "currencyValue", quantity: "quantityValue", relationId: "relationIdValue (for custom price lists)" }
- * @param {String[]} additionalProductInfoFields additional fields from Product
- *                   They are added to the result with the Fieldname as key. e.g. if the array is ["INFO"] the result will contain the key "INFO"
- * 
- * @example //Product_entity, Field: PRODUCT_ID, Process: onValueChange
- *          var pid = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.PRODUCT_ID"));
- *          var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
- *          var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
- *          var pUtils = new ProductUtils();
- *          var PriceListFilter = { currency: curr, quantity: vars.get("$field.QUANTITY"), contactId: contactid };
- *          var ProductDetails = pUtils.getProductDetails(pid, PriceListFilter, ["INFO"]);
- * 
- * @return {Object} { <br>
- *                   productId: "productid" <br>
- *                   , productName: "product name" <br>
- *                   , groupCode: "keyvalue of keyword 'GROUPCODE'" <br>
- *                   , unit: "keyvalue of keyword 'UNIT'" <br>
- *                   , PriceLists: {$pricelistid$ { <br>
- *                          priceListId: "pricelistid" <br>
- *                          , relationId: "contactid" when filled -> custom price list <br>
- *                          , priceList: "keyvalue of keyword 'PRICELIST'" <br>
- *                          , price: "price" <br>
- *                          , vat: "vat" <br>
- *                          , validFrom: TIMESTAMP <br>
- *                          , validTo: TIMESTAMP <br>
- *                          , buySell: "SP" / "PP" <br>
- *                          , fromQuantity: "fromquantity" <br>
- *                          , currency: "keyvalue of keyword 'CURRENCY'" <br>
- *                      } } <br>
- *                   , CurrentValidPriceLists: {$pricelistid$ { <br>
- *                          priceListId: "pricelistid" <br>
- *                          , relationId: "contactid" when filled -> custom price list <br>
- *                          , priceList: "keyvalue of keyword 'PRICELIST'" <br>
- *                          , price: "price" <br>
- *                          , vat: "vat" <br>
- *                          , validFrom: TIMESTAMP <br>
- *                          , validTo: TIMESTAMP <br>
- *                          , buySell: "SP" / "PP" <br>
- *                          , fromQuantity: "fromquantity" <br>
- *                          , currency: "keyvalue of keyword 'CURRENCY'" <br>
- *                      } } <br>
- *                   , PriceListToUse: {$pricelistid$ { <br>
- *                          priceListId: "pricelistid" <br>
- *                          , relationId: "contactid" when filled -> custom price list <br>
- *                          , priceList: "keyvalue of keyword 'PRICELIST'" <br>
- *                          , price: "price" <br>
- *                          , vat: "vat" <br>
- *                          , validFrom: TIMESTAMP <br>
- *                          , validTo: TIMESTAMP <br>
- *                          , buySell: "SP" / "PP" <br>
- *                          , fromQuantity: "fromquantity" <br>
- *                          , currency: "keyvalue of keyword 'CURRENCY'" <br>
- *                      } }, <br>
- *                   INFO: "the productinfo"
- *               }
- */
-ProductUtils.getProductDetails = function(pid, priceListFilter, additionalProductInfoFields)
-{
-    if (additionalProductInfoFields == undefined) {additionalProductInfoFields = []}
-    var ProductDetails = {};
-
-    var cols = [];
-    var colsProduct = ["PRODUCT.PRODUCTID", "PRODUCT.PRODUCTNAME", "PRODUCT.GROUPCODEID", "PRODUCT.UNIT"];
-    var defaultProductFieldCount = colsProduct.length;
-    colsProduct = colsProduct.concat(additionalProductInfoFields.map(function(item) {return "PRODUCT." + item}));
-    
-    cols = cols.concat(colsProduct);
-
-    var joins = [];
-    var orderby = ["PRODUCTID"];
-
-    //PriceList (all)
-    var colsPricelistAll = ["allPP.PRODUCTPRICEID", "allPP.CONTACT_ID", "allPP.PRICELIST", "allPP.PRICE", "allPP.VAT"
-                        , "allPP.VALID_FROM", "allPP.VALID_TO", "allPP.BUYSELL", "allPP.FROMQUANTITY", "allPP.CURRENCY"];
-
-    cols = cols.concat(colsPricelistAll);
-    joins.push(" left join PRODUCTPRICE allPP on allPP.PRODUCT_ID = PRODUCTID ");
-
-    //PriceList (currently valid)
-    var validPriceLists = false;
-    if (priceListFilter != undefined 
-        && priceListFilter.currency != undefined && priceListFilter.currency != "" 
-        && priceListFilter.quantity != undefined && priceListFilter.quantity != "")
-    {
-        validPriceLists = true;
-        var colsPricelistValid = ["validPP.PRODUCTPRICEID", "validPP.CONTACT_ID", "validPP.PRICELIST", "validPP.PRICE", "validPP.VAT"
-                        , "validPP.VALID_FROM", "validPP.VALID_TO", "validPP.BUYSELL", "validPP.FROMQUANTITY", "validPP.CURRENCY"];
-        orderby = orderby.concat(["validPP.VALID_FROM desc", "validPP.FROMQUANTITY desc"]);
-
-        cols = cols.concat(colsPricelistValid);
-        joins.push("left join PRODUCTPRICE validPP on " 
-                    + db.translateCondition(SqlCondition.begin()
-                               .and("validPP.PRODUCT_ID = PRODUCTID")
-                               .andPrepare(["PRODUCTPRICE", "CURRENCY", "validPP"], priceListFilter.currency)
-                               .andPrepare(["PRODUCTPRICE", "VALID_FROM", "validPP"], datetime.date().toString(), "# <= ?")
-                               .andPrepare(["PRODUCTPRICE", "FROMQUANTITY", "validPP"], priceListFilter.quantity, "# <= ?")
-                               .andSqlCondition(SqlCondition.begin()
-                                    .orPrepare(["PRODUCTPRICE", "CONTACT_ID", "validPP"], priceListFilter.relationId)
-                                    .orSqlCondition(SqlCondition.begin()
-                                        .and("validPP.CONTACT_ID is null")
-                                        .andPrepare(["PRODUCTPRICE", "BUYSELL", "validPP"], 'SP'), 
-                                    "1 = 2"), 
-                                "1 = 2")
-                                .build("1 = 2")))
-    }
-    
-    var ProductDataSql = SqlCondition.begin()
-                            .andPrepare("PRODUCT.PRODUCTID", pid)
-                            .buildSql("select " + cols.join(", ") + " from PRODUCT " + joins.join(" "),
-                                         "1 = 2",
-                                         "order by " + orderby.join(", "))
-logging.log(ProductDataSql.toSource())
-    var ProductData = db.table(ProductDataSql);
-
-    for (var i = 0; i < ProductData.length; i++)
-    {
-        //Product
-        if (ProductDetails.productId == undefined)
-        {
-            ProductDetails = {
-                            productId: ProductData[i][0]
-                            , productName: ProductData[i][1]
-                            , groupCode: ProductData[i][2]
-                            , unit: ProductData[i][3]
-                            , PriceLists: {}
-                            , CurrentValidPriceLists: {}
-                            , PriceListToUse: null
-                        };
-                        
-            // add additional fields to the details
-            var countPos = defaultProductFieldCount;
-            additionalProductInfoFields.forEach(function(productField)
-            {
-                this[productField] = ProductData[i][countPos];
-                countPos++;
-            }, ProductDetails);
-        }
-        //Pricelist (all)
-        var colIdx = colsProduct.length;
-        if (ProductData[i][colIdx] != "" && ProductDetails.PriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found
-        {
-            ProductDetails.PriceLists[ProductData[i][colIdx]] = _getPriceListObject();
-        }
-
-        //Pricelist (currently valid)
-        colIdx = colsProduct.length + colsPricelistAll.length;
-        if (validPriceLists)
-        {
-            if (ProductData[i][colIdx] != "" && ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found
-            {
-                ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] = _getPriceListObject();
-            }
-        }
-    }
-
-    if (validPriceLists)
-        ProductDetails.PriceListToUse = _getPriceListToUse(ProductDetails.CurrentValidPriceLists, priceListFilter);
-
-    return ProductDetails;
-
-    function _getPriceListObject() {
-        return {
-                priceListId: ProductData[i][colIdx++]
-                , relationId: ProductData[i][colIdx++]
-                , priceList: ProductData[i][colIdx++]
-                , price: ProductData[i][colIdx++]
-                , vat: ProductData[i][colIdx++]
-                , validFrom: ProductData[i][colIdx++]
-                , validTo: ProductData[i][colIdx++]
-                , buySell: ProductData[i][colIdx++]
-                , fromQuantity: ProductData[i][colIdx++]
-                , currency: ProductData[i][colIdx++]
-        };
-    }
-
-    //price list to use for offer/order
-    function _getPriceListToUse(priceLists, priceListFilter) {
-        for (var list in priceLists) {
-            //custom price (defined in Org -> Conditions)
-            if (priceListFilter.relationId != "" && priceListFilter.relationId == priceLists[list].relationId) {
-                return priceLists[list];
-            }
-            //customer deposited price list (defined by Attribute)
-            if (priceListFilter.priceList != "" && priceListFilter.priceList == priceLists[list].priceList) {
-                return priceLists[list];
-            }
-            //default price list
-            if (priceLists[list].priceList == $KeywordRegistry.productPricelist$standardList()) {
-                return priceLists[list];
-            }
-        }
-
-        //no valid price list found
-        return null;
-    }
-}
-
-/**
- * Checks if there is already an existing price list identical to the passed price list 
- * 
- * @param {String} pid ProductID
- * @param {Object} priceList { <br>
- *                                  priceList: "keyvalue of keyword 'PRICELIST'" <br>
- *                                  , validFrom: TIMESTAMP <br>
- *                                  , validTo: TIMESTAMP <br>
- *                                  , buySell: "SP" / "PP" <br>
- *                                  , fromQuantity: "fromquantity" <br>
- *                                  , currency: "keyvalue of keyword 'CURRENCY'" <br>
- *                             }
- * 
- * @example //Productprice_entity, Field: PRICELIST, Process: onValidation
- *          var pUtils = new ProductUtils();
- *          var priceList = {
- *                          priceList: ProcessHandlingUtils.getOnValidationValue(vars.get("$field.PRICELIST"))
- *                          , fromQuantity: vars.get("$field.FROMQUANTITY")
- *                          , buySell: vars.get("$field.BUYSELL")
- *                          , currency: vars.get("$field.CURRENCY")
- *                          , validFrom: vars.get("$field.VALID_FROM")
- *                          , validTo: vars.get("$field.VALID_TO")
- *                      };
- *
- *          var identicalPriceList = pUtils.checkForIndenticalPriceLists(vars.get("$field.PRODUCT_ID"), priceList);
- *          if (identicalPriceList != null)
- *          {
- *              result.string(translate.text("Identical price list found!"));
- *          }
- * 
- * @return {Object | null} null if no identical price list was found, otherwise the found price list
- */
-ProductUtils.checkForIndenticalPriceLists = function(pid, priceList) {
-    var PriceLists = this.getProductDetails(pid).PriceLists;
-
-    for (var pricelist in PriceLists) {
-        //different pricelist id
-        //equal price list
-        //equal fromquantity
-        //equal currency
-        //equal pp/sp
-        if (priceList.priceListId != PriceLists[pricelist].priceListId
-            && priceList.priceList == PriceLists[pricelist].priceList 
-            && parseFloat(priceList.fromQuantity) == parseFloat(PriceLists[pricelist].fromQuantity) 
-            && priceList.buySell == PriceLists[pricelist].buySell
-            && priceList.currency == PriceLists[pricelist].currency) {
-            
-            //identical validFrom & validTo
-            // OR NOT [ validFrom_new <= validFrom & validTo_new <= validTo
-            //        OR validFrom_new >= validFrom & validTo_new >= validTo
-            //        OR validFrom_new < validFrom & validTo_new > validTo
-            // ]
-            if (priceList.validFrom == PriceLists[pricelist].validFrom && priceList.validTo == PriceLists[pricelist].validTo
-                || ! (priceList.validFrom <= PriceLists[pricelist].validFrom && priceList.validTo <= PriceLists[pricelist].validTo
-                       || priceList.validFrom >= PriceLists[pricelist].validFrom && priceList.validTo >= PriceLists[pricelist].validTo
-                       || priceList.validFrom < PriceLists[pricelist].validFrom && priceList.validTo > PriceLists[pricelist].validTo)) {
-                //identical price list found
-                return PriceLists[pricelist];
-            }
-        }
-    }
-
-    //no identical price list found
-    return null;        
-}
-
-/**
- * returns the image for a product
- * 
- * @param {String} pProductId the id of the product.
- * @param {String} pDefaultText the text, to use for default image generation.
- * @return {String} base64 coded String of the image. If none existed, the given String is used to create an image.
- */
-ProductUtils.getImage = function(pProductId, pDefaultText)
-{
-    return ImageUtils.get("PRODUCT", "IMAGE", pProductId, pDefaultText);
-}
-
-/**
- * sets the image of a product
- * 
- * @param {String} pProductId the id of the product.
- * @param {String} pImageDateBase64 base64 coded String of the image.
- * @return {Boolean} if image could be set
- */
-ProductUtils.setImage = function(pProductId, pImageDateBase64)
-{
-    return ImageUtils.set("PRODUCT", "IMAGE", pProductId, pImageDateBase64, "ProductImage", "Image of the product");
-}
-
-/**
- * deletes the image of a product
- * 
- * @param {String} pProductId the id of the product.
- * @return {Boolean} if image could be removed
- */
-ProductUtils.removeImage = function(pProductId)
-{
-    return ImageUtils.remove("PRODUCT", "IMAGE", pProductId);
-}
-
-/**
- * Class containing utility functions for Prod2Prod (Parts list)
- * 
- * @param {String} productId req ProductID
- * 
- * @class
- *
- */
-function Prod2ProdUtils(productId) {    
-    this.productId = productId;
-    this.data = undefined;
-}
-
-/**
- * Delivers an Object containing parts list structure for passed product "productId" (Constructor parameter)
- * 
- * @return {Object} { $prod2prodid$ { <br>
- *                       ids: [ Array containing child Prod2ProdIds for passed product "pProductId" (Constructor parameter) ] <br>
- *                       , rowdata: [ "PROD2PRODID", "DEST_ID", "SOURCE_ID", "QUANTITY", "OPTIONAL", "TAKEPRICE" ] from DB-Table PROD2PROD <br>
- *                       , destid: "Parent ProductID" <br>
- *                       , sourceid: "Child ProductID" <br>
- *                       , quantity: "Quantity" <br>
- *                       , optional: "0" = not optional, "1" = optional <br>
- *                       , takeprice: "0" = no price, "1" = price <br>
- *                  } }
- */
-Prod2ProdUtils.prototype.getPartsListObject = function() {
-    return this._relateChilds().getTreeObject();
-}
-
-/**
- * Delivers a 2D-Array for RecordContainer of Entity "Prod2prod_entity" 
- * containing parts list for passed product "productId" (Constructor parameter).
- * 
- * It is necessary to generate a specifically UID for the RecordContainer because 
- * the same data record can be listed several times. Therefore the primary key "PROD2PRODID"
- * can not be used for UID because this must be unique.
- * 
- * @return {String[][]} [ ["UID"
- *                    , "PARENTID" (equals "DEST_ID")
- *                    , "PROD2PRODID"
- *                    , "DEST_ID"
- *                    , "SOURCE_ID"
- *                    , "QUANTITY"
- *                    , "OPTIONAL"
- *                    , "TAKEPRICE"
- *                    , "PRODUCTCODE"
- *                    , "PRODUCTID"] ]
- */
-Prod2ProdUtils.prototype.getPartsListForRecordContainer = function() {
-    var tree = this._relateChilds();
-    return tree.toArray(7);
-}
-
-/**
-* Delivers an Array containing productids of the parts list 
-* for passed product "productId" (Constructor parameter).
-* 
-* 
-* @return {String[]} [ "SOURCE_ID" ]
-*/
-Prod2ProdUtils.prototype.getPartsListProdIds = function() {
-    var ret = [];
-    var childs = this._relateChilds().getTreeObject();
-
-    __push(childs.root);
-
-    return ret;
-
-    function __push(pObj) {
-        for (var i = 0; i < pObj.ids.length; i++) {
-            ret.push(childs[pObj.ids[i]].sourceid);
-            __push(childs[pObj.ids[i]]);
-        }
-    }
-}
-
-/**
-* Delivers an Array containing productids of the parent list
-* for passed product "productId" (Constructor parameter).
-* 
-* 
-* @return {String[]} [ "DEST_ID" ]
-*/
-Prod2ProdUtils.prototype.getParentProdIds = function() {
-    var ret = [];
-    var parents = this._relateParents();
-
-    __push(parents.root);
-
-    return ret;
-
-    function __push(pObj) {
-        for (var i = 0; i < pObj.ids.length; i++) {
-            ret.push(parents[pObj.ids[i]].destid);
-            __push(parents[pObj.ids[i]]);
-        }
-    }
-}
-
-/** 
-* Function to initalize class variable "data" containing complete Prod2Prod-Data.<br>
-* It guarantees a unique load of data per instance.
-*
-* @ignore
-*/
-Prod2ProdUtils.prototype._initProd2ProdData = function() {
-    if (this.data == undefined) {
-        this.data = db.table("select SOURCE_ID, DEST_ID, PROD2PRODID, QUANTITY, OPTIONAL, TAKEPRICE, PRODUCTCODE, PRODUCTID, SOURCE_ID, DEST_ID "
-                    + "from PROD2PROD join PRODUCT on PROD2PROD.SOURCE_ID = PRODUCTID "
-                    + "order by PRODUCTCODE ");
-    }
-}
-
-/**
- * object tree to relate products by DEST_ID / SOURCE_ID.
- **/
-Prod2ProdUtils.prototype._buildTree = function(supervised) {
-    this._initProd2ProdData();
-    var productId = this.productId;
-        
-    var tree = DataTree.begin(this.productId).addArray(this.data,
-        function(pUid, pNode)
-        {
-            if (pUid == productId)
-            {
-                pNode["sourceid"] = productId;
-                if (supervised) 
-                {
-                    pNode["destid"] = productId;
-                }
-            } 
-            else
-            {
-                pNode["destid"] = pNode.parent;
-                pNode["sourceid"] = pUid;
-                
-                if (pNode.data != undefined) {
-                    pNode["quantity"] = pNode.data[1];
-                    pNode["optional"] = pNode.data[2];
-                    pNode["takeprice"] = pNode.data[3];
-                    pNode["productcode"] = pNode.data[4];
-                    pNode["productid"] = pNode.data[5];
-                }
-            }
-        }
-    );
-
-    return tree;
-}
-
-Prod2ProdUtils.prototype._relateChilds = function() {
-    var tree = this._buildTree(false);
-    __relate(this.productId);
-
-    return tree;
-
-    function __relate(id) {
-        var treeObject = tree.getTreeObject();
-        if (treeObject[id] != undefined)
-        {
-            for (var treeId in treeObject) {
-                if (treeObject[treeId].destid == treeObject[id].sourceid && treeObject[id].ids.indexOf(treeId) == -1) { 
-                    treeObject[id].ids.push(treeId);
-                    __relate(treeId);
-                }    
-            }
-        }
-    }
-}
-
-Prod2ProdUtils.prototype._relateParents = function() {
-    var tree = this._buildTree(true);
-
-    __relate(this.productId);
-
-    return tree;
-
-
-    function __relate(id) {
-        var treeObject = tree.getTreeObject();
-        if (treeObject[id] != undefined)
-        {
-            for (var treeId in treeObject) {
-                if (treeObject[treeId].sourceid == treeObject[id].destid && treeObject[id].ids.indexOf(treeId) == -1) {   
-                    treeObject[id].ids.push(treeId);
-                    __relate(treeId);
-                }    
-            }
-        }
-    }
+import("system.logging");
+import("system.util");
+import("system.SQLTYPES");
+import("system.datetime");
+import("system.db");
+import("system.vars");
+import("system.translate");
+import("KeywordRegistry_basic");
+import("Util_lib");
+import("Binary_lib");
+import("Sql_lib");
+import("Keyword_lib");
+import("Data_lib");
+
+/**
+ * utility functions for products
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function ProductUtils() {}
+
+/**
+ * Delivers the currently valid product price 
+ * 
+ * @param {String} pid ProductID
+ * @param {String} buySell possible values: PP, SP
+ * 
+ * @example productUtils.getCurrentProductPrice(vars.get("$field.PRODUCTID"), "PP")
+ * 
+ * @return {Array[]} currently valid product price with currency: [price, "CURRENCY"] or [] if no price found
+ */
+ProductUtils.getCurrentProductPrice = function(pid, buySell) {
+    if (pid != undefined && pid != "" && buySell != undefined && buySell != "")
+    {
+        var today = datetime.clearTime(vars.get("sys.date"), "utc");
+        var actualPriceCondition = SqlCondition.begin()
+                    .andPrepare("PRODUCTPRICE.BUYSELL", buySell)
+                    .andPrepare("PRODUCTPRICE.PRODUCT_ID", pid)
+                    .andPrepare("PRODUCTPRICE.VALID_FROM", today, "# <= ?")
+                    .andSqlCondition(SqlCondition.begin()
+                        .orPrepare("PRODUCTPRICE.VALID_TO", today, "# >= ?")
+                        .or("PRODUCTPRICE.VALID_TO is null"), "1 = 2");
+                            
+        var productPriceData = db.array(db.ROW, actualPriceCondition.buildSql("select PRICE, CURRENCY from PRODUCTPRICE", "1 = 2", "order by VALID_FROM desc"));
+
+        if (productPriceData[0] && productPriceData[1])
+            return  [productPriceData[0], KeywordUtils.getViewValue($KeywordRegistry.currency(), productPriceData[1])];
+        else
+            return [];
+    } else {
+        return [];
+    }
+}
+
+/**
+ * Delivers the stock
+ * 
+ * @param {String} pid ProductID
+ * 
+ * @example productUtils.getStockCount(vars.get("$field.PRODUCTID"))
+ * 
+ * @return {String} stock count
+ */
+ProductUtils.getStockCount = function(pid) {
+    if (pid != undefined && pid != "")
+    {
+        var sum = db.cell(SqlCondition.begin()
+                                      .andPrepare("STOCK.PRODUCT_ID", pid)
+                                      .buildSql("select sum(QUANTITY * case IN_OUT when 0 then -1 else 1)"
+                                                 + " from STOCK"));
+        
+        if (sum == "")
+            sum = "0";
+
+        return sum;
+    }
+    else
+    {
+        throw new Error(translate.withArguments("${PRODUCT_LIB_NO_PRODUCT_ID} function: %0", ["ProductUtils.getStockCount"]));
+    }
+}
+
+/**
+ * Delivers metadata and price lists of the passed product. 
+ * If parameter "priceListFilter" is passed valid price lists and the 
+ * current price list to use for offer/order are delivered.
+ * 
+ * @param {String} pid req ProductID
+ * @param {Object} priceListFilter opt { currency: "currencyValue", quantity: "quantityValue", relationId: "relationIdValue (for custom price lists)" }
+ * @param {String[]} additionalProductInfoFields additional fields from Product
+ *                   They are added to the result with the Fieldname as key. e.g. if the array is ["INFO"] the result will contain the key "INFO"
+ * 
+ * @example //Product_entity, Field: PRODUCT_ID, Process: onValueChange
+ *          var pid = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.PRODUCT_ID"));
+ *          var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
+ *          var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
+ *          var pUtils = new ProductUtils();
+ *          var PriceListFilter = { currency: curr, quantity: vars.get("$field.QUANTITY"), contactId: contactid };
+ *          var ProductDetails = pUtils.getProductDetails(pid, PriceListFilter, ["INFO"]);
+ * 
+ * @return {Object} { <br>
+ *                   productId: "productid" <br>
+ *                   , productName: "product name" <br>
+ *                   , groupCode: "keyvalue of keyword 'GROUPCODE'" <br>
+ *                   , unit: "keyvalue of keyword 'UNIT'" <br>
+ *                   , PriceLists: {$pricelistid$ { <br>
+ *                          priceListId: "pricelistid" <br>
+ *                          , relationId: "contactid" when filled -> custom price list <br>
+ *                          , priceList: "keyvalue of keyword 'PRICELIST'" <br>
+ *                          , price: "price" <br>
+ *                          , vat: "vat" <br>
+ *                          , validFrom: TIMESTAMP <br>
+ *                          , validTo: TIMESTAMP <br>
+ *                          , buySell: "SP" / "PP" <br>
+ *                          , fromQuantity: "fromquantity" <br>
+ *                          , currency: "keyvalue of keyword 'CURRENCY'" <br>
+ *                      } } <br>
+ *                   , CurrentValidPriceLists: {$pricelistid$ { <br>
+ *                          priceListId: "pricelistid" <br>
+ *                          , relationId: "contactid" when filled -> custom price list <br>
+ *                          , priceList: "keyvalue of keyword 'PRICELIST'" <br>
+ *                          , price: "price" <br>
+ *                          , vat: "vat" <br>
+ *                          , validFrom: TIMESTAMP <br>
+ *                          , validTo: TIMESTAMP <br>
+ *                          , buySell: "SP" / "PP" <br>
+ *                          , fromQuantity: "fromquantity" <br>
+ *                          , currency: "keyvalue of keyword 'CURRENCY'" <br>
+ *                      } } <br>
+ *                   , PriceListToUse: {$pricelistid$ { <br>
+ *                          priceListId: "pricelistid" <br>
+ *                          , relationId: "contactid" when filled -> custom price list <br>
+ *                          , priceList: "keyvalue of keyword 'PRICELIST'" <br>
+ *                          , price: "price" <br>
+ *                          , vat: "vat" <br>
+ *                          , validFrom: TIMESTAMP <br>
+ *                          , validTo: TIMESTAMP <br>
+ *                          , buySell: "SP" / "PP" <br>
+ *                          , fromQuantity: "fromquantity" <br>
+ *                          , currency: "keyvalue of keyword 'CURRENCY'" <br>
+ *                      } }, <br>
+ *                   INFO: "the productinfo"
+ *               }
+ */
+ProductUtils.getProductDetails = function(pid, priceListFilter, additionalProductInfoFields)
+{
+    if (additionalProductInfoFields == undefined) {additionalProductInfoFields = []}
+    var ProductDetails = {};
+
+    var cols = [];
+    var colsProduct = ["PRODUCT.PRODUCTID", "PRODUCT.PRODUCTNAME", "PRODUCT.GROUPCODEID", "PRODUCT.UNIT"];
+    var defaultProductFieldCount = colsProduct.length;
+    colsProduct = colsProduct.concat(additionalProductInfoFields.map(function(item) {return "PRODUCT." + item}));
+    
+    cols = cols.concat(colsProduct);
+
+    var joins = [];
+    var orderby = ["PRODUCTID"];
+
+    //PriceList (all)
+    var colsPricelistAll = ["allPP.PRODUCTPRICEID", "allPP.CONTACT_ID", "allPP.PRICELIST", "allPP.PRICE", "allPP.VAT"
+                        , "allPP.VALID_FROM", "allPP.VALID_TO", "allPP.BUYSELL", "allPP.FROMQUANTITY", "allPP.CURRENCY"];
+
+    cols = cols.concat(colsPricelistAll);
+    joins.push(" left join PRODUCTPRICE allPP on allPP.PRODUCT_ID = PRODUCTID ");
+
+    //PriceList (currently valid)
+    var validPriceLists = false;
+    if (priceListFilter != undefined 
+        && priceListFilter.currency != undefined && priceListFilter.currency != "" 
+        && priceListFilter.quantity != undefined && priceListFilter.quantity != "")
+    {
+        validPriceLists = true;
+        var colsPricelistValid = ["validPP.PRODUCTPRICEID", "validPP.CONTACT_ID", "validPP.PRICELIST", "validPP.PRICE", "validPP.VAT"
+                        , "validPP.VALID_FROM", "validPP.VALID_TO", "validPP.BUYSELL", "validPP.FROMQUANTITY", "validPP.CURRENCY"];
+        orderby = orderby.concat(["validPP.VALID_FROM desc", "validPP.FROMQUANTITY desc"]);
+
+        cols = cols.concat(colsPricelistValid);
+        joins.push("left join PRODUCTPRICE validPP on " 
+                    + db.translateCondition(SqlCondition.begin()
+                               .and("validPP.PRODUCT_ID = PRODUCTID")
+                               .andPrepare(["PRODUCTPRICE", "CURRENCY", "validPP"], priceListFilter.currency)
+                               .andPrepare(["PRODUCTPRICE", "VALID_FROM", "validPP"], datetime.date().toString(), "# <= ?")
+                               .andPrepare(["PRODUCTPRICE", "FROMQUANTITY", "validPP"], priceListFilter.quantity, "# <= ?")
+                               .andSqlCondition(SqlCondition.begin()
+                                    .orPrepare(["PRODUCTPRICE", "CONTACT_ID", "validPP"], priceListFilter.relationId)
+                                    .orSqlCondition(SqlCondition.begin()
+                                        .and("validPP.CONTACT_ID is null")
+                                        .andPrepare(["PRODUCTPRICE", "BUYSELL", "validPP"], 'SP'), 
+                                    "1 = 2"), 
+                                "1 = 2")
+                                .build("1 = 2")))
+    }
+    
+    var ProductDataSql = SqlCondition.begin()
+                            .andPrepare("PRODUCT.PRODUCTID", pid)
+                            .buildSql("select " + cols.join(", ") + " from PRODUCT " + joins.join(" "),
+                                         "1 = 2",
+                                         "order by " + orderby.join(", "))
+                                         
+    var ProductData = db.table(ProductDataSql);
+
+    for (var i = 0; i < ProductData.length; i++)
+    {
+        //Product
+        if (ProductDetails.productId == undefined)
+        {
+            ProductDetails = {
+                            productId: ProductData[i][0]
+                            , productName: ProductData[i][1]
+                            , groupCode: ProductData[i][2]
+                            , unit: ProductData[i][3]
+                            , PriceLists: {}
+                            , CurrentValidPriceLists: {}
+                            , PriceListToUse: null
+                        };
+                        
+            // add additional fields to the details
+            var countPos = defaultProductFieldCount;
+            additionalProductInfoFields.forEach(function(productField)
+            {
+                this[productField] = ProductData[i][countPos];
+                countPos++;
+            }, ProductDetails);
+        }
+        //Pricelist (all)
+        var colIdx = colsProduct.length;
+        if (ProductData[i][colIdx] != "" && ProductDetails.PriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found
+        {
+            ProductDetails.PriceLists[ProductData[i][colIdx]] = _getPriceListObject();
+        }
+
+        //Pricelist (currently valid)
+        colIdx = colsProduct.length + colsPricelistAll.length;
+        if (validPriceLists)
+        {
+            if (ProductData[i][colIdx] != "" && ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found
+            {
+                ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] = _getPriceListObject();
+            }
+        }
+    }
+
+    if (validPriceLists)
+        ProductDetails.PriceListToUse = _getPriceListToUse(ProductDetails.CurrentValidPriceLists, priceListFilter);
+
+    return ProductDetails;
+
+    function _getPriceListObject() {
+        return {
+                priceListId: ProductData[i][colIdx++]
+                , relationId: ProductData[i][colIdx++]
+                , priceList: ProductData[i][colIdx++]
+                , price: ProductData[i][colIdx++]
+                , vat: ProductData[i][colIdx++]
+                , validFrom: ProductData[i][colIdx++]
+                , validTo: ProductData[i][colIdx++]
+                , buySell: ProductData[i][colIdx++]
+                , fromQuantity: ProductData[i][colIdx++]
+                , currency: ProductData[i][colIdx++]
+        };
+    }
+
+    //price list to use for offer/order
+    function _getPriceListToUse(priceLists, priceListFilter) {
+        for (var list in priceLists) {
+            //custom price (defined in Org -> Conditions)
+            if (priceListFilter.relationId != "" && priceListFilter.relationId == priceLists[list].relationId) {
+                return priceLists[list];
+            }
+            //customer deposited price list (defined by Attribute)
+            if (priceListFilter.priceList != "" && priceListFilter.priceList == priceLists[list].priceList) {
+                return priceLists[list];
+            }
+            //default price list
+            if (priceLists[list].priceList == $KeywordRegistry.productPricelist$standardList()) {
+                return priceLists[list];
+            }
+        }
+
+        //no valid price list found
+        return null;
+    }
+}
+
+/**
+ * Checks if there is already an existing price list identical to the passed price list 
+ * 
+ * @param {String} pid ProductID
+ * @param {Object} priceList { <br>
+ *                                  priceList: "keyvalue of keyword 'PRICELIST'" <br>
+ *                                  , validFrom: TIMESTAMP <br>
+ *                                  , validTo: TIMESTAMP <br>
+ *                                  , buySell: "SP" / "PP" <br>
+ *                                  , fromQuantity: "fromquantity" <br>
+ *                                  , currency: "keyvalue of keyword 'CURRENCY'" <br>
+ *                             }
+ * 
+ * @example //Productprice_entity, Field: PRICELIST, Process: onValidation
+ *          var pUtils = new ProductUtils();
+ *          var priceList = {
+ *                          priceList: ProcessHandlingUtils.getOnValidationValue(vars.get("$field.PRICELIST"))
+ *                          , fromQuantity: vars.get("$field.FROMQUANTITY")
+ *                          , buySell: vars.get("$field.BUYSELL")
+ *                          , currency: vars.get("$field.CURRENCY")
+ *                          , validFrom: vars.get("$field.VALID_FROM")
+ *                          , validTo: vars.get("$field.VALID_TO")
+ *                      };
+ *
+ *          var identicalPriceList = pUtils.checkForIndenticalPriceLists(vars.get("$field.PRODUCT_ID"), priceList);
+ *          if (identicalPriceList != null)
+ *          {
+ *              result.string(translate.text("Identical price list found!"));
+ *          }
+ * 
+ * @return {Object | null} null if no identical price list was found, otherwise the found price list
+ */
+ProductUtils.checkForIndenticalPriceLists = function(pid, priceList) {
+    var PriceLists = this.getProductDetails(pid).PriceLists;
+
+    for (var pricelist in PriceLists) {
+        //different pricelist id
+        //equal price list
+        //equal fromquantity
+        //equal currency
+        //equal pp/sp
+        if (priceList.priceListId != PriceLists[pricelist].priceListId
+            && priceList.priceList == PriceLists[pricelist].priceList 
+            && parseFloat(priceList.fromQuantity) == parseFloat(PriceLists[pricelist].fromQuantity) 
+            && priceList.buySell == PriceLists[pricelist].buySell
+            && priceList.currency == PriceLists[pricelist].currency) {
+            
+            //identical validFrom & validTo
+            // OR NOT [ validFrom_new <= validFrom & validTo_new <= validTo
+            //        OR validFrom_new >= validFrom & validTo_new >= validTo
+            //        OR validFrom_new < validFrom & validTo_new > validTo
+            // ]
+            if (priceList.validFrom == PriceLists[pricelist].validFrom && priceList.validTo == PriceLists[pricelist].validTo
+                || ! (priceList.validFrom <= PriceLists[pricelist].validFrom && priceList.validTo <= PriceLists[pricelist].validTo
+                       || priceList.validFrom >= PriceLists[pricelist].validFrom && priceList.validTo >= PriceLists[pricelist].validTo
+                       || priceList.validFrom < PriceLists[pricelist].validFrom && priceList.validTo > PriceLists[pricelist].validTo)) {
+                //identical price list found
+                return PriceLists[pricelist];
+            }
+        }
+    }
+
+    //no identical price list found
+    return null;        
+}
+
+/**
+ * returns the image for a product
+ * 
+ * @param {String} pProductId the id of the product.
+ * @param {String} pDefaultText the text, to use for default image generation.
+ * @return {String} base64 coded String of the image. If none existed, the given String is used to create an image.
+ */
+ProductUtils.getImage = function(pProductId, pDefaultText)
+{
+    return ImageUtils.get("PRODUCT", "IMAGE", pProductId, pDefaultText);
+}
+
+/**
+ * sets the image of a product
+ * 
+ * @param {String} pProductId the id of the product.
+ * @param {String} pImageDateBase64 base64 coded String of the image.
+ * @return {Boolean} if image could be set
+ */
+ProductUtils.setImage = function(pProductId, pImageDateBase64)
+{
+    return ImageUtils.set("PRODUCT", "IMAGE", pProductId, pImageDateBase64, "ProductImage", "Image of the product");
+}
+
+/**
+ * deletes the image of a product
+ * 
+ * @param {String} pProductId the id of the product.
+ * @return {Boolean} if image could be removed
+ */
+ProductUtils.removeImage = function(pProductId)
+{
+    return ImageUtils.remove("PRODUCT", "IMAGE", pProductId);
+}
+
+/**
+ * Class containing utility functions for Prod2Prod (Parts list)
+ * 
+ * @param {String} productId req ProductID
+ * 
+ * @class
+ *
+ */
+function Prod2ProdUtils(productId) 
+{    
+    this.productId = productId;
+    this.data = undefined;
+}
+
+/**
+ * Delivers an Object containing parts list structure for passed product "pProductId" (Constructor parameter)
+ *  
+ * @return {Object} { $prod2prodid$ { <br>
+ *                       ids: [ Array containing child Prod2ProdIds for passed product "pProductId" (Constructor parameter) ] <br>
+ *                       , rowdata: [ "PROD2PRODID", "DEST_ID", "SOURCE_ID", "QUANTITY", "OPTIONAL", "TAKEPRICE" ] from DB-Table PROD2PROD <br>
+ *                       , destid: "Parent ProductID" <br>
+ *                       , sourceid: "Child ProductID" <br>
+ *                       , quantity: "Quantity" <br>
+ *                       , optional: "0" = not optional, "1" = optional <br>
+ *                       , takeprice: "0" = no price, "1" = price <br>
+ *                       , productcode: "Productcode" <br>
+ *                       , productid: "Productid" <br>
+ *                  } }
+ */
+Prod2ProdUtils.prototype.getPartsListObject = function() 
+{
+    return this._relateChilds();
+}
+
+/**
+ * Delivers a 2D-Array for RecordContainer of Entity "Prod2prod_entity" 
+ * containing parts list for passed product "productId" (Constructor parameter).
+ * 
+ * It is necessary to generate a specifically UID for the RecordContainer because 
+ * the same data record can be listed several times. Therefore the primary key "PROD2PRODID"
+ * can not be used for UID because this must be unique.
+ * 
+ * @return {String[][]} [ ["UID"
+ *                    , "PARENTID" (equals "DEST_ID")
+ *                    , "PROD2PRODID"
+ *                    , "DEST_ID"
+ *                    , "SOURCE_ID"
+ *                    , "QUANTITY"
+ *                    , "OPTIONAL"
+ *                    , "TAKEPRICE"
+ *                    , "PRODUCTCODE"
+ *                    , "PRODUCTID"] ]
+ */
+Prod2ProdUtils.prototype.getPartsListForRecordContainer = function() 
+{
+    var ret = [];
+    var childs = this._relateChilds();
+
+    __push(childs.root);
+
+    function __push(pObj)
+    {
+        for(var i = 0; i < pObj.ids.length; i++)
+        {
+            var rowdata = childs[pObj.ids[i]].rowdata;
+            var UID = util.getNewUUID();
+            var PARENTID = childs[pObj.ids[i]].destid;
+
+            rowdata = [UID, PARENTID].concat(rowdata);
+            ret.push(rowdata);
+            __push( childs[pObj.ids[i]] );
+        }
+    }
+    return ret;
+}
+
+/**
+* Delivers an Array containing productids of the parts list 
+* for passed product "productId" (Constructor parameter).
+* 
+* 
+* @return {String[]} [ "SOURCE_ID" ]
+*/
+Prod2ProdUtils.prototype.getPartsListProdIds = function() 
+{
+    var ret = [];
+    var childs = this._relateChilds();
+
+    __push(childs.root);
+
+    return ret;
+
+    function __push(pObj)
+    {
+        for(var i = 0; i < pObj.ids.length; i++)
+        {
+            ret.push(childs[pObj.ids[i]].sourceid);
+            __push( childs[pObj.ids[i]] );
+        }
+    }
+}
+
+/**
+* Delivers an Array containing productids of the parent list
+* for passed product "productId" (Constructor parameter).
+* 
+* 
+* @return {String[]} [ "DEST_ID" ]
+*/
+Prod2ProdUtils.prototype.getParentProdIds = function() 
+{
+    var ret = [];
+    var parents = this._relateParents();
+
+    __push(parents.root);
+
+    return ret;
+
+    function __push(pObj)
+    {
+        for(var i = 0; i < pObj.ids.length; i++)
+        {
+            ret.push(parents[pObj.ids[i]].destid);
+            __push( parents[pObj.ids[i]] );
+        }
+    }
+}
+
+/** 
+* Function to initalize class variable "data" containing complete Prod2Prod-Data.<br>
+* It guarantees a unique load of data per instance.
+*
+* @ignore
+*/
+Prod2ProdUtils.prototype._initProd2ProdData = function()
+{
+    if (this.data == undefined) {
+        this.data = db.table("select PROD2PRODID, DEST_ID, SOURCE_ID, QUANTITY, OPTIONAL, TAKEPRICE, PRODUCTCODE, PRODUCTID "
+                    + "from PROD2PROD join PRODUCT on PROD2PROD.SOURCE_ID = PRODUCTID "
+                    + "order by PRODUCTCODE ");
+    }
+}
+
+/**
+ * object tree to relate products by DEST_ID / SOURCE_ID.
+ **/
+Prod2ProdUtils.prototype._buildTree = function(pSupervised)
+{
+    this._initProd2ProdData();
+
+        var tree = { root: {ids: [], sourceid: this.productId } };
+        
+        if(pSupervised)
+            tree = { root: {ids: [], destid: this.productId } };
+
+        for (var i = 0; i < this.data.length; i++)
+        {
+            var prod2prodid = this.data[i][0];
+            if ( tree[prod2prodid] == undefined )   
+            {
+                tree[prod2prodid] = {
+                    ids: [] 
+                    , rowdata: this.data[i].slice(0)//copy to get NativeArray for concatenation
+                    , destid: this.data[i][1]
+                    , sourceid: this.data[i][2] 
+                    , quantity: this.data[i][3]
+                    , optional: this.data[i][4]
+                    , takeprice: this.data[i][5]
+                    , productcode: this.data[i][6]
+                    , productid: this.data[i][7]
+                };
+            }
+        }
+        
+        return tree;
+
+}
+
+Prod2ProdUtils.prototype._relateChilds = function()
+{
+    var tree = this._buildTree(false);
+
+    __relate("root");
+
+    return tree;
+
+    function __relate(pID)
+    {
+        for ( var id in tree )
+        {
+            if ( tree[id].destid == tree[pID].sourceid && tree[pID].ids.indexOf(id) == -1 )
+            {   
+                tree[pID].ids.push(id);
+                __relate(id);
+            }    
+        }
+    }
+}
+
+Prod2ProdUtils.prototype._relateParents = function() 
+{
+    var tree = this._buildTree(true);
+
+    __relate("root");
+
+    return tree;
+
+
+    function __relate(pID)
+    {
+        for ( var id in tree )
+        {
+            if ( tree[id].sourceid == tree[pID].destid && tree[pID].ids.indexOf(id) == -1 )
+            {   
+                tree[pID].ids.push(id);
+                __relate(id);
+            }    
+        }
+    }
 }
\ No newline at end of file
diff --git a/process/Salesproject_lib/process.js b/process/Salesproject_lib/process.js
index 6887b3ee1b7ec63315f82d96e785398cc9f9a95f..380aecbc0df64c6f1984150721286c52dfcecdf7 100644
--- a/process/Salesproject_lib/process.js
+++ b/process/Salesproject_lib/process.js
@@ -80,3 +80,16 @@ Salesproject.getSalesProjectTitleById = function(pSalesProjectId)
                         .andPrepare("SALESPROJECT.SALESPROJECTID", pSalesProjectId)
                         .buildSql("select PROJECTTITLE from SALESPROJECT", "1=0"));
 }
+
+/**
+ * Create a new Salesproject and open the Salesproject context in NEW-mode
+ */
+Salesproject.createNewSalesproject= function(pRelationId)
+{
+    var params = {};
+    
+    if (pRelationId)
+        params["ContactId_param"] = pRelationId;
+    
+    neon.openContext("Salesproject", null, null, neon.OPERATINGSTATE_NEW, params);
+}