From 4a2b3a4c41a64c748be70dd86b12911d775c2009 Mon Sep 17 00:00:00 2001
From: "S.Listl" <S.Listl@SLISTL.aditosoftware.local>
Date: Thu, 4 Apr 2019 11:56:39 +0200
Subject: [PATCH] Employee preset email, roles added

---
 .../entityfields/role/possibleItemsProcess.js | 14 ++--
 entity/Employee_entity/Employee_entity.aod    | 48 ++++-------
 .../objectrowid_param/valueProcess.js         |  2 +-
 .../objectrowid_param/valueProcess.js         |  2 +-
 .../assignmentrowid_param/valueProcess.js     |  2 +-
 .../email_address/onValidation.js             | 10 +++
 .../email_address/possibleItemsProcess.js     | 30 +++++++
 .../email_address/valueProcess.js             | 17 ++++
 .../entityfields/firstname/valueProcess.js    |  4 +-
 .../entityfields/isactive/valueProcess.js     |  2 +-
 .../entityfields/lastname/valueProcess.js     |  4 +-
 .../base64string_param/valueProcess.js        |  4 -
 .../children/username_param/valueProcess.js   |  4 -
 .../{uid => title}/onValidation.js            |  4 +-
 .../entityfields/title/valueProcess.js        |  7 ++
 .../entityfields/uid/valueProcess.js          |  7 ++
 .../recordcontainers/jdito/contentProcess.js  |  5 +-
 .../recordcontainers/jdito/onDelete.js        |  4 +-
 .../recordcontainers/jdito/onInsert.js        |  3 +-
 .../recordcontainers/jdito/onUpdate.js        |  5 +-
 .../StoredSelection_entity.aod                | 59 -------------
 .../recordcontainers/jdito/contentProcess.js  | 28 -------
 .../recordcontainers/jdito/onDelete.js        | 29 -------
 .../_____LANGUAGE_EXTRA.aod                   | 30 +++++++
 .../_____LANGUAGE_de/_____LANGUAGE_de.aod     | 41 +++++++++
 .../_____LANGUAGE_en/_____LANGUAGE_en.aod     | 30 +++++++
 .../StoredSelection/StoredSelection.aod       | 12 ---
 .../EmployeeEdit_view/EmployeeEdit_view.aod   | 12 +--
 .../EmployeeFilter_view.aod                   |  2 +-
 .../EmployeeMain_view/EmployeeMain_view.aod   |  5 --
 .../EmployeePreview_view.aod                  |  2 +-
 .../StoredSelectionFilter_view.aod            | 27 ------
 process/Employee_lib/process.js               | 83 +++++++++++++++++++
 .../PROJECT_Administrator.aod                 |  6 ++
 role/PROJECT_Everyone/PROJECT_Everyone.aod    |  6 ++
 .../PROJECT_FieldStaff/PROJECT_FieldStaff.aod |  6 ++
 .../PROJECT_HumanResources.aod                |  6 ++
 role/PROJECT_Marketing/PROJECT_Marketing.aod  |  6 ++
 .../PROJECT_OfficeStaff.aod                   |  6 ++
 role/PROJECT_Project/PROJECT_Project.aod      |  6 ++
 .../PROJECT_ProjectManagement.aod             |  6 ++
 role/PROJECT_Resource/PROJECT_Resource.aod    |  6 ++
 role/PROJECT_Service/PROJECT_Service.aod      |  6 ++
 role/PROJECT_Support/PROJECT_Support.aod      |  6 ++
 44 files changed, 376 insertions(+), 228 deletions(-)
 create mode 100644 entity/Employee_entity/entityfields/email_address/onValidation.js
 create mode 100644 entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js
 create mode 100644 entity/Employee_entity/entityfields/email_address/valueProcess.js
 delete mode 100644 entity/Employee_entity/entityfields/storedselections/children/base64string_param/valueProcess.js
 delete mode 100644 entity/Employee_entity/entityfields/storedselections/children/username_param/valueProcess.js
 rename entity/Employee_entity/entityfields/{uid => title}/onValidation.js (69%)
 create mode 100644 entity/Employee_entity/entityfields/title/valueProcess.js
 create mode 100644 entity/Employee_entity/entityfields/uid/valueProcess.js
 delete mode 100644 entity/StoredSelection_entity/StoredSelection_entity.aod
 delete mode 100644 entity/StoredSelection_entity/recordcontainers/jdito/contentProcess.js
 delete mode 100644 entity/StoredSelection_entity/recordcontainers/jdito/onDelete.js
 delete mode 100644 neonContext/StoredSelection/StoredSelection.aod
 delete mode 100644 neonView/StoredSelectionFilter_view/StoredSelectionFilter_view.aod
 create mode 100644 role/PROJECT_Administrator/PROJECT_Administrator.aod
 create mode 100644 role/PROJECT_Everyone/PROJECT_Everyone.aod
 create mode 100644 role/PROJECT_FieldStaff/PROJECT_FieldStaff.aod
 create mode 100644 role/PROJECT_HumanResources/PROJECT_HumanResources.aod
 create mode 100644 role/PROJECT_Marketing/PROJECT_Marketing.aod
 create mode 100644 role/PROJECT_OfficeStaff/PROJECT_OfficeStaff.aod
 create mode 100644 role/PROJECT_Project/PROJECT_Project.aod
 create mode 100644 role/PROJECT_ProjectManagement/PROJECT_ProjectManagement.aod
 create mode 100644 role/PROJECT_Resource/PROJECT_Resource.aod
 create mode 100644 role/PROJECT_Service/PROJECT_Service.aod
 create mode 100644 role/PROJECT_Support/PROJECT_Support.aod

diff --git a/entity/EmployeeRole_entity/entityfields/role/possibleItemsProcess.js b/entity/EmployeeRole_entity/entityfields/role/possibleItemsProcess.js
index 6c9d51db744..e52145c8011 100644
--- a/entity/EmployeeRole_entity/entityfields/role/possibleItemsProcess.js
+++ b/entity/EmployeeRole_entity/entityfields/role/possibleItemsProcess.js
@@ -1,7 +1,9 @@
+import("system.translate");
 import("system.vars");
 import("system.result");
 import("system.tools");
 
+var selectedRole = vars.get("$field.ROLE");
 var roles = [];
 var allRoles = tools.getAllRoles([tools.ROLE_INTERNAL, tools.ROLE_PROJECT, tools.ROLE_XMPP]);
 var excludeRoles = {
@@ -11,13 +13,15 @@ var excludeRoles = {
     "INTERNAL_TECHNICAL" : true
 };
 
-var userRoles = tools.getRoles(vars.get("$param.UserTitle_param"));
-for (let i in userRoles)
-    if (vars.get("$field.ROLE") != userRoles[i])
+if (tools.existUsers(vars.get("$param.UserTitle_param")))
+{
+    var userRoles = tools.getRoles(vars.get("$param.UserTitle_param"));
+    for (let i in userRoles)
         excludeRoles[userRoles[i]] = true;
+}
 
 for (let roleId in allRoles)
-    if (!excludeRoles[roleId])
-        roles.push([roleId, allRoles[roleId][0]]);
+    if (!excludeRoles[roleId] || roleId == selectedRole)
+        roles.push([roleId, translate.text(allRoles[roleId][0])]);
 
 result.object(roles);
\ No newline at end of file
diff --git a/entity/Employee_entity/Employee_entity.aod b/entity/Employee_entity/Employee_entity.aod
index c4d400c893a..c1a5ae6a1ca 100644
--- a/entity/Employee_entity/Employee_entity.aod
+++ b/entity/Employee_entity/Employee_entity.aod
@@ -15,14 +15,15 @@
     </entityProvider>
     <entityField>
       <name>UID</name>
-      <title>Username</title>
-      <mandatory v="true" />
-      <onValidation>%aditoprj%/entity/Employee_entity/entityfields/uid/onValidation.js</onValidation>
+      <searchable v="false" />
+      <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/uid/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
-      <name>TITLE_ORIGINAL</name>
-      <description>the original username, this is required to update the correct user when the username is changed</description>
-      <searchable v="false" />
+      <name>TITLE</name>
+      <title>Username</title>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/title/valueProcess.js</valueProcess>
+      <onValidation>%aditoprj%/entity/Employee_entity/entityfields/title/onValidation.js</onValidation>
     </entityField>
     <entityField>
       <name>CONTACT_ID</name>
@@ -40,6 +41,7 @@
     <entityField>
       <name>LASTNAME</name>
       <title>Lastname</title>
+      <mandatory v="false" />
       <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/lastname/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
@@ -53,6 +55,10 @@
       <name>EMAIL_ADDRESS</name>
       <title>Email</title>
       <mandatory v="true" />
+      <possibleItemsProcess>%aditoprj%/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js</possibleItemsProcess>
+      <newItemsAllowed v="true" />
+      <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/email_address/valueProcess.js</valueProcess>
+      <onValidation>%aditoprj%/entity/Employee_entity/entityfields/email_address/onValidation.js</onValidation>
     </entityField>
     <entityField>
       <name>PASSWORD</name>
@@ -210,30 +216,6 @@
         </entityParameter>
       </children>
     </entityConsumer>
-    <entityConsumer>
-      <name>StoredSelections</name>
-      <title>Stored selections</title>
-      <fieldType>DEPENDENCY_OUT</fieldType>
-      <dependency>
-        <name>dependency</name>
-        <entityName>StoredSelection_entity</entityName>
-        <fieldName>StoredSelections</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>Base64String_param</name>
-          <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/storedselections/children/base64string_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>UserName_param</name>
-          <valueProcess>%aditoprj%/entity/Employee_entity/entityfields/storedselections/children/username_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>STORED_SELECTIONS</name>
-      <searchable v="false" />
-    </entityField>
     <entityProvider>
       <name>Employees</name>
       <fieldType>DEPENDENCY_IN</fieldType>
@@ -259,6 +241,10 @@
         </entityParameter>
       </children>
     </entityProvider>
+    <entityField>
+      <name>TITLE_ORIGINAL</name>
+      <searchable v="false" />
+    </entityField>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
@@ -270,11 +256,13 @@
       <onDelete>%aditoprj%/entity/Employee_entity/recordcontainers/jdito/onDelete.js</onDelete>
       <recordFields>
         <element>UID.value</element>
+        <element>TITLE.value</element>
         <element>TITLE_ORIGINAL.value</element>
         <element>ISACTIVE.value</element>
         <element>FIRSTNAME.value</element>
         <element>LASTNAME.value</element>
         <element>EMAIL_ADDRESS.value</element>
+        <element>EMAIL_ADDRESS.displayValue</element>
         <element>DESCRIPTION.value</element>
         <element>CONTACT_ID.value</element>
         <element>CONTACT_ID.displayValue</element>
diff --git a/entity/Employee_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js b/entity/Employee_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js
index ef0d5bcac51..16c85500b53 100644
--- a/entity/Employee_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js
+++ b/entity/Employee_entity/entityfields/attributes/children/objectrowid_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.CONTACT_ID"));
\ No newline at end of file
+result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js b/entity/Employee_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js
index ef0d5bcac51..16c85500b53 100644
--- a/entity/Employee_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js
+++ b/entity/Employee_entity/entityfields/attributetree/children/objectrowid_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.CONTACT_ID"));
\ No newline at end of file
+result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/documents/children/assignmentrowid_param/valueProcess.js b/entity/Employee_entity/entityfields/documents/children/assignmentrowid_param/valueProcess.js
index ef0d5bcac51..16c85500b53 100644
--- a/entity/Employee_entity/entityfields/documents/children/assignmentrowid_param/valueProcess.js
+++ b/entity/Employee_entity/entityfields/documents/children/assignmentrowid_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.CONTACT_ID"));
\ No newline at end of file
+result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/email_address/onValidation.js b/entity/Employee_entity/entityfields/email_address/onValidation.js
new file mode 100644
index 00000000000..f6a829134cf
--- /dev/null
+++ b/entity/Employee_entity/entityfields/email_address/onValidation.js
@@ -0,0 +1,10 @@
+import("system.translate");
+import("system.neon");
+import("system.result");
+import("system.vars");
+import("system.tools");
+import("Entity_lib");
+
+var email = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.EMAIL_ADDRESS"));
+if (email != "" && tools.getUsersByAttribute(tools.EMAIL, [email]).length)
+        result.string(translate.text("Email must be unique!"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js b/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js
new file mode 100644
index 00000000000..a171cd824ec
--- /dev/null
+++ b/entity/Employee_entity/entityfields/email_address/possibleItemsProcess.js
@@ -0,0 +1,30 @@
+import("Communication_lib");
+import("system.neon");
+import("system.vars");
+import("system.db");
+import("system.result");
+import("Sql_lib");
+
+var contactId = vars.get("$field.CONTACT_ID");
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+    && contactId)
+{
+    var sql = SqlCondition.begin()
+        .andPrepare("COMMUNICATION.CONTACT_ID", contactId)
+        .and("COMMUNICATION.MEDIUM_ID in ('" + CommUtil.getMediumIdsByCategory("EMAIL").join("', '") + "')")
+        .buildSql("select ADDR, ADDR from COMMUNICATION");
+    
+    var addresses = db.table(sql);
+    
+    //include the currently set email address
+    var currentAddress = vars.get("$field.EMAIL_ADDRESS");
+    if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT && currentAddress
+        && !addresses.some(function (row) {return row[0] == currentAddress;}))
+    {
+        addresses.push([currentAddress, currentAddress]);
+    }   
+            
+    result.object(addresses);
+}
+else
+    result.object([])
diff --git a/entity/Employee_entity/entityfields/email_address/valueProcess.js b/entity/Employee_entity/entityfields/email_address/valueProcess.js
new file mode 100644
index 00000000000..7931dce1d63
--- /dev/null
+++ b/entity/Employee_entity/entityfields/email_address/valueProcess.js
@@ -0,0 +1,17 @@
+import("system.result");
+import("system.db");
+import("system.neon");
+import("system.vars");
+import("Sql_lib");
+import("Communication_lib");
+
+var contactId = vars.get("$field.CONTACT_ID");
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+    && contactId && !vars.get("$field.EMAIL_ADDRESS"))
+{
+    var defaultMail = db.cell(SqlCondition.begin()
+        .andPrepare("CONTACT.CONTACTID", contactId)
+        .buildSql("select (" + CommUtil.getStandardSubSqlMail() + ") from CONTACT")
+    );
+    result.string(defaultMail);
+}
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/firstname/valueProcess.js b/entity/Employee_entity/entityfields/firstname/valueProcess.js
index 310fb8ddc85..f118b02d965 100644
--- a/entity/Employee_entity/entityfields/firstname/valueProcess.js
+++ b/entity/Employee_entity/entityfields/firstname/valueProcess.js
@@ -5,8 +5,8 @@ import("system.vars");
 import("Sql_lib");
 
 var contactId = vars.get("$field.CONTACT_ID");
-if ((vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT)
-    && contactId)
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+    && contactId && !vars.get("$field.FIRSTNAME"))
 {
     var firstname = db.cell(SqlCondition.begin()
         .andPrepare("CONTACT.CONTACTID", contactId)
diff --git a/entity/Employee_entity/entityfields/isactive/valueProcess.js b/entity/Employee_entity/entityfields/isactive/valueProcess.js
index 7993af1a5f4..86ff56f08f7 100644
--- a/entity/Employee_entity/entityfields/isactive/valueProcess.js
+++ b/entity/Employee_entity/entityfields/isactive/valueProcess.js
@@ -2,5 +2,5 @@ import("system.neon");
 import("system.vars");
 import("system.result");
 
-if (vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW)
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
     result.string("true");
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/lastname/valueProcess.js b/entity/Employee_entity/entityfields/lastname/valueProcess.js
index 5913681662c..d0f5d394fa6 100644
--- a/entity/Employee_entity/entityfields/lastname/valueProcess.js
+++ b/entity/Employee_entity/entityfields/lastname/valueProcess.js
@@ -5,8 +5,8 @@ import("system.vars");
 import("Sql_lib");
 
 var contactId = vars.get("$field.CONTACT_ID");
-if ((vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT)
-    && contactId)
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+    && contactId && !vars.get("$field.LASTNAME"))
 {
     var lastname = db.cell(SqlCondition.begin()
         .andPrepare("CONTACT.CONTACTID", contactId)
diff --git a/entity/Employee_entity/entityfields/storedselections/children/base64string_param/valueProcess.js b/entity/Employee_entity/entityfields/storedselections/children/base64string_param/valueProcess.js
deleted file mode 100644
index 8d34e510f8d..00000000000
--- a/entity/Employee_entity/entityfields/storedselections/children/base64string_param/valueProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.STORED_SELECTIONS"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/storedselections/children/username_param/valueProcess.js b/entity/Employee_entity/entityfields/storedselections/children/username_param/valueProcess.js
deleted file mode 100644
index 2c71e53a498..00000000000
--- a/entity/Employee_entity/entityfields/storedselections/children/username_param/valueProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/uid/onValidation.js b/entity/Employee_entity/entityfields/title/onValidation.js
similarity index 69%
rename from entity/Employee_entity/entityfields/uid/onValidation.js
rename to entity/Employee_entity/entityfields/title/onValidation.js
index e6c2cc26a81..b7a2177b025 100644
--- a/entity/Employee_entity/entityfields/uid/onValidation.js
+++ b/entity/Employee_entity/entityfields/title/onValidation.js
@@ -5,7 +5,7 @@ import("system.vars");
 import("system.tools");
 import("Entity_lib");
 
-var title = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.UID"));
-if (!(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT && title == vars.get("$field.TITLE_ORIGINAL")) 
+var title = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.TITLE"));
+if (!(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT && title == vars.get("$field.TITLE_ORIGINAL")) 
     && title != "" && tools.existUsers(title))
         result.string(translate.text("Username already exists!"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/title/valueProcess.js b/entity/Employee_entity/entityfields/title/valueProcess.js
new file mode 100644
index 00000000000..058b37c3c1c
--- /dev/null
+++ b/entity/Employee_entity/entityfields/title/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("Employee_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT && !vars.get("$field.TITLE"))
+    result.string(EmployeeUtils.generateUserName(vars.get("$field.FIRSTNAME"), vars.get("$field.LASTNAME"), "f.l+"));
\ No newline at end of file
diff --git a/entity/Employee_entity/entityfields/uid/valueProcess.js b/entity/Employee_entity/entityfields/uid/valueProcess.js
new file mode 100644
index 00000000000..4e2c2abf86f
--- /dev/null
+++ b/entity/Employee_entity/entityfields/uid/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+if ((vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+    && vars.get("$field.TITLE"))
+        result.string(vars.get("$field.TITLE"));
\ No newline at end of file
diff --git a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
index bd4a9109ac9..f40cbd25c02 100644
--- a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js
@@ -4,6 +4,7 @@ import("system.tools");
 import("Util_lib");
 import("Contact_lib");
 import("JditoFilter_lib");
+import("Employee_lib");
 
 var users;
 if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
@@ -19,12 +20,14 @@ else
 users = users.map(function (user)
 {
     return [
+        user[tools.TITLE],
         user[tools.TITLE],
         user[tools.TITLE],
         user[tools.PARAMS][tools.ISACTIVE],
         user[tools.PARAMS][tools.FIRSTNAME],
         user[tools.PARAMS][tools.LASTNAME],
         user[tools.PARAMS][tools.EMAIL],
+        user[tools.PARAMS][tools.EMAIL],
         user[tools.DESCRIPTION],
         user[tools.PARAMS][tools.CONTACTID],
         ContactUtils.getTitleByContactId(user[tools.PARAMS][tools.CONTACTID]), //TODO: get the names more efficiently
@@ -35,7 +38,7 @@ users = users.map(function (user)
 var filter = vars.exists("$local.filter") && vars.get("$local.filter"); 
 
 //TODO: this is a workaround that filters the records manually, it should be possible to filter the users with a tools.* method
-users = JditoFilterUtils.filterRecords(["UID", "", "ISACTIVE", "FIRSTNAME", "LASTNAME", "EMAIL_ADDRESS", "DESCRIPTION", "CONTACT_ID", "", ], users, filter);
+users = JditoFilterUtils.filterRecords(["UID", "TITLE", "TITLE_ORIGINAL", "ISACTIVE", "FIRSTNAME", "LASTNAME", "EMAIL_ADDRESS", "DESCRIPTION", "CONTACT_ID", ""], users, filter);
 
 
 ArrayUtils.sort2d(users, 0, true, false); //sort by username
diff --git a/entity/Employee_entity/recordcontainers/jdito/onDelete.js b/entity/Employee_entity/recordcontainers/jdito/onDelete.js
index 08459131451..212b6d23132 100644
--- a/entity/Employee_entity/recordcontainers/jdito/onDelete.js
+++ b/entity/Employee_entity/recordcontainers/jdito/onDelete.js
@@ -4,5 +4,5 @@ import("system.tools");
 import("Employee_lib");
 
 //TODO: the current user should not delete himself, put this condition in grantDelete when available
-if (EmployeeUtils.getCurrentUserName() != vars.get("$field.UID"))
-    tools.deleteUser(vars.get("$field.UID"));
\ No newline at end of file
+if (EmployeeUtils.getCurrentUserName() != vars.get("$field.TITLE") && !EmployeeUtils.hasRelations(vars.get("$field.CONTACT_ID")))
+    tools.deleteUser(vars.get("$field.TITLE"));
\ No newline at end of file
diff --git a/entity/Employee_entity/recordcontainers/jdito/onInsert.js b/entity/Employee_entity/recordcontainers/jdito/onInsert.js
index 21f772e8ce2..9d7e0fddbe4 100644
--- a/entity/Employee_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/Employee_entity/recordcontainers/jdito/onInsert.js
@@ -1,6 +1,7 @@
 import("system.neon");
 import("system.vars");
 import("system.tools");
+import("Employee_lib");
 
 var user = {};
 var params = []; //this has to be an array
@@ -12,7 +13,7 @@ params[tools.CONTACTID] = vars.get("$field.CONTACT_ID");
 params[tools.DESCRIPTION] = vars.get("$field.DESCRIPTION");
 params[tools.ISACTIVE] = vars.get("$field.ISACTIVE");
 
-user[tools.TITLE] = vars.get("$field.UID");
+user[tools.TITLE] = vars.get("$field.TITLE");
 user[tools.PARAMS] = params;
 
 if (vars.get("$field.PASSWORD") && vars.get("$field.PASSWORD") == vars.get("$field.CONFIRM_PASSWORD"))
diff --git a/entity/Employee_entity/recordcontainers/jdito/onUpdate.js b/entity/Employee_entity/recordcontainers/jdito/onUpdate.js
index 03a003f2633..6818acfd629 100644
--- a/entity/Employee_entity/recordcontainers/jdito/onUpdate.js
+++ b/entity/Employee_entity/recordcontainers/jdito/onUpdate.js
@@ -18,10 +18,9 @@ FieldChanges.assimilateChangeAndDispose("$field.IMAGE", function (state, value)
         PersUtils.removeImage(personId);
 });
 
-var user = {};
-user[tools.PARAMS] = [];
+var user = tools.getUser(vars.get("$field.TITLE_ORIGINAL"));
 
-user[tools.TITLE] = vars.get("$field.UID");
+user[tools.TITLE] = vars.get("$field.TITLE");
 user[tools.PARAMS][tools.ISACTIVE] = vars.get("$field.ISACTIVE");
 user[tools.PARAMS][tools.FIRSTNAME] = vars.get("$field.FIRSTNAME");
 user[tools.PARAMS][tools.LASTNAME] = vars.get("$field.LASTNAME");
diff --git a/entity/StoredSelection_entity/StoredSelection_entity.aod b/entity/StoredSelection_entity/StoredSelection_entity.aod
deleted file mode 100644
index 59114c2e095..00000000000
--- a/entity/StoredSelection_entity/StoredSelection_entity.aod
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.1">
-  <name>StoredSelection_entity</name>
-  <title>Stored selections</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <recordContainer>jdito</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>UID</name>
-    </entityField>
-    <entityParameter>
-      <name>Base64String_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityProvider>
-      <name>StoredSelections</name>
-      <fieldType>DEPENDENCY_IN</fieldType>
-      <dependencies>
-        <entityDependency>
-          <name>1386345f-0ed8-4c82-b96d-a249775314ee</name>
-          <entityName>Employee_entity</entityName>
-          <fieldName>StoredSelections</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-    </entityProvider>
-    <entityField>
-      <name>CONTEXT_NAME</name>
-      <title>Module</title>
-      <state>READONLY</state>
-    </entityField>
-    <entityField>
-      <name>SELECTION_TITLE</name>
-      <title>Name</title>
-      <state>READONLY</state>
-    </entityField>
-    <entityParameter>
-      <name>UserName_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-  </entityFields>
-  <recordContainers>
-    <jDitoRecordContainer>
-      <name>jdito</name>
-      <contentProcess>%aditoprj%/entity/StoredSelection_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
-      <onDelete>%aditoprj%/entity/StoredSelection_entity/recordcontainers/jdito/onDelete.js</onDelete>
-      <recordFields>
-        <element>UID.value</element>
-        <element>CONTEXT_NAME.value</element>
-        <element>SELECTION_TITLE.value</element>
-      </recordFields>
-    </jDitoRecordContainer>
-  </recordContainers>
-</entity>
diff --git a/entity/StoredSelection_entity/recordcontainers/jdito/contentProcess.js b/entity/StoredSelection_entity/recordcontainers/jdito/contentProcess.js
deleted file mode 100644
index d92a27b39c7..00000000000
--- a/entity/StoredSelection_entity/recordcontainers/jdito/contentProcess.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import("system.result");
-import("system.pack");
-import("system.util");
-import("system.vars");
-
-var records = [];
-if (vars.exists("$param.Base64String_param") && vars.get("$param.Base64String_param"))
-{
-    var codedSelections = pack.gunzip(vars.get("$param.Base64String_param"));
-
-    var selections = new XML(util.decodeBase64String(codedSelections));
-    selections = selections.FRAME;
-    for (let i in selections)
-    {
-        context = selections[i];
-        var contextName = context.NAME;
-        if (contextName)
-        {
-            var title = context.STORE.(ID == "#STORE_SAVED").ELEMENT.TITLE;
-            for (let ii in title)
-            {
-                records.push([(contextName + title[ii]), contextName, title[ii]]);
-            }
-        }
-    }
-}
-
-result.object(records);
\ No newline at end of file
diff --git a/entity/StoredSelection_entity/recordcontainers/jdito/onDelete.js b/entity/StoredSelection_entity/recordcontainers/jdito/onDelete.js
deleted file mode 100644
index cf864004f98..00000000000
--- a/entity/StoredSelection_entity/recordcontainers/jdito/onDelete.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import("system.util");
-import("system.pack");
-import("system.vars");
-import("system.tools");
-import("Employee_lib");
-
-var userName = vars.exists("$param.UserName_param") && vars.get("$param.UserName_param");
-var contextName = vars.get("$field.CONTEXT_NAME");
-var selectionTitle = vars.get("$field.SELECTION_TITLE");
-
-if (vars.exists("$param.Base64String_param") && vars.get("$param.Base64String_param") && user && tools.existUsers(user))
-{
-    var user;
-    if (userName == EmployeeUtils.getCurrentUserName())
-        user = tools.getCurrentUser();
-    else 
-        user = tools.getUser(userName, tools.PROFILE_FULL);
-    
-    var codedSelections = pack.gunzip(vars.get("$param.Base64String_param"));
-    var selections = new XML(util.decodeBase64String(codedSelections));
-    delete selections.FRAME.(NAME == contextName).STORE.(ID == "#STORE_SAVED").ELEMENT.(TITLE == selectionTitle)[0];
-
-    user[tools.PARAMS][tools.FRAME_STOREDSEARCHES] = pack.gzip(util.encodeBase64String(selections.toString()));
-    
-    if (userName == EmployeeUtils.getCurrentUserName()) 
-        tools.updateCurrentUser(user) 
-    else 
-        tools.updateUser(user);
-}
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 6c31d77bfab..73af0d0247c 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -2688,6 +2688,36 @@
     <entry>
       <key>This private person doeas already exist and can not be created once more.</key>
     </entry>
+    <entry>
+      <key>Everyone</key>
+    </entry>
+    <entry>
+      <key>Project</key>
+    </entry>
+    <entry>
+      <key>Human resources</key>
+    </entry>
+    <entry>
+      <key>Project management</key>
+    </entry>
+    <entry>
+      <key>Office staff</key>
+    </entry>
+    <entry>
+      <key>Field staff</key>
+    </entry>
+    <entry>
+      <key>Resource</key>
+    </entry>
+    <entry>
+      <key>Human Resources</key>
+    </entry>
+    <entry>
+      <key>The title already exists!</key>
+    </entry>
+    <entry>
+      <key>Note</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 816ec30255a..3ab2420888c 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -6,14 +6,26 @@
   <country></country>
   <variant></variant>
   <keyValueMap>
+    <entry>
+      <key>Project management</key>
+      <value>Projektmanagement</value>
+    </entry>
     <entry>
       <key>Company</key>
       <value>Firma</value>
     </entry>
+    <entry>
+      <key>Office staff</key>
+      <value>Innendienst</value>
+    </entry>
     <entry>
       <key>Confirm password</key>
       <value>Passwort prüfen</value>
     </entry>
+    <entry>
+      <key>Human Resources</key>
+      <value>Personal</value>
+    </entry>
     <entry>
       <key>Entrydate (Day)</key>
       <value>Eingangsdatum (Tag)</value>
@@ -26,6 +38,10 @@
       <key>Discount %</key>
       <value>Rabatt %</value>
     </entry>
+    <entry>
+      <key>Email must be unique!</key>
+      <value>Die E-Mail-Adresse muss eindeutig sein!</value>
+    </entry>
     <entry>
       <key>E-Mail</key>
       <value>E-Mail</value>
@@ -1067,6 +1083,10 @@
       <key>My Activities</key>
       <value>Meine Aktivitäten</value>
     </entry>
+    <entry>
+      <key>Everyone</key>
+      <value>Jeder</value>
+    </entry>
     <entry>
       <key>Combobox Value</key>
       <value>Combobox-Wert</value>
@@ -1201,6 +1221,10 @@
     <entry>
       <key>ISO 3166-1 alpha-2</key>
     </entry>
+    <entry>
+      <key>Field staff</key>
+      <value>Außendienst</value>
+    </entry>
     <entry>
       <key>0.00</key>
     </entry>
@@ -2506,6 +2530,10 @@
       <key>Christmas Island</key>
       <value>Weihnachtsinsel</value>
     </entry>
+    <entry>
+      <key>Project</key>
+      <value>Projekt</value>
+    </entry>
     <entry>
       <key>Netherlands</key>
       <value>Niederlande</value>
@@ -2602,6 +2630,10 @@
       <key>Congo (Democratic Republic of the)</key>
       <value>Kongo (Demokratische Republik)</value>
     </entry>
+    <entry>
+      <key>Resource</key>
+      <value>Ressource</value>
+    </entry>
     <entry>
       <key>Greece</key>
       <value>Griechenland</value>
@@ -3462,6 +3494,15 @@
       <key>This private person doeas already exist and can not be created once more.</key>
       <value>Diese Privatperson existiert bereits und kann daher nicht noch ein mal angelegt werden.</value>
     </entry>
+    <entry>
+      <key>The title already exists!</key>
+    </entry>
+    <entry>
+      <key>Human resources</key>
+    </entry>
+    <entry>
+      <key>Note</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index c35bab99b66..a7440fd6ab5 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -1038,6 +1038,9 @@
     <entry>
       <key>Seite</key>
     </entry>
+    <entry>
+      <key>Note</key>
+    </entry>
     <entry>
       <key>Senden per E-Mail</key>
     </entry>
@@ -2671,6 +2674,9 @@
       <key>${MIN_MAX_ERROR} field: %0, value: %1, min: %2, max: %3</key>
       <value>%0 has to be between %2 and %3.</value>
     </entry>
+    <entry>
+      <key>The title already exists!</key>
+    </entry>
     <entry>
       <key>Password</key>
     </entry>
@@ -2718,6 +2724,30 @@
     <entry>
       <key>This private person doeas already exist and can not be created once more.</key>
     </entry>
+    <entry>
+      <key>Everyone</key>
+    </entry>
+    <entry>
+      <key>Project</key>
+    </entry>
+    <entry>
+      <key>Human resources</key>
+    </entry>
+    <entry>
+      <key>Project management</key>
+    </entry>
+    <entry>
+      <key>Office staff</key>
+    </entry>
+    <entry>
+      <key>Field staff</key>
+    </entry>
+    <entry>
+      <key>Resource</key>
+    </entry>
+    <entry>
+      <key>Human Resources</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/StoredSelection/StoredSelection.aod b/neonContext/StoredSelection/StoredSelection.aod
deleted file mode 100644
index b758aed2aa3..00000000000
--- a/neonContext/StoredSelection/StoredSelection.aod
+++ /dev/null
@@ -1,12 +0,0 @@
-<?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>StoredSelection</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <entity>StoredSelection_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>8ab7727b-5dc7-47bb-9034-079d84ede3a3</name>
-      <view>StoredSelectionFilter_view</view>
-    </neonViewReference>
-  </references>
-</neonContext>
diff --git a/neonView/EmployeeEdit_view/EmployeeEdit_view.aod b/neonView/EmployeeEdit_view/EmployeeEdit_view.aod
index 9d89615fa4e..71614eff593 100644
--- a/neonView/EmployeeEdit_view/EmployeeEdit_view.aod
+++ b/neonView/EmployeeEdit_view/EmployeeEdit_view.aod
@@ -14,17 +14,13 @@
       <entityField>#ENTITY</entityField>
       <fields>
         <entityFieldLink>
-          <name>fdd5320e-a8c0-4043-a88e-aeba1ca02cd1</name>
-          <entityField>UID</entityField>
+          <name>1925ef51-54a8-41e2-aa78-6d95d1ee4b99</name>
+          <entityField>CONTACT_ID</entityField>
         </entityFieldLink>
         <entityFieldLink>
           <name>9170856b-45c2-4d8a-864d-4db36bfe4a8c</name>
           <entityField>ISACTIVE</entityField>
         </entityFieldLink>
-        <entityFieldLink>
-          <name>1925ef51-54a8-41e2-aa78-6d95d1ee4b99</name>
-          <entityField>CONTACT_ID</entityField>
-        </entityFieldLink>
         <entityFieldLink>
           <name>7d36467f-8b79-4647-b8e5-5759bdbf37a7</name>
           <entityField>FIRSTNAME</entityField>
@@ -33,6 +29,10 @@
           <name>00a2dedb-67f5-4662-b053-bf841b30e365</name>
           <entityField>LASTNAME</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>9c030b62-bf17-4be1-bcc6-87b304a618c0</name>
+          <entityField>TITLE</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>6155e6b7-ee2c-45b4-87f5-9e506ffc5775</name>
           <entityField>EMAIL_ADDRESS</entityField>
diff --git a/neonView/EmployeeFilter_view/EmployeeFilter_view.aod b/neonView/EmployeeFilter_view/EmployeeFilter_view.aod
index a11de42475c..88171ca8fcb 100644
--- a/neonView/EmployeeFilter_view/EmployeeFilter_view.aod
+++ b/neonView/EmployeeFilter_view/EmployeeFilter_view.aod
@@ -19,7 +19,7 @@
         </neonTableColumn>
         <neonTableColumn>
           <name>3e3552f9-9591-45ae-a0bb-a85210c2b382</name>
-          <entityField>UID</entityField>
+          <entityField>TITLE</entityField>
         </neonTableColumn>
         <neonTableColumn>
           <name>307dfdad-a0b2-436f-b8a1-9825821dba0c</name>
diff --git a/neonView/EmployeeMain_view/EmployeeMain_view.aod b/neonView/EmployeeMain_view/EmployeeMain_view.aod
index ce9851ad9ae..1cbb84296df 100644
--- a/neonView/EmployeeMain_view/EmployeeMain_view.aod
+++ b/neonView/EmployeeMain_view/EmployeeMain_view.aod
@@ -34,10 +34,5 @@
       <entityField>Documents</entityField>
       <view>DocumentFilter_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>aaca4c8c-7953-43d8-9390-53b78d86863a</name>
-      <entityField>StoredSelections</entityField>
-      <view>StoredSelectionFilter_view</view>
-    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/EmployeePreview_view/EmployeePreview_view.aod b/neonView/EmployeePreview_view/EmployeePreview_view.aod
index cbad6667101..198c613625f 100644
--- a/neonView/EmployeePreview_view/EmployeePreview_view.aod
+++ b/neonView/EmployeePreview_view/EmployeePreview_view.aod
@@ -12,7 +12,7 @@
       <name>Header</name>
       <iconField>IMAGE</iconField>
       <titleField>NAME_fieldGroup</titleField>
-      <subtitleField>UID</subtitleField>
+      <subtitleField>TITLE</subtitleField>
       <entityField>#ENTITY</entityField>
     </cardViewTemplate>
     <genericViewTemplate>
diff --git a/neonView/StoredSelectionFilter_view/StoredSelectionFilter_view.aod b/neonView/StoredSelectionFilter_view/StoredSelectionFilter_view.aod
deleted file mode 100644
index 9974513f1b5..00000000000
--- a/neonView/StoredSelectionFilter_view/StoredSelectionFilter_view.aod
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>StoredSelectionFilter_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <tableViewTemplate>
-      <name>Table</name>
-      <isEditable v="false" />
-      <entityField>#ENTITY</entityField>
-      <columns>
-        <neonTableColumn>
-          <name>713574de-2d9c-4006-93a3-3860fb145c26</name>
-          <entityField>CONTEXT_NAME</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>4cc4d5ff-24cf-46d9-9941-cda11e445a17</name>
-          <entityField>SELECTION_TITLE</entityField>
-        </neonTableColumn>
-      </columns>
-    </tableViewTemplate>
-  </children>
-</neonView>
diff --git a/process/Employee_lib/process.js b/process/Employee_lib/process.js
index ef3273b4955..99e49048679 100644
--- a/process/Employee_lib/process.js
+++ b/process/Employee_lib/process.js
@@ -1,3 +1,6 @@
+import("system.logging");
+import("system.db");
+import("Sql_lib");
 import("system.tools");
 
 /**
@@ -29,4 +32,84 @@ EmployeeUtils.getCurrentUserName = function ()
 {
     var user = tools.getCurrentUser();
     return user ? user[tools.TITLE] : null;
+}
+
+EmployeeUtils.sliceUserId = function (pUserId)
+{
+    return pUserId.substr(10, 36);
+}
+
+/**
+ * generates a username from the firstname and lastname with the given structure
+ * 
+ * @param {String} pFirstName
+ * @param {String} pLastName
+ * @param {String} pStructure the structure of the username, special characters:
+ *      f - one letter of the firstname in lowercase
+ *      F - one letter of the firstname in uppsercase
+ *      l - one letter of the lastname in lowercase
+ *      L - one letter of the lastname in uppsercase
+ *      f+ - the complete firstname in lowercase
+ *      F+ - the complete firstname
+ *      l+ - the complete lastname in lowercae
+ *      L+ - the complete lastname 
+ * 
+ * @return {String} the generated username
+ */
+EmployeeUtils.generateUserName = function (pFirstName, pLastName, pStructure)
+{
+    if (!pStructure || (!pFirstName && !pLastName))
+        return null;
+    
+    var firstNameIndex = 0;
+    var lastNameIndex = 0;
+    var userName = pStructure.replace(/(f\+|l\+|f|l)/ig, function (type)
+    {
+        switch (type)
+        {
+            case "f+":
+            return pFirstName.toLowerCase() || "";
+            case "F+":
+                return pFirstName || "";
+            case "l+":
+                return pLastName.toLowerCase()  || "";
+            case "L+":
+                return pLastName || "";
+            case "f":
+                return pFirstName.charAt(firstNameIndex++).toLowerCase() || "";
+            case "F":
+                return pFirstName.charAt(firstNameIndex++).toUpperCase() || "";
+            case "l":
+                return pLastName.charAt(lastNameIndex++).toLowerCase() || "";
+            case "L":
+                return pLastName.charAt(lastNameIndex++).toUpperCase() || "";
+        }
+    });
+    
+    return userName;
+}
+
+/**
+ * checks if an employee is used somewhere
+ * 
+ * @param {String} pContactId the contact id of the user
+ * 
+ * @return {boolean} if the employee has relations
+ */
+EmployeeUtils.hasRelations = function (pContactId)
+{
+    //sql queries with selects on tables where an employee can be used
+    var queries = [
+        SqlCondition.begin()
+            .andPrepare("ACTIVITY.CREATOR", pContactId)
+            .buildSql("select 1 from ACTIVITY"),
+        SqlCondition.begin()
+            .andPrepare("TIMETRACKING.CONTACT_ID", pContactId)
+            .buildSql("select 1 from TIMETRACKING")
+    ];
+    logging.log(queries.toSource())
+    return queries.some(function (sql)
+        {
+            return db.cell(sql) != "";
+        });
 }
\ No newline at end of file
diff --git a/role/PROJECT_Administrator/PROJECT_Administrator.aod b/role/PROJECT_Administrator/PROJECT_Administrator.aod
new file mode 100644
index 00000000000..49266936de0
--- /dev/null
+++ b/role/PROJECT_Administrator/PROJECT_Administrator.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Administrator</name>
+  <title>Administrator</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_Everyone/PROJECT_Everyone.aod b/role/PROJECT_Everyone/PROJECT_Everyone.aod
new file mode 100644
index 00000000000..f14d5573e86
--- /dev/null
+++ b/role/PROJECT_Everyone/PROJECT_Everyone.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Everyone</name>
+  <title>Everyone</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_FieldStaff/PROJECT_FieldStaff.aod b/role/PROJECT_FieldStaff/PROJECT_FieldStaff.aod
new file mode 100644
index 00000000000..5dafdb429b0
--- /dev/null
+++ b/role/PROJECT_FieldStaff/PROJECT_FieldStaff.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_FieldStaff</name>
+  <title>Field staff</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_HumanResources/PROJECT_HumanResources.aod b/role/PROJECT_HumanResources/PROJECT_HumanResources.aod
new file mode 100644
index 00000000000..3f8a7fd6594
--- /dev/null
+++ b/role/PROJECT_HumanResources/PROJECT_HumanResources.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_HumanResources</name>
+  <title>Human Resources</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_Marketing/PROJECT_Marketing.aod b/role/PROJECT_Marketing/PROJECT_Marketing.aod
new file mode 100644
index 00000000000..f28c9ae8f67
--- /dev/null
+++ b/role/PROJECT_Marketing/PROJECT_Marketing.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Marketing</name>
+  <title>Marketing</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_OfficeStaff/PROJECT_OfficeStaff.aod b/role/PROJECT_OfficeStaff/PROJECT_OfficeStaff.aod
new file mode 100644
index 00000000000..9b70512446b
--- /dev/null
+++ b/role/PROJECT_OfficeStaff/PROJECT_OfficeStaff.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_OfficeStaff</name>
+  <title>Office staff</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_Project/PROJECT_Project.aod b/role/PROJECT_Project/PROJECT_Project.aod
new file mode 100644
index 00000000000..ecc4f7aae41
--- /dev/null
+++ b/role/PROJECT_Project/PROJECT_Project.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Project</name>
+  <title>Project</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_ProjectManagement/PROJECT_ProjectManagement.aod b/role/PROJECT_ProjectManagement/PROJECT_ProjectManagement.aod
new file mode 100644
index 00000000000..8016375c8be
--- /dev/null
+++ b/role/PROJECT_ProjectManagement/PROJECT_ProjectManagement.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_ProjectManagement</name>
+  <title>Project Management</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_Resource/PROJECT_Resource.aod b/role/PROJECT_Resource/PROJECT_Resource.aod
new file mode 100644
index 00000000000..e6904e26c26
--- /dev/null
+++ b/role/PROJECT_Resource/PROJECT_Resource.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Resource</name>
+  <title>Resource</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_Service/PROJECT_Service.aod b/role/PROJECT_Service/PROJECT_Service.aod
new file mode 100644
index 00000000000..7d586ddd20c
--- /dev/null
+++ b/role/PROJECT_Service/PROJECT_Service.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Service</name>
+  <title>Service</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
diff --git a/role/PROJECT_Support/PROJECT_Support.aod b/role/PROJECT_Support/PROJECT_Support.aod
new file mode 100644
index 00000000000..39c78787682
--- /dev/null
+++ b/role/PROJECT_Support/PROJECT_Support.aod
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<role xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/role/1.2.0">
+  <name>PROJECT_Support</name>
+  <title>Support</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</role>
-- 
GitLab