diff --git a/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod b/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod
index 7d0ae33708ceeb3ebe7cb1d2abfba943e2ab862b..9e9a4d6125d879ef8fdae6a6a34b2549ab017f47 100644
--- a/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod
+++ b/application/_____SYSTEM_APPLICATION/_____SYSTEM_APPLICATION.aod
@@ -1,17 +1,10 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<application xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/application/1.1.8">
-  <name>_____SYSTEM_APPLICATION</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <entityNode name="_____SYSTEM_COMPANY" kind="200">
-    <node name="Group" kind="123" title="">
-      <node name="Group2" kind="123" title="">
-        <node name="Util_lib" kind="103" />
-        <node name="INTERNAL_ADMINISTRATOR" kind="159" />
-      </node>
-    </node>
-  </entityNode>
-  <company>
-    <name>company</name>
-    <backgroundColor v="0xff83cbd8" />
-  </company>
-</application>
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/application/1.1.8">
+  <name>_____SYSTEM_APPLICATION</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <entityNode name="_____SYSTEM_COMPANY" kind="200" />
+  <company>
+    <name>company</name>
+    <backgroundColor v="0xff83cbd8" />
+  </company>
+</application>
diff --git a/entity/AttributeRelation_entity/AttributeRelation_entity.aod b/entity/AttributeRelation_entity/AttributeRelation_entity.aod
index c13c98c8e85d98a9ec58064b1ce447edbd77fca9..e014c096bd5a961e40db0b8f38e6fd74e664adaf 100644
--- a/entity/AttributeRelation_entity/AttributeRelation_entity.aod
+++ b/entity/AttributeRelation_entity/AttributeRelation_entity.aod
@@ -59,6 +59,12 @@
           <fieldName>AttributeChildren</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>ba8046ba-f58c-48f1-9c35-fe897247534a</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>Attributes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
       <children>
         <entityParameter>
diff --git a/entity/Attribute_entity/Attribute_entity.aod b/entity/Attribute_entity/Attribute_entity.aod
index 3032d15a7f9cfa12ed50a252ae4551ceadb4e0da..19200a77d9fa5e23d745fab789b98709c7f8c658 100644
--- a/entity/Attribute_entity/Attribute_entity.aod
+++ b/entity/Attribute_entity/Attribute_entity.aod
@@ -23,6 +23,7 @@
       <title>Type</title>
       <consumer>KeywordAttributeType</consumer>
       <mandatory v="true" />
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Attribute_entity/entityfields/attribute_type/displayValueProcess.js</displayValueProcess>
     </entityField>
diff --git a/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js b/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b768fb2fba7336e45a6e5c99d6224d9e623d4e5b
--- /dev/null
+++ b/entity/Attribute_entity/entityfields/attribute_type/stateProcess.js
@@ -0,0 +1,12 @@
+import("system.db");
+import("system.neon");
+import("system.result");
+import("system.vars");
+import("Attribute_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$field.ATTRIBUTE_PARENT_ID") != "")
+{
+    var type = AttributeHandler.begin(vars.get("$field.ATTRIBUTE_PARENT_ID")).getAttributeType();
+    if (type == $AttributeTypes.COMBO)
+        result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
\ No newline at end of file
diff --git a/entity/Attribute_entity/recordcontainers/db/conditionProcess.js b/entity/Attribute_entity/recordcontainers/db/conditionProcess.js
index 1a5a7ef8aa7f0828ba0791f1ea8a2acd3e99f354..bdd0ea7449ed0bd35470a8ac8dffb388034951c6 100644
--- a/entity/Attribute_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Attribute_entity/recordcontainers/db/conditionProcess.js
@@ -7,24 +7,8 @@ import("Attribute_lib");
 var condition = "AB_ATTRIBUTE.ATTRIBUTE_TYPE = '" + $AttributeTypes.GROUP + "'";
 
 if (vars.exists("$param.attrParentId_param") && vars.get("$param.attrParentId_param"))
-    condition = "AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + getAllChildren(vars.getString("$param.attrParentId_param")).join("','") + "')";
+    condition = "AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + AttributeUtil.getAllChildren(vars.getString("$param.attrParentId_param")).join("','") + "')";
 else if (vars.get("$param.attrParentId_param") !== "")
     condition = "";
 
 result.string(condition);
-
-function getAllChildren (pAttributeId)
-{
-    var childIds = [];
-    var attributes= [pAttributeId];
-    while (attributes.length > 0)
-    {
-        attributes = db.array(db.COLUMN, SqlCondition.begin()
-            .and("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID in ('" + attributes.join("','") + "')")
-            .buildSql("select AB_ATTRIBUTEID from AB_ATTRIBUTE")
-        );
-        if (attributes.length > 0)
-            childIds = childIds.concat(attributes);
-    }
-    return childIds;
-}
diff --git a/entity/Attribute_entity/recordcontainers/db/onDBDelete.js b/entity/Attribute_entity/recordcontainers/db/onDBDelete.js
index 504e2d5e4f82c9ccbdeb7b380f546003c3f5f9a8..7d1eb8b477436101b8cacb2fa7aa00241708adae 100644
--- a/entity/Attribute_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Attribute_entity/recordcontainers/db/onDBDelete.js
@@ -1,11 +1,29 @@
 import("system.vars");
 import("system.db");
 import("Sql_lib");
+import("Attribute_lib");
 
 var attributeId = vars.get("$field.AB_ATTRIBUTEID");
-var usageCondition = SqlCondition.begin()
-    .andPrepare("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID", attributeId)
+
+var childIds = AttributeUtil.getAllChildren(attributeId).concat(attributeId);
+
+var condition = SqlCondition.begin()
+    .and("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID in ('" + childIds.join("','") + "')")
     .build();
 
 //delete all entries in AB_ATTRIBUTEUSAGE belonging to the attribute to avoid unrelated entries
-db.deleteData("AB_ATTRIBUTEUSAGE", usageCondition);
\ No newline at end of file
+db.deleteData("AB_ATTRIBUTEUSAGE", condition);
+
+condition = SqlCondition.begin()
+    .and("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID in ('" + childIds.join("','") + "')")
+    .build();
+
+//delete all entries in AB_ATTRIBUTERELATION for the attributes
+db.deleteData("AB_ATTRIBUTERELATION", condition);
+
+condition = SqlCondition.begin()
+    .and("AB_ATTRIBUTE.AB_ATTRIBUTEID in ('" + childIds.join("','") + "')")
+    .build();
+
+//delete all attribute children
+db.deleteData("AB_ATTRIBUTE", condition);
diff --git a/entity/Communication_entity/entityfields/communicationid/valueProcess.js b/entity/Communication_entity/entityfields/communicationid/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..86ef789e064a4016f2d12c432498dc23474807aa
--- /dev/null
+++ b/entity/Communication_entity/entityfields/communicationid/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.util");
+import("system.vars");
+import("system.result");
+import("system.neon");
+
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+    result.string(util.getNewUUID());
\ No newline at end of file
diff --git a/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod b/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
index 26a3cc11148f4c3ba051ee2c16769f3199f9af9c..e1079bb8c8e2765881abf59cddf9d4dcee1d8f8d 100644
--- a/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
+++ b/entity/KeywordAttribute_entity/KeywordAttribute_entity.aod
@@ -92,6 +92,7 @@
       <name>db</name>
       <alias>Data_alias</alias>
       <conditionProcess>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <onDBDelete>%aditoprj%/entity/KeywordAttribute_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
         <linkInformation>
           <name>bd113d67-34ab-4708-b0e5-60a44332e6b8</name>
diff --git a/entity/KeywordAttribute_entity/recordcontainers/db/onDBDelete.js b/entity/KeywordAttribute_entity/recordcontainers/db/onDBDelete.js
new file mode 100644
index 0000000000000000000000000000000000000000..106ba3d52cf62b33fe39087d4a893ea7821b9462
--- /dev/null
+++ b/entity/KeywordAttribute_entity/recordcontainers/db/onDBDelete.js
@@ -0,0 +1,5 @@
+import("Sql_lib");
+import("system.db");
+
+var cond = SqlCondition.begin().andPrepareVars("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", "$field.AB_KEYWORD_ATTRIBUTEID").build("1=2");
+db.deleteData("AB_KEYWORD_ATTRIBUTERELATION", cond);
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index 97125bb8039cdfc95b82b1a17c2dc1f1e9d0d198..5460a7848abff474a7e42230bd91080ef97f3c21 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -22,6 +22,8 @@
       <mandatory v="true" />
       <possibleItemsProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/possibleItemsProcess.js</possibleItemsProcess>
       <groupable v="true" />
+      <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/container/stateProcess.js</stateProcess>
     </entityField>
     <entityField>
       <name>AB_KEYWORD_ENTRYID</name>
@@ -30,10 +32,13 @@
     </entityField>
     <entityField>
       <name>KEYID</name>
+      <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/documentation.adoc</documentation>
       <title>Key</title>
+      <mandatory v="true" />
       <state>READONLY</state>
       <stateProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js</valueProcess>
+      <onValidation>%aditoprj%/entity/KeywordEntry_entity/entityfields/keyid/onValidation.js</onValidation>
     </entityField>
     <entityField>
       <name>TITLE</name>
@@ -294,7 +299,7 @@
       <alias>Data_alias</alias>
       <conditionProcess>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
       <orderClauseProcess>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
-      <onDBUpdate>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
+      <onDBDelete>%aditoprj%/entity/KeywordEntry_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
         <linkInformation>
           <name>52acbfe0-57f4-4614-83af-9882e168f431</name>
diff --git a/entity/KeywordEntry_entity/entityfields/container/documentation.adoc b/entity/KeywordEntry_entity/entityfields/container/documentation.adoc
index b46aaac93ed420d5150d4d5202dc302a4898ca70..e1cfb215ac798637843c387c914479f4428e301a 100644
--- a/entity/KeywordEntry_entity/entityfields/container/documentation.adoc
+++ b/entity/KeywordEntry_entity/entityfields/container/documentation.adoc
@@ -1 +1,2 @@
- `CONTAINER` is the a name and used for grouping keyword-entries. This is was a keyword-container essentially is.
\ No newline at end of file
+ `CONTAINER` is the a name and used for grouping keyword-entries. This is was a keyword-container essentially is.
+After creation of an entry it cannot be changed anymore.
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/entityfields/container/stateProcess.js b/entity/KeywordEntry_entity/entityfields/container/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..82fc64847e6ac4e59a674fac7873eef6161aa741
--- /dev/null
+++ b/entity/KeywordEntry_entity/entityfields/container/stateProcess.js
@@ -0,0 +1,19 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+/*allowing the CONTAINER to change later would result in a lot of problems like
+ * - what happens to SORTING-value?
+ * - what happens with already created keyword-attributerelations?
+ * - what happens when a key is specified twice after the change?
+ * - what happens when the keywordentry has been already used?
+ * 
+ * Therefore just forbid to change it after the record has been inserted
+ */
+var fieldState;
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+    fieldState = neon.COMPONENTSTATE_AUTO;
+else
+    fieldState = neon.COMPONENTSTATE_READONLY;
+
+result.string(fieldState);
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/entityfields/keyid/documentation.adoc b/entity/KeywordEntry_entity/entityfields/keyid/documentation.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..543e079982a272d1ea3414231414004150915df5
--- /dev/null
+++ b/entity/KeywordEntry_entity/entityfields/keyid/documentation.adoc
@@ -0,0 +1,7 @@
+The key of an keyword-entry is a internal, technical representation which is stored in references.
+It's unique within a keyword-container but not within the whole keyword-module (like the `AB_KEYWORD_ENTRYID` is).
+
+A UUID is generated and used as preset-value but it's possible to overwrite the `KEYID` with an own value (as long as the custom key follows the rules, like keyword-entry-level-uniqueness)
+This could for example be ISO-standardised value or a value that is maintained within an ERP-system.
+
+After creation of an entry it cannot be changed anymore.
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/entityfields/keyid/onValidation.js b/entity/KeywordEntry_entity/entityfields/keyid/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0830f5196463702be757aa76d46e9b3d3c1c8f4
--- /dev/null
+++ b/entity/KeywordEntry_entity/entityfields/keyid/onValidation.js
@@ -0,0 +1,26 @@
+import("system.translate");
+import("system.result");
+import("system.db");
+import("system.vars");
+import("Sql_lib");
+import("Entity_lib");
+
+var container = vars.get("$field.CONTAINER");
+var keyId = ProcessHandlingUtils.getOnValidationValue(vars.get("$field.KEYID")).trim();
+
+//a KEY has always to be unique within one container and since the user can specify the key on insert we've to ensure that it's unique
+if (container && keyId)
+{
+    var selfEntryId = vars.get("$field.AB_KEYWORD_ENTRYID");
+    var sqlMasks = new SqlMaskingUtils();
+    var alreadyExistsSql = SqlCondition.begin()
+                                        .andPrepare(sqlMasks.trim("AB_KEYWORD_ENTRY.KEYID"), keyId, null, SqlUtils.getSingleColumnType("AB_KEYWORD_ENTRY", "KEYID"))
+                                        .andPrepare("AB_KEYWORD_ENTRY.CONTAINER", container)
+                                        .andPrepare("AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID", selfEntryId, "# != ?")
+                                        .buildSql("select AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID from AB_KEYWORD_ENTRY");
+    var alreadyExistantEntryId = db.cell(alreadyExistsSql);
+    
+    if (alreadyExistantEntryId != "")
+        result.string(translate.text("the specified key has to be unique for that container but does already exist"));
+    
+}
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js b/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js
index 4af99287f59a86e98d9b4c552c010fe13c106cc7..2fc41228ab188dc70af71478adb1d1afd7c1cb77 100644
--- a/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js
+++ b/entity/KeywordEntry_entity/entityfields/keyid/valueProcess.js
@@ -3,5 +3,5 @@ import("system.result");
 import("system.neon");
 import("system.vars");
 
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value"))
     result.string(util.getNewUUID());
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/recordcontainers/db/onDBDelete.js b/entity/KeywordEntry_entity/recordcontainers/db/onDBDelete.js
new file mode 100644
index 0000000000000000000000000000000000000000..5770e446a9d339b5e4aa822f225fa0d36bd3a4ac
--- /dev/null
+++ b/entity/KeywordEntry_entity/recordcontainers/db/onDBDelete.js
@@ -0,0 +1,5 @@
+import("Sql_lib");
+import("system.db");
+
+var cond = SqlCondition.begin().andPrepareVars("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID", "$field.AB_KEYWORD_ENTRYID").build("1=2");
+db.deleteData("AB_KEYWORD_ATTRIBUTERELATION", cond);
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/recordcontainers/db/onDBUpdate.js b/entity/KeywordEntry_entity/recordcontainers/db/onDBUpdate.js
deleted file mode 100644
index d9f8978acd6592e20a2851d1e46b490b2ff398d7..0000000000000000000000000000000000000000
--- a/entity/KeywordEntry_entity/recordcontainers/db/onDBUpdate.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import("system.translate");
-import("system.db");
-import("system.vars");
-import("system.text");
-import("system.neon");
-import("Sql_lib");
-
-var changedFields = vars.get("$local.changed");
-//whenever the container is changed data that depends on the keyword-container has be "fixed" to keep consistency
-//this could be information like Keyword-attributes or the sorting-position
-// TODO: maybe it'd be better to lock KeywordContainer as read-only after creation
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT && changedFields.indexOf("AB_KEYWORD_ENTRY.CONTAINER") > -1)
-{
-    var keyContainer = vars.get("$field.CONTAINER");
-    if (keyContainer)
-    {
-        var cond = SqlCondition.begin().andPrepare("AB_KEYWORD_ENTRY.CONTAINER", keyContainer);
-        var maskingHelper = new SqlMaskingUtils();
-        var newCodeNumber = db.cell(cond.buildSql("select " + maskingHelper.max("AB_KEYWORD_ENTRY.SORTING") + " from AB_KEYWORD_ENTRY", "1 = 2"));
-        newCodeNumber = Number(newCodeNumber);//if no number exists till no, start value will be 1 (due to: ++0)
-        if (isNaN(newCodeNumber))
-            throw new TypeError(translate.text("The code number is not a valid number."));
-
-        var cols = ["SORTING"];
-        var vals = [++newCodeNumber];
-        cond.clear().andPrepare("AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID", vars.get("$sys.uid"));
-        db.updateData("AB_KEYWORD_ENTRY", cols, null, vals, cond.build("1 = 2"));
-    }
-}
\ No newline at end of file
diff --git a/entity/ObjectRelation_entity/ObjectRelation_entity.aod b/entity/ObjectRelation_entity/ObjectRelation_entity.aod
index 5a3be8bc441a7c7be97e56d8618a0b407e0761b8..7962870d76d7b67f7f3d91d16bb3a4a301c3cc2d 100644
--- a/entity/ObjectRelation_entity/ObjectRelation_entity.aod
+++ b/entity/ObjectRelation_entity/ObjectRelation_entity.aod
@@ -40,7 +40,9 @@
       <linkedContextProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/object2_rowid/linkedContextProcess.js</linkedContextProcess>
       <mandatory v="true" />
       <stateProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/object2_rowid/stateProcess.js</stateProcess>
+      <titleProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/object2_rowid/titleProcess.js</titleProcess>
       <valueProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/object2_rowid/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/object2_rowid/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>OBJECT2_TYPE</name>
@@ -153,6 +155,14 @@
       <targetIdField>OBJECT2_ROWID</targetIdField>
       <documentation>%aditoprj%/entity/ObjectRelation_entity/entityfields/bothobjects/documentation.adoc</documentation>
       <recordContainer>db</recordContainer>
+      <dependencies>
+        <entityDependency>
+          <name>cb49ee3d-4497-4edc-90b6-82d397464f75</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>TaskObjectRelations</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
       <children>
         <entityParameter>
           <name>AnyObjectRowid_param</name>
@@ -165,7 +175,7 @@
         <entityParameter>
           <name>Object1Rowid_param</name>
           <expose v="true" />
-          <mandatory v="true" />
+          <mandatory v="false" />
         </entityParameter>
         <entityParameter>
           <name>Object1Type_param</name>
@@ -175,7 +185,7 @@
         <entityParameter>
           <name>Object2Rowid_param</name>
           <expose v="true" />
-          <mandatory v="true" />
+          <mandatory v="false" />
         </entityParameter>
         <entityParameter>
           <name>Object2Type_param</name>
@@ -323,6 +333,14 @@
       <valueProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/anyobjecttype/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/ObjectRelation_entity/entityfields/anyobjecttype/displayValueProcess.js</displayValueProcess>
     </entityField>
+    <entityParameter>
+      <name>Object2RowidTitle_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>EMPTY</name>
+    </entityField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/ObjectRelation_entity/entityfields/object2_rowid/displayValueProcess.js b/entity/ObjectRelation_entity/entityfields/object2_rowid/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..04cbd7a32102a5efd583a0af62b1ce46ecebdbb7
--- /dev/null
+++ b/entity/ObjectRelation_entity/entityfields/object2_rowid/displayValueProcess.js
@@ -0,0 +1,14 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("system.db");
+import("Context_lib");
+
+var recordstate = vars.get("$sys.recordstate");
+if (recordstate == neon.OPERATINGSTATE_EDIT)
+{
+    if (vars.exists("$field.OBJECT1_ROWID") && vars.get("$field.OBJECT1_ROWID") && vars.exists("$field.OBJECT1_TYPE") && vars.get("$field.OBJECT1_TYPE"))
+    {
+        result.string(db.cell(ContextUtils.getNameSql(vars.get("$field.OBJECT1_TYPE"), vars.get("$field.OBJECT1_ROWID"))));
+    }
+}
\ No newline at end of file
diff --git a/entity/ObjectRelation_entity/entityfields/object2_rowid/titleProcess.js b/entity/ObjectRelation_entity/entityfields/object2_rowid/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc39a528c34c8e610d4f6f53ea6f83b98699f497
--- /dev/null
+++ b/entity/ObjectRelation_entity/entityfields/object2_rowid/titleProcess.js
@@ -0,0 +1,5 @@
+import("system.translate");
+import("system.vars");
+import("system.result");
+import("Context_lib");
+result.string(vars.exists("$param.Object2RowidTitle_param") ? vars.get("$param.Object2RowidTitle_param") : "Object 2");
\ No newline at end of file
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index 003c2e6a3c7811c6426ca9afdf74c250ab58adae..cba3010100ed198c433c1a2f516d8a2bd7e7ed8c 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -15,6 +15,8 @@
       <name>CURRENCY</name>
       <title>Currency</title>
       <consumer>KeywordCurrencies</consumer>
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/currency/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/currency/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>OFFERCODE</name>
@@ -87,6 +89,7 @@
       <name>HEADER</name>
       <title>Cover letter</title>
       <contentType>HTML</contentType>
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/header/valueProcess.js</valueProcess>
     </entityField>
     <entityConsumer>
       <name>Offeritems</name>
@@ -181,12 +184,14 @@
       <title>Language</title>
       <consumer>Languages</consumer>
       <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/language/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/language/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityActionField>
-      <name>newOffer</name>
+      <name>copyOffer</name>
       <fieldType>ACTION</fieldType>
       <title>Copy offer</title>
-      <onActionProcess>%aditoprj%/entity/Offer_entity/entityfields/newoffer/onActionProcess.js</onActionProcess>
+      <onActionProcess>%aditoprj%/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js</onActionProcess>
     </entityActionField>
     <entityField>
       <name>VERSNR</name>
@@ -198,6 +203,7 @@
     <entityField>
       <name>OFFER_ID</name>
       <documentation>%aditoprj%/entity/Offer_entity/entityfields/offer_id/documentation.adoc</documentation>
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/offer_id/valueProcess.js</valueProcess>
     </entityField>
     <entityFieldGroup>
       <name>OfferCode_VersNr_fieldgroup</name>
@@ -314,6 +320,7 @@
       <description></description>
       <contentType>LONG_TEXT</contentType>
       <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/address/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
       <name>ChosenAddress</name>
@@ -418,6 +425,55 @@
         </entityParameter>
       </children>
     </entityProvider>
+    <entityParameter>
+      <name>OfferCurrency_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>OfferLanguage_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>OfferHeader_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>OfferOriginal_Id_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>OfferAddress_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>OfferCode_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>OfferVersnr_param</name>
+      <expose v="true" />
+      <triggerRecalculation v="true" />
+      <mandatory v="false" />
+      <description>PARAMETER</description>
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -426,6 +482,7 @@
       <maximumDbRows v="0" />
       <fromClauseProcess>%aditoprj%/entity/Offer_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
       <conditionProcess>%aditoprj%/entity/Offer_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <onDBInsert>%aditoprj%/entity/Offer_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <onDBDelete>%aditoprj%/entity/Offer_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
         <linkInformation>
diff --git a/entity/Offer_entity/entityfields/address/valueProcess.js b/entity/Offer_entity/entityfields/address/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..160f9518edab8b5ed593d921661aada906512ee4
--- /dev/null
+++ b/entity/Offer_entity/entityfields/address/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.vars");
+
+if (vars.exists("$param.OfferAddress_param")) 
+{
+    result.string(vars.get("$param.OfferAddress_param"));
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js b/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4957b1ff844fb074b3ffd05533d1e75377f5b96d
--- /dev/null
+++ b/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js
@@ -0,0 +1,12 @@
+import("system.vars");
+import("system.neon");
+import("Offer_lib");
+
+var contactId = vars.getString("$field.CONTACT_ID");
+var currency = vars.getString("$field.CURRENCY");
+var language = vars.getString("$field.LANGUAGE");
+var header = vars.getString("$field.HEADER");
+var offerId = vars.getString("$field.OFFERID");
+
+OfferUtils.copyOffer(offerId, contactId, language, currency, header);
+    
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/currency/displayValueProcess.js b/entity/Offer_entity/entityfields/currency/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..251895de0caa384e595ac12282df6a3955093b04
--- /dev/null
+++ b/entity/Offer_entity/entityfields/currency/displayValueProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("system.vars");
+import("Keyword_lib");
+
+if (vars.exists("$param.OfferCurrency_param") && vars.get("$param.OfferCurrency_param")) 
+{
+    var currency = KeywordUtils.getViewValue($KeywordRegistry.get.Currency, vars.get("$param.OfferCurrency_param"));
+    result.string(currency);
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/currency/valueProcess.js b/entity/Offer_entity/entityfields/currency/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..636be1adc9a7505eea4d957860d46a81856f5a93
--- /dev/null
+++ b/entity/Offer_entity/entityfields/currency/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.vars");
+
+if (vars.exists("$param.OfferCurrency_param") && vars.get("$param.OfferCurrency_param")) 
+{
+    result.string(vars.get("$param.OfferCurrency_param"));
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/header/valueProcess.js b/entity/Offer_entity/entityfields/header/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c1dd2bbc6e368ccd25f363f47e8e86f6abceaa55
--- /dev/null
+++ b/entity/Offer_entity/entityfields/header/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.vars");
+
+if (vars.exists("$param.OfferHeader_param") && vars.get("$param.OfferHeader_param")) 
+{
+    result.string(vars.get("$param.OfferHeader_param"));
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/language/displayValueProcess.js b/entity/Offer_entity/entityfields/language/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..987df7556fbe55afa0152a52e1e8d4c766b4ce39
--- /dev/null
+++ b/entity/Offer_entity/entityfields/language/displayValueProcess.js
@@ -0,0 +1,15 @@
+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("$param.OfferLanguage_param");
+    var latinName = db.cell(SqlCondition.begin()
+        .andPrepare("AB_LANGUAGE.ISO3", iso3)
+        .buildSql("select NAME_LATIN from AB_LANGUAGE", "1=0"));
+    latinName = translate.text(latinName);
+    result.string(latinName);
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/language/valueProcess.js b/entity/Offer_entity/entityfields/language/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4fc924e18219f6a6b30f4b3ebb8ffb22d8ed3cb0
--- /dev/null
+++ b/entity/Offer_entity/entityfields/language/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("system.vars");
+
+if (vars.exists("$param.OfferLanguage_param") && vars.get("$param.OfferLanguage_param")) 
+{
+    result.string(vars.get("$param.OfferLanguage_param"));
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/newoffer/onActionProcess.js b/entity/Offer_entity/entityfields/newoffer/onActionProcess.js
deleted file mode 100644
index 1991c7036f76bc53bdb6c9ce2b6abe508001a7a1..0000000000000000000000000000000000000000
--- a/entity/Offer_entity/entityfields/newoffer/onActionProcess.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import("system.vars");
-import("system.neon");
-import("Util_lib");
-import("Neon_lib");
-import("Offer_lib");
-
-var InputMapping = {
-    
-    "OFFER": {
-            condition: "OFFERID = '" + vars.get("$field.OFFERID") + "'"
-            , ValueMapping: {
-                            "OFFER_ID": ""
-                            , "OFFERCODE":  OfferUtils.getNextOfferNumber()
-                            , "VERSNR": "1"
-                        }
-            , SubModules:{
-                "OFFERITEM": {
-                    condition: "OFFER_ID = '" + vars.get("$field.OFFERID") + "' order by ITEMSORT" 
-            }
-        }
-    }
-}
-
-var ModulesMapping = CopyModuleUtils.copyModule(InputMapping);
-
-CopyModuleUtils.openNewModules("Offer", ModulesMapping);
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/newofferversion/onActionProcess.js b/entity/Offer_entity/entityfields/newofferversion/onActionProcess.js
index 0a83f6827223845ef954c036bf5d99866118fe5e..add48fbf11814bdf125f71afc331b9957afa4172 100644
--- a/entity/Offer_entity/entityfields/newofferversion/onActionProcess.js
+++ b/entity/Offer_entity/entityfields/newofferversion/onActionProcess.js
@@ -1,26 +1,16 @@
 import("system.vars");
 import("system.neon");
-import("Util_lib");
-import("Neon_lib");
 import("Offer_lib");
 
-var InputMapping = {
-    
-    "OFFER": {
-            condition: "OFFERID = '" + vars.get("$field.OFFERID") + "'"
-            , ValueMapping: {
-                            "OFFER_ID": vars.get("$field.OFFERID")
-                            , "OFFERCODE":  vars.get("$field.OFFERCODE")
-                            , "VERSNR":  OfferUtils.getNextOfferVersionNumber(vars.get("$field.OFFERCODE"))
-                        }
-            , SubModules:{
-                "OFFERITEM": {
-                    condition: "OFFER_ID = '" + vars.get("$field.OFFERID") + "' order by ITEMSORT" 
-            }
-        }
-    }
+var params = {
+    "ContactId_param" : vars.get("$field.CONTACT_ID"),
+    "SalesprojectId_param" : vars.get("$field.SALESPROJECT_ID"),
+    "OfferLanguage_param" : vars.get("$field.LANGUAGE"),
+    "OfferOriginal_Id_param" : vars.get("$field.OFFERID"),
+    "OfferCode_param" : vars.get("$field.OFFERCODE"),
+    "OfferVersnr_param" : OfferUtils.getNextOfferVersionNumber(vars.get("$field.OFFERCODE")),
+    "OfferCurrency_param" : vars.get("$field.CURRENCY"),
+    "OfferAddress_param" : vars.get("$field.ADDRESS"),
+    "OfferHeader_param" : vars.get("$field.HEADER")
 }
-
-var ModulesMapping = CopyModuleUtils.copyModule(InputMapping);
-
-CopyModuleUtils.openNewModules("Offer", ModulesMapping);
\ No newline at end of file
+neon.openContext("Offer", null, null, neon.OPERATINGSTATE_NEW, params);
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/offer_id/valueProcess.js b/entity/Offer_entity/entityfields/offer_id/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/entity/Offer_entity/entityfields/offercode/onValidation.js b/entity/Offer_entity/entityfields/offercode/onValidation.js
index de949a3e766bbf81de26ee22689c4808a7faae44..3b9c0b76f65fa2b8ae4026d17b1e78d5197d919f 100644
--- a/entity/Offer_entity/entityfields/offercode/onValidation.js
+++ b/entity/Offer_entity/entityfields/offercode/onValidation.js
@@ -6,7 +6,8 @@ import("Salesproject_lib");
 import("Util_lib");
 import("Entity_lib");
 
-if( vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW
+    && !vars.exists("$param.OfferCode_param")
     && !OfferUtils.validateOfferNumber(ProcessHandlingUtils.getOnValidationValue(vars.get("$field.OFFERCODE"))) )
 {
     vars.set( "$field.OFFERCODE", OfferUtils.getNextOfferNumber().toString() );
diff --git a/entity/Offer_entity/entityfields/offercode/valueProcess.js b/entity/Offer_entity/entityfields/offercode/valueProcess.js
index 933257e8cc871bfd2d5cb0be92049e55ea93a2b8..502b44731b281c7fc79094de58242869d07e423d 100644
--- a/entity/Offer_entity/entityfields/offercode/valueProcess.js
+++ b/entity/Offer_entity/entityfields/offercode/valueProcess.js
@@ -4,6 +4,9 @@ import("system.neon");
 import("Offer_lib");
 
 if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-{    
-    result.string(OfferUtils.getNextOfferNumber());
+{
+    if (vars.exists("$param.OfferCode_param") && vars.get("$param.OfferCode_param"))
+        result.string(vars.get("$param.OfferCode_param"));
+    else
+        result.string(OfferUtils.getNextOfferNumber());
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/versnr/valueProcess.js b/entity/Offer_entity/entityfields/versnr/valueProcess.js
index f3ad73d05605a0009779e02d2767edba66fe2189..5d3797b77b0fc1e83590585de35fa636da9962aa 100644
--- a/entity/Offer_entity/entityfields/versnr/valueProcess.js
+++ b/entity/Offer_entity/entityfields/versnr/valueProcess.js
@@ -5,5 +5,8 @@ import("Offer_lib");
 
 if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
 {
-    result.string( "1" );
+    if (vars.exists("$param.OfferVersnr_param") && vars.get("$param.OfferVersnr_param"))
+        result.string(vars.get("$param.OfferVersnr_param"));
+    else
+        result.string( "1" );
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/recordcontainers/db/onDBInsert.js b/entity/Offer_entity/recordcontainers/db/onDBInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..6b3c4033a05890bdd874ce4fa610333b06fdc538
--- /dev/null
+++ b/entity/Offer_entity/recordcontainers/db/onDBInsert.js
@@ -0,0 +1,6 @@
+import("system.neon");
+import("system.vars");
+import("Offer_lib");
+
+if (vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.OfferOriginal_Id_param"))
+    OfferUtils.copyOfferItems(vars.getString("$param.OfferOriginal_Id_param"), vars.get("$field.OFFERID"));
diff --git a/entity/Order_entity/entityfields/currency/displayValueProcess.js b/entity/Order_entity/entityfields/currency/displayValueProcess.js
index 6be00b937833451cf3146a6c30d09c46980cf840..2519786ebebdab4dd7112825bf47108ea7110ead 100644
--- a/entity/Order_entity/entityfields/currency/displayValueProcess.js
+++ b/entity/Order_entity/entityfields/currency/displayValueProcess.js
@@ -1,5 +1,3 @@
-import("system.db");
-import("system.translate");
 import("system.result");
 import("system.vars");
 import("Keyword_lib");
diff --git a/entity/Orderitem_entity/Orderitem_entity.aod b/entity/Orderitem_entity/Orderitem_entity.aod
index 9162c9654de9ae11fc8509b929d8f764d7497db5..c479324ec12198fed69af55498a8f6bc10d18342 100644
--- a/entity/Orderitem_entity/Orderitem_entity.aod
+++ b/entity/Orderitem_entity/Orderitem_entity.aod
@@ -235,10 +235,6 @@
           <name>ASSIGNEDTO.value</name>
           <recordfield>SALESORDERITEM.ASSIGNEDTO</recordfield>
         </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DESCRIPTION.value</name>
-          <recordfield>SALESORDERITEM.DESCRIPTION</recordfield>
-        </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>DISCOUNT.value</name>
           <recordfield>SALESORDERITEM.DISCOUNT</recordfield>
@@ -303,6 +299,10 @@
           <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>
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 844a65942f92a6089f1c7a5197d1065a0a1311d1..2c01c9e912c5329aafa66b08f07e49672f7d733d 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -476,6 +476,57 @@
         <fieldName>LanguagesISO3Code</fieldName>
       </dependency>
     </entityConsumer>
+    <entityConsumer>
+      <name>Salesprojects</name>
+      <title>Salesprojects</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Salesproject_entity</entityName>
+        <fieldName>Salesprojects</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContactId_param</name>
+          <code>%aditoprj%/entity/Organisation_entity/entityfields/salesprojects/children/contactid_param/code.js</code>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityActionField>
+      <name>newTask</name>
+      <fieldType>ACTION</fieldType>
+      <title>New task</title>
+      <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/newtask/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:TASKS</iconId>
+    </entityActionField>
+    <entityConsumer>
+      <name>TaskObjectRelations</name>
+      <title>Tasks</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>ObjectRelation_entity</entityName>
+        <fieldName>BothObjects</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>Object1Rowid_param</name>
+          <code>%aditoprj%/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1rowid_param/code.js</code>
+        </entityParameter>
+        <entityParameter>
+          <name>Object1Type_param</name>
+          <code>%aditoprj%/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1type_param/code.js</code>
+        </entityParameter>
+        <entityParameter>
+          <name>Object2Type_param</name>
+          <code>%aditoprj%/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2type_param/code.js</code>
+        </entityParameter>
+        <entityParameter>
+          <name>Object2RowidTitle_param</name>
+          <code>%aditoprj%/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2rowidtitle_param/code.js</code>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -486,14 +537,14 @@
       <onDBUpdate>%aditoprj%/entity/Organisation_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
       <linkInformation>
         <linkInformation>
-          <name>ff0fa64f-4d73-49b3-bc02-02018392e838</name>
+          <name>47c6c065-ae0e-4cee-b913-335570e3221c</name>
           <tableName>ORGANISATION</tableName>
           <primaryKey>ORGANISATIONID</primaryKey>
           <isUIDTable v="true" />
           <readonly v="false" />
         </linkInformation>
         <linkInformation>
-          <name>e3033b6f-966e-415a-9390-c61d5a1b19fc</name>
+          <name>e6120ee7-e6c3-4f60-9327-417627ba1fac</name>
           <tableName>CONTACT</tableName>
           <primaryKey>CONTACTID</primaryKey>
           <isUIDTable v="false" />
diff --git a/entity/Organisation_entity/entityfields/newtask/onActionProcess.js b/entity/Organisation_entity/entityfields/newtask/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..184aba3ab162e889d040c46a76c62f651e982d86
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/newtask/onActionProcess.js
@@ -0,0 +1,8 @@
+import("system.vars");
+import("system.neon");
+import("Context_lib");
+
+var params = {};
+params["ObjectType_param"] = ContextUtils.getCurrentContextId();
+params["RowId_param"] = vars.get("$field.ORGANISATIONID");
+neon.openContext("Task", null, null, neon.OPERATINGSTATE_NEW, params);
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/salesprojects/children/contactid_param/code.js b/entity/Organisation_entity/entityfields/salesprojects/children/contactid_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..835140d0bee877176a6fd5a8e94460e5b5e776d1
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/salesprojects/children/contactid_param/code.js
@@ -0,0 +1,3 @@
+import("system.vars");
+import("system.result");
+result.string(vars.get("$field.ORGANISATIONID"));
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1rowid_param/code.js b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1rowid_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..bcfda44fe71eac93b3f8c11cc0c85a496f2cd51c
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1rowid_param/code.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.ORGANISATIONID"));
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1type_param/code.js b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1type_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..008915f61deac19ccdd40fff81701de63eb3b6a2
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object1type_param/code.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Context_lib");
+
+result.string(ContextUtils.getCurrentContextId());
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2rowidtitle_param/code.js b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2rowidtitle_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..e273ebaf0d31de77e8d77836146eeb81503ed474
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2rowidtitle_param/code.js
@@ -0,0 +1,3 @@
+import("system.translate");
+import("system.result");
+result.string(translate.text("Task"))
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2type_param/code.js b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2type_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..86bf9bdfc95f2757f6ee947b7549edad4ce0b154
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/taskobjectrelations/children/object2type_param/code.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.string("Task");
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 33c0699ff37e75273231d5d84c7f4f07c7b67b14..5670b1cf170b95644959a18c467cbb0853c025ea 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -43,6 +43,8 @@
     <entityField>
       <name>SALUTATION</name>
       <title>Salutation</title>
+      <mandatory v="true" />
+      <possibleItemsProcess>%aditoprj%/entity/Person_entity/entityfields/salutation/possibleItemsProcess.js</possibleItemsProcess>
     </entityField>
     <entityField>
       <name>TITLE</name>
@@ -529,6 +531,29 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityConsumer>
+      <name>Attributes</name>
+      <title>Attributes</title>
+      <fieldType>DEPENDENCY_OUT</fieldType>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AttributeRelation_entity</entityName>
+        <fieldName>RelationsForSpecificObject</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>objectRowId_param</name>
+          <code>%aditoprj%/entity/Person_entity/entityfields/attributes/children/objectrowid_param/code.js</code>
+          <expose v="true" />
+          <triggerRecalculation v="true" />
+        </entityParameter>
+        <entityParameter>
+          <name>objectType_param</name>
+          <code>%aditoprj%/entity/Person_entity/entityfields/attributes/children/objecttype_param/code.js</code>
+          <triggerRecalculation v="true" />
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Person_entity/entityfields/attributes/children/objectrowid_param/code.js b/entity/Person_entity/entityfields/attributes/children/objectrowid_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..ee0cddc370f78c08084b64d57e2a36686aad1e82
--- /dev/null
+++ b/entity/Person_entity/entityfields/attributes/children/objectrowid_param/code.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.PERSONID"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/attributes/children/objecttype_param/code.js b/entity/Person_entity/entityfields/attributes/children/objecttype_param/code.js
new file mode 100644
index 0000000000000000000000000000000000000000..008915f61deac19ccdd40fff81701de63eb3b6a2
--- /dev/null
+++ b/entity/Person_entity/entityfields/attributes/children/objecttype_param/code.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Context_lib");
+
+result.string(ContextUtils.getCurrentContextId());
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/openeditdefaultsview/onActionProcess.js b/entity/Person_entity/entityfields/openeditdefaultsview/onActionProcess.js
index e7afa1485396900885b2a74453df003aa2869337..f8e59e680f629617e444c405a8e6e42c2997c901 100644
--- a/entity/Person_entity/entityfields/openeditdefaultsview/onActionProcess.js
+++ b/entity/Person_entity/entityfields/openeditdefaultsview/onActionProcess.js
@@ -1,3 +1,3 @@
 import("system.vars");
 import("system.neon");
-neon.openContext("Person", "ContactEditDefaults_view", [vars.get("$field.CONTACTID")], neon.OPERATINGSTATE_EDIT, null);
\ No newline at end of file
+neon.openContext("Person", "PersonEditDefaults_view", [vars.get("$field.CONTACTID")], neon.OPERATINGSTATE_EDIT, null);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/salutation/possibleItemsProcess.js b/entity/Person_entity/entityfields/salutation/possibleItemsProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..935c4ef90bfcfae64a38388e2c0c9a44cbec9da2
--- /dev/null
+++ b/entity/Person_entity/entityfields/salutation/possibleItemsProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.object([["Frau", "Frau"], ["Herr", "Herr"]])
\ No newline at end of file
diff --git a/entity/SalesprojectForecast_entity/recordcontainers/db/onDBUpdate.js b/entity/SalesprojectForecast_entity/recordcontainers/db/onDBUpdate.js
index f165ed8fa18606a2080496441041fe5a39a06d59..ee62dca4c5b6641758a1ce2856db770d63641278 100644
--- a/entity/SalesprojectForecast_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/SalesprojectForecast_entity/recordcontainers/db/onDBUpdate.js
@@ -1,3 +1,3 @@
 import("Salesproject_lib");
 
-notifyToUpdateForecast()
\ No newline at end of file
+Salesproject.notifyToUpdateForecast()
\ No newline at end of file
diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod
index 582e6402cccd851b531c43f1bd2894b6c858ea34..33747b351b2cd6381beb1bb75c19b69da28b32ca 100644
--- a/entity/Salesproject_entity/Salesproject_entity.aod
+++ b/entity/Salesproject_entity/Salesproject_entity.aod
@@ -311,6 +311,7 @@
       <description>the total hours of all time trackings related to the salesproject</description>
       <state>READONLY</state>
       <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/timetrackingsum/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/timetrackingsum/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>IMAGE</name>
@@ -397,9 +398,29 @@
     <entityField>
       <name>DAYS_NOTACTIVE</name>
       <title>Days inactive</title>
+      <contentType>NUMBER</contentType>
       <state>READONLY</state>
       <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/days_notactive/valueProcess.js</valueProcess>
     </entityField>
+    <entityProvider>
+      <name>Salesprojects</name>
+      <fieldType>DEPENDENCY_IN</fieldType>
+      <dependencies>
+        <entityDependency>
+          <name>0925d17f-a26a-4641-aaf4-0f74796fefa7</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>Salesprojects</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ContactId_param</name>
+          <expose v="true" />
+          <mandatory v="true" />
+        </entityParameter>
+      </children>
+    </entityProvider>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Salesproject_entity/entityfields/timetrackingsum/displayValueProcess.js b/entity/Salesproject_entity/entityfields/timetrackingsum/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..bfe42a40a4a4811369dc8073130dc00b96032782
--- /dev/null
+++ b/entity/Salesproject_entity/entityfields/timetrackingsum/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+import("Timetracking_lib");
+
+result.string(Timetracking.minutesToReadableHour(parseInt(vars.getString("$field.TIMETRACKINGSUM"))));
\ No newline at end of file
diff --git a/entity/Salesproject_entity/entityfields/timetrackingsum/valueProcess.js b/entity/Salesproject_entity/entityfields/timetrackingsum/valueProcess.js
index e3ef6877942e157abdbd49460716516416b058d0..83c88895a0224ff240ea0dfbaf5b68249efffe8d 100644
--- a/entity/Salesproject_entity/entityfields/timetrackingsum/valueProcess.js
+++ b/entity/Salesproject_entity/entityfields/timetrackingsum/valueProcess.js
@@ -1,10 +1,5 @@
-import("system.text");
-import("system.translate");
-import("system.result");
-import("system.vars");
-import("Timetracking_lib");
-
-var hrs = Timetracking.getTotalTrackingTime(vars.getString("$field.SALESPROJECTID")) / 60;
-hrs = text.formatDouble(hrs, "0.00");
-
-result.string(hrs + " " + translate.text("hrs"));
\ No newline at end of file
+import("system.vars");
+import("system.result");
+import("Timetracking_lib");
+
+result.string(Timetracking.getTotalTrackingTime(vars.getString("$field.SALESPROJECTID")));
\ No newline at end of file
diff --git a/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js b/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js
index c5ae703c9e1ee768bc4f56bfcbdc6290871d04f6..222926e7c12d2e84a2f409dd5b6698a8bbbf4c87 100644
--- a/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js
@@ -15,7 +15,7 @@ vars.get("$local.changed").forEach(function(fieldName) {
             fieldVar = "$field.STATE";
             break;
     }
-        
+
     if (typeValue) {
         Salesproject.insertMilestone(vars.getString("$field.SALESPROJECTID"), typeValue, vars.getString(fieldVar), true);
     }
diff --git a/entity/Task_entity/Task_entity.aod b/entity/Task_entity/Task_entity.aod
index ae40a70777205328c343a84c6367771724ab9df9..a3ddd4cb0337a612790735ecad50e256f04add53 100644
--- a/entity/Task_entity/Task_entity.aod
+++ b/entity/Task_entity/Task_entity.aod
@@ -11,6 +11,7 @@
   <entityFields>
     <entityProvider>
       <name>#PROVIDER</name>
+      <recordContainer>db</recordContainer>
     </entityProvider>
     <entityField>
       <name>CODE</name>
@@ -223,12 +224,23 @@
       <onActionProcess>%aditoprj%/entity/Task_entity/entityfields/newtask_action/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:PLUS</iconId>
     </entityActionField>
+    <entityParameter>
+      <name>RowId_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>ObjectType_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
       <name>db</name>
       <alias>Data_alias</alias>
       <orderClauseProcess>%aditoprj%/entity/Task_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
+      <onDBInsert>%aditoprj%/entity/Task_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <linkInformation>
         <linkInformation>
           <name>47e1b4a5-6901-48b0-85ba-bec39b86a2d7</name>
diff --git a/entity/Task_entity/recordcontainers/db/onDBInsert.js b/entity/Task_entity/recordcontainers/db/onDBInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..333d4d3ca97769c16660a9c6fa7459e28669b98e
--- /dev/null
+++ b/entity/Task_entity/recordcontainers/db/onDBInsert.js
@@ -0,0 +1,13 @@
+import("system.vars");
+import("system.util");
+import("system.db");
+
+if (vars.exists("$param.ObjectType_param") && vars.exists("$param.RowId_param") && vars.get("$param.ObjectType_param") && vars.get("$param.RowId_param"))
+    db.insertData("AB_OBJECTRELATION", ["AB_OBJECTRELATIONID", "OBJECT1_TYPE", "OBJECT1_ROWID", "OBJECT2_TYPE", "OBJECT2_ROWID"], null,
+                    [
+                        util.getNewUUID(),
+                        vars.get("$param.ObjectType_param"),
+                        vars.get("$param.RowId_param"),
+                        "Task",
+                        vars.get("$field.TASKID")
+                    ]);
\ No newline at end of file
diff --git a/entity/Timetracking_entity/Timetracking_entity.aod b/entity/Timetracking_entity/Timetracking_entity.aod
index 4bdee59f79a0d7ca91293f99c44eb094b05b6259..8e52105f68d966cf5b7d9f7dc22db12a9c829bed 100644
--- a/entity/Timetracking_entity/Timetracking_entity.aod
+++ b/entity/Timetracking_entity/Timetracking_entity.aod
@@ -15,8 +15,10 @@
     </entityField>
     <entityField>
       <name>MINUTES</name>
-      <title>Minutes</title>
+      <title>Time</title>
+      <contentType>NUMBER</contentType>
       <mandatory v="true" />
+      <displayValueProcess>%aditoprj%/entity/Timetracking_entity/entityfields/minutes/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>OBJECT_ID</name>
diff --git a/entity/Timetracking_entity/entityfields/minutes/displayValueProcess.js b/entity/Timetracking_entity/entityfields/minutes/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..326c2a9f306a8a9356e4f895c630ace18a27a91f
--- /dev/null
+++ b/entity/Timetracking_entity/entityfields/minutes/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+import("Timetracking_lib");
+
+result.string(Timetracking.minutesToReadableHour(parseInt(vars.getString("$field.MINUTES"))));
\ No newline at end of file
diff --git a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js
index 58bc65ef52c577062f096bb6e0772453784bd6e9..74fa0b796d49d26a64f3dc1afebdec42fa58ec9d 100644
--- a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js
@@ -5,7 +5,8 @@ import("system.db");
 import("system.result");
 import("system.translate");
 import("Data_lib");
-
+import("Keyword_lib");
+import("Money_lib");
 
 var turnoverCategory = translate.text('Turnover');
 var forecastCategory = translate.text('Forecast');
@@ -13,6 +14,13 @@ var forecastCategory = translate.text('Forecast');
 // load data
 var sumOfMonthTurnover = db.table("select year(SALESORDERDATE) yearNum, month(SALESORDERDATE) monthNum, sum(NET + VAT) from SALESORDER group by year(SALESORDERDATE), month(SALESORDERDATE) order by yearNum, monthNum");
 var sumOfMonthForecast = db.table("select year(DATE_START) yearNum, month(DATE_START) monthNum, sum(VOLUME * 1000) from SALESPROJECT_FORECAST group by year(DATE_START), month(DATE_START) order by yearNum, monthNum");
+var sumOfMonthProductsTurnover = db.table("select year(SALESORDERDATE) yearNum, month(SALESORDERDATE) monthNum, SALESORDERITEM.DISCOUNT, SALESORDERITEM.VAT, SALESORDERITEM.PRICE, sum(SALESORDERITEM.QUANTITY), SALESORDERITEM.GROUPCODEID, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.get.ProductGroupcode, "SALESORDERITEM.GROUPCODEID") + ") \n\
+                                            from SALESORDER \n\
+                                            join SALESORDERITEM on SALESORDERITEM.SALESORDER_ID = SALESORDER.SALESORDERID \n\
+                                            where SALESORDERITEM.OPTIONAL <> 1 \n\
+                                            group by year(SALESORDERDATE), month(SALESORDERDATE), SALESORDERITEM.GROUPCODEID, SALESORDERITEM.DISCOUNT, SALESORDERITEM.VAT, SALESORDERITEM.PRICE \n\
+                                            order by yearNum, monthNum");                  //           V--V--> there is no VAT/Discount in forecasts  V-----> forecasts are grouped by grupcode and have always quantity 1
+var sumOfMonthProductsForecast = db.table("select year(DATE_START) yearNum, month(DATE_START) monthNum, 0, 0, sum(VOLUME * 1000),                      1, GROUPCODE, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.get.ProductGroupcode, "GROUPCODE") + ") from SALESPROJECT_FORECAST group by year(DATE_START), month(DATE_START), GROUPCODE order by yearNum, monthNum");
 
 // build chartData
 var rootNode = "";
@@ -27,30 +35,33 @@ for (let i = 0; i < yearCountToShow; i++)
 {
     var year = i + maxYear - yearCountToShow + 1;
     
-    var TurnoverYearSum = 0;
-    var ForecastYearSum = 0;
+    var turnoverYearSum = 0;
+    var forecastYearSum = 0;
     
     // filter data by current year
-    var TurnoverYearData = sumOfMonthTurnover.filter(function(row)
+    var turnoverYearData = sumOfMonthTurnover.filter(function(row)
     {
-        return row[0] == year
+        return row[0] == year;
     });
     
-    var ForecastYearData = sumOfMonthForecast.filter(function(row)
+    var forecastYearData = sumOfMonthForecast.filter(function(row)
     {
-        return row[0] == year
+        return row[0] == year;
     });
     
     for (let i = 1; i <= 12; i++) 
     { 
         // add months
-        TurnoverYearSum += _addMonth(year, i, TurnoverYearData, turnoverCategory);
-        ForecastYearSum += _addMonth(year, i, ForecastYearData, forecastCategory);
+        turnoverYearSum += _addMonth(year, i, turnoverYearData, turnoverCategory);
+        forecastYearSum += _addMonth(year, i, forecastYearData, forecastCategory);
+        
+        _addProducts(year, i, sumOfMonthProductsTurnover, turnoverCategory);
+        _addProducts(year, i, sumOfMonthProductsForecast, forecastCategory);
     }
     
     // add year nodes
-    chartData.add(turnoverCategory + year, rootNode, [turnoverCategory, year.toString(), TurnoverYearSum]);
-    chartData.add(forecastCategory + year, rootNode, [forecastCategory, year.toString(), ForecastYearSum]);
+    chartData.add(turnoverCategory + year, rootNode, [turnoverCategory, year.toString(), turnoverYearSum]);
+    chartData.add(forecastCategory + year, rootNode, [forecastCategory, year.toString(), forecastYearSum]);
 
 }
 
@@ -86,4 +97,40 @@ function _addMonth(pYear, pMonth, pData, pCategory)
     // add month node
     chartData.add(pCategory + pYear + pMonth, pCategory + pYear, [pCategory, monthDate, monthValue]);
     return yearSum;
-}
\ No newline at end of file
+}
+
+function _addProducts(pYear, pMonth, pData, pCategory)
+{
+    var groupcodeSums = {};
+    
+    for (let i = 0; i < pData.length; i++) 
+    { 
+        if (pData[i][0] == pYear && pData[i][1] == pMonth)
+        {
+            var groupCode = pData[i][6];
+            if (groupCode != undefined)
+            {
+                if (groupcodeSums[groupCode] == undefined)
+                {
+                    groupcodeSums[groupCode] = {
+                        sum: 0,
+                        name: pData[i][7]
+                    }
+                }
+                
+                pData[i][2] = pData[i][2] || 0;
+                pData[i][3] = pData[i][3] || 0;
+                pData[i][4] = pData[i][4] || 0;
+                pData[i][5] = pData[i][5] || 0;
+
+                groupcodeSums[groupCode]["sum"] += MoneyUtils.getGross(parseFloat(pData[i][3]), parseFloat(pData[i][4]), parseFloat(pData[i][5]), parseFloat(pData[i][2]));
+            }
+        }
+    }
+    
+    for (let groupcode in groupcodeSums) 
+    {
+        if (groupcodeSums[groupcode]["sum"])
+            chartData.add(pCategory + pYear + pMonth + groupcode, pCategory + pYear + pMonth, [pCategory, groupcodeSums[groupcode]["name"], groupcodeSums[groupcode]["sum"]]);
+    }
+}
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 9e2338a3cef1e448c82e6b74c022c7a571a0977f..bb50a0cfc5ae38837d03dbd597767fbd1009e531 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -2348,7 +2348,6 @@
     </entry>
     <entry>
       <key>Print Offer</key>
-      <key>Touchpoint</key>
     </entry>
     <entry>
       <key>Touchpoints</key>
@@ -2362,6 +2361,30 @@
     <entry>
       <key>Days inactive</key>
     </entry>
+    <entry>
+      <key>Touchpoint</key>
+    </entry>
+    <entry>
+      <key>Combobox Value</key>
+    </entry>
+    <entry>
+      <key>relations</key>
+    </entry>
+    <entry>
+      <key>Time</key>
+    </entry>
+    <entry>
+      <key>New task</key>
+    </entry>
+    <entry>
+      <key>MyTasks</key>
+    </entry>
+    <entry>
+      <key>Show my tasks</key>
+    </entry>
+    <entry>
+      <key>the specified key has to be unique for that container but does already exist</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 c31e4d2d49ec1633572bdd9d49602d6f827d7a78..ae516de8b29040697890f44b499916e7ca0ed646 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -1063,6 +1063,10 @@
       <key>My Activities</key>
       <value>Meine Aktivitäten</value>
     </entry>
+    <entry>
+      <key>Combobox Value</key>
+      <value>Combobox-Wert</value>
+    </entry>
     <entry>
       <key>Salesprojects</key>
       <value>Vertriebsprojekte</value>
@@ -1687,9 +1691,11 @@
     </entry>
     <entry>
       <key>Customer</key>
+      <value>Kunde</value>
     </entry>
     <entry>
       <key>Outgoing</key>
+      <value>ausgehend</value>
     </entry>
     <entry>
       <key>Paraguay</key>
@@ -1862,6 +1868,7 @@
     </entry>
     <entry>
       <key>${ORGTYPE_OTHER}</key>
+      <value>Sonstiges</value>
     </entry>
     <entry>
       <key>Haiti</key>
@@ -1874,6 +1881,7 @@
     </entry>
     <entry>
       <key>waiting</key>
+      <value>warten auf Rückmeldung</value>
     </entry>
     <entry>
       <key>American Samoa</key>
@@ -1934,6 +1942,7 @@
     </entry>
     <entry>
       <key>Incoming</key>
+      <value>eingehend</value>
     </entry>
     <entry>
       <key>Ghana</key>
@@ -1985,6 +1994,7 @@
     </entry>
     <entry>
       <key>Supplier</key>
+      <value>Lieferant</value>
     </entry>
     <entry>
       <key>Nigeria</key>
@@ -2009,6 +2019,7 @@
     </entry>
     <entry>
       <key>Prospect</key>
+      <value>Potenzieller Kunde</value>
     </entry>
     <entry>
       <key>Estonia</key>
@@ -2039,6 +2050,7 @@
     </entry>
     <entry>
       <key>new</key>
+      <value>neu</value>
     </entry>
     <entry>
       <key>Adviser</key>
@@ -2369,6 +2381,7 @@
     </entry>
     <entry>
       <key>Internal</key>
+      <value>intern</value>
     </entry>
     <entry>
       <key>Brunei Darussalam</key>
@@ -2429,6 +2442,7 @@
     </entry>
     <entry>
       <key>${GENDER_OTHER}</key>
+      <value>Divers</value>
     </entry>
     <entry>
       <key>Touchpoint</key>
@@ -2479,6 +2493,7 @@
     </entry>
     <entry>
       <key>in process</key>
+      <value>in Bearbeitung</value>
     </entry>
     <entry>
       <key>Saint Martin (French part)</key>
@@ -2518,7 +2533,7 @@
     </entry>
     <entry>
       <key>ended</key>
-      <value></value>
+      <value>abgeschlossen</value>
     </entry>
     <entry>
       <key>Saint Barthélemy</key>
@@ -2644,6 +2659,7 @@
     </entry>
     <entry>
       <key>Checkbox</key>
+      <value></value>
     </entry>
     <entry>
       <key>Numeric value</key>
@@ -2665,6 +2681,7 @@
     </entry>
     <entry>
       <key>${NUMBER}</key>
+      <value>Zahl</value>
     </entry>
     <entry>
       <key>Name \&amp;quot;%0\&amp;quot; already used for container \&amp;quot;%1\&amp;quot;</key>
@@ -2728,6 +2745,28 @@
       <key>Print Offer</key>
       <value>Angebot drucken</value>
     </entry>
+    <entry>
+      <key>relations</key>
+    </entry>
+    <entry>
+      <key>Time</key>
+      <value>Zeit</value>
+    </entry>
+    <entry>
+      <key>New task</key>
+      <value>Neue Aufgabe</value>
+    </entry>
+    <entry>
+      <key>MyTasks</key>
+      <value>Meine Aufgaben</value>
+    </entry>
+    <entry>
+      <key>Show my tasks</key>
+      <value>Meine Aufgaben anzeigen</value>
+    </entry>
+    <entry>
+      <key>the specified key has to be unique for that container but does already exist</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 7a1809e94d1c8a8ce9acbec4d836ff7684a4254a..4c101a4c2c0ac238cf76b884496c4bd3ab3c1274 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -2388,6 +2388,27 @@
     <entry>
       <key>Days inactive</key>
     </entry>
+    <entry>
+      <key>Combobox Value</key>
+    </entry>
+    <entry>
+      <key>relations</key>
+    </entry>
+    <entry>
+      <key>Time</key>
+    </entry>
+    <entry>
+      <key>New task</key>
+    </entry>
+    <entry>
+      <key>MyTasks</key>
+    </entry>
+    <entry>
+      <key>Show my tasks</key>
+    </entry>
+    <entry>
+      <key>the specified key has to be unique for that container but does already exist</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/AttributeRelation/AttributeRelation.aod b/neonContext/AttributeRelation/AttributeRelation.aod
index 7e9ce7018b9378bf85def94c6f6ec4f0bdc8148e..3d56373fb0ac8111c7d1df0efc29eee8f5c1b36f 100644
--- a/neonContext/AttributeRelation/AttributeRelation.aod
+++ b/neonContext/AttributeRelation/AttributeRelation.aod
@@ -10,5 +10,9 @@
       <name>d21d2e1b-db79-4013-a056-6e9ce35a5757</name>
       <view>AttributeRelationFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>d2970ead-0da7-4fad-9f82-0c02fe85fe2c</name>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonContext/ObjectRelation/ObjectRelation.aod b/neonContext/ObjectRelation/ObjectRelation.aod
index 610ecc6e44d59d765957fde0ca29bb669befd723..763a754b47c69d0746663e2b28c48748487daaa0 100644
--- a/neonContext/ObjectRelation/ObjectRelation.aod
+++ b/neonContext/ObjectRelation/ObjectRelation.aod
@@ -19,5 +19,9 @@
       <name>30334c84-5e46-4a4e-a5c4-3c42d1cb109b</name>
       <view>ObjectRelationEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>cec4dc52-b38f-4f7c-b8ca-4b81ccda3ac1</name>
+      <view>Object1RelationFilter_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonContext/Organisation/Organisation.aod b/neonContext/Organisation/Organisation.aod
index 968ccbfe817a9cc274763fca03626b25ece07bfa..26e9b98ce2551670cd108cf2ad6cc54f7486eed9 100644
--- a/neonContext/Organisation/Organisation.aod
+++ b/neonContext/Organisation/Organisation.aod
@@ -31,13 +31,13 @@
       <name>bb592f88-fa9f-4ecc-98cc-51a7903dc970</name>
       <view>OrganisationAttr_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>b1634a51-b3f3-47b7-aea0-b9e8fba851da</name>
-      <view>OrganisationEditDefaults_view</view>
-    </neonViewReference>
     <neonViewReference>
       <name>27c1cd03-506a-4e1e-a080-79b9dca6eefd</name>
       <view>OrganisationLookup_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>0e8f983b-0ff6-431c-9118-fecd9563c742</name>
+      <view>OrganisationEditDefaults_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonView/AttributePreview_view/AttributePreview_view.aod b/neonView/AttributePreview_view/AttributePreview_view.aod
index 59adbab341fa443a18be81de0097635898b4fc31..f3e5d5fa9e51b0d3fedf0e8f0b07f37f8c561472 100644
--- a/neonView/AttributePreview_view/AttributePreview_view.aod
+++ b/neonView/AttributePreview_view/AttributePreview_view.aod
@@ -20,6 +20,10 @@
       <entityField>#ENTITY</entityField>
       <title></title>
       <fields>
+        <entityFieldLink>
+          <name>5f20a5d4-0343-4b8c-92bf-15eeb2483ba9</name>
+          <entityField>ATTRIBUTE_PARENT_ID</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>e00bfeb1-7003-4d5a-b71a-c6921e255c9d</name>
           <entityField>ATTRIBUTE_ACTIVE</entityField>
diff --git a/neonView/AttributeRelationEdit_view/AttributeRelationEdit_view.aod b/neonView/AttributeRelationEdit_view/AttributeRelationEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..b4c8d4ad85db22baaa90965b82fac2e75f090642
--- /dev/null
+++ b/neonView/AttributeRelationEdit_view/AttributeRelationEdit_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.0.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.1">
+  <name>AttributeRelationEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <genericMultipleViewTemplate>
+      <name>MultiEdit</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>3da856c1-6a5b-4fc3-aa41-0865b331a5e4</name>
+          <entityField>AB_ATTRIBUTE_ID</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>04dda499-d970-41d1-a524-5e354c0d2bfd</name>
+          <entityField>ATTRIBUTERELATION_VALUE</entityField>
+        </neonTableColumn>
+      </columns>
+    </genericMultipleViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/Object1RelationFilter_view/Object1RelationFilter_view.aod b/neonView/Object1RelationFilter_view/Object1RelationFilter_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..bd5d9de2901e7bcb490f61daef99819f696d9c1f
--- /dev/null
+++ b/neonView/Object1RelationFilter_view/Object1RelationFilter_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.0.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.1">
+  <name>Object1RelationFilter_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>Object2</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>9df2f22f-96ab-461e-af54-2dfdfa2de221</name>
+          <entityField>OBJECT2_ROWID</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>9df2f22f-96ab-461e-af54-2dfdfa7de221</name>
+          <entityField>EMPTY</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/OrgEditDefaults_view/OrgEditDefaults_view.aod b/neonView/OrganisationEditDefaults_view/OrganisationEditDefaults_view.aod
similarity index 84%
rename from neonView/OrgEditDefaults_view/OrgEditDefaults_view.aod
rename to neonView/OrganisationEditDefaults_view/OrganisationEditDefaults_view.aod
index 725872a478b159d9f03a1f8c15b2d05b135b373f..4c660f02d48e4fce4c8af45f2f21198c2cc3fd55 100644
--- a/neonView/OrgEditDefaults_view/OrgEditDefaults_view.aod
+++ b/neonView/OrganisationEditDefaults_view/OrganisationEditDefaults_view.aod
@@ -14,15 +14,15 @@
       <entityField>#ENTITY</entityField>
       <fields>
         <entityFieldLink>
-          <name>08c00d5b-fc5e-451b-8341-0e5c5172faa8</name>
+          <name>ccc421c9-3943-4668-a6c7-960753c38562</name>
           <entityField>ADDRESS_ID</entityField>
         </entityFieldLink>
         <entityFieldLink>
-          <name>8fac75ad-cde5-411c-b0ad-744b5aab0c5d</name>
+          <name>8625fb63-550c-4ad3-9b39-3091762e3f29</name>
           <entityField>STANDARD_EMAIL_COMMUNICATION</entityField>
         </entityFieldLink>
         <entityFieldLink>
-          <name>48722352-b85f-47d4-a6b1-dc87f9e9e6fc</name>
+          <name>a984c913-54e8-492e-928a-3553a1e76726</name>
           <entityField>STANDARD_PHONE_COMMUNICATION</entityField>
         </entityFieldLink>
       </fields>
diff --git a/neonView/OrganisationEdit_view/OrganisationEdit_view.aod b/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
index 98a781f875c112f8898b153c0acc936b66d172fd..3663da44374d333a97dddbdee952647333d17e74 100644
--- a/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
+++ b/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
@@ -52,5 +52,10 @@
       <entityField>Communications</entityField>
       <view>CommunicationMultiEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>2037ef93-6719-49af-9352-9ca3c03d6972</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/OrganisationMain_view/OrganisationMain_view.aod b/neonView/OrganisationMain_view/OrganisationMain_view.aod
index 804bbee490041b4c9eb72c6ec7b644071ff661bb..5fcec76945e9d274d53facb435b159b212b99989 100644
--- a/neonView/OrganisationMain_view/OrganisationMain_view.aod
+++ b/neonView/OrganisationMain_view/OrganisationMain_view.aod
@@ -50,5 +50,15 @@
       <entityField>ObjectRelations</entityField>
       <view>AnyObjectRelationFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>dc1aa0ca-d0bd-45fd-84dc-55cfcf3ca430</name>
+      <entityField>Salesprojects</entityField>
+      <view>SalesprojectFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>331f8519-f112-48c8-8430-85927dd0635e</name>
+      <entityField>TaskObjectRelations</entityField>
+      <view>Object1RelationFilter_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/PersonEdit_view/PersonEdit_view.aod b/neonView/PersonEdit_view/PersonEdit_view.aod
index f846c2c82867c21a3c16c9885c8cac3996c136a6..f284f32b2b819fa90d398b224cfa1c8db9dbeffe 100644
--- a/neonView/PersonEdit_view/PersonEdit_view.aod
+++ b/neonView/PersonEdit_view/PersonEdit_view.aod
@@ -70,5 +70,10 @@
       <entityField>Communications</entityField>
       <view>CommunicationMultiEdit_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>520f3056-2a24-4469-a86f-76ba80090829</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationEdit_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/PersonMain_view/PersonMain_view.aod b/neonView/PersonMain_view/PersonMain_view.aod
index c1585cf24ddda592508fed29d38aaf9d469926d1..93442d69e26e9db2feda7e0dc32b9613366468ff 100644
--- a/neonView/PersonMain_view/PersonMain_view.aod
+++ b/neonView/PersonMain_view/PersonMain_view.aod
@@ -39,5 +39,10 @@
       <entityField>ObjectRelations</entityField>
       <view>AnyObjectRelationFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>be48c6fe-1837-4c40-aef1-130fc1a5c544</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationFilter_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/TaskFilter_view/TaskFilter_view.aod b/neonView/TaskFilter_view/TaskFilter_view.aod
index 685009d266653d324a1b6368fe4d8d75aef30f93..8aec97e1e839ad21e9faa44c00b8e1d13a3d26d2 100644
--- a/neonView/TaskFilter_view/TaskFilter_view.aod
+++ b/neonView/TaskFilter_view/TaskFilter_view.aod
@@ -3,6 +3,23 @@
   <name>TaskFilter_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <filterable v="true" />
+  <dashletConfigurations>
+    <neonDashletConfiguration>
+      <name></name>
+      <title>MyTasks</title>
+      <description>Show my tasks</description>
+      <fragment>Task/filter</fragment>
+      <singleton v="true" />
+      <requiresConfiguration v="false" />
+      <icon>VAADIN:TASKS</icon>
+      <categories>
+        <neonDashletCategory>
+          <name>tasks</name>
+          <title>Tasks</title>
+        </neonDashletCategory>
+      </categories>
+    </neonDashletConfiguration>
+  </dashletConfigurations>
   <layout>
     <groupLayout>
       <name>layout</name>
diff --git a/others/db_changes/dashboardChangelog.xml b/others/db_changes/dashboardChangelog.xml
deleted file mode 100644
index e47788724f67f0e4f30e5cacd57747370332268a..0000000000000000000000000000000000000000
--- a/others/db_changes/dashboardChangelog.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.1" encoding="UTF-8" standalone="no"?>
-<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
-    <include file="data_alias/data/DASHLET_data.xml"/>
-    <include file="data_alias/data/DASHLETCONFIGURATION_data.xml"/>
-</databaseChangeLog>
diff --git a/others/db_changes/data_alias/data/DASHLETCONFIGURATION_data.xml b/others/db_changes/data_alias/data/DASHLETCONFIGURATION_data.xml
deleted file mode 100644
index c70a7012f5aa51beed3b322856ef841bb1bf8758..0000000000000000000000000000000000000000
--- a/others/db_changes/data_alias/data/DASHLETCONFIGURATION_data.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?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="m.escher" id="bd4a9ffe-64d6-4f2d-8006-a29947eba5741">
-        <delete tableName="ASYS_DASHLETCONFIGURATIONS"/>
-    </changeSet>
-</databaseChangeLog>
\ No newline at end of file
diff --git a/others/db_changes/data_alias/data/DASHLET_data.xml b/others/db_changes/data_alias/data/DASHLET_data.xml
deleted file mode 100644
index d7e2561fb92ca8ed0cda313aab3a1940d67be47e..0000000000000000000000000000000000000000
--- a/others/db_changes/data_alias/data/DASHLET_data.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?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="m.escher" id="1203e9e4-472b-48ac-9d6b-23ebae976beb">
-        <delete tableName="ASYS_DASHLETS"/>
-    </changeSet>
-</databaseChangeLog>
\ No newline at end of file
diff --git a/others/guide/how to copy objects with subitems.adoc b/others/guide/how to copy objects with subitems.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..63f85af69459e163f28844400e364f42d7ca8023
--- /dev/null
+++ b/others/guide/how to copy objects with subitems.adoc	
@@ -0,0 +1,100 @@
+How to make an action for copying modules
+=========================================
+:toc2: left
+:numbered:
+
+== What this guide is for ==
+You want to create an action or process that should copy a module with
+related sub-items.
+(for example: Offer + OfferItems, Order + OrderItems)
+
+== How to do it ==
+There are two possibilities when it comes to creating a new dataset based on another one:
+
+* Save it directly and open the created dataset in show-mode
+* Open it in new-mode so that the user can make changes first or cancel the action
+
+=== Save it directly ===
+This is relatively easy to do with the functions in the Neon_lib.
+At first you have make the copy with the method "CopyModuleUtils.copyModule". It requires an InputMapping object that
+defines the structure of the module. For example:
+
+[source, javascript]
+----
+var InputMapping = {
+    "OFFER": {
+            condition: "OFFERID = '" + vars.get("$field.OFFERID") + "'"
+            , ValueMapping: {
+                            "OFFER_ID": ""
+                            , "OFFERCODE":  OfferUtils.getNextOfferNumber()
+                            , "VERSNR": "1"
+                        }
+            , SubModules:{
+                "OFFERITEM": {
+                    condition: "OFFER_ID = '" + vars.get("$field.OFFERID") + "' order by ITEMSORT" 
+            }
+        }
+    }
+}
+----
+
+The root element of the object (in this case 'OFFER') defines what module is copied, the condition is used to select the specific dataset.
+'ValueMapping' should be used when some fields need new values (for example the offercode should not be the same as in the copied object).
+You can also set 'SubModules' in order to copy sub-elements like offerItems.
+Now you just have to use the following code:
+
+[source, javascript]
+----
+var ModulesMapping = CopyModuleUtils.copyModule(InputMapping);
+
+CopyModuleUtils.openNewModules("Offer", ModulesMapping);
+----
+
+The first line copies the module and the second line opens the newly created dataset.
+
+=== Open it in new-mode first ===
+For this case it needs a few more steps. For values that should be preset in the edit view, you will need to create
+parameters in the entity for every one (set them exposed, triggerRecalculation and not mandatory). After that you have to use these parameters in the valueProcess of the fields
+they should fill. 
+The next step is to create an action that opens the context in new-mode. That could look like this:
+
+[source, javascript]
+----
+var params = {
+    "ContactId_param" : vars.get("$field.CONTACT_ID"),
+    "SalesprojectId_param" : vars.get("$field.SALESPROJECT_ID"),
+    "OfferLanguage_param" : vars.get("$field.LANGUAGE"),
+    "OfferOriginal_Id_param" : vars.get("$field.OFFERID"),
+    "OfferCode_param" : vars.get("$field.OFFERCODE"),
+    "OfferVersnr_param" : OfferUtils.getNextOfferVersionNumber(vars.get("$field.OFFERCODE")),
+    "OfferCurrency_param" : vars.get("$field.CURRENCY"),
+    "OfferAddress_param" : vars.get("$field.ADDRESS"),
+    "OfferHeader_param" : vars.get("$field.HEADER")
+}
+neon.openContext("Offer", null, null, neon.OPERATINGSTATE_NEW, params);
+----
+
+Important: There has to be one parameter for the id, so that sub-items can be copied (see the following).
+
+Now we can preset values of the module, but what about related things like offerItems?
+For that we use the same function as in the section above. Because the offerItems should only be copied to the new offer when the user
+saved it, this has to be done in the onInsert-process of the recordcontainer.
+
+[source, javascript]
+----
+if (vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.OfferOriginal_Id_param"))
+{
+    var InputMapping = {
+        "OFFERITEM": {
+            condition: "OFFER_ID = '" + vars.getString("$param.OfferOriginal_Id_param") + "' order by ITEMSORT",
+            ValueMapping: {
+                "OFFER_ID" : vars.get("$field.OFFERID")
+            }
+        }
+    };
+    CopyModuleUtils.copyModule(InputMapping);
+}
+----
+
+The offer is already created, so that only offerItem is needed in the 'InputMapping'. The 'condition' should use the id of the offer
+that is copied and in 'ValueMapping' the foreign-key 'OFFER_ID' gets the value of the id of the newly created offer.
\ No newline at end of file
diff --git a/process/Attribute_lib/process.js b/process/Attribute_lib/process.js
index 7fdcc7c68792930a848c0b46a65caf996eb6a9b8..755d9c190519f25facadb77f0c98302f89293b33 100644
--- a/process/Attribute_lib/process.js
+++ b/process/Attribute_lib/process.js
@@ -5,8 +5,8 @@ import("system.db");
 import("Sql_lib");
 
 /**
- * Provides functions for the work with attributes, like setting or getting the value of an attribute
- * or listing the available attributes for a context.
+ * Provides functions for the work with attributes, like
+ * listing the available attributes for a context.
  * Don't instanciate this!
  * 
  * @class
@@ -91,14 +91,55 @@ AttributeUtil.getSimpleAttributeName = function (pAttributeId)
 }
 
 /**
- * gets the value of an attribute for one dataset (e. g. a person)
+ * returns the ids of all subordinated attributes of an attribute
+ * 
+ * @param {String} pAttributeId the id of the attribute
+ * 
+ * @result {String[]} array with the ids of every subordinated attribute
  */
-AttributeUtil.getAttribute = function (pAttributeId, pObjectType, pObjectRowId, pGetIdValue)
+AttributeUtil.getAllChildren = function (pAttributeId)
 {
-    //TODO: implement
+    var childIds = [];
+    var attributes= [pAttributeId];
+    while (attributes.length > 0)
+    {
+        attributes = db.array(db.COLUMN, SqlCondition.begin()
+            .and("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID in ('" + attributes.join("','") + "')")
+            .buildSql("select AB_ATTRIBUTEID from AB_ATTRIBUTE")
+        );
+        if (attributes.length > 0)
+            childIds = childIds.concat(attributes);
+    }
+    return childIds;
+}
+
+/*********************************************************************************************************************/
+
+/**
+ * Provides functions for the work with attributeRelations, getting the value of an attributeRelation for an object.
+ * Don't instanciate this!
+ * 
+ * @class
+ */
+function AttributeRelationUtils () {}
+
+/**
+ * gets the value of an attributeRelation for one dataset (e. g. a person)
+ */
+AttributeRelationUtils.getAttribute = function (pAttributeId, pObjectRowId, pObjectType)
+{
+    var attrCond = SqlCondition().begin()
+        .andPrepare("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId)
+        .andPrepare("AB_ATTRIBUTERELATION.OBJECT_ROWID", pObjectRowId);
+    if (pObjectType != null)
+        attrCond.andPrepare("AB_ATTRIBUTERELATION.OBJECT_TYPE", pAttributeId);
+    
+    var attrSql = AttributeRelationUtils.getSqlUtil();
+    var attributeValues = db.array(db.ROW, attrCond.buildSql(attrSql.sqlSelect));
+    return attrSql.getFieldFromType(attributeValues);
 }
 
-AttributeUtil.getAttributes = function ()
+AttributeRelationUtils.getAttributes = function ()
 {
     //TODO: implement maybe
 }
@@ -106,11 +147,62 @@ AttributeUtil.getAttributes = function ()
 /**
  * sets the value of an attribute for one dataset (e. g. a person)
  */
-AttributeUtil.setAttribute = function ()
+AttributeRelationUtils.setAttribute = function ()
 {
     //TODO: implement
 }
 
+/**
+ * Builds an object for the work with the values of attributeRelations. This should make
+ * the attribute type definition more flexible, the returned object has the following properties
+ * and methods:
+ *
+ * columns = array of all database columns in AB_ATTRIBUTERELATION that hold attribute values
+ * typeColMap = object with the attribute type as key and the index in the columns-array with the column holding
+ *      the value for that attribute type as value
+ * sqlSelect = an sql-select string where the columns are the type of the attribute plus the value columns
+ * getFieldFromType = a method that takes a one-dimensional array that has been created with a query using the 'sqlSelect' property
+ *      and returns the value at the right position of that array depending on the type. For example:
+ *                      //type,   values
+ *          vals = ["TEXT", "abcdef", "", "", "", ""];
+ *      the method would return "abcdef", because it looks at the first position where the type is, e. g. "TEXT"
+ *      and then it gets the value at, for example, index 1 because the typeColMap object says that the value for type "TEXT"
+ *      is at position 1.
+ * 
+ */
+AttributeRelationUtils.getSqlUtil = function ()
+{
+    var types = Object.keys($AttributeTypes);
+    var sqlMap = {
+        columns : [],
+        typeColMap : {}
+    };
+    types.forEach(function (type)
+    {
+        var typeKey = type.toString();
+        var colIndex = this.columns.indexOf(type.databaseField);
+        if (colIndex == -1)
+        {
+            colIndex = this.columns.length;
+            this.columns.push(type.databaseField);
+        }
+        this.typeColMap[typeKey] = colIndex;
+    }, sqlMap);
+    
+    sqlMap.sqlSelect = "select ATTRIBUTE_TYPE, " + sqlMap.columns.join(", ") + " from AB_ATTRIBUTERELATION "
+        + " join AB_ATTRIBUTE on AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID ";
+    
+    sqlMap.getFieldFromType = function (pTypeAndValues)
+    {
+        if (pTypeAndValues.length > 0)
+            return pTypeAndValues[this.typeColMap[pTypeAndValues[0]] + 1];
+        return null;
+    }
+    
+    return sqlMap;
+}
+
+/*********************************************************************************************************************/
 
 /**
  * This is used in the AttributeRelation enitiy to make the work with attributes there
@@ -195,6 +287,7 @@ AttributeHandler.prototype.setAttributeValue = function (pValue)
  * should be done in AttributeUtils.
  * The values for each type are:
  * 
+ * keyword = the key of the corresponding keyword
  * contentType = the value that is returned in the contentType process for the attribute
  * databaseField = the database field that holds values of attributes with the type
  * entityField = the field in the AttributeRelation enity that holds the value of the attribute for that type
diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js
index db0117bcd46b02c19229b2f367da8645e88f5ee7..058f498fa6c9b9fbff0404cc52c957ee07fc974c 100644
--- a/process/Context_lib/process.js
+++ b/process/Context_lib/process.js
@@ -1,3 +1,5 @@
+import("system.logging");
+import("system.translate");
 import("system.project");
 import("system.vars");
 import("system.SQLTYPES");
@@ -116,10 +118,20 @@ ContextUtils._getSelectMap = function()
 //        "Appointment": ["SUMMARY", "ASYS_CALENDARBACKEND", "UID"]
         "Offer": [maskingUtils.cast("OFFERCODE", SQLTYPES.VARCHAR, 10), "OFFER", "OFFERID"],
         "Order": [maskingUtils.cast("SALESORDERCODE", SQLTYPES.VARCHAR, 10), "SALESORDER", "SALESORDERID"],
-        "Product": ["PRODUCTNAME", "PRODUCT", "PRODUCTID"]
+        "Product": ["PRODUCTNAME", "PRODUCT", "PRODUCTID"],
+        "Task": ["SUBJECT", "TASK", "TASKID", translate.text("Task")]
     }
 }
 
+ContextUtils.getFieldTitle = function(pContextId, pDefault)
+{
+    if (ContextUtils._getSelectMap()[pContextId] != undefined && ContextUtils._getSelectMap()[pContextId].length >= 3)
+        return ContextUtils._getSelectMap()[pContextId][3];
+    
+    return pDefault;
+}
+
+
 /**
  * TODO: !!!temporary function until you can get fields from another Entity!!!
  */
diff --git a/process/Money_lib/Money_lib.aod b/process/Money_lib/Money_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..61248fd244213806e7a23ebd44d8353bed49dc4b
--- /dev/null
+++ b/process/Money_lib/Money_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.1.7" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.1.7">
+  <name>Money_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/Money_lib/process.js</process>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/Money_lib/process.js b/process/Money_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..1b59e2d69db667b7904c12747574f8c20ed65ae8
--- /dev/null
+++ b/process/Money_lib/process.js
@@ -0,0 +1,70 @@
+import("system.logging");
+import("system.eMath");
+
+/**
+ * Class containing static utility functions for working with money
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function MoneyUtils() {}
+
+/**
+ * round a price with eMath.ROUND_HALF_UP
+ * @param {Double} pPrice
+ * 
+ * @return rounded price
+ */
+MoneyUtils.round = function(pPrice) 
+{
+    return eMath.roundDec(pPrice, 2, eMath.ROUND_HALF_UP);
+}
+
+/**
+ * get net price
+ * @param {Double} pPrice
+ * @param {Double} [pQuantity=0.0]
+ * @param {Double} [pDiscount=0.0]
+ * 
+ * @return net of price
+ */
+MoneyUtils.getNet = function(pPrice, pQuantity, pDiscount) 
+{
+    pQuantity = pQuantity || 0;
+    pDiscount = pDiscount || 0;
+    return MoneyUtils.round(pPrice * pQuantity * (100 - pDiscount) / 100);
+}
+
+/**
+ * get vat of a price
+ * @param {Double} pVat
+ * @param {Double} pPrice
+ * @param {Double} [pQuantity=0.0]
+ * @param {Double} [pDiscount=0.0]
+ * 
+ * @return vat of price
+ */
+MoneyUtils.getVat = function(pVat, pPrice, pQuantity, pDiscount) 
+{
+    pQuantity = pQuantity || 0;
+    pDiscount = pDiscount || 0;
+    
+    return MoneyUtils.round(pPrice * pQuantity * (100 - pDiscount) / 100 * pVat / 100);
+}
+
+/**
+ * get gross of a price
+ * @param {Double} pVat
+ * @param {Double} pPrice
+ * @param {Double} [pQuantity=0.0]
+ * @param {Double} [pDiscount=0.0]
+ * 
+ * @return gross of price
+ */
+MoneyUtils.getGross = function(pVat, pPrice, pQuantity, pDiscount) {
+    
+    pQuantity = pQuantity || 0;
+    pDiscount = pDiscount || 0;
+    
+    return eMath.addDec(MoneyUtils.getNet(pPrice, pQuantity, pDiscount), MoneyUtils.getVat(pVat, pPrice, pQuantity, pDiscount));
+}
\ No newline at end of file
diff --git a/process/Neon_lib/process.js b/process/Neon_lib/process.js
index c811a8f7be0193ac7efff4c6f214d742caebbb3d..65e019d7c4c2bc5f6789467daf8e527f652eccab 100644
--- a/process/Neon_lib/process.js
+++ b/process/Neon_lib/process.js
@@ -153,6 +153,7 @@ CopyModuleUtils.copyModule = function(pInputMapping)
         var rootModule = Object.keys(pInputMapping)[0];
         var ModuleMapping = _ModuleMapping(rootModule, pInputMapping[rootModule]);
         var ModuleData = _getModuleData(rootModule, pInputMapping[rootModule].condition);
+        ModulesMapping[rootModule] = ModuleMapping;
 
         for(var row in ModuleData)
         {
@@ -282,7 +283,7 @@ CopyModuleUtils.copyModule = function(pInputMapping)
                 case "OFFERITEM":
                 {
                     //OFFER_ID mappen
-                    if(ModuleRowMapping.ParentModuleMapping.name == "OFFER")
+                    if(ModuleRowMapping.ParentModuleMapping != null && ModuleRowMapping.ParentModuleMapping.name == "OFFER")
                     {
                         ModuleRowMapping.ColumnMapping["OFFER_ID"].newValue = ModulesMapping[ModuleRowMapping.ParentModuleMapping.name].DataRows[ModuleRowMapping.ColumnMapping["OFFER_ID"].oldValue].newPrimaryKey;
                     }
diff --git a/process/OfferOrder_lib/process.js b/process/OfferOrder_lib/process.js
index cb1dc57b42c964b43850f223dfaee60a8aff5789..d96c87ce756caa5319eac5ad3ddba88aa09625e1 100644
--- a/process/OfferOrder_lib/process.js
+++ b/process/OfferOrder_lib/process.js
@@ -6,6 +6,7 @@ import("system.util");
 import("system.eMath");
 import("system.db");
 import("Product_lib");
+import("Money_lib");
 
 /**
  * Abstract class that provides methods for dealing with offer / order items.
@@ -163,8 +164,8 @@ ItemUtils.prototype.getNetAndVat = function(itemIds) {
 
     for (var i = 0; i < orderItems.length; i++)
     {
-        sum += this.getItemSum(orderItems[i][0], orderItems[i][1], orderItems[i][2], orderItems[i][4]);
-        vat += this.getItemVAT(orderItems[i][0], orderItems[i][1], orderItems[i][2], orderItems[i][3], orderItems[i][4]);
+        sum = eMath.addDec(sum, this.getItemSum(orderItems[i][0], orderItems[i][1], orderItems[i][2], orderItems[i][4]));
+        vat = eMath.addDec(vat, this.getItemVAT(orderItems[i][0], orderItems[i][1], orderItems[i][2], orderItems[i][3], orderItems[i][4]));
     }
 
     return [sum, vat];
@@ -200,33 +201,33 @@ ItemUtils.prototype.initItemTree = function() {
 /**
  * @abstract
  */
-ItemUtils.prototype.getItemSum = function(quantity, price, discount, optional) {
-    quantity = quantity || 0;
-    price = price || 0;
-    discount = discount || 0;
+ItemUtils.prototype.getItemSum = function(pQuantity, pPrice, pDiscount, pOptional) {
+    pQuantity = pQuantity || 0;
+    pPrice = pPrice || 0;
+    pDiscount = pDiscount || 0;
 
-    return optional ? (parseFloat(quantity) * parseFloat(price) * ((100 - parseFloat(discount)) / 100))
+    return pOptional == "0" ? (MoneyUtils.getNet(parseFloat(pPrice), parseFloat(pQuantity), parseFloat(pDiscount)))
                     : 0;
 }
 
 /**
  * @abstract
  */
-ItemUtils.prototype.getItemVAT = function(quantity, price, discount, vat, optional) {
-    quantity = quantity || 0;
-    price = price || 0;
-    discount = discount || 0;
-    vat = vat || 0;
-
-    return optional ? (parseFloat(quantity) * parseFloat(price) * ((100 - parseFloat(discount)) / 100) * (parseFloat(vat) / 100)) 
+ItemUtils.prototype.getItemVAT = function(pQuantity, pPrice, pDiscount, pVat, pOptional) {
+    pQuantity = pQuantity || 0;
+    pPrice = pPrice || 0;
+    pDiscount = pDiscount || 0;
+    pVat = pVat || 0;
+    logging.log(pOptional.toSource())
+    return pOptional == "0" ? (MoneyUtils.getVat(parseFloat(pVat), parseFloat(pPrice), parseFloat(pQuantity), parseFloat(pDiscount))) 
                     : 0;
 }
 
 /**
  * @abstract
  */
-ItemUtils.prototype.roundPrice = function(price) {
-    return eMath.roundDec(price, 2, eMath.ROUND_HALF_UP);
+ItemUtils.prototype.roundPrice = function(pPrice) {
+    return MoneyUtils.round(pPrice);
 }
 
 /**
diff --git a/process/Offer_lib/process.js b/process/Offer_lib/process.js
index 6f7515d1036833af71835a986d51e50568178501..716a56fb2ae06122dde7cf8903132805185f100f 100644
--- a/process/Offer_lib/process.js
+++ b/process/Offer_lib/process.js
@@ -13,6 +13,7 @@ import("Product_lib");
 import("Report_lib");
 import("OfferOrder_lib");
 import("PostalAddress_lib");
+import("Neon_lib");
 
 /**
  * Methods used by Offer.
@@ -273,6 +274,54 @@ OfferUtils.openOfferReport = function(pOfferID)
     offerReport.openReport();
 }
 
+/**
+ * opens an offer in NEW mode with values from an offer
+ * 
+ * @param pOfferId {String} id of the offer
+ * @param pContactId {String} contact id
+ * @param pLanguage {String} language
+ * @param pCurrency {String} [currency=""]
+ * @param pHeader {String} [header=""]
+ */
+OfferUtils.copyOffer = function (pOfferId, pContactId, pLanguage, pCurrency, pHeader)
+{
+    var params = {
+        "ContactId_param" : pContactId,
+        "OfferLanguage_param" : pLanguage,
+        "OfferOriginal_Id_param" : pOfferId,
+        "OfferCurrency_param" : pCurrency || "",
+        "OfferHeader_param" : pHeader || ""
+    };
+    neon.openContext("Offer", null, null, neon.OPERATINGSTATE_NEW, params);
+}
+
+/**
+ * copies all offerItems from one offer to another
+ * 
+ * @param {String} pSourceOfferId
+ * @param {String} pTargetOfferId
+ */
+OfferUtils.copyOfferItems = function (pSourceOfferId, pTargetOfferId)
+{
+    var InputMapping = {
+        "OFFERITEM": {
+            condition: "OFFER_ID = '" + pSourceOfferId + "' order by ITEMSORT",
+            ValueMapping: {
+                "OFFER_ID" : pTargetOfferId
+            }
+        }
+    };
+    CopyModuleUtils.copyModule(InputMapping);
+    
+    var oiUtils = new OfferItemUtils(pTargetOfferId);
+    
+    //update order price
+    cols = ["NET", "VAT"];
+    var vals = oiUtils.getNetAndVat();
+    
+    db.updateData("OFFER", cols, null, vals, SqlCondition.equals("OFFER.OFFERID", pTargetOfferId, "1 = 2"));
+}
+
 /**
  * opens an order in NEW mode with values from an offer
  * 
diff --git a/process/Order_lib/process.js b/process/Order_lib/process.js
index 0c927b0ed370eb84461c5b0d40ee5c5b69f1a08e..818de7d7027bb5c0994fe4ae5743764e5a69c31f 100644
--- a/process/Order_lib/process.js
+++ b/process/Order_lib/process.js
@@ -82,62 +82,36 @@ OrderUtils.createNewOrder = function(pSalesprojectId, pRelationId)
  * 
  * @param {String} pOfferId the offer to get the items from
  * @param {String} pOrderId the order to create the items for
- * 
- * @return {Number[]} Array with the ids of the inserted orderItems
  */
 OrderUtils.copyOfferItemsToOrder = function (pOfferId, pOrderId)
 {
-    var cols = [
-        "UNIT", 
-        "QUANTITY", 
-        "GROUPCODEID", 
-        "ASSIGNEDTO", 
-        "PRICE", 
-        "ITEMSORT", 
-        "PRODUCT_ID", 
-        "VAT", 
-        "ITEMNAME", 
-        "OPTIONAL", 
-        "DISCOUNT", 
-        "ITEMPOSITION", 
-        "INFO"
-    ];
-    var offerItemSql = SqlCondition.begin()
-        .andPrepare("OFFERITEM.OFFER_ID", pOfferId)
-        .buildSql("select " + cols.concat(["OFFERITEMID"]).join(", ") + " from OFFERITEM", "1=0");
-    var offerItems = db.table(offerItemSql);
-
-    var table = "SALESORDERITEM";
-    cols = cols.concat(["SALESORDERITEMID", "SALESORDER_ID"]);
-    var types = db.getColumnTypes(table, cols);
-    
-    //the rows need new UIDs, but because items can be related over ASSIGNEDTO, ASSIGNEDTO must also be 
-    //changed to the newly generated id of the parent item, so the "oldId : newId" pairs have to be stored
-    //to set ASSIGNEDTO correctly
-    var idMap = {}; 
-    
-    var toInsert = [];
-    while (offerItems.length > 0)
-        for (let i = 0; i < offerItems.length; i++)
-        {
-            var row = offerItems[i];
-            
-            //checks if the parent attribute has already been put into the insert-array,
-            //otherwise the foreign-key ASSIGNEDTO could have the id of a row that hasn't been inserted yet
-            // -> toInsert needs to be in the correct order
-            if (row[3] == "" || row[3] in idMap)
-            {
-                row[3] = idMap[row[3]] || "";
-                var newId = util.getNewUUID();
-                idMap[row[13]] = newId;
-                row[13] = newId; //replace the UID
-                toInsert.push([table, cols, types, row.concat([pOrderId])]);
-                offerItems.splice(i, 1); //remove the row from offerItems
-                i--;
+    var InputMapping = {
+        "OFFERITEM": {
+            destinationModuleName : "SALESORDERITEM",
+            DestinationColumnMapping : {
+                "OFFERITEMID" : "SALESORDERITEMID",
+                "ITEMPOSITION" : "ITEMPOSITION", 
+                "GROUPCODEID" : "GROUPCODEID", 
+                "OFFER_ID" : "SALESORDER_ID",
+                "ASSIGNEDTO" : "ASSIGNEDTO", 
+                "PRODUCT_ID" : "PRODUCT_ID", 
+                "QUANTITY" : "QUANTITY", 
+                "ITEMSORT" : "ITEMSORT", 
+                "ITEMNAME" : "ITEMNAME", 
+                "OPTIONAL" : "OPTIONAL", 
+                "DISCOUNT" : "DISCOUNT", 
+                "PRICE" : "PRICE", 
+                "UNIT" : "UNIT", 
+                "INFO" : "INFO",
+                "VAT" : "VAT"
+            },
+            condition: "OFFER_ID = '" + pOfferId + "' order by ITEMSORT",
+            ValueMapping: {
+                "OFFER_ID" : pOrderId
             }
         }
-    
-    db.inserts(toInsert);
+    };
+    CopyModuleUtils.copyModule(InputMapping);
     
     var oiUtils = new OrderItemUtils(pOrderId);
     
@@ -146,11 +120,6 @@ OrderUtils.copyOfferItemsToOrder = function (pOfferId, pOrderId)
     var vals = oiUtils.getNetAndVat();
     
     db.updateData("SALESORDER", cols, null, vals, SqlCondition.equals("SALESORDER.SALESORDERID", pOrderId, "1 = 2"));
-    
-    return Object.keys(idMap).map(function (id) 
-    {
-        return idMap[id];
-    });
 }
 
 
diff --git a/process/Salesproject_lib/process.js b/process/Salesproject_lib/process.js
index 3ca5cd3d006d00d888830cf349654874a82ee57d..479848b10d7f01270ceddc1a6456d9a040897b96 100644
--- a/process/Salesproject_lib/process.js
+++ b/process/Salesproject_lib/process.js
@@ -56,7 +56,7 @@ Salesproject.insertMilestone = function(salesprojectId, type, value, notifyForec
             [util.getNewUUID(), salesprojectId, type, value, vars.get("$sys.date")]);
             
         if (notifyForecast) {
-            this.notifyToUpdateForecast()
+            Salesproject.notifyToUpdateForecast()
         }
         return true;
     }
diff --git a/process/Timetracking_lib/process.js b/process/Timetracking_lib/process.js
index 664d6574bedc18c220cea42395ecf787791d5e83..d2128cd195542977845b87086fe6bc0da1f74520 100644
--- a/process/Timetracking_lib/process.js
+++ b/process/Timetracking_lib/process.js
@@ -44,4 +44,19 @@ Timetracking.createNewTimeTracking = function (pRowId)
     };
     
     neon.openContext("Timetracking", null, null, neon.OPERATINGSTATE_NEW, params);
+}
+
+/*
+ * converts minutes tho hours and minuets. e.g. 105 to 1:45
+ * 
+ * @param {integer} pMinutes req 
+ * 
+ * @return {String} Hours:Minutes
+ */
+Timetracking.minutesToReadableHour = function(pMinutes) 
+{
+    var timeHour = parseInt(pMinutes / 60);
+    var minutes = parseInt(pMinutes % 60);
+    
+    return "" + timeHour + ":" + ((minutes <= 9) ? "0" + minutes : minutes);
 }
\ No newline at end of file