diff --git a/.liquibase/Data_alias/basic/2020.0.2/Memberroles/extend_keword_memberroles.xml b/.liquibase/Data_alias/basic/2020.0.2/Memberroles/extend_keword_memberroles.xml
index 83e825733c4970c00e13f6f072a06b263a858869..05e3ec24cb9cdeac9f10dabc1fdd674b7650ef1f 100644
--- a/.liquibase/Data_alias/basic/2020.0.2/Memberroles/extend_keword_memberroles.xml
+++ b/.liquibase/Data_alias/basic/2020.0.2/Memberroles/extend_keword_memberroles.xml
@@ -1,6 +1,6 @@
 <?xml version="1.1" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
-    <changeSet author="s.pongratz" id="28627941-6c9b-46e8-922a-b4660b33723c">
+    <changeSet author="s.pongratz" id="c30bc71b-fcef-4ae6-9356-207adaca9dbd">
         <!--Atribute-->
         <insert tableName="AB_KEYWORD_ATTRIBUTE">
             <column name="AB_KEYWORD_ATTRIBUTEID" value="08fcb5db-531d-4a83-8c6e-b9c9c95dcb16"/>
diff --git a/.liquibase/Data_alias/basic/2020.2.3/Offer/addColumnOffer.xml b/.liquibase/Data_alias/basic/2020.2.3/Offer/addColumnOffer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1ae38fd53a3e8cd90aa3ae2a373c704004c016f7
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2020.2.3/Offer/addColumnOffer.xml
@@ -0,0 +1,16 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="s.garb" id="995a11c7-fb16-4c33-b5ad-0c35f44905c3">
+        <addColumn tableName="OFFER">
+            <column name="DISCOUNT"  type="NUMERIC(14,2)" />
+            <column name="DISCOUNTED_NET"  type="NUMERIC(14,2)" />
+        </addColumn>
+    </changeSet> 
+    <changeSet author="s.garb" id="801708bd-91f0-4468-bed9-0bbab7e46997">
+        <addColumn tableName="OFFER">
+            <column name="DISCOUNTED_VAT"  type="NUMERIC(14,2)" />
+        </addColumn>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2020.2.3/Offer/changelog.xml b/.liquibase/Data_alias/basic/2020.2.3/Offer/changelog.xml
new file mode 100644
index 0000000000000000000000000000000000000000..86ddb71fe50db74127c2f6397e78cfffbacf5740
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2020.2.3/Offer/changelog.xml
@@ -0,0 +1,6 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <include file="addColumnOffer.xml" relativeToChangelogFile="true" />
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2020.2.3/changelog.xml b/.liquibase/Data_alias/basic/2020.2.3/changelog.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c2a68fc34547cb7edcb594b4a2e5eccac52948b0
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2020.2.3/changelog.xml
@@ -0,0 +1,5 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <include relativeToChangelogFile="true" file="Offer/changelog.xml"/>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/changelog.xml b/.liquibase/Data_alias/changelog.xml
index 3f25ca1dbb1f91ed6ec3330368189a268665602b..71e32bf0790de16fb02e4c71968f5749a36ffffe 100644
--- a/.liquibase/Data_alias/changelog.xml
+++ b/.liquibase/Data_alias/changelog.xml
@@ -18,6 +18,7 @@
     <include relativeToChangelogFile="true" file="basic/2020.2.0/changelog.xml"/>
     <include relativeToChangelogFile="true" file="basic/2020.2.1/changelog.xml"/>
     <include relativeToChangelogFile="true" file="basic/2020.2.2/changelog.xml"/>
+    <include relativeToChangelogFile="true" file="basic/2020.2.3/changelog.xml"/>
 
     <!--enable this only when you definetly want to overwrite the existing data with demo records:-->
     <!--<include relativeToChangelogFile="true" file="basic/_demoData/changelog.xml" context="example"/>-->
diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod
index 1b90bea7f650ec646579634c155ced038fcf0d35..dbca10b0c0e70175cf3fdec1d3809a2fd5080360 100644
--- a/aliasDefinition/Data_alias/Data_alias.aod
+++ b/aliasDefinition/Data_alias/Data_alias.aod
@@ -3108,6 +3108,48 @@
                 <title></title>
                 <description></description>
               </entityFieldDb>
+              <entityFieldDb>
+                <name>DISCOUNT</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="3" />
+                <size v="14" />
+                <scale v="2" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>DISCOUNTED_NET</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="3" />
+                <size v="14" />
+                <scale v="2" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>DISCOUNTED_VAT</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="3" />
+                <size v="14" />
+                <scale v="2" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
             </entityFields>
           </entityDb>
           <entityDb>
diff --git a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
index 9e61fe62da309c52a87c237fe3b5b2f0ebbec31a..adb51ef4372f7731293b2be3e1ca1360a9bd83b5 100644
--- a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
+++ b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
@@ -38,10 +38,6 @@
                 <name>Task</name>
                 <kind v="10077" />
               </entityNode>
-              <entityNode>
-                <name>Favorite</name>
-                <kind v="10077" />
-              </entityNode>
             </childNodes>
           </entityNode>
         </childNodes>
diff --git a/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js b/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
index 0764eff7f7bb307932d6c09366ff99f6431a1114..3d9c6d75f1d5026e6e31e985752e51b6a88a9262 100644
--- a/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
+++ b/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
@@ -4,11 +4,22 @@ import("system.result");
 var res = { 
     "Offer": {}, 
     "Order": {
-        "setGroupBy":"ORDERTYPE"
+        "setGroupBy":"ORDERTYPE",
+        "groupByKeyword":"OrderType"
     }, 
     "Contract": {}, 
-    "SupportTicket": {},
-    "Campaign": {}
-}
+    "SupportTicket": {        
+        "subContext":"TaskLink",
+        "childField":"TASK_ID",
+        "parentField":"TASK_TASKID",
+        "contactIdField":"OBJECT_ROWID"
+    },
+    "Campaign": {        
+        "subContext":"CampaignParticipant",
+        "childField":"CAMPAIGN_ID",
+        "parentField":"CAMPAIGNID",
+        "contactIdField":"CONTACT_ID"
+    }
+};
 
-result.string(JSON.stringify(res))
\ No newline at end of file
+result.string(JSON.stringify(res));
\ No newline at end of file
diff --git a/entity/Activity_entity/entityfields/msteamsactions/stateProcess.js b/entity/Activity_entity/entityfields/msteamsactions/stateProcess.js
index 828bf3fc5838fa000ec45ce424e0b3d9e16aeae8..2708ddc1ec8a3c626e049d0956bd4b116ed2c10b 100644
--- a/entity/Activity_entity/entityfields/msteamsactions/stateProcess.js
+++ b/entity/Activity_entity/entityfields/msteamsactions/stateProcess.js
@@ -4,4 +4,4 @@ import("system.result");
 import("MSTeams_lib");
 
 var isTeamsEnabled = vars.get("$param.ObjectId_param") in MSTeamsUtils.getTeamLinkContexts() && MSTeamsUtils.isTeamsEnabled();
-result.string(/*isTeamsEnabled ? neon.COMPONENTSTATE_EDITABLE : */neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
+result.string(isTeamsEnabled ? neon.COMPONENTSTATE_EDITABLE : neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Activity_entity/entityfields/newoffer/onActionProcess.js b/entity/Activity_entity/entityfields/newoffer/onActionProcess.js
index 2973002c2cfac6ea1cf0ff1bc79b0c50aa31d5db..73cd9c4d17edf67a358563f95030f6ce963e1859 100644
--- a/entity/Activity_entity/entityfields/newoffer/onActionProcess.js
+++ b/entity/Activity_entity/entityfields/newoffer/onActionProcess.js
@@ -1,4 +1,21 @@
+import("Sql_lib");
 import("system.vars");
 import("Offer_lib");
 
-OfferUtils.createNewOffer(null, null, null, vars.get("$field.ACTIVITYID"));
\ No newline at end of file
+var activityId = vars.get("$field.ACTIVITYID");
+var activityLinks = newSelect("ACTIVITYLINK.OBJECT_TYPE, ACTIVITYLINK.OBJECT_ROWID")
+                                .from("ACTIVITYLINK")
+                                .where("ACTIVITYLINK.ACTIVITY_ID", activityId)
+                                .and("ACTIVITYLINK.OBJECT_TYPE", ["Person", "Organisation", "Salesproject"], SqlBuilder.IN())
+                                .table();
+
+//make a map from the 2d-array to easily access the ids by objectType
+var linkMap = new Map(activityLinks);
+
+//if we only have one Person: that person is the contact.
+//otherwise: we check for organisations: if we only have one then we use that one.
+//same logic for salesprojects: if we have only one: use that one
+var contactId = linkMap.get("Person") || linkMap.get("Organisation");
+var salesprojectId = linkMap.get("Salesproject");
+
+OfferUtils.createNewOffer("Salesproject", salesprojectId, contactId, activityId);
\ No newline at end of file
diff --git a/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js b/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js
index 9a5657456f3a131ca47d303d21a17b46ada862d1..f782309d32349f8320ada9dd3aa91588f3069e4e 100644
--- a/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js
+++ b/entity/Analyses_entity/entityfields/imminent_appointments/valueProcess.js
@@ -1,3 +1,4 @@
+import("system.tools");
 import("system.SQLTYPES");
 import("system.db");
 import("system.datetime");
@@ -8,45 +9,49 @@ import("Sql_lib");
 import("system.calendars");
 import("Calendar_lib");
 
-var pFilter =  CalendarUtil.reset_filterEvent();
-var conditions = [];
-var conditioncount = 0;
-var user = undefined;
-var stati = [];
-var entries = [];
+var calendarId = tools.getCurrentUser()[tools.PARAMS][tools.CALENDARID];
+if(calendarId != "" && calendarId != null && calendarId != undefined)
+{
+    var pFilter =  CalendarUtil.reset_filterEvent();
+    var conditions = [];
+    var conditioncount = 0;
+    var user = undefined;
+    var stati = [];
+    var entries = [];
 
-var startnumber = Number(vars.get("$sys.date"));
-var endnumber = startnumber + 43200000 ;
+    var startnumber = Number(vars.get("$sys.date"));
+    var endnumber = startnumber + 43200000 ;
 
-var start = startnumber + "";
-var end = endnumber + "";
+    var start = startnumber + "";
+    var end = endnumber + "";
 
-if ( pFilter.tentative == "true" )    
-    stati.push(calendars.STATUS_TENTATIVE);
+    if ( pFilter.tentative == "true" )    
+        stati.push(calendars.STATUS_TENTATIVE);
 
-if ( pFilter.cancelled == "true" )    
-    stati.push(calendars.STATUS_CANCELLED);
+    if ( pFilter.cancelled == "true" )    
+        stati.push(calendars.STATUS_CANCELLED);
 
-if ( pFilter.confirmed == "true" )
-    stati.push(CalendarUtil.mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
+    if ( pFilter.confirmed == "true" )
+        stati.push(CalendarUtil.mapCalendarStatus(calendars.STATUS_CONFIRMED, calendars.getBackendType() ));
 
-if (CalendarUtil.getCalendarSystemType(calendars.VEVENT) == calendars.BACKEND_EXCHANGEWS && pFilter.free == "true")
-    stati.push(calendars.STATUS_FREE);
+    if (CalendarUtil.getCalendarSystemType(calendars.VEVENT) == calendars.BACKEND_EXCHANGEWS && pFilter.free == "true")
+        stati.push(calendars.STATUS_FREE);
 
-if ( pFilter.user != "" )	
-    user = (pFilter.user).trim();
+    if ( pFilter.user != "" )	
+        user = (pFilter.user).trim();
 
-for ( var z = 0; z < stati.length; z++ )
-    CalendarUtil.addEntryCondition(conditions, ++conditioncount,
-    {
-        TYPE: calendars.VEVENT,
-        START: start,
-        END: end,
-        USER: user,
-        STATUS: stati[z]
-    });
+    for ( var z = 0; z < stati.length; z++ )
+        CalendarUtil.addEntryCondition(conditions, ++conditioncount,
+        {
+            TYPE: calendars.VEVENT,
+            START: start,
+            END: end,
+            USER: user,
+            STATUS: stati[z]
+        });
 
-conditions["COUNT"] = String(conditioncount);
-entries = calendars.getEntries(conditions);
+    conditions["COUNT"] = String(conditioncount);
+    entries = calendars.getEntries(conditions);
 
-result.string(entries.length);
+    result.string(entries.length);
+}
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/documenttemplate_id/onValueChange.js b/entity/BulkMail_entity/entityfields/documenttemplate_id/onValueChange.js
index c581ed319d6abf9a33281237cd2ccee9cdbfdd69..fa553b4c0ebe856c7b540afcf5f4c2e4504ecd7d 100644
--- a/entity/BulkMail_entity/entityfields/documenttemplate_id/onValueChange.js
+++ b/entity/BulkMail_entity/entityfields/documenttemplate_id/onValueChange.js
@@ -4,6 +4,7 @@ import("system.util");
 import("system.mail");
 import("DocumentTemplate_lib");
 import("Entity_lib");
+import("EmailUtil_lib");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
 {
diff --git a/entity/CampaignCost_entity/CampaignCost_entity.aod b/entity/CampaignCost_entity/CampaignCost_entity.aod
index 096e8a8d95bd5caf65e5490d901dec5f44b583df..7652bce2911c9999a838ab39eefdafe3bdbdc17c 100644
--- a/entity/CampaignCost_entity/CampaignCost_entity.aod
+++ b/entity/CampaignCost_entity/CampaignCost_entity.aod
@@ -80,14 +80,6 @@
     <entityProvider>
       <name>CampaignCosts</name>
       <documentation>%aditoprj%/entity/CampaignCost_entity/entityfields/campaigncosts/documentation.adoc</documentation>
-      <dependencies>
-        <entityDependency>
-          <name>7131288b-af5c-4914-96f5-c5d70217fc23</name>
-          <entityName>Campaign_entity</entityName>
-          <fieldName>CampaignCosts</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
       <children>
         <entityParameter>
           <name>CampaignStepId_param</name>
@@ -107,24 +99,18 @@
           <expose v="false" />
         </entityParameter>
       </children>
-    </entityProvider>
-    <entityProvider>
-      <name>StepCosts</name>
-      <documentation>%aditoprj%/entity/CampaignCost_entity/entityfields/stepcosts/documentation.adoc</documentation>
       <dependencies>
         <entityDependency>
-          <name>af147f3e-a1bd-4eb0-9ac8-325dbdaba17d</name>
-          <entityName>CampaignStep_entity</entityName>
-          <fieldName>CampaignStepCosts</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-        <entityDependency>
-          <name>2a92b738-c0bb-4c14-9915-aff9e18effaf</name>
+          <name>7131288b-af5c-4914-96f5-c5d70217fc23</name>
           <entityName>Campaign_entity</entityName>
-          <fieldName>CampaignStepCosts</fieldName>
+          <fieldName>CampaignCosts</fieldName>
           <isConsumer v="false" />
         </entityDependency>
       </dependencies>
+    </entityProvider>
+    <entityProvider>
+      <name>StepCosts</name>
+      <documentation>%aditoprj%/entity/CampaignCost_entity/entityfields/stepcosts/documentation.adoc</documentation>
       <children>
         <entityParameter>
           <name>CampaignStepId_param</name>
@@ -144,6 +130,20 @@
           <expose v="false" />
         </entityParameter>
       </children>
+      <dependencies>
+        <entityDependency>
+          <name>af147f3e-a1bd-4eb0-9ac8-325dbdaba17d</name>
+          <entityName>CampaignStep_entity</entityName>
+          <fieldName>CampaignStepCosts</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>2a92b738-c0bb-4c14-9915-aff9e18effaf</name>
+          <entityName>Campaign_entity</entityName>
+          <fieldName>CampaignStepCosts</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
     </entityProvider>
     <entityConsumer>
       <name>Campaigns</name>
@@ -155,35 +155,35 @@
     </entityConsumer>
     <entityConsumer>
       <name>CampaignSteps</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>CampaignStep_entity</entityName>
-        <fieldName>CampaignSteps</fieldName>
-      </dependency>
       <children>
         <entityParameter>
           <name>campaignId_param</name>
           <valueProcess>%aditoprj%/entity/CampaignCost_entity/entityfields/campaignsteps/children/campaignid_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
-    </entityConsumer>
-    <entityConsumer>
-      <name>KeywordCampaignManagementCostCategory</name>
       <dependency>
         <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
+        <entityName>CampaignStep_entity</entityName>
+        <fieldName>CampaignSteps</fieldName>
       </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>KeywordCampaignManagementCostCategory</name>
       <children>
         <entityParameter>
           <name>ContainerName_param</name>
           <valueProcess>%aditoprj%/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/containername_param/valueProcess.js</valueProcess>
         </entityParameter>
         <entityParameter>
-          <name>ExcludedKeyIdsSubquery_param</name>
-          <valueProcess>%aditoprj%/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/excludedkeyidssubquery_param/valueProcess.js</valueProcess>
+          <name>BlacklistIds_param</name>
+          <valueProcess>%aditoprj%/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/blacklistids_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
     </entityConsumer>
     <entityParameter>
       <name>CampaignId_param</name>
diff --git a/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/excludedkeyidssubquery_param/valueProcess.js b/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/blacklistids_param/valueProcess.js
similarity index 84%
rename from entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/excludedkeyidssubquery_param/valueProcess.js
rename to entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/blacklistids_param/valueProcess.js
index d918b95bfcb392e62eeee2bc4e77dacf8b9efd29..64277edeb0afa5bd2ed0c3a9bf86700a54343e6e 100644
--- a/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/excludedkeyidssubquery_param/valueProcess.js
+++ b/entity/CampaignCost_entity/entityfields/keywordcampaignmanagementcostcategory/children/blacklistids_param/valueProcess.js
@@ -12,9 +12,9 @@ var cond = newSelect("CATEGORY")
 if (vars.get("$field.CAMPAIGNSTEP_ID"))
     cond.andIfSet("CAMPAIGNCOST.CAMPAIGNSTEP_ID", "$field.CAMPAIGNSTEP_ID");
 else
-    cond.and("CAMPAIGNCOST.CAMPAIGNSTEP_ID is null")
+    cond.and("CAMPAIGNCOST.CAMPAIGNSTEP_ID is null");
     
 if (vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW)
     cond.andIfSet("CAMPAIGNCOST.CAMPAIGNCOSTID", "$field.CAMPAIGNCOSTID", SqlBuilder.NOT_EQUAL());
 
-result.string(cond.toString());
\ No newline at end of file
+result.string(JSON.stringify(cond.arrayColumn()));
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstep_id.displayvalue/expression.js b/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstep_id.displayvalue/expression.js
index c2a7f5503d93c7ac48568fb0476a41b0bb4193ef..840d4c2dc1202bd94f31491b84d05e76e55adf03 100644
--- a/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstep_id.displayvalue/expression.js
+++ b/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstep_id.displayvalue/expression.js
@@ -1,3 +1,4 @@
 import("system.result");
 import("Sql_lib");
+
 result.string(newSelect("CAMPAIGNSTEP.NAME").from("CAMPAIGNSTEP").where("CAMPAIGNSTEP.CAMPAIGNSTEPID = CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID").toString());
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstepcurrentparticipantcount.value/expression.js b/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstepcurrentparticipantcount.value/expression.js
index 7d896cba463f89dde65274356f8bbc5fb2a1097e..d563f19045726a045494d9156cadf3f53389589e 100644
--- a/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstepcurrentparticipantcount.value/expression.js
+++ b/entity/CampaignParticipant_entity/recordcontainers/participantsdbrecordcontainer/recordfieldmappings/campaignstepcurrentparticipantcount.value/expression.js
@@ -1,3 +1,4 @@
 import("system.result");
 import("Sql_lib");
+
 result.string(newSelect("COUNT(*)").from("CAMPAIGNPARTICIPANT", "p1").where("p1.CAMPAIGNSTEP_ID = CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID").toString());
\ No newline at end of file
diff --git a/entity/CampaignPlanning_entity/CampaignPlanning_entity.aod b/entity/CampaignPlanning_entity/CampaignPlanning_entity.aod
index f274ff6890107a465ec82b673a40316a9b542e39..62ae8a76e9ae487f97b651173b78bc4c8acbf3ff 100644
--- a/entity/CampaignPlanning_entity/CampaignPlanning_entity.aod
+++ b/entity/CampaignPlanning_entity/CampaignPlanning_entity.aod
@@ -81,17 +81,17 @@
     </entityField>
     <entityConsumer>
       <name>CampaignStatusKeyword</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
-      </dependency>
       <children>
         <entityParameter>
           <name>ContainerName_param</name>
           <valueProcess>%aditoprj%/entity/CampaignPlanning_entity/entityfields/campaignstatuskeyword/children/containername_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
     </entityConsumer>
     <entityProvider>
       <name>#PROVIDER_AGGREGATES</name>
@@ -99,58 +99,6 @@
     </entityProvider>
   </entityFields>
   <recordContainers>
-    <dbRecordContainer>
-      <name>recordContainer</name>
-      <alias>Data_alias</alias>
-      <fromClauseProcess>%aditoprj%/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/fromClauseProcess.js</fromClauseProcess>
-      <orderClauseProcess>%aditoprj%/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/orderClauseProcess.js</orderClauseProcess>
-      <linkInformation>
-        <linkInformation>
-          <name>091a323d-d1e8-4eec-8f33-0c91bc7f62af</name>
-          <tableName>CAMPAIGN</tableName>
-          <primaryKey>CAMPAIGNID</primaryKey>
-          <isUIDTable v="false" />
-          <readonly v="true" />
-        </linkInformation>
-        <linkInformation>
-          <name>2df8e267-6c25-4bae-bd0f-2b7b4399cc2b</name>
-          <tableName>CAMPAIGNSTEP</tableName>
-          <primaryKey>CAMPAIGNSTEPID</primaryKey>
-          <isUIDTable v="true" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>CAMPAIGN_ID.value</name>
-          <recordfield>CAMPAIGN.CAMPAIGNID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_END.value</name>
-          <recordfield>CAMPAIGNSTEP.DATE_END</recordfield>
-          <isFilterable v="true" />
-          <isLookupFilter v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_START.value</name>
-          <recordfield>CAMPAIGNSTEP.DATE_START</recordfield>
-          <isFilterable v="true" />
-          <isLookupFilter v="true" />
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>PREDECESSOR_STEP_ID.value</name>
-          <recordfield>CAMPAIGNSTEP.PREDECESSORSTEP_ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>STEP_DESCRIPTION.value</name>
-          <recordfield>CAMPAIGNSTEP.DESCRIPTION</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>STEP_ID.value</name>
-          <recordfield>CAMPAIGNSTEP.CAMPAIGNSTEPID</recordfield>
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-    </dbRecordContainer>
     <jDitoRecordContainer>
       <name>jditoRecordContainer</name>
       <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
diff --git a/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/contentProcess.js b/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/contentProcess.js
index 9f1541d2f9b4b072bcdb0a64bdf3c8c84baf1d7a..53985b5cc50a47402b9df28330a3f2623c768f39 100644
--- a/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/contentProcess.js
+++ b/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/contentProcess.js
@@ -1,3 +1,4 @@
+import("system.logging");
 import("JditoFilter_lib");
 import("system.util");
 import("system.db");
@@ -26,34 +27,47 @@ if (isMariaDB)
     columnName = "\`NAME\`";
 }
 
-var stepsRows = stepCondition.select("CAMPAIGNSTEPID, CAMPAIGNSTEP."+ columnName + ", CAMPAIGNSTEP.PREDECESSORSTEP_ID,"
+stepCondition.select("CAMPAIGNSTEPID, CAMPAIGNSTEP."+ columnName + ", CAMPAIGNSTEP.PREDECESSORSTEP_ID,"
                                    + " CAMPAIGNSTEP.DESCRIPTION, CAMPAIGNSTEP.DATE_START, CAMPAIGNSTEP.DATE_END, CAMPAIGNID, CAMPAIGN."+ columnName +", CAMPAIGN.STATUS")
                              .from("CAMPAIGN")
-                             .join("CAMPAIGNSTEP", "CAMPAIGN.CAMPAIGNID = CAMPAIGNSTEP.CAMPAIGN_ID")
-                             .orderBy("SORTING")
-                             .table();
+                             .join("CAMPAIGNSTEP", "CAMPAIGN.CAMPAIGNID = CAMPAIGNSTEP.CAMPAIGN_ID");
+                             
+if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
+   stepCondition.and("CAMPAIGNSTEP.CAMPAIGNSTEPID", vars.get("$local.idvalues"), SqlBuilder.IN());
 
-stepsRows = stepsRows.map(function ([stepId, stepName, predecessorId, desc, stepStartDate, stepEndDate, campaignId, campaignName, campaignStatus])
+var stepsRows = stepCondition.orderBy("SORTING").table();
+
+//this can happen when not a CampaignStep, but a Campaign node was selected
+if(stepsRows.length == 0 && vars.get("$local.idvalues") && newSelect("count(*)").from("CAMPAIGN").where("CAMPAIGN.CAMPAIGNID", vars.get("$local.idvalues")).cell() > 0)
 {
-    if (!campaignRows[campaignId])
-    {
-        let startDate = CampaignUtils.getCampaignStartDate(campaignId);
-        let endDate = CampaignUtils.getCampaignEndDate(campaignId);
-        campaignRows[campaignId] = [campaignId, campaignName, null, null, startDate, endDate, campaignId, TARGET_CONTEXT_ROOT_ELEMENT, campaignStatus];
-    }
-    stepIds[stepId] = true;
-    
-    return [stepId, stepName, predecessorId || campaignId, desc, stepStartDate, stepEndDate, campaignId, TARGET_CONTEXT_ELEMENT, campaignStatus];
-});
+    stepsRows = [[vars.get("$local.idvalues"), "", "", "", "", "", vars.get("$local.idvalues"), "", ""]]
+}
 
-//replace all predecessor ids that are not in the tree with the campaign id
-stepsRows.forEach(function (row)
+if(!vars.get("$local.idvalues"))
 {
-    if (!(stepIds[row[2]]))
-        row[2] = row[6];
-});
+    stepsRows = stepsRows.map(function ([stepId, stepName, predecessorId, desc, stepStartDate, stepEndDate, campaignId, campaignName, campaignStatus])
+    {
+        if (!campaignRows[campaignId])
+        {
+            let startDate = CampaignUtils.getCampaignStartDate(campaignId);
+            let endDate = CampaignUtils.getCampaignEndDate(campaignId);
+            campaignRows[campaignId] = [campaignId, campaignName, null, null, startDate, endDate, campaignId, TARGET_CONTEXT_ROOT_ELEMENT, campaignStatus];
+        }
+        stepIds[stepId] = true;
+
+        return [stepId, stepName, predecessorId || campaignId, desc, stepStartDate, stepEndDate, campaignId, TARGET_CONTEXT_ELEMENT, campaignStatus];
+    });
 
-//convert the object to an array
-campaignRows = Object.keys(campaignRows).map(function (id) {return campaignRows[id];});
+    //replace all predecessor ids that are not in the tree with the campaign id
+    stepsRows.forEach(function (row)
+    {
+        if (!(stepIds[row[2]]))
+            row[2] = row[6];
+    });
 
-result.object(campaignRows.concat(stepsRows))
+    //convert the object to an array
+    campaignRows = Object.keys(campaignRows).map(function (id) {return campaignRows[id];});
+    
+    stepsRows = campaignRows.concat(stepsRows);
+}
+result.object(stepsRows);
diff --git a/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/fromClauseProcess.js b/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/fromClauseProcess.js
deleted file mode 100644
index b007b4d58a7376e99c1fb0b20cfe88459dc89a4f..0000000000000000000000000000000000000000
--- a/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/fromClauseProcess.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("system.result");
-
-result.string("CAMPAIGN join CAMPAIGNSTEP on CAMPAIGN.CAMPAIGNID = CAMPAIGNSTEP.CAMPAIGN_ID")
\ No newline at end of file
diff --git a/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/orderClauseProcess.js b/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/orderClauseProcess.js
deleted file mode 100644
index 8538a702d13027d9d9739d9b6652105b87725638..0000000000000000000000000000000000000000
--- a/entity/CampaignPlanning_entity/recordcontainers/recordcontainer/orderClauseProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.result");
-import("system.db");
-
-result.object({"CAMPAIGNSTEP.SORTING": db.ASCENDING});
\ No newline at end of file
diff --git a/entity/CommRestriction_Entity/CommRestriction_Entity.aod b/entity/CommRestriction_Entity/CommRestriction_Entity.aod
index 102c450de9e00d97a4f3e8329bc4d5b528787b1f..407e45312848c4daf741f99d7df616f30754ca5b 100644
--- a/entity/CommRestriction_Entity/CommRestriction_Entity.aod
+++ b/entity/CommRestriction_Entity/CommRestriction_Entity.aod
@@ -55,11 +55,6 @@
     </entityConsumer>
     <entityConsumer>
       <name>CommRestrictionMedium</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordEntry_entity</entityName>
-        <fieldName>SpecificContainerKeywords</fieldName>
-      </dependency>
       <children>
         <entityParameter>
           <name>ContainerName_param</name>
@@ -67,10 +62,15 @@
           <expose v="false" />
         </entityParameter>
         <entityParameter>
-          <name>ExcludedKeyIdsSubquery_param</name>
-          <valueProcess>%aditoprj%/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js</valueProcess>
+          <name>BlacklistIds_param</name>
+          <valueProcess>%aditoprj%/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/blacklistids_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
     </entityConsumer>
     <entityProvider>
       <name>CommRestrictions</name>
@@ -103,17 +103,17 @@
     </entityField>
     <entityConsumer>
       <name>MediumKeywordAttribute</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>KeywordAttribute_entity</entityName>
-        <fieldName>SpecificContainerKeyword</fieldName>
-      </dependency>
       <children>
         <entityParameter>
           <name>ContainerName_param</name>
           <valueProcess>%aditoprj%/entity/CommRestriction_Entity/entityfields/mediumkeywordattribute/children/containername_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordAttribute_entity</entityName>
+        <fieldName>SpecificContainerKeyword</fieldName>
+      </dependency>
     </entityConsumer>
     <entityProvider>
       <name>#PROVIDER_AGGREGATES</name>
diff --git a/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/blacklistids_param/valueProcess.js b/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/blacklistids_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c1f39ed63d29e2c0be655f3a075b7cd45cc6010b
--- /dev/null
+++ b/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/blacklistids_param/valueProcess.js
@@ -0,0 +1,11 @@
+import("system.vars");
+import("Sql_lib");
+import("system.result");
+
+var alreadyUsedMediums = new SqlBuilder()
+    .select("MEDIUM")
+    .from("COMMRESTRICTION")
+    .where("COMMRESTRICTION.CONTACT_ID", vars.get("$field.CONTACT_ID"))
+    .arrayColumn();
+
+result.string(JSON.stringify(alreadyUsedMediums));
\ No newline at end of file
diff --git a/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js b/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js
deleted file mode 100644
index 50167db735b55a82144eadc0e440f38b57ce6de7..0000000000000000000000000000000000000000
--- a/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import("system.question");
-import("system.vars");
-import("Sql_lib");
-import("system.result");
-
-var contactId = vars.get("$field.CONTACT_ID");
-var alreadyUsedMediums = new SqlBuilder().select("MEDIUM").from("COMMRESTRICTION").where("COMMRESTRICTION.CONTACT_ID", contactId);
-
-result.string(alreadyUsedMediums);
\ No newline at end of file
diff --git a/entity/Document_entity/entityfields/msteam/children/synchronizedocuments/onActionProcess.js b/entity/Document_entity/entityfields/msteam/children/synchronizedocuments/onActionProcess.js
index 841ff10b1844fa44c81a817f99987d1ff2f42db7..aef50aebaf302304a699c6713ceeec227d70350b 100644
--- a/entity/Document_entity/entityfields/msteam/children/synchronizedocuments/onActionProcess.js
+++ b/entity/Document_entity/entityfields/msteam/children/synchronizedocuments/onActionProcess.js
@@ -1,7 +1,7 @@
 import("system.neon");
 import("system.vars");
 
-neon.openContext("MSTTeamsDocument", "MSTeamsDocumentEdit_view", null, neon.OPERATINGSTATE_VIEW, {
+neon.openContext("MSTeamsDocument", "MSTeamsDocumentEdit_view", null, neon.OPERATINGSTATE_VIEW, {
     "MSTTeamId_param" : vars.get("$param.MSTTeamId_param"),
     "ObjectRowId_param" : vars.get("$param.AssignmentRowId_param"),
     "AssignmentName_param" : vars.get("$param.AssignmentName_param"),
diff --git a/entity/Favorite_entity/recordcontainers/jditorecordcontainer/contentProcess.js b/entity/Favorite_entity/recordcontainers/jditorecordcontainer/contentProcess.js
index eafabfcf64d2ef9eaea73303673e6b186e7ab184..1c6923b2958dfd7578394cc3a7bd2a7374d19846 100644
--- a/entity/Favorite_entity/recordcontainers/jditorecordcontainer/contentProcess.js
+++ b/entity/Favorite_entity/recordcontainers/jditorecordcontainer/contentProcess.js
@@ -8,41 +8,61 @@ import("system.favorite");
 import("system.tools");
 import("system.entities");
 
+/*
+ *  loading favorites by id
+ */
 if(vars.get("$local.idvalues") && vars.get("$local.idvalues").length != 0)
 {
-    var selected = vars.get("$local.idvalues");
-    var selectedFavos = [];
+    var seekedByCore = vars.get("$local.idvalues");
+    var seekedByCoreFavos = [];
     
-    for(h = 0; h < selected.length; h++)
-        selectedFavos.push(buildFavoriteForDeletion(favorite.getFavorites(favorite.createGetFavoriteByIdConfig()
-                                                                                    .setId(selected[h]))[0]));
+    var config = favorite.createGetFavoriteByIdConfig().setIds(seekedByCore);
+    seekedByCoreFavos = buildFavoritesForDeletion(favorite.getFavorites(config));
 
-    result.object(selectedFavos);
+    result.object(seekedByCoreFavos);
 }
+
+/*
+ * loading and filtering by UI
+ */
 else
 {
-    
+    //save active filters and their logical operator
     var filters = vars.get("$local.filter");
     var activeFilters = [];
+    var logicalConnectionOperator;
     if(filters["filter"] != null)
+    {
+        logicalConnectionOperator = filters["filter"]["operator"];
         for(g = 0; g < filters["filter"]["childs"].length; g++)
             activeFilters.push(filters["filter"]["childs"][g])
+    }
     
     
     var finishedFavoritesForDisplay = [];
     
+    /*
+     * load all contexts and all favorites
+     */
     var allContexts = getAllFavoriteEnabledContexts();
+    var allFavorites = favorite.getFavorites(favorite.createGetFavoritesConfig().setUserId(tools.getCurrentUser()[tools.NAME]));
+    
+    /*
+     * complete-load (in buildFavorites) favorites by one context at a time
+     */
     for(i = 0; i < allContexts.length; i++)
     {
-        var allFavorites = favorite.getFavorites(favorite.createGetFavoritesConfig()
-                                                            .setUserId(tools.getCurrentUser()[tools.NAME])
-                                                            .setObjectType(allContexts[i]));
-        var builtFavos = buildFavorites(allFavorites, allContexts[i]);
+        var contextFavorites = [];
+        for(x = 0; x < allFavorites.length; x++)
+            if(allFavorites[x]["objecttype"] === allContexts[i])
+                contextFavorites.push(allFavorites[x])
+            
+        var builtFavos = buildFavorites(contextFavorites, allContexts[i]);
     
         for(let x = 0; x < builtFavos.length; x++)
         {
             var favo = builtFavos[x];
-            if(isFiltered(activeFilters, favo))
+            if(isFiltered(activeFilters, logicalConnectionOperator, favo))
                 finishedFavoritesForDisplay.push(favo);
         }
     }
@@ -50,44 +70,46 @@ else
     result.object(finishedFavoritesForDisplay);
 }
 
-function isFiltered(filters, fav)
+function isFiltered(filters, logicalConnectionOperator, fav)
 {
+    if(filters == null || filters.length == 0)
+        return true;
+    
     var favoObjectType = fav[3];
     var favoGroupName = fav[1];
     var favoRowId = fav[5];
     var favoTitle = fav[6];
     
-    var isFiltered = true;
+    var allFilterFulfilled = true;
+    var oneFilterFulfilled = false;
     
     for(let i = 0; i < filters.length; i++)
     {
+        var attributeValue = "";
         if(filters[i]["name"].includes("groupTypeExtension"))
-        {
-            if(!isValid(favoObjectType, filters[i]))
-            {
-                isFiltered = false;
-                break;
-            }
-        }
-        if(filters[i]["name"].includes("groupTitleExtension"))
-        {
-            if(!isValid(favoTitle, filters[i]))
-            {
-                isFiltered = false;
-                break;
-            }
-        }
-        if(filters[i]["name"].includes("groupGroupNameExtension"))
-        {
-            if(!isValid(favoGroupName, filters[i]))
-            {
-                isFiltered = false;
-                break;
-            }
-        }
+            attributeValue = favoObjectType;
+        else if(filters[i]["name"].includes("groupTitleExtension"))
+            attributeValue = favoTitle;
+        else if(filters[i]["name"].includes("groupGroupNameExtension"))
+            attributeValue = favoGroupName;
+
+        if(!isValid(attributeValue, filters[i]))
+            allFilterFulfilled = false;
+        else
+            oneFilterFulfilled = true;
     }
-        
-    return isFiltered;
+    
+    if(logicalConnectionOperator == "AND")
+        if(allFilterFulfilled)
+            return true;
+        else
+            return false;
+    
+    if(logicalConnectionOperator == "OR")
+        if(oneFilterFulfilled)
+            return true;
+        else
+            return false;
 }
 
 function isValid(value, filter)
@@ -193,29 +215,36 @@ function getAllFavoriteEnabledContexts()
     return permittedContexts;
 }
 
-function buildFavoriteForDeletion(favo)
-{        
-    var groupid = favo["group"]["groupid"];
-    var grouptitle = favo["group"]["grouptitle"];
-    var grouptype = favo["group"]["grouptype"];
-    var objecttype = favo["objecttype"];
-    var image = "";
-    var rowid = favo["rowid"];
-    var title = "";
-    var id = favo["id"];
-    var user = favo["group"]["groupuser"];
-    
-    return [
-        groupid,
-        grouptitle,
-        grouptype, 
-        objecttype, 
-        image,
-        rowid,
-        title,
-        id,
-        user
-    ];
+function buildFavoritesForDeletion(favos)
+{      
+    var results = [];
+    
+    for(i = 0; i < favos.length; i++)
+    {
+        var groupid = favos[i]["group"]["groupid"];
+        var grouptitle = favos[i]["group"]["grouptitle"];
+        var grouptype = favos[i]["group"]["grouptype"];
+        var objecttype = favos[i]["objecttype"];
+        var image = "";
+        var rowid = favos[i]["rowid"];
+        var title = "";
+        var id = favos[i]["id"];
+        var user = favos[i]["group"]["groupuser"];
+    
+        results.push([
+            groupid,
+            grouptitle,
+            grouptype, 
+            objecttype, 
+            image,
+            rowid,
+            title,
+            id,
+            user
+        ]);
+    }
+    
+    return results;
 }
 
 
diff --git a/entity/Favorite_entity/recordcontainers/jditorecordcontainer/onDelete.js b/entity/Favorite_entity/recordcontainers/jditorecordcontainer/onDelete.js
index 5c5ab2b521e59ad3ba0e1b71bb5c99b51044fdf3..70ac8f02ca1518b3ce375c2f4c5901d08d2c1d4f 100644
--- a/entity/Favorite_entity/recordcontainers/jditorecordcontainer/onDelete.js
+++ b/entity/Favorite_entity/recordcontainers/jditorecordcontainer/onDelete.js
@@ -1,4 +1,5 @@
 import("system.vars");
 import("system.favorite");
 
-favorite.remove(favorite.createRemoveByIdConfig().setFavoriteRecordId(vars.get("$local.uid")));
\ No newline at end of file
+var selected = vars.get("$local.uid");
+favorite.remove(favorite.createRemoveMultipleByIdConfig().setFavoriteRecordIds([selected]));
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index 3472852e89848b764ea1dc9a2525a2e6bc300530..d897ddd5ff1732ea13f318d6834412bf0993cd20 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -639,7 +639,7 @@
       <name>ExcludedKeyIdsSubquery_param</name>
       <expose v="true" />
       <documentation>%aditoprj%/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc</documentation>
-      <description>PARAMETER</description>
+      <description>DEPRECATED!!! DO NOT USE!!!</description>
     </entityParameter>
     <entityParameter>
       <name>WhitelistIds_param</name>
@@ -661,6 +661,10 @@
       <name>#PROVIDER_AGGREGATES</name>
       <useAggregates v="true" />
     </entityProvider>
+    <entityParameter>
+      <name>BlacklistIds_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc b/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc
index 55fde66fa9fdb8f3dfebb3341ea9f95471189c32..5992cb1957a8d69753478d3e19384a511371d90f 100644
--- a/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc
+++ b/entity/KeywordEntry_entity/entityfields/excludedkeyidssubquery_param/documentation.adoc
@@ -1,2 +1,5 @@
+DEPRECATED! This parameter does not work with caching, because if the result of the subquery changes while the subquery itself doesn't, the cached
+result won't be updated
+
 Can be filled with a subquery-string, which delivers KeyIds to exclude.
 The subquery is used insade a "KEYID not in(...)" 
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/recordcontainers/db/cacheKeyProcess.js b/entity/KeywordEntry_entity/recordcontainers/db/cacheKeyProcess.js
index bd9e8c01354097c564fcb6fd65e3e5390fbb9f10..822b1e5a4479fd59faf95e148e48d34d917071e2 100644
--- a/entity/KeywordEntry_entity/recordcontainers/db/cacheKeyProcess.js
+++ b/entity/KeywordEntry_entity/recordcontainers/db/cacheKeyProcess.js
@@ -1,6 +1,6 @@
 import("CachedRecordContainer_lib");
 import("system.result")
 
-var res = CachedRecordContainerUtils.getCommonKey("$param.ContainerName_param", "$param.ExcludedKeyIdsSubquery_param", "$param.OnlyActives_param"
+var res = CachedRecordContainerUtils.getCommonKey("$param.ContainerName_param", "$param.BlacklistIds_param", "$param.OnlyActives_param"
     , "$param.WhitelistIds_param");
 result.string(res);
diff --git a/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js b/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js
index c2921e933fff759455fdd5adefee3f8731fe79d3..90f58744de34c09de3164a324889dc3d3bf03859 100644
--- a/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/KeywordEntry_entity/recordcontainers/db/conditionProcess.js
@@ -1,3 +1,4 @@
+import("Util_lib");
 import("system.vars");
 import("system.db");
 import("system.result");
@@ -13,14 +14,16 @@ if (vars.get("$param.OnlyActives_param") == "true")
 if (vars.exists("$param.ExcludedKeyIdsSubquery_param") && vars.get("$param.ExcludedKeyIdsSubquery_param"))
     cond.and("AB_KEYWORD_ENTRY.KEYID not in (" + vars.get("$param.ExcludedKeyIdsSubquery_param") + ")");
 
-if (vars.getString("$param.WhitelistIds_param"))
+var whitelist = Utils.parseJSON(vars.get("$param.WhitelistIds_param"));
+var blacklist = Utils.parseJSON(vars.get("$param.BlacklistIds_param"));
+if (whitelist)
 {
-    var whitelist = JSON.parse(vars.getString("$param.WhitelistIds_param"));
-   
     if (whitelist.length > 0)
-        cond.and("AB_KEYWORD_ENTRY.KEYID", JSON.parse(vars.getString("$param.WhitelistIds_param")), SqlBuilder.IN());
+        cond.and("AB_KEYWORD_ENTRY.KEYID", whitelist, SqlBuilder.IN());
     else
         cond.noResult(); // force empty result if whitelist is empty
 }
+if (blacklist && blacklist.length > 0)
+    cond.and("AB_KEYWORD_ENTRY.KEYID", blacklist, SqlBuilder.NOT_IN());
 
 result.string(cond.toString());
diff --git a/entity/LetterRecipient_entity/LetterRecipient_entity.aod b/entity/LetterRecipient_entity/LetterRecipient_entity.aod
index 63ec8c14576769c9f89e4cedc7152fb2fc92b02c..e8f4ac96e66e694bab194186688c63f7c8bfa300 100644
--- a/entity/LetterRecipient_entity/LetterRecipient_entity.aod
+++ b/entity/LetterRecipient_entity/LetterRecipient_entity.aod
@@ -6,6 +6,7 @@
   <siblings>
     <element>Address_entity</element>
   </siblings>
+  <onValidation>%aditoprj%/entity/LetterRecipient_entity/onValidation.js</onValidation>
   <titlePlural>Recipients</titlePlural>
   <recordContainer>db</recordContainer>
   <entityFields>
diff --git a/entity/LetterRecipient_entity/onValidation.js b/entity/LetterRecipient_entity/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..b165c8bd18fd2983e52e191b2ec9e71b404cbb7f
--- /dev/null
+++ b/entity/LetterRecipient_entity/onValidation.js
@@ -0,0 +1,16 @@
+import("system.translate");
+import("system.result");
+import("Sql_lib");
+import("system.vars");
+
+var contactId = vars.get("$field.CONTACT_ID");
+
+var standardAddress = newSelect("CONTACT.ADDRESS_ID")
+                                .from("CONTACT")
+                                .where("CONTACT.CONTACTID", contactId)
+                                .cell();
+
+if(!standardAddress)
+{
+    result.string(translate.text("The selected Contact doesn't have an address set."));
+}
\ No newline at end of file
diff --git a/entity/MSTTeamMember_entity/MSTTeamMember_entity.aod b/entity/MSTTeamMember_entity/MSTTeamMember_entity.aod
index 72dead10e1dc47cf5fe80fb31d4493667fd40677..1f1e68f496fa64090a7ddcdb33ef5aad5634e607 100644
--- a/entity/MSTTeamMember_entity/MSTTeamMember_entity.aod
+++ b/entity/MSTTeamMember_entity/MSTTeamMember_entity.aod
@@ -94,6 +94,7 @@
       <mandatoryProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/role/mandatoryProcess.js</mandatoryProcess>
       <dropDownProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/role/dropDownProcess.js</dropDownProcess>
       <stateProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/role/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/role/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
       <name>INVITE</name>
@@ -101,6 +102,7 @@
       <mandatoryProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/invite/mandatoryProcess.js</mandatoryProcess>
       <dropDownProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/invite/dropDownProcess.js</dropDownProcess>
       <stateProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/invite/stateProcess.js</stateProcess>
+      <valueProcess>%aditoprj%/entity/MSTTeamMember_entity/entityfields/invite/valueProcess.js</valueProcess>
     </entityField>
     <entityProvider>
       <name>#PROVIDER_AGGREGATES</name>
diff --git a/entity/MSTTeamMember_entity/entityfields/invite/valueProcess.js b/entity/MSTTeamMember_entity/entityfields/invite/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..516e09d60f21ed6d91e8f27b41593afec8f686ff
--- /dev/null
+++ b/entity/MSTTeamMember_entity/entityfields/invite/valueProcess.js
@@ -0,0 +1,6 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == null)
+    result.string(false);
\ No newline at end of file
diff --git a/entity/MSTTeamMember_entity/entityfields/role/valueProcess.js b/entity/MSTTeamMember_entity/entityfields/role/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d79978a6cbc07884ec953adb3be3de3d78997b78
--- /dev/null
+++ b/entity/MSTTeamMember_entity/entityfields/role/valueProcess.js
@@ -0,0 +1,6 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == null)
+    result.string("member");
\ No newline at end of file
diff --git a/entity/MSTTeam_entity/entityfields/teammembers/onValidation.js b/entity/MSTTeam_entity/entityfields/teammembers/onValidation.js
index 0629031e507398d3f502728590e967582d74fc50..ab18aabd0ba1fb0f4c2d93a91aa191b29ba2c352 100644
--- a/entity/MSTTeam_entity/entityfields/teammembers/onValidation.js
+++ b/entity/MSTTeam_entity/entityfields/teammembers/onValidation.js
@@ -1,8 +1,20 @@
+import("system.vars");
+import("system.entities");
 import("Entity_lib");
 import("system.result");
 import("system.translate");
 
-var members = EntityConsumerRowsHelper.getCurrentConsumerRows("TeamMembers", ["ROLE"]);
+//this is a workaround, EntityConsumerRowsHelper.getCurrentConsumerRows should be used here
+var loadRowsConfig = entities.createConfigForLoadingRows()
+    .entity("MSTTeamMember_entity")
+    .provider("MembersOfTeam")
+    .fields(["#UID", "ROLE"])
+    .addParameter("MSTTeamId_param", vars.get("$field.UID"));
+var savedRows = entities.getRows(loadRowsConfig);
+var members = new EntityConsumerRowsHelper(savedRows)
+    .consumer("TeamMembers")
+    .applyConsumerRowChanges()
+    .getRows();
 var hasOwner = members.some(function (member)
 {
     return member["ROLE"] == "owner";
diff --git a/entity/MSTeamsActivityImport_entity/MSTeamsActivityImport_entity.aod b/entity/MSTeamsActivityImport_entity/MSTeamsActivityImport_entity.aod
index 2f279cf23fb22d886b2a3a7bce9c60edcf83206c..17cde5886a40df0410dcd5b3c9ea721f13d32cf1 100644
--- a/entity/MSTeamsActivityImport_entity/MSTeamsActivityImport_entity.aod
+++ b/entity/MSTeamsActivityImport_entity/MSTeamsActivityImport_entity.aod
@@ -78,9 +78,11 @@
       <name>#PROVIDER_AGGREGATES</name>
       <useAggregates v="true" />
     </entityProvider>
-    <entityActionField>
-      <name>importMessages</name>
-    </entityActionField>
+    <entityField>
+      <name>TeamMessages</name>
+      <consumer>Messages</consumer>
+      <selectionMode>MULTI</selectionMode>
+    </entityField>
   </entityFields>
   <recordContainers>
     <datalessRecordContainer>
diff --git a/entity/MSTeamsDocument_entity/MSTeamsDocument_entity.aod b/entity/MSTeamsDocument_entity/MSTeamsDocument_entity.aod
index 7b63c5f0e10641d17d6bc056c6f771d217cc1e7d..282dfbc5ff907b3da341b62f9a5079a3628c3645 100644
--- a/entity/MSTeamsDocument_entity/MSTeamsDocument_entity.aod
+++ b/entity/MSTeamsDocument_entity/MSTeamsDocument_entity.aod
@@ -63,6 +63,7 @@
     </entityProvider>
     <entityActionField>
       <name>importDocuments</name>
+      <title>Import Documents</title>
       <onActionProcess>%aditoprj%/entity/MSTeamsDocument_entity/entityfields/importdocuments/onActionProcess.js</onActionProcess>
     </entityActionField>
   </entityFields>
diff --git a/entity/MSTeamsDocument_entity/entityfields/importdocuments/onActionProcess.js b/entity/MSTeamsDocument_entity/entityfields/importdocuments/onActionProcess.js
index 7237c6c01de74d5355cde59d84173d56989b55b0..23dcd6873c5979acde3412cd24bc618244881c17 100644
--- a/entity/MSTeamsDocument_entity/entityfields/importdocuments/onActionProcess.js
+++ b/entity/MSTeamsDocument_entity/entityfields/importdocuments/onActionProcess.js
@@ -1,14 +1,11 @@
 import("system.text");
-import("system.teams");
 import("system.vars");
 import("system.db");
-import("system.util")
+import("system.util");
 import("Sql_lib");
-import("system.net")
-import("system.logging");
+import("system.net");
 import("system.neon");
 
-var rowData = vars.get("$local.rowdata");
 var documents = text.decodeMS(vars.get("$field.DOCUMENTS"));
 
 documents.forEach(function (document)
@@ -25,3 +22,5 @@ documents.forEach(function (document)
         file, documentName, "", "", alias, util.getNewUUID());    
 });
 
+neon.closeImage(vars.get("$sys.currentimage"), true);
+neon.refreshAll();
\ No newline at end of file
diff --git a/entity/MSTeamsMessage_entity/MSTeamsMessage_entity.aod b/entity/MSTeamsMessage_entity/MSTeamsMessage_entity.aod
index 437ba4f01752bc9a118f40f47ce80f9fdb5b7e3c..8100af9bbee696961ab43850b8e49906237b4f00 100644
--- a/entity/MSTeamsMessage_entity/MSTeamsMessage_entity.aod
+++ b/entity/MSTeamsMessage_entity/MSTeamsMessage_entity.aod
@@ -57,6 +57,20 @@
       <name>#PROVIDER_AGGREGATES</name>
       <useAggregates v="true" />
     </entityProvider>
+    <entityActionField>
+      <name>importMessages</name>
+      <title>Import</title>
+      <onActionProcess>%aditoprj%/entity/MSTeamsMessage_entity/entityfields/importmessages/onActionProcess.js</onActionProcess>
+    </entityActionField>
+    <entityActionField>
+      <name>loadNext</name>
+      <title>Next</title>
+      <onActionProcess>%aditoprj%/entity/MSTeamsMessage_entity/entityfields/loadnext/onActionProcess.js</onActionProcess>
+    </entityActionField>
+    <entityActionField>
+      <name>loadPrevious</name>
+      <title>Prev</title>
+    </entityActionField>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
diff --git a/entity/MSTeamsMessage_entity/entityfields/importmessages/onActionProcess.js b/entity/MSTeamsMessage_entity/entityfields/importmessages/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..8b5a94d660b9cbd5ef4a49457965ad8bd4767f0e
--- /dev/null
+++ b/entity/MSTeamsMessage_entity/entityfields/importmessages/onActionProcess.js
@@ -0,0 +1,23 @@
+import("Sql_lib");
+import("system.datetime");
+import("system.neon");
+import("Util_lib");
+import("system.vars");
+
+var messages = vars.get("$sys.selection");
+var description = messages.map(function (id)
+{
+    var [user, date, message] = JSON.parse(id);
+    date = Date.parse(date).valueOf();
+    return "[" + datetime.toDate(date, "dd.MM.yyyy HH:mm") + "] " + user + "<br>" + message + "<br>";
+}).join("<br>");
+
+var links = newSelect(["OBJECT_TYPE", "OBJECT_ROWID"])
+    .from("MST_TEAMLINK")
+    .where("MST_TEAMLINK.MST_TEAM_ID", vars.get("$param.TeamId_param"))
+    .table();
+
+neon.openContext("Activity", "ActivityEdit_view", null, neon.OPERATINGSTATE_NEW, {
+    "Info_param": description,
+    "PresetLinks_param": JSON.stringify(links)
+});
\ No newline at end of file
diff --git a/entity/MSTeamsMessage_entity/entityfields/loadnext/onActionProcess.js b/entity/MSTeamsMessage_entity/entityfields/loadnext/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/entity/MSTeamsMessage_entity/recordcontainers/jdito/contentProcess.js b/entity/MSTeamsMessage_entity/recordcontainers/jdito/contentProcess.js
index d8c0bad8a65f7fb8ad38753f002d20f1eb5f505a..0007cf9a2d5994cbbf002e496d12620d49ee358c 100644
--- a/entity/MSTeamsMessage_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/MSTeamsMessage_entity/recordcontainers/jdito/contentProcess.js
@@ -31,7 +31,7 @@ else if (vars.get("$param.TeamId_param") && vars.get("$param.Channel_param"))
 messages = messages.map(function (message)
 {
     return [
-        util.getNewUUID(), 
+        JSON.stringify([message.author.userName, message.createdDateTime, message.message.message]), 
         message.author.userName, 
         message.message.message, 
         Date.parse(message.createdDateTime).toString()
diff --git a/entity/Notification_entity/Notification_entity.aod b/entity/Notification_entity/Notification_entity.aod
index 2668a0419e9a0b0d0d74c0f6f25867fd05c13faf..07dd08d1d45a3f702685d1a844e52d28ff548ddf 100644
--- a/entity/Notification_entity/Notification_entity.aod
+++ b/entity/Notification_entity/Notification_entity.aod
@@ -173,6 +173,7 @@
     <entityField>
       <name>SUBCATEGORY</name>
       <title>Subcategory</title>
+      <groupable v="true" />
     </entityField>
   </entityFields>
   <recordContainers>
diff --git a/entity/ObjectTree_entity/entityfields/target_context/valueProcess.js b/entity/ObjectTree_entity/entityfields/target_context/valueProcess.js
index 700dc7461b5f61b17ead3d2735ef8fd2eb7ac6f6..cd4083fad2fbb15ab6da846ce70808957582da6a 100644
--- a/entity/ObjectTree_entity/entityfields/target_context/valueProcess.js
+++ b/entity/ObjectTree_entity/entityfields/target_context/valueProcess.js
@@ -5,5 +5,9 @@ import("ObjectRelation_lib");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
 {
-    result.string(ObjectRelationUtils.getRelationType(vars.get("$field.OBJECTRELATIONTYPEID"))[6]);
+    var relationType = ObjectRelationUtils.getRelationType(vars.get("$field.OBJECTRELATIONTYPEID"));
+    if(relationType[3] == "reverse")
+        result.string(ObjectRelationUtils.getRelationType(vars.get("$field.OBJECTRELATIONTYPEID"))[5]);
+    else
+        result.string(ObjectRelationUtils.getRelationType(vars.get("$field.OBJECTRELATIONTYPEID"))[6]);
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index 4dea791122c221136088882e9d8718097154f65c..2cfb61b2ae7d1ad11c1c3dea35fa7840de750c82 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -98,6 +98,7 @@
       <contentType>NUMBER</contentType>
       <inputFormat>#,##0.00</inputFormat>
       <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/vat/stateProcess.js</stateProcess>
       <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/vat/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
@@ -145,6 +146,10 @@
           <name>Language_param</name>
           <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/offeritems/children/language_param/valueProcess.js</valueProcess>
         </entityParameter>
+        <entityParameter>
+          <name>Discount_param</name>
+          <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/offeritems/children/discount_param/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
       <dependency>
         <name>dependency</name>
@@ -164,7 +169,7 @@
       <contentType>NUMBER</contentType>
       <outputFormat>#,##0.00</outputFormat>
       <inputFormat>#,##0.00</inputFormat>
-      <groupable v="true" />
+      <groupable v="false" />
       <state>READONLY</state>
       <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/net/displayValueProcess.js</displayValueProcess>
     </entityField>
@@ -1056,6 +1061,45 @@
     <entityField>
       <name>ACTIVE</name>
     </entityField>
+    <entityField>
+      <name>DISCOUNT</name>
+      <title>Discount</title>
+      <contentType>NUMBER</contentType>
+      <outputFormat>0.00'%'</outputFormat>
+      <inputFormat>0.00</inputFormat>
+      <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/discount/valueProcess.js</valueProcess>
+      <onValueChange>%aditoprj%/entity/Offer_entity/entityfields/discount/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+      </onValueChangeTypes>
+      <onValidation>%aditoprj%/entity/Offer_entity/entityfields/discount/onValidation.js</onValidation>
+    </entityField>
+    <entityField>
+      <name>DISCOUNTED_NET</name>
+      <title>discounted Price</title>
+      <contentType>NUMBER</contentType>
+      <outputFormat>#,##0.00</outputFormat>
+      <inputFormat>#,##0.00</inputFormat>
+      <state>READONLY</state>
+      <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/discounted_net/stateProcess.js</stateProcess>
+      <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/discounted_net/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityParameter>
+      <name>Discount_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>DiscountChanged</name>
+    </entityField>
+    <entityField>
+      <name>DISCOUNTED_VAT</name>
+      <title>discounted Vat</title>
+      <contentType>NUMBER</contentType>
+      <inputFormat>#,##0.00</inputFormat>
+      <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/discounted_vat/stateProcess.js</stateProcess>
+      <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/discounted_vat/displayValueProcess.js</displayValueProcess>
+    </entityField>
     <entityConsumer>
       <name>Products</name>
       <children>
@@ -1326,6 +1370,18 @@
           <name>ACTIVE.value</name>
           <expression>%aditoprj%/entity/Offer_entity/recordcontainers/db/recordfieldmappings/active.value/expression.js</expression>
         </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DISCOUNTED_NET.value</name>
+          <recordfield>OFFER.DISCOUNTED_NET</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DISCOUNT.value</name>
+          <recordfield>OFFER.DISCOUNT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DISCOUNTED_VAT.value</name>
+          <recordfield>OFFER.DISCOUNTED_VAT</recordfield>
+        </dbRecordFieldMapping>
       </recordFieldMappings>
       <filterExtensions>
         <filterExtensionSet>
diff --git a/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js b/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js
index d610943f3409687827462179063e28df0aa3dde8..1b596584b051bec97da19e07429f38fecb1a9894 100644
--- a/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js
+++ b/entity/Offer_entity/entityfields/copyoffer/onActionProcess.js
@@ -1,8 +1,8 @@
 import("system.vars");
+import("system.neon");
 import("Offer_lib");
 
 var offerId = vars.getString("$field.OFFERID");
-
 var fieldValues = {
     contactId: vars.getString("$field.CONTACT_ID"),
     language: vars.getString("$field.ISOLANGUAGE"),
@@ -12,7 +12,9 @@ var fieldValues = {
     deliveryTerm: vars.getString("$field.DELIVERYTERMS"),
     paymentTerm: vars.getString("$field.PAYMENTTERMS"),
     objectRowId: vars.getString("$field.OBJECT_ROWID"),
-    objectType: vars.getString("$field.OBJECT_TYPE")
+    objectType: vars.getString("$field.OBJECT_TYPE"),
+    discount: vars.getString("$field.DISCOUNT")
+    
 };
 
 OfferUtils.copyOffer(offerId, fieldValues);
diff --git a/entity/Offer_entity/entityfields/discount/onValidation.js b/entity/Offer_entity/entityfields/discount/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..595a5d9aae549242aaa2246e2e4b6e6d602249a0
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discount/onValidation.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.vars");
+import("Util_lib");
+import("Entity_lib");
+
+var value = vars.get("local.value");
+var validationResult = NumberUtils.validateIsBetweenFloat("Discount", value, 0, 100);
+
+if (validationResult)
+    result.string(validationResult);
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/discount/onValueChange.js b/entity/Offer_entity/entityfields/discount/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..5fc7651884946ad0f59a3f5c51b5bb93f0505c30
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discount/onValueChange.js
@@ -0,0 +1,5 @@
+import("system.neon");
+import("system.vars");
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon. OPERATINGSTATE_EDIT){
+    neon.setFieldValue("$field.DiscountChanged", "true");
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/discount/valueProcess.js b/entity/Offer_entity/entityfields/discount/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..fa96d16798f8258f091583613760f918dc4a8126
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discount/valueProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+    
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.Discount_param")
+    && vars.get("$param.Discount_param")){
+    result.string(vars.get("$param.Discount_param"));
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/discounted_net/displayValueProcess.js b/entity/Offer_entity/entityfields/discounted_net/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c7473e812c66616164442674dc87bdd5282dc50d
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discounted_net/displayValueProcess.js
@@ -0,0 +1,6 @@
+import("Util_lib");
+import("system.vars");
+import("system.translate");
+import("system.result");
+
+result.string(NumberUtils.formatWithCurrency(vars.get("$field.DISCOUNTED_NET"), translate.text("#,##0.00"), vars.get("$field.CURRENCY")));
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/discounted_net/stateProcess.js b/entity/Offer_entity/entityfields/discounted_net/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7443b0c0dcb6c9e38045968ddaa64b5763dfd85e
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discounted_net/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.vars");
+import("system.neon");
+import("system.result");
+
+var discount = vars.get("$field.DISCOUNT");
+
+if(parseInt(discount) == parseInt("0") || !discount)
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+else 
+    result.string(neon.COMPONENTSTATE_READONLY);
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/discounted_vat/displayValueProcess.js b/entity/Offer_entity/entityfields/discounted_vat/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..730396f16084a8c954d9cd54640efdd758e8cb52
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discounted_vat/displayValueProcess.js
@@ -0,0 +1,6 @@
+import("Util_lib");
+import("system.vars");
+import("system.translate");
+import("system.result");
+
+result.string(NumberUtils.formatWithCurrency(vars.get("$field.DISCOUNTED_VAT"), translate.text("#,##0.00"), vars.get("$field.CURRENCY")));
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/discounted_vat/stateProcess.js b/entity/Offer_entity/entityfields/discounted_vat/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7443b0c0dcb6c9e38045968ddaa64b5763dfd85e
--- /dev/null
+++ b/entity/Offer_entity/entityfields/discounted_vat/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.vars");
+import("system.neon");
+import("system.result");
+
+var discount = vars.get("$field.DISCOUNT");
+
+if(parseInt(discount) == parseInt("0") || !discount)
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+else 
+    result.string(neon.COMPONENTSTATE_READONLY);
\ 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 5a7493c41130f53a5a877ad0823f5783c8c80c02..02f67ef9c37049f446df6879107ff67b6032e91e 100644
--- a/entity/Offer_entity/entityfields/newofferversion/onActionProcess.js
+++ b/entity/Offer_entity/entityfields/newofferversion/onActionProcess.js
@@ -15,6 +15,7 @@ var params = {
     "OfferHeader_param" : vars.get("$field.HEADER"),
     "OfferFooter_param" : vars.get("$field.FOOTER"),
     "OfferDeliveryTerm_param" : vars.get("$field.DELIVERYTERMS"),
-    "OfferPaymentTerm_param" : vars.get("$field.PAYMENTTERMS")
+    "OfferPaymentTerm_param" : vars.get("$field.PAYMENTTERMS"),
+    "Discount_param": vars.get("$field.DISCOUNT")
 }
 neon.openContext("Offer", null, null, neon.OPERATINGSTATE_NEW, params);
\ No newline at end of file
diff --git a/entity/Role_entity/entityfields/permissionoverviews/children/roletitle_param/valueProcess.js b/entity/Offer_entity/entityfields/offeritems/children/discount_param/valueProcess.js
similarity index 51%
rename from entity/Role_entity/entityfields/permissionoverviews/children/roletitle_param/valueProcess.js
rename to entity/Offer_entity/entityfields/offeritems/children/discount_param/valueProcess.js
index c4fc6bffb984a2312dbe938d59b5770b9703ce50..67b63c37f044f7d1f4e807d7a863457a78552701 100644
--- a/entity/Role_entity/entityfields/permissionoverviews/children/roletitle_param/valueProcess.js
+++ b/entity/Offer_entity/entityfields/offeritems/children/discount_param/valueProcess.js
@@ -1,4 +1,4 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.ROLENAME"));
\ No newline at end of file
+import("system.result");
+import("system.vars");
+
+result.string(vars.get("$field.DISCOUNT"));
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/totalgross/valueProcess.js b/entity/Offer_entity/entityfields/totalgross/valueProcess.js
index 6e374c8f50a610ed0f50b89319726224167631d0..9d6a6c9330d2fd3eb57fa5f5102e55ad5eb0ef3b 100644
--- a/entity/Offer_entity/entityfields/totalgross/valueProcess.js
+++ b/entity/Offer_entity/entityfields/totalgross/valueProcess.js
@@ -2,7 +2,8 @@ import("system.result");
 import("system.vars");
 import("system.eMath");
 
-var netValue = vars.get("$field.NET");
-var vatValue = vars.get("$field.VAT");
+var discount = vars.get("$field.DISCOUNT");
+var netValue = discount && parseInt(discount) != parseInt("0")  ? vars.get("$field.DISCOUNTED_NET") : vars.get("$field.NET")
+var vatValue =  discount && parseInt(discount) != parseInt("0") ? vars.get("$field.DISCOUNTED_VAT") : vars.get("$field.VAT");
 
 result.string( eMath.addDec(netValue, vatValue) );
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/vat/stateProcess.js b/entity/Offer_entity/entityfields/vat/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..42a2d8e6788a09e0c2c8b410c5e4eadb7bfeb115
--- /dev/null
+++ b/entity/Offer_entity/entityfields/vat/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.neon");
+import("system.result");
+import("system.vars");
+var discount = vars.get("$field.DISCOUNT");
+
+if(discount && parseInt(discount) != parseInt("0")){
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
+}
+else 
+    result.string(neon.COMPONENTSTATE_READONLY)
\ No newline at end of file
diff --git a/entity/Offer_entity/recordcontainers/db/onDBInsert.js b/entity/Offer_entity/recordcontainers/db/onDBInsert.js
index da551808a8c82e05a35c7aecf40d283434b2f4c0..c7d3c3336eadfb5bc6b41deaec997081f23c491b 100644
--- a/entity/Offer_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Offer_entity/recordcontainers/db/onDBInsert.js
@@ -1,17 +1,20 @@
 import("Context_lib");
 import("system.workflow");
 import("Workflow_lib");
+import("system.db");
 import("system.datetime");
+import("system.util");
 import("system.neon");
 import("system.vars");
 import("Offer_lib");
-import("Sql_lib");
 
+var rowdata = vars.get("$local.rowdata");
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
 {
     var offerId = vars.get("$local.uid");
-    if (vars.exists("$param.OfferOriginal_Id_param"))
-        OfferUtils.copyOfferItems(vars.getString("$param.OfferOriginal_Id_param"), offerId);
+    var discount = rowdata["OFFER.DISCOUNT"];
+    if (vars.exists("$param.OfferOriginal_Id_param") && vars.get("$param.OfferOriginal_Id_param"))
+        OfferUtils.copyOfferItems(vars.getString("$param.OfferOriginal_Id_param"), offerId, discount);
     
     var activityId = vars.get("$param.ActivityId_param");
     if (activityId)
diff --git a/entity/Offer_entity/recordcontainers/db/onDBUpdate.js b/entity/Offer_entity/recordcontainers/db/onDBUpdate.js
index 2e53f3cad9a9edf21cc5bbc6fdecc00c5001dfee..866c488632bc1e0629e2bfd4b4681a8f3baad6a5 100644
--- a/entity/Offer_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Offer_entity/recordcontainers/db/onDBUpdate.js
@@ -1,3 +1,38 @@
+import("system.entities");
+import("Offer_lib");
+import("system.vars");
 import("Workflow_lib");
 
+var rowdata = vars.get("$local.rowdata");
+var oid = rowdata["OFFER.OFFERID"];
+if(vars.get("$field.DiscountChanged") == "true" && oid){
+    var discount = rowdata["OFFER.DISCOUNT"];
+    var oiUtils = new OfferItemUtils(oid);  
+    
+    var vals = oiUtils.getNetAndVat();
+    var discountedVals = OfferItemUtils.getDiscountedNet(null, oid, discount);
+    
+    let config = entities.createConfigForUpdatingRows();
+    config.entity("Offer_entity");
+    if(discountedVals){
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1],
+            "DISCOUNTED_NET": discountedVals[0],
+            "DISCOUNTED_VAT": discountedVals[1]
+        });
+    }
+    else 
+    {
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1]
+        });
+    }
+
+    config.uid(oid);
+    entities.updateRow(config);
+
+}
+
 WorkflowSignalSender.updated();
\ No newline at end of file
diff --git a/entity/Offeritem_entity/Offeritem_entity.aod b/entity/Offeritem_entity/Offeritem_entity.aod
index c74679b2c4b96dd239b3a54ead4b7934ae090958..648d3ef347fe73ceaf135c1967ab8f4c65d57e76 100644
--- a/entity/Offeritem_entity/Offeritem_entity.aod
+++ b/entity/Offeritem_entity/Offeritem_entity.aod
@@ -254,6 +254,10 @@
       <name>ProductId_param</name>
       <expose v="true" />
     </entityParameter>
+    <entityParameter>
+      <name>Discount_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Offeritem_entity/recordcontainers/db/onDBDelete.js b/entity/Offeritem_entity/recordcontainers/db/onDBDelete.js
index 88f823f4fb90b6fcbd3e10b059a1bbf3df190dc0..283d1cb7a7cdb0568b117c1f8001fe4f7a2ef796 100644
--- a/entity/Offeritem_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Offeritem_entity/recordcontainers/db/onDBDelete.js
@@ -1,3 +1,4 @@
+import("system.entities");
 import("system.neon");
 import("system.vars");
 import("system.db");
@@ -8,6 +9,7 @@ var oid = vars.get("$field.OFFER_ID");
 if(oid != "")
 {
     var oiid = vars.get("$field.OFFERITEMID");
+    var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): "";
     var oiUtils = new OfferItemUtils(oid);
     var deletedIds = oiUtils.deletePartsList(oiid);
     oiUtils.reOrgItems();
@@ -15,8 +17,27 @@ if(oid != "")
     deletedIds.push(oiid);
     var cols = ["NET", "VAT"];
     
-    var vals = oiUtils.getNetAndVat(deletedIds);
+    var vals = oiUtils.getNetAndVat(deletedIds);    
+    var discountedVals = OfferItemUtils.getDiscountedNet(deletedIds, oid, discount);
     
-    newWhere("OFFER.OFFERID", oid)
-        .updateData(true, "OFFER", cols, null, vals)
+    let config = entities.createConfigForUpdatingRows()
+    config.entity("Offer_entity");
+    
+    if(discountedVals){
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1],
+            "DISCOUNTED_NET": discountedVals[0],
+            "DISCOUNTED_VAT": discountedVals[1]
+        });
+    }
+    else{
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1]
+        });
+    }
+    config.uid(oid);
+    entities.updateRow(config);
+
 }
\ No newline at end of file
diff --git a/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js b/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js
index 473b49850845193bb86ddee243f668ae206617e4..f7e305e7c5ecac3ab334df84828152e91e3e9d30 100644
--- a/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js
@@ -1,3 +1,4 @@
+import("system.entities");
 import("system.datetime");
 import("system.neon");
 import("system.vars");
@@ -14,14 +15,34 @@ if(oid != "")
 {
     var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
     var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
+    var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): "";
     var oiUtils = new OfferItemUtils(rowdata["OFFERITEM.OFFER_ID"]);    
     oiUtils.insertPartsList(rowdata["OFFERITEM.PRODUCT_ID"], vars.get("$local.uid"), curr, contactid, vars.get("$param.Language_param"));
     oiUtils.reOrgItems();
     
     //update offer price
     var vals = oiUtils.getNetAndVat();
-    var cols = ["NET", "VAT"];
+    var discountedVals = OfferItemUtils.getDiscountedNet(null, oid,  discount);
+    
+    let config = entities.createConfigForUpdatingRows()
+    config.entity("Offer_entity");
+
+    if(discountedVals){
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1],
+            "DISCOUNTED_NET": discountedVals[0],
+            "DISCOUNTED_VAT": discountedVals[1]
+        });
+    }
+    else{
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1]
+        });
+
+    }
+    config.uid(oid);
+    entities.updateRow(config);
 
-    newWhere("OFFER.OFFERID", oid)
-        .updateData(true, "OFFER", cols, null, vals);    
 }
\ No newline at end of file
diff --git a/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js b/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js
index a1e94cd51186a9e57ee45df344263e3cc26d79b9..a004c7c8b6e4ca57eb19c52f75ef55dafded35b8 100644
--- a/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js
@@ -1,3 +1,4 @@
+import("system.entities");
 import("system.vars");
 import("system.db");
 import("system.neon");
@@ -7,9 +8,30 @@ import("Sql_lib");
 var oid = vars.get("$field.OFFER_ID");
 if(oid != "")
 {
+    var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): "";
     var cols = ["NET", "VAT"];    
     var oiUtils = new OfferItemUtils(oid);
+    var vals = oiUtils.getNetAndVat();
+    var discountedVals = OfferItemUtils.getDiscountedNet(null, oid, discount);
     
-    newWhere("OFFER.OFFERID", oid)
-        .updateData(true, "OFFER", cols, null, oiUtils.getNetAndVat());    
+    let config = entities.createConfigForUpdatingRows()
+    config.entity("Offer_entity");
+    
+    if(discountedVals){
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1],
+            "DISCOUNTED_NET": discountedVals[0],
+            "DISCOUNTED_VAT": discountedVals[1]
+        });
+    }
+    else{
+        config.fieldValues({
+            "NET": vals[0],
+            "VAT": vals[1]
+        });
+    }
+    config.uid(oid);
+    entities.updateRow(config);
+ 
 }
\ No newline at end of file
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index 076fe1f6213c28183ea068723d42855cd05d09c4..3c28665b6f4dafd38a997021fa55dd2fca257d70 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -1807,6 +1807,9 @@
           <indexFieldType>ADDRESS</indexFieldType>
           <isGlobalSearchField v="false" />
         </indexRecordFieldMapping>
+        <indexRecordFieldMapping>
+          <name>PICTURE.value</name>
+        </indexRecordFieldMapping>
       </indexFieldMappings>
     </indexRecordContainer>
   </recordContainers>
diff --git a/entity/Organisation_entity/recordcontainers/index/query.js b/entity/Organisation_entity/recordcontainers/index/query.js
index e26250598edb296c39f96f355d82fae6f096a7df..c2b15cd1890eac332871fee390b5c4137359adec 100644
--- a/entity/Organisation_entity/recordcontainers/index/query.js
+++ b/entity/Organisation_entity/recordcontainers/index/query.js
@@ -42,7 +42,7 @@ var querySelect = newSelect([
         sqlHelper.concatWithSeparator([sqlHelper.concatWithSeparator(["standardAddress.ADDRESS", "standardAddress.BUILDINGNO"])
             ,sqlHelper.concatWithSeparator(["standardAddress.COUNTRY", "standardAddress.ZIP", "standardAddress.CITY"])
         ], " - ")
-    ])
+    , "ORGANISATION.PICTURE"])
     .from("ORGANISATION")
     .join("CONTACT", "CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID and CONTACT.PERSON_ID is null")
     .leftJoin("ADDRESS", "standardAddress.ADDRESSID = CONTACT.ADDRESS_ID", "standardAddress")
diff --git a/entity/PermissionDetail_entity/PermissionDetail_entity.aod b/entity/PermissionDetail_entity/PermissionDetail_entity.aod
index e18801ffb9cab3450e4dc8c5dbe77069c76add1b..2adfbf836586ba40322bbdfd1e2d28fb40bff967 100644
--- a/entity/PermissionDetail_entity/PermissionDetail_entity.aod
+++ b/entity/PermissionDetail_entity/PermissionDetail_entity.aod
@@ -110,7 +110,7 @@
       </dependencies>
     </entityProvider>
     <entityParameter>
-      <name>RoleTitle_param</name>
+      <name>RoleName_param</name>
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
@@ -133,7 +133,7 @@
       </dependency>
     </entityConsumer>
     <entityParameter>
-      <name>EntityTitle_param</name>
+      <name>EntityId_param</name>
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
diff --git a/entity/PermissionDetail_entity/contentTitleProcess.js b/entity/PermissionDetail_entity/contentTitleProcess.js
index 327e3f48bfe87797eb4f122b038302ea716de517..4ab83eef7bd698f6e11166a888ecbf502ba578bb 100644
--- a/entity/PermissionDetail_entity/contentTitleProcess.js
+++ b/entity/PermissionDetail_entity/contentTitleProcess.js
@@ -6,18 +6,21 @@ import("system.result");
 
 var res = "";
 var entityName = vars.get("$field.ENTITY");
+var roleName = vars.get("$field.ROLE");
+var accesstype = vars.get("$field.ACCESSTYPE");
+var cond = vars.get("$field.CONDITION");
 var emptyCond = PermissionUtil.getEmptyCondString(entityName);
 
-switch (vars.get("$field.ACCESSTYPE")) {
+switch (accesstype) {
     case "E":
-        if (vars.get("$param.RoleTitle_param") && vars.get("$field.ENTITY") != "") {
-            res += vars.get("$field.ENTITY");
-        } else if (vars.get("$param.EntityTitle_param") && vars.get("$field.ROLE") != "") {
-            res += vars.get("$field.ROLE");
-        } else if (vars.get("$field.ROLE") != "") {
-            res += vars.get("$field.ROLE");
-        } else if (vars.get("$field.ENTITY") != "") {
-            res += vars.get("$field.ENTITY");
+        if (vars.get("$param.RoleName_param") && entityName != "") {
+            res += entityName;
+        } else if (vars.get("$param.EntityId_param") && roleName != "") {
+            res += roleName;
+        } else if (roleName != "") {
+            res += roleName;
+        } else if (entityName != "") {
+            res += entityName;
         }
         break;
     case "R":
@@ -31,8 +34,8 @@ switch (vars.get("$field.ACCESSTYPE")) {
         break;
 }
 
-if (vars.get("$field.ACCESSTYPE") != "E") {
-    if (vars.get("$field.CONDITION") != emptyCond && vars.get("$field.CONDITION") != "") {
+if (accesstype != "E") {
+    if (cond != emptyCond && cond != "") {
         res += " - conditional";
     } else {
         res += " - default";
diff --git a/entity/PermissionDetail_entity/entityfields/accesstype/displayValueProcess.js b/entity/PermissionDetail_entity/entityfields/accesstype/displayValueProcess.js
index 366a3b45d7d89260fedc3f340331ff5d67f22f55..a559d0e548e50f9100892d4f684a222c0477f25d 100644
--- a/entity/PermissionDetail_entity/entityfields/accesstype/displayValueProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/accesstype/displayValueProcess.js
@@ -10,7 +10,11 @@ var roleName = vars.get("$field.ROLE");
 var entity = vars.get("$field.ENTITY");
 var accesstype = vars.get("$field.ACCESSTYPE");
 
-if (operatingState == neon.OPERATINGSTATE_SEARCH || operatingState == neon.OPERATINGSTATE_VIEW) {
+if (
+    operatingState == neon.OPERATINGSTATE_SEARCH ||
+    operatingState == neon.OPERATINGSTATE_VIEW ||
+    operatingState == neon.OPERATINGSTATE_EDIT
+    ) {
     switch (accesstype) {
         case "E":
             result.string(translate.text("Entity"));
@@ -23,7 +27,7 @@ if (operatingState == neon.OPERATINGSTATE_SEARCH || operatingState == neon.OPERA
             break;
     }
 } else {
-    // editing/creating a new permission
+    // creating a new permission
     // if there is no permission set for a given role-entity-combination or only one with condtype 0 -> permission has to be Entity
     // otherwise Record
     // if $field.FIELD is filled, then its a permission on Field access level
diff --git a/entity/PermissionDetail_entity/entityfields/entity/displayValueProcess.js b/entity/PermissionDetail_entity/entityfields/entity/displayValueProcess.js
index d6e5c24e75eed9d70d14526054b11a129a22f83b..9af4d04f98f855a4ac508c84de3efe76fa26ecdc 100644
--- a/entity/PermissionDetail_entity/entityfields/entity/displayValueProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/entity/displayValueProcess.js
@@ -5,8 +5,8 @@ import("system.neon");
 var recordstate = vars.get("$sys.recordstate");
 var entity = "";
 
-if(vars.exists("$param.EntityTitle_param") && recordstate == neon.OPERATINGSTATE_NEW) {
-    entity = vars.get("$param.EntityTitle_param"); 
+if(vars.exists("$param.EntityId_param") && recordstate == neon.OPERATINGSTATE_NEW) {
+    entity = vars.get("$param.EntityId_param"); 
 } else {
     entity = vars.get("$field.ENTITY");
 }
diff --git a/entity/PermissionDetail_entity/entityfields/entity/stateProcess.js b/entity/PermissionDetail_entity/entityfields/entity/stateProcess.js
index 943bb0881702bf7d6a70344f64c3d99834e6834b..81377c2374ab5fb09010365597bd8ea59d280baf 100644
--- a/entity/PermissionDetail_entity/entityfields/entity/stateProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/entity/stateProcess.js
@@ -2,7 +2,7 @@ import("system.result");
 import("system.vars");
 import("system.neon");
 
-var entityTitle = vars.get("$param.EntityTitle_param");
+var entityTitle = vars.get("$param.EntityId_param");
 
 if (entityTitle != undefined && entityTitle != null && entityTitle != "") {
     result.string(neon.COMPONENTSTATE_READONLY);
diff --git a/entity/PermissionDetail_entity/entityfields/entity/valueProcess.js b/entity/PermissionDetail_entity/entityfields/entity/valueProcess.js
index d6e5c24e75eed9d70d14526054b11a129a22f83b..9af4d04f98f855a4ac508c84de3efe76fa26ecdc 100644
--- a/entity/PermissionDetail_entity/entityfields/entity/valueProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/entity/valueProcess.js
@@ -5,8 +5,8 @@ import("system.neon");
 var recordstate = vars.get("$sys.recordstate");
 var entity = "";
 
-if(vars.exists("$param.EntityTitle_param") && recordstate == neon.OPERATINGSTATE_NEW) {
-    entity = vars.get("$param.EntityTitle_param"); 
+if(vars.exists("$param.EntityId_param") && recordstate == neon.OPERATINGSTATE_NEW) {
+    entity = vars.get("$param.EntityId_param"); 
 } else {
     entity = vars.get("$field.ENTITY");
 }
diff --git a/entity/PermissionDetail_entity/entityfields/role/displayValueProcess.js b/entity/PermissionDetail_entity/entityfields/role/displayValueProcess.js
index 2451eaf8b61ddfb81691af626c0e388f80b07cc1..dd624541a8d9d3bc51548ef10d3d536cd41f7f4a 100644
--- a/entity/PermissionDetail_entity/entityfields/role/displayValueProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/role/displayValueProcess.js
@@ -6,8 +6,8 @@ import("system.neon");
 var recordstate = vars.get("$sys.recordstate");
 var role = "";
 
-if (vars.exists("$param.RoleTitle_param") && recordstate == neon.OPERATINGSTATE_NEW) {
-    role = vars.get("$param.RoleTitle_param");
+if (vars.exists("$param.RoleName_param") && recordstate == neon.OPERATINGSTATE_NEW) {
+    role = vars.get("$param.RoleName_param");
 } else {
     role = vars.get("$this.value"); // this.value is already role title - role name gets converted to role title in contentProcess
 }
diff --git a/entity/PermissionDetail_entity/entityfields/role/stateProcess.js b/entity/PermissionDetail_entity/entityfields/role/stateProcess.js
index f5fec84a8c27d08002a0d7e50ab9aa4839078944..2a216166d092e128f9b3d2d8f544b6a8c8c7ddad 100644
--- a/entity/PermissionDetail_entity/entityfields/role/stateProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/role/stateProcess.js
@@ -2,7 +2,7 @@ import("system.result");
 import("system.vars");
 import("system.neon");
 
-var roleTitle = vars.get("$param.RoleTitle_param");
+var roleTitle = vars.get("$param.RoleName_param");
 
 if (roleTitle != undefined && roleTitle != null && roleTitle != "") {
     result.string(neon.COMPONENTSTATE_READONLY);
diff --git a/entity/PermissionDetail_entity/entityfields/role/valueProcess.js b/entity/PermissionDetail_entity/entityfields/role/valueProcess.js
index 83a1eb4e203e560ee9f4be26a3e1fed3886bbe8e..a085bf7a670d5f99bee99966ea01e134a3af6e8e 100644
--- a/entity/PermissionDetail_entity/entityfields/role/valueProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/role/valueProcess.js
@@ -6,8 +6,8 @@ import("system.neon");
 var recordstate = vars.get("$sys.recordstate");
 var role = "";
 
-if (vars.exists("$param.RoleTitle_param") && recordstate == neon.OPERATINGSTATE_NEW) {
-    role = vars.get("$param.RoleTitle_param");
+if (vars.exists("$param.RoleName_param") && recordstate == neon.OPERATINGSTATE_NEW) {
+    role = vars.get("$param.RoleName_param");
 } else {
     role = PermissionUtil.resolveRoleTitle(vars.get("$this.value"));
 }
diff --git a/entity/PermissionDetail_entity/iconIdProcess.js b/entity/PermissionDetail_entity/iconIdProcess.js
index a1d937f1db6a42a70921758a3cf759f1701701ad..a52fc0e601bfdae5f3d3676d6ca0ec9b3e9ceff1 100644
--- a/entity/PermissionDetail_entity/iconIdProcess.js
+++ b/entity/PermissionDetail_entity/iconIdProcess.js
@@ -3,9 +3,9 @@ import("system.result");
 
 switch (vars.get("$field.ACCESSTYPE")) {
     case "E":
-        if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) {
+        if (vars.exists("$param.RoleName_param") && vars.get("$param.RoleName_param")) {
             result.string("VAADIN:CONNECT");
-        } else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) {
+        } else if (vars.exists("$param.EntityId_param") && vars.get("$param.EntityId_param")) {
             result.string("VAADIN:USER_CHECK");
         }
         break;
diff --git a/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js b/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js
index af8f904bf6b375b2f4ffd304214a0879a3f6d5cf..64e6cf96666fb928990c9c5b01372351b4050c4e 100644
--- a/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js
@@ -52,10 +52,10 @@ else if (entitiesUsePermFlagSet.length > 0)
     querySelect.and(newWhereIfSet("ASYS_PERMISSIONSET.FIELD_ID", fieldsUsePermFlagSet, SqlBuilder.IN(), undefined, alias)
                               .or("FIELD_ID is NULL"));
     
-    if (vars.get("$param.RoleTitle_param")) {
-        querySelect.and("ASYS_PERMISSIONSET.ROLE_ID", "$param.RoleTitle_param")
-    } else if (vars.get("$param.EntityTitle_param")) {
-        querySelect.and("ASYS_PERMISSIONSET.ENTITY_ID", "$param.EntityTitle_param")
+    if (vars.get("$param.RoleName_param")) {
+        querySelect.and("ASYS_PERMISSIONSET.ROLE_ID", "$param.RoleName_param")
+    } else if (vars.get("$param.EntityId_param")) {
+        querySelect.and("ASYS_PERMISSIONSET.ENTITY_ID", "$param.EntityId_param")
     }
     
     // get all permissions which are already in db
@@ -206,7 +206,7 @@ function sortResultsByCondition(a, b) {
 }
 
 function sortResultByTitleAlphabetically(a, b) {
-    if (vars.get("$param.RoleTitle_param")) {
+    if (vars.get("$param.RoleName_param")) {
         if (a[1] < b[1]) return -1;
         if (a[1] > b[1]) return 1;
         return 0;
diff --git a/entity/PermissionMetaData_entity/PermissionMetaData_entity.aod b/entity/PermissionMetaData_entity/PermissionMetaData_entity.aod
index b2006b9d74a349c0fd3b27a7ceca370802b5c8d6..36e70416b835fd711ead67d87f15d54b0cabb3f1 100644
--- a/entity/PermissionMetaData_entity/PermissionMetaData_entity.aod
+++ b/entity/PermissionMetaData_entity/PermissionMetaData_entity.aod
@@ -57,7 +57,7 @@
       </dependency>
       <children>
         <entityParameter>
-          <name>EntityTitle_param</name>
+          <name>EntityId_param</name>
           <valueProcess>%aditoprj%/entity/PermissionMetaData_entity/entityfields/permissionoverviews/children/entitytitle_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
@@ -72,7 +72,7 @@
       </dependency>
       <children>
         <entityParameter>
-          <name>EntityTitle_param</name>
+          <name>EntityId_param</name>
           <valueProcess>%aditoprj%/entity/PermissionMetaData_entity/entityfields/permissiondetails/children/entitytitle_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
diff --git a/entity/PermissionOverview_entity/PermissionOverview_entity.aod b/entity/PermissionOverview_entity/PermissionOverview_entity.aod
index 70dfee92a9a3555047c7503b3f829a8ff6be0df7..f0e8a0786144a64086670e6506476e93f625f4de 100644
--- a/entity/PermissionOverview_entity/PermissionOverview_entity.aod
+++ b/entity/PermissionOverview_entity/PermissionOverview_entity.aod
@@ -76,12 +76,12 @@
       </dependencies>
     </entityProvider>
     <entityParameter>
-      <name>RoleTitle_param</name>
+      <name>RoleName_param</name>
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
     <entityParameter>
-      <name>EntityTitle_param</name>
+      <name>EntityId_param</name>
       <expose v="true" />
       <description>PARAMETER</description>
     </entityParameter>
diff --git a/entity/PermissionOverview_entity/entityfields/entity/titleProcess.js b/entity/PermissionOverview_entity/entityfields/entity/titleProcess.js
index 4dc06d1921917b2bf4fbad084eed77af247ba273..5973b8dab2349f1dc0538156f49abdb96e65740e 100644
--- a/entity/PermissionOverview_entity/entityfields/entity/titleProcess.js
+++ b/entity/PermissionOverview_entity/entityfields/entity/titleProcess.js
@@ -2,8 +2,8 @@ import("system.result");
 import("system.vars");
 import("system.translate");
 
-if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) {
+if (vars.exists("$param.RoleName_param") && vars.get("$param.RoleName_param")) {
     result.string(translate.text("Entity"));
-} else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) {
+} else if (vars.exists("$param.EntityId_param") && vars.get("$param.EntityId_param")) {
     result.string(translate.text("Role"));
 }
\ No newline at end of file
diff --git a/entity/PermissionOverview_entity/iconIdProcess.js b/entity/PermissionOverview_entity/iconIdProcess.js
index df51be0f8f1a0e175ed2c78421459b46cc76721d..48a0dccaacf8b151c0628908159a1ad5899e4fa3 100644
--- a/entity/PermissionOverview_entity/iconIdProcess.js
+++ b/entity/PermissionOverview_entity/iconIdProcess.js
@@ -1,8 +1,8 @@
 import("system.vars");
 import("system.result");
 
-if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) {
+if (vars.exists("$param.RoleName_param") && vars.get("$param.RoleName_param")) {
     result.string("VAADIN:CONNECT");
-} else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) {
+} else if (vars.exists("$param.EntityId_param") && vars.get("$param.EntityId_param")) {
     result.string("VAADIN:USER_CHECK");
 }
\ No newline at end of file
diff --git a/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js b/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js
index 293144a2513456337e2e290106ec4020e21269a3..74858275777a3decccb191074f1cf3c611ca0333 100644
--- a/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js
@@ -25,8 +25,8 @@ for each (let entityMetaData in entitiesMetaData) {
 var rolesOrEntitiesSelect = new SqlBuilder(alias).where();
 var rolesOrEntities = [];
 
-if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) {
-    roleName = vars.getString("$param.RoleTitle_param");
+if (vars.exists("$param.RoleName_param") && vars.get("$param.RoleName_param")) {
+    roleName = vars.getString("$param.RoleName_param");
     if (roleName == roleInternalEveryone) {
         var counter = 0;
         for each (let entityUsePermFlagSet in entitiesUsePermFlagSet) {
@@ -39,8 +39,8 @@ if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param"))
     rolesOrEntitiesSelect.select("distinct ASYS_PERMISSIONSET.ENTITY_ID")
         .from("ASYS_PERMISSIONSET")
         .and("ASYS_PERMISSIONSET.ROLE_ID", roleName);
-} else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) {
-    entityName = vars.getString("$param.EntityTitle_param");
+} else if (vars.exists("$param.EntityId_param") && vars.get("$param.EntityId_param")) {
+    entityName = vars.getString("$param.EntityId_param");
     if (PermissionUtil.getNumberOfPermissions(entityName, roleInternalEveryone) == 0) {
         // no permissions for INTERNAL_EVERYONE found -> display X's for all actions
         res.push(["NOREALPERMINDB", roleInternalEveryone, "VAADIN:CLOSE", "VAADIN:CLOSE", "VAADIN:CLOSE", "VAADIN:CLOSE", "VAADIN:CLOSE"]);
@@ -56,9 +56,9 @@ rolesOrEntities = rolesOrEntitiesSelect
 
 var entityPermSetId = "";
 for each (var entry in rolesOrEntities) { // entry contains either a role or an entity, depending on which param exists
-    if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) {
+    if (vars.exists("$param.RoleName_param") && vars.get("$param.RoleName_param")) {
         entityPermSetId = PermissionUtil.getSetRoot(roleName, entry);
-    } else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) {
+    } else if (vars.exists("$param.EntityId_param") && vars.get("$param.EntityId_param")) {
         entityPermSetId = PermissionUtil.getSetRoot(entry, entityName);
     }
     var recordPermSetId = newSelect("ASYS_PERMISSIONSET.ASYS_PERMISSIONSETID", alias)
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index ccb951171b001f5b1ed08cf8daa5368ae64d7990..b209d491c916e9bb01a4079feb5ab570b0065f62 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -7,6 +7,7 @@
   <title>Contact</title>
   <siblings>
     <element>Address_entity</element>
+    <element>Contact_entity</element>
   </siblings>
   <grantDeleteProcess>%aditoprj%/entity/Person_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Person_entity/contentTitleProcess.js</contentTitleProcess>
@@ -1415,6 +1416,13 @@
         <fieldName>#PROVIDER</fieldName>
       </dependency>
     </entityConsumer>
+    <entityActionField>
+      <name>deleteFunction</name>
+      <title>Delete this Function</title>
+      <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/deletefunction/onActionProcess.js</onActionProcess>
+      <iconId>NEON:TRASH</iconId>
+      <stateProcess>%aditoprj%/entity/Person_entity/entityfields/deletefunction/stateProcess.js</stateProcess>
+    </entityActionField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -1837,6 +1845,9 @@
           </additionalFieldNameAliases>
           <isMultiValued v="true" />
         </indexRecordFieldMapping>
+        <indexRecordFieldMapping>
+          <name>PICTURE.value</name>
+        </indexRecordFieldMapping>
       </indexFieldMappings>
     </indexRecordContainer>
   </recordContainers>
diff --git a/entity/Person_entity/entityfields/deletefunction/onActionProcess.js b/entity/Person_entity/entityfields/deletefunction/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..083e2d8b0d3d0649e0984e06b3947a6ae709fd3e
--- /dev/null
+++ b/entity/Person_entity/entityfields/deletefunction/onActionProcess.js
@@ -0,0 +1,40 @@
+import("system.entities");
+import("system.neon");
+import("Workflow_lib");
+import("Context_lib");
+import("DuplicateScanner_lib");
+import("Sql_lib");
+import("system.vars");
+
+var personId = vars.get("$field.PERSONID");
+
+var contactIds = newSelect("count(CONTACT.CONTACTID)")
+                            .from("CONTACT")
+                            .join("PERSON", "CONTACT.PERSON_ID = PERSON.PERSONID")
+                            .where("PERSON.PERSONID", personId)
+                            .cell();
+if(contactIds > 1)
+{
+    var contactId = vars.get("$field.CONTACTID");
+
+    var config = entities.createConfigForDeletingRows().entity("Contact_entity").uid(contactId);
+    
+    entities.deleteRow(config);
+    
+    DuplicateScannerUtils.deleteCachedDuplicate(contactId);
+
+    new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
+        .deleteAllAttributes();
+
+    newWhere("COMMUNICATION.CONTACT_ID", contactId).deleteData();
+    newWhere("ADDRESS.CONTACT_ID", contactId).deleteData();
+    newWhere("COMMRESTRICTION.CONTACT_ID", contactId).deleteData();
+    newWhere("AB_APPOINTMENTLINK.OBJECT_TYPE", "Person")
+    .and("AB_APPOINTMENTLINK.OBJECT_ROWID", contactId).deleteData();
+    newWhere("AB_ATTRIBUTERELATION.OBJECT_TYPE", "Person")
+    .and("AB_ATTRIBUTERELATION.OBJECT_ROWID", contactId).deleteData();
+
+    WorkflowSignalSender.deleted();
+    
+    neon.closeImage(vars.get("$sys.currentimage"), true); //ToDo: #1070797 This should probably not be necessary 
+}
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/deletefunction/stateProcess.js b/entity/Person_entity/entityfields/deletefunction/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1b946d06bd61d13e75b51286466d8fbcd8d9f41
--- /dev/null
+++ b/entity/Person_entity/entityfields/deletefunction/stateProcess.js
@@ -0,0 +1,20 @@
+import("system.result");
+import("system.neon");
+import("Sql_lib");
+import("system.vars");
+
+var res = neon.COMPONENTSTATE_DISABLED;
+
+var personId = vars.get("$field.PERSONID");
+
+var contactIds = newSelect("count(CONTACT.CONTACTID)")
+                            .from("CONTACT")
+                            .join("PERSON", "CONTACT.PERSON_ID = PERSON.PERSONID")
+                            .where("PERSON.PERSONID", personId)
+                            .cell();
+if(contactIds > 1)
+{
+    res = neon.COMPONENTSTATE_EDITABLE;
+}
+
+result.string(res);
\ No newline at end of file
diff --git a/entity/Person_entity/recordcontainers/index/query.js b/entity/Person_entity/recordcontainers/index/query.js
index e5c704e81ad9981791035100cf08dade778bc713..61ec0a66cbf788e47523eaa832bedf9fcb12e562 100644
--- a/entity/Person_entity/recordcontainers/index/query.js
+++ b/entity/Person_entity/recordcontainers/index/query.js
@@ -38,7 +38,8 @@ var querySelect = newSelect([
         "ADDRESS.ZIP",
         "ADDRESS.CITY",
         "COMMUNICATION.ADDR",
-        "PHONE.ADDR" 
+        "PHONE.ADDR",
+        "PERSON.PICTURE"
     ])
     .from("PERSON")
     .join("CONTACT", "CONTACT.PERSON_ID = PERSON.PERSONID")
diff --git a/entity/QuickEntry_entity/recordcontainers/jdito/onInsert.js b/entity/QuickEntry_entity/recordcontainers/jdito/onInsert.js
index aa0f51c76fd12f0f2b68af5357d04ea7f1303952..d356c25a42ac666f57272596da429d9afa741fd1 100644
--- a/entity/QuickEntry_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/QuickEntry_entity/recordcontainers/jdito/onInsert.js
@@ -25,7 +25,7 @@ if (rowdata["ORGANISATION_NAME.value"])
         "USER_NEW_CONTACT": userNew,
         "DATE_NEW_CONTACT" : dateNew,
         "STATUS" : $KeywordRegistry.contactStatus$active(),
-        "ISOLANGUAGE" : rowdata["ISOLANGUAGE.value"]
+        "LANGUAGE" : rowdata["ISOLANGUAGE.value"]
     });
     
     entities.createRow(configOrg);
@@ -55,7 +55,7 @@ if (rowdata["LASTNAME.value"])
         "CONTACTID": rowdata["PERSON_CONTACT_ID.value"],
         "ORGANISATION_ID": organisationId,
         "STATUS" : $KeywordRegistry.contactStatus$active(),
-        "ISOLANGUAGE": rowdata["ISOLANGUAGE.value"]
+        "LANGUAGE": rowdata["ISOLANGUAGE.value"]
     });
     
     entities.createRow(configPer);
diff --git a/entity/Role_entity/Role_entity.aod b/entity/Role_entity/Role_entity.aod
index 82bc56f08e993e369d264cac45d9c6bad35e0a7b..b2d23b5d87cd6cc41b29d3cbee11c913218217c3 100644
--- a/entity/Role_entity/Role_entity.aod
+++ b/entity/Role_entity/Role_entity.aod
@@ -41,6 +41,18 @@
     </entityField>
     <entityConsumer>
       <name>TheirPermissions</name>
+      <children>
+        <entityParameter>
+          <name>RoleName_param</name>
+          <valueProcess>%aditoprj%/entity/Role_entity/entityfields/theirpermissions/children/roletitle_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+      <children>
+        <entityParameter>
+          <name>RoleTitle_param</name>
+          <valueProcess>%aditoprj%/entity/Role_entity/entityfields/theirpermissions/children/roletitle_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
       <dependency>
         <name>dependency</name>
         <entityName>PermissionDetail_entity</entityName>
@@ -51,7 +63,7 @@
       <name>PermissionOverviews</name>
       <children>
         <entityParameter>
-          <name>RoleTitle_param</name>
+          <name>RoleName_param</name>
           <valueProcess>%aditoprj%/entity/Role_entity/entityfields/permissionoverviews/children/roletitle_param/valueProcess.js</valueProcess>
         </entityParameter>
       </children>
diff --git a/entity/Task_entity/entityfields/newoffer/onActionProcess.js b/entity/Task_entity/entityfields/newoffer/onActionProcess.js
index 7d951f8def4f9946c424f94ef6d137410da2c862..f80e61d2535e668b8afa4ad5ff2767e3ee068aaf 100644
--- a/entity/Task_entity/entityfields/newoffer/onActionProcess.js
+++ b/entity/Task_entity/entityfields/newoffer/onActionProcess.js
@@ -1,4 +1,20 @@
+import("Sql_lib");
 import("system.vars");
 import("Offer_lib");
 
-OfferUtils.createNewOffer();
+var links = newSelect("TASKLINK.OBJECT_TYPE, TASKLINK.OBJECT_ROWID")
+                                .from("TASKLINK")
+                                .where("TASKLINK.TASK_ID", vars.get("$field.TASKID"))
+                                .and("TASKLINK.OBJECT_TYPE", ["Person", "Organisation", "Salesproject"], SqlBuilder.IN())
+                                .table();
+
+//make a map from the 2d-array to easily access the ids by objectType
+var linkMap = new Map(links);
+
+//if we only have one Person: that person is the contact.
+//otherwise: we check for organisations: if we only have one then we use that one.
+//same logic for salesprojects: if we have only one: use that one
+var contactId = linkMap.get("Person") || linkMap.get("Organisation");
+var salesprojectId = linkMap.get("Salesproject");
+
+OfferUtils.createNewOffer("Salesproject", salesprojectId, contactId);
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 375e6f269678c8240a93bfc520ffd0c42045ac97..c8f697eb37c54696ad3a806fb357c661cf301fff 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -7587,6 +7587,9 @@
     <entry>
       <key>The team must have at least one owner</key>
     </entry>
+    <entry>
+      <key>Delete this Function</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 7a6508eb395f84848470e010a4e910443466b513..a00f483ea2e2c8fd456a3bfcd959c49e4eb506ea 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -10,6 +10,10 @@
       <key>The max participants count can not be equal or less then 0</key>
       <value>Die maximale Teilnehmerzahl muss größer 0 sein!</value>
     </entry>
+    <entry>
+      <key>discounted Vat</key>
+      <value>Rbt. Mehrwertssteuer</value>
+    </entry>
     <entry>
       <key>Illegal Parent Operator in buildFilterObj-Function:</key>
       <value>Übergebener Operator ungültig in Funktion "buildFilterObj"</value>
@@ -46,6 +50,10 @@
       <key>Private</key>
       <value>Privat</value>
     </entry>
+    <entry>
+      <key>discounted Price</key>
+      <value>Rbt. Betrag netto</value>
+    </entry>
     <entry>
       <key>Add app</key>
       <value>App hinzufügen</value>
@@ -210,6 +218,10 @@
       <key>Sender address</key>
       <value>Senderadresse</value>
     </entry>
+    <entry>
+      <key>The selected Contact doesn't have an address set.</key>
+      <value>Der ausgewählte Kontakt hat keine Adresse festgelegt.</value>
+    </entry>
     <entry>
       <key>Complete tasks</key>
       <value>Aufgaben abschließen</value>
@@ -2855,6 +2867,10 @@
       <key>Guam</key>
       <value>Guam</value>
     </entry>
+    <entry>
+      <key>Subtotal</key>
+      <value>Zwischensumme</value>
+    </entry>
     <entry>
       <key>Lesotho</key>
       <value>Lesotho</value>
@@ -4467,6 +4483,10 @@
       <key>Salesproject milestone Id</key>
       <value>VertriebsprojektsmeilensteinId</value>
     </entry>
+    <entry>
+      <key>without Vat</key>
+      <value>ohne UmSt.</value>
+    </entry>
     <entry>
       <key>Appointment Id</key>
       <value>Termin Id</value>
@@ -8389,7 +8409,6 @@ Bitte Datumseingabe prüfen</value>
     </entry>
     <entry>
       <key>Subcategory</key>
-      <value>Unterkategorie</value>
     </entry>
     <entry>
       <key>The radius has to be at least %0.</key>
@@ -8663,6 +8682,10 @@ Bitte Datumseingabe prüfen</value>
       <key>My Calendar</key>
       <value>Mein Kalender</value>
     </entry>
+    <entry>
+      <key>Invoice Discount</key>
+      <value>Rechnungsrabatt</value>
+    </entry>
     <entry>
       <key>Variable</key>
       <value>Variable</value>
@@ -9550,6 +9573,10 @@ Bitte Datumseingabe prüfen</value>
       <key>Date (Month)</key>
       <value>Datum (Monat)</value>
     </entry>
+    <entry>
+      <key>Delete this Function</key>
+      <value>Diese Funktion löschen</value>
+    </entry>
     <entry>
       <key>Date (Year)</key>
       <value>Datum (Jahr)</value>
@@ -9872,6 +9899,10 @@ Bitte Datumseingabe prüfen</value>
     <entry>
       <key>Messages</key>
     </entry>
+    <entry>
+      <key>incl. Vat</key>
+      <value>inkl. UmSt.</value>
+    </entry>
     <entry>
       <key>Channel Name</key>
     </entry>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index e27607261acb9a472b6febcf29b79d1b6aebb970..56cb1721db20330175fd6f807047dfd6f89657fd 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -7668,6 +7668,9 @@
     <entry>
       <key>The team must have at least one owner</key>
     </entry>
+    <entry>
+      <key>Delete this Function</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/MSTeamsMessage/MSTeamsMessage.aod b/neonContext/MSTeamsMessage/MSTeamsMessage.aod
index ecf21a7e76897a9415073d8108020d36522d2d4d..3e2fdddb1fd203df7b6ab0bc1243e94fd3ab92d2 100644
--- a/neonContext/MSTeamsMessage/MSTeamsMessage.aod
+++ b/neonContext/MSTeamsMessage/MSTeamsMessage.aod
@@ -3,6 +3,7 @@
   <name>MSTeamsMessage</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <filterView>MSTeamsMessageFilter_view</filterView>
+  <lookupView>MSTeamsMessageFilter_view</lookupView>
   <entity>MSTeamsMessage_entity</entity>
   <references>
     <neonViewReference>
diff --git a/neonView/MSTeamsActivityImportEdit_view/MSTeamsActivityImportEdit_view.aod b/neonView/MSTeamsActivityImportEdit_view/MSTeamsActivityImportEdit_view.aod
index a2f7266662173bd55c3192dda407a0c50e6555db..cd543c363d5dc8785a8aeaf4285a3103f87b3a2d 100644
--- a/neonView/MSTeamsActivityImportEdit_view/MSTeamsActivityImportEdit_view.aod
+++ b/neonView/MSTeamsActivityImportEdit_view/MSTeamsActivityImportEdit_view.aod
@@ -22,16 +22,9 @@
       </fields>
     </genericViewTemplate>
     <neonViewReference>
-      <name>e486a1bb-5deb-432a-aa28-c3872f0f88fc</name>
+      <name>59b3d882-d067-43eb-b19b-f52758c9d10b</name>
       <entityField>Messages</entityField>
       <view>MSTeamsMessageFilter_view</view>
     </neonViewReference>
-    <actionsViewTemplate>
-      <name>Actions</name>
-      <actions>
-        <element>loadNextMessages</element>
-      </actions>
-      <entityField>#ENTITY</entityField>
-    </actionsViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/MSTeamsDocumentEdit_view/MSTeamsDocumentEdit_view.aod b/neonView/MSTeamsDocumentEdit_view/MSTeamsDocumentEdit_view.aod
index c13a80654c3c766b980b8ebe87ac4a1aa97b2879..bc7e317b3b8e1b0445d4fc5c057b5c1687a72ba1 100644
--- a/neonView/MSTeamsDocumentEdit_view/MSTeamsDocumentEdit_view.aod
+++ b/neonView/MSTeamsDocumentEdit_view/MSTeamsDocumentEdit_view.aod
@@ -26,5 +26,11 @@
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
+    <actionsViewTemplate>
+      <name>Actions</name>
+      <actions>
+        <element>importDocuments</element>
+      </actions>
+    </actionsViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/MSTeamsMessageFilter_view/MSTeamsMessageFilter_view.aod b/neonView/MSTeamsMessageFilter_view/MSTeamsMessageFilter_view.aod
index c9cae5e66e22ac705d668d977fdd66a478d86d1a..14b4fcec5a5044d3572264103fc4888e28f3dbb7 100644
--- a/neonView/MSTeamsMessageFilter_view/MSTeamsMessageFilter_view.aod
+++ b/neonView/MSTeamsMessageFilter_view/MSTeamsMessageFilter_view.aod
@@ -27,5 +27,11 @@
         </neonTableColumn>
       </columns>
     </tableViewTemplate>
+    <actionsViewTemplate>
+      <name>ImportAction</name>
+      <actions>
+        <element>importMessages</element>
+      </actions>
+    </actionsViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/OfferEdit_view/OfferEdit_view.aod b/neonView/OfferEdit_view/OfferEdit_view.aod
index 5bacbaaaf3210c985a93785da25639a707bac134..7d489489df27db7e454a213ef456d153010f108b 100644
--- a/neonView/OfferEdit_view/OfferEdit_view.aod
+++ b/neonView/OfferEdit_view/OfferEdit_view.aod
@@ -48,13 +48,17 @@
           <name>7ab3eb65-b713-4251-9eb1-3119432565f5</name>
           <entityField>ISOLANGUAGE</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>1e98fe37-8d52-4eef-8825-8ea14e7e20b5</name>
+          <entityField>PAYMENTTERMS</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>7a9b0943-eb06-4b44-a111-ed4e2749da6a</name>
           <entityField>DELIVERYTERMS</entityField>
         </entityFieldLink>
         <entityFieldLink>
-          <name>1e98fe37-8d52-4eef-8825-8ea14e7e20b5</name>
-          <entityField>PAYMENTTERMS</entityField>
+          <name>35804879-e866-477a-a0e6-9fea1506fc1d</name>
+          <entityField>DISCOUNT</entityField>
         </entityFieldLink>
         <entityFieldLink>
           <name>45ddf7c2-531b-4e18-826d-9c652ecc4d01</name>
diff --git a/neonView/OfferPreview_view/OfferPreview_view.aod b/neonView/OfferPreview_view/OfferPreview_view.aod
index 7b78909905af090ebc923109ba2ed9bdcb0492dd..d0e3891b5166dada85ca47fd9c06daa9df7b06ec 100644
--- a/neonView/OfferPreview_view/OfferPreview_view.aod
+++ b/neonView/OfferPreview_view/OfferPreview_view.aod
@@ -67,10 +67,18 @@
           <name>d7ca2b66-5e7a-4951-a89b-fbeab0f4f798</name>
           <entityField>NET</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>3e9e37e2-6756-41c2-ace7-6ff094dc78c1</name>
+          <entityField>DISCOUNTED_NET</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>c50dec3f-5468-4196-be88-a413ae3947de</name>
           <entityField>VAT</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>5cc461e4-fd0f-47e6-ab06-886a18621c31</name>
+          <entityField>DISCOUNTED_VAT</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>43972a26-67f7-4fb5-9107-111731d326af</name>
           <entityField>TotalGross</entityField>
@@ -99,6 +107,10 @@
           <name>a3a9ee30-bdd2-4907-b215-d4b4adcc0f1d</name>
           <entityField>DELIVERYTERMS</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>b67494ee-f7c1-4002-a550-50ce1eac5020</name>
+          <entityField>DISCOUNT</entityField>
+        </entityFieldLink>
       </fields>
     </genericViewTemplate>
     <neonViewReference>
diff --git a/neonView/RoleChildrenList_view/RoleChildrenList_view.aod b/neonView/RoleChildrenList_view/RoleChildrenList_view.aod
index ada141eeefbfbf0e0e287e56ad32182a097eabaa..8876a89c73b21bdb8c993bcca9dcdaee38c45f97 100644
--- a/neonView/RoleChildrenList_view/RoleChildrenList_view.aod
+++ b/neonView/RoleChildrenList_view/RoleChildrenList_view.aod
@@ -10,16 +10,12 @@
   <children>
     <titledListViewTemplate>
       <name>TitledList</name>
+      <titleField>CHILD_ROLE</titleField>
+      <titleFieldFullWidth v="true" />
       <entityField>#ENTITY</entityField>
       <isDeletable v="false" />
       <isEditable v="false" />
       <isCreatable v="false" />
-      <columns>
-        <neonTitledListTableColumn>
-          <name>0451e2ec-e216-4d4f-8080-e6b9aaf56613</name>
-          <entityField>CHILD_ROLE</entityField>
-        </neonTitledListTableColumn>
-      </columns>
     </titledListViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/RoleParentList_view/RoleParentList_view.aod b/neonView/RoleParentList_view/RoleParentList_view.aod
index 2a2073e31961aeda39ace51d84243065d475c40b..d4901c30aff838b71555a44577dbcb1649bf757d 100644
--- a/neonView/RoleParentList_view/RoleParentList_view.aod
+++ b/neonView/RoleParentList_view/RoleParentList_view.aod
@@ -10,16 +10,12 @@
   <children>
     <titledListViewTemplate>
       <name>TitledList</name>
+      <titleField>PARENT_ROLE</titleField>
+      <titleFieldFullWidth v="true" />
       <entityField>#ENTITY</entityField>
       <isDeletable v="false" />
       <isEditable v="false" />
       <isCreatable v="false" />
-      <columns>
-        <neonTitledListTableColumn>
-          <name>cdc83256-2ea4-4a97-a323-b400a4037915</name>
-          <entityField>PARENT_ROLE</entityField>
-        </neonTitledListTableColumn>
-      </columns>
     </titledListViewTemplate>
   </children>
 </neonView>
diff --git a/process/Campaign_lib/process.js b/process/Campaign_lib/process.js
index f3934b933660f8cb2ba2fe7b756d1b0094b87e7f..2d0507917a2047a0e9a8028ceb221045a9db3326 100644
--- a/process/Campaign_lib/process.js
+++ b/process/Campaign_lib/process.js
@@ -283,17 +283,17 @@ CampaignUtils.getDefaultCampaignStep = function(pCampaignId)
 /**
  * Returns the start date to the corresponding campaign id.<br>
  * 
- * @param {String} pCapmaignId                  <p>
+ * @param {String} pCampaignId                  <p>
  *                                              The corresponding campaign id.<br>
  * @return {String}                             <p>
  *                                              The end date in this format:<br>
  *                                              <b>yyyy-mm-dd</b>                                             
  */
-CampaignUtils.getCampaignStartDate = function(pCapmaignId)
+CampaignUtils.getCampaignStartDate = function(pCampaignId)
 {
     return newSelect("DATE_START")
         .from("CAMPAIGNSTEP")
-        .whereIfSet("CAMPAIGNSTEP.CAMPAIGN_ID", pCapmaignId)
+        .whereIfSet("CAMPAIGNSTEP.CAMPAIGN_ID", pCampaignId)
         .orderBy("SORTING ASC")
         .cell(true);
 }
@@ -301,17 +301,17 @@ CampaignUtils.getCampaignStartDate = function(pCapmaignId)
 /**
  * Returns the end date to the corresponding campaign id.<br>
  * 
- * @param {String} pCapmaignId                          <p>
+ * @param {String} pCampaignId                          <p>
  *                                                      The corresponding campaign id.<br>
  * @return {String}                                     <p>
  *                                                      The end date in this format:<br>
  *                                                      <b>yyyy-mm-dd</b>                                                     
  */
-CampaignUtils.getCampaignEndDate = function(pCapmaignId)
+CampaignUtils.getCampaignEndDate = function(pCampaignId)
 {
     return newSelect("DATE_END")
         .from("CAMPAIGNSTEP")
-        .whereIfSet("CAMPAIGNSTEP.CAMPAIGN_ID", pCapmaignId)
+        .whereIfSet("CAMPAIGNSTEP.CAMPAIGN_ID", pCampaignId)
         .orderBy("SORTING DESC")
         .cell(true);
 }
diff --git a/process/Contact_lib/process.js b/process/Contact_lib/process.js
index 7bbafdc693adac2eb70bf75da3d35f24790c6560..4a59839543915bbe0c16edfb2c56985efe935f15 100644
--- a/process/Contact_lib/process.js
+++ b/process/Contact_lib/process.js
@@ -528,10 +528,8 @@ ContactUtils.hasCommRestriction = function(pContactId, pMedium, pStartDate)
  */
 ContactUtils.getActiveCommRestrictionsSubselect = function()
 {
-    var mediumList = KeywordUtils.getEntryNamesAndIdsByContainer($KeywordRegistry.communicationMediumCampaign());
-    var sqlMasking = new SqlMaskingUtils();
-
-    var parts = [];
+    var mediumList = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.communicationMediumCampaign(), "COMMRESTRICTION.MEDIUM");
+    var mask = new SqlMaskingUtils()
 
     var orgContactSubselect = newSelect("orgContact.CONTACTID")
                                     .from("CONTACT anyContact")
@@ -539,20 +537,19 @@ ContactUtils.getActiveCommRestrictionsSubselect = function()
                                                                     .and("orgContact.PERSON_ID IS NULL"))
                                     .where("anyContact.CONTACTID = CONTACT.CONTACTID")
 
-    mediumList.forEach(function(pMedium) 
+    var group = mask.getGroupConcat("DISTINCT "+mediumList, "', '");
+    var subselect = "''";
+    if(group)
     {
-        var subquery = newSelect("COMMRESTRICTION.MEDIUM, COMMRESTRICTIONID")
-                            .from("COMMRESTRICTION")
-                            .where("COMMRESTRICTION.MEDIUM", pMedium[0])
-                            .and("COMMRESTRICTION.STARTDATE", vars.get("$sys.date"), SqlBuilder.LESS_OR_EQUAL())
-                            .and(newWhere()
-                                    .or("COMMRESTRICTION.CONTACT_ID = CONTACT.CONTACTID")
-                                    .or("COMMRESTRICTION.CONTACT_ID", orgContactSubselect));
-        //!SqlBuilder
-        parts.push("case when exists(" + subquery.toString() + ") then '" + pMedium[1] + "' else '' end");
-    })
-
-    return sqlMasking.concatWithSeparator(parts, " ", false);
+        var res = newSelect(group).from("COMMRESTRICTION")
+                    .where("COMMRESTRICTION.CONTACT_ID = CONTACT.CONTACTID")
+
+        var subres = newSelect(group).from("COMMRESTRICTION")
+                    .where("COMMRESTRICTION.CONTACT_ID in ( "+orgContactSubselect.toString()+")")
+                    
+        subselect = mask.concatWithSeparator(["("+res.toString()+")", "("+subres.toString()+")"], ", ", false);
+    }
+    return subselect;
 }
 
 /**
diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js
index 40e6e00d4c2d686986fa22bb843da5b35d29c01f..5d0a3a81c1d8a05ae2b32234b3c290994ec76584 100644
--- a/process/Context_lib/process.js
+++ b/process/Context_lib/process.js
@@ -269,28 +269,36 @@ ContextUtils.loadContent = function(pEntity, pUid, pFields, pExcludeIDs, pProvid
  */
 ContextUtils.getContexts = function(pBlacklist, pInvertBlacklist)
 {
-    if (pInvertBlacklist == undefined)
-        pInvertBlacklist = false;
-
-
-    var contexts = project.getDataModels(project.DATAMODEL_KIND_CONTEXT);
-    var contextsStandardList = ["Organisation", "Person", "PrivatePerson", "Activity", "Salesproject", "Contract", "Offer", "Order", "Product", "Task",
-    "Campaign", "CampaignStep", "SupportTicket", "Leadimport"];
-
-    contexts = contexts.filter(function(pContext) {
-        if (contextsStandardList.indexOf(pContext[0]) > -1)
-            return true;
-        return false;
-    });
-
-    if (pBlacklist)
+    var whitelist;
+    if (pInvertBlacklist && pBlacklist)
+        whitelist = new Set(pBlacklist);
+    else
     {
-        contexts = contexts.filter(function(pContext) {
-            if (pBlacklist && pBlacklist.indexOf(pContext[0]) > -1 != pInvertBlacklist)
-                return false;
-            return true;
-        });
+        whitelist = new Set()
+            .add("Organisation")
+            .add("Person")
+            .add("PrivatePerson")
+            .add("Activity")
+            .add("Salesproject")
+            .add("Contract")
+            .add("Offer")
+            .add("Order")
+            .add("Product")
+            .add("Task")
+            .add("Campaign")
+            .add("CampaignStep")
+            .add("SupportTicket")
+            .add("Leadimport");
+            
+        if (pBlacklist)
+            pBlacklist.forEach(whitelist["delete"], whitelist);
     }
+    
+    var contexts = project.getDataModels(project.DATAMODEL_KIND_CONTEXT);
+    contexts = contexts.filter(function(context) 
+    {
+        return whitelist.has(context[0]);
+    });
 
     return contexts.map(ContextUtils._contextDataMapping).sort(function(pContext1, pContext2)
     {
diff --git a/process/DocumentTemplate_lib/process.js b/process/DocumentTemplate_lib/process.js
index 2f1507904e3a4016dab89bd39b365c77ef59b0b7..3579096b94ccbc30fc17b3c2f1c748d8a1a1d5fd 100644
--- a/process/DocumentTemplate_lib/process.js
+++ b/process/DocumentTemplate_lib/process.js
@@ -316,8 +316,15 @@ DocumentTemplate.loadTemplate = function (pAssignmentRowId, pAssignmentTable, pR
             return null;
         }
     }
-    
-    var templateDocument = db.getBinaryMetadata(pAssignmentTable, "DOCUMENT", pAssignmentRowId, false, alias, null);
+    var templateDocument;
+    if(pAssignmentTable == "SERIALLETTER")
+    {
+        templateDocument = db.getBinaryMetadata(pAssignmentTable, "SERIALLETTERFILE", pAssignmentRowId, false, alias, null);
+    }
+    else
+    {
+        templateDocument = db.getBinaryMetadata(pAssignmentTable, "DOCUMENT", pAssignmentRowId, false, alias, null);
+    }
     if (!templateDocument[0])
         return new DocumentTemplate(undefined, undefined, undefined, undefined, templateId);
     var binaryId = templateDocument[0][db.BINARY_ID];
diff --git a/process/Email_lib/process.js b/process/Email_lib/process.js
index bffbe633e28bdc6119fdea0898094c96809e493e..8f560c533ad7994e8b1896715b41ee6aabb311b6 100644
--- a/process/Email_lib/process.js
+++ b/process/Email_lib/process.js
@@ -13,6 +13,7 @@ import("system.neon");
 import("system.mail");
 import("Bulkmail_lib");
 import("system.tools");
+import("EmailUtil_lib");
 
 function EmailWritingUtils () {}
 
diff --git a/process/Keyword_lib/process.js b/process/Keyword_lib/process.js
index 994fd55c07d07fda603f24db728838663dd844f2..dd8986377eaaff95d792cc821b8be28b39634724 100644
--- a/process/Keyword_lib/process.js
+++ b/process/Keyword_lib/process.js
@@ -26,7 +26,7 @@ function KeywordUtils(){}
 KeywordUtils.getResolvedTitleSqlPart = function(pContainerName, pDbFieldName, pLocale)
 {
     var keywordData = KeywordData.getSimpleData(pContainerName, pLocale);
-    var resSql = SqlUtils.getResolvingCaseWhen(keywordData, pDbFieldName, pLocale);
+    var resSql = SqlUtils.getResolvingCaseWhen(keywordData, pDbFieldName, false);
     return SqlUtils.translateStatementWithQuotes(resSql);
 };
 
diff --git a/process/OfferOrder_lib/process.js b/process/OfferOrder_lib/process.js
index f33eba68fa16f14af4e88b25b3102a64e3da4d04..49477739fd0a0b2931359ff565701150edf9108a 100644
--- a/process/OfferOrder_lib/process.js
+++ b/process/OfferOrder_lib/process.js
@@ -390,7 +390,7 @@ ItemUtils.prototype.getNextItemPosition = function(assignedTo, tree, ids) {
         }
     } else {
         if (ids.length > 0) {
-            maxPos[0] = this.ItemTree[ids[ids.length-1]].pos.split(".")[0];
+            maxPos[0] = tree[ids[ids.length-1]].pos.split(".")[0];
         }    
     }
     maxPos[maxPos.length-1] = (Number(maxPos[maxPos.length-1]) + 1).toString();
diff --git a/process/Offer_lib/process.js b/process/Offer_lib/process.js
index 78ea329bfc0de71f18965d80cc03b82397687b0e..687423b989882845fbcb5062c4ee38a9e03ad478 100644
--- a/process/Offer_lib/process.js
+++ b/process/Offer_lib/process.js
@@ -18,6 +18,7 @@ import("Neon_lib");
 import("KeywordRegistry_basic");
 import("Address_lib");
 import("DocumentTemplate_lib");
+import("system.eMath");
 
 /**
  * Methods used by Offer.
@@ -99,37 +100,42 @@ OfferUtils.createNewOffer = function(pContextId, pRowId, pRelationId, pActivityI
  * Builds the Offer report.
  * 
  * @param {String} pOfferID
+ * @param {String} pExclDiscountGroupcodes
  * @return {Array} [filename, data_bytes]
  */
-OfferUtils.buildOfferReport = function (pOfferID)
+OfferUtils.buildOfferReport = function (pOfferID, pExclDiscountGroupcodes)
 {
     var offerReport = new Report("Offer_report");  
 
     var sqlUtil = new SqlMaskingUtils();
     
     var offerFields = [
-        "ADDRESS", 
-        "CONTACT_ID", 
-        "ISOLANGUAGE", 
-        "PAYMENTTERMS", 
-        "DELIVERYTERMS", //4
-        "OFFERCODE", 
-        "CURRENCY", 
-        "OFFERDATE", 
-        "HEADER", //8
-        "VAT", 
-        sqlUtil.isNull("VERSNR", "0"),
-        sqlUtil.isNull("OFFERCODE", "0"), 
-        "OBJECT_TYPE", //12
-        "OBJECT_ROWID", //13
-        "FOOTER", //14
-        "LETTERSALUTATION" // 15
+    "ADDRESS", 
+    "CONTACT_ID", 
+    "ISOLANGUAGE", 
+    "PAYMENTTERMS", 
+    "DELIVERYTERMS", //4
+    "OFFERCODE", 
+    "CURRENCY", 
+    "OFFERDATE", 
+    "HEADER", //8
+    "VAT", 
+    sqlUtil.isNull("VERSNR", "0"),
+    sqlUtil.isNull("OFFERCODE", "0"), 
+    "OBJECT_TYPE", //12
+    "OBJECT_ROWID", //13
+    "FOOTER", //14
+    "LETTERSALUTATION", // 15
+    "DISCOUNT",
+    "NET",
+    "DISCOUNTED_NET", 
+    "DISCOUNTED_VAT"
     ];
    
     var offerData = newSelect(offerFields)
-                        .from("OFFER")
-                        .where("OFFER.OFFERID", pOfferID)
-                        .arrayRow();
+    .from("OFFER")
+    .where("OFFER.OFFERID", pOfferID)
+    .arrayRow();
   
     if (offerData.length === 0)
         return null;
@@ -137,36 +143,37 @@ OfferUtils.buildOfferReport = function (pOfferID)
     var letterSalutation = offerData[15];
     
     var language = newSelect("ISO2")
-                        .from("AB_LANGUAGE")
-                        .where("AB_LANGUAGE.ISO3", offerData[2])
-                        .cell();
+    .from("AB_LANGUAGE")
+    .where("AB_LANGUAGE.ISO3", offerData[2])
+    .cell();
                         
     offerData[7] = datetime.toDate(offerData[7], translate.text("dd.MM.yyyy", language));                    
         
     var offerItemFields = [
-        "OFFERITEM.INFO", 
-        "OFFERITEM.ASSIGNEDTO",
-        "OFFERITEM.PRODUCT_ID", 
-        "OFFERITEM.ITEMNAME" , 
-        "OFFERITEM.OPTIONAL",  //4
-        "OFFERITEM.ITEMPOSITION", 
-        "PRODUCT.PRODUCTCODE", 
-        "PRODUCT.PRODUCTID", 
-        "OFFERITEM.UNIT", //8
-        sqlUtil.isNull("OFFERITEM.QUANTITY", "0"), 
-        sqlUtil.isNull("OFFERITEM.PRICE", "0"),
-        sqlUtil.isNull("OFFERITEM.DISCOUNT", "0"), 
-        sqlUtil.isNull("OFFERITEM.VAT", "0"), //12
-        "0", 
-        "''"
+    "OFFERITEM.INFO", 
+    "OFFERITEM.ASSIGNEDTO",
+    "OFFERITEM.PRODUCT_ID", 
+    "OFFERITEM.ITEMNAME" , 
+    "OFFERITEM.OPTIONAL",  //4
+    "OFFERITEM.ITEMPOSITION", 
+    "PRODUCT.PRODUCTCODE", 
+    "PRODUCT.PRODUCTID", 
+    "OFFERITEM.UNIT", //8
+    sqlUtil.isNull("OFFERITEM.QUANTITY", "0"), 
+    sqlUtil.isNull("OFFERITEM.PRICE", "0"),
+    sqlUtil.isNull("OFFERITEM.DISCOUNT", "0"), 
+    sqlUtil.isNull("OFFERITEM.VAT", "0"), //12
+    "0", 
+    "''",
+    "OFFERITEM.GROUPCODEID"
     ]; 
 
     var itemData = newSelect(offerItemFields)
-                            .from("OFFERITEM")
-                            .leftJoin("PRODUCT", "PRODUCT.PRODUCTID = OFFERITEM.PRODUCT_ID")
-                            .where("OFFERITEM.OFFER_ID", pOfferID)
-                            .orderBy("OFFERITEM.ITEMSORT asc")
-                            .table();
+    .from("OFFERITEM")
+    .leftJoin("PRODUCT", "PRODUCT.PRODUCTID = OFFERITEM.PRODUCT_ID")
+    .where("OFFERITEM.OFFER_ID", pOfferID)
+    .orderBy("OFFERITEM.ITEMSORT asc")
+    .table();
             
     if (itemData.length == 0)
         return null;
@@ -178,10 +185,29 @@ OfferUtils.buildOfferReport = function (pOfferID)
     var sums = [];
     var vatsum = 0;
     var printDiscount = false;
+    var printHeadDiscount = false; 
+    var discValue = 0;
     
     var header = new DocumentTemplate(offerData[8], DocumentTemplate.types.PLAIN).getReplacedContentByContactId(offerData[1]);
     var footer = new DocumentTemplate(offerData[14], DocumentTemplate.types.PLAIN).getReplacedContentByContactId(offerData[1]);
     
+    var discount;
+    if(offerData[17] && offerData[18]){
+        discount = eMath.subDec(offerData[17].toString(), offerData[18].toString());
+        discount = text.formatDouble(discount.toString(), "#,##0.00", true);     
+    }
+    if (!printHeadDiscount && discount && parseFloat(discount) != parseFloat("0"))
+        printHeadDiscount = true;
+    if(printHeadDiscount){
+        total = eMath.addDec(offerData[18], offerData[19])
+    }
+    if(offerData[16]){
+        discValue = text.formatDouble(offerData[16], "#,##0.00", true);
+    }
+    if(offerData[18]){
+        offerData[18] = text.formatDouble(offerData[18], "#,##0.00", true);
+    }
+    
     itemData = itemData.map(function (item)
     {
         //quantity * price
@@ -192,45 +218,62 @@ OfferUtils.buildOfferReport = function (pOfferID)
             //itemSum = (fullPrice * (100 - discount)) / 100
             itemSum = eMath.roundDec(eMath.divDec(eMath.mulDec(fullPrice, eMath.subDec(100, item[11])), 100), 2, eMath.ROUND_HALF_EVEN); //sum of the item (with discount)
             sumItemSum += itemSum; //total sum (without vat) 
+
+            let excluded = -1
+            if(pExclDiscountGroupcodes){
+                excluded = pExclDiscountGroupcodes.indexOf(item[15])
+            }
+            //vatsum = itemSum * vat / 100
+
+            if(printHeadDiscount && offerData[16] && excluded == -1){
+                vatsum = ItemUtils.prototype.getItemVAT(item[9], item[10], item[11], item[12], item[4]);
+                vatsum = eMath.subDec(vatsum, eMath.divDec(eMath.mulDec(vatsum, offerData[16]), "100"));
+            }
+            else
+                vatsum = ItemUtils.prototype.getItemVAT(item[9], item[10], item[11], item[12], item[4])
+
+            if (item[12] > 0) 
+                sums.push([item[12], vatsum]); //MWSteuerwerte für Map vorbereiten
         }
-        //vatsum = itemSum * vat / 100
-        vatsum = eMath.divDec(eMath.mulDec(itemSum, item[12]), 100); //vat per product
-        if (item[12] > 0) 
-            sums.push([item[12], vatsum]); //MWSteuerwerte für Map vorbereiten
+        
         
         // sumItemSum + vat
-        total = eMath.addDec(sumItemSum, offerData[9]); //total sum with vat
+        if(!printHeadDiscount)
+            total = eMath.addDec(sumItemSum, offerData[9]); //total sum with vat
         
         if (!printDiscount && item[11] > 0)
             printDiscount = true;
         
         return [
-            offerData[6],   //currency
-            offerData[7],   //offerdate
-            pOfferID,       //offerId
-            item[0],        //info
-            item[1],        //assignedTo
-            item[3],        //itemname
-            item[4],        //optional
-            item[5],        //itemposition
-            item[6],        //productcode
-            header,         //header 
-            footer,         //footer 
-            text.formatDouble(item[9], "#,##0", true),          //quantity
-            text.formatDouble(item[10], "#,##0.00", true),      //price
-            text.formatDouble(item[11], "0.00", true),          //discount
-            offerData[10],  //versnr
-            offerData[5],   //offercode
-            text.formatDouble(item[12], "#,##0.00", true),      //vat
-            text.formatDouble(itemSum, "#,##0.00", true),       //itemsum
-            KeywordUtils.getViewValue($KeywordRegistry.quantityUnit(), item[8]) //unittext
+        offerData[6],   //currency
+        offerData[7],   //offerdate
+        pOfferID,       //offerId
+        item[0],        //info
+        item[1],        //assignedTo
+        item[3],        //itemname
+        item[4],        //optional
+        item[5],        //itemposition
+        item[6],        //productcode
+        header,         //header 
+        footer,         //footer 
+        text.formatDouble(item[9], "#,##0", true),          //quantity
+        text.formatDouble(item[10], "#,##0.00", true),      //price
+        text.formatDouble(item[11], "0.00", true),          //discount
+        offerData[10],  //versnr
+        offerData[5],   //offercode
+        text.formatDouble(item[12], "#,##0.00", true),      //vat
+        text.formatDouble(itemSum, "#,##0.00", true),       //itemsum
+        KeywordUtils.getViewValue($KeywordRegistry.quantityUnit(), item[8]), //unittext
+        discValue,
+        offerData[18],
+        discount
         ];
     });
     
     // TODO: get Images implementieren
     var imgData = ["meineFirma | Wilhelm-Str. 2  |  DE 80807 München",
-                   "base64:iVBORw0KGgoAAAANSUhEUgAAAM4AAABRCAYAAACaL5lSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDA4QzAyM0IwREIwMTFFNEFGMDREM0VEMjExRjlBRTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDA4QzAyM0MwREIwMTFFNEFGMDREM0VEMjExRjlBRTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMDhDMDIzOTBEQjAxMUU0QUYwNEQzRUQyMTFGOUFFMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMDhDMDIzQTBEQjAxMUU0QUYwNEQzRUQyMTFGOUFFMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhF3nYoAAAlvSURBVHja7J1fjBXVHcfPJQJRoe1urQYJRBYlMUJisqwvGNjY3WgEUtN2CeWBIGb3Ju6LElsW+gA8AHe1UfuwTcBASB/Q7CZNG0tjw2pWU15kNzEBJFnLqmvQBNEbU0pbX+jve+9vlrOzM/fOnTtz78zs95P8cv/MOTPnzJzvnN/5zZ+Tu3XrliGE1MYC7gJCKBxCKBxCKBxCKBxCKBxCCIVDCIVDCIVDCIVDyDzmDq8/d+1/PY5trRB7VGyt2BqxVWLLxe4RW6JpbohdF7sq9qnYpNhFsY/Evoi6QKeOvMAWQKITToQ8LPaEWKfYBrFlVdL/SO1BsU3W/1+JnRMbE3tP7DIPHcmicLrFfia2VWxlBOuD4H6pNi32tthfxM7yEJIsCAc9yw6x7WJLYyozhNgvtlPsLbHT2hMRkjrhYPzynNhu/d4IIMxesafEToqdiGMcREhcwnlKe4AtTaoDhHpArF1sSOwdHlYSN/WGo/Niv2+iaGy2aFnyPKwkqT1OTmyf2pIE1Qdh7t+J/VjsqBgfbyWJEU5OXaMDCa0ThHxYbJHYIYqHJMVV25dg0dgc0LIS0nTh5FPWGPdxzEOaLRxEz/YkbEwTxG3bo2UnpOHCQci3XwffaWONln0FDzdptHBwcXNLiuu5RetASMOE02nKdwSknd1aF0IaIpwdGXFzVmhdCIldOLjLeXuG6rtd60RIrMLBowFLM1TfpVonQmITDh5C25rBOm/VuhESi3Dw5ObKDNZ5pdaNkFiE05nhenfy0JM4hIMI1IYM13uD4QVREoNw8DaaZRmu9zKtIyGh8HusYG3UG/pJ6w/NKy89O/P70j+nzSsn/zTz+5EHV5oHlt9rep58fFa+sQ8vmEtXps35C5/4+12PrTMP3H9v6dMGeZAX6/Cp49tsAiRK4TTsnrS771xsdj3TZTrWPeQrCtiljmnzhzfPmH//538zyyC0/l9tLonSC6wT1tmxzgxJ3q+//a4pdSTzx1Vb1SjR/Hr3L3xFY4MeCWnt3wf7d/iKxgYC+83un7vTruLhJ1H3OMsbsfHnpbdAo0Yv8rcPzpsz74/P6i3QU0AgtgA2b1pvPhQXDHltd+7MB+MzPQrSIa/tukE0mzeuN6f+/O6cOuZyubrr0tvb12bK73nDZ/cbbxwfzWKD2Tnw2l75KIiN/rHwYibvwggyobSfcO6Ju3COINDYX5axjsuNKo1PYLue+eksATy9scN0rF1T6q0AxkkYL9l8dvWaOXX1XfPZl9dK+W23zxJY1HXsUtEANK7RBDf+s1reakyJOFa7/utz6ivr6ZLlmTxBhHXVGvawmsfYYxYjf//HrHENBIMexVnmFs2cwIJr+WO33cKo64gGNKXfBzPcZo479Z2voqnU4zQENGz0DpWAaJAOLpoNxGa7dn6cv/jJbHfv/vtiqYu4ZhDN6pQd/5rdLUk/mPETQ109zo2GCOf8hUDpPr4yHTqvu8exAgQ3DCERC+d63BtGT1Ktt3G45uHK+VybmYPbDbSEc52Hn0QtnKtxb7jSuKZaWojOHvfUkt8JKjSijmT+jXEwqdOmeHuc/4bOe7OOvK46etLb24eoWI8pv4/aHhSP+IWZNRx9RX/mJd3xasvlP2wDUSo7wlUaQ8jyYrUKhClnvewceO2Yltkr4maHq0vLEXkz5SijU8duJ6jgXpf8btPfe937Q5YXNU+LpilYaSY0zUiVsrdrObD+FmsR8o1Uyx+kx5mcByeNSa/GLzauB6XdtRgH66w21rqR9aDRDJu5YWGsf1yF5pe3YeWsU2QoW6DQt6a94hLNzP6AYFRY4y7RGN0Hwypav/UXrLwtrsU91fIHFc7FeSCci67G2KIHGQehqL1CDmbK0TLnbFSQtH11brtPbdDaRqu5Hept82hAzShnveDEgN5ltZzNc2pePaFTJ5S9Fel89sewfs876zPlR+GdywAFFZcX7VYPtj5E/kCuGubcxPSBWb1D+iuto01BDwp2YreGl0vo923SEIf17LTXOqhhaHe7c+qa5VUYJRdOvg94uGxRlhMXMStdJu+u41oNyjgRMNzdoq7SNucPdc3y2pC7rBPJNtulQvkkTd7cnp2vx3iHyydUcFP2nzXkD9TjYIKmcxnubc4ZaxIqbazO2XnQbowunB0KV6m9ju2PusdALn/bfZZsVjnrZTCCtPZ+8hyHqLinLMEajzQDbtG48hcr5Q/a44AxU55zM4uMefi4Xg13FtJQJ6Qh2o16IqxwAi5ri7mcsd5vVsNguyhp/co44fPdzZTur7aQxZ0wwW5DqioczO6Mq4dZfO/Aex5uhcO3VqOr5l6EpVih0RcrbL/R5ayHqSj2RwURhdqeFZWzx5s1i62ScDAlOh706s+gcC4npHHVSoshoRDB9Fjjw7qpdq8apkTH7M5LM75fnTNeUc74rSxn5kTjXFtyGLDHUAhE1HDHeCDhYGWYEr13nginBQPwIBcfWc5UsdcKLmyLYoVB3h192mR/GvRRnwE4y5n+3qbdcnErBSvaoxbOmNjJLO9cRKGsgWehylX7rmZdlU9LOdM2RtS7ClqiFg44IfbXtO6thQvvuBkgWd7auePuRqcN8Zi5faGsWaSlnIlAw9yOS1vQIIEjmDb7frkogwMOcNWGTPnNMGl7O8zknYsX/UA+76p2NpcGB/93WBslzugFn+QTzapMWsqZMPLW/sI9ae7l3ToOChxxq2UO0HfEXjXpegAMZX118aKFNwM2SvjAqzXqUvRohPi/tdkv4khLORPU64yoONxjHNyVsD7MbUU5rzd67Nr/eqU8+8UOp2Sf/VbsiN/CU0deYKsioVgQIs9RsUMpqNshLSshkRPmZR23tFF+L7bPJG/69hsqmKNaVkISIRxHPHCBvhHbk6CAwaSOw47x0JIkCscBDfRzU76frdnTuSNcPqRBDEISLRyjDfWSKUdzMCV6o+edQagcF2hPmOzf4UAyJByn8R405bsMMCU6ZneO+8bQf5nyfXSnzdznawhJhXAcxtQQL8fszpioNurnefCMEB53wJ3bvDpOMiEch7NqGHNgotpOU54+MOw7DPCOgHMqSjyEdpmHjmRROA6X1YZ07IPpAzETGqJwmJ8GU21g1gAnpI1QMt6wiZcF4r1niJLhbTQfcfxCkkQuyFwghJDZLOAuIITCIYTCIYTCIYTCIYTCIYRQOIRQOIRQOIRQOIRQOISQWvi/AAMA9UczDEaG0p8AAAAASUVORK5CYII="]
-                // getMyASYS_ICONSdata();
+    "base64:iVBORw0KGgoAAAANSUhEUgAAAM4AAABRCAYAAACaL5lSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDA4QzAyM0IwREIwMTFFNEFGMDREM0VEMjExRjlBRTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDA4QzAyM0MwREIwMTFFNEFGMDREM0VEMjExRjlBRTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMDhDMDIzOTBEQjAxMUU0QUYwNEQzRUQyMTFGOUFFMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMDhDMDIzQTBEQjAxMUU0QUYwNEQzRUQyMTFGOUFFMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhF3nYoAAAlvSURBVHja7J1fjBXVHcfPJQJRoe1urQYJRBYlMUJisqwvGNjY3WgEUtN2CeWBIGb3Ju6LElsW+gA8AHe1UfuwTcBASB/Q7CZNG0tjw2pWU15kNzEBJFnLqmvQBNEbU0pbX+jve+9vlrOzM/fOnTtz78zs95P8cv/MOTPnzJzvnN/5zZ+Tu3XrliGE1MYC7gJCKBxCKBxCKBxCKBxCKBxCCIVDCIVDCIVDCIVDyDzmDq8/d+1/PY5trRB7VGyt2BqxVWLLxe4RW6JpbohdF7sq9qnYpNhFsY/Evoi6QKeOvMAWQKITToQ8LPaEWKfYBrFlVdL/SO1BsU3W/1+JnRMbE3tP7DIPHcmicLrFfia2VWxlBOuD4H6pNi32tthfxM7yEJIsCAc9yw6x7WJLYyozhNgvtlPsLbHT2hMRkjrhYPzynNhu/d4IIMxesafEToqdiGMcREhcwnlKe4AtTaoDhHpArF1sSOwdHlYSN/WGo/Niv2+iaGy2aFnyPKwkqT1OTmyf2pIE1Qdh7t+J/VjsqBgfbyWJEU5OXaMDCa0ThHxYbJHYIYqHJMVV25dg0dgc0LIS0nTh5FPWGPdxzEOaLRxEz/YkbEwTxG3bo2UnpOHCQci3XwffaWONln0FDzdptHBwcXNLiuu5RetASMOE02nKdwSknd1aF0IaIpwdGXFzVmhdCIldOLjLeXuG6rtd60RIrMLBowFLM1TfpVonQmITDh5C25rBOm/VuhESi3Dw5ObKDNZ5pdaNkFiE05nhenfy0JM4hIMI1IYM13uD4QVREoNw8DaaZRmu9zKtIyGh8HusYG3UG/pJ6w/NKy89O/P70j+nzSsn/zTz+5EHV5oHlt9rep58fFa+sQ8vmEtXps35C5/4+12PrTMP3H9v6dMGeZAX6/Cp49tsAiRK4TTsnrS771xsdj3TZTrWPeQrCtiljmnzhzfPmH//538zyyC0/l9tLonSC6wT1tmxzgxJ3q+//a4pdSTzx1Vb1SjR/Hr3L3xFY4MeCWnt3wf7d/iKxgYC+83un7vTruLhJ1H3OMsbsfHnpbdAo0Yv8rcPzpsz74/P6i3QU0AgtgA2b1pvPhQXDHltd+7MB+MzPQrSIa/tukE0mzeuN6f+/O6cOuZyubrr0tvb12bK73nDZ/cbbxwfzWKD2Tnw2l75KIiN/rHwYibvwggyobSfcO6Ju3COINDYX5axjsuNKo1PYLue+eksATy9scN0rF1T6q0AxkkYL9l8dvWaOXX1XfPZl9dK+W23zxJY1HXsUtEANK7RBDf+s1reakyJOFa7/utz6ivr6ZLlmTxBhHXVGvawmsfYYxYjf//HrHENBIMexVnmFs2cwIJr+WO33cKo64gGNKXfBzPcZo479Z2voqnU4zQENGz0DpWAaJAOLpoNxGa7dn6cv/jJbHfv/vtiqYu4ZhDN6pQd/5rdLUk/mPETQ109zo2GCOf8hUDpPr4yHTqvu8exAgQ3DCERC+d63BtGT1Ktt3G45uHK+VybmYPbDbSEc52Hn0QtnKtxb7jSuKZaWojOHvfUkt8JKjSijmT+jXEwqdOmeHuc/4bOe7OOvK46etLb24eoWI8pv4/aHhSP+IWZNRx9RX/mJd3xasvlP2wDUSo7wlUaQ8jyYrUKhClnvewceO2Yltkr4maHq0vLEXkz5SijU8duJ6jgXpf8btPfe937Q5YXNU+LpilYaSY0zUiVsrdrObD+FmsR8o1Uyx+kx5mcByeNSa/GLzauB6XdtRgH66w21rqR9aDRDJu5YWGsf1yF5pe3YeWsU2QoW6DQt6a94hLNzP6AYFRY4y7RGN0Hwypav/UXrLwtrsU91fIHFc7FeSCci67G2KIHGQehqL1CDmbK0TLnbFSQtH11brtPbdDaRqu5Hept82hAzShnveDEgN5ltZzNc2pePaFTJ5S9Fel89sewfs876zPlR+GdywAFFZcX7VYPtj5E/kCuGubcxPSBWb1D+iuto01BDwp2YreGl0vo923SEIf17LTXOqhhaHe7c+qa5VUYJRdOvg94uGxRlhMXMStdJu+u41oNyjgRMNzdoq7SNucPdc3y2pC7rBPJNtulQvkkTd7cnp2vx3iHyydUcFP2nzXkD9TjYIKmcxnubc4ZaxIqbazO2XnQbowunB0KV6m9ju2PusdALn/bfZZsVjnrZTCCtPZ+8hyHqLinLMEajzQDbtG48hcr5Q/a44AxU55zM4uMefi4Xg13FtJQJ6Qh2o16IqxwAi5ri7mcsd5vVsNguyhp/co44fPdzZTur7aQxZ0wwW5DqioczO6Mq4dZfO/Aex5uhcO3VqOr5l6EpVih0RcrbL/R5ayHqSj2RwURhdqeFZWzx5s1i62ScDAlOh706s+gcC4npHHVSoshoRDB9Fjjw7qpdq8apkTH7M5LM75fnTNeUc74rSxn5kTjXFtyGLDHUAhE1HDHeCDhYGWYEr13nginBQPwIBcfWc5UsdcKLmyLYoVB3h192mR/GvRRnwE4y5n+3qbdcnErBSvaoxbOmNjJLO9cRKGsgWehylX7rmZdlU9LOdM2RtS7ClqiFg44IfbXtO6thQvvuBkgWd7auePuRqcN8Zi5faGsWaSlnIlAw9yOS1vQIIEjmDb7frkogwMOcNWGTPnNMGl7O8zknYsX/UA+76p2NpcGB/93WBslzugFn+QTzapMWsqZMPLW/sI9ae7l3ToOChxxq2UO0HfEXjXpegAMZX118aKFNwM2SvjAqzXqUvRohPi/tdkv4khLORPU64yoONxjHNyVsD7MbUU5rzd67Nr/eqU8+8UOp2Sf/VbsiN/CU0deYKsioVgQIs9RsUMpqNshLSshkRPmZR23tFF+L7bPJG/69hsqmKNaVkISIRxHPHCBvhHbk6CAwaSOw47x0JIkCscBDfRzU76frdnTuSNcPqRBDEISLRyjDfWSKUdzMCV6o+edQagcF2hPmOzf4UAyJByn8R405bsMMCU6ZneO+8bQf5nyfXSnzdznawhJhXAcxtQQL8fszpioNurnefCMEB53wJ3bvDpOMiEch7NqGHNgotpOU54+MOw7DPCOgHMqSjyEdpmHjmRROA6X1YZ07IPpAzETGqJwmJ8GU21g1gAnpI1QMt6wiZcF4r1niJLhbTQfcfxCkkQuyFwghJDZLOAuIITCIYTCIYTCIYTCIYTCIYRQOIRQOIRQOIRQOIRQOISQWvi/AAMA9UczDEaG0p8AAAAASUVORK5CYII="]
+    // getMyASYS_ICONSdata();
     
     // TODO: implementieren wenn Attribute möglich sind
     var adma = ""; //adma = Aussendienstmitarbeiter
@@ -266,7 +309,12 @@ OfferUtils.buildOfferReport = function (pOfferID)
         "responsible" : adma,
         "SUMITEMSUM" : sumItemSum,
         "TOTAL" : text.formatDouble(total, "#,##0.00", true),
-        "printDiscount" : printDiscount ? "1" : "0"
+        "printDiscount" : printDiscount ? "1" : "0",
+        "subTotal": translate.text("Subtotal", language),
+        "InvoiceDiscount": translate.text("Invoice Discount", language),
+        "TotalWithoutVat": translate.text("without Vat", language),
+        "TotalWithVat": translate.text("incl. Vat", language),
+        "printHeadDiscount": printHeadDiscount ? "1" : "0"
     };
     
     
@@ -278,27 +326,30 @@ OfferUtils.buildOfferReport = function (pOfferID)
 
     offerReport.setReportData(ReportData.begin(
         [
-            "OFFER_CURRENCY", 
-            "OFFER_OFFERDATE", 
-            "OFFER_OFFERID",  
-            "OFFERITEM_INFO", 
-            "OFFERITEM_ASSIGNEDTO", //4
-            "OFFERITEM_ITEMNAME" , 
-            "OFFERITEM_OPTIONAL", 
-            "OFFERITEM_ITEMPOSITION", 
-            "PRODUCT_PRODUCTCODE", //8
-            "OFFER_HEADER", 
-            "OFFER_FOOTER", 
-            "OFFERITEM_QUANTITY", 
-            "OFFERITEM_PRICE", 
-            "OFFERITEM_DISCOUNT", //13
-            "OFFER_VERSNR", 
-            "OFFER_OFFERCODE", 
-            "OFFERITEM_VAT", 
-            "ITEMSUM", // 17
-            "OFFERITEM_UNITTEXT"
+        "OFFER_CURRENCY", 
+        "OFFER_OFFERDATE", 
+        "OFFER_OFFERID",  
+        "OFFERITEM_INFO", 
+        "OFFERITEM_ASSIGNEDTO", //4
+        "OFFERITEM_ITEMNAME" , 
+        "OFFERITEM_OPTIONAL", 
+        "OFFERITEM_ITEMPOSITION", 
+        "PRODUCT_PRODUCTCODE", //8
+        "OFFER_HEADER", 
+        "OFFER_FOOTER", 
+        "OFFERITEM_QUANTITY", 
+        "OFFERITEM_PRICE", 
+        "OFFERITEM_DISCOUNT", //13
+        "OFFER_VERSNR", 
+        "OFFER_OFFERCODE", 
+        "OFFERITEM_VAT", 
+        "ITEMSUM", // 17
+        "OFFERITEM_UNITTEXT",
+        "OFFER_DISCOUNT",
+        "OFFER_DISCOUNTED_NET",
+        "OFFER_DISCOUNTSUM"
         ])
-        .add(itemData));
+    .add(itemData));
         
     return offerReport.exportReport();
 }
@@ -336,7 +387,8 @@ OfferUtils.copyOffer = function (pOfferId, pOfferData)
         "OfferDeliveryTerm_param": pOfferData.deliveryTerm || "",
         "OfferPaymentTerm_param": pOfferData.paymentTerm || "",
         "ObjectType_param": pOfferData.objectType || "",
-        "ObjectRowId_param": pOfferData.objectRowId || ""
+        "ObjectRowId_param": pOfferData.objectRowId || "",
+        "Discount_param" :  pOfferData.discount || ""
     };
     neon.openContext("Offer", null, null, neon.OPERATINGSTATE_NEW, params);
 }
@@ -346,8 +398,9 @@ OfferUtils.copyOffer = function (pOfferId, pOfferData)
  * 
  * @param {String} pSourceOfferId
  * @param {String} pTargetOfferId
+ * @param {Number} pDiscount
  */
-OfferUtils.copyOfferItems = function (pSourceOfferId, pTargetOfferId)
+OfferUtils.copyOfferItems = function (pSourceOfferId, pTargetOfferId, pDiscount)
 {
     var inputMapping = {
         "OFFERITEM": {
@@ -363,12 +416,24 @@ OfferUtils.copyOfferItems = function (pSourceOfferId, pTargetOfferId)
     
     //update order price
     var [netPrice, vat] = oiUtils.getNetAndVat();
+    var discountedVals = OfferItemUtils.getDiscountedNet(null, pSourceOfferId,  pDiscount);
     
-    newWhere("OFFER.OFFERID", pTargetOfferId)
+    if(discountedVals){
+        newWhere("OFFER.OFFERID", pTargetOfferId)
+        .updateFields({
+            "NET": netPrice,
+            "VAT": vat,
+            "DISCOUNTED_NET": discountedVals[0],
+            "DISCOUNTED_VAT": discountedVals[1]
+        });
+    }
+    else{
+        newWhere("OFFER.OFFERID", pTargetOfferId)
         .updateFields({
             "NET": netPrice,
             "VAT": vat
         });
+    }
 }
 
 /**
@@ -384,8 +449,8 @@ OfferUtils.copyOfferItems = function (pSourceOfferId, pTargetOfferId)
  */
 OfferUtils.copyToOrder = function (pOfferId, pContextId, pRowId, pContactId, pLanguage, pCurrency, pAddress)
 {  
-        var fieldparams = 
-        {
+    var fieldparams = 
+    {
         "$field.CONTACT_ID" : pContactId,
         "$field.ISOLANGUAGE" : pLanguage,
         "$field.OFFER_ID" : pOfferId,
@@ -393,7 +458,7 @@ OfferUtils.copyToOrder = function (pOfferId, pContextId, pRowId, pContactId, pLa
         "$field.PAYMENTADDRESS" : pAddress || "",
         "$field.OBJECT_TYPE" : pContextId || "",
         "$field.OBJECT_ROWID" : pRowId || ""
-        };
+    };
     
     var params = {};
     params["Copy_param"] = JSON.stringify(fieldparams);
@@ -414,13 +479,13 @@ OfferUtils.getOfferTitleById = function (pOfferId)
     if (!pOfferId)
         return "";
     var offerNumber = newSelect("OFFERCODE, VERSNR")
-                        .from("OFFER")
-                        .where("OFFER.OFFERID", pOfferId)
-                        .arrayRow();
+    .from("OFFER")
+    .where("OFFER.OFFERID", pOfferId)
+    .arrayRow();
                         
     return offerNumber.length > 0 
-        ? translate.text("Offer") + " " + offerNumber.join("-") 
-        : "";
+    ? translate.text("Offer") + " " + offerNumber.join("-") 
+    : "";
 }
 
 
@@ -482,26 +547,26 @@ OfferItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCu
     this.initItemTree();
     
     var cols =  ["OFFERITEMID"
-                , "OFFER_ID"
-                , "PRODUCT_ID"
-                , "GROUPCODEID"
-                , "ASSIGNEDTO"
-                , "ITEMNAME"
-                , "UNIT"
-                , "PRICE"
-                , "VAT"
-                , "QUANTITY"
-                , "OPTIONAL"
-                , "ITEMPOSITION"
-                , "ITEMSORT"];
+    , "OFFER_ID"
+    , "PRODUCT_ID"
+    , "GROUPCODEID"
+    , "ASSIGNEDTO"
+    , "ITEMNAME"
+    , "UNIT"
+    , "PRICE"
+    , "VAT"
+    , "QUANTITY"
+    , "OPTIONAL"
+    , "ITEMPOSITION"
+    , "ITEMSORT"];
 
     return ItemUtils.prototype.insertPartsList.apply(this, [cols, pProductId, pAssignedTo, pCurrency, pContactId, [[["info", "INFO"], ["info", 
-                            "( " + newSelect("DESCRIPTION")
-                                .from("DESCRIPTIONTRANSLATION")
-                                .where("DESCRIPTIONTRANSLATION.OBJECT_ROWID = PRODUCT.PRODUCTID")
-                                .and("DESCRIPTIONTRANSLATION.OBJECT_TYPE", "Product")
-                                .and("DESCRIPTIONTRANSLATION.LANG", pLanguage)
-                                .toString() + ")"]]]]);
+        "( " + newSelect("DESCRIPTION")
+        .from("DESCRIPTIONTRANSLATION")
+        .where("DESCRIPTIONTRANSLATION.OBJECT_ROWID = PRODUCT.PRODUCTID")
+        .and("DESCRIPTIONTRANSLATION.OBJECT_TYPE", "Product")
+        .and("DESCRIPTIONTRANSLATION.LANG", pLanguage)
+        .toString() + ")"]]]]);
                                   
 }
 
@@ -541,3 +606,51 @@ OfferItemUtils.prototype.reOrgItems = function() {
     ItemUtils.prototype.reOrgItems.apply(this);
 }
 
+
+
+OfferItemUtils.getDiscountedNet = function(pExcludedIs, pOfferId, pDiscount, pExcludedProductgroups){
+    pDiscount = pDiscount ? pDiscount : 0;
+    var ret;
+    var sum = 0;
+    var sumExcluded = 0;
+    var vat = 0;
+    var vatExcluded = 0;
+    if(pOfferId){
+        var offeritemData = newSelect("QUANTITY, PRICE, DISCOUNT, VAT, OPTIONAL")
+        .from("OFFERITEM")
+        .where("OFFERITEM.OFFER_ID", pOfferId)
+        .andIfSet("OFFERITEM.GROUPCODEID", pExcludedProductgroups, SqlBuilder.NOT_IN())
+        .andIfSet("OFFERITEM.OFFERITEMID", pExcludedIs, SqlBuilder.NOT_IN())
+        .table();
+        for (var i = 0; i < offeritemData.length; i++)
+        {
+            sum = eMath.addDec(sum, ItemUtils.prototype.getItemSum(offeritemData[i][0], offeritemData[i][1], offeritemData[i][2], offeritemData[i][4]));
+            vat = eMath.addDec(vat, ItemUtils.prototype.getItemVAT(offeritemData[i][0], offeritemData[i][1], offeritemData[i][2], offeritemData[i][3], offeritemData[i][4]));
+        }
+       
+        sum = eMath.subDec(sum, eMath.divDec(eMath.mulDec(sum, pDiscount), "100"));
+        vat = eMath.subDec(vat, eMath.divDec(eMath.mulDec(vat, pDiscount), "100"));
+        
+        if(pExcludedProductgroups){
+            var excludedOfferitemData = newSelect("QUANTITY, PRICE, DISCOUNT, VAT, OPTIONAL")
+            .from("OFFERITEM")
+            .where("OFFERITEM.OFFER_ID", pOfferId)
+            .and("OFFERITEM.GROUPCODEID", pExcludedProductgroups, SqlBuilder.IN())
+            .andIfSet("OFFERITEM.OFFERITEMID", pExcludedIs, SqlBuilder.NOT_IN())
+            .table();
+            for (var j = 0; j < excludedOfferitemData.length; j++)
+            {
+                sumExcluded = eMath.addDec(sumExcluded, ItemUtils.prototype.getItemSum(excludedOfferitemData[j][0], excludedOfferitemData[j][1], excludedOfferitemData[j][2], excludedOfferitemData[j][4]));
+                vatExcluded = eMath.addDec(vatExcluded, ItemUtils.prototype.getItemVAT(excludedOfferitemData[i][0], excludedOfferitemData[i][1], excludedOfferitemData[i][2], excludedOfferitemData[i][3], excludedOfferitemData[i][4]));
+            }
+        }
+        if(sumExcluded){
+            sum = eMath.addDec(sum, sumExcluded);
+        }
+        if(vatExcluded){
+            vat = eMath.addDec(vat, vatExcluded);
+        }
+    }
+    ret = [sum, vat]
+    return ret;
+}
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index eecd2a9c83628dd909a5c182d53c53d38963a53b..fc7918d66d118477455fae249da67ff726a009cb 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -2279,6 +2279,9 @@ SqlBuilder.prototype._prepare = function(pField, pValue, pCondition, pFieldType,
     else
     {
         var type = pFieldType;
+        //booleans are normally stored with TINYINT, this is to support true/false directly
+        if (_isIntegerType(type) && Utils.isBoolean(pValue))
+            pValue = Number(pValue);
         values = [[pValue.toString(), type]];
     }
 
@@ -2286,6 +2289,14 @@ SqlBuilder.prototype._prepare = function(pField, pValue, pCondition, pFieldType,
         pCondition = SqlUtils.replaceConditionTemplate(pCondition, "#", alias);
     
     return [pCondition, values];
+    
+    function _isIntegerType (pType)
+    {
+        return pType == SQLTYPES.TINYINT
+            || pType == SQLTYPES.SMALLINT
+            || pType == SQLTYPES.INTEGER
+            || pType == SQLTYPES.BIGINT;
+    }
 }
 
 /**
@@ -3292,6 +3303,45 @@ SqlMaskingUtils.prototype.getConcatSymbol = function()
     }
 }
 
+
+/**
+*  Returns the group_concat function, which groups <br>
+*  multiple Row Values into one Cell. Note: This function <br>
+*  does not work on Derby<br>
+*
+* @param {String} pField                 <p>
+*                                       Expression that shall be grouped.<br>
+* @param {String} pSeperator             <p>
+*                                       Character that shall be used as Seperator<br>
+* @return {String}                      <p>
+*                                       Returns the field with groupConcat wrapped around<br>
+*/
+SqlMaskingUtils.prototype.getGroupConcat = function(pField, pSeperator) 
+{
+    var group;
+    if(pField == null || pSeperator == null || pField == null && pSeperator == null)
+        throw new Error(translate.withArguments("Field or Seperator were empty function: %0", ["SqlMaskingUtils.prototype.getGroupConcat"]));
+    
+    switch(this.dbType) 
+    {
+        case db.DBTYPE_MARIADB10:
+        case db.DBTYPE_MYSQL4:
+            group = " GROUP_CONCAT("+pField+" SEPARATOR "+pSeperator+")";
+            break;
+        case db.DBTYPE_ORACLE10_CLUSTER:
+        case db.DBTYPE_ORACLE10_THIN:
+        case db.DBTYPE_ORACLE10_OCI:
+        case db.DBTYPE_POSTGRESQL8:
+        case db.DBTYPE_SQLSERVER2000:
+            group = " STRING_AGG("+pField+", "+pSeperator+")";
+            break;
+        case db.DBTYPE_DERBY10:
+            logging.log(translate.withArguments("${SQL_LIB_UNSUPPORTED_DBTYPE} function: %0", ["SqlMaskingUtils.prototype.getGroupConcat"]), logging.ERROR);
+            break;
+    }
+    return group;
+}
+
 /**
 *  Returns the trim function, which removes the<br>
 *  leading and trailing spaces in a string, depending<br>
diff --git a/process/Turnover_lib/process.js b/process/Turnover_lib/process.js
index 1e69ad37d5f05c94e3779b5fe5c6edb3fe81cbc5..b070a1a6605c5a3c5d63ef49760af0709429cf9c 100644
--- a/process/Turnover_lib/process.js
+++ b/process/Turnover_lib/process.js
@@ -78,22 +78,33 @@ TurnoverUtil.getTurnoverData = function (pMaxYear, pYearCount, pSalesprojectId)
  */
 TurnoverUtil.getForecastData = function (pMaxYear, pYearCount, pSalesprojectId)
 {
-    var forecastCategory = translate.text('Forecast');
-
+    var forecastCategory = translate.text("Forecast");
     var minYear = pMaxYear - pYearCount + 1;
+    var sqlMask = new SqlMaskingUtils();
 
     // load data
-    var forecastSelect = newSelect("'" + forecastCategory + "', year(DATE_START) yearNum, month(DATE_START) monthNum, 0 discount, 0 vat, sum(VOLUME) price, 1 quantity, GROUPCODE prodGroup, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "GROUPCODE") + ") prodGroupName")
-                            .from("FORECAST")
-                            .where("FORECAST.DATE_START", pMaxYear, "year(#) <= ?", SQLTYPES.INTEGER)
-                            .and("FORECAST.DATE_START", minYear, "year(#) >= ?", SQLTYPES.INTEGER)
+    var forecastSelect = newSelect([
+            "'" + forecastCategory + "'", 
+            sqlMask.yearFromDate("DATE_START") + " yearNum", 
+            sqlMask.monthFromDate("DATE_START") + " monthNum", 
+            "0 discount", 
+            "0 vat", 
+            "sum(VOLUME) price", 
+            "1 quantity", 
+            "GROUPCODE prodGroup", 
+            "(" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "GROUPCODE") + ") prodGroupName"
+        ])
+        .from("FORECAST")
+        .where("FORECAST.DATE_START", pMaxYear, sqlMask.yearFromDate("#") + " <= ?", SQLTYPES.INTEGER)
+        .and("FORECAST.DATE_START", minYear, sqlMask.yearFromDate("#") + " >= ?", SQLTYPES.INTEGER);
+        
     if (pSalesprojectId)
     {
-        forecastSelect.and("FORECAST.OBJECT_TYPE", 'Salesproject')
+        forecastSelect.and("FORECAST.OBJECT_TYPE", "Salesproject")
                       .and("FORECAST.OBJECT_ROWID", pSalesprojectId)
     }   
     
-    forecastSelect.groupBy("year(DATE_START), month(DATE_START), GROUPCODE")
+    forecastSelect.groupBy([sqlMask.yearFromDate("DATE_START"), sqlMask.monthFromDate("DATE_START"), "GROUPCODE"])
                   .orderBy("yearNum, monthNum");
                   
     return forecastSelect.table();
diff --git a/process/Util_lib/process.js b/process/Util_lib/process.js
index 00ddb82a71bc8976508282f740e58b7fc996d5a3..154076f048f07ef9c800784fb3e056ea741ee46c 100644
--- a/process/Util_lib/process.js
+++ b/process/Util_lib/process.js
@@ -411,7 +411,7 @@ Utils.objectValues = function (pObject)
  */
 Utils.buildFilterObj = function(pFilterObj, pFieldName, pOperator, pContentType, pValue, pKey, pParentOperator)
 {
-    
+    //TODO: maybe something like this should be inside the JditoFilter_lib, but more fluent
     if(pParentOperator && pParentOperator != "AND" && pParentOperator != "OR")
         throw new Error(translate.text("Illegal Parent Operator in buildFilterObj-Function: "+pParentOperator));
     
diff --git a/process/buildSerialLetter_serverProcess/process.js b/process/buildSerialLetter_serverProcess/process.js
index 1d5cff1f39473a26019577b3c2d3c23121b5ced2..7be5de72cd71f6c4dee9d1fab003af0582d4afcd 100644
--- a/process/buildSerialLetter_serverProcess/process.js
+++ b/process/buildSerialLetter_serverProcess/process.js
@@ -21,4 +21,15 @@ SingleBinaryUtils.set("SERIALLETTER", "SERIALLETTERFILE", letterId, document.con
 
 var message = translate.text("Download ready");
 var description = translate.withArguments("Serial letter \"%0\" can now be downloaded", [document.title]);
-notification.addNotification(util.getNewUUID(), text.encodeMS(["SerialLetter", letterId]), null, null, "DownloadReady", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
\ No newline at end of file
+
+var notificationConfig = notification.createConfig()
+.initialState(notification.STATE_UNSEEN)
+.forcedPriority(notification.PRIO_NORMAL)
+    .linkInfo(text.encodeMS(["SerialLetter", letterId]))
+    .daysToLive(2)
+    .addUserWithId(user)
+    .notificationType("DownloadReady")
+    .caption(message)
+    .description(description);
+    
+notification.addNotificationWith(notificationConfig);
\ No newline at end of file
diff --git a/process/importLead_serverProcess/process.js b/process/importLead_serverProcess/process.js
index a24b084a933769d7e6d3ab8b6b1d316828841452..35ac42b2b31f5cd4b801573bd295413747352f42 100644
--- a/process/importLead_serverProcess/process.js
+++ b/process/importLead_serverProcess/process.js
@@ -192,7 +192,7 @@ if(exeptions != "")//insert error document
 if (userId)// if there is an user - show a notification to this user when the import is complete
 {
     var description = translate.withArguments("%0 leads imported, %1 errors", [rows, errorCount]);
-    notification.addNotification(util.getNewUUID(), null, null, null, "LeadImport_Notification", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [userId], importName, description);
+    notification.addNotification(util.getNewUUID(), null, null, null, "LeadImport_Notification", null, notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [userId], importName, description);
 }
 
 
diff --git a/process/mstBot_rest/process.js b/process/mstBot_rest/process.js
index c93ca1c87aa2e9770cf5510c7b46c8c6f1871878..26fc6409b451e12b8f4f4a4203009a0be62c8fb9 100644
--- a/process/mstBot_rest/process.js
+++ b/process/mstBot_rest/process.js
@@ -12,6 +12,7 @@ function restpost(pRequestAsJson)
      //Umformen, dass man den Body des Requests als JsonFormat Base64 decodiert hat
     var jsonRequest = JSON.parse(pRequestAsJson);
     var body = jsonRequest.body;
+    body = util.decodeBase64String(body);
     var jsonBody = JSON.parse(body);
    
     
diff --git a/process/sendBulkMail_serverProcess/process.js b/process/sendBulkMail_serverProcess/process.js
index 711120feb205e4b00a1fbda8afdea68708681fca..7ed237beffbb5978141a82b08c745385a1f21bee 100644
--- a/process/sendBulkMail_serverProcess/process.js
+++ b/process/sendBulkMail_serverProcess/process.js
@@ -23,5 +23,5 @@ if (user && !testRecipients)
     var message = translate.withArguments("Bulk mail \"%0\" was sent!", [mailName]);
     var description = translate.withArguments("%0 mails sent sucessfully, %1 mails failed. Process took %2 s.", 
         [res.sucessful, res.failed, Math.round((datetime.date() - startTime) / datetime.ONE_SECOND)]);
-    notification.addNotification(util.getNewUUID(), null, null, null, "BulkMailSent", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
+    notification.addNotification(util.getNewUUID(), null, null, null, "BulkMailSent", null, notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
 }
\ No newline at end of file
diff --git a/report/Offer_report/reportData.jrxml b/report/Offer_report/reportData.jrxml
index 2f3a25316e09aa7a8a18a74718bb72d930e3e4f5..76b33d239d03b4c903aed440ea6f8c4b5c30df50 100644
--- a/report/Offer_report/reportData.jrxml
+++ b/report/Offer_report/reportData.jrxml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report1" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="e7a916c8-3f9a-497d-84bb-3909b15271ea">
-	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.zoom" value="1.7715610000000064"/>
 	<property name="ireport.x" value="0"/>
-	<property name="ireport.y" value="0"/>
+	<property name="ireport.y" value="279"/>
 	<parameter name="myAddr" class="java.lang.String"/>
 	<parameter name="Pos" class="java.lang.String"/>
 	<parameter name="Articledescription" class="java.lang.String"/>
@@ -24,7 +24,7 @@
 	<parameter name="OfferDeliveryTerm" class="java.lang.String"/>
 	<parameter name="responsible" class="java.lang.String"/>
 	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
-		<defaultValueExpression><![CDATA["C:\\dev\\project\\basic\\report\\Offer_report\\"]]></defaultValueExpression>
+		<defaultValueExpression><![CDATA["C:\\Users\\s.neumaier\\Documents\\AditoProjects\\basic_2020.2\\report\\Offer_report\\"]]></defaultValueExpression>
 	</parameter>
 	<parameter name="adito.datasource.subdata" class="java.lang.Object"/>
 	<parameter name="SUMITEMSUM" class="java.lang.Double"/>
@@ -32,6 +32,11 @@
 	<parameter name="adito.image.myLogo" class="java.lang.String"/>
 	<parameter name="printDiscount" class="java.lang.String"/>
 	<parameter name="directlyResponsible" class="java.lang.String"/>
+	<parameter name="subTotal" class="java.lang.String"/>
+	<parameter name="InvoiceDiscount" class="java.lang.String"/>
+	<parameter name="TotalWithoutVat" class="java.lang.String"/>
+	<parameter name="TotalWithVat" class="java.lang.String"/>
+	<parameter name="printHeadDiscount" class="java.lang.String"/>
 	<queryString>
 		<![CDATA[]]>
 	</queryString>
@@ -53,6 +58,9 @@
 	<field name="OFFER_HEADER" class="java.lang.String"/>
 	<field name="ITEMSUM" class="java.lang.String"/>
 	<field name="OFFER_FOOTER" class="java.lang.String"/>
+	<field name="OFFER_DISCOUNT" class="java.lang.String"/>
+	<field name="OFFER_DISCOUNTED_NET" class="java.lang.String"/>
+	<field name="OFFER_DISCOUNTSUM" class="java.lang.String"/>
 	<sortField name="OFFER_OFFERID"/>
 	<group name="OFFERID" isStartNewPage="true">
 		<groupExpression><![CDATA[$F{OFFER_OFFERID}]]></groupExpression>
@@ -233,19 +241,69 @@
 			</band>
 		</groupHeader>
 		<groupFooter>
-			<band height="24">
+			<band height="23">
 				<line>
 					<reportElement x="356" y="4" width="196" height="1" uuid="228a3e86-96b6-470f-b9d8-9c566a0f1065"/>
 				</line>
 				<textField pattern="#,##0.00;-#,##0.00">
-					<reportElement x="452" y="6" width="100" height="15" uuid="f71cd6ef-6a10-4bd5-9bd5-4c8de5a276f1"/>
+					<reportElement x="469" y="8" width="83" height="15" uuid="f71cd6ef-6a10-4bd5-9bd5-4c8de5a276f1"/>
 					<textElement textAlignment="Right">
-						<font size="8"/>
+						<font size="8" isBold="true"/>
 					</textElement>
 					<textFieldExpression><![CDATA[$P{SUMITEMSUM}]]></textFieldExpression>
 				</textField>
+				<textField>
+					<reportElement x="356" y="8" width="113" height="15" uuid="c505a568-afb9-4cb3-9d15-b7803aeff207"/>
+					<textElement>
+						<font size="8" isBold="true"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$P{subTotal}]]></textFieldExpression>
+				</textField>
 			</band>
-			<band height="18">
+			<band height="34">
+				<printWhenExpression><![CDATA[!$P{printHeadDiscount}.equals("0")]]></printWhenExpression>
+				<textField isStretchWithOverflow="true">
+					<reportElement positionType="Float" x="469" y="19" width="83" height="15" uuid="26cc2b42-75a8-4e17-a674-f75a83465476">
+						<printWhenExpression><![CDATA[!$P{printHeadDiscount}.equals("0")]]></printWhenExpression>
+					</reportElement>
+					<textElement textAlignment="Right">
+						<font size="8" isBold="true"/>
+						<paragraph lineSpacing="Proportional"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$F{OFFER_DISCOUNTED_NET}]]></textFieldExpression>
+				</textField>
+				<textField isStretchWithOverflow="true">
+					<reportElement positionType="Float" x="356" y="19" width="113" height="15" uuid="05470803-14c1-4ecc-81f0-de432ec80c27">
+						<printWhenExpression><![CDATA[!$P{printHeadDiscount}.equals("0")]]></printWhenExpression>
+					</reportElement>
+					<textElement>
+						<font size="8" isBold="true"/>
+						<paragraph lineSpacing="Proportional"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$P{Total} + " " + $F{OFFER_CURRENCY} + " " + $P{TotalWithoutVat}]]></textFieldExpression>
+				</textField>
+				<textField isStretchWithOverflow="true">
+					<reportElement positionType="Float" x="356" y="2" width="113" height="15" uuid="152d4841-b63c-4cd3-bc6b-935af23ad0b8">
+						<printWhenExpression><![CDATA[!$P{printHeadDiscount}.equals("0")]]></printWhenExpression>
+					</reportElement>
+					<textElement>
+						<font size="8"/>
+						<paragraph lineSpacing="Proportional"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$F{OFFER_DISCOUNT} + " % " + $P{InvoiceDiscount}]]></textFieldExpression>
+				</textField>
+				<textField isStretchWithOverflow="true">
+					<reportElement positionType="Float" x="469" y="2" width="83" height="15" uuid="e205d256-1ac5-439b-9b9c-3735d7a301df">
+						<printWhenExpression><![CDATA[!$P{printHeadDiscount}.equals("0")]]></printWhenExpression>
+					</reportElement>
+					<textElement textAlignment="Right">
+						<font size="8"/>
+						<paragraph lineSpacing="Proportional"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$F{OFFER_DISCOUNTSUM}]]></textFieldExpression>
+				</textField>
+			</band>
+			<band height="19">
 				<subreport>
 					<reportElement isPrintRepeatedValues="false" x="355" y="2" width="196" height="15" isRemoveLineWhenBlank="true" uuid="8683c745-01bf-44aa-af62-a6ba881a9edd"/>
 					<subreportParameter name="PlusSalestax">
@@ -257,46 +315,47 @@
 			</band>
 			<band height="33">
 				<textField>
-					<reportElement x="20" y="13" width="100" height="20" uuid="112f15db-0989-430e-b2c4-61f975f7b8a4">
-						<printWhenExpression><![CDATA[!$P{OfferPaymentTerm}.equals("")]]></printWhenExpression>
-					</reportElement>
-					<textElement>
-						<font size="8"/>
-					</textElement>
-					<textFieldExpression><![CDATA[$P{PaymentConditions}]]></textFieldExpression>
-				</textField>
-				<textField>
-					<reportElement x="122" y="13" width="100" height="20" uuid="8149be09-d439-4e1a-a853-f82bd5e5683e"/>
+					<reportElement x="122" y="12" width="100" height="20" uuid="8149be09-d439-4e1a-a853-f82bd5e5683e"/>
 					<textElement>
 						<font size="8"/>
 					</textElement>
 					<textFieldExpression><![CDATA[$P{OfferPaymentTerm}]]></textFieldExpression>
 				</textField>
+				<line>
+					<reportElement x="356" y="29" width="196" height="1" uuid="982cac61-6b87-4439-93cb-6c89fcc7932c"/>
+					<graphicElement>
+						<pen lineWidth="3.0" lineStyle="Double"/>
+					</graphicElement>
+				</line>
 				<textField>
-					<reportElement x="402" y="8" width="90" height="20" uuid="c3444576-6cb8-47f2-9dc9-e892a91ceb07"/>
-					<textElement textAlignment="Right">
+					<reportElement x="356" y="7" width="113" height="20" uuid="c3444576-6cb8-47f2-9dc9-e892a91ceb07"/>
+					<textElement textAlignment="Left">
 						<font size="8" isBold="true"/>
 					</textElement>
-					<textFieldExpression><![CDATA[$P{Total} + " " + $F{OFFER_CURRENCY}]]></textFieldExpression>
+					<textFieldExpression><![CDATA[$P{Total} + " " + $F{OFFER_CURRENCY} + " " + $P{TotalWithVat}]]></textFieldExpression>
 				</textField>
 				<line>
-					<reportElement x="356" y="2" width="196" height="1" uuid="8973e664-cfc0-4b52-bd0d-c80a49910da2"/>
-				</line>
-				<line>
-					<reportElement x="356" y="30" width="196" height="1" uuid="982cac61-6b87-4439-93cb-6c89fcc7932c"/>
-					<graphicElement>
-						<pen lineWidth="3.0" lineStyle="Double"/>
-					</graphicElement>
+					<reportElement x="356" y="1" width="196" height="1" uuid="8973e664-cfc0-4b52-bd0d-c80a49910da2"/>
 				</line>
 				<textField pattern="###0.00;-###0.00">
-					<reportElement x="491" y="8" width="59" height="20" uuid="75bb0951-e562-4170-a5c2-731d3219ec66"/>
+					<reportElement x="469" y="7" width="81" height="20" uuid="75bb0951-e562-4170-a5c2-731d3219ec66"/>
 					<textElement textAlignment="Right">
 						<font size="8" isBold="true"/>
 					</textElement>
 					<textFieldExpression><![CDATA[$P{TOTAL}]]></textFieldExpression>
 				</textField>
+				<textField>
+					<reportElement x="20" y="12" width="100" height="20" uuid="112f15db-0989-430e-b2c4-61f975f7b8a4">
+						<printWhenExpression><![CDATA[!$P{OfferPaymentTerm}.equals("")]]></printWhenExpression>
+					</reportElement>
+					<textElement>
+						<font size="8"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$P{PaymentConditions}]]></textFieldExpression>
+				</textField>
 			</band>
 			<band height="20">
+				<printWhenExpression><![CDATA[($F{OFFER_FOOTER} != null && !$F{OFFER_FOOTER}.trim().isEmpty())]]></printWhenExpression>
 				<textField>
 					<reportElement x="20" y="0" width="100" height="20" uuid="75b328c0-4ab1-478d-afb8-0ed8974da1af">
 						<printWhenExpression><![CDATA[!$P{OfferDeliveryTerm}.equals("")]]></printWhenExpression>
@@ -315,7 +374,6 @@
 				</textField>
 			</band>
 			<band height="20">
-				<printWhenExpression><![CDATA[($F{OFFER_FOOTER} != null && !$F{OFFER_FOOTER}.trim().isEmpty())]]></printWhenExpression>
 				<textField isStretchWithOverflow="true">
 					<reportElement x="20" y="0" width="530" height="20" uuid="2a2d0fe8-9c83-43b7-913d-a551a9879608"/>
 					<textElement>
diff --git a/report/Offer_report/reportData_subreport1.jrxml b/report/Offer_report/reportData_subreport1.jrxml
index 45e05cbc8afa6664aeeca709bcf3ec6afcf86df2..2429050e564354bcdb770e4cdb3ce3d989251f82 100644
--- a/report/Offer_report/reportData_subreport1.jrxml
+++ b/report/Offer_report/reportData_subreport1.jrxml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="reportData_subreport1" pageWidth="200" pageHeight="802" columnWidth="200" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="65da6912-abcf-40ed-a854-750d851fe857">
-	<property name="ireport.zoom" value="6.72749994932561"/>
+	<property name="ireport.zoom" value="4.177248169415656"/>
 	<property name="ireport.x" value="0"/>
 	<property name="ireport.y" value="0"/>
 	<parameter name="PlusSalestax" class="java.lang.String"/>
diff --git a/report/Reminder_report/reportData.jrxml b/report/Reminder_report/reportData.jrxml
index 1347b1ef959b34c58be528e8eecfb4bc139ff51a..ecbfcaa763c5fd38ea839ee2e483d79b57bf80ea 100644
--- a/report/Reminder_report/reportData.jrxml
+++ b/report/Reminder_report/reportData.jrxml
@@ -2,7 +2,7 @@
 <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Mahnung" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="e7a916c8-3f9a-497d-84bb-3909b15271ea">
 	<property name="ireport.zoom" value="2.1435888100000016"/>
 	<property name="ireport.x" value="0"/>
-	<property name="ireport.y" value="0"/>
+	<property name="ireport.y" value="192"/>
 	<parameter name="myAddr" class="java.lang.String"/>
 	<parameter name="Kontenabstimmung" class="java.lang.String"/>
 	<parameter name="Rech.-Nr" class="java.lang.String"/>
@@ -114,14 +114,14 @@
 				</textField>
 				<textField>
 					<reportElement x="307" y="0" width="81" height="15" uuid="000feb72-9b7d-42e6-ade9-8e12359c3eef"/>
-					<textElement>
+					<textElement textAlignment="Right">
 						<font size="8"/>
 					</textElement>
 					<textFieldExpression><![CDATA[$R{Rechnungsbetrag}]]></textFieldExpression>
 				</textField>
 				<textField>
 					<reportElement x="430" y="0" width="81" height="15" uuid="8eee46c0-f3c3-4563-b1b1-746aeb7e73c6"/>
-					<textElement>
+					<textElement textAlignment="Right">
 						<font size="8"/>
 					</textElement>
 					<textFieldExpression><![CDATA[$P{OutstandingAmount}]]></textFieldExpression>
@@ -170,14 +170,14 @@
 				<textFieldExpression><![CDATA[$P{Reminder}]]></textFieldExpression>
 			</textField>
 			<textField pattern="dd.MM.yyyy">
-				<reportElement x="388" y="192" width="100" height="20" uuid="5141d92f-3325-445b-b616-90630c1648f7"/>
+				<reportElement x="411" y="192" width="100" height="20" uuid="5141d92f-3325-445b-b616-90630c1648f7"/>
 				<textElement textAlignment="Right">
 					<font size="8"/>
 				</textElement>
 				<textFieldExpression><![CDATA[new java.util.Date()]]></textFieldExpression>
 			</textField>
-			<textField>
-				<reportElement x="13" y="232" width="294" height="20" uuid="3f7d1c4a-a326-436b-831d-5da9fd255bf0"/>
+			<textField isStretchWithOverflow="true">
+				<reportElement x="13" y="232" width="542" height="20" isPrintWhenDetailOverflows="true" uuid="3f7d1c4a-a326-436b-831d-5da9fd255bf0"/>
 				<textElement>
 					<font size="8" isBold="true"/>
 				</textElement>
diff --git a/report/Salesorder_report/reportData.jrxml b/report/Salesorder_report/reportData.jrxml
index dddb5cf7b47625ee6351e06257b40734c7dbbf38..e885e5f6bceda798028872ef5bc26c7c7f393d88 100644
--- a/report/Salesorder_report/reportData.jrxml
+++ b/report/Salesorder_report/reportData.jrxml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Beleg" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="e7a916c8-3f9a-497d-84bb-3909b15271ea">
-	<property name="ireport.zoom" value="1.0"/>
-	<property name="ireport.x" value="0"/>
-	<property name="ireport.y" value="0"/>
+	<property name="ireport.zoom" value="2.3579476910000023"/>
+	<property name="ireport.x" value="175"/>
+	<property name="ireport.y" value="665"/>
 	<parameter name="myAddr" class="java.lang.String"/>
 	<parameter name="Artikelbezeichnung" class="java.lang.String"/>
 	<parameter name="Artikel-Nr" class="java.lang.String"/>
@@ -27,7 +27,7 @@
 	<parameter name="SUMITEMSUM" class="java.lang.Double"/>
 	<parameter name="TOTAL" class="java.lang.String"/>
 	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
-		<defaultValueExpression><![CDATA["C:\\dev\\project\\basic\\report\\Salesorder_report\\"]]></defaultValueExpression>
+		<defaultValueExpression><![CDATA["C:\\Entwicklung\\2020.2\\project\\basic2\\report\\Salesorder_report\\"]]></defaultValueExpression>
 	</parameter>
 	<parameter name="adito.datasource.subdata" class="java.lang.Object" isForPrompting="false"/>
 	<parameter name="adito.image.myLogo" class="java.lang.String"/>
@@ -77,7 +77,7 @@
 	<variable name="Menge_Einheit" class="java.lang.String">
 		<variableExpression><![CDATA[$F{QUANTITY}.toString() + " " + $F{UNITTEXT}]]></variableExpression>
 	</variable>
-	<group name="SALESORDERID">
+	<group name="SALESORDERID" isStartNewPage="true">
 		<groupExpression><![CDATA[$F{SALESORDERID}]]></groupExpression>
 		<groupHeader>
 			<band height="53">
@@ -302,6 +302,15 @@
 					<textFieldExpression><![CDATA[$P{OrderDeliveryTerm}]]></textFieldExpression>
 				</textField>
 			</band>
+			<band height="50">
+				<textField isStretchWithOverflow="true">
+					<reportElement x="0" y="0" width="555" height="50" uuid="678c4956-6136-49ba-8199-ed41c384e3ea"/>
+					<textElement>
+						<font size="8"/>
+					</textElement>
+					<textFieldExpression><![CDATA[$F{FOOTER}]]></textFieldExpression>
+				</textField>
+			</band>
 		</groupFooter>
 	</group>
 	<group name="VAT">
@@ -397,17 +406,6 @@
 			</textField>
 		</band>
 	</detail>
-	<columnFooter>
-		<band height="21" splitType="Stretch">
-			<textField isStretchWithOverflow="true">
-				<reportElement x="0" y="0" width="555" height="20" uuid="678c4956-6136-49ba-8199-ed41c384e3ea"/>
-				<textElement>
-					<font size="8"/>
-				</textElement>
-				<textFieldExpression><![CDATA[$F{FOOTER}]]></textFieldExpression>
-			</textField>
-		</band>
-	</columnFooter>
 	<pageFooter>
 		<band height="46" splitType="Stretch">
 			<textField pattern="EEEEE dd MMMMM yyyy">