diff --git a/.liquibase/Data_alias/basic/2019.1.4/AditoBasic/init_SalesprojectState.xml b/.liquibase/Data_alias/basic/2019.1.4/AditoBasic/init_SalesprojectState.xml
index 89f21df74c3819160a9939c1ee5db66dba382a5d..e8705ad413b54602f48a5926cdd39c4d41693664 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/AditoBasic/init_SalesprojectState.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/AditoBasic/init_SalesprojectState.xml
@@ -4,7 +4,7 @@
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="115495eb-dff4-436d-8114-b9a7644586bf"/>
 
-            <column name="KEYID" value="23d38486-4cce-41ce-a8df-164ad44df706"/>
+            <column name="KEYID" value="SALPROJSTATPOSTPONED"/>
             <column name="TITLE" value="Postponed"/>
             <column name="CONTAINER" value="SalesprojectState"/>
             <column name="SORTING" valueNumeric="2"/>
@@ -34,7 +34,7 @@
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="19997ffa-bfe3-4f6a-82f8-e862acb24655"/>
 
-            <column name="KEYID" value="SALPROJSTATLOST"/>
+            <column name="KEYID" value="SALPROJSTATORDER"/>
             <column name="TITLE" value="Order"/>
             <column name="CONTAINER" value="SalesprojectState"/>
             <column name="SORTING" valueNumeric="5"/>
@@ -44,50 +44,12 @@
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="d8e2cc64-cc61-440e-b0fc-3d5b45d75ba0"/>
 
-            <column name="KEYID" value="d8a60f60-a4e6-46ee-88ec-bac53e1afedd"/>
+            <column name="KEYID" value="SALPROJSTATLOST"/>
             <column name="TITLE" value="Lost"/>
             <column name="CONTAINER" value="SalesprojectState"/>
             <column name="SORTING" valueNumeric="6"/>
             <column name="ISACTIVE" valueNumeric="1"/>
             <column name="ISESSENTIAL" valueNumeric="0"/>
         </insert>
-        <rollback>
-            <delete tableName="AB_KEYWORD_ENTRY">
-                <where>AB_KEYWORD_ENTRYID = ?</where>
-                <whereParams>
-                    <param value="c6eeab06-cec9-42c3-8f11-468c7e602de4" />
-                </whereParams>
-            </delete>
-            <delete tableName="AB_KEYWORD_ENTRY">
-                <where>AB_KEYWORD_ENTRYID = ?</where>
-                <whereParams>
-                    <param value="115495eb-dff4-436d-8114-b9a7644586bf" />
-                </whereParams>
-            </delete>
-            <delete tableName="AB_KEYWORD_ENTRY">
-                <where>AB_KEYWORD_ENTRYID = ?</where>
-                <whereParams>
-                    <param value="9212a797-4470-4170-b4d1-330a5d991625" />
-                </whereParams>
-            </delete>
-            <delete tableName="AB_KEYWORD_ENTRY">
-                <where>AB_KEYWORD_ENTRYID = ?</where>
-                <whereParams>
-                    <param value="1f857be1-7de0-479f-bac8-59b22d48fe39" />
-                </whereParams>
-            </delete>
-            <delete tableName="AB_KEYWORD_ENTRY">
-                <where>AB_KEYWORD_ENTRYID = ?</where>
-                <whereParams>
-                    <param value="19997ffa-bfe3-4f6a-82f8-e862acb24655" />
-                </whereParams>
-            </delete>
-            <delete tableName="AB_KEYWORD_ENTRY">
-                <where>AB_KEYWORD_ENTRYID = ?</where>
-                <whereParams>
-                    <param value="d8e2cc64-cc61-440e-b0fc-3d5b45d75ba0" />
-                </whereParams>
-            </delete>
-        </rollback>
     </changeSet>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.1.4/BulkMail/bulkMail_keywords.xml b/.liquibase/Data_alias/basic/2019.1.4/BulkMail/bulkMail_keywords.xml
index e970a26e5417dddbbbed5407fc254a5ee93e44e9..8e54b9eef3b41bb4c7e83cbf725f252f8aa31374 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/BulkMail/bulkMail_keywords.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/BulkMail/bulkMail_keywords.xml
@@ -4,27 +4,76 @@
     <changeSet author="s.listl" id="c652301e-5510-4e1a-a39d-cdc6a3356d62">
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="2710c44b-73a7-4da5-b828-c7ac572ab79c"/>
-            <column name="KEYID" value="9a0c5608-070e-49fb-92cd-f6abece9242d"/>
+            <column name="KEYID" value="EMAILPENDING                        "/>
             <column name="TITLE" value="Pending"/>
-            <column name="CONTAINER" value="BulkMailSentStatus"/>
+            <column name="CONTAINER" value="BulkMailRecipientStatus"/>
             <column name="SORTING" valueNumeric="1"/>
             <column name="ISACTIVE" valueNumeric="1"/>
         </insert>
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="82d04090-3ef1-4eaf-9836-0490733a078f"/>
-            <column name="KEYID" value="147211fb-a1cf-49c8-8e08-c3cfe0404f9b"/>
+            <column name="KEYID" value="EMAILSENT                           "/>
             <column name="TITLE" value="Sent"/>
-            <column name="CONTAINER" value="BulkMailSentStatus"/>
+            <column name="CONTAINER" value="BulkMailRecipientStatus"/>
             <column name="SORTING" valueNumeric="2"/>
             <column name="ISACTIVE" valueNumeric="1"/>
         </insert>
         <insert tableName="AB_KEYWORD_ENTRY">
             <column name="AB_KEYWORD_ENTRYID" value="d1d6a461-1bbf-4f03-ac99-33a2d38a36e3"/>
-            <column name="KEYID" value="353e27e9-7491-4bfd-b9f9-f18f2cb2a36c"/>
+            <column name="KEYID" value="EMAILFAILED                         "/>
             <column name="TITLE" value="Failed"/>
-            <column name="CONTAINER" value="BulkMailSentStatus"/>
+            <column name="CONTAINER" value="BulkMailRecipientStatus"/>
             <column name="SORTING" valueNumeric="3"/>
             <column name="ISACTIVE" valueNumeric="1"/>
         </insert>
+        
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="6e95db61-6991-41c8-b2bb-e2b39c38efa3"/>
+            <column name="KEYID" value="BULKMAILNOTSENT                     "/>
+            <column name="TITLE" value="Not sent"/>
+            <column name="CONTAINER" value="BulkMailStatus"/>
+            <column name="SORTING" valueNumeric="1"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="250e5cd6-1842-46b1-b968-03988255eaba"/>
+            <column name="KEYID" value="BULKMAILBEINGSENT                   "/>
+            <column name="TITLE" value="Is being sent"/>
+            <column name="CONTAINER" value="BulkMailStatus"/>
+            <column name="SORTING" valueNumeric="2"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ENTRY">
+            <column name="AB_KEYWORD_ENTRYID" value="ec51253e-9b45-468d-aafa-42331e54f32b"/>
+            <column name="KEYID" value="BULKMAILSENT                        "/>
+            <column name="TITLE" value="Sent"/>
+            <column name="CONTAINER" value="BulkMailStatus"/>
+            <column name="SORTING" valueNumeric="3"/>
+            <column name="ISACTIVE" valueNumeric="1"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTE">
+                <column name="AB_KEYWORD_ATTRIBUTEID" value="ec51253e-9b45-468d-aafa-42331e54f32b"/>
+                <column name="NAME" value="bulkMailIcon"/>
+                <column name="CONTAINER" value="BulkMailStatus"/>
+                <column name="TYPE" value="CHAR_VALUE"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+                <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="801268a9-e93e-4481-b98d-1e37ca308e10"/>
+                <column name="AB_KEYWORD_ENTRY_ID" value="6e95db61-6991-41c8-b2bb-e2b39c38efa3"/>
+                <column name="AB_KEYWORD_ATTRIBUTE_ID" value="ec51253e-9b45-468d-aafa-42331e54f32b"/>
+                <column name="CHAR_VALUE" value="VAADIN:ENVELOPE_OPEN"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+                <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="ad58ebca-7b2a-4488-b2e0-3ab8f4740845"/>
+                <column name="AB_KEYWORD_ENTRY_ID" value="250e5cd6-1842-46b1-b968-03988255eaba"/>
+                <column name="AB_KEYWORD_ATTRIBUTE_ID" value="ec51253e-9b45-468d-aafa-42331e54f32b"/>
+                <column name="CHAR_VALUE" value="VAADIN:ENVELOPE_OPEN"/>
+        </insert>
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+                <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="fe80ac90-af31-466a-a309-a34edb6be6cf"/>
+                <column name="AB_KEYWORD_ENTRY_ID" value="ec51253e-9b45-468d-aafa-42331e54f32b"/>
+                <column name="AB_KEYWORD_ATTRIBUTE_ID" value="ec51253e-9b45-468d-aafa-42331e54f32b"/>
+                <column name="CHAR_VALUE" value="VAADIN:ENVELOPE"/>
+        </insert>
     </changeSet>
 </databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2019.1.4/KeywordRelatedStructureChanges/SalesProjectState.xml b/.liquibase/Data_alias/basic/2019.1.4/KeywordRelatedStructureChanges/SalesProjectState.xml
index 931bd328935f7899110b370fb8c0bdcd454f8ea8..2f63980104102d820e5ab1b1caa9f23167dde818 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/KeywordRelatedStructureChanges/SalesProjectState.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/KeywordRelatedStructureChanges/SalesProjectState.xml
@@ -10,7 +10,7 @@
             <where>STATE_OLD = 1</where>
         </update>
         <update tableName="SALESPROJECT">
-            <column name="STATE" value="23d38486-4cce-41ce-a8df-164ad44df706"/>
+            <column name="STATE" value="SALPROJSTATPOSTPONED"/>
             <where>STATE_OLD = 2</where>
         </update>
         <update tableName="SALESPROJECT">
@@ -22,45 +22,13 @@
             <where>STATE_OLD = 4</where>
         </update>
         <update tableName="SALESPROJECT">
-            <column name="STATE" value="SALPROJSTATLOST"/>
+            <column name="STATE" value="SALPROJSTATORDER"/>
             <where>STATE_OLD = 5</where>
         </update>
         <update tableName="SALESPROJECT">
-            <column name="STATE" value="d8a60f60-a4e6-46ee-88ec-bac53e1afedd"/>
+            <column name="STATE" value="SALPROJSTATLOST"/>
             <where>STATE_OLD = 6</where>
         </update>
         <dropColumn tableName="SALESPROJECT" columnName="STATE_OLD"/>
- 
-        <rollback>
-            <renameColumn newColumnName="STATE_OLD" oldColumnName="STATE" columnDataType="CHAR(36)" tableName="SALESPROJECT"/>
-            <addColumn tableName="SALESPROJECT">
-                <column name="STATE" type="INTEGER"/>
-            </addColumn>   
-            <update tableName="SALESPROJECT">
-                <column name="STATE" valueNumeric="1"/>
-                <where>STATE_OLD = 'SALPROJSTATOPEN'</where>
-            </update>
-            <update tableName="SALESPROJECT">
-                <column name="STATE" valueNumeric="2"/>
-                <where>STATE_OLD = '23d38486-4cce-41ce-a8df-164ad44df706'</where>
-            </update>
-            <update tableName="SALESPROJECT">
-                <column name="STATE" valueNumeric="3"/>
-                <where>STATE_OLD = 'SALPROJSTATABORT'</where>
-            </update>
-            <update tableName="SALESPROJECT">
-                <column name="STATE" valueNumeric="4"/>
-                <where>STATE_OLD = 'SALPROJSTATPARTIAL'</where>
-            </update>
-            <update tableName="SALESPROJECT">
-                <column name="STATE" valueNumeric="5"/>
-                <where>STATE_OLD = 'SALPROJSTATLOST'</where>
-            </update>
-            <update tableName="SALESPROJECT">
-                <column name="STATE" valueNumeric="6"/>
-                <where>STATE_OLD = 'd8a60f60-a4e6-46ee-88ec-bac53e1afedd'</where>
-            </update>
-            <dropColumn tableName="SALESPROJECT" columnName="STATE_OLD"/>
-        </rollback>
     </changeSet>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.1.4/changelog.xml b/.liquibase/Data_alias/basic/2019.1.4/changelog.xml
index c76020a5b1a97d67a9725995fa037b5619ff5a1c..57c4dcd3fa87ecc8450287ab2017a7f0f5ebb9c0 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/changelog.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/changelog.xml
@@ -94,7 +94,6 @@
     <include relativeToChangelogFile="true" file="constraintsRefactor/indices_Activity.xml"/>
     <include relativeToChangelogFile="true" file="constraintsRefactor/indices_Task.xml"/>
 
-    <include relativeToChangelogFile="true" file="update_Keyword_Essentials.xml" />
     <include relativeToChangelogFile="true" file="Contactmanagement_added_ImageBlobs.xml" />
 	
     <include relativeToChangelogFile="true" file="alter_activityLink.xml" />
@@ -166,4 +165,9 @@
 
     <include relativeToChangelogFile="true" file="Attributes/AB_ATTRIBUTE.xml"/>
     <include relativeToChangelogFile="true" file="Attributes/AB_ATTRIBUTEUSAGE.xml"/>
+
+    <include relativeToChangelogFile="true" file="create_description_translation.xml"/>
+    <include relativeToChangelogFile="true" file="remove_productInfo_language.xml"/>
+    
+    <include relativeToChangelogFile="true" file="update_Keyword_Essentials.xml"/>
 </databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2019.1.4/create_description_translation.xml b/.liquibase/Data_alias/basic/2019.1.4/create_description_translation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..07230bba7ef2d81b2165a00c360d2295255b1483
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.1.4/create_description_translation.xml
@@ -0,0 +1,18 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+<changeSet author="m.mansour" id="ba354d1e-f161-4b20-aaf2-f7ddf6419f57">
+    <createTable tableName="DESCRIPTIONTRANSLATION">
+        <column name="DESCRIPTIONTRANSLATIONID" type="CHAR(36)">
+            <constraints primaryKey="true" primaryKeyName="PK_DESCRIPTIONTRANSLATION_DESCRIPTIONTRANSLATIONID"/>
+        </column>
+        <column name="OBJECT_TYPE" type="VARCHAR(50)">
+            <constraints nullable="false"/>
+        </column>
+        <column name="OBJECT_ROWID" type="CHAR(36)">
+            <constraints nullable="false"/>
+        </column>
+        <column name="LANG" type="CHAR(36)"/>
+        <column name="DESCRIPTION" type="NCLOB"/>
+    </createTable>
+</changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.1.4/remove_productInfo_language.xml b/.liquibase/Data_alias/basic/2019.1.4/remove_productInfo_language.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1cd980ac242eb266a59827214d707d6c55b318fd
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.1.4/remove_productInfo_language.xml
@@ -0,0 +1,7 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+<changeSet author="m.mansour" id="99b87771-f603-49b7-85df-09931eac69df">
+    <dropColumn tableName="PRODUCT" columnName="LANGUAGE"/>
+    <dropColumn tableName="PRODUCT" columnName="INFO"/>
+</changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2019.1.4/update_Keyword_Essentials.xml b/.liquibase/Data_alias/basic/2019.1.4/update_Keyword_Essentials.xml
index 42e86e904cace377c5d5b0938759eaddb7c5840f..2a81caa90f8217a62d3cde44d9169899531ea189 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/update_Keyword_Essentials.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/update_Keyword_Essentials.xml
@@ -3,15 +3,59 @@
   <changeSet author="a.loreth" id="b1629529-92ab-437d-b864-0fd68fe5ceab">
     <update tableName="AB_KEYWORD_ENTRY">
       <column name="ISESSENTIAL" valueNumeric="1" />
-      <where>KEYID in ('QUANTITYPIECES', 'i', 'o', 'CONTACTSTATACTIVE', 'NEW', 'TASK', 'PRICELISTDEFAULT', 'TASKPRIONORMAL', 'TASKPROG0')</where>
-    </update>
-
-
-    <rollback>
-      <update tableName="AB_KEYWORD_ENTRY">
-        <column name="ISESSENTIAL" valueNumeric="0" />
-        <where>KEYID in ('QUANTITYPIECES', 'i', 'o', 'CONTACTSTATACTIVE', 'NEW', 'TASK', 'PRICELISTDEFAULT', 'TASKPRIONORMAL', 'TASKPROG0')</where>
-      </update>
-    </rollback>
+      <where>CONTAINER = 'QuantityUnit' and KEYID in ('QUANTITYPIECES                      ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'ActivityDirection' and KEYID in ('i                                   ', 'o                                   ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'ContactStatus' and KEYID in ('CONTACTSTATACTIVE                   ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'TaskStatus' and KEYID in ('NEW                                 ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'TaskType' and KEYID in ('TASK                                ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'ProductPricelist' and KEYID in ('PRICELISTDEFAULT                    ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'TaskPriority' and KEYID in ('TASKPRIOMEDIUM                      ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'TaskProgress' and KEYID in ('TASKPROG0                           ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'ContractStatus' and KEYID in ('CONTRACTSTATVALIDUNLI               ', 'CONTRACTSTATVALIDLI                 ', 'CONTRACTSTATSIGN                    ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'SalesprojectState' and KEYID in ('SALPROJSTATOPEN                     ', 'SALPROJSTATPOSTPONED                ')</where>
+    </update>
+    
+    <update tableName="AB_KEYWORD_ENTRY">
+      <column name="ISESSENTIAL" valueNumeric="1" />
+      <where>CONTAINER = 'TaskStatus' and KEYID in ('NEW                                 ', 'ASSIGNED                            ', 'IN-PROGRESS                         ', 'WAITING                             ', 'ENDED                               ', 'CUSTOMER-CHECKS                     ', 'UNASSIGNED                          ')</where>
+    </update>
+    
+    
   </changeSet>
 </databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/PRODUCT.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/PRODUCT.xml
index d17b83d957a2a8e6454bde2c62835aef181192d5..e8fb8fcc3a97e72d1261a1ea4b1b341043550ef1 100644
--- a/.liquibase/Data_alias/basic/_demoData/generatedData/PRODUCT.xml
+++ b/.liquibase/Data_alias/basic/_demoData/generatedData/PRODUCT.xml
@@ -75,7 +75,6 @@
       <column name="DATE_EDIT" valueDate="2019-05-21T09:00:55"/>
       <column name="DATE_NEW" valueDate="2019-05-16T01:43:25"/>
       <column name="GROUPCODEID" value="PRODUCTGROUP1"/>
-      <column name="INFO" value="Standard Stahlträger mit den Maßen 5m x 0,3m x 0,3m."/>
       <column name="MINSTOCK" valueNumeric="10"/>
       <column name="PRODUCTCODE" value="WG0001"/>
       <column name="PRODUCTID" value="8cdbd2d8-70e2-4899-9ac6-3f0c3e28cab1"/>
@@ -85,12 +84,18 @@
       <column name="USER_EDIT" value="Admin"/>
       <column name="USER_NEW" value="Admin"/>
     </insert>
+    <insert tableName="DESCRIPTIONTRANSLATION">
+        <column name="DESCRIPTIONTRANSLATIONID" value="70108db9-2c27-438d-9dff-d01c8b54c8c7"/>
+        <column name="OBJECT_TYPE" value="Product"/>
+        <column name="OBJECT_ROWID" value="8cdbd2d8-70e2-4899-9ac6-3f0c3e28cab1"/>
+        <column name="LANG" value="deu"/>
+        <column name="DESCRIPTION" value="Standard Stahlträger mit den Maßen 5m x 0,3m x 0,3m."/>
+    </insert>
     <insert tableName="PRODUCT">
       <column name="ADVERTISING" value="N"/>
       <column name="DATE_EDIT" valueDate="2019-05-21T09:00:55"/>
       <column name="DATE_NEW" valueDate="2019-05-16T01:48:31"/>
       <column name="GROUPCODEID" value="PRODUCTGROUP2"/>
-      <column name="INFO" value="4 Zonen Klimaanlage für Mittelklasse Wagen"/>
       <column name="PRODUCTCODE" value="WG2002"/>
       <column name="PRODUCTID" value="535cec1a-e81c-4833-aad6-1d2348dbc0fb"/>
       <column name="PRODUCTNAME" value="WG2 Produkt 1"/>
@@ -99,12 +104,18 @@
       <column name="USER_EDIT" value="Admin"/>
       <column name="USER_NEW" value="Admin"/>
     </insert>
+    <insert tableName="DESCRIPTIONTRANSLATION">
+        <column name="DESCRIPTIONTRANSLATIONID" value="91f7d8e8-136c-46de-8d01-ba231ebb49e3"/>
+        <column name="OBJECT_TYPE" value="Product"/>
+        <column name="OBJECT_ROWID" value="535cec1a-e81c-4833-aad6-1d2348dbc0fb"/>
+        <column name="LANG" value="deu"/>
+        <column name="DESCRIPTION" value="4 Zonen Klimaanlage für Mittelklasse Wagen"/>
+    </insert>
     <insert tableName="PRODUCT">
       <column name="ADVERTISING" value="N"/>
       <column name="DATE_EDIT" valueDate="2019-05-21T09:00:55"/>
       <column name="DATE_NEW" valueDate="2019-05-16T01:49:51"/>
       <column name="GROUPCODEID" value="PRODUCTGROUP2"/>
-      <column name="INFO" value="2 Zonen Klimaanlage für Klein- und Kompaktwagen"/>
       <column name="PRODUCTCODE" value="WG2003"/>
       <column name="PRODUCTID" value="80b77bce-5299-4c1d-bf41-5eca0add2f50"/>
       <column name="PRODUCTNAME" value="WG2 Produkt 2"/>
@@ -113,6 +124,13 @@
       <column name="USER_EDIT" value="Admin"/>
       <column name="USER_NEW" value="Admin"/>
     </insert>
+    <insert tableName="DESCRIPTIONTRANSLATION">
+        <column name="DESCRIPTIONTRANSLATIONID" value="020ca255-eae8-4771-a4a3-e62d6702f9f0"/>
+        <column name="OBJECT_TYPE" value="Product"/>
+        <column name="OBJECT_ROWID" value="80b77bce-5299-4c1d-bf41-5eca0add2f50"/>
+        <column name="LANG" value="deu"/>
+        <column name="DESCRIPTION" value="2 Zonen Klimaanlage für Klein- und Kompaktwagen"/>
+    </insert>
     <insert tableName="PRODUCT">
       <column name="ADVERTISING" value="N"/>
       <column name="DATE_EDIT" valueDate="2019-05-21T09:00:55"/>
diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod
index 8093a67a652bbefb83dadb1fdccae44b963b96be..3fdcab6a247ac61a7b15b94cba3b782b5df395a7 100644
--- a/aliasDefinition/Data_alias/Data_alias.aod
+++ b/aliasDefinition/Data_alias/Data_alias.aod
@@ -1779,48 +1779,6 @@
                   </customStringProperty>
                 </customProperties>
               </entityFieldDb>
-              <entityFieldDb>
-                <name>INFO</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="2005" />
-                <size v="2147483647" />
-                <scale v="0" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title>Description</title>
-                <description></description>
-                <customProperties>
-                  <customBooleanProperty>
-                    <name>log</name>
-                    <global v="false" />
-                    <property v="true" />
-                  </customBooleanProperty>
-                </customProperties>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>LANGUAGE</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="1" />
-                <size v="3" />
-                <scale v="0" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title>Language</title>
-                <description></description>
-                <customProperties>
-                  <customBooleanProperty>
-                    <name>log</name>
-                    <global v="false" />
-                    <property v="true" />
-                  </customBooleanProperty>
-                </customProperties>
-              </entityFieldDb>
               <entityFieldDb>
                 <name>DATE_EDIT</name>
                 <dbName></dbName>
@@ -10201,6 +10159,96 @@
               </entityFieldDb>
             </entityFields>
           </entityDb>
+          <entityDb>
+            <name>DESCRIPTIONTRANSLATION</name>
+            <dbName></dbName>
+            <idColumn>DESCRIPTIONTRANSLATIONID</idColumn>
+            <idGeneratorType v="0" />
+            <idGeneratorInterval v="1" />
+            <documentation></documentation>
+            <title></title>
+            <description></description>
+            <auditSyncConfig>
+              <name>auditSyncConfig</name>
+              <auditMode v="0" />
+              <syncActive v="false" />
+              <syncComplete v="true" />
+              <syncDirection v="1" />
+              <syncIds></syncIds>
+            </auditSyncConfig>
+            <entityFields>
+              <entityFieldDb>
+                <name>OBJECT_ROWID</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="true" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>DESCRIPTIONTRANSLATIONID</name>
+                <dbName></dbName>
+                <primaryKey v="true" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="true" />
+                <isUnique v="true" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>DESCRIPTION</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="2005" />
+                <size v="2147483647" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>OBJECT_TYPE</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="50" />
+                <scale v="0" />
+                <notNull v="true" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>LANG</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+            </entityFields>
+          </entityDb>
           <entityDb>
             <name>AB_UNLINKEDMAIL</name>
             <dbName></dbName>
diff --git a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
index be1269caa3bd1a42cd7860df6e215423b4e6f2a3..2fdf03fd0321dda9c77c68d1f9d859653b670de1 100644
--- a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
+++ b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
@@ -108,6 +108,10 @@
                 <kind v="10077" />
                 <title></title>
               </entityNode>
+              <entityNode>
+                <name>DocumentTemplate</name>
+                <kind v="10077" />
+              </entityNode>
               <entityNode>
                 <name>INTERNAL_ADMINISTRATOR</name>
                 <kind v="159" />
@@ -152,40 +156,56 @@
             <title></title>
             <childNodes>
               <entityNode>
-                <name>Notification</name>
+                <name>Attribute</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>Attribute</name>
+                <name>KeywordEntry</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>DocumentTemplate</name>
+                <name>KeywordAttribute</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>Employee</name>
+                <name>ObjectRelationType</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>KeywordEntry</name>
+                <name>ClassificationAdmin</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>KeywordAttribute</name>
+                <name>Salutation</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>ObjectRelationType</name>
-                <kind v="10077" />
+                <name>INTERNAL_ADMINISTRATOR</name>
+                <kind v="159" />
               </entityNode>
+            </childNodes>
+          </entityNode>
+        </childNodes>
+      </entityNode>
+      <entityNode>
+        <name>Group5</name>
+        <kind v="123" />
+        <title>User Administration</title>
+        <icon>VAADIN:UNLINK</icon>
+        <childNodes>
+          <entityNode>
+            <name>Group7</name>
+            <kind v="123" />
+            <title></title>
+            <childNodes>
               <entityNode>
-                <name>ClassificationAdmin</name>
+                <name>Employee</name>
                 <kind v="10077" />
               </entityNode>
               <entityNode>
-                <name>Salutation</name>
-                <kind v="10077" />
+                <name>INTERNAL_ADMINISTRATOR</name>
+                <kind v="159" />
+                <title></title>
               </entityNode>
               <entityNode>
                 <name>Role</name>
@@ -197,10 +217,6 @@
                 <kind v="10077" />
                 <title></title>
               </entityNode>
-              <entityNode>
-                <name>INTERNAL_ADMINISTRATOR</name>
-                <kind v="159" />
-              </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 2004dbd1cf970659a1d350fda68c4115067eec71..51c40eed05ba103ae4347347277aea4e2bad20a3 100644
--- a/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
+++ b/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js
@@ -1,4 +1,4 @@
 import("system.vars");
 import("system.result");
 
-result.object(["Offer", "Contract", "Campaign", "Order"]);
\ No newline at end of file
+result.object(["Offer", "Contract", "Campaign", "Order", "SupportTicket"]);
\ No newline at end of file
diff --git a/entity/Appointment_entity/Appointment_entity.aod b/entity/Appointment_entity/Appointment_entity.aod
index 7bd09fc91bc3500e041fc30bcfd3dc00216e7d1f..4805824fc40af93261d7cbe99faddf0b24ab99a0 100644
--- a/entity/Appointment_entity/Appointment_entity.aod
+++ b/entity/Appointment_entity/Appointment_entity.aod
@@ -213,6 +213,10 @@
         </entityDependency>
       </dependencies>
     </entityProvider>
+    <entityParameter>
+      <name>LinkedAppointmentsFromDashlet_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
diff --git a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
index 4e8aac3eba017eeb2368f7023a22deb0ea38c715..23649935d1dd90af87cbefa612a2733cafe75d63 100644
--- a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js
@@ -1,3 +1,4 @@
+import("system.tools");
 import("system.logging");
 import("system.db");
 import("Sql_lib");
@@ -10,31 +11,36 @@ import("system.util");
 import("system.neon");
 import("system.entities")
 
+
+var cond = SqlCondition.begin();
+
 if(vars.get("$local.idvalues") != null && vars.get("$local.idvalues") != "")
 {
     var selectedids = vars.get("$local.idvalues");
     result.object([buildEntry(calendars.getEntry(selectedids, null, null), null)]);
 }
 
+else if(vars.getString("$param.LinkedAppointmentsFromDashlet_param"))
+{
+    var contactid = tools.getCurrentUser()["params"]["contactID"];
+    
+    cond.andPrepareValue("AB_APPOINTMENTLINK.OBJECT_ROWID", contactid)
+    var idscond = db.translateCondition(cond.build("1 = 1"));
+   
+    var appointmentUids = db.table("select APPOINTMENT_ID from AB_APPOINTMENTLINK where " + idscond);
+    result.object(buildEntriesFromUids(appointmentUids));
+}
+
 /**
  * Will be triggert if a module needs AppointmentFilter_view
  */
 else if(vars.getString("$param.LinkedObjectId_param") != undefined)
 {
-    var cond = SqlCondition
-                        .begin()
-                        .andPrepareVars("AB_APPOINTMENTLINK.OBJECT_ROWID", "$param.LinkedObjectId_param")
+    cond.andPrepareVars("AB_APPOINTMENTLINK.OBJECT_ROWID", "$param.LinkedObjectId_param")
     var idscond = db.translateCondition(cond.build("1 = 1"));
    
     var appointmentUids = db.table("select APPOINTMENT_ID from AB_APPOINTMENTLINK where " + idscond);
-    
-    var entryArray = new Array(appointmentUids.length);
-    
-    for(var i = 0; i < appointmentUids.length; i++)
-    {
-        entryArray[i] = buildEntry(calendars.getEntry(appointmentUids[i], null, null), null);
-    }
-    result.object(entryArray);
+    result.object(buildEntriesFromUids(appointmentUids));
 }
 /**
  * Will be used, if the user is operating the calendar.
@@ -54,6 +60,16 @@ else if(vars.exists("$param.Entry_param") && vars.get("$param.Entry_param"))
     ]);
 }
 
+function buildEntriesFromUids(appointmentUids)
+{
+    var entryArray = new Array(appointmentUids.length);
+    
+    for(var i = 0; i < appointmentUids.length; i++)
+        entryArray[i] = buildEntry(calendars.getEntry(appointmentUids[i], null, null), null);
+    
+    return entryArray;
+}
+
 
 function buildEntry(pEntry, pMasterentry)
 {
diff --git a/entity/Attribute_entity/entityfields/icon/colorProcess.js b/entity/Attribute_entity/entityfields/icon/colorProcess.js
index 844e0e11d45ee7ff3480018549e36539979de949..b73702d761bbbd93f6aecd43c3ceaddea285a2d0 100644
--- a/entity/Attribute_entity/entityfields/icon/colorProcess.js
+++ b/entity/Attribute_entity/entityfields/icon/colorProcess.js
@@ -3,4 +3,4 @@ import("system.result");
 import("system.neon");
 
 if (vars.getString("$field.ATTRIBUTE_ACTIVE") != "1")
-    result.string(neon.PRIORITY_LOW_COLOR); //TODO: disabled color
+    result.string(neon.READONLY_COLOR);
diff --git a/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod b/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..4ce25bf1b78e723d677cfcdd0677f9a351f4f960
--- /dev/null
+++ b/entity/BulkMailAddRecipients_entity/BulkMailAddRecipients_entity.aod
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.9" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.9">
+  <name>BulkMailAddRecipients_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>UID</name>
+    </entityField>
+    <entityField>
+      <name>recipientCountMessage</name>
+    </entityField>
+    <entityField>
+      <name>BULKMAIL_ID</name>
+      <title>Bulk mail</title>
+      <consumer>BulkMails</consumer>
+      <linkedContext>BulkMail</linkedContext>
+    </entityField>
+    <entityConsumer>
+      <name>BulkMails</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>BulkMail_entity</entityName>
+        <fieldName>#PROVIDER</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityParameter>
+      <name>ContactIds_param</name>
+      <expose v="true" />
+    </entityParameter>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
+      <onInsert>%aditoprj%/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js</onInsert>
+      <recordFieldMappings>
+        <jDitoRecordFieldMapping>
+          <name>UID.value</name>
+        </jDitoRecordFieldMapping>
+      </recordFieldMappings>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js b/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..527bf07cc5f786bc9dbf18cd0747408362473f04
--- /dev/null
+++ b/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js
@@ -0,0 +1,31 @@
+import("KeywordRegistry_basic");
+import("system.util");
+import("system.db");
+import("Sql_lib");
+import("system.vars");
+
+
+//TODO: put this into a function and use only contacts without advertising ban
+var contactIds = JSON.parse(vars.getString("$param.ContactIds_param"));
+var bulkMailId = vars.get("$field.BULKMAIL_ID");
+
+var existsQuery = "not exists(select BULKMAILRECIPIENTID from BULKMAILRECIPIENT where BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID and # = ?)";
+var query = SqlCondition.begin()
+    .andIn("CONTACT.CONTACTID", contactIds)
+    .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", bulkMailId, existsQuery)
+    .buildSql("select CONTACTID from CONTACT");
+
+contactIds = db.array(db.COLUMN, query); //only add contacts that aren't already recipients
+
+var columns = [
+    "BULKMAILRECIPIENTID",
+    "BULKMAIL_ID",
+    "CONTACT_ID",
+    "STATUS"
+];
+var inserts = [];
+for (let i = 0, l = contactIds.length; i < l; i++)
+{
+    inserts.push(["BULKMAILRECIPIENT", columns, null, [util.getNewUUID(), bulkMailId, contactIds[i], $KeywordRegistry.bulkMailRecipientStatus$pending()]]);
+}
+db.inserts(inserts);
\ No newline at end of file
diff --git a/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod b/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod
index ea8b88f1fb7aa2ee350f5e64697677bc12792974..14ec8a459047d055534c8138b13812ec31da3a26 100644
--- a/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod
+++ b/entity/BulkMailRecipient_entity/BulkMailRecipient_entity.aod
@@ -19,6 +19,7 @@
       <consumer>Contacts</consumer>
       <linkedContextProcess>%aditoprj%/entity/BulkMailRecipient_entity/entityfields/contact_id/linkedContextProcess.js</linkedContextProcess>
       <mandatory v="true" />
+      <onValidation>%aditoprj%/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js</onValidation>
     </entityField>
     <entityField>
       <name>STATUS</name>
diff --git a/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js b/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f8c80384957e3e8e8eb5d034ad6d2e9871ecddc
--- /dev/null
+++ b/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js
@@ -0,0 +1,18 @@
+import("system.translate");
+import("system.result");
+import("system.datetime");
+import("KeywordRegistry_basic");
+import("Sql_lib");
+import("Entity_lib");
+import("Bulkmail_lib");
+import("system.db");
+
+var query = SqlCondition.begin()
+    .andPrepare("CONTACT.CONTACTID", ProcessHandlingUtils.getOnValidationValue())
+    .andSqlCondition(BulkMailUtils.getCommRestrictionCondition(true))
+    .buildSql("select count(*) = 0 from CONTACT", "1=2");
+
+var noMails = db.cell(query) != "true";
+
+if (noMails)
+    result.string(translate.text("The contact has an advertising ban for emails!"));
\ No newline at end of file
diff --git a/entity/BulkMailRecipient_entity/entityfields/status/valueProcess.js b/entity/BulkMailRecipient_entity/entityfields/status/valueProcess.js
index e506dbc464cb9b87a8b18c2a4f0bf4e1f3fad21a..4f0cac524313cb538a4b1d1b6104f07b2a222518 100644
--- a/entity/BulkMailRecipient_entity/entityfields/status/valueProcess.js
+++ b/entity/BulkMailRecipient_entity/entityfields/status/valueProcess.js
@@ -4,4 +4,4 @@ import("system.result");
 import("KeywordRegistry_basic");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-    result.string($KeywordRegistry.bulkMailSentStatus$pending());
\ No newline at end of file
+    result.string($KeywordRegistry.bulkMailRecipientStatus$pending());
\ No newline at end of file
diff --git a/entity/BulkMailRecipient_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js b/entity/BulkMailRecipient_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
index 80fc4d9e397480c63c23e050fe4e2e3a97cc56c7..92fb534f8ba741d4dacd9e69cfb9273085d8c684 100644
--- a/entity/BulkMailRecipient_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
+++ b/entity/BulkMailRecipient_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
@@ -2,5 +2,5 @@ import("system.result");
 import("Keyword_lib");
 import("KeywordRegistry_basic");
 
-var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.bulkMailSentStatus(), "BULKMAILRECIPIENT.STATUS");
+var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.bulkMailRecipientStatus(), "BULKMAILRECIPIENT.STATUS");
 result.string(sql);
diff --git a/entity/BulkMail_entity/BulkMail_entity.aod b/entity/BulkMail_entity/BulkMail_entity.aod
index 74ebbd65688fbe4493efc63f7f8033f59a190ba6..155528efdd22eeae5cab9feabc58605d01316dec 100644
--- a/entity/BulkMail_entity/BulkMail_entity.aod
+++ b/entity/BulkMail_entity/BulkMail_entity.aod
@@ -9,9 +9,18 @@
   <entityFields>
     <entityProvider>
       <name>#PROVIDER</name>
+      <dependencies>
+        <entityDependency>
+          <name>88f8ded7-fe8f-41ef-8e01-030bae0867ee</name>
+          <entityName>BulkMailAddRecipients_entity</entityName>
+          <fieldName>BulkMails</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
     </entityProvider>
     <entityField>
       <name>BULKMAILID</name>
+      <searchable v="false" />
     </entityField>
     <entityField>
       <name>NAME</name>
@@ -30,7 +39,8 @@
       <name>DOCUMENTTEMPLATE_ID</name>
       <title>Document Template</title>
       <consumer>Templates</consumer>
-      <mandatory v="true" />
+      <mandatory v="false" />
+      <onValueChange>%aditoprj%/entity/BulkMail_entity/entityfields/documenttemplate_id/onValueChange.js</onValueChange>
     </entityField>
     <entityConsumer>
       <name>Recipients</name>
@@ -66,6 +76,10 @@
     </entityConsumer>
     <entityField>
       <name>STATUS</name>
+      <title>Status</title>
+      <consumer>StatusKeyword</consumer>
+      <valueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/status/valueProcess.js</valueProcess>
+      <displayValueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/status/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityField>
       <name>SENDER</name>
@@ -77,24 +91,55 @@
       <title>Send</title>
       <onActionProcess>%aditoprj%/entity/BulkMail_entity/entityfields/sendmail/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:PAPERPLANE</iconId>
+      <stateProcess>%aditoprj%/entity/BulkMail_entity/entityfields/sendmail/stateProcess.js</stateProcess>
     </entityActionField>
     <entityField>
       <name>ICON</name>
       <contentType>IMAGE</contentType>
+      <searchable v="false" />
       <valueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/icon/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
-      <name>PREVIEW</name>
+      <name>preview</name>
       <contentType>HTML</contentType>
+      <searchable v="false" />
       <state>READONLY</state>
       <displayValueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/preview/displayValueProcess.js</displayValueProcess>
     </entityField>
+    <entityConsumer>
+      <name>StatusKeyword</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/statuskeyword/children/containername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>BINDATA</name>
+      <contentType>FILE</contentType>
+      <searchable v="false" />
+      <stateProcess>%aditoprj%/entity/BulkMail_entity/entityfields/bindata/stateProcess.js</stateProcess>
+    </entityField>
+    <entityFieldGroup>
+      <name>subjectPreview</name>
+      <valueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/subjectpreview/valueProcess.js</valueProcess>
+      <fields>
+        <element>SUBJECT</element>
+      </fields>
+    </entityFieldGroup>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
       <name>db</name>
       <alias>Data_alias</alias>
       <fromClauseProcess>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
+      <onDBDelete>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
         <linkInformation>
           <name>6444866d-42ee-4b7b-8536-6dc8f6437c45</name>
@@ -140,6 +185,14 @@
           <name>DOCUMENTTEMPLATE_ID.displayValue</name>
           <recordfield>DOCUMENTTEMPLATE.NAME</recordfield>
         </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.value</name>
+          <recordfield>BULKMAIL.STATUS</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.displayValue</name>
+          <expression>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
       </recordFieldMappings>
     </dbRecordContainer>
   </recordContainers>
diff --git a/entity/BulkMail_entity/entityfields/bindata/stateProcess.js b/entity/BulkMail_entity/entityfields/bindata/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6dfc93b8846e0309f402d154d1e550f10f9b3a0d
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/bindata/stateProcess.js
@@ -0,0 +1,8 @@
+import("system.vars");
+import("system.result");
+import("system.neon");
+
+var state = neon.COMPONENTSTATE_EDITABLE;
+if (vars.getString("$field.DOCUMENTTEMPLATE_ID") != "")
+    state = neon.COMPONENTSTATE_READONLY;
+result.string(state);
\ 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
new file mode 100644
index 0000000000000000000000000000000000000000..6d1fe433a0ad7b27289c152edd86ce47b2c096f7
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/documenttemplate_id/onValueChange.js
@@ -0,0 +1,17 @@
+import("system.vars");
+import("system.neon");
+import("system.util");
+import("system.mail");
+import("DocumentTemplate_lib");
+import("Entity_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+{
+    var templateId = ProcessHandlingUtils.getOnValidationValue();
+    var template = DocumentTemplate.loadTemplate(templateId);
+    if (template.type == DocumentTemplate.types.EML)
+    {
+        let subject = mail.parseRFC(util.decodeBase64String(template.content))[mail.MAIL_SUBJECT];
+        neon.setFieldValue("$field.SUBJECT", subject);
+    }
+}
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/icon/valueProcess.js b/entity/BulkMail_entity/entityfields/icon/valueProcess.js
index 020c60c60455d5fc6321066f0a947538b70b09d8..3d5da8ba5f5c8e4be29ccdcb3295de9fd2ecf8b8 100644
--- a/entity/BulkMail_entity/entityfields/icon/valueProcess.js
+++ b/entity/BulkMail_entity/entityfields/icon/valueProcess.js
@@ -4,8 +4,7 @@ import("system.neon");
 import("Keyword_lib");
 import("KeywordRegistry_basic");
 
-//var type = vars.getString("$field.ATTRIBUTE_TYPE");
-//var keywordAttributes = KeywordUtils.getAttributeRelationsByKey(type, $KeywordRegistry.attributeType())
-//var icon = keywordAttributes.defaultAvatarRepresentation;
+var type = vars.getString("$field.STATUS");
+var keywordAttributes = KeywordUtils.getAttributeRelationsByKey(type, $KeywordRegistry.bulkMailStatus())
 
-result.string("VAADIN:ENVELOPE_OPEN");
\ No newline at end of file
+result.string(keywordAttributes.bulkMailIcon);
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/sendmail/onActionProcess.js b/entity/BulkMail_entity/entityfields/sendmail/onActionProcess.js
index f0423ecfeccd78869dd626ca3bdf7bef4a4be782..84cc2e975ffd32302521043c2342a774b0a927cf 100644
--- a/entity/BulkMail_entity/entityfields/sendmail/onActionProcess.js
+++ b/entity/BulkMail_entity/entityfields/sendmail/onActionProcess.js
@@ -1,6 +1,11 @@
+import("Sql_lib");
 import("system.neon");
 import("system.vars");
 import("Bulkmail_lib");
+import("system.db");
+import("KeywordRegistry_basic");
 
-BulkMailUtils.sendBulkMail(vars.get("$field.BULKMAILID"));
-neon.refreshAll(); //to refresh the status in the recipient table
\ No newline at end of file
+db.updateData("BULKMAIL", ["STATUS"], null, [$KeywordRegistry.bulkMailStatus$beingSent()], 
+    SqlCondition.equals("BULKMAIL.BULKMAILID", vars.get("$field.BULKMAILID"), "1=2"));
+neon.refreshAll();
+BulkMailUtils.sendBulkMailOnServer(vars.get("$field.BULKMAILID"));
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/sendmail/stateProcess.js b/entity/BulkMail_entity/entityfields/sendmail/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..8fb06b7a1c02b912611222575069463cec2c368e
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/sendmail/stateProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("KeywordRegistry_basic");
+import("system.vars");
+import("system.neon");
+
+var state = neon.COMPONENTSTATE_EDITABLE;
+if (vars.get("$field.STATUS") == $KeywordRegistry.bulkMailStatus$beingSent())
+    state = neon.COMPONENTSTATE_DISABLED;
+result.string(state);
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/status/displayValueProcess.js b/entity/BulkMail_entity/entityfields/status/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..0dd6bd59e0bb7db1bba471167d20ae5a41cb8423
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/status/displayValueProcess.js
@@ -0,0 +1,6 @@
+import("system.vars");
+import("KeywordRegistry_basic");
+import("system.result");
+import("Keyword_lib");
+
+result.string(KeywordUtils.getViewValue($KeywordRegistry.bulkMailStatus(), vars.get("$this.value")));
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/status/valueProcess.js b/entity/BulkMail_entity/entityfields/status/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..2c4fb811282cee3c1fc37c168d8f70f528497570
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/status/valueProcess.js
@@ -0,0 +1,7 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("KeywordRegistry_basic");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+    result.string($KeywordRegistry.bulkMailStatus$notSent());
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/statuskeyword/children/containername_param/valueProcess.js b/entity/BulkMail_entity/entityfields/statuskeyword/children/containername_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4a018c9980ab872dd7b397a32f74e96875738525
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/statuskeyword/children/containername_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("KeywordRegistry_basic");
+import("system.result");
+
+result.string($KeywordRegistry.bulkMailStatus());
\ No newline at end of file
diff --git a/entity/BulkMail_entity/entityfields/subjectpreview/valueProcess.js b/entity/BulkMail_entity/entityfields/subjectpreview/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6db9b03be72afa3472c7ea1c868f7b2b0005d3a2
--- /dev/null
+++ b/entity/BulkMail_entity/entityfields/subjectpreview/valueProcess.js
@@ -0,0 +1,9 @@
+import("Employee_lib");
+import("system.vars");
+import("system.result");
+import("DocumentTemplate_lib");
+
+var template = new DocumentTemplate(vars.get("$field.SUBJECT"), DocumentTemplate.types.PLAIN);
+var subject = template.getReplacedContentByContactId(EmployeeUtils.getCurrentContactId());
+
+result.string(subject);
\ No newline at end of file
diff --git a/entity/BulkMail_entity/recordcontainers/db/onDBDelete.js b/entity/BulkMail_entity/recordcontainers/db/onDBDelete.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ff74f9c6b2f007c25a9ec2b6e6364c075896980
--- /dev/null
+++ b/entity/BulkMail_entity/recordcontainers/db/onDBDelete.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("Sql_lib");
+import("system.db");
+
+db.deleteData("BULKMAILRECIPIENT", SqlCondition.equals("BULKMAILRECIPIENT.BULKMAIL_ID", vars.get("$local.uid"), "1=2"));
\ No newline at end of file
diff --git a/entity/BulkMail_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js b/entity/BulkMail_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c0e56dba1c4f80d2feac92dcac3937ea6010123
--- /dev/null
+++ b/entity/BulkMail_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.bulkMailStatus(), "BULKMAIL.STATUS");
+result.string(sql);
diff --git a/entity/DescriptionTranslation_entity/DescriptionTranslation_entity.aod b/entity/DescriptionTranslation_entity/DescriptionTranslation_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..d34d158451225500cc054f5b91f2f3b8caafe41b
--- /dev/null
+++ b/entity/DescriptionTranslation_entity/DescriptionTranslation_entity.aod
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.9" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.9">
+  <name>DescriptionTranslation_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <title>Description</title>
+  <titlePlural>Descriptions</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>DESCRIPTIONTRANSLATIONID</name>
+    </entityField>
+    <entityField>
+      <name>OBJECT_TYPE</name>
+      <title>Type</title>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/DescriptionTranslation_entity/entityfields/object_type/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>OBJECT_ROWID</name>
+      <title>Object</title>
+      <mandatory v="true" />
+      <valueProcess>%aditoprj%/entity/DescriptionTranslation_entity/entityfields/object_rowid/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>LANG</name>
+      <title>Language</title>
+      <consumer>Languages</consumer>
+      <mandatory v="true" />
+      <displayValueProcess>%aditoprj%/entity/DescriptionTranslation_entity/entityfields/lang/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityField>
+      <name>DESCRIPTION</name>
+      <title>Description</title>
+      <contentType>LONG_TEXT</contentType>
+      <mandatory v="true" />
+    </entityField>
+    <entityConsumer>
+      <name>Languages</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Language_entity</entityName>
+        <fieldName>ISO3NameFiltered</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ExcludedIds_param</name>
+          <valueProcess>%aditoprj%/entity/DescriptionTranslation_entity/entityfields/languages/children/excludedids_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityParameter>
+      <name>ObjectType_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+    </entityParameter>
+    <entityParameter>
+      <name>ObjectRowid_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+    </entityParameter>
+    <entityProvider>
+      <name>DescriptionTranslations</name>
+      <dependencies>
+        <entityDependency>
+          <name>72298519-6028-4d4b-9ef6-3227fb065bb8</name>
+          <entityName>Product_entity</entityName>
+          <fieldName>DescriptionTranslations</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <conditionProcess>%aditoprj%/entity/DescriptionTranslation_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <linkInformation>
+        <linkInformation>
+          <name>b12c4b68-b868-45fe-9f72-aa914a19382a</name>
+          <tableName>DESCRIPTIONTRANSLATION</tableName>
+          <primaryKey>DESCRIPTIONTRANSLATIONID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>DESCRIPTION.value</name>
+          <recordfield>DESCRIPTIONTRANSLATION.DESCRIPTION</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DESCRIPTIONTRANSLATIONID.value</name>
+          <recordfield>DESCRIPTIONTRANSLATION.DESCRIPTIONTRANSLATIONID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECT_ROWID.value</name>
+          <recordfield>DESCRIPTIONTRANSLATION.OBJECT_ROWID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECT_TYPE.value</name>
+          <recordfield>DESCRIPTIONTRANSLATION.OBJECT_TYPE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>LANG.value</name>
+          <recordfield>DESCRIPTIONTRANSLATION.LANG</recordfield>
+          <expression>%aditoprj%/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.value/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>LANG.displayValue</name>
+          <expression>%aditoprj%/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/Product_entity/entityfields/language/displayValueProcess.js b/entity/DescriptionTranslation_entity/entityfields/lang/displayValueProcess.js
similarity index 79%
rename from entity/Product_entity/entityfields/language/displayValueProcess.js
rename to entity/DescriptionTranslation_entity/entityfields/lang/displayValueProcess.js
index de5246774faf8a3f68bea969823cf3fe462d1504..ac0f29fc259baae6d6042a83e588737d6c76fd31 100644
--- a/entity/Product_entity/entityfields/language/displayValueProcess.js
+++ b/entity/DescriptionTranslation_entity/entityfields/lang/displayValueProcess.js
@@ -6,5 +6,5 @@ import("KeywordRegistry_basic");
 import("Keyword_lib");
 import("Sql_lib");
 
-result.string(translate.text(db.cell(SqlCondition.begin().andPrepareVars("AB_LANGUAGE.ISO3", "$field.LANGUAGE")
-                                   .buildSql("select NAME_LATIN from AB_LANGUAGE", "1=2"))));
+result.string(translate.text(db.cell(SqlCondition.begin().andPrepareVars("AB_LANGUAGE.ISO3", "$this.value")
+                                   .buildSql("select NAME_LATIN from AB_LANGUAGE", "1=2"))));
\ No newline at end of file
diff --git a/entity/DescriptionTranslation_entity/entityfields/languages/children/excludedids_param/valueProcess.js b/entity/DescriptionTranslation_entity/entityfields/languages/children/excludedids_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..15bf867229fbf60954c4f5da8528c73dfd8ba5da
--- /dev/null
+++ b/entity/DescriptionTranslation_entity/entityfields/languages/children/excludedids_param/valueProcess.js
@@ -0,0 +1,9 @@
+import("Sql_lib");
+import("system.db");
+import("system.result");
+import("system.neon");
+
+result.object(db.array(db.COLUMN, SqlCondition.begin()
+                                              .andPrepareVars("DESCRIPTIONTRANSLATION.OBJECT_TYPE", "$param.ObjectType_param")
+                                              .andPrepareVars("DESCRIPTIONTRANSLATION.OBJECT_ROWID", "$param.ObjectRowid_param")
+                                              .buildSql("select LANG from DESCRIPTIONTRANSLATION", "1=2")));
\ No newline at end of file
diff --git a/entity/DescriptionTranslation_entity/entityfields/object_rowid/valueProcess.js b/entity/DescriptionTranslation_entity/entityfields/object_rowid/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..753abe3b0853ce610cfe25e8b2632e84fa865617
--- /dev/null
+++ b/entity/DescriptionTranslation_entity/entityfields/object_rowid/valueProcess.js
@@ -0,0 +1,8 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) 
+{
+    result.string(vars.get("$param.ObjectRowid_param"));
+}
\ No newline at end of file
diff --git a/entity/DescriptionTranslation_entity/entityfields/object_type/valueProcess.js b/entity/DescriptionTranslation_entity/entityfields/object_type/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..55877cba6b885eb12a5f2be9928a7cd5acaa287d
--- /dev/null
+++ b/entity/DescriptionTranslation_entity/entityfields/object_type/valueProcess.js
@@ -0,0 +1,8 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) 
+{
+    result.string(vars.get("$param.ObjectType_param"));
+}
\ No newline at end of file
diff --git a/entity/DescriptionTranslation_entity/recordcontainers/db/conditionProcess.js b/entity/DescriptionTranslation_entity/recordcontainers/db/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..59b16d3684e1267b5ac40e6cb6bc9e926ffca60c
--- /dev/null
+++ b/entity/DescriptionTranslation_entity/recordcontainers/db/conditionProcess.js
@@ -0,0 +1,9 @@
+import("system.db");
+import("system.result");
+import("Sql_lib");
+
+var cond = SqlCondition.begin()
+                       .andPrepareVars("DESCRIPTIONTRANSLATION.OBJECT_TYPE", "$param.ObjectType_param")
+                       .andPrepareVars("DESCRIPTIONTRANSLATION.OBJECT_ROWID", "$param.ObjectRowid_param");
+                       
+result.string(db.translateCondition(cond.build("1 = 2")))
\ No newline at end of file
diff --git a/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.displayvalue/expression.js b/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..c0156ae28d7ef04c0c79d5678f96cf52ed668f83
--- /dev/null
+++ b/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.displayvalue/expression.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Keyword_lib");
+
+var sql = LanguageKeywordUtils.getResolvedTitleSqlPart("DESCRIPTIONTRANSLATION.LANG");
+result.string(sql);
\ No newline at end of file
diff --git a/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.value/expression.js b/entity/DescriptionTranslation_entity/recordcontainers/db/recordfieldmappings/lang.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/entity/Email_entity/recordcontainers/jdito/onInsert.js b/entity/Email_entity/recordcontainers/jdito/onInsert.js
index a4a6db2b00da0ebb8ffa004876a78a4a6edc75ca..6cacfadc459568989baeae6ce715af0c7dc2104a 100644
--- a/entity/Email_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/Email_entity/recordcontainers/jdito/onInsert.js
@@ -4,11 +4,12 @@ import("Employee_lib");
 import("system.vars");
 import("Email_lib");
 
+var contactId = vars.get("$param.ContactId_param");
 EmailUtils.openMailTemplate(
     vars.get("$field.RECIPIENT"), 
     EmployeeUtils.getCurrentContactId(), 
     vars.get("$field.DOCUMENT_TEMPLATE"), 
-    vars.get("$param.ContactId_param")
+    contactId
 );
 
 var links = [];
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index ae3f89af92614f9f30f1e4984f2bb6fb58b32cd9..736ab304a19bfcb34a9fee5bfa9002667779982a 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -435,6 +435,12 @@
           <fieldName>KeywordTaskPriority</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>d8c587cc-47db-4e08-a6ac-92ec1d91acb5</name>
+          <entityName>BulkMail_entity</entityName>
+          <fieldName>StatusKeyword</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
       <children>
         <entityParameter>
diff --git a/entity/Language_entity/Language_entity.aod b/entity/Language_entity/Language_entity.aod
index 89843a7e0ba6731d6a87a98ae3ec8a13691cc0ce..113932dd5ccb725f589389436ad196fc102f05e4 100644
--- a/entity/Language_entity/Language_entity.aod
+++ b/entity/Language_entity/Language_entity.aod
@@ -55,12 +55,6 @@
           <fieldName>Languages</fieldName>
           <isConsumer v="false" />
         </entityDependency>
-        <entityDependency>
-          <name>0b2dd6bf-933f-4476-9071-de9d5e23800b</name>
-          <entityName>Product_entity</entityName>
-          <fieldName>Languages</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
         <entityDependency>
           <name>030ac1ae-5f5b-4815-b9f4-1121b7c881ad</name>
           <entityName>Contact_entity</entityName>
@@ -74,12 +68,40 @@
           <isConsumer v="false" />
         </entityDependency>
       </dependencies>
+      <children>
+        <entityParameter>
+          <name>ExcludedIds_param</name>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityProvider>
+      <name>ISO3NameFiltered</name>
+      <dependencies>
+        <entityDependency>
+          <name>2df9d0ed-c26b-4166-9667-786a55146e05</name>
+          <entityName>DescriptionTranslation_entity</entityName>
+          <fieldName>Languages</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>ExcludedIds_param</name>
+          <expose v="true" />
+        </entityParameter>
+      </children>
     </entityProvider>
+    <entityParameter>
+      <name>ExcludedIds_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
       <name>db</name>
       <alias>Data_alias</alias>
+      <conditionProcess>%aditoprj%/entity/Language_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
       <linkInformation>
         <linkInformation>
           <name>3cd06d7c-16c3-49e5-87cd-672a7222e613</name>
diff --git a/entity/Language_entity/recordcontainers/db/conditionProcess.js b/entity/Language_entity/recordcontainers/db/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..f35be6d3c9a951a3ecd210484e522606a660dfa1
--- /dev/null
+++ b/entity/Language_entity/recordcontainers/db/conditionProcess.js
@@ -0,0 +1,12 @@
+import("system.vars");
+import("system.db");
+import("system.result");
+import("Sql_lib");
+var cond = SqlCondition.begin();
+
+if (vars.exists("$param.ExcludedIds_param") && vars.getString("$param.ExcludedIds_param"))
+{
+    cond.andIn("AB_LANGUAGE.ISO3", JSON.parse(vars.getString("$param.ExcludedIds_param")), undefined, true)
+}
+
+result.string(db.translateCondition(cond.build("1 = 1")))
\ No newline at end of file
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index 8a4ea740f6357914c4bd084a6a523b202cf91599..b2b01a601000b98bc1c27e076892ab4c52b2bf1a 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -5,6 +5,7 @@
   <documentation>%aditoprj%/entity/Offer_entity/documentation.adoc</documentation>
   <title>Offer</title>
   <grantUpdateProcess>%aditoprj%/entity/Offer_entity/grantUpdateProcess.js</grantUpdateProcess>
+  <grantDeleteProcess>%aditoprj%/entity/Offer_entity/grantDeleteProcess.js</grantDeleteProcess>
   <contentTitleProcess>%aditoprj%/entity/Offer_entity/contentTitleProcess.js</contentTitleProcess>
   <afterUiInit>%aditoprj%/entity/Offer_entity/afterUiInit.js</afterUiInit>
   <iconId>VAADIN:CART</iconId>
@@ -120,6 +121,10 @@
           <expose v="true" />
           <mandatory v="true" />
         </entityParameter>
+        <entityParameter>
+          <name>Language_param</name>
+          <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/offeritems/children/language_param/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
     </entityConsumer>
     <entityActionField>
@@ -151,6 +156,7 @@
       <title>Language</title>
       <consumer>Languages</consumer>
       <mandatory v="true" />
+      <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/language/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/Offer_entity/entityfields/language/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Offer_entity/entityfields/language/displayValueProcess.js</displayValueProcess>
     </entityField>
diff --git a/entity/Offer_entity/entityfields/currency/valueProcess.js b/entity/Offer_entity/entityfields/currency/valueProcess.js
index 787ece941a73bd5747239c362d3f0bb9fcc0e439..2f2451289c947c75e2bba4dcdb3f224de3c01881 100644
--- a/entity/Offer_entity/entityfields/currency/valueProcess.js
+++ b/entity/Offer_entity/entityfields/currency/valueProcess.js
@@ -1,6 +1,7 @@
 import("system.neon");
 import("system.result");
 import("system.vars");
+import("KeywordRegistry_basic");
 
 if (vars.exists("$param.OfferCurrency_param") && vars.get("$param.OfferCurrency_param")) 
 {
@@ -8,5 +9,5 @@ if (vars.exists("$param.OfferCurrency_param") && vars.get("$param.OfferCurrency_
 }
 else if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value"))
 {
-    result.string("EUR");
+    result.string($KeywordRegistry.currency$eur());
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/deliveryterms/valueProcess.js b/entity/Offer_entity/entityfields/deliveryterms/valueProcess.js
index 0ae20dad6e06f3bda90fdbff5e7b83a63e5ca241..4463e8d84dc0de8bd1c3fb297d48119201e7a764 100644
--- a/entity/Offer_entity/entityfields/deliveryterms/valueProcess.js
+++ b/entity/Offer_entity/entityfields/deliveryterms/valueProcess.js
@@ -3,6 +3,7 @@ import("system.neon");
 import("system.result");
 import("system.vars");
 import("Attribute_lib");
+import("Contact_lib");
 
 if (vars.exists("$param.OfferDeliveryTerm_param") && vars.get("$param.OfferDeliveryTerm_param")) 
 {
@@ -10,9 +11,13 @@ if (vars.exists("$param.OfferDeliveryTerm_param") && vars.get("$param.OfferDeliv
 } 
 else if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
 {
-    var contactId = vars.getString("$field.CONTACT_ID");
-    if (contactId)
-    { 
-        result.string(AttributeRelationUtils.getAttribute($AttributeRegistry.deliveryTerm(), contactId));
+    var contactIds = ContactUtils.getPersOrgIds(vars.getString("$field.CONTACT_ID"))
+    if (contactIds.length >= 3 && contactIds[2])
+    {
+        var orgContactId = ContactUtils.getOrgContactId(contactIds[2]);
+        if (orgContactId)
+        { 
+            result.string(AttributeRelationUtils.getAttribute($AttributeRegistry.deliveryTerm(), orgContactId));
+        }
     }
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/language/stateProcess.js b/entity/Offer_entity/entityfields/language/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..05ceada3a320c2eed56dab6341368a831ee73b1e
--- /dev/null
+++ b/entity/Offer_entity/entityfields/language/stateProcess.js
@@ -0,0 +1,12 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+{
+    result.string(neon.COMPONENTSTATE_EDITABLE);
+}
+else
+{
+    result.string(neon.COMPONENTSTATE_READONLY);
+}
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/objects/children/contactid_param/valueProcess.js b/entity/Offer_entity/entityfields/objects/children/contactid_param/valueProcess.js
index 22a6e045a3a3c037f3081a29d3d34810375564f9..7b92c1bb14aa08001b7d5738111337ab7e81f4cc 100644
--- a/entity/Offer_entity/entityfields/objects/children/contactid_param/valueProcess.js
+++ b/entity/Offer_entity/entityfields/objects/children/contactid_param/valueProcess.js
@@ -1,10 +1,10 @@
-import("system.result");
-import("system.vars");
-import("Contact_lib");
-
-if (vars.get("$field.CONTACT_ID"))
-{
-    var ids = ContactUtils.getPersOrgIds(vars.getString("$field.CONTACT_ID"));
-    if (ids.length >= 3 && ids[2])
-        result.string(ContactUtils.getPersOrgIds(vars.getString("$field.CONTACT_ID"))[2]);
+import("system.result");
+import("system.vars");
+import("Contact_lib");
+
+if (vars.get("$field.CONTACT_ID"))
+{
+    var ids = ContactUtils.getPersOrgIds(vars.getString("$field.CONTACT_ID"));
+    if (ids.length >= 3 && ids[2])
+        result.string(ids[2]);
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/offeritems/children/language_param/valueProcess.js b/entity/Offer_entity/entityfields/offeritems/children/language_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..33d4d6d238c6273767dcb38ba121c6edd66acbea
--- /dev/null
+++ b/entity/Offer_entity/entityfields/offeritems/children/language_param/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.logging");
+import("system.vars");
+import("system.result");
+logging.log("offer " + vars.get("$field.LANGUAGE"))
+result.string(vars.get("$field.LANGUAGE"));
diff --git a/entity/Offer_entity/entityfields/paymentterms/valueProcess.js b/entity/Offer_entity/entityfields/paymentterms/valueProcess.js
index e75c10c9751ea47fa79c80841cfc2831dafb2deb..020e52b587cd8ab247a95db399a99b50e9755925 100644
--- a/entity/Offer_entity/entityfields/paymentterms/valueProcess.js
+++ b/entity/Offer_entity/entityfields/paymentterms/valueProcess.js
@@ -1,3 +1,4 @@
+import("Contact_lib");
 import("AttributeRegistry_basic");
 import("system.neon");
 import("system.result");
@@ -10,9 +11,13 @@ if (vars.exists("$param.OfferPaymentTerm_param") && vars.get("$param.OfferPaymen
 }
 else if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
 {
-    var contactId = vars.getString("$field.CONTACT_ID");
-    if (contactId)
+    var contactIds = ContactUtils.getPersOrgIds(vars.getString("$field.CONTACT_ID"))
+    if (contactIds.length >= 3 && contactIds[2])
     {
-        result.string(AttributeRelationUtils.getAttribute($AttributeRegistry.paymentTerm(), contactId));
+        var orgContactId = ContactUtils.getOrgContactId(contactIds[2]);
+        if (orgContactId)
+        { 
+            result.string(AttributeRelationUtils.getAttribute($AttributeRegistry.paymentTerm(), orgContactId));
+        }
     }
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/status/valueProcess.js b/entity/Offer_entity/entityfields/status/valueProcess.js
index ef4ec27fb0c16db8e3b6a59b3723da26f78f54e8..57f4b66b2e7ca5cd616c944b52d0fece864f8fa4 100644
--- a/entity/Offer_entity/entityfields/status/valueProcess.js
+++ b/entity/Offer_entity/entityfields/status/valueProcess.js
@@ -1,6 +1,7 @@
 import("system.neon");
 import("system.vars");
 import("system.result");
+import("KeywordRegistry_basic");
 
 if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value"))
-    result.string("70d27a1b-7233-481d-826f-01a13a4bb0b2"); //Open
\ No newline at end of file
+    result.string($KeywordRegistry.offerStatus$open()); //Open
\ No newline at end of file
diff --git a/entity/Offer_entity/grantDeleteProcess.js b/entity/Offer_entity/grantDeleteProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..f95c719463a913f0dfef05cfee0712e084c530ce
--- /dev/null
+++ b/entity/Offer_entity/grantDeleteProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+import("Offer_lib");
+
+result.string(OfferUtils.isDeletable(vars.get("$field.STATUS")));
\ No newline at end of file
diff --git a/entity/Offeritem_entity/Offeritem_entity.aod b/entity/Offeritem_entity/Offeritem_entity.aod
index d18aaea766801725e30d896e611a47c9003a8102..64025c21478525550458e16697419503ff46a8e6 100644
--- a/entity/Offeritem_entity/Offeritem_entity.aod
+++ b/entity/Offeritem_entity/Offeritem_entity.aod
@@ -75,6 +75,7 @@
       <consumer>Products</consumer>
       <linkedContext>Product</linkedContext>
       <mandatory v="true" />
+      <state>READONLY</state>
       <displayValueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/product_id/displayValueProcess.js</displayValueProcess>
       <onValueChange>%aditoprj%/entity/Offeritem_entity/entityfields/product_id/onValueChange.js</onValueChange>
       <onValueChangeTypes>
@@ -181,6 +182,11 @@
           <name>OfferStatus_param</name>
           <expose v="true" />
         </entityParameter>
+        <entityParameter>
+          <name>Language_param</name>
+          <title></title>
+          <expose v="true" />
+        </entityParameter>
       </children>
     </entityProvider>
     <entityField>
@@ -188,7 +194,7 @@
       <documentation>%aditoprj%/entity/Offeritem_entity/entityfields/info/documentation.adoc</documentation>
       <title>Description</title>
       <contentType>LONG_TEXT</contentType>
-      <state>READONLY</state>
+      <state>AUTO</state>
     </entityField>
     <entityConsumer>
       <name>KeywordProductGroupcodes</name>
@@ -228,6 +234,10 @@
         <fieldName>#PROVIDER</fieldName>
       </dependency>
     </entityConsumer>
+    <entityParameter>
+      <name>Language_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Offeritem_entity/entityfields/product_id/onValueChange.js b/entity/Offeritem_entity/entityfields/product_id/onValueChange.js
index 85a18b53383611f0bc12ede10ebecb332041aa6e..b3cc01ab49bbd4ddc910037d3319e4ebb11ce25b 100644
--- a/entity/Offeritem_entity/entityfields/product_id/onValueChange.js
+++ b/entity/Offeritem_entity/entityfields/product_id/onValueChange.js
@@ -1,3 +1,5 @@
+import("system.db");
+import("Sql_lib");
 import("AttributeRegistry_basic");
 import("system.vars");
 import("system.neon");
@@ -16,14 +18,20 @@ if(pid != "")
     var PriceListFilter = { currency: currency, quantity: vars.get("$field.QUANTITY"), relationId: contactid, priceList: pricelist };
     
     //TODO: loading from db until loading from Consumer is possible.
-    var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter, ["INFO"]);
+    var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter, 
+            [["info", db.translateStatement(SqlCondition.begin()
+                                  .andPrepareVars("DESCRIPTIONTRANSLATION.OBJECT_ROWID", "$field.PRODUCT_ID")
+                                  .and("DESCRIPTIONTRANSLATION.OBJECT_TYPE = 'Product'")
+                                  .andPrepareVars("DESCRIPTIONTRANSLATION.LANG", "$param.Language_param")
+                                  .buildSql("(select DESCRIPTION from DESCRIPTIONTRANSLATION", "1=2", ")"))]
+            ]);
     
     if(ProductDetails.productId != undefined)
     {
         neon.setFieldValue("$field.GROUPCODEID", ProductDetails.groupCode);
         neon.setFieldValue("$field.UNIT", ProductDetails.unit);
         neon.setFieldValue("$field.ITEMNAME", ProductDetails.productName);
-        neon.setFieldValue("$field.INFO", ProductDetails.INFO);
+        neon.setFieldValue("$field.INFO", ProductDetails.info);
         
         if(ProductDetails.PriceListToUse != null)
         {
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index ed96a1cac03b6aec0ee3dc3c4c1b425a2085e5d8..a2fdf472856ac6df5a4bb30e6567c31c4f5cb7b3 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -762,6 +762,12 @@
           <tooltip>Add the selection to a campaign</tooltip>
           <tooltipProcess>%aditoprj%/entity/Organisation_entity/entityfields/campaignactiongroup/children/addtocampaignfromtable/tooltipProcess.js</tooltipProcess>
         </entityActionField>
+        <entityActionField>
+          <name>addToBulkMailFromTable</name>
+          <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:ENVELOPES</iconId>
+        </entityActionField>
       </children>
     </entityActionGroup>
     <entityActionField>
diff --git a/entity/Organisation_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js b/entity/Organisation_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d723a8841f561e91a346e6eea8e86054aabaeaa1
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js
@@ -0,0 +1,6 @@
+import("Bulkmail_lib");
+import("system.vars");
+import("system.neon");
+
+if (vars.exists("$sys.selection"))
+    BulkMailUtils.openAddRecipientView(vars.getString("$sys.selection"));
\ No newline at end of file
diff --git a/entity/PermissionOverview_entity/PermissionOverview_entity.aod b/entity/PermissionOverview_entity/PermissionOverview_entity.aod
index c16477d891a091665df4ee26517ef98d8f36bfe4..68547b8afdc929aca9433a08b65293dac72c973b 100644
--- a/entity/PermissionOverview_entity/PermissionOverview_entity.aod
+++ b/entity/PermissionOverview_entity/PermissionOverview_entity.aod
@@ -34,8 +34,8 @@
       <contentType>IMAGE</contentType>
     </entityField>
     <entityField>
-      <name>ACTION_EDIT</name>
-      <title>Edit</title>
+      <name>ACTION_UPDATE</name>
+      <title>Update</title>
       <contentType>IMAGE</contentType>
     </entityField>
     <entityField>
@@ -101,7 +101,7 @@
           <name>ACTION_READ.value</name>
         </jDitoRecordFieldMapping>
         <jDitoRecordFieldMapping>
-          <name>ACTION_EDIT.value</name>
+          <name>ACTION_UPDATE.value</name>
         </jDitoRecordFieldMapping>
         <jDitoRecordFieldMapping>
           <name>ACTION_DELETE.value</name>
diff --git a/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js b/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js
index ff906bb09a9367ddac33aefd446e2cf44aa7648b..97a97d450fec1e92a8284e8788a923e895d0870f 100644
--- a/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/PermissionOverview_entity/recordcontainers/jdito/contentProcess.js
@@ -83,7 +83,7 @@ function prepareOverview(pPermSetId, pCurrOverview, pMode) {
                         case "read":
                             currOverview[4] = "VAADIN:CIRCLE";
                             break;
-                        case "edit":
+                        case "update":
                             currOverview[5] = "VAADIN:CIRCLE";
                             break;
                         case "delete":
@@ -112,7 +112,7 @@ function prepareOverview(pPermSetId, pCurrOverview, pMode) {
                         case "read":
                             currOverview[4] = "VAADIN:CIRCLE_THIN";
                             break;
-                        case "edit":
+                        case "update":
                             currOverview[5] = "VAADIN:CIRCLE_THIN";
                             break;
                         case "delete":
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index d59edee620c510478d04343e60ca17e7e84f09de..eaad79c79f1b8da3baed03f60b8b6f7249366ec0 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -824,6 +824,12 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
           <tooltip>Add the selection to a campaign</tooltip>
           <tooltipProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/addtocampaignfromtable/tooltipProcess.js</tooltipProcess>
         </entityActionField>
+        <entityActionField>
+          <name>addToBulkMailFromTable</name>
+          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:ENVELOPES</iconId>
+        </entityActionField>
       </children>
     </entityActionGroup>
     <entityActionField>
diff --git a/entity/Person_entity/entityfields/appointments/children/linkedobjectid_param/valueProcess.js b/entity/Person_entity/entityfields/appointments/children/linkedobjectid_param/valueProcess.js
index b08d2d5cae52e973ed036c402375ee31bc1551ce..18cdb55d5f138cf19832a538801cd462c1c61246 100644
--- a/entity/Person_entity/entityfields/appointments/children/linkedobjectid_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/appointments/children/linkedobjectid_param/valueProcess.js
@@ -2,4 +2,4 @@ import("system.result");
 import("system.vars");
 
 
-result.string(vars.get("$field.PERSONID"));
\ No newline at end of file
+result.string(vars.get("$field.CONTACTID"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js b/entity/Person_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d723a8841f561e91a346e6eea8e86054aabaeaa1
--- /dev/null
+++ b/entity/Person_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js
@@ -0,0 +1,6 @@
+import("Bulkmail_lib");
+import("system.vars");
+import("system.neon");
+
+if (vars.exists("$sys.selection"))
+    BulkMailUtils.openAddRecipientView(vars.getString("$sys.selection"));
\ No newline at end of file
diff --git a/entity/Product_entity/Product_entity.aod b/entity/Product_entity/Product_entity.aod
index 8adc4776543990ecd11199ac501e64bc7176529a..d3d32965cffe17c91ffc124a8aafba1b730aa4cf 100644
--- a/entity/Product_entity/Product_entity.aod
+++ b/entity/Product_entity/Product_entity.aod
@@ -202,11 +202,6 @@
         <element>PROCESS_SETVALUE</element>
       </onValueChangeTypes>
     </entityField>
-    <entityField>
-      <name>INFO</name>
-      <title>Description</title>
-      <contentType>LONG_TEXT</contentType>
-    </entityField>
     <entityConsumer>
       <name>Documents</name>
       <selectionMode>MULTI</selectionMode>
@@ -275,22 +270,6 @@
         </entityParameter>
       </children>
     </entityConsumer>
-    <entityField>
-      <name>LANGUAGE</name>
-      <consumer>Languages</consumer>
-      <searchable v="false" />
-      <titleProcess>%aditoprj%/entity/Product_entity/entityfields/language/titleProcess.js</titleProcess>
-      <valueProcess>%aditoprj%/entity/Product_entity/entityfields/language/valueProcess.js</valueProcess>
-      <displayValueProcess>%aditoprj%/entity/Product_entity/entityfields/language/displayValueProcess.js</displayValueProcess>
-    </entityField>
-    <entityConsumer>
-      <name>Languages</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Language_entity</entityName>
-        <fieldName>ISO3Name</fieldName>
-      </dependency>
-    </entityConsumer>
     <entityConsumer>
       <name>Activities</name>
       <dependency>
@@ -445,6 +424,24 @@
       <name>ProductText_param</name>
       <valueProcess>%aditoprj%/entity/Product_entity/entityfields/producttext_param/valueProcess.js</valueProcess>
     </entityParameter>
+    <entityConsumer>
+      <name>DescriptionTranslations</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>DescriptionTranslation_entity</entityName>
+        <fieldName>DescriptionTranslations</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ObjectRowid_param</name>
+          <valueProcess>%aditoprj%/entity/Product_entity/entityfields/descriptiontranslations/children/objectrowid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>ObjectType_param</name>
+          <valueProcess>%aditoprj%/entity/Product_entity/entityfields/descriptiontranslations/children/objecttype_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -520,10 +517,6 @@
           <name>CONTACT_ID.value</name>
           <recordfield>PRODUCT.CONTACT_ID</recordfield>
         </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>INFO.value</name>
-          <recordfield>PRODUCT.INFO</recordfield>
-        </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>GROUPCODEID.displayValue</name>
           <expression>%aditoprj%/entity/Product_entity/recordcontainers/db/recordfieldmappings/groupcodeid.displayvalue/expression.js</expression>
@@ -532,14 +525,6 @@
           <name>UNIT.displayValue</name>
           <expression>%aditoprj%/entity/Product_entity/recordcontainers/db/recordfieldmappings/unit.displayvalue/expression.js</expression>
         </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>LANGUAGE.value</name>
-          <recordfield>PRODUCT.LANGUAGE</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>LANGUAGE.displayValue</name>
-          <expression>%aditoprj%/entity/Product_entity/recordcontainers/db/recordfieldmappings/language.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>USER_NEW.value</name>
           <recordfield>PRODUCT.USER_NEW</recordfield>
diff --git a/entity/Product_entity/entityfields/descriptiontranslations/children/objectrowid_param/valueProcess.js b/entity/Product_entity/entityfields/descriptiontranslations/children/objectrowid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..533f8ec837ea2f9b588ddf05545ac47cdda23d18
--- /dev/null
+++ b/entity/Product_entity/entityfields/descriptiontranslations/children/objectrowid_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$sys.uid"));
\ No newline at end of file
diff --git a/entity/Product_entity/entityfields/descriptiontranslations/children/objecttype_param/valueProcess.js b/entity/Product_entity/entityfields/descriptiontranslations/children/objecttype_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..cc6924394ae950c43386275dda2c8db5d7a9c0ed
--- /dev/null
+++ b/entity/Product_entity/entityfields/descriptiontranslations/children/objecttype_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("Context_lib");
+import("system.result");
+
+result.string(ContextUtils.getCurrentContextId());
\ No newline at end of file
diff --git a/entity/Product_entity/entityfields/language/titleProcess.js b/entity/Product_entity/entityfields/language/titleProcess.js
deleted file mode 100644
index 04be2c545b0879ee1106eeb333161b65e5520edf..0000000000000000000000000000000000000000
--- a/entity/Product_entity/entityfields/language/titleProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.translate");
-import("system.result");
-
-result.string(translate.text("Language") + " (" + translate.text("Description") + ")");
\ No newline at end of file
diff --git a/entity/Product_entity/entityfields/language/valueProcess.js b/entity/Product_entity/entityfields/language/valueProcess.js
deleted file mode 100644
index fef47cfe6e7315f7dad5f4864bbe69e1276f7f38..0000000000000000000000000000000000000000
--- a/entity/Product_entity/entityfields/language/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.neon");
-import("system.vars");
-import("system.db");
-import("system.result");
-
-if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.getString("$field.LANGUAGE"))
-    result.string("deu");
\ No newline at end of file
diff --git a/entity/Product_entity/recordcontainers/db/recordfieldmappings/language.displayvalue/expression.js b/entity/Product_entity/recordcontainers/db/recordfieldmappings/language.displayvalue/expression.js
deleted file mode 100644
index 368c9593d9bde80e463b49879026c47394294f12..0000000000000000000000000000000000000000
--- a/entity/Product_entity/recordcontainers/db/recordfieldmappings/language.displayvalue/expression.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.result");
-import("Keyword_lib");
-
-var sql = LanguageKeywordUtils.getResolvedTitleSqlPart("PRODUCT.LANGUAGE");
-result.string(sql);
diff --git a/entity/Salesproject_entity/entityfields/reasons/mandatoryProcess.js b/entity/Salesproject_entity/entityfields/reasons/mandatoryProcess.js
index 086a5d36d49678a0e352341b792f65b46d756025..e04fe64bb9f9475704a97e61647eef1cda571d94 100644
--- a/entity/Salesproject_entity/entityfields/reasons/mandatoryProcess.js
+++ b/entity/Salesproject_entity/entityfields/reasons/mandatoryProcess.js
@@ -1,6 +1,7 @@
 import("system.result");
 import("system.vars");
+import("KeywordRegistry_basic");
 
 // IDs: SalesprojectState Order and Lost
-var res = vars.get("$field.STATE") && (vars.get("$field.STATE") == 'd8a60f60-a4e6-46ee-88ec-bac53e1afedd' || vars.get("$field.STATE") == '130bb53a-a97e-455e-8f34-8d445e985474');
+var res = vars.get("$field.STATE") && (vars.get("$field.STATE") == $KeywordRegistry.salesprojectState$order() || vars.get("$field.STATE") == $KeywordRegistry.salesprojectState$lost());
 result.string(res);
\ No newline at end of file
diff --git a/entity/Salesproject_entity/entityfields/reasons/stateProcess.js b/entity/Salesproject_entity/entityfields/reasons/stateProcess.js
index 5e5536334c4ff87b845fff9f55a37d1e1dc06281..666b25be556fdf618dc8fc730751b30d5b1ce085 100644
--- a/entity/Salesproject_entity/entityfields/reasons/stateProcess.js
+++ b/entity/Salesproject_entity/entityfields/reasons/stateProcess.js
@@ -1,8 +1,9 @@
 import("system.result");
 import("system.vars");
+import("KeywordRegistry_basic");
 
 // IDs: SalesprojectState Order and Lost
-if(vars.get("$field.STATE") && (vars.get("$field.STATE") == 'd8a60f60-a4e6-46ee-88ec-bac53e1afedd' || vars.get("$field.STATE") == '130bb53a-a97e-455e-8f34-8d445e985474'))
+if(vars.get("$field.STATE") && (vars.get("$field.STATE") == $KeywordRegistry.salesprojectState$order() || vars.get("$field.STATE") == $KeywordRegistry.salesprojectState$lost()))
         result.string("EDITABLE");
 else
         result.string("INVISIBLE");
diff --git a/entity/Salesproject_entity/entityfields/state/onValueChange.js b/entity/Salesproject_entity/entityfields/state/onValueChange.js
index fd8dae9d669334bc145bbc55b693b70a55e63726..515f51620ca73b2e70eb7da43ae31c18825586a1 100644
--- a/entity/Salesproject_entity/entityfields/state/onValueChange.js
+++ b/entity/Salesproject_entity/entityfields/state/onValueChange.js
@@ -12,7 +12,7 @@ if (vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW)
     var state = vars.get("$field.STATE");
 
     // Postponed
-    if (state == '23d38486-4cce-41ce-a8df-164ad44df706')
+    if (state == $KeywordRegistry.salesprojectState$postponed())
     {
         var stateName = KeywordUtils.getViewValue($KeywordRegistry.salesprojectState(), state);
         var clearForecast = question.askYesNo(translate.withArguments("Clear forecast and set state to '%0'?", [stateName]), translate.withArguments("Would you really like to clear the forecast and set the state to '%0'?" + "\n" + translate.text("This cannot be undone!"), [stateName]), false);
diff --git a/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js b/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js
index 67dfadce51729efc98e31f67a5a9892eb264710e..775a8af9d388163a8d1208e001d41893eaa4447d 100644
--- a/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Salesproject_entity/recordcontainers/db/onDBUpdate.js
@@ -30,7 +30,7 @@ vars.get("$local.changed").forEach(function(fieldName) {
             // set COMPETITION / OFFER to Lost
             
             // Lost
-            if (state == 'd8a60f60-a4e6-46ee-88ec-bac53e1afedd')
+            if (state == $KeywordRegistry.salesprojectState$lost())
             {
                 // set all offers of the salesproject to lost
                 db.updateData("OFFER", ["STATUS"], null, ["a5682630-01ae-4769-8f03-47dc1db44da4"], SqlCondition.equals("OFFER.OBJECT_ROWID", vars.getString("$field.SALESPROJECTID"), "1=2"));
@@ -38,7 +38,7 @@ vars.get("$local.changed").forEach(function(fieldName) {
                 clearReason = false;
             }
             // Order
-            else if (state == '130bb53a-a97e-455e-8f34-8d445e985474')
+            else if (state == $KeywordRegistry.salesprojectState$order())
             {
                 // set all competitions of the salesproject to lost
                 db.updateData("COMPETITION", ["STATUS"], null, ["ff73172c-8517-4b6e-98cb-43aebacd9af1"], SqlCondition.equals("COMPETITION.OBJECT_ROWID", vars.getString("$field.SALESPROJECTID"), "1=2"));
@@ -46,7 +46,7 @@ vars.get("$local.changed").forEach(function(fieldName) {
                 clearReason = false;
             }
             // Postponed
-            else if (state == '23d38486-4cce-41ce-a8df-164ad44df706')
+            else if (state == $KeywordRegistry.salesprojectState$postponed())
             {
                 // do not notify as the user just got a question, if he really would like to clear the forecast
                 needToUpdateForecast = false;
diff --git a/entity/Task_entity/Task_entity.aod b/entity/Task_entity/Task_entity.aod
index 42f7c04df52352d564827aa3922d03f924d78824..28a0a68c41edf29423f4beb0e2c463def666c894 100644
--- a/entity/Task_entity/Task_entity.aod
+++ b/entity/Task_entity/Task_entity.aod
@@ -428,7 +428,6 @@
       <alias>Data_alias</alias>
       <conditionProcess>%aditoprj%/entity/Task_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
       <orderClauseProcess>%aditoprj%/entity/Task_entity/recordcontainers/db/orderClauseProcess.js</orderClauseProcess>
-      <onDBInsert>%aditoprj%/entity/Task_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
       <onDBDelete>%aditoprj%/entity/Task_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
       <linkInformation>
         <linkInformation>
diff --git a/entity/Task_entity/entityfields/keywordstates/children/whitelistids_param/valueProcess.js b/entity/Task_entity/entityfields/keywordstates/children/whitelistids_param/valueProcess.js
index 82820e3158ff5a5eba0f8340bbf49f34891d31dd..03b66f45bd45fd69ac03a36d21907b6bd3c537b4 100644
--- a/entity/Task_entity/entityfields/keywordstates/children/whitelistids_param/valueProcess.js
+++ b/entity/Task_entity/entityfields/keywordstates/children/whitelistids_param/valueProcess.js
@@ -3,7 +3,7 @@ import("KeywordRegistry_basic");
 
 result.object([
     $KeywordRegistry.taskStatus$new(),
-    $KeywordRegistry.taskStatus$inProcess(),
+    $KeywordRegistry.taskStatus$inProgress(),
     $KeywordRegistry.taskStatus$waiting(),
     $KeywordRegistry.taskStatus$ended()
 ]);
\ No newline at end of file
diff --git a/entity/Task_entity/recordcontainers/db/onDBInsert.js b/entity/Task_entity/recordcontainers/db/onDBInsert.js
deleted file mode 100644
index d1600f76112729020c057ab2a436a59ca5da716e..0000000000000000000000000000000000000000
--- a/entity/Task_entity/recordcontainers/db/onDBInsert.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("ActivityTask_lib")
-
-TaskUtils.setCode(vars.get("$field.TASKID"));
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index a8c3c421bdef4f17adf9d09278ff446ce9ff37eb..3ee7d10b5560326cb0ecd0831c8a189f9ac8804a 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -4434,6 +4434,33 @@
     <entry>
       <key>Linked Appointments</key>
     </entry>
+    <entry>
+      <key>Location</key>
+    </entry>
+    <entry>
+      <key>Not sent</key>
+    </entry>
+    <entry>
+      <key>Is being sent</key>
+    </entry>
+    <entry>
+      <key>Preview</key>
+    </entry>
+    <entry>
+      <key>Content</key>
+    </entry>
+    <entry>
+      <key>Bulk mail was sent!</key>
+    </entry>
+    <entry>
+      <key>%0 mails sent sucessfully, %1 mails failed</key>
+    </entry>
+    <entry>
+      <key>Bulk mail \"%0\" was sent!</key>
+    </entry>
+    <entry>
+      <key>Descriptions</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 2b0b8d4c42eac355d3ff2a6920179b44fde74b79..32ba367380b17dd9e9aaaea9521edcb359c866c4 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -53,6 +53,14 @@
       <key>This contact has no possible link.</key>
       <value>Dieser Kontakt hat keine möglichen Verknüpfungen.</value>
     </entry>
+    <entry>
+      <key>Is being sent</key>
+      <value>Wird versendet</value>
+    </entry>
+    <entry>
+      <key>User Administration</key>
+      <value>Benutzerverwaltung</value>
+    </entry>
     <entry>
       <key>Restrictions</key>
       <value>Einschränkungen</value>
@@ -97,6 +105,10 @@
       <key>Bulk mail</key>
       <value>Serienmail</value>
     </entry>
+    <entry>
+      <key>Bulk mail \"%0\" was sent!</key>
+      <value>Serienmail \"%0\" wurde versendet!</value>
+    </entry>
     <entry>
       <key>No fax</key>
       <value>Kein Fax</value>
@@ -613,6 +625,10 @@
       <key>Confirmed</key>
       <value>Bestätigt</value>
     </entry>
+    <entry>
+      <key>Descriptions</key>
+      <value>Beschreibungen</value>
+    </entry>
     <entry>
       <key>Free</key>
       <value>Frei</value>
@@ -843,6 +859,10 @@
       <key>Advertising material</key>
       <value>Werbemittel</value>
     </entry>
+    <entry>
+      <key>%0 mails sent sucessfully, %1 mails failed</key>
+      <value>%0 Mails erfolgreich versendet, %1 Mails fehlgeschlagen</value>
+    </entry>
     <entry>
       <key>Valid from</key>
       <value>gültig ab</value>
@@ -1229,6 +1249,10 @@
       <key>Show all offers</key>
       <value>Alle Angebote anzeigen</value>
     </entry>
+    <entry>
+      <key>Preview</key>
+      <value>Vorschau</value>
+    </entry>
     <entry>
       <key>Filetype</key>
       <value>Dateityp</value>
@@ -2568,6 +2592,10 @@
       <key>Czech Republic</key>
       <value>Tschechische Republik</value>
     </entry>
+    <entry>
+      <key>Not sent</key>
+      <value>Nicht versendet</value>
+    </entry>
     <entry>
       <key>Mauritania</key>
       <value>Mauretanien</value>
@@ -3761,6 +3789,7 @@
     </entry>
     <entry>
       <key>Calendar</key>
+      <value>Kalender</value>
     </entry>
     <entry>
       <key>${SQL_LIB_UNDEFINED_VALUE} field: %0</key>
@@ -3866,6 +3895,10 @@
       <key>per</key>
       <value>pro</value>
     </entry>
+    <entry>
+      <key>Content</key>
+      <value>Inhalt</value>
+    </entry>
     <entry>
       <key>The max participants count has to be equal or greater than the count of the current participants!</key>
       <value>Die maximale Teilnehmerzahl muss gleich oder größer der aktuellen Teilnehmerzahl sein!</value>
@@ -5577,6 +5610,9 @@
     <entry>
       <key>USER_NEW_CONTACT</key>
     </entry>
+    <entry>
+      <key>Bulk mail was sent!</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index fe2f84a688a4761263b6c8641fc602a3bfca9e54..89992de9004ee040636942b438c4c88afcaa5869 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -4483,6 +4483,36 @@
     <entry>
       <key>Linked Appointments</key>
     </entry>
+    <entry>
+      <key>Location</key>
+    </entry>
+    <entry>
+      <key>Not sent</key>
+    </entry>
+    <entry>
+      <key>Is being sent</key>
+    </entry>
+    <entry>
+      <key>Preview</key>
+    </entry>
+    <entry>
+      <key>Content</key>
+    </entry>
+    <entry>
+      <key>Bulk mail was sent!</key>
+    </entry>
+    <entry>
+      <key>%0 mails sent sucessfully, %1 mails failed</key>
+    </entry>
+    <entry>
+      <key>Bulk mail \"%0\" was sent!</key>
+    </entry>
+    <entry>
+      <key>Descriptions</key>
+    </entry>
+    <entry>
+      <key>User Administration</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/Appointment/Appointment.aod b/neonContext/Appointment/Appointment.aod
index 88ff16a8549e9b4073a8006e90b97dd9d27440f3..67da92ae2faee58f5e7fe5e08c9a7c212f32ca27 100644
--- a/neonContext/Appointment/Appointment.aod
+++ b/neonContext/Appointment/Appointment.aod
@@ -23,5 +23,9 @@
       <name>2a5e05b2-3f12-43b4-a3f4-3c31dbe0dace</name>
       <view>AppointmentFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>de97b676-6504-4edc-96ba-77ff8483a3a0</name>
+      <view>AppointmentFilterDashlet_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonContext/BulkMailAddRecipients/BulkMailAddRecipients.aod b/neonContext/BulkMailAddRecipients/BulkMailAddRecipients.aod
new file mode 100644
index 0000000000000000000000000000000000000000..1769aa30496e1a30b4acc2e8b4d05757bc332b9c
--- /dev/null
+++ b/neonContext/BulkMailAddRecipients/BulkMailAddRecipients.aod
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
+  <name>BulkMailAddRecipients</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <editview>BulkMailAddRecipientsEdit_view</editview>
+  <entity>BulkMailAddRecipients_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>bab2e1b6-77a8-4830-8f60-cc0d4129f54d</name>
+      <view>BulkMailAddRecipientsEdit_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/DescriptionTranslation/DescriptionTranslation.aod b/neonContext/DescriptionTranslation/DescriptionTranslation.aod
new file mode 100644
index 0000000000000000000000000000000000000000..caef8dbd5c08a7f4b057a7d4db0d0ec048f21d53
--- /dev/null
+++ b/neonContext/DescriptionTranslation/DescriptionTranslation.aod
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
+  <name>DescriptionTranslation</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterview>DescriptionTranslationFilter_view</filterview>
+  <editview>DescriptionTranslationEdit_view</editview>
+  <preview>DescriptionTranslationPreview_view</preview>
+  <entity>DescriptionTranslation_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>dd74152c-282f-4cde-9ad8-93a027dbbf56</name>
+      <view>DescriptionTranslationFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>0d8720bb-5bef-4913-a0ea-d426875d8127</name>
+      <view>DescriptionTranslationEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>d0cfda07-eb27-440d-a698-03763ca8d664</name>
+      <view>DescriptionTranslationPreview_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/Product/Product.aod b/neonContext/Product/Product.aod
index 64a4cf42e7c55d9be744f9b415413a62aeeaa7b3..a91bfe8529ca21610ebc1edcea60092691199a93 100644
--- a/neonContext/Product/Product.aod
+++ b/neonContext/Product/Product.aod
@@ -1,34 +1,30 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
-  <name>Product</name>
-  <title>Product</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <mainview>ProductMain_view</mainview>
-  <filterview>ProductFilter_view</filterview>
-  <editview>ProductEdit_view</editview>
-  <preview>ProductPreview_view</preview>
-  <lookupview>ProductFilter_view</lookupview>
-  <entity>Product_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>8a0bd726-b3f6-4c5a-bd2a-251285b9ad90</name>
-      <view>ProductMain_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>ecb98950-5460-44ab-8da8-757bd143c03e</name>
-      <view>ProductEdit_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>cc985c0d-755f-46bd-89a2-71c5c6227198</name>
-      <view>ProductFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>5580ead4-2257-4cdb-a3ac-5e7067c4c1ab</name>
-      <view>ProductPreview_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>f5f7c429-56ca-421e-8e43-e8da14ca88a0</name>
-      <view>ProductDescription_view</view>
-    </neonViewReference>
-  </references>
-</neonContext>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0">
+  <name>Product</name>
+  <title>Product</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <mainview>ProductMain_view</mainview>
+  <filterview>ProductFilter_view</filterview>
+  <editview>ProductEdit_view</editview>
+  <preview>ProductPreview_view</preview>
+  <lookupview>ProductFilter_view</lookupview>
+  <entity>Product_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>8a0bd726-b3f6-4c5a-bd2a-251285b9ad90</name>
+      <view>ProductMain_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>ecb98950-5460-44ab-8da8-757bd143c03e</name>
+      <view>ProductEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>cc985c0d-755f-46bd-89a2-71c5c6227198</name>
+      <view>ProductFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>5580ead4-2257-4cdb-a3ac-5e7067c4c1ab</name>
+      <view>ProductPreview_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonNotificationType/BulkMailSent/BulkMailSent.aod b/neonNotificationType/BulkMailSent/BulkMailSent.aod
new file mode 100644
index 0000000000000000000000000000000000000000..63b6ad9c3e2da370cdd6b33a807b1852aece2ed8
--- /dev/null
+++ b/neonNotificationType/BulkMailSent/BulkMailSent.aod
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0">
+  <name>BulkMailSent</name>
+  <title>Bulk mail sent</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <icon>VAADIN:ENVELOPES</icon>
+</neonNotificationType>
diff --git a/neonView/AppointmentFilterDashlet_view/AppointmentFilterDashlet_view.aod b/neonView/AppointmentFilterDashlet_view/AppointmentFilterDashlet_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..6ce3ce63a5671607245180c40b9e70a45093daf2
--- /dev/null
+++ b/neonView/AppointmentFilterDashlet_view/AppointmentFilterDashlet_view.aod
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>AppointmentFilterDashlet_view</name>
+  <title>Linked Appointments</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="false" />
+  <dashletConfigurations>
+    <neonDashletConfiguration>
+      <name>appointmentFilterConfig</name>
+      <title>Linked Appointments</title>
+      <fragment>Appointment/full</fragment>
+      <icon>VAADIN:CALENDAR</icon>
+      <categories>
+        <neonDashletCategory>
+          <name>Calendar</name>
+          <title>Calendar</title>
+        </neonDashletCategory>
+      </categories>
+      <parameters>
+        <neonDashletParameter>
+          <name>LinkedAppointmentsFromDashlet_param</name>
+          <value>true</value>
+        </neonDashletParameter>
+      </parameters>
+    </neonDashletConfiguration>
+  </dashletConfigurations>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>Table</name>
+      <autoNewRow v="false" />
+      <entityField>#ENTITY</entityField>
+      <isEditable v="false" />
+      <isDeletable v="false" />
+      <columns>
+        <neonTableColumn>
+          <name>0aa3d147-674f-4765-826e-f97a4b48dc8a</name>
+          <entityField>SUMMARY</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>87170445-d63e-449b-9568-a055d5ed8afd</name>
+          <entityField>BEGIN</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>2284bbe2-dab7-45ce-9ced-8227802c3e92</name>
+          <entityField>END</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>43f7ef8a-19da-4ed6-afd3-2cfb825ab5b8</name>
+          <entityField>LOCATION</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/BulkMailAddRecipientsEdit_view/BulkMailAddRecipientsEdit_view.aod b/neonView/BulkMailAddRecipientsEdit_view/BulkMailAddRecipientsEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..cb799d087782807ae075e4b5cec63c5f025e7175
--- /dev/null
+++ b/neonView/BulkMailAddRecipientsEdit_view/BulkMailAddRecipientsEdit_view.aod
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>BulkMailAddRecipientsEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <genericViewTemplate>
+      <name>Generic</name>
+      <editMode v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>96932894-43f2-471f-b511-3b38bd5f93cb</name>
+          <entityField>BULKMAIL_ID</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/BulkMailEdit_view/BulkMailEdit_view.aod b/neonView/BulkMailEdit_view/BulkMailEdit_view.aod
index 31576a804c694002745b9516b683025ade29786e..fa4ece93b65ff37c3fb38c7105bbe9d5db336d36 100644
--- a/neonView/BulkMailEdit_view/BulkMailEdit_view.aod
+++ b/neonView/BulkMailEdit_view/BulkMailEdit_view.aod
@@ -13,6 +13,14 @@
       <editMode v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
+        <entityFieldLink>
+          <name>b68c65de-4ecd-4a23-9242-f85e7b708b1e</name>
+          <entityField>DOCUMENTTEMPLATE_ID</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>f040d032-823c-4199-8314-01d784fdc167</name>
+          <entityField>BINDATA</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>e363bda2-d8bf-456e-bcae-d1870408022a</name>
           <entityField>NAME</entityField>
@@ -25,10 +33,6 @@
           <name>c73d0fb7-b740-48ac-8f3e-fd4199f169da</name>
           <entityField>SUBJECT</entityField>
         </entityFieldLink>
-        <entityFieldLink>
-          <name>b68c65de-4ecd-4a23-9242-f85e7b708b1e</name>
-          <entityField>DOCUMENTTEMPLATE_ID</entityField>
-        </entityFieldLink>
         <entityFieldLink>
           <name>e4ec09c2-3815-4a3b-bce8-c12d5b919b04</name>
           <entityField>SENDER</entityField>
diff --git a/neonView/BulkMailFilter_view/BulkMailFilter_view.aod b/neonView/BulkMailFilter_view/BulkMailFilter_view.aod
index a9691dae520b369f613e1e946922dff754cfb7d4..1f07968102c5c5cf47c41b4224fe72ad74885c81 100644
--- a/neonView/BulkMailFilter_view/BulkMailFilter_view.aod
+++ b/neonView/BulkMailFilter_view/BulkMailFilter_view.aod
@@ -2,6 +2,7 @@
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
   <name>BulkMailFilter_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/BulkMailPreview_view/BulkMailPreview_view.aod b/neonView/BulkMailPreview_view/BulkMailPreview_view.aod
index a617140741df8b4536a270b848e191e5921e1122..d04a9df95690a3a24933127b028b23fdc96bcbe4 100644
--- a/neonView/BulkMailPreview_view/BulkMailPreview_view.aod
+++ b/neonView/BulkMailPreview_view/BulkMailPreview_view.aod
@@ -13,13 +13,22 @@
       <name>Card</name>
       <iconField>ICON</iconField>
       <titleField>NAME</titleField>
-      <descriptionField>SUBJECT</descriptionField>
+      <descriptionField>STATUS</descriptionField>
       <entityField>#ENTITY</entityField>
     </cardViewTemplate>
     <genericViewTemplate>
       <name>Generic</name>
+      <showDrawer v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
+        <entityFieldLink>
+          <name>524c32f8-99d8-453d-afe5-b72a322a4555</name>
+          <entityField>SUBJECT</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>9ef1ecd4-063a-4c18-9def-d395f59a64dc</name>
+          <entityField>SENDER</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>28c1e091-0fea-4324-8fb8-1893388354b7</name>
           <entityField>STATUS</entityField>
@@ -28,10 +37,6 @@
           <name>edbeea4d-019f-4661-b0d7-c07468e747cc</name>
           <entityField>DOCUMENTTEMPLATE_ID</entityField>
         </entityFieldLink>
-        <entityFieldLink>
-          <name>9ef1ecd4-063a-4c18-9def-d395f59a64dc</name>
-          <entityField>SENDER</entityField>
-        </entityFieldLink>
         <entityFieldLink>
           <name>8bb72d39-3348-4bd6-b57d-f7f5ae573e73</name>
           <entityField>DESCRIPTION</entityField>
diff --git a/neonView/BulkMailTest_view/BulkMailTest_view.aod b/neonView/BulkMailTest_view/BulkMailTest_view.aod
index bc1d38234b70e8ec5734946823f0003490361546..c6442e56b066bfb47f58b9154ef3e9fa9d2a2fcb 100644
--- a/neonView/BulkMailTest_view/BulkMailTest_view.aod
+++ b/neonView/BulkMailTest_view/BulkMailTest_view.aod
@@ -10,12 +10,30 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>Generic</name>
+      <name>Subject</name>
+      <showDrawer v="true" />
+      <drawerCaption>Subject</drawerCaption>
+      <fixedDrawer v="true" />
+      <hideLabels v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
         <entityFieldLink>
-          <name>481f729b-08c1-442f-bd6c-037ed50e2c4c</name>
-          <entityField>PREVIEW</entityField>
+          <name>d85c2b49-3a32-4261-95aa-6e13d9debe46</name>
+          <entityField>subjectPreview</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+    <genericViewTemplate>
+      <name>Body</name>
+      <showDrawer v="true" />
+      <drawerCaption>Content</drawerCaption>
+      <fixedDrawer v="true" />
+      <hideLabels v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>13d21d66-6f52-4535-9cb9-3b26db11dfbf</name>
+          <entityField>preview</entityField>
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
diff --git a/neonView/DescriptionTranslationEdit_view/DescriptionTranslationEdit_view.aod b/neonView/DescriptionTranslationEdit_view/DescriptionTranslationEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..ee50c236734f4a44c8e6450ff34389c425ecc44e
--- /dev/null
+++ b/neonView/DescriptionTranslationEdit_view/DescriptionTranslationEdit_view.aod
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>DescriptionTranslationEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <isSmall v="true" />
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <genericViewTemplate>
+      <name>translationData</name>
+      <editMode v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>9f8ad216-e4da-4973-bf3f-1d24dca765f3</name>
+          <entityField>LANG</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>64dde5e6-d8f7-42f7-bea9-104210ebf08f</name>
+          <entityField>DESCRIPTION</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/DescriptionTranslationFilter_view/DescriptionTranslationFilter_view.aod b/neonView/DescriptionTranslationFilter_view/DescriptionTranslationFilter_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..043efc0bd39b67534eb63122bcf14f71c6a5e293
--- /dev/null
+++ b/neonView/DescriptionTranslationFilter_view/DescriptionTranslationFilter_view.aod
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>DescriptionTranslationFilter_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>translation</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>4bdaf352-d5f1-44a1-9cca-7cb877928ba5</name>
+          <entityField>LANG</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>e00000eb-c883-4fd4-854e-c985938392aa</name>
+          <entityField>DESCRIPTION</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/ProductDescription_view/ProductDescription_view.aod b/neonView/DescriptionTranslationPreview_view/DescriptionTranslationPreview_view.aod
similarity index 61%
rename from neonView/ProductDescription_view/ProductDescription_view.aod
rename to neonView/DescriptionTranslationPreview_view/DescriptionTranslationPreview_view.aod
index b5f0f9e807ae07a33d7f8f3eca82c6a53086666b..9096d2a3ee378868b4b8a00d4658ca63726c12c2 100644
--- a/neonView/ProductDescription_view/ProductDescription_view.aod
+++ b/neonView/DescriptionTranslationPreview_view/DescriptionTranslationPreview_view.aod
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>ProductDescription_view</name>
-  <title>Description</title>
+  <name>DescriptionTranslationPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
@@ -10,18 +10,19 @@
   </layout>
   <children>
     <genericViewTemplate>
-      <name>Info</name>
+      <name>TranslationInfo</name>
       <showDrawer v="true" />
-      <drawerCaption>Description</drawerCaption>
+      <drawerCaption></drawerCaption>
+      <hideLabels v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
         <entityFieldLink>
-          <name>f0743860-a2f8-4c9c-998f-200ad1e67bb2</name>
-          <entityField>LANGUAGE</entityField>
+          <name>5e432839-ca9a-4a29-8006-0a1673d94c92</name>
+          <entityField>LANG</entityField>
         </entityFieldLink>
         <entityFieldLink>
-          <name>cd7cd596-0f25-4067-9aac-5ee188a3af64</name>
-          <entityField>INFO</entityField>
+          <name>1348a3ee-b372-4091-a0d5-5ab45fcb58a9</name>
+          <entityField>DESCRIPTION</entityField>
         </entityFieldLink>
       </fields>
     </genericViewTemplate>
diff --git a/neonView/EmployeeFilter_view/EmployeeFilter_view.aod b/neonView/EmployeeFilter_view/EmployeeFilter_view.aod
index f4644fdd94916d3a1424ab62bae534d47d3ed201..0aace42766f5597dee08d2a5830f832a9de7faf5 100644
--- a/neonView/EmployeeFilter_view/EmployeeFilter_view.aod
+++ b/neonView/EmployeeFilter_view/EmployeeFilter_view.aod
@@ -33,6 +33,22 @@
           <name>27c4199c-157a-4c3e-a851-01aa1d82dfd2</name>
           <entityField>LASTNAME</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>dd2d35d1-b418-4ee5-ba37-85d22f574ee7</name>
+          <entityField>CONTACT_ID</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>f14b2144-bfd4-4016-a6e8-e7a7c7668d6f</name>
+          <entityField>DEPARTMENT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>acf1037c-e198-4b2d-9c7f-a2438fa70089</name>
+          <entityField>EMAIL_ADDRESS</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>5acac530-7ff7-4fd1-ac48-4a9c441a8b13</name>
+          <entityField>DESCRIPTION</entityField>
+        </neonTableColumn>
       </columns>
     </tableViewTemplate>
   </children>
diff --git a/neonView/OfferitemPreview_view/OfferitemPreview_view.aod b/neonView/OfferitemPreview_view/OfferitemPreview_view.aod
index 4a13f1d9332f23905e9790a127a9185844b178fb..2e87d1704e8186573699c77f1dde3a7c100dcb27 100644
--- a/neonView/OfferitemPreview_view/OfferitemPreview_view.aod
+++ b/neonView/OfferitemPreview_view/OfferitemPreview_view.aod
@@ -5,29 +5,21 @@
   <layout>
     <headerFooterLayout>
       <name>layout</name>
-      <header>Header</header>
     </headerFooterLayout>
   </layout>
   <children>
-    <cardViewTemplate>
-      <name>Header</name>
-      <iconField>IMAGE</iconField>
-      <titleField>ITEMNAME</titleField>
-      <subtitleField>PRODUCT_ID</subtitleField>
-      <entityField>#ENTITY</entityField>
-    </cardViewTemplate>
     <genericViewTemplate>
       <name>Info</name>
       <showDrawer v="true" />
       <entityField>#ENTITY</entityField>
       <fields>
         <entityFieldLink>
-          <name>3b207cf2-c621-4e7d-b7aa-32feace5fe04</name>
-          <entityField>INFO</entityField>
+          <name>171901d8-32a2-4689-aeb3-e00936172330</name>
+          <entityField>ITEMPOSITION</entityField>
         </entityFieldLink>
         <entityFieldLink>
-          <name>c0c04d1c-90a7-4c0b-9323-1f0783757987</name>
-          <entityField>GROUPCODEID</entityField>
+          <name>335b6954-46ab-4235-9681-3ebd261af72a</name>
+          <entityField>PRODUCT_ID</entityField>
         </entityFieldLink>
         <entityFieldLink>
           <name>e792d720-187f-4aa1-917c-1c8065222b72</name>
@@ -54,7 +46,17 @@
           <entityField>OPTIONAL</entityField>
         </entityFieldLink>
         <entityFieldLink>
-          <name>9868560c-41c7-4641-b0f1-627a61b796b3</name>
+          <name>3b207cf2-c621-4e7d-b7aa-32feace5fe04</name>
+          <entityField>INFO</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+    <genericViewTemplate>
+      <name>Price</name>
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>4ced54f6-0d81-489b-b57b-432a75b77481</name>
           <entityField>TotalPrice</entityField>
         </entityFieldLink>
       </fields>
diff --git a/neonView/PermissionOverviewFilter_view/PermissionOverviewFilter_view.aod b/neonView/PermissionOverviewFilter_view/PermissionOverviewFilter_view.aod
index 456775fc326f8a86aa8b75b67e3b1e01bde00649..bd439feec7fa9b3cb042e9eb0392f532ea280258 100644
--- a/neonView/PermissionOverviewFilter_view/PermissionOverviewFilter_view.aod
+++ b/neonView/PermissionOverviewFilter_view/PermissionOverviewFilter_view.aod
@@ -36,7 +36,7 @@
         </neonTableColumn>
         <neonTableColumn>
           <name>0699fd7b-d4ac-4ef8-ac19-1cd249ce3251</name>
-          <entityField>ACTION_EDIT</entityField>
+          <entityField>ACTION_UPDATE</entityField>
         </neonTableColumn>
         <neonTableColumn>
           <name>f7c3479e-e635-44f1-afc0-45570c4fffe9</name>
diff --git a/neonView/ProductEdit_view/ProductEdit_view.aod b/neonView/ProductEdit_view/ProductEdit_view.aod
index 20027b6e81447837ee9425792d3954214e92a3b6..d4a5ea781da01966d342115ef24990cb144f8485 100644
--- a/neonView/ProductEdit_view/ProductEdit_view.aod
+++ b/neonView/ProductEdit_view/ProductEdit_view.aod
@@ -1,68 +1,60 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>ProductEdit_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <genericViewTemplate>
-      <name>Edit</name>
-      <editMode v="true" />
-      <entityField>#ENTITY</entityField>
-      <fields>
-        <entityFieldLink>
-          <name>d5cfa031-1bce-43b3-b1c1-d79a4c1205dc</name>
-          <entityField>ADVERTISING</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>950b57a7-df15-42a3-9f94-3377ed757ba3</name>
-          <entityField>GROUPCODEID</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>77197b19-54ea-493c-8d12-27391cd54a7a</name>
-          <entityField>MINSTOCK</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>472939e5-a69b-4eba-986f-0b47e72d0e9d</name>
-          <entityField>ORGANISATION_ID</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>cefb3dc8-8d9b-47c4-a0f8-e78e66303ec7</name>
-          <entityField>PRODUCTCODE</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>0019c5bd-368f-457a-b6e3-dd1d12cbe19e</name>
-          <entityField>PRODUCTNAME</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>5882a13d-3f07-4017-ad5b-042ee49c67d4</name>
-          <entityField>LANGUAGE</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>07f4aa57-24e9-4ce2-8b81-c4a3e8bcbce6</name>
-          <entityField>INFO</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>49b07dd2-1ee1-4b80-88a7-daf4879848d2</name>
-          <entityField>STATUS</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>a068f12a-ed45-4997-9e94-c865ccffee2a</name>
-          <entityField>UNIT</entityField>
-        </entityFieldLink>
-        <entityFieldLink>
-          <name>0c921c3d-df1a-4794-862b-6d190d6ef04e</name>
-          <entityField>CONTACT_ID</entityField>
-        </entityFieldLink>
-      </fields>
-    </genericViewTemplate>
-    <neonViewReference>
-      <name>34659538-e8a5-4f76-9710-a322548885ef</name>
-      <entityField>Attributes</entityField>
-      <view>AttributeRelationMultiEdit_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>ProductEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <genericViewTemplate>
+      <name>Edit</name>
+      <editMode v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>d5cfa031-1bce-43b3-b1c1-d79a4c1205dc</name>
+          <entityField>ADVERTISING</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>950b57a7-df15-42a3-9f94-3377ed757ba3</name>
+          <entityField>GROUPCODEID</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>77197b19-54ea-493c-8d12-27391cd54a7a</name>
+          <entityField>MINSTOCK</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>472939e5-a69b-4eba-986f-0b47e72d0e9d</name>
+          <entityField>ORGANISATION_ID</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>cefb3dc8-8d9b-47c4-a0f8-e78e66303ec7</name>
+          <entityField>PRODUCTCODE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>0019c5bd-368f-457a-b6e3-dd1d12cbe19e</name>
+          <entityField>PRODUCTNAME</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>49b07dd2-1ee1-4b80-88a7-daf4879848d2</name>
+          <entityField>STATUS</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>a068f12a-ed45-4997-9e94-c865ccffee2a</name>
+          <entityField>UNIT</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>0c921c3d-df1a-4794-862b-6d190d6ef04e</name>
+          <entityField>CONTACT_ID</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+    <neonViewReference>
+      <name>34659538-e8a5-4f76-9710-a322548885ef</name>
+      <entityField>Attributes</entityField>
+      <view>AttributeRelationMultiEdit_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/neonView/ProductMain_view/ProductMain_view.aod b/neonView/ProductMain_view/ProductMain_view.aod
index 44ff539d6aea525dd5b2f9653fd2b80d7b408649..170b358c21eb28a731ed5f1b6cded2ffc0b8d475 100644
--- a/neonView/ProductMain_view/ProductMain_view.aod
+++ b/neonView/ProductMain_view/ProductMain_view.aod
@@ -1,58 +1,58 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
-  <name>ProductMain_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <masterSlaveLayout>
-      <name>layout</name>
-      <master>9ff71d55-84be-411e-9637-5dc0eba6c79e</master>
-    </masterSlaveLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>9ff71d55-84be-411e-9637-5dc0eba6c79e</name>
-      <entityField>#ENTITY</entityField>
-      <view>ProductPreview_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>41887933-bb9a-48ce-818d-1db815021a36</name>
-      <entityField>Activities</entityField>
-      <view>ActivityFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>754b4efe-3ea7-42de-8e35-c85c3a0b4abf</name>
-      <entityField>Tasks</entityField>
-      <view>TaskFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>51f37fe5-91e1-4b76-83b3-be0319e871a4</name>
-      <entityField>#ENTITY</entityField>
-      <view>ProductDescription_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>7f416115-ff89-45ca-be10-ed568cac266c</name>
-      <entityField>ProductLinks</entityField>
-      <view>Prod2prodFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>11c4c5a0-27fa-4748-a6c6-3a667d2f3d8f</name>
-      <entityField>Productprices</entityField>
-      <view>ProductpriceFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>616f7cc3-93e7-41ee-8d38-027dd3d4b299</name>
-      <entityField>Documents</entityField>
-      <view>DocumentFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>6ee1258f-b571-45c1-b833-f292361b5a04</name>
-      <entityField>AttributeTree</entityField>
-      <view>AttributeRelationTree_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>0faf6a9e-b1f3-452d-b7fd-d0c9e3fc25f8</name>
-      <entityField>LogHistoryConsumer</entityField>
-      <view>LogHistoryFilter_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>ProductMain_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <masterSlaveLayout>
+      <name>layout</name>
+      <master>9ff71d55-84be-411e-9637-5dc0eba6c79e</master>
+    </masterSlaveLayout>
+  </layout>
+  <children>
+    <neonViewReference>
+      <name>9ff71d55-84be-411e-9637-5dc0eba6c79e</name>
+      <entityField>#ENTITY</entityField>
+      <view>ProductPreview_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>41887933-bb9a-48ce-818d-1db815021a36</name>
+      <entityField>Activities</entityField>
+      <view>ActivityFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>754b4efe-3ea7-42de-8e35-c85c3a0b4abf</name>
+      <entityField>Tasks</entityField>
+      <view>TaskFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>c647d35b-3535-4acf-b6cb-c9786a353b08</name>
+      <entityField>DescriptionTranslations</entityField>
+      <view>DescriptionTranslationFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>7f416115-ff89-45ca-be10-ed568cac266c</name>
+      <entityField>ProductLinks</entityField>
+      <view>Prod2prodFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>11c4c5a0-27fa-4748-a6c6-3a667d2f3d8f</name>
+      <entityField>Productprices</entityField>
+      <view>ProductpriceFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>616f7cc3-93e7-41ee-8d38-027dd3d4b299</name>
+      <entityField>Documents</entityField>
+      <view>DocumentFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>6ee1258f-b571-45c1-b833-f292361b5a04</name>
+      <entityField>AttributeTree</entityField>
+      <view>AttributeRelationTree_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>0faf6a9e-b1f3-452d-b7fd-d0c9e3fc25f8</name>
+      <entityField>LogHistoryConsumer</entityField>
+      <view>LogHistoryFilter_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/process/Bulkmail_lib/process.js b/process/Bulkmail_lib/process.js
index 5738a1e9f50bf2b4b919ed010b00863b5fa891ea..0f60eb164cb65562896e41009d5f0cc57ee09e7e 100644
--- a/process/Bulkmail_lib/process.js
+++ b/process/Bulkmail_lib/process.js
@@ -1,13 +1,43 @@
+import("system.datetime");
+import("system.neon");
+import("Employee_lib");
 import("system.vars");
 import("KeywordRegistry_basic");
 import("Sql_lib");
 import("system.db");
 import("DocumentTemplate_lib");
 import("Email_lib");
-
+import("system.process");
 
 function BulkMailUtils () {}
 
+/**
+ * Executes a process to send bulk mails on the server and creates a notification when finished.
+ * 
+ * @param {String} pBulkMailId id of the bulk mail
+ * @param {String} [pUser=currentUser] User that will get the notification, if null (not undefined!), no notification
+ *                                      will be created.
+ */
+BulkMailUtils.sendBulkMailOnServer = function (pBulkMailId, pUser)
+{
+    if (pUser === undefined)
+        pUser = EmployeeUtils.getCurrentUserId();
+    process.execute("sendBulkMail_serverProcess", 
+        {
+            bulkMailId : pBulkMailId,
+            user : pUser || ""
+        }
+    );
+}
+
+/**
+ * Sends a bulk mail. You should only call this function on the server because it
+ * can take some time to execute, use BulkMailUtils.sendBulkMailOnServer instead.
+ * 
+ * @param {String} pBulkMailId id of the bulk mail
+ * 
+ * @return {Object} count of sucessful and failed mails 
+ */
 BulkMailUtils.sendBulkMail = function (pBulkMailId)
 {
     //TODO: Mailbridge, Werbesperre beachten
@@ -16,19 +46,23 @@ BulkMailUtils.sendBulkMail = function (pBulkMailId)
         .andPrepare("BULKMAIL.BULKMAILID", pBulkMailId)
         .buildSql("select DOCUMENTTEMPLATE_ID, SUBJECT, SENDER from BULKMAIL", "1=2")
     );
-    var template = DocumentTemplate.loadTemplate(templateId);
+    var template = DocumentTemplate.loadTemplate(templateId); //TODO: check if the bulk mail itself has a document and prefer this
     var emailSender;
     
     var recipientData = db.table(SqlCondition.begin()
         .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
-        //TODO: more condition
+        .andPrepare("BULKMAILRECIPIENT.STATUS", $KeywordRegistry.bulkMailRecipientStatus$sent(), "# != ?")
+        //and no advertising ban
         .buildSql("select BULKMAILRECIPIENTID, CONTACT_ID, '' from BULKMAILRECIPIENT", "1=2")
     );
-    
+    var contactIds = recipientData.map(function (e) {return e[1];});
     var successIds = [];
     var failedIds = [];
     var sentDate = vars.get("$sys.date");
-    var mails = template.getReplacedEmailsByContactIds(recipientData.map(function (e) {return e[1];}));
+    var mails = template.getReplacedEmailsByContactIds(contactIds);
+    
+    var subjectTemplate = new DocumentTemplate(subject, DocumentTemplate.types.PLAIN);
+    var subjects = subjectTemplate.getReplacedContentByContactIds(contactIds);
     
     for (let i = 0, l = recipientData.length; i < l; i++)
     {
@@ -37,9 +71,9 @@ BulkMailUtils.sendBulkMail = function (pBulkMailId)
         let email = mails[contactId];
         if (email !== undefined)
         {
-            email.toRecipients = [recipientData[i][1]];
+            email.toRecipients = [recipientData[i][2]]; //TODO: email address missing
             email.sender = emailSender;
-            email.subject = subject;
+            email.subject = subjects[contactId];
             email.sender = sender;
 
             isSuccess = email.send();
@@ -49,15 +83,46 @@ BulkMailUtils.sendBulkMail = function (pBulkMailId)
         else
             failedIds.push(recipientData[i][0]); //set the recipient status to 'failed'
     }
-    db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailSentStatus$sent(), sentDate], 
+    db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$sent(), sentDate], 
         SqlCondition.begin()
             .andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", successIds)
             .build("1=2")
     );
-    db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailSentStatus$failed(), sentDate], 
+    db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$failed(), sentDate], 
         SqlCondition.begin()
             .andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", failedIds)
             .build("1=2")
     );
+        
+    db.updateData("BULKMAIL", ["STATUS"], null, [$KeywordRegistry.bulkMailStatus$sent()], 
+        SqlCondition.equals("BULKMAIL.BULKMAILID", pBulkMailId, "1=2"));
+        
+    return {
+        sucessful : successIds.length,
+        failed : failedIds.length
+    };
+}
+
+BulkMailUtils.openAddRecipientView = function (pContactIds)
+{
+    var params = {
+        "ContactIds_param" : pContactIds
+    };
+    neon.openContext("BulkMailAddRecipients", null, null, neon.OPERATINGSTATE_NEW, params);
+}
+
+
+BulkMailUtils.getCommRestrictionCondition = function (pPositive)
+{
+    var currentDate = datetime.date();
+    var existsQuery = SqlCondition.begin()
+        .andPrepare("COMMRESTRICTION.MEDIUM", $KeywordRegistry.communicationMediumCampaign$mail())
+        .andPrepare("COMMRESTRICTION.STARTDATE", currentDate, "# <= ?")
+        .and("COMMRESTRICTION.CONTACT_ID = CONTACT.CONTACTID or COMMRESTRICTION.CONTACT_ID = CONTACT.PERSON_ID")
+        .buildSql("exists(select COMMRESTRICTIONID from COMMRESTRICTION", "1=2", ")");
+    existsQuery = db.translateCondition(existsQuery);
+    if (!pPositive)
+        existsQuery = "not " + existsQuery;
     
+    return SqlCondition.begin().and(existsQuery);
 }
\ No newline at end of file
diff --git a/process/Contact_lib/process.js b/process/Contact_lib/process.js
index 5cca68dfd2b81d5023746b9596a1ca2a1a78baa1..3ea1aece0b5db28903cd7bb956432c8dff4d2e4a 100644
--- a/process/Contact_lib/process.js
+++ b/process/Contact_lib/process.js
@@ -292,6 +292,24 @@ ContactUtils.getPersOrgIds = function(pContactId)
     return [];
 }
 
+/**
+ * get the contactId from the OrganisationId
+ * 
+ * @param {String} pOrgId
+ * @return {String} the contactId or ""
+ */
+ContactUtils.getOrgContactId = function(pOrgId)
+{
+    if (pOrgId) {
+        return db.cell(SqlCondition.begin()
+                        .andPrepare("CONTACT.ORGANISATION_ID", pOrgId)
+                        .and("CONTACT.PERSON_ID is null")
+                        .buildSql("select CONTACTID from CONTACT", "1=0"));
+    }
+    
+    return "";
+}
+
 /**
  * get the name of the person or organisation
  * 
diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js
index 1bec33e710bf9e3396cbef4005e1d374ac018527..78ce55472f5a7be0ed3aa9e8778d1c4e8f07ef9c 100644
--- a/process/Context_lib/process.js
+++ b/process/Context_lib/process.js
@@ -8,6 +8,7 @@ import("Keyword_lib");
 import("Sql_lib");
 import("Proto_lib");
 import("Contact_lib");
+import("KeywordRegistry_basic");
 
 /**
  * Methods to manage contexts.
@@ -25,15 +26,7 @@ function ContextUtils() {}
  */
 ContextUtils.getCurrentContextId = function()
 {
-    var entityName = vars.getString("$sys.currententityname");
-    // TODO: replace with Core-method instead of switch-case!!!
-
-    // TODO: workaround: remove "entity" and add "context". This is a Workaround and has to be changed (see above todo)!
-    return entityName.substr(0, entityName.length-7);
-
-
-    
-   // return vars.getString("$sys.currentcontextname");
+   return vars.getString("$sys.currentcontextname");
 }
 
 /**
@@ -378,7 +371,7 @@ ContextUtils.getSelectMap  = function()
                                        .setJoinExpression("join CONTACT on ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID and CONTACT.PERSON_ID is null")
                                        .setCondition(SqlCondition.begin().and("ORGANISATION.ORGANISATIONID != '0'"))
                                        .setSubContexts({
-                                           "Person": ["select CONTACTID from CONTACT where PERSON_ID is not null and", "CONTACT.ORGANISATION_ID", '', ["Offer", "Order", "Contract"]]
+                                           "Person": ["select CONTACTID from CONTACT where PERSON_ID is not null and", "CONTACT.ORGANISATION_ID", '', ["Offer", "Order", "Contract", "SupportTicket"]]
                                        })
             ,"Person": ContextSelector.create("CONTACT", "CONTACTID")
                                       .setTitleExpression(maskingUtils.concat([
@@ -403,7 +396,7 @@ ContextUtils.getSelectMap  = function()
                                             .setContactIdField("CONTACT_ID")
                                             .setCreationDateField("STARTDATE")
                                             .setStateField("STATE")
-                                            .setActiveStates(["483bcaeb-1e5b-4772-b54e-7d7d8aa65712", "23d38486-4cce-41ce-a8df-164ad44df706"])
+                                            .setActiveStates([$KeywordRegistry.salesprojectState$open(), $KeywordRegistry.salesprojectState$postponed()])
             ,"Contract": ContextSelector.create("CONTRACT", "CONTRACTID")
                                         .setTitleExpression(maskingUtils.concat([
                                                                 KeywordUtils.getResolvedTitleSqlPart("ContractType", "CONTRACTTYPE"),
@@ -412,7 +405,7 @@ ContextUtils.getSelectMap  = function()
                                         .setContactIdField("CONTACT_ID")
                                         .setCreationDateField("CONTRACTSTART")
                                         .setStateField("CONTRACTSTATUS")
-                                        .setActiveStates(["e12d37e9-3429-40b5-973b-c1569843ca46", "3579eb0c-d8ca-4b6b-85ee-f1800a9301eb", "4c63c82d-0276-4c12-9937-13fd361ad786"])
+                                        .setActiveStates([$KeywordRegistry.contractState$validLimited(), $KeywordRegistry.contractState$validUnlimited(), $KeywordRegistry.contractState$notSigned()])
             ,"Offer": ContextSelector.create("OFFER", "OFFERID")
                                      .setTitleExpression(maskingUtils.concat([
                                                 "'" + translate.text("Offer") + "'",
@@ -451,9 +444,22 @@ ContextUtils.getSelectMap  = function()
                                             "left join CAMPAIGNSTEP on CAMPAIGNSTEP.CAMPAIGNSTEPID = CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID")
                         .setCreationDateField("CAMPAIGNSTEP.DATE_START")
                         .setStateField("CAMPAIGN.STATE")
-                        .setActiveStates(["e04c9c59-0590-463c-a10e-e25c583e9cf2", "42e1ee2b-0108-4ccf-ab43-29cbcb0377bf"])
+                        .setActiveStates([$KeywordRegistry.campaignState$planning(), $KeywordRegistry.campaignState$approved()])
             ,"CampaignStep" : ContextSelector.create("CAMPAIGNSTEP", "CAMPAIGNSTEPID", "NAME")
-
+            ,"SupportTicket": ContextSelector.create("TICKET", "TICKETID", "TASK.SUBJECT")
+                        .setJoinExpression("left join TASK on TASK.TASKID = TICKET.TASK_ID")
+                        .setCondition(SqlCondition.begin().andPrepare("TICKET.TICKETTYPE", $KeywordRegistry.ticketType$supportTicket()))
+                        .setContactIdField("TASK.REQUESTOR_CONTACT_ID")
+                        .setStateField("TASK.STATUS")
+                        .setActiveStates([
+                            $KeywordRegistry.taskStatus$new(),
+                            $KeywordRegistry.taskStatus$unassigned(),
+                            $KeywordRegistry.taskStatus$assigned(),
+                            $KeywordRegistry.taskStatus$inProgress(),
+                            $KeywordRegistry.taskStatus$waiting(),
+                            $KeywordRegistry.taskStatus$customerChecks(),
+                        ])
+                        .setCreationDateField("TASK.START_DATE")
     }
 }
 
@@ -519,6 +525,7 @@ ContextUtils.getContextDataSql = function(pContextId, pContactId, pWithDate, pAc
     var cond = SqlCondition.begin();
     if (pContactId)
     {
+        logging.log(JSON.stringify(ownContextSelector, null, "\t"))
         cond.andPrepare(ownContextSelector.getFullField(ownContextSelector.contactIdField), pContactId)
     }
     
diff --git a/process/DocumentTemplate_lib/process.js b/process/DocumentTemplate_lib/process.js
index 60435e3d7734bca1eb7ac3d458ddd651f35827e1..296b74a0d2e35cfd7eb10c557988bca193a31349 100644
--- a/process/DocumentTemplate_lib/process.js
+++ b/process/DocumentTemplate_lib/process.js
@@ -34,6 +34,8 @@ function DocumentTemplate (pTemplateContent, pType, pFilename)
 
 DocumentTemplate.prototype.toString = function ()
 {
+    if (this.type == DocumentTemplate.types.PLAIN)
+        return this.content;
     return text.parseDocument(this.content);
 }
 
@@ -48,22 +50,26 @@ DocumentTemplate.types = {
     HTML : "html",
     EML : "eml",
     ODT : "odt",
-    DOCX : "docx"
+    DOCX : "docx",
+    PLAIN : "plain" //for simple strings
 };
 
 /**
  * Loads the content of a document template and creates a new DocumentTemplate object with that.
  * 
- * @param {String} pTemplateId id of the template
+ * @param {String} pAssignmentRowId id of the assignment (in most cases the document template id)
+ * @param {String} [pAssignmentTable="DOCUMENTTEMPLATE"] the LOB assignment table
  * 
  * @return {DocumentTemplate} template object
  * 
  * @throws {Error} if the type can't be used
  */
-DocumentTemplate.loadTemplate = function (pTemplateId)
+DocumentTemplate.loadTemplate = function (pAssignmentRowId, pAssignmentTable)
 {
     var alias = "_____SYSTEMALIAS";
-    var templateDocument = db.getBinaryMetadata("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, false, alias, null);
+    if (!pAssignmentTable)
+        pAssignmentTable = "DOCUMENTTEMPLATE";
+    var templateDocument = db.getBinaryMetadata(pAssignmentTable, "DOCUMENT", pAssignmentRowId, false, alias, null);
     if (!templateDocument[0])
         return new DocumentTemplate();
     var binaryId = templateDocument[0][db.BINARY_ID];
@@ -138,6 +144,8 @@ DocumentTemplate.prototype.getReplacedContent = function (pReplacements)
             return this._getReplacedODT(pReplacements);
         case DocumentTemplate.types.DOCX:
             return this._getReplacedDOCX(pReplacements);
+        case DocumentTemplate.types.PLAIN:
+            return DocumentTemplate._replaceText(this.content, pReplacements);
         default:
             return null;
     }
@@ -313,6 +321,31 @@ DocumentTemplate.prototype._getReplacedODT = function (pReplacements)
                 body = body.replace(placeholder,
                     pReplacements[placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&amp;"), "ig");
             }
+            
+            //TODO: TableData
+//            for (ti = 0; ti < pTableData.length; ti++)
+//                {
+//                    var tablepos = bulkbody.indexOf( getDefaultODTplaceholer(pTableData[ti].Table, true));
+//                    if ( tablepos != -1 )
+//                    {
+//                        var tablebegin = bulkbody.lastIndexOf("<table:table-row", tablepos);
+//                        var tableend =  bulkbody.indexOf("</table:table-row>", tablepos ) + 18;
+//                        var lasttable =  bulkbody.substr( tableend );
+//                        var tablerow = bulkbody.substring( tablebegin, tableend );
+//                        bulkbody = bulkbody.substring( 0, tablebegin );
+//                        var tabledata = pTableData[ti].TableData[addrdata[i][0]];
+//                        if ( tabledata != undefined )
+//                        {
+//                            for (var tz = 0; tz < tabledata.length; tz++)
+//                            {
+//                                var table = tablerow;
+//                                bulkbody += relaceAdditionValues( table, pTableData[ti].Fields, tabledata[tz], pTableData[ti].Table + "." );
+//                            }
+//                        }
+//                        bulkbody += lasttable;
+//                }
+                
+                
             contentXml = beforeBody + body + afterBody;
             pack.addToZip(pODTFileName, "content.xml", util.encodeBase64String(contentXml));
             
diff --git a/process/Employee_lib/process.js b/process/Employee_lib/process.js
index 2be8c9f21461ec1c98e0daaa7b4bf9edee59fd56..8b2729142c99c08b40186bf5b9aae89134bc8958 100644
--- a/process/Employee_lib/process.js
+++ b/process/Employee_lib/process.js
@@ -1,116 +1,127 @@
-import("system.db");
-import("Sql_lib");
-import("system.tools");
-
-/**
- * Provides functions for employees and users.j
- * 
- * Do not create an instance of this!
- * 
- * @class
- */
-function EmployeeUtils () {}
-
-/**
- * Returns the contact id of the current user
- * 
- * @return the contact id
- */
-EmployeeUtils.getCurrentContactId = function ()
-{
-    var user = tools.getCurrentUser();
-    return user ? user[tools.PARAMS][tools.CONTACTID] : null;
-}
-
-/**
- * Returns the username id of the current user
- * 
- * @return the username
- */
-EmployeeUtils.getCurrentUserName = function ()
-{
-    var user = tools.getCurrentUser();
-    return user ? user[tools.TITLE] : null;
-}
-
-EmployeeUtils.sliceUserId = function (pUserId)
-{
-    return pUserId.slice(-36);
-}
-
-/**
- * generates a username from the firstname and lastname with the given structure
- * 
- * @param {String} pFirstName
- * @param {String} pLastName
- * @param {String} pStructure the structure of the username, special characters:
- *      f - one letter of the firstname in lowercase
- *      F - one letter of the firstname in uppsercase
- *      l - one letter of the lastname in lowercase
- *      L - one letter of the lastname in uppsercase
- *      f+ - the complete firstname in lowercase
- *      F+ - the complete firstname
- *      l+ - the complete lastname in lowercae
- *      L+ - the complete lastname 
- * 
- * @return {String} the generated username
- */
-EmployeeUtils.generateUserName = function (pFirstName, pLastName, pStructure)
-{
-    if (!pStructure || (!pFirstName && !pLastName))
-        return null;
-    
-    var firstNameIndex = 0;
-    var lastNameIndex = 0;
-    var userName = pStructure.replace(/(f\+|l\+|f|l)/ig, function (type)
-    {
-        switch (type)
-        {
-            case "f+":
-            return pFirstName.toLowerCase() || "";
-            case "F+":
-                return pFirstName || "";
-            case "l+":
-                return pLastName.toLowerCase()  || "";
-            case "L+":
-                return pLastName || "";
-            case "f":
-                return pFirstName.charAt(firstNameIndex++).toLowerCase() || "";
-            case "F":
-                return pFirstName.charAt(firstNameIndex++).toUpperCase() || "";
-            case "l":
-                return pLastName.charAt(lastNameIndex++).toLowerCase() || "";
-            case "L":
-                return pLastName.charAt(lastNameIndex++).toUpperCase() || "";
-        }
-    });
-    
-    return userName;
-}
-
-/**
- * checks if an employee is used somewhere
- * 
- * @param {String} pContactId the contact id of the user
- * 
- * @return {boolean} if the employee has relations
- */
-EmployeeUtils.hasRelations = function (pContactId)
-{
-    //sql queries with selects on tables where an employee can be used
-    var queries = [
-        SqlCondition.begin()
-            .andPrepare("ACTIVITY.RESPONSIBLE", pContactId)
-            .buildSql("select 1 from ACTIVITY"),
-        SqlCondition.begin()
-            .andPrepare("TASK.REQUESTOR_CONTACT_ID", pContactId)
-            .buildSql("select 1 from TASK"),
-        SqlCondition.begin()
-            .andPrepare("TIMETRACKING.CONTACT_ID", pContactId)
-            .buildSql("select 1 from TIMETRACKING")
-    ];
-    return queries.some(function (sql)
-        {
-            return db.cell(sql) != "";
-        });
+import("system.db");
+import("Sql_lib");
+import("system.tools");
+
+/**
+ * Provides functions for employees and users.j
+ * 
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function EmployeeUtils () {}
+
+/**
+ * Returns the contact id of the current user
+ * 
+ * @return the contact id
+ */
+EmployeeUtils.getCurrentContactId = function ()
+{
+    var user = tools.getCurrentUser();
+    return user ? user[tools.PARAMS][tools.CONTACTID] : null;
+}
+
+/**
+ * Returns the username id of the current user
+ * 
+ * @return the username
+ */
+EmployeeUtils.getCurrentUserName = function ()
+{
+    var user = tools.getCurrentUser();
+    return user ? user[tools.TITLE] : null;
+}
+
+/**
+ * Returns the username id of the current user
+ * 
+ * @return the username
+ */
+EmployeeUtils.getCurrentUserId = function ()
+{
+    var user = tools.getCurrentUser();
+    return user ? user[tools.NAME] : null;
+}
+
+EmployeeUtils.sliceUserId = function (pUserId)
+{
+    return pUserId.slice(-36);
+}
+
+/**
+ * generates a username from the firstname and lastname with the given structure
+ * 
+ * @param {String} pFirstName
+ * @param {String} pLastName
+ * @param {String} pStructure the structure of the username, special characters:
+ *      f - one letter of the firstname in lowercase
+ *      F - one letter of the firstname in uppsercase
+ *      l - one letter of the lastname in lowercase
+ *      L - one letter of the lastname in uppsercase
+ *      f+ - the complete firstname in lowercase
+ *      F+ - the complete firstname
+ *      l+ - the complete lastname in lowercae
+ *      L+ - the complete lastname 
+ * 
+ * @return {String} the generated username
+ */
+EmployeeUtils.generateUserName = function (pFirstName, pLastName, pStructure)
+{
+    if (!pStructure || (!pFirstName && !pLastName))
+        return null;
+    
+    var firstNameIndex = 0;
+    var lastNameIndex = 0;
+    var userName = pStructure.replace(/(f\+|l\+|f|l)/ig, function (type)
+    {
+        switch (type)
+        {
+            case "f+":
+            return pFirstName.toLowerCase() || "";
+            case "F+":
+                return pFirstName || "";
+            case "l+":
+                return pLastName.toLowerCase()  || "";
+            case "L+":
+                return pLastName || "";
+            case "f":
+                return pFirstName.charAt(firstNameIndex++).toLowerCase() || "";
+            case "F":
+                return pFirstName.charAt(firstNameIndex++).toUpperCase() || "";
+            case "l":
+                return pLastName.charAt(lastNameIndex++).toLowerCase() || "";
+            case "L":
+                return pLastName.charAt(lastNameIndex++).toUpperCase() || "";
+        }
+    });
+    
+    return userName;
+}
+
+/**
+ * checks if an employee is used somewhere
+ * 
+ * @param {String} pContactId the contact id of the user
+ * 
+ * @return {boolean} if the employee has relations
+ */
+EmployeeUtils.hasRelations = function (pContactId)
+{
+    //sql queries with selects on tables where an employee can be used
+    var queries = [
+        SqlCondition.begin()
+            .andPrepare("ACTIVITY.RESPONSIBLE", pContactId)
+            .buildSql("select 1 from ACTIVITY"),
+        SqlCondition.begin()
+            .andPrepare("TASK.REQUESTOR_CONTACT_ID", pContactId)
+            .buildSql("select 1 from TASK"),
+        SqlCondition.begin()
+            .andPrepare("TIMETRACKING.CONTACT_ID", pContactId)
+            .buildSql("select 1 from TIMETRACKING")
+    ];
+    return queries.some(function (sql)
+        {
+            return db.cell(sql) != "";
+        });
 }
\ No newline at end of file
diff --git a/process/KeywordRegistry_basic/process.js b/process/KeywordRegistry_basic/process.js
index 2290c97e85027ccef8131c7e606f69eae5992100..39f6b4e2340dee2d357dfca826c2426d683b103c 100644
--- a/process/KeywordRegistry_basic/process.js
+++ b/process/KeywordRegistry_basic/process.js
@@ -21,6 +21,9 @@ $KeywordRegistry.attributeType = function(){return "AttributeType";};
 $KeywordRegistry.keywordAttributeType = function(){return "KeywordAttributeType";};
 $KeywordRegistry.contractPayment = function(){return "ContractPayment";};
 $KeywordRegistry.contractStatus = function(){return "ContractStatus";};
+$KeywordRegistry.contractState$validLimited = function(){return "CONTRACTSTATVALIDLI                 ";};
+$KeywordRegistry.contractState$validUnlimited = function(){return "CONTRACTSTATVALIDUNLI               ";};
+$KeywordRegistry.contractState$notSigned = function(){return "CONTRACTSTATSIGN                    ";};
 $KeywordRegistry.contractType = function(){return "ContractType";};
 
 $KeywordRegistry.activityDirection = function(){return "ActivityDirection";};
@@ -31,8 +34,11 @@ $KeywordRegistry.contactStatus = function(){return "ContactStatus";};
 $KeywordRegistry.contactStatus$active = function(){return "CONTACTSTATACTIVE";};
 
 $KeywordRegistry.currency = function(){return "Currency";};
+$KeywordRegistry.currency$eur = function(){return "EUR                                 ";};
 $KeywordRegistry.productGroupcode = function(){return "ProductGroupcode";};
 $KeywordRegistry.offerStatus = function(){return "OfferStatus";};
+$KeywordRegistry.offerStatus$open = function(){return "OFFERSTATOPEN                       ";};
+$KeywordRegistry.offerStatus$checked = function(){return "OFFERSTATCHECK                      ";};
 $KeywordRegistry.offerStatus$sent = function(){return "OFFERSTATSENT                       ";};
 $KeywordRegistry.offerStatus$won = function(){return "OFFERSTATWON                        ";};
 $KeywordRegistry.offerStatus$lost = function(){return "OFFERSTATLOST                       ";};
@@ -45,13 +51,16 @@ $KeywordRegistry.personGender = function(){return "PersonGender";};
 
 $KeywordRegistry.taskStatus = function(){return "TaskStatus";};
 $KeywordRegistry.taskStatus$new = function(){return "NEW                                 ";};
-$KeywordRegistry.taskStatus$inProcess = function(){return "IN-PROGRESS                         ";};
+$KeywordRegistry.taskStatus$unassigned = function(){return "UNASSIGNED                          ";};
+$KeywordRegistry.taskStatus$assigned = function(){return "ASSIGNED                            ";};
+$KeywordRegistry.taskStatus$inProgress = function(){return "IN-PROGRESS                         ";};
 $KeywordRegistry.taskStatus$waiting = function(){return "WAITING                             ";};
 $KeywordRegistry.taskStatus$ended = function(){return "ENDED                               ";};
+$KeywordRegistry.taskStatus$customerChecks = function(){return "CUSTOMER-CHECKS                     ";};
 
 $KeywordRegistry.taskType = function(){return "TaskType";};
-$KeywordRegistry.taskType$task = function(){return "TASK";};
-$KeywordRegistry.taskType$ticket = function(){return "TICKET";};
+$KeywordRegistry.taskType$task = function(){return "TASK                                ";};
+$KeywordRegistry.taskType$ticket = function(){return "TICKET                              ";};
 
 $KeywordRegistry.ticketType = function(){return "TicketType";};
 $KeywordRegistry.ticketType$supportTicket = function(){return "SUPPORTTICKET                       ";};
@@ -79,6 +88,12 @@ $KeywordRegistry.salesprojectPricePolitics = function(){return "SalesprojectPric
 $KeywordRegistry.salesprojectWeakness = function(){return "SalesprojectWeakness";};
 $KeywordRegistry.salesprojectStrenght = function(){return "SalesprojectStrenght";};
 $KeywordRegistry.salesprojectState = function(){return "SalesprojectState";};
+$KeywordRegistry.salesprojectState$open = function(){return "SALPROJSTATOPEN                     ";};
+$KeywordRegistry.salesprojectState$postponed = function(){return "SALPROJSTATPOSTPONED                ";};
+$KeywordRegistry.salesprojectState$aborted = function(){return "SALPROJSTATABORT                    ";};
+$KeywordRegistry.salesprojectState$partialOrder = function(){return "SALPROJSTATPARTIAL                  ";};
+$KeywordRegistry.salesprojectState$order = function(){return "SALPROJSTATORDER                    ";};
+$KeywordRegistry.salesprojectState$lost = function(){return "SALPROJSTATLOST                     ";};
 $KeywordRegistry.salesprojectPhase = function(){return "SalesprojectPhase";};
 $KeywordRegistry.taskPriority = function(){return "TaskPriority";};
 $KeywordRegistry.taskPriority$none = function(){return "TASKPRIONONE";};
@@ -95,9 +110,10 @@ $KeywordRegistry.contactDepartment = function(){return "ContactDepartment";};
 $KeywordRegistry.contactPosition = function(){return "ContactPosition";};
 $KeywordRegistry.contactContactrole = function(){return "ContactContactrole";};
 $KeywordRegistry.campaignState = function(){return "CampaignManagementStates";};
-$KeywordRegistry.campaignState$planning = function(){return "PLANNING";};
+$KeywordRegistry.campaignState$planning = function(){return "PLANNING                            ";};
+$KeywordRegistry.campaignState$approved = function(){return "APPROVED                            ";};
 $KeywordRegistry.campaignStepState = function(){return "CampaignManagementStepStates";};
-$KeywordRegistry.campaignStepState$open = function(){return "OPEN";};
+$KeywordRegistry.campaignStepState$open = function(){return "OPEN                                ";};
 $KeywordRegistry.campaignStepCostCategory = function(){return "CampaignManagementCostCategory";};
 $KeywordRegistry.documentTemplateType = function(){return "DocumentTemplateType";};
 $KeywordRegistry.documentTemplateType$letter = function(){return "LET                                 ";};
@@ -118,8 +134,14 @@ $KeywordRegistry.DSGVOTablename = function() {return "DSGVOTablename";};
 $KeywordRegistry.DSGVOType = function() {return "DSGVOType";};
 $KeywordRegistry.textPlaceholder = function(){return "textPlaceholder";};
 $KeywordRegistry.communicationMediumCampaign = function(){return "CommunicationMediumCampaign";};
+$KeywordRegistry.communicationMediumCampaign$mail = function(){return "CAMPAIGNEMAIL                       ";};
 
-$KeywordRegistry.bulkMailSentStatus = function(){return "BulkMailSentStatus";};
-$KeywordRegistry.bulkMailSentStatus$pending = function(){return "9a0c5608-070e-49fb-92cd-f6abece9242d";};
-$KeywordRegistry.bulkMailSentStatus$sent = function(){return "147211fb-a1cf-49c8-8e08-c3cfe0404f9b";};
-$KeywordRegistry.bulkMailSentStatus$failed = function(){return "353e27e9-7491-4bfd-b9f9-f18f2cb2a36c";};
\ No newline at end of file
+$KeywordRegistry.bulkMailRecipientStatus = function(){return "BulkMailRecipientStatus";};
+$KeywordRegistry.bulkMailRecipientStatus$pending = function(){return "EMAILPENDING                        ";};
+$KeywordRegistry.bulkMailRecipientStatus$sent = function(){return "EMAILSENT                           ";};
+$KeywordRegistry.bulkMailRecipientStatus$failed = function(){return "EMAILFAILED                         ";};
+
+$KeywordRegistry.bulkMailStatus = function(){return "BulkMailStatus";};
+$KeywordRegistry.bulkMailStatus$notSent = function(){return "BULKMAILNOTSENT                     ";};
+$KeywordRegistry.bulkMailStatus$beingSent = function(){return "BULKMAILBEINGSENT                   ";};
+$KeywordRegistry.bulkMailStatus$sent = function(){return "BULKMAILSENT                        ";};
\ No newline at end of file
diff --git a/process/Offer_lib/process.js b/process/Offer_lib/process.js
index 09d10a01ebdd2ff2b36dcbd6e7ebfe3d44660c48..680e10c4ee5d6b8a08e9f86284a1075a17af11ba 100644
--- a/process/Offer_lib/process.js
+++ b/process/Offer_lib/process.js
@@ -65,6 +65,12 @@ OfferUtils.isEditable = function(status) {
     return status != $KeywordRegistry.offerStatus$sent() && status != $KeywordRegistry.offerStatus$won() && status != $KeywordRegistry.offerStatus$lost();
 }
 
+OfferUtils.isDeletable = function(status) {
+    // TODO: Administrator darf immer ändern, warten auf neue Berechtigungslogik?
+    // Offer should be editable if offer state not equals "Sent", "Won" or "Lost"
+    return status != $KeywordRegistry.offerStatus$won() && status != $KeywordRegistry.offerStatus$lost();
+}
+
 /**
  * Create a new offer and open the offer context in NEW-mode
  */
diff --git a/process/Placeholder_lib/process.js b/process/Placeholder_lib/process.js
index 8b837310b6ff822c9e28911c7227b20ffa5dd5d7..a373b2b34f5eeb33eb79efdbf1a8f8f333c91bca 100644
--- a/process/Placeholder_lib/process.js
+++ b/process/Placeholder_lib/process.js
@@ -37,6 +37,9 @@ PlaceholderUtils.getPlaceholders = function ()
     _addAddressFormat("senderFullAddress", "", Placeholder.targets.SENDER);
     
     _addSqlPart("orgname", "ORGANISATION.NAME");
+    _addSqlPart("firstname", "PERSON.FIRSTNAME");
+    _addSqlPart("lastname", "PERSON.LASTNAME");
+    _addSqlPart("salutation", "PERSON.SALUTATION");
     _addSqlPart("phone", CommUtil.getStandardSubSqlPhone());
     _addSqlPart("email", CommUtil.getStandardSubSqlMail());
     _addSqlPart("name", sqlUtil.concat(["SALUTATION", "TITLE", "FIRSTNAME", "LASTNAME"]));
diff --git a/process/Product_lib/process.js b/process/Product_lib/process.js
index 58fef178569b70fbd9c50fe0a7dc77301937b35d..a12b9218c5ad09f3e8e4229847fb64b4234f69f1 100644
--- a/process/Product_lib/process.js
+++ b/process/Product_lib/process.js
@@ -95,7 +95,7 @@ ProductUtils.getStockCount = function(pid) {
  * 
  * @param {String} pid req ProductID
  * @param {Object} priceListFilter opt { currency: "currencyValue", quantity: "quantityValue", relationId: "relationIdValue (for custom price lists)" }
- * @param {String[]} additionalProductInfoFields additional fields from Product
+ * @param {String[]} additionalProductInfoSubselects additional fields from Product
  *                   They are added to the result with the Fieldname as key. e.g. if the array is ["INFO"] the result will contain the key "INFO"
  * 
  * @example //Product_entity, Field: PRODUCT_ID, Process: onValueChange
@@ -150,15 +150,15 @@ ProductUtils.getStockCount = function(pid) {
  *                   INFO: "the productinfo"
  *               }
  */
-ProductUtils.getProductDetails = function(pid, priceListFilter, additionalProductInfoFields)
+ProductUtils.getProductDetails = function(pid, priceListFilter, additionalProductInfoSubselects)
 {
-    if (additionalProductInfoFields == undefined) {additionalProductInfoFields = []}
+    if (additionalProductInfoSubselects == undefined) {additionalProductInfoSubselects = []}
     var ProductDetails = {};
 
     var cols = [];
     var colsProduct = ["PRODUCT.PRODUCTID", "PRODUCT.PRODUCTNAME", "PRODUCT.GROUPCODEID", "PRODUCT.UNIT"];
     var defaultProductFieldCount = colsProduct.length;
-    colsProduct = colsProduct.concat(additionalProductInfoFields.map(function(item) {return "PRODUCT." + item}));
+    colsProduct = colsProduct.concat(additionalProductInfoSubselects.map(function(item) {return item[1]}));
     
     cols = cols.concat(colsProduct);
 
@@ -229,9 +229,9 @@ ProductUtils.getProductDetails = function(pid, priceListFilter, additionalProduc
                         
             // add additional fields to the details
             var countPos = defaultProductFieldCount;
-            additionalProductInfoFields.forEach(function(productField)
+            additionalProductInfoSubselects.forEach(function(productSubselect)
             {
-                this[productField] = ProductData[i][countPos];
+                this[productSubselect[0]] = ProductData[i][countPos];
                 countPos++;
             }, ProductDetails);
         }
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index ae7bfd7d0836060686f9c879220136c012bb307f..cfb5a109638a20414127ffd5e066d2356ccd774e 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -277,6 +277,13 @@ SqlCondition.prototype.andPrepareVars = function(field, variable, cond, fieldTyp
     return this;
 }
 
+SqlCondition.prototype.andPrepareValue = function(field, value) {
+    if (value) {
+        return this.andPrepare(field, value, null, null);
+    }
+    return this;
+}
+
 /**
  * same as the "orPrepare"-function but with validation of adito-variables functionality
  * @param {String | String[]} field the database field as "tablename.columnname"; e.g. "ORGANISATION.NAME" or as array with column-alias: ["ORGANISATION", "NAME", "myorgAlias"]
@@ -580,6 +587,250 @@ SqlCondition.equalsNot = function(pField, pValue, pAlternativeCond, pAlias) {
     return SqlCondition.begin(pAlias).andPrepare(pField, pValue, "# <> ?").build(pAlternativeCond);
 }
 
+
+/**
+ * Object for building sqls. The main purpose of this is to make it
+ * possible to use SqlCondition objects inside join conditions or sub sqls.
+ * This can also be useful to build complex sqls where parts should be added
+ * dynamically while keeping the code clear.
+ * 
+ * @class
+ */
+function SqlBuilder ()
+{
+    this._query = [];
+}
+
+/**
+ * Alternative way of creating a new SqlBuilder object that allows to use
+ * methods on it directly without having to put brackets around it
+ * 
+ * @return {SqlBuilder} a new SqlBuilder object
+ */
+SqlBuilder.begin = function ()
+{
+    return new SqlBuilder();
+}
+
+/**
+ * Builds the sql and uses db.translateStatement to make a string out of it.
+ * @return {String} the sql as string
+ */
+SqlBuilder.prototype.toString = function ()
+{
+    return db.translateStatement(this.build());
+}
+
+/**
+ * Adds a select clause to the sql.
+ * @param {String|String[]} pFields
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.select = function (pFields)
+{
+    this._append(pFields, "select", true);
+    return this;
+}
+
+/**
+ * Adds a select distinct clause to the sql.
+ * @param {String|String[]} pFields
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.selectDistinct = function (pFields)
+{
+    this._append(pFields, "select distinct", true);
+    return this;
+}
+
+/**
+ * Adds a from clause to the sql.
+ * @param {String} pTable
+ * @param {String} [pAlias] table alias
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.from = function (pTable, pAlias)
+{
+    if (pAlias)
+        pTable += " " + pAlias;
+    this._append(pTable, "from");
+    return this;
+}
+
+/**
+ * Adds a join clause to the sql.
+ * @param {String} pTable
+ * @param {String|String[]} pCondition The where condition. This can be
+ *          a string (without the where keyword) or an array (for prepared queries).
+ * @param {String} [pAlias] table alias
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.join = function (pTable, pCondition, pAlias)
+{
+    var joinStr = "join " + pTable;
+    if (pAlias)
+        joinStr += " " + pAlias;
+    this._append(joinStr + " on");
+    this._append(pCondition);
+    return this;
+}
+
+/**
+ * Adds a left join clause to the sql.
+ * @param {String} pTable
+ * @param {String|String[]} pCondition The where condition. This can be
+ *          a string (without the where keyword) or an array (for prepared queries).
+ * @param {String} [pAlias] table alias
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.leftJoin = function (pTable, pCondition, pAlias)
+{
+    var joinStr = "left join " + pTable;
+    if (pAlias)
+        joinStr += " " + pAlias;
+    this._append(joinStr + " on");
+    this._append(pCondition);
+    return this;
+}
+
+/**
+ * Adds a where clause to the sql.
+ * 
+ * @param {String|String[]} pCondition The where condition. This can be
+ *          a string (without the where keyword) or an array (for prepared queries).
+ *          
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.where = function (pCondition)
+{
+    this._append("where");
+    this._append(pCondition);
+    return this;
+}
+
+/**
+ * Adds a order by clause to the sql.
+ * @param {String} pOrderBy
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.orderBy = function (pOrderBy)
+{
+    this._append(pOrderBy, "order by");
+    return this;
+}
+
+/**
+ * Adds another SqlBuilder object as a subquery.
+ * @param {SqlBuilder} pSubSelect
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.subSelect = function (pSubSelect)
+{
+    this._append(pSubSelect);
+    return this;
+}
+
+/**
+ * Adds a group by clause to the sql.
+ * @param {String|String[]} pFields
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.groupBy = function (pFields)
+{
+    this._append(pFields, "group by", true);
+    return this;
+}
+
+/**
+ * Adds another SqlBuilder object or select string with union.
+ * @param {SqlBuilder|String} pSelect
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.union = function (pSelect)
+{
+    this._append("union");
+    this._append(pSelect);
+    return this;
+}
+
+/**
+ * Adds another SqlBuilder object or select string with union all.
+ * @param {SqlBuilder|String} pSelect
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.unionAll = function (pSelect)
+{
+    this._append("union all");
+    this._append(pSelect);
+    return this;
+}
+
+/**
+ * Adds a having clause to the sql.
+ * 
+ * @param {String|String[]} pCondition The where condition. This can be
+ *          a string (without the where keyword) or an array (for prepared queries).
+ *          
+ * @return {SqlBuilder} current SqlBuilder object
+ */
+SqlBuilder.prototype.having = function (pCondition)
+{
+    this._append("having");
+    this._append(pCondition);
+    return this;
+}
+
+/**
+ * adds an element
+ * 
+ * @param {String|String[]|SqlBuilder} pElement the element to append
+ * @param {String} [pPrefix] string to be added before pElement
+ * @param {Boolean} [pAutoJoin] if this is true and pElement is an array, it will be automatically
+ *                               joined together to a string
+ * 
+ * @private
+ */
+SqlBuilder.prototype._append = function (pElement, pPrefix, pAutoJoin)
+{
+    if (pAutoJoin && pElement && typeof pElement !== "string" && pElement.length !== undefined)
+        pElement = pElement.join(", ");
+    if (pPrefix)
+        pElement = pPrefix + " " + pElement;
+    this._query.push(pPrefix + " " + pElement);
+}
+
+/**
+ * builds a prepared statement out of the object
+ * 
+ * @return {String[]} prepared statement
+ */
+SqlBuilder.prototype.build = function ()
+{
+    var sqlStr = "";
+    var preparedValues = [];
+    
+    for (let i = 0, l = this._query.length; i < l; i++)
+    {
+        let sqlPart = this._query[i];
+        if (sqlPart instanceof SqlBuilder)
+        {
+            let condition = sqlPart.build();
+            sqlPart = "(" + condition[0] + ")";
+            preparedValues = preparedValues.concat(condition[1]);
+        }
+        //array => prepared statement
+        else if (typeof pElement !== "string" && pElement.length === 2 && pElement[1].length !== undefined) 
+        {
+            preparedValues = preparedValues.concat(sqlPart[1]);
+            sqlPart = sqlPart[0];
+        }
+        sqlStr += " " + sqlPart;
+    }
+    return [sqlStr.trim(), preparedValues];
+}
+
+
+
 /**
  *provides functions for masking sql functions
  *
diff --git a/process/sendBulkMail_serverProcess/process.js b/process/sendBulkMail_serverProcess/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..40bd252ef6a43197982835d8211d9b60171115cf
--- /dev/null
+++ b/process/sendBulkMail_serverProcess/process.js
@@ -0,0 +1,22 @@
+import("Sql_lib");
+import("system.db");
+import("system.util");
+import("system.translate");
+import("Bulkmail_lib");
+import("system.vars");
+import("system.notification");
+
+var bulkMailId = vars.get("$local.bulkMailId");
+var user = vars.get("$local.user");
+var res = BulkMailUtils.sendBulkMail(bulkMailId);
+
+if (user)
+{
+    var mailName = db.cell(SqlCondition.begin()
+        .andPrepare("BULKMAIL.BULKMAILID", bulkMailId)
+        .buildSql("select NAME from BULKMAIL")
+    );
+    var message = translate.withArguments("Bulk mail \"%0\" was sent!", [mailName]);
+    var description = translate.withArguments("%0 mails sent sucessfully, %1 mails failed", [res.sucessful, res.failed]);
+    notification.addNotification(util.getNewUUID(), null, null, null, "BulkMailSent", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
+}
\ No newline at end of file
diff --git a/process/sendBulkMail_serverProcess/sendBulkMail_serverProcess.aod b/process/sendBulkMail_serverProcess/sendBulkMail_serverProcess.aod
new file mode 100644
index 0000000000000000000000000000000000000000..eedbd698a37de20e16572ed649bfc21ad97ae355
--- /dev/null
+++ b/process/sendBulkMail_serverProcess/sendBulkMail_serverProcess.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>sendBulkMail_serverProcess</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/sendBulkMail_serverProcess/process.js</process>
+  <variants>
+    <element>EXECUTABLE</element>
+  </variants>
+</process>