diff --git a/.liquibase/Data_alias/basic/2019.2/update_TaskType_Task.xml b/.liquibase/Data_alias/basic/2019.2/update_TaskType_Task.xml
index 5bb414d9ead9c49922c7e3800ba2919ca35b74c6..06db96f69c993afceea0547914ec8f6ecdccfa9b 100644
--- a/.liquibase/Data_alias/basic/2019.2/update_TaskType_Task.xml
+++ b/.liquibase/Data_alias/basic/2019.2/update_TaskType_Task.xml
@@ -1,6 +1,14 @@
 <?xml version="1.1" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
     <changeSet author="a.loreth" id="d1440b93-e01c-406b-9f0d-c55cac877fcd">
+        <insert tableName="AB_KEYWORD_ATTRIBUTE">
+            <column name="AB_KEYWORD_ATTRIBUTEID" value="e8e3e2e9-8cce-4582-a71b-7f66593c7ade"/>
+
+            <column name="NAME" value="group"/>
+            <column name="CONTAINER" value="TaskType"/>
+            <column name="TYPE" value="CHAR_VALUE"/>
+        </insert>
+
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="9e30365b-a9a6-4b57-ae6b-140c9e5a4eb4"/>
             <column name="KEYID" value="4dee8727-8299-422e-ae41-6cdf9de2dfd7"/>
@@ -10,16 +18,44 @@
             <column name="ISACTIVE" valueNumeric="1"/>
             <column name="ISESSENTIAL" valueNumeric="1"/>
         </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="1eef7882-90eb-4c5b-a01a-c6cf1ea7a82b"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="9e30365b-a9a6-4b57-ae6b-140c9e5a4eb4"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="e8e3e2e9-8cce-4582-a71b-7f66593c7ade"/>
+            <column name="CHAR_VALUE" value="Task"/>
+        </insert>
         
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="2ef84e0e-988a-44b4-9d14-3461555d2f18"/>
             <column name="KEYID" value="f3da0edd-49d9-4061-98c1-8fda8631be7e"/>
             <column name="TITLE" value="Ticket"/>
             <column name="CONTAINER" value="TaskType"/>
-            <column name="SORTING" valueNumeric="0"/>
+            <column name="SORTING" valueNumeric="1"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+            <column name="ISESSENTIAL" valueNumeric="1"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="ca8e16d4-0bae-45e7-a288-0f8a846193f1"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="2ef84e0e-988a-44b4-9d14-3461555d2f18"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="e8e3e2e9-8cce-4582-a71b-7f66593c7ade"/>
+            <column name="CHAR_VALUE" value="Ticket"/>
+        </insert>
+
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="9d326a2a-923c-41de-adb9-b0f86417e7c2"/>
+            <column name="KEYID" value="7bf77721-470f-4cdf-a6af-452bf05a405b"/>
+            <column name="TITLE" value="Support ticket"/>
+            <column name="CONTAINER" value="TaskType"/>
+            <column name="SORTING" valueNumeric="2"/>
             <column name="ISACTIVE" valueNumeric="1"/>
             <column name="ISESSENTIAL" valueNumeric="1"/>
         </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="6e54c8f3-f24b-411f-a3e3-eba878fdaa1b"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="9d326a2a-923c-41de-adb9-b0f86417e7c2"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="e8e3e2e9-8cce-4582-a71b-7f66593c7ade"/>
+            <column name="CHAR_VALUE" value="Ticket"/>
+        </insert>
 
         <delete tableName="AB_KEYWORD_ENTRY">
             <where>AB_KEYWORD_ENTRYID = ?</where>
diff --git a/entity/Task_entity/entityfields/code/stateProcess.js b/entity/Task_entity/entityfields/code/stateProcess.js
index 385d44b6aa605c6ff4985ba4d9881a398a89ad65..7043cdcb8a099a6a83e0e2cf3861dfeb6e15f794 100644
--- a/entity/Task_entity/entityfields/code/stateProcess.js
+++ b/entity/Task_entity/entityfields/code/stateProcess.js
@@ -1,9 +1,9 @@
+import("system.neon");
 import("system.result");
 import("system.vars");
-import("KeywordRegistry_basic")
-import("system.neon")
+import("ActivityTask_lib");
 
-if (vars.get("$field.TYPE") == $KeywordRegistry.taskType$Ticket())
+if (TaskUtils.getTypeGroup(vars.get("$field.TYPE")) == "Ticket")
 {
     result.string(neon.COMPONENTSTATE_READONLY);
 }
diff --git a/entity/Task_entity/recordcontainers/db/onDBInsert.js b/entity/Task_entity/recordcontainers/db/onDBInsert.js
index 041508a682b2668a1cfa2398a6e20cc7c5be6fbd..d1600f76112729020c057ab2a436a59ca5da716e 100644
--- a/entity/Task_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Task_entity/recordcontainers/db/onDBInsert.js
@@ -1,6 +1,4 @@
 import("system.vars");
-import("Sql_lib");
-import("system.db");
+import("ActivityTask_lib")
 
-var max = db.cell("select max(CODE) from TASK");
-db.updateData("TASK", ["CODE"], null, [parseInt(max)+1], SqlCondition.equals("TASK.TASKID", vars.get("$field.TASKID"), "1=2"));
\ No newline at end of file
+TaskUtils.setCode(vars.get("$field.TASKID"));
\ No newline at end of file
diff --git a/process/ActivityTask_lib/process.js b/process/ActivityTask_lib/process.js
index 26a4efc1d49cfdef8c81de0730eb1c9097a79e69..a201c8776b08042008f7ef53f2598bdc140a8daa 100644
--- a/process/ActivityTask_lib/process.js
+++ b/process/ActivityTask_lib/process.js
@@ -9,6 +9,7 @@ import("system.eMath");
 import("Util_lib");
 import("Sql_lib");
 import("Keyword_lib");
+import("KeywordRegistry_basic");
 import("Product_lib");
 import("Report_lib");
 import("Context_lib");
@@ -101,6 +102,20 @@ TaskUtils.hasTasks = function(pRowId, pObjectType)
         return true;
 }
 
+/**
+ * Sets the code of the given Task to the current max-code + 1
+ */
+TaskUtils.setCode = function(pTaskId)
+{
+    var max = db.cell("select max(CODE) from TASK");
+    db.updateData("TASK", ["CODE"], null, [parseInt(max)+1], SqlCondition.equals("TASK.TASKID", pTaskId, "1=2"));
+}
+
+TaskUtils.getTypeGroup = function(pType)
+{
+    return KeywordUtils.getAttributeRelation(pType, $KeywordRegistry.taskType(), "group", "Task");
+}
+
 /**
  * add the links to the link-table in new mode
  * 
diff --git a/process/Keyword_lib/process.js b/process/Keyword_lib/process.js
index 12e4083b349d6f5aa5d14f18eacf803987962141..88d943523396453ebaace8795750b53e09932c71 100644
--- a/process/Keyword_lib/process.js
+++ b/process/Keyword_lib/process.js
@@ -1,3 +1,4 @@
+import("KeywordRegistry_basic");
 import("KeywordData_lib");
 import("system.vars");
 import("system.SQLTYPES");
@@ -76,6 +77,25 @@ KeywordUtils.getAttributeRelationsByKey = function(pKeyId, pContainerName)
         return data[pKeyId];
 };
 
+/**
+ * return a specific attribute. Only call if you need only one. If you need more than one use getAttributeRelationsByKey()
+ * 
+ * @param {String} pKeyId the key of an element within a containerName - this is the value that is stored in the reference-table (e.g. "DE")
+ * @param {String} pContainerName specifies the type of the keyword and therefore the list elements;
+ *                                  e.g. "COUNTRY"; use an entry of the $KeywordRegistry here
+ * @param {String} pAttrName The Attribute name you need
+ * @param {String} [pDefault=null] the default value, if the attribute doesn't exist. If not specified, null will be used.
+ * 
+ * @return {Object} the value or pDefault
+ */
+KeywordUtils.getAttributeRelation = function(pKeyId, pContainerName, pAttrName, pDefault)
+{
+    var attributes = KeywordUtils.getAttributeRelationsByKey(pKeyId, pContainerName);
+    if (attributes && attributes[pAttrName])
+        return attributes[pAttrName];
+    return pDefault ? pDefault : null;
+};
+
 /**
 * provides a distinctive list of all keyword-container-names in the system
 * 
diff --git a/process/Task_lib/Task_lib.aod b/process/Task_lib/Task_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..30e91db22cac5800fd5de0258da1399453f9deea
--- /dev/null
+++ b/process/Task_lib/Task_lib.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>Task_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/Task_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/Task_lib/process.js b/process/Task_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..f1d04087af5c0f86f5eeafd4c837f2219ac2ee55
--- /dev/null
+++ b/process/Task_lib/process.js
@@ -0,0 +1,56 @@
+import("system.vars");
+import("Keyword_lib")
+import("KeywordRegistry_basic")
+/**
+ * Methods to manage entities, which show different Fields and / or different modules based on a Type.
+ * 
+ * DO NOT USE THIS, IF YOU NEED DIFFERENT LOGIK IN (STATE, MANDATORY, ...-)PROCESSES!
+ * IF YOU HAVE THIS CASE, IT IS MUCH CLEANER TO CREATE A SEPERATE ENTITY AND CONTEXT WHICH USES THE SAME DATASOURCE!!!
+ * 
+ * @class
+ */
+function MultiEntityUtils(pType) {
+    this._loadTypeInfo(pType);
+    this.fieldVar = "$" + vars.getString("$this.name");
+    this.fieldName = fieldVar.split(".")[1];
+}
+
+/**
+ * 
+ */
+MultiEntityUtils.prototype._loadTypeInfo = function(pType)
+{
+    if (this._typeData != undefined)
+    {
+        return this._typeData;
+    }
+    
+    if (KeywordUtils.exists(pType, $KeywordRegistry.taskType()))
+    {
+        var attributes = KeywordUtils.getAttributeRelationsByKey(pType, $KeywordRegistry.taskType());
+        if (attributes != null && attributes.fields)
+        {
+            // read json
+            attributes.fields = JSON.parse(attributes.fields)
+            this._typeData = attributes;
+        }
+    }
+    
+    return vars.getString("$sys.currentcontextname");
+}
+
+MultiEntityUtils.prototype.getFieldCustomProp = function(pPropName, pDefault) {
+    if (this._typeData.fields[this.fieldName] && this._typeData.fields[this.fieldName][pPropName]) {
+        return this._typeData.fields[this.fieldName][pPropName];
+    }
+    
+    return pDefault;
+}
+
+MultiEntityUtils.prototype.getMandatory = function(pDefault) {
+    return this.getFieldCustomProp("mandatory", pDefault);
+}
+
+MultiEntityUtils.prototype.getState = function(pDefault) {
+    return this.getFieldCustomProp("state", pDefault);
+}
\ No newline at end of file