diff --git a/.liquibase/Data_alias/basic/2019.1.4/Attributes/AB_ATTRIBUTEUSAGE.xml b/.liquibase/Data_alias/basic/2019.1.4/Attributes/AB_ATTRIBUTEUSAGE.xml
index 97d385d676be03f04ed8321adac32646f2e623b1..f3f612ddd017969474ff83dcfad72790394a0483 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/Attributes/AB_ATTRIBUTEUSAGE.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/Attributes/AB_ATTRIBUTEUSAGE.xml
@@ -516,6 +516,7 @@
       <column name="AB_ATTRIBUTEUSAGEID" value="e79d1096-a2e0-4c4f-acca-2f5976699dcd"/>
       <column name="AB_ATTRIBUTE_ID" value="e73ed929-8631-46de-b28f-eb1423abb808"/>
       <column name="MIN_COUNT" valueNumeric="1"/>
+      <column name="MAX_COUNT" valueNumeric="1"/>
       <column name="OBJECT_TYPE" value="Person"/>
     </insert>
     <insert tableName="AB_ATTRIBUTEUSAGE">
@@ -574,6 +575,7 @@
       <column name="AB_ATTRIBUTEUSAGEID" value="2d2c7f0f-29aa-42e8-88f5-b6234d52e349"/>
       <column name="AB_ATTRIBUTE_ID" value="e73ed929-8631-46de-b28f-eb1423abb808"/>
       <column name="MIN_COUNT" valueNumeric="1"/>
+      <column name="MAX_COUNT" valueNumeric="1"/>
       <column name="OBJECT_TYPE" value="Organisation"/>
     </insert>
     <insert tableName="AB_ATTRIBUTEUSAGE">
diff --git a/.liquibase/Data_alias/basic/2019.1.4/Salesproject_Phase_LongNames.xml b/.liquibase/Data_alias/basic/2019.1.4/Salesproject_Phase_LongNames.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2f5fae70ad39f6302717c63396c499967f66e0e1
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2019.1.4/Salesproject_Phase_LongNames.xml
@@ -0,0 +1,67 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="m.mansour" id="13c8eaf7-39d2-41c0-aff4-9cca30d32422">
+        <insert tableName="AB_KEYWORD_ATTRIBUTE">
+            <column name="AB_KEYWORD_ATTRIBUTEID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="NAME" value="longName"/>
+            <column name="CONTAINER" value="SalesprojectPhase"/>
+            <column name="TYPE" value="CHAR_VALUE"/>
+        </insert>
+
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="4b4045ac-913c-4618-b6be-9458c2094d21"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="b42caac9-8f8f-46e5-9f1c-d121cdf3ad8f"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Not Qualified Contact"/>
+        </insert>
+        
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="b6a9f74b-bfc0-41b5-ac97-48f059cd1051"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="8a2d19c9-bc32-437e-9261-78ed30110e92"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Marketing Accepted Lead"/>
+        </insert>
+        
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="77370a25-7b08-4a75-b09b-ff806c184a12"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="46f55a58-dbe4-40ae-9306-481df9095088"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Marketing Qualified Lead"/>
+        </insert>
+        
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="16fd4267-46d0-4d66-8241-ad620ba359e0"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="afa8cf58-07e8-4ee9-b24e-96cb6fa76aec"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Sales Accepted Lead"/>
+        </insert>
+                
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="846c6387-56b0-45b5-8f4b-71f1177d7c25"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="c9483fb9-c295-43d2-94e0-8c949cf6dc47"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Sales Qualified Offer"/>
+        </insert>
+        
+         <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="4284c1b3-c217-43b5-a06f-462626aadfdc"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="028af5dd-1071-4108-8685-ed7124376706"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Marketing Qualified Contact"/>
+        </insert>
+        
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="945097dd-590f-4c53-bb33-5d425516495e"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="0e8eab64-4c79-4eed-9746-0ac6fc397620"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Offer"/>
+        </insert>
+        
+        <insert tableName="AB_KEYWORD_ATTRIBUTERELATION">
+            <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="440bd4c0-9d2a-4adc-a4ee-15aa8109a265"/>
+            <column name="AB_KEYWORD_ENTRY_ID" value="405e2b7b-20c2-4824-a8b5-c7a533784ef3"/>
+            <column name="AB_KEYWORD_ATTRIBUTE_ID" value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/>
+            <column name="CHAR_VALUE" value="Negotiation"/>
+        </insert>
+    </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2019.1.4/changelog.xml b/.liquibase/Data_alias/basic/2019.1.4/changelog.xml
index 4349d6825ff73baeafd3a7136a97e6c2ce4c779b..4570600ab792eced684c66818796aaa31bd5f502 100644
--- a/.liquibase/Data_alias/basic/2019.1.4/changelog.xml
+++ b/.liquibase/Data_alias/basic/2019.1.4/changelog.xml
@@ -168,4 +168,7 @@
     <include relativeToChangelogFile="true" file="Salesproject_Phase_icons.xml"/>
     
     <include relativeToChangelogFile="true" file="Salesprojectmilestone_add_parent.xml"/>
+    <include relativeToChangelogFile="true" file="Salesproject_Phase_LongNames.xml"/>
+    
+    
 </databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/SALESPROJECT_MILESTONE.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/SALESPROJECT_MILESTONE.xml
index 0ee5288d6e79134eb6547aa58fb41ecf54c8f228..63753bb7742ecf2f273981b04aef739a8e2f0149 100644
--- a/.liquibase/Data_alias/basic/_demoData/generatedData/SALESPROJECT_MILESTONE.xml
+++ b/.liquibase/Data_alias/basic/_demoData/generatedData/SALESPROJECT_MILESTONE.xml
@@ -10,7 +10,7 @@
       <column name="VALUE" value="SALPROJPHASENQC"/>
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
-      <column name="DATE_START" valueDate="2019-05-16T01:34:58"/>
+      <column name="DATE_START" valueDate="2019-06-15T01:34:58"/>
       <column name="SALESPROJECT_ID" value="438537db-0dc6-4aed-b1d1-813011baf88c"/>
       <column name="SALESPROJECT_MILESTONEID" value="ae7fe604-2fea-4aa1-be75-e990e8f31c74"/>
       <column name="TYPE" value="SalesprojectState"/>
@@ -51,7 +51,7 @@
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_END" valueDate="2019-05-23T10:44:48"/>
-      <column name="DATE_START" valueDate="2019-05-17T08:39:38"/>
+      <column name="DATE_START" valueDate="2019-05-10T08:39:38"/>
       <column name="SALESPROJECT_ID" value="d422ad81-717f-42b0-bd64-fc892744aac7"/>
       <column name="SALESPROJECT_MILESTONEID" value="4e764ba9-8f81-4e01-93de-f9769205dd3c"/>
       <column name="TYPE" value="SalesprojectPhase"/>
@@ -66,7 +66,7 @@
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_END" valueDate="2019-05-23T10:44:26"/>
-      <column name="DATE_START" valueDate="2019-05-22T11:51:20"/>
+      <column name="DATE_START" valueDate="2019-05-14T11:51:20"/>
       <column name="SALESPROJECT_ID" value="7e2680f6-a438-45aa-956a-787363f85923"/>
       <column name="SALESPROJECT_MILESTONEID" value="d77a1712-bd57-4d4f-bc58-69ce58f31685"/>
       <column name="TYPE" value="SalesprojectPhase"/>
@@ -81,11 +81,22 @@
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_START" valueDate="2019-05-22T01:42:51"/>
+      <column name="DATE_END" valueDate="2019-06-19T08:08:07"/>
       <column name="SALESPROJECT_ID" value="ef7f4726-4476-4f59-97c2-706dc1e0046f"/>
       <column name="SALESPROJECT_MILESTONEID" value="eff31d24-4434-4b92-9de9-eeb8eb43cb72"/>
       <column name="TYPE" value="SalesprojectPhase"/>
       <column name="VALUE" value="SALPROJPHASESQO"/>
     </insert>
+    
+      <insert tableName="SALESPROJECT_MILESTONE">
+      <column name="DATE_START" valueDate="2019-06-19T08:08:07"/>
+      <column name="PARENT_ID" value="eff31d24-4434-4b92-9de9-eeb8eb43cb72"/>
+      <column name="SALESPROJECT_ID" value="ef7f4726-4476-4f59-97c2-706dc1e0046f"/>
+      <column name="SALESPROJECT_MILESTONEID" value="40512b52-d0f4-4a07-a894-88f72455e700"/>
+      <column name="TYPE" value="SalesprojectPhase"/>
+      <column name="VALUE" value="SALPROJPHASEMAL"/>
+    </insert>
+    
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_START" valueDate="2019-05-22T01:42:51"/>
       <column name="SALESPROJECT_ID" value="ef7f4726-4476-4f59-97c2-706dc1e0046f"/>
@@ -93,9 +104,11 @@
       <column name="TYPE" value="SalesprojectState"/>
       <column name="VALUE" value="SALPROJSTATOPEN"/>
     </insert>
+    
     <insert tableName="SALESPROJECT_MILESTONE">
-      <column name="DATE_END" valueDate="2019-05-23T11:30:09"/>
-      <column name="DATE_START" valueDate="2019-05-23T10:18:10"/>
+      <column name="DATE_END" valueDate="2019-06-15T11:30:09"/>
+      <column name="DATE_START" valueDate="2019-06-01T10:18:10"/>
+      <column name="PARENT_ID" value="b2cb428d-b76b-423a-9b61-04d03213e6d3"/>
       <column name="SALESPROJECT_ID" value="438537db-0dc6-4aed-b1d1-813011baf88c"/>
       <column name="SALESPROJECT_MILESTONEID" value="47999521-d6ea-4a4d-959c-e72776ba5a25"/>
       <column name="TYPE" value="SalesprojectPhase"/>
@@ -103,6 +116,7 @@
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_START" valueDate="2019-05-23T10:44:26"/>
+      <column name="PARENT_ID" value="d77a1712-bd57-4d4f-bc58-69ce58f31685"/>
       <column name="SALESPROJECT_ID" value="7e2680f6-a438-45aa-956a-787363f85923"/>
       <column name="SALESPROJECT_MILESTONEID" value="61f7f5d6-01a6-4088-9387-820cb71ea526"/>
       <column name="TYPE" value="SalesprojectPhase"/>
@@ -110,6 +124,7 @@
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_START" valueDate="2019-05-23T10:44:48"/>
+      <column name="PARENT_ID" value="4e764ba9-8f81-4e01-93de-f9769205dd3c"/>
       <column name="SALESPROJECT_ID" value="d422ad81-717f-42b0-bd64-fc892744aac7"/>
       <column name="SALESPROJECT_MILESTONEID" value="8a33dafb-4a1b-4ec9-a1cd-37a6c75e3721"/>
       <column name="TYPE" value="SalesprojectPhase"/>
@@ -117,6 +132,8 @@
     </insert>
     <insert tableName="SALESPROJECT_MILESTONE">
       <column name="DATE_START" valueDate="2019-05-23T11:30:10"/>
+      <column name="DATE_END" valueDate="2019-06-01T11:30:09"/>
+      <column name="PARENT_ID" value="b2cb428d-b76b-423a-9b61-04d03213e6d3"/>
       <column name="SALESPROJECT_ID" value="438537db-0dc6-4aed-b1d1-813011baf88c"/>
       <column name="SALESPROJECT_MILESTONEID" value="14da1165-ed6c-4f2a-8766-11d3533804cb"/>
       <column name="TYPE" value="SalesprojectPhase"/>
diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/TASK.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/TASK.xml
index aeb8b84043ae3f7d5b4b2be615cb69da6dcc6a61..f90edd2e0c2a4287f37989e817570e532b389278 100644
--- a/.liquibase/Data_alias/basic/_demoData/generatedData/TASK.xml
+++ b/.liquibase/Data_alias/basic/_demoData/generatedData/TASK.xml
@@ -4,7 +4,7 @@
     <insert tableName="TASK">
       <column name="DESCRIPTION" value="Zu offenen Opportunities den Forecast anpassen"/>
       <column name="MATURITY_DATE" valueDate="2019-05-24T09:34:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOLOW"/>
       <column name="PROGRESS" value="TASKPROG0"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
@@ -17,7 +17,7 @@
     <insert tableName="TASK">
       <column name="DESCRIPTION" value="Kunde wollte ein Angebot, hierzu die offenen Posten klären"/>
       <column name="MATURITY_DATE" valueDate="2019-05-15T09:36:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOMEDIUM"/>
       <column name="PROGRESS" value="TASKPROG0"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
@@ -30,7 +30,7 @@
     <insert tableName="TASK">
       <column name="EDITOR_CONTACT_ID" value="4cc98357-25f3-462b-898c-440f9faf4b97"/>
       <column name="MATURITY_DATE" valueDate="2019-05-24T09:38:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOMEDIUM"/>
       <column name="PROGRESS" value="TASKPROG0"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
@@ -43,7 +43,7 @@
     <insert tableName="TASK">
       <column name="DESCRIPTION" value="Kampagnenplanung für dieses Jahr beenden."/>
       <column name="MATURITY_DATE" valueDate="2019-05-22T10:25:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOHIGH"/>
       <column name="PROGRESS" value="TASKPROG0"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
@@ -56,7 +56,7 @@
     <insert tableName="TASK">
       <column name="EDITOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
       <column name="MATURITY_DATE" valueDate="2019-05-29T01:44:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOMEDIUM"/>
       <column name="PROGRESS" value="TASKPROG50"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
@@ -69,7 +69,7 @@
     <insert tableName="TASK">
       <column name="EDITOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
       <column name="MATURITY_DATE" valueDate="2019-05-24T01:46:00"/>
-      <column name="PRIORITY" value="SALPROJPHASESAL"/>
+      <column name="PRIORITY" value="TASKPRIONONE"/>
       <column name="PROGRESS" value="TASKPROG50"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="1a67eaa7-21da-4a18-97ab-755ac5cb74f7"/>
@@ -83,7 +83,7 @@
       <column name="DESCRIPTION" value="Kunde ist sehr interessiert an unserem Produkten, weitere Produktabstimmung intern."/>
       <column name="EDITOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
       <column name="MATURITY_DATE" valueDate="2019-05-29T01:48:00"/>
-      <column name="PRIORITY" value="SALPROJPHASEMQL"/>
+      <column name="PRIORITY" value="TASKPRIOLOW"/>
       <column name="PROGRESS" value="TASKPROG50"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="a2e084e2-d68a-4f1e-a1bb-f8d46ad6293d"/>
@@ -95,7 +95,7 @@
     </insert>
     <insert tableName="TASK">
       <column name="MATURITY_DATE" valueDate="2019-06-21T06:03:00"/>
-      <column name="PRIORITY" value="SALPROJPHASEMQL"/>
+      <column name="PRIORITY" value="TASKPRIOLOW"/>
       <column name="PROGRESS" value="TASKPROG25"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
@@ -108,7 +108,7 @@
     <insert tableName="TASK">
       <column name="DESCRIPTION" value="Strategieevent 2-Tage"/>
       <column name="MATURITY_DATE" valueDate="2019-11-13T06:04:00"/>
-      <column name="PRIORITY" value="SALPROJPHASESAL"/>
+      <column name="PRIORITY" value="TASKPRIOHIGH"/>
       <column name="PROGRESS" value="TASKPROG75"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
@@ -121,7 +121,7 @@
     <insert tableName="TASK">
       <column name="DESCRIPTION" value="Winterreifen draufmachen lassen"/>
       <column name="MATURITY_DATE" valueDate="2019-10-01T06:05:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIONONE"/>
       <column name="PROGRESS" value="TASKPROG0"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="a2e084e2-d68a-4f1e-a1bb-f8d46ad6293d"/>
@@ -134,7 +134,7 @@
     <insert tableName="TASK">
       <column name="DESCRIPTION" value="Preisabstimmung."/>
       <column name="MATURITY_DATE" valueDate="2019-04-05T09:08:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOMEDIUM"/>
       <column name="PROGRESS" value="TASKPROG75"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
@@ -146,7 +146,7 @@
     </insert>
     <insert tableName="TASK">
       <column name="MATURITY_DATE" valueDate="2019-05-30T09:21:00"/>
-      <column name="PRIORITY" value="SALPROJPHASEMQL"/>
+      <column name="PRIORITY" value="TASKPRIOHIGH"/>
       <column name="PROGRESS" value="TASKPROG75"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="d5a2dc64-e503-4aed-a0c6-d54f49b8db87"/>
@@ -158,7 +158,7 @@
     </insert>
     <insert tableName="TASK">
       <column name="MATURITY_DATE" valueDate="2019-05-30T11:50:00"/>
-      <column name="PRIORITY" value="TASKPRIONORMAL"/>
+      <column name="PRIORITY" value="TASKPRIOLOW"/>
       <column name="PROGRESS" value="TASKPROG0"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="c7ddf982-0e58-4152-b82b-8f5673b0b729"/>
@@ -172,7 +172,7 @@
       <column name="DESCRIPTION" value="Es sollen die effizienten Wertschöpfungsketten der Prozessdefinitionseinheiten im primären Schritt gebündelt und sekundär analysiert und verifiziert werden."/>
       <column name="EDITOR_CONTACT_ID" value="ef345d11-a40d-59e0-a24c-afcb6095d2cb"/>
       <column name="MATURITY_DATE" valueDate="2019-01-20T05:00:00"/>
-      <column name="PRIORITY" value="SALPROJPHASEMQL"/>
+      <column name="PRIORITY" value="TASKPRIOHIGH"/>
       <column name="PROTECTIONLEVEL" valueNumeric="0"/>
       <column name="REQUESTOR_CONTACT_ID" value="ef345d11-a40d-59e0-a24c-afcb6095d2cb"/>
       <column name="START_DATE" valueDate="2019-01-20T03:00:00"/>
diff --git a/entity/AddressValidation_entity/AddressValidation_entity.aod b/entity/AddressValidation_entity/AddressValidation_entity.aod
index 14071d6da47fb0c8a577e31c7e6bf4cf590a2533..c1e6c8b8b0cd6493d0110595d69a7b43141dd2b6 100644
--- a/entity/AddressValidation_entity/AddressValidation_entity.aod
+++ b/entity/AddressValidation_entity/AddressValidation_entity.aod
@@ -1,182 +1,204 @@
-<?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>AddressValidation_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <contentTitleProcess>%aditoprj%/entity/AddressValidation_entity/contentTitleProcess.js</contentTitleProcess>
-  <recordContainer>jdito</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>UID</name>
-      <title>Address</title>
-      <description>UID consists of all fields as JSON. </description>
-    </entityField>
-    <entityProvider>
-      <name>ZipValidaton</name>
-      <dependencies>
-        <entityDependency>
-          <name>fcfcbebe-260a-4773-a874-9791b4887ae2</name>
-          <entityName>Address_entity</entityName>
-          <fieldName>ZipValidation</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>Type_param</name>
-          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/zipvalidaton/children/type_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>Type_param</name>
-      <expose v="true" />
-      <mandatory v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityParameter>
-      <name>Country_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityField>
-      <name>COUNTRY</name>
-      <title>Country</title>
-    </entityField>
-    <entityField>
-      <name>ZIP</name>
-      <title>Zip</title>
-    </entityField>
-    <entityField>
-      <name>CITY</name>
-      <title>City</title>
-    </entityField>
-    <entityField>
-      <name>DISTRICT</name>
-      <title>District</title>
-    </entityField>
-    <entityField>
-      <name>REGION</name>
-      <title>Region</title>
-    </entityField>
-    <entityField>
-      <name>STATE</name>
-      <title>${ADDRESS_STATE}</title>
-    </entityField>
-    <entityField>
-      <name>VALUE</name>
-      <description>Final value returned</description>
-    </entityField>
-    <entityProvider>
-      <name>CityValidation</name>
-      <dependencies>
-        <entityDependency>
-          <name>27114db7-8562-43b2-87d8-fa605bbf2319</name>
-          <entityName>Address_entity</entityName>
-          <fieldName>CityValidation</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>Type_param</name>
-          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/cityvalidation/children/type_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>CurrentValue_param</name>
-      <expose v="true" />
-      <description>PARAMETER</description>
-    </entityParameter>
-    <entityProvider>
-      <name>FullAddressValidation</name>
-      <dependencies>
-        <entityDependency>
-          <name>10f700b5-1ac6-4d50-bcb8-aae55714fb43</name>
-          <entityName>Address_entity</entityName>
-          <fieldName>FullAddressValidation</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>Type_param</name>
-          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/fulladdressvalidation/children/type_param/valueProcess.js</valueProcess>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityField>
-      <name>STREET</name>
-      <title>Street</title>
-    </entityField>
-    <entityField>
-      <name>LON</name>
-    </entityField>
-    <entityField>
-      <name>LAT</name>
-    </entityField>
-    <entityField>
-      <name>CITYEXT</name>
-    </entityField>
-    <entityField>
-      <name>BUILDINGNO</name>
-    </entityField>
-  </entityFields>
-  <recordContainers>
-    <jDitoRecordContainer>
-      <name>jdito</name>
-      <jDitoRecordAlias></jDitoRecordAlias>
-      <isFilterable v="true" />
-      <isRequireContainerFiltering v="true" />
-      <isSortable v="true" />
-      <contentProcess>%aditoprj%/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
-      <recordFieldMappings>
-        <jDitoRecordFieldMapping>
-          <name>UID.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>UID.displayValue</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>ZIP.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>CITY.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>CITYEXT.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>COUNTRY.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>DISTRICT.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>REGION.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>STATE.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>STREET.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>BUILDINGNO.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>LON.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>LAT.value</name>
-        </jDitoRecordFieldMapping>
-      </recordFieldMappings>
-    </jDitoRecordContainer>
-  </recordContainers>
-</entity>
+<?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>AddressValidation_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <contentTitleProcess>%aditoprj%/entity/AddressValidation_entity/contentTitleProcess.js</contentTitleProcess>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>UID</name>
+      <title>Address</title>
+      <description>UID consists of all fields as JSON. </description>
+    </entityField>
+    <entityProvider>
+      <name>ZipValidaton</name>
+      <dependencies>
+        <entityDependency>
+          <name>fcfcbebe-260a-4773-a874-9791b4887ae2</name>
+          <entityName>Address_entity</entityName>
+          <fieldName>ZipValidation</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/zipvalidaton/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>Type_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityParameter>
+      <name>Country_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityField>
+      <name>COUNTRY</name>
+      <title>Country</title>
+    </entityField>
+    <entityField>
+      <name>ZIP</name>
+      <title>Zip</title>
+    </entityField>
+    <entityField>
+      <name>CITY</name>
+      <title>City</title>
+    </entityField>
+    <entityField>
+      <name>DISTRICT</name>
+      <title>District</title>
+    </entityField>
+    <entityField>
+      <name>REGION</name>
+      <title>Region</title>
+    </entityField>
+    <entityField>
+      <name>STATE</name>
+      <title>${ADDRESS_STATE}</title>
+    </entityField>
+    <entityField>
+      <name>VALUE</name>
+      <description>Final value returned</description>
+    </entityField>
+    <entityProvider>
+      <name>CityValidation</name>
+      <dependencies>
+        <entityDependency>
+          <name>27114db7-8562-43b2-87d8-fa605bbf2319</name>
+          <entityName>Address_entity</entityName>
+          <fieldName>CityValidation</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/cityvalidation/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>CurrentValue_param</name>
+      <expose v="true" />
+      <description>PARAMETER</description>
+    </entityParameter>
+    <entityProvider>
+      <name>FullAddressValidation</name>
+      <dependencies>
+        <entityDependency>
+          <name>10f700b5-1ac6-4d50-bcb8-aae55714fb43</name>
+          <entityName>Address_entity</entityName>
+          <fieldName>FullAddressValidation</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/fulladdressvalidation/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityField>
+      <name>STREET</name>
+      <title>Street</title>
+    </entityField>
+    <entityField>
+      <name>LON</name>
+    </entityField>
+    <entityField>
+      <name>LAT</name>
+    </entityField>
+    <entityField>
+      <name>CITYEXT</name>
+    </entityField>
+    <entityField>
+      <name>BUILDINGNO</name>
+    </entityField>
+    <entityProvider>
+      <name>StreetValidation</name>
+      <dependencies>
+        <entityDependency>
+          <name>3211d147-0867-4fc1-8640-34a1b8fdcf18</name>
+          <entityName>Address_entity</entityName>
+          <fieldName>StreetValidation</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+      <children>
+        <entityParameter>
+          <name>Type_param</name>
+          <valueProcess>%aditoprj%/entity/AddressValidation_entity/entityfields/streetvalidation/children/type_param/valueProcess.js</valueProcess>
+          <expose v="false" />
+        </entityParameter>
+      </children>
+    </entityProvider>
+    <entityParameter>
+      <name>City_param</name>
+      <expose v="true" />
+    </entityParameter>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <jDitoRecordAlias></jDitoRecordAlias>
+      <isFilterable v="true" />
+      <isRequireContainerFiltering v="true" />
+      <isSortable v="true" />
+      <contentProcess>%aditoprj%/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
+      <recordFieldMappings>
+        <jDitoRecordFieldMapping>
+          <name>UID.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>UID.displayValue</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ZIP.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>CITY.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>CITYEXT.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>COUNTRY.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>DISTRICT.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>REGION.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>STATE.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>STREET.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>BUILDINGNO.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>LON.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>LAT.value</name>
+        </jDitoRecordFieldMapping>
+      </recordFieldMappings>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/AddressValidation_entity/entityfields/streetvalidation/children/type_param/valueProcess.js b/entity/AddressValidation_entity/entityfields/streetvalidation/children/type_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..84ce4d3552f2a616ba448406736d64b2b560825a
--- /dev/null
+++ b/entity/AddressValidation_entity/entityfields/streetvalidation/children/type_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("WsValidation_lib");
+import("system.result");
+
+result.string(WsValidationType.get().TYPE_STREET_NOMINATIM.key);
\ No newline at end of file
diff --git a/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js b/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
index 70bcb62de39fd2d5e04dcdaf5f8bc1689a1342bf..23d093d4cfac35df3f945324673a3718d1f5a2d2 100644
--- a/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/AddressValidation_entity/recordcontainers/jdito/contentProcess.js
@@ -10,6 +10,10 @@ var country = "";
 if (vars.exists("$param.Country_param") && vars.get("$param.Country_param"))
     country = vars.get("$param.Country_param");
 
+var city = "";
+if (vars.exists("$param.City_param") && vars.get("$param.City_param"))
+    city = vars.get("$param.City_param");
+
 // get the value typed by the user
 var filter = "";
 var localFilter = vars.get("$local.filter");
@@ -21,5 +25,5 @@ if(localFilter.filter != null) {
 if (!filter && vars.exists("$param.CurrentValue_param") && vars.get("$param.CurrentValue_param"))
     filter = vars.get("$param.CurrentValue_param");
 
-var foundAddresses = WsValidationUtils.validate(filter, type, country);
+var foundAddresses = WsValidationUtils.validate(filter, type, country, city);
 result.object(foundAddresses);
\ No newline at end of file
diff --git a/entity/Address_entity/Address_entity.aod b/entity/Address_entity/Address_entity.aod
index a792cd32d55c5494cce7b52f26f48e8002e28339..4af02845d6b88a7b1f7554e453cf73a34ff78202 100644
--- a/entity/Address_entity/Address_entity.aod
+++ b/entity/Address_entity/Address_entity.aod
@@ -12,7 +12,15 @@
     <entityField>
       <name>ADDRESS</name>
       <title>Street</title>
+      <consumer>StreetValidation</consumer>
       <mandatoryProcess>%aditoprj%/entity/Address_entity/entityfields/address/mandatoryProcess.js</mandatoryProcess>
+      <textInputAllowed v="true" />
+      <displayValueProcess>%aditoprj%/entity/Address_entity/entityfields/address/displayValueProcess.js</displayValueProcess>
+      <onValueChange>%aditoprj%/entity/Address_entity/entityfields/address/onValueChange.js</onValueChange>
+      <onValueChangeTypes>
+        <element>MASK</element>
+        <element>PROCESS</element>
+      </onValueChangeTypes>
     </entityField>
     <entityField>
       <name>ADDRESSADDITION</name>
@@ -367,6 +375,28 @@
         </entityParameter>
       </children>
     </entityConsumer>
+    <entityConsumer>
+      <name>StreetValidation</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>AddressValidation_entity</entityName>
+        <fieldName>StreetValidation</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>City_param</name>
+          <valueProcess>%aditoprj%/entity/Address_entity/entityfields/streetvalidation/children/city_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>Country_param</name>
+          <valueProcess>%aditoprj%/entity/Address_entity/entityfields/streetvalidation/children/country_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>CurrentValue_param</name>
+          <valueProcess>%aditoprj%/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Address_entity/entityfields/address/displayValueProcess.js b/entity/Address_entity/entityfields/address/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..de2c5e835eaf4fe6dd8b3521b3e17a39c9ac23c1
--- /dev/null
+++ b/entity/Address_entity/entityfields/address/displayValueProcess.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.result");
+
+// needed for instant display name change if value set by neon.setFieldValue
+result.string(vars.get("$this.value"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/address/onValueChange.js b/entity/Address_entity/entityfields/address/onValueChange.js
new file mode 100644
index 0000000000000000000000000000000000000000..5634474c9dabbfeec7a11ee3c23680b765030b4a
--- /dev/null
+++ b/entity/Address_entity/entityfields/address/onValueChange.js
@@ -0,0 +1,3 @@
+import("WsValidation_lib");
+
+WsValidationUtils.setAddressFields();
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js b/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js
index b6d717bf6d0a017888c93e57157690f2e1f44f18..210aab5135161a47229a09613e2ed186ebf9528f 100644
--- a/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js
+++ b/entity/Address_entity/entityfields/cityvalidation/children/currentvalue_param/valueProcess.js
@@ -1,4 +1,4 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.CITY"))
\ No newline at end of file
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$this.value"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/streetvalidation/children/city_param/valueProcess.js b/entity/Address_entity/entityfields/streetvalidation/children/city_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..74c070329cde0f8edeabd0e80677b4105b3e256e
--- /dev/null
+++ b/entity/Address_entity/entityfields/streetvalidation/children/city_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.CITY"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/streetvalidation/children/country_param/valueProcess.js b/entity/Address_entity/entityfields/streetvalidation/children/country_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..41f3b8dc1a9b50c6ae934a4fae1402d699cc87b8
--- /dev/null
+++ b/entity/Address_entity/entityfields/streetvalidation/children/country_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("system.vars");
+
+result.string(vars.get("$field.COUNTRY"));
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js b/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..210aab5135161a47229a09613e2ed186ebf9528f
--- /dev/null
+++ b/entity/Address_entity/entityfields/streetvalidation/children/currentvalue_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$this.value"))
\ No newline at end of file
diff --git a/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js b/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js
index 5b95cc2dbda4676eb8fd41482418b10dcbe6d4e0..210aab5135161a47229a09613e2ed186ebf9528f 100644
--- a/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js
+++ b/entity/Address_entity/entityfields/zipvalidation/children/currentvalue_param/valueProcess.js
@@ -1,4 +1,4 @@
-import("system.vars");
-import("system.result");
-
-result.string(vars.get("$field.ZIP"))
\ No newline at end of file
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$this.value"))
\ No newline at end of file
diff --git a/entity/Attribute_entity/Attribute_entity.aod b/entity/Attribute_entity/Attribute_entity.aod
index 91bf56fb9869f53b9895d847aa70269ce02a8274..d03c5a3316f66a591cd06d6ba377100387e45c49 100644
--- a/entity/Attribute_entity/Attribute_entity.aod
+++ b/entity/Attribute_entity/Attribute_entity.aod
@@ -113,6 +113,7 @@
     </entityParameter>
     <entityConsumer>
       <name>AttributeUsages</name>
+      <stateProcess>%aditoprj%/entity/Attribute_entity/entityfields/attributeusages/stateProcess.js</stateProcess>
       <dependency>
         <name>dependency</name>
         <entityName>AttributeUsage_entity</entityName>
diff --git a/entity/Attribute_entity/entityfields/attributeusages/stateProcess.js b/entity/Attribute_entity/entityfields/attributeusages/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..ce839fd25662eec6b92b1a49076fce4f7eec821d
--- /dev/null
+++ b/entity/Attribute_entity/entityfields/attributeusages/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+import("Attribute_lib");
+
+var state = neon.COMPONENTSTATE_EDITABLE;
+if (vars.get("$field.ATTRIBUTE_TYPE").trim() == $AttributeTypes.COMBOVALUE)
+    state = neon.COMPONENTSTATE_INVISIBLE;
+
+result.string(state);
\ No newline at end of file
diff --git a/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js b/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js
index 1eb2b84b73cf4232f140ac4e8685db124a84a0b7..d47a0319721d5b49a4e57fcce24ca7009dd1fc34 100644
--- a/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/BulkMailAddRecipients_entity/recordcontainers/jdito/onInsert.js
@@ -1,22 +1,7 @@
 import("Bulkmail_lib");
-import("KeywordRegistry_basic");
-import("system.util");
-import("system.db");
-import("Sql_lib");
 import("system.vars");
 
 var contactIds = JSON.parse(vars.getString("$field.recipientContactIds"));
 var bulkMailId = vars.get("$field.BULKMAIL_ID");
 
-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);
+BulkMailUtils.addRecipients(bulkMailId, contactIds);
diff --git a/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js b/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js
index 647d1a9ec4213b06fcfddb8864f62c56fdee732c..727a9813cc00efdebc9871dff07e767a8b14f6d5 100644
--- a/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js
+++ b/entity/BulkMailRecipient_entity/entityfields/contact_id/onValidation.js
@@ -1,19 +1,8 @@
 import("Contact_lib");
 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(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail()))
-    .buildSql("select count(*) = 0 from CONTACT", "1=2");
-
-var noMails = db.cell(query) != "true";
-
-if (noMails)
+if (ContactUtils.hasCommRestriction(ProcessHandlingUtils.getOnValidationValue(), $KeywordRegistry.communicationMediumCampaign$mail()))
     result.string(translate.text("The contact has an advertising ban for emails!"));
\ No newline at end of file
diff --git a/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/colorProcess.js b/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/colorProcess.js
index 6eb15be1ccd1b86ef9dbf1a8790d78d8b7d8c12d..0c478c06f5f0d5bec38a2c6cee2135b21194077d 100644
--- a/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/colorProcess.js
+++ b/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/colorProcess.js
@@ -6,12 +6,7 @@ import("system.vars");
 import("system.neon");
 import("Campaign_lib");
 
-//var commrescolor = CampaignUtils.checkforCommRestrictions();
-                
-var commres = db.cell(SqlCondition.begin()
-                .andPrepareVars("COMMRESTRICTION.CONTACT_ID", "$field.CONTACT_ID")
-                .andPrepareVars("CAMPAIGNSTEP.CAMPAIGNSTEPID", "$field.CAMPAIGNSTEP_ID")
-                .buildSql("select MEDIUM from CAMPAIGNSTEP join COMMRESTRICTION on MEDIUM = STEPMEDIUM", "1=2"));
+var commres = CampaignUtils.checkforCommRestrictions(vars.get("$field.CONTACT_ID"), vars.get("$field.CAMPAIGNSTEP_ID"));
                 
 if(commres)
 {
diff --git a/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/valueProcess.js b/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/valueProcess.js
index 1f772f37e3af1cd60c2539f60dca76895c1963ae..cf69811ac8cbb00ca31d0c3935cae70ddb983c86 100644
--- a/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/valueProcess.js
+++ b/entity/CampaignParticipant_entity/entityfields/advertisingban_icon/valueProcess.js
@@ -1,3 +1,4 @@
+import("system.vars");
 import("system.logging");
 import("system.result");
 import("KeywordRegistry_basic");
@@ -6,8 +7,8 @@ import("Sql_lib");
 import("system.db");
 import("Campaign_lib");
 
-var commres = CampaignUtils.checkforCommRestrictions();
-                
+var commres = CampaignUtils.checkforCommRestrictions(vars.get("$field.CONTACT_ID"), vars.get("$field.CAMPAIGNSTEP_ID"));
+                                
 if(commres)
 {
     var keywordAttributes = KeywordUtils.getAttributeRelationsByKey(commres, $KeywordRegistry.communicationMediumCampaign())
diff --git a/entity/LetterRecipient_entity/LetterRecipient_entity.aod b/entity/LetterRecipient_entity/LetterRecipient_entity.aod
index d0ba00b73763d23f0cdbd697c239d0f115e5c38e..a099305feb249c107cfa9abc15758a6bd847344e 100644
--- a/entity/LetterRecipient_entity/LetterRecipient_entity.aod
+++ b/entity/LetterRecipient_entity/LetterRecipient_entity.aod
@@ -10,15 +10,18 @@
     </entityProvider>
     <entityField>
       <name>LETTERRECIPIENTID</name>
+      <searchable v="false" />
     </entityField>
     <entityField>
       <name>CONTACT_ID</name>
       <title>Contact</title>
       <consumer>Contacts</consumer>
       <linkedContextProcess>%aditoprj%/entity/LetterRecipient_entity/entityfields/contact_id/linkedContextProcess.js</linkedContextProcess>
+      <onValidation>%aditoprj%/entity/LetterRecipient_entity/entityfields/contact_id/onValidation.js</onValidation>
     </entityField>
     <entityProvider>
       <name>SerialLetterRecipients</name>
+      <lookupIdfield>LETTERRECIPIENTID</lookupIdfield>
       <targetContextField>TARGETCONTEXT</targetContextField>
       <targetIdField>CONTACT_ID</targetIdField>
       <dependencies>
@@ -37,6 +40,7 @@
     </entityParameter>
     <entityField>
       <name>SERIALLETTER_ID</name>
+      <searchable v="false" />
       <valueProcess>%aditoprj%/entity/LetterRecipient_entity/entityfields/serialletter_id/valueProcess.js</valueProcess>
     </entityField>
     <entityConsumer>
@@ -50,19 +54,24 @@
     <entityField>
       <name>ICON</name>
       <contentType>IMAGE</contentType>
+      <searchable v="false" />
       <valueProcess>%aditoprj%/entity/LetterRecipient_entity/entityfields/icon/valueProcess.js</valueProcess>
     </entityField>
     <entityField>
       <name>ORGANISATION_ID</name>
+      <searchable v="false" />
     </entityField>
     <entityField>
       <name>PERSON_ID</name>
+      <searchable v="false" />
     </entityField>
     <entityField>
       <name>HASCOMMRESTRICTION</name>
+      <searchable v="false" />
     </entityField>
     <entityField>
       <name>TARGETCONTEXT</name>
+      <searchable v="false" />
     </entityField>
   </entityFields>
   <recordContainers>
diff --git a/entity/LetterRecipient_entity/entityfields/contact_id/onValidation.js b/entity/LetterRecipient_entity/entityfields/contact_id/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c0fb39943a54c11d7c568a7f31e4534095d3d4c
--- /dev/null
+++ b/entity/LetterRecipient_entity/entityfields/contact_id/onValidation.js
@@ -0,0 +1,8 @@
+import("Contact_lib");
+import("system.translate");
+import("system.result");
+import("KeywordRegistry_basic");
+import("Entity_lib");
+
+if (ContactUtils.hasCommRestriction(ProcessHandlingUtils.getOnValidationValue(), $KeywordRegistry.communicationMediumCampaign$letter()))
+    result.string(translate.text("The contact has an advertising ban for letters!"));
\ No newline at end of file
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index df06c88b7a21d3e0f87670c25e2236dc1c998fdc..dcd3bc7164d1a5760ae3b3b45997505d9f6d594b 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -869,8 +869,6 @@
       <onValueChange>%aditoprj%/entity/Offer_entity/entityfields/contact_id/onValueChange.js</onValueChange>
       <onValueChangeTypes>
         <element>MASK</element>
-        <element>PROCESS</element>
-        <element>PROCESS_SETVALUE</element>
       </onValueChangeTypes>
       <onValidation>%aditoprj%/entity/Offer_entity/entityfields/contact_id/onValidation.js</onValidation>
     </entityField>
diff --git a/entity/Offer_entity/entityfields/contact_id/onValueChange.js b/entity/Offer_entity/entityfields/contact_id/onValueChange.js
index 933b3192f785834e9c600315ee2d16465cf50dd8..cc8fab26f942a1a6e83f581c2e9c26bf57b72903 100644
--- a/entity/Offer_entity/entityfields/contact_id/onValueChange.js
+++ b/entity/Offer_entity/entityfields/contact_id/onValueChange.js
@@ -26,5 +26,7 @@ else
 
 if(!vars.get("$param.ObjectRowId_param"))
 {
+   // logging.log(JSON.stringify(vars.get("$local.type"), null, "\t"))
+   // logging.log(JSON.stringify(vars.get("$local.typevalue"), null, "\t"))
     neon.setFieldValue("$field.OBJECT_ROWID", "");
 }
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/object_rowid/stateProcess.js b/entity/Offer_entity/entityfields/object_rowid/stateProcess.js
index 68e51e8c391f18996f9f92aaf3f24453702fd0b3..a69c939f7d40740ebb993eddb54960cdec74d493 100644
--- a/entity/Offer_entity/entityfields/object_rowid/stateProcess.js
+++ b/entity/Offer_entity/entityfields/object_rowid/stateProcess.js
@@ -2,7 +2,7 @@ import("system.neon");
 import("system.result");
 import("system.vars");
 import("Entity_lib");
-
+/*
 switch (vars.get("$sys.recordstate")) 
 {
     case neon.OPERATINGSTATE_NEW:
@@ -15,3 +15,4 @@ switch (vars.get("$sys.recordstate"))
     default:
         result.object(neon.COMPONENTSTATE_READONLY);
 }
+*/
\ No newline at end of file
diff --git a/entity/Offer_entity/entityfields/object_rowid/valueProcess.js b/entity/Offer_entity/entityfields/object_rowid/valueProcess.js
index 752a1b6b75422488d7490688c686a6a5a0d59dc0..29bb85ddce909faec7a1d90bb521f3d129b4b495 100644
--- a/entity/Offer_entity/entityfields/object_rowid/valueProcess.js
+++ b/entity/Offer_entity/entityfields/object_rowid/valueProcess.js
@@ -1,5 +1,8 @@
+import("system.logging");
+import("system.neon");
 import("system.vars");
 import("system.result");
 
-if(vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param"))
-    result.string(vars.get("$param.ObjectRowId_param"));
+logging.log("--- " + JSON.stringify(vars.get("$sys.recordstate"), vars.exists("$param.ObjectRowId_param"), null, "\t"))
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param"))
+    result.string(vars.get("$param.ObjectRowId_param"));
\ No newline at end of file
diff --git a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js
index d2920a905317babb7361c90c0a30f67077543563..7b7bf4c94ca3639b0f3e6acf5c5950eaf5c9fc3b 100644
--- a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js
+++ b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js
@@ -1,3 +1,4 @@
+import("system.logging");
 import("AttributeRegistry_basic");
 import("system.vars");
 import("system.neon");
@@ -20,8 +21,8 @@ if(pid != "" && newQuantity != "")
     
     if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null)
     {
-        vars.set("$field.PRICE", ProductDetails.PriceListToUse.price);
-        vars.set("$field.VAT", ProductDetails.PriceListToUse.vat);
+        neon.setFieldValue("$field.PRICE", ProductDetails.PriceListToUse.price);
+        neon.setFieldValue("$field.VAT", ProductDetails.PriceListToUse.vat);
     }
 }
 
diff --git a/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js b/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js
index ff5074afaa498e940f7e9a557dbc9dda218d012e..60704bc72e12f666589462ef55d7b84b26e5ea63 100644
--- a/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js
+++ b/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js
@@ -5,4 +5,4 @@ import("Offer_lib");
 var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID"));
 
 result.string(oiUtils.roundPrice(oiUtils.getItemSum(vars.get("$field.QUANTITY"), vars.get("$field.PRICE")
-                                , vars.get("$field.DISCOUNT"), vars.get("$field.OPTIONAL"))));
\ No newline at end of file
+                                , vars.get("$field.DISCOUNT"), vars.get("$field.OPTIONAL"))));
diff --git a/entity/Offeritem_entity/grantCreateProcess.js b/entity/Offeritem_entity/grantCreateProcess.js
deleted file mode 100644
index b8e2e7b1a844d2c2449e44ce4249f0d0f9531167..0000000000000000000000000000000000000000
--- a/entity/Offeritem_entity/grantCreateProcess.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("system.result");
-import("Offer_lib");
-
-result.string(OfferUtils.isEditable(vars.get("$param.OfferStatus_param")));
\ No newline at end of file
diff --git a/entity/Offeritem_entity/grantDeleteProcess.js b/entity/Offeritem_entity/grantDeleteProcess.js
index 907809c328cd0899a4a8bb1c088887d5d8d80807..ffba9c3fc52f6376974251a5bf594ba9b5b81992 100644
--- a/entity/Offeritem_entity/grantDeleteProcess.js
+++ b/entity/Offeritem_entity/grantDeleteProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.result");
 import("Offer_lib");
 
-//result.object(OfferUtils.isDeletable(vars.get("$param.OfferStatus_param")) && vars.get("$field.ASSIGNEDTO") == "");
\ No newline at end of file
+result.object(OfferUtils.isDeletable(vars.get("$param.OfferStatus_param")) && vars.get("$field.ASSIGNEDTO") == "");
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 271f6750b8dbfd259995741d731152dd2bbc39bd..b985f968bb922b3d3389c4c70bbd2025e27ca82a 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -832,6 +832,14 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
           <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/addtobulkmailfromtable/onActionProcess.js</onActionProcess>
           <isObjectAction v="false" />
           <isSelectionAction v="true" />
+          <iconId>VAADIN:AT</iconId>
+        </entityActionField>
+        <entityActionField>
+          <name>addToSerialLetter</name>
+          <title>Add to serial letter</title>
+          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/addtoserialletter/onActionProcess.js</onActionProcess>
+          <isObjectAction v="false" />
+          <isSelectionAction v="true" />
           <iconId>VAADIN:ENVELOPES</iconId>
         </entityActionField>
       </children>
diff --git a/entity/Person_entity/entityfields/campaignactiongroup/children/addtoserialletter/onActionProcess.js b/entity/Person_entity/entityfields/campaignactiongroup/children/addtoserialletter/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..3bbd8231ed11dd2906547f569e1463e72561c9bd
--- /dev/null
+++ b/entity/Person_entity/entityfields/campaignactiongroup/children/addtoserialletter/onActionProcess.js
@@ -0,0 +1,6 @@
+import("Bulkmail_lib");
+import("system.vars");
+import("system.neon");
+
+if (vars.exists("$sys.selection"))
+    SerialLetterUtils.openAddRecipientView(vars.getString("$sys.selection"));
\ No newline at end of file
diff --git a/entity/Prod2prod_entity/entityfields/optional/valueProcess.js b/entity/Prod2prod_entity/entityfields/optional/valueProcess.js
index 31b2531af1ad332b9ab67942d5a89d742c9ab368..a26e8321a9bc322bca5ef91f34b4d7628d796ee2 100644
--- a/entity/Prod2prod_entity/entityfields/optional/valueProcess.js
+++ b/entity/Prod2prod_entity/entityfields/optional/valueProcess.js
@@ -2,5 +2,5 @@ import("system.vars");
 import("system.result");
 import("system.neon");
 
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.getString("$this.value"))
     result.string("0");
\ No newline at end of file
diff --git a/entity/Prod2prod_entity/entityfields/takeprice/valueProcess.js b/entity/Prod2prod_entity/entityfields/takeprice/valueProcess.js
index 31b2531af1ad332b9ab67942d5a89d742c9ab368..a26e8321a9bc322bca5ef91f34b4d7628d796ee2 100644
--- a/entity/Prod2prod_entity/entityfields/takeprice/valueProcess.js
+++ b/entity/Prod2prod_entity/entityfields/takeprice/valueProcess.js
@@ -2,5 +2,5 @@ import("system.vars");
 import("system.result");
 import("system.neon");
 
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.getString("$this.value"))
     result.string("0");
\ No newline at end of file
diff --git a/entity/Productprice_entity/Productprice_entity.aod b/entity/Productprice_entity/Productprice_entity.aod
index 365ab1e964aa772acaa354036fb6e707d432266d..cf6936bffcf0e2eed54989c2ece6bfa6eef88e87 100644
--- a/entity/Productprice_entity/Productprice_entity.aod
+++ b/entity/Productprice_entity/Productprice_entity.aod
@@ -4,6 +4,9 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Productprice_entity/documentation.adoc</documentation>
   <title>Prices</title>
+  <siblings>
+    <element>Product_entity</element>
+  </siblings>
   <onValidation>%aditoprj%/entity/Productprice_entity/onValidation.js</onValidation>
   <afterOperatingState>%aditoprj%/entity/Productprice_entity/afterOperatingState.js</afterOperatingState>
   <recordContainer>db</recordContainer>
diff --git a/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod b/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod
index 2e2402e44fa73292fa12ff1840ed36389f8bcbd7..f9e52a10f02e48fab6369c30c61c2ac8ab21fc0a 100644
--- a/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod
+++ b/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod
@@ -147,6 +147,10 @@
       <name>dateEndGantt</name>
       <valueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/dateendgantt/valueProcess.js</valueProcess>
     </entityField>
+    <entityField>
+      <name>valueLongName</name>
+      <valueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js</valueProcess>
+    </entityField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js b/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ae48ddbbb0191c823d743878247074078e201f5
--- /dev/null
+++ b/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js
@@ -0,0 +1,8 @@
+import("system.translate");
+import("system.vars");
+import("system.result");
+import("Keyword_lib")
+
+var keywordAttr = new KeywordAttribute(vars.get("$field.TYPE"), "longName", vars.get("$field.VALUE.displayValue"))
+
+result.string(translate.text(keywordAttr.getValue(vars.get("$field.VALUE"))))
\ No newline at end of file
diff --git a/entity/SerialLetterAddRecipients_entity/SerialLetterAddRecipients_entity.aod b/entity/SerialLetterAddRecipients_entity/SerialLetterAddRecipients_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..6bbe10695fbb4e37b239aaa781d69605f2090e7a
--- /dev/null
+++ b/entity/SerialLetterAddRecipients_entity/SerialLetterAddRecipients_entity.aod
@@ -0,0 +1,51 @@
+<?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>SerialLetterAddRecipients_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <recordContainer>jdito</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>SERIALLETTER_ID</name>
+      <title>Serial letter</title>
+      <consumer>SerialLetters</consumer>
+    </entityField>
+    <entityField>
+      <name>UID</name>
+    </entityField>
+    <entityField>
+      <name>recipientContactIds</name>
+      <valueProcess>%aditoprj%/entity/SerialLetterAddRecipients_entity/entityfields/recipientcontactids/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>recipientCountMessage</name>
+      <valueProcess>%aditoprj%/entity/SerialLetterAddRecipients_entity/entityfields/recipientcountmessage/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>ContactIds_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityConsumer>
+      <name>SerialLetters</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>SerialLetter_entity</entityName>
+        <fieldName>#PROVIDER</fieldName>
+      </dependency>
+    </entityConsumer>
+  </entityFields>
+  <recordContainers>
+    <jDitoRecordContainer>
+      <name>jdito</name>
+      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
+      <onInsert>%aditoprj%/entity/SerialLetterAddRecipients_entity/recordcontainers/jdito/onInsert.js</onInsert>
+      <recordFieldMappings>
+        <jDitoRecordFieldMapping>
+          <name>UID.value</name>
+        </jDitoRecordFieldMapping>
+      </recordFieldMappings>
+    </jDitoRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/SerialLetterAddRecipients_entity/entityfields/recipientcontactids/valueProcess.js b/entity/SerialLetterAddRecipients_entity/entityfields/recipientcontactids/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..24da2511d991a4ba74841744f7fb3df7e07a0821
--- /dev/null
+++ b/entity/SerialLetterAddRecipients_entity/entityfields/recipientcontactids/valueProcess.js
@@ -0,0 +1,21 @@
+import("Contact_lib");
+import("system.result");
+import("Bulkmail_lib");
+import("KeywordRegistry_basic");
+import("system.util");
+import("system.db");
+import("Sql_lib");
+import("system.vars");
+
+var contactIds = JSON.parse(vars.getString("$param.ContactIds_param"));
+var letterId = vars.get("$field.SERIALLETTER_ID");
+
+var existsQuery = "not exists(select LETTERRECIPIENTID from LETTERRECIPIENT where LETTERRECIPIENT.CONTACT_ID = CONTACT.CONTACTID and # = ?)";
+var query = SqlCondition.begin()
+    .andIn("CONTACT.CONTACTID", contactIds)
+    .andPrepare("LETTERRECIPIENT.SERIALLETTER_ID", letterId, existsQuery) //only add contacts that aren't already recipients
+    .andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$letter(), true))  //check if there's a commrestriction
+    .buildSql("select CONTACTID from CONTACT");
+
+contactIds = db.array(db.COLUMN, query); 
+result.string(JSON.stringify(contactIds));
diff --git a/entity/SerialLetterAddRecipients_entity/entityfields/recipientcountmessage/valueProcess.js b/entity/SerialLetterAddRecipients_entity/entityfields/recipientcountmessage/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..498e4d8494c31a112e65d92ac7412856a822b8a8
--- /dev/null
+++ b/entity/SerialLetterAddRecipients_entity/entityfields/recipientcountmessage/valueProcess.js
@@ -0,0 +1,9 @@
+import("system.translate");
+import("system.result");
+import("system.vars");
+
+if (vars.get("$field.SERIALLETTER_ID"))
+{
+    var count = JSON.parse(vars.getString("$field.recipientContactIds")).length;
+    result.string(translate.withArguments("%0 new recipients will be added to the serial letter.", [String(count)]));
+}
\ No newline at end of file
diff --git a/entity/SerialLetterAddRecipients_entity/recordcontainers/jdito/onInsert.js b/entity/SerialLetterAddRecipients_entity/recordcontainers/jdito/onInsert.js
new file mode 100644
index 0000000000000000000000000000000000000000..3afb7c68f28e9a1ca239132f704d76ceece13f40
--- /dev/null
+++ b/entity/SerialLetterAddRecipients_entity/recordcontainers/jdito/onInsert.js
@@ -0,0 +1,7 @@
+import("Bulkmail_lib");
+import("system.vars");
+
+var contactIds = JSON.parse(vars.getString("$field.recipientContactIds"));
+var letterId = vars.get("$field.SERIALLETTER_ID");
+
+SerialLetterUtils.addRecipients(letterId, contactIds);
diff --git a/entity/SerialLetter_entity/SerialLetter_entity.aod b/entity/SerialLetter_entity/SerialLetter_entity.aod
index 7c75673e306c084e6ee3330c040a1d458aa2c1ba..18c8dd3d22f6c7e9f82d77db29b87ba309d07f06 100644
--- a/entity/SerialLetter_entity/SerialLetter_entity.aod
+++ b/entity/SerialLetter_entity/SerialLetter_entity.aod
@@ -4,10 +4,19 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <icon>VAADIN:ENVELOPES</icon>
   <title>Serial letter</title>
+  <contentTitleProcess>%aditoprj%/entity/SerialLetter_entity/contentTitleProcess.js</contentTitleProcess>
   <recordContainer>db</recordContainer>
   <entityFields>
     <entityProvider>
       <name>#PROVIDER</name>
+      <dependencies>
+        <entityDependency>
+          <name>8cb1a355-eb91-414a-8860-0210b18bd1ba</name>
+          <entityName>SerialLetterAddRecipients_entity</entityName>
+          <fieldName>SerialLetters</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
     </entityProvider>
     <entityActionField>
       <name>downloadLetter</name>
@@ -39,6 +48,8 @@
     </entityConsumer>
     <entityField>
       <name>ICON</name>
+      <contentType>IMAGE</contentType>
+      <valueProcess>%aditoprj%/entity/SerialLetter_entity/entityfields/icon/valueProcess.js</valueProcess>
     </entityField>
     <entityConsumer>
       <name>Templates</name>
diff --git a/entity/SerialLetter_entity/contentTitleProcess.js b/entity/SerialLetter_entity/contentTitleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..94f61859cc64100bb6a6dcd445efc67835002c1a
--- /dev/null
+++ b/entity/SerialLetter_entity/contentTitleProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.TITLE"));
\ No newline at end of file
diff --git a/entity/SerialLetter_entity/entityfields/downloadletter/onActionProcess.js b/entity/SerialLetter_entity/entityfields/downloadletter/onActionProcess.js
index dd42c6355440750b5866f9b6d3f65f896a11fbd5..0b4d4abfc7f03b415d5494e33188d75a1a5384d4 100644
--- a/entity/SerialLetter_entity/entityfields/downloadletter/onActionProcess.js
+++ b/entity/SerialLetter_entity/entityfields/downloadletter/onActionProcess.js
@@ -1,3 +1,5 @@
+import("KeywordRegistry_basic");
+import("Contact_lib");
 import("Sql_lib");
 import("system.db");
 import("system.neon");
@@ -7,7 +9,8 @@ import("DocumentTemplate_lib");
 var template = DocumentTemplate.loadTemplate(vars.get("$field.DOCUMENTTEMPLATE_ID"));
 var contactIds = db.table(SqlCondition.begin()
     .andPrepareVars("LETTERRECIPIENT.SERIALLETTER_ID", "$field.SERIALLETTERID")
-    .buildSql("select CONTACT_ID from LETTERRECIPIENT", "1=2")
+    .andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$letter(), true))
+    .buildSql("select CONTACT_ID from LETTERRECIPIENT join CONTACT on LETTERRECIPIENT.CONTACT_ID = CONTACT.CONTACTID", "1=2")
 );
 var document = template.getSerialLetterByContactIds(contactIds);
 if (document)
diff --git a/entity/SerialLetter_entity/entityfields/icon/valueProcess.js b/entity/SerialLetter_entity/entityfields/icon/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f0fc6c65725b4a85d8ca5d8e22a1d4c1c2ada94
--- /dev/null
+++ b/entity/SerialLetter_entity/entityfields/icon/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.string("VAADIN:ENVELOPE");
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 51d9eb1e67cedf91080ed19e9310a6b21f1db901..b34751abfcee0ae87c275c31769dbcbd687548a1 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -4611,6 +4611,9 @@
     <entry>
       <key>Remove recipients with advertising ban</key>
     </entry>
+    <entry>
+      <key>Serial letter</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
   <sqlModels>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index 45d46ddc9536e172a263f912a6a0cbeee8008a7b..0c71e7838339219a1f11db7b2a24fdd55fb3ecaf 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -4660,6 +4660,9 @@
     <entry>
       <key>Remove recipients with advertising ban</key>
     </entry>
+    <entry>
+      <key>Serial letter</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/SerialLetterAddRecipients/SerialLetterAddRecipients.aod b/neonContext/SerialLetterAddRecipients/SerialLetterAddRecipients.aod
new file mode 100644
index 0000000000000000000000000000000000000000..54014f14dd0ea1af8baabeeaee345bc0ce539373
--- /dev/null
+++ b/neonContext/SerialLetterAddRecipients/SerialLetterAddRecipients.aod
@@ -0,0 +1,12 @@
+<?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>SerialLetterAddRecipients</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <entity>SerialLetterAddRecipients_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>8207d6db-d23e-4704-95e9-97474ed971fd</name>
+      <view>SerialLetterAddRecipientsEdit_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonView/AddressList_view/AddressList_view.aod b/neonView/AddressList_view/AddressList_view.aod
index 10eda8020c44b69d04226f9846a42c12d03983e9..b81e84f291f3290332b1d662b2693a7d42bb544d 100644
--- a/neonView/AddressList_view/AddressList_view.aod
+++ b/neonView/AddressList_view/AddressList_view.aod
@@ -16,6 +16,10 @@
       <entityField>#ENTITY</entityField>
       <title></title>
       <columns>
+        <neonTableColumn>
+          <name>dfaa01a1-0b11-4f92-aa18-89f12ebb2db5</name>
+          <entityField>COUNTRY</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>dd514a8b-68b1-4fba-b84e-bc8d8ed708bc</name>
           <entityField>AddressSearch</entityField>
@@ -23,16 +27,12 @@
           <expandRatio v="100" />
         </neonTableColumn>
         <neonTableColumn>
-          <name>dfaa01a1-0b11-4f92-aa18-89f12ebb2db5</name>
-          <entityField>COUNTRY</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>4e5e6a4f-f43e-4861-a912-fb05e576f960</name>
-          <entityField>ADDRESS</entityField>
+          <name>aafc58cf-7dbb-42cb-b04c-d0869e58d09a</name>
+          <entityField>STATE</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>935bcecf-fdd9-4e82-a53f-3c3082c85340</name>
-          <entityField>BUILDINGNO</entityField>
+          <name>29dbb3f5-6f80-4100-aed3-334ac0b9cc48</name>
+          <entityField>REGION</entityField>
         </neonTableColumn>
         <neonTableColumn>
           <name>0336ea99-c4a1-4f39-b5aa-a520a7dcbaab</name>
@@ -43,12 +43,12 @@
           <entityField>CITY</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>aafc58cf-7dbb-42cb-b04c-d0869e58d09a</name>
-          <entityField>STATE</entityField>
+          <name>4e5e6a4f-f43e-4861-a912-fb05e576f960</name>
+          <entityField>ADDRESS</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>29dbb3f5-6f80-4100-aed3-334ac0b9cc48</name>
-          <entityField>REGION</entityField>
+          <name>935bcecf-fdd9-4e82-a53f-3c3082c85340</name>
+          <entityField>BUILDINGNO</entityField>
         </neonTableColumn>
         <neonTableColumn>
           <name>6af52273-25bf-4286-83cc-217aea94ad09</name>
diff --git a/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod b/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
index 1324c689c0cba980289bf61cf94d2b1fec7264bf..50146b13b56946a3de8f2916eecac8b9a576274f 100644
--- a/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
+++ b/neonView/AdressMultiEdit_view/AdressMultiEdit_view.aod
@@ -16,22 +16,22 @@
           <name>2aebe24e-875a-4c57-8461-16da46d6f080</name>
           <entityField>ADDR_TYPE</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>435f10b8-b6ef-4187-bffc-fc6104a6130c</name>
+          <entityField>COUNTRY</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>00300f6f-ac45-4daa-9693-6452da972403</name>
           <entityField>AddressSearch</entityField>
           <width v="100" />
         </neonTableColumn>
         <neonTableColumn>
-          <name>435f10b8-b6ef-4187-bffc-fc6104a6130c</name>
-          <entityField>COUNTRY</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>ac71d5eb-7ce7-41a0-91aa-5594f2238788</name>
-          <entityField>ADDRESS</entityField>
+          <name>66ae75ca-7a5c-4cf0-b768-6c2900f7b7c6</name>
+          <entityField>STATE</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>61261845-740e-4f4b-a1f8-5e6aeac2deba</name>
-          <entityField>BUILDINGNO</entityField>
+          <name>b62515bf-e89d-44a9-94ff-933766657fe5</name>
+          <entityField>REGION</entityField>
         </neonTableColumn>
         <neonTableColumn>
           <name>c1372a93-cf83-4c55-90e6-3b6b352abebf</name>
@@ -43,12 +43,12 @@
           <width v="75" />
         </neonTableColumn>
         <neonTableColumn>
-          <name>66ae75ca-7a5c-4cf0-b768-6c2900f7b7c6</name>
-          <entityField>STATE</entityField>
+          <name>ac71d5eb-7ce7-41a0-91aa-5594f2238788</name>
+          <entityField>ADDRESS</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>b62515bf-e89d-44a9-94ff-933766657fe5</name>
-          <entityField>REGION</entityField>
+          <name>61261845-740e-4f4b-a1f8-5e6aeac2deba</name>
+          <entityField>BUILDINGNO</entityField>
         </neonTableColumn>
         <neonTableColumn>
           <name>443b9d7d-dac2-40b2-bb2b-d5e0091877a9</name>
diff --git a/neonView/LetterRecipientFilter_view/LetterRecipientFilter_view.aod b/neonView/LetterRecipientFilter_view/LetterRecipientFilter_view.aod
index 1492d8eec721663e3f3206d3eb703d1a73b4a394..6acc37c52b2e531da51ab5d9f68a2e218790b9da 100644
--- a/neonView/LetterRecipientFilter_view/LetterRecipientFilter_view.aod
+++ b/neonView/LetterRecipientFilter_view/LetterRecipientFilter_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>LetterRecipientFilter_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="true" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod b/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod
index 40940270b8025b9329988c4ccb7289442ffff1a5..abbe9ef163cf9150c08fba01de3802038836c8f9 100644
--- a/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod
+++ b/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod
@@ -12,7 +12,7 @@
       <name>MilestoneGantt</name>
       <beginDateField>DATE_START</beginDateField>
       <endDateField>dateEndGantt</endDateField>
-      <titleField>VALUE</titleField>
+      <titleField>valueLongName</titleField>
       <uidField>SALESPROJECT_MILESTONEID</uidField>
       <stepPredecessorIdField>PARENT_ID</stepPredecessorIdField>
       <entityField>#ENTITY</entityField>
diff --git a/neonView/SerialLetterAddRecipientsEdit_view/SerialLetterAddRecipientsEdit_view.aod b/neonView/SerialLetterAddRecipientsEdit_view/SerialLetterAddRecipientsEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..a165f4557ebc987c79368e2cdc9e37e8d8d41a08
--- /dev/null
+++ b/neonView/SerialLetterAddRecipientsEdit_view/SerialLetterAddRecipientsEdit_view.aod
@@ -0,0 +1,35 @@
+<?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>SerialLetterAddRecipientsEdit_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>c289afee-ed44-48d7-8f2a-50c1bffb886e</name>
+          <entityField>SERIALLETTER_ID</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+    <genericViewTemplate>
+      <name>Message</name>
+      <hideLabels v="true" />
+      <entityField>#ENTITY</entityField>
+      <fields>
+        <entityFieldLink>
+          <name>ab256925-6375-4b7f-880d-039f6a68ccbc</name>
+          <entityField>recipientCountMessage</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod b/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod
index eded6bf3cd7748e5a866ca10a35b7d11d1493e26..ec75a789d995c138cd146e077e8a856bd83ff9e9 100644
--- a/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod
+++ b/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod
@@ -12,6 +12,10 @@
       <name>Table</name>
       <entityField>#ENTITY</entityField>
       <columns>
+        <neonTableColumn>
+          <name>eb5b36ee-ac45-45f5-ae04-7555d6c984ae</name>
+          <entityField>ICON</entityField>
+        </neonTableColumn>
         <neonTableColumn>
           <name>81088f4a-4ce6-43fc-8dab-7ecf1aec0386</name>
           <entityField>TITLE</entityField>
diff --git a/neonView/SerialLetterPreview_view/SerialLetterPreview_view.aod b/neonView/SerialLetterPreview_view/SerialLetterPreview_view.aod
index 404e6b689d3afd91177b8b1412616ea47f47b40b..65a1512e427dfb5c5c48f1584f0f7f18f5a956c3 100644
--- a/neonView/SerialLetterPreview_view/SerialLetterPreview_view.aod
+++ b/neonView/SerialLetterPreview_view/SerialLetterPreview_view.aod
@@ -10,6 +10,7 @@
   <children>
     <cardViewTemplate>
       <name>Card</name>
+      <iconField>ICON</iconField>
       <titleField>TITLE</titleField>
       <entityField>#ENTITY</entityField>
     </cardViewTemplate>
diff --git a/neonView/SupportTicketFilter_view/SupportTicketFilter_view.aod b/neonView/SupportTicketFilter_view/SupportTicketFilter_view.aod
index d44a603556eb227bf6d617ad7a74a91605cdea8d..a49cf96bd1f937203c5696074fed44af7a07a716 100644
--- a/neonView/SupportTicketFilter_view/SupportTicketFilter_view.aod
+++ b/neonView/SupportTicketFilter_view/SupportTicketFilter_view.aod
@@ -36,7 +36,7 @@
       <name>TicketsTimeline</name>
       <favoriteActionGroup1>tableActions</favoriteActionGroup1>
       <dateField>TASK_MATURITY_DATE</dateField>
-      <titleField>TASK_SUBJECT</titleField>
+      <titleField>TASK_SUBJECT_DETAILS</titleField>
       <descriptionField>TASK_DESCRIPTION</descriptionField>
       <iconIdField>TASK_PRIORITY_ICON</iconIdField>
       <entityField>#ENTITY</entityField>
diff --git a/process/Bulkmail_lib/process.js b/process/Bulkmail_lib/process.js
index 093a22f3a7801bb527887d1c5b845024cb195152..48a86f98145d53a3fcc52d5fd774554ad5dc9c6a 100644
--- a/process/Bulkmail_lib/process.js
+++ b/process/Bulkmail_lib/process.js
@@ -1,3 +1,4 @@
+import("system.util");
 import("Contact_lib");
 import("system.datetime");
 import("system.neon");
@@ -11,7 +12,7 @@ import("Email_lib");
 import("system.process");
 
 /**
- * functions for bulk mails and serial letters
+ * functions for bulk mails
  */
 function BulkMailUtils () {}
 
@@ -38,7 +39,7 @@ BulkMailUtils.sendBulkMailOnServer = function (pBulkMailId, 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
+ * @param {String} pBulkMailId id of the bulk mail 
  * 
  * @return {Object} count of sucessful and failed mails 
  */
@@ -119,12 +120,64 @@ BulkMailUtils.openAddRecipientView = function (pContactIds)
     neon.openContext("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
 }
 
-BulkMailUtils.removeCommRestrictionRecipients = function ()
+BulkMailUtils.removeCommRestrictionRecipients = function (pBulkMailId)
 {
-    
+    var recipientIds = db.array(db.COLUMN, SqlBuilder.begin()
+        .select("BULKMAILRECIPIENTID")
+        .from("BULKMAILRECIPIENT")
+        .join("CONTACT", SqlCondition.begin()
+            .and("BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
+            .andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail())))
+        .where(SqlCondition.begin()
+            .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId))
+        .build());
+
+    if (recipientIds.length)
+    {
+        db.deleteData("BULKMAILRECIPIENT", SqlCondition.begin()
+            .andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", recipientIds)
+            .build("1=2"));
+    }
 }
 
-BulkMailUtils.addRecipients = function (pContactIds)
+BulkMailUtils.addRecipients = function (pBulkMailId, pContactIds)
 {
-    
+    var columns = [
+        "BULKMAILRECIPIENTID",
+        "BULKMAIL_ID",
+        "CONTACT_ID",
+        "STATUS"
+    ];
+    var inserts = [];
+    for (let i = 0, l = pContactIds.length; i < l; i++)
+    {
+        inserts.push(["BULKMAILRECIPIENT", columns, null, [util.getNewUUID(), pBulkMailId, pContactIds[i], $KeywordRegistry.bulkMailRecipientStatus$pending()]]);
+    }
+    db.inserts(inserts);
+}
+
+function SerialLetterUtils () {}
+
+SerialLetterUtils.addRecipients = function (pBulkMailId, pContactIds)
+{
+    var columns = [
+        "LETTERRECIPIENTID",
+        "SERIALLETTER_ID",
+        "CONTACT_ID"
+    ];
+    var inserts = [];
+    for (let i = 0, l = pContactIds.length; i < l; i++)
+    {
+        inserts.push(["LETTERRECIPIENT", columns, null, [util.getNewUUID(), pBulkMailId, pContactIds[i]]]);
+    }
+    db.inserts(inserts);
+}
+
+
+SerialLetterUtils.openAddRecipientView = function (pContactIds)
+{
+    var params = {
+        "ContactIds_param" : pContactIds
+    };
+    neon.openContext("SerialLetterAddRecipients", "SerialLetterAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
 }
\ No newline at end of file
diff --git a/process/Campaign_lib/process.js b/process/Campaign_lib/process.js
index d9368a36af46248b49cb9656a0c3ac69aaa65656..873f2b92835c55dfba0a4be3566eb75d23af2971 100644
--- a/process/Campaign_lib/process.js
+++ b/process/Campaign_lib/process.js
@@ -288,11 +288,11 @@ CampaignUtils.updateCampaignStep = function(pCampaignStepId, pDateStart, pDateEn
     
     db.updateData("CAMPAIGNSTEP", columnsToUpdate, null, newValues, campaignStepIdCondition)
 }
-CampaignUtils.checkforCommRestrictions = function()
+CampaignUtils.checkforCommRestrictions = function(contactid, campaignstepid)
 {
     return db.cell(SqlCondition.begin()
-                .andPrepareVars("COMMRESTRICTION.CONTACT_ID", "$field.CONTACT_ID")
-                .andPrepareVars("CAMPAIGNSTEP.CAMPAIGNSTEPID", "$field.CAMPAIGNSTEP_ID")
+                .andPrepare("COMMRESTRICTION.CONTACT_ID", contactid)
+                .andPrepare("CAMPAIGNSTEP.CAMPAIGNSTEPID", campaignstepid)
                 .buildSql("select MEDIUM from CAMPAIGNSTEP join COMMRESTRICTION on MEDIUM = STEPMEDIUM", "1=2"));
 }
 
diff --git a/process/Contact_lib/process.js b/process/Contact_lib/process.js
index 2c6081ff585f6d2af5ff7d02e7a8ab9fad69ce05..63a47219b9f5b47f3d95e6dceae2970d9ad83cfd 100644
--- a/process/Contact_lib/process.js
+++ b/process/Contact_lib/process.js
@@ -442,6 +442,25 @@ ContactUtils.getCommRestrictionCondition = function (pMedium, pNoRestriction, pS
     return SqlCondition.begin().andSqlBuilder(existsQuery, cond);
 }
 
+/**
+ * checks if a contact has a commrestriction
+ * 
+ * @param {String} pContactId contact id
+ * @param {String} pMedium medium to check
+ * @param {String|Number} [pStartDate=current date] the start date of the commrestriction
+ * 
+ * @return {Boolean} true, if the contact has a commrestriction, otherwise false
+ */
+ContactUtils.hasCommRestriction = function (pContactId, pMedium, pStartDate)
+{
+    var query = SqlCondition.begin()
+        .andPrepare("CONTACT.CONTACTID", pContactId)
+        .andSqlCondition(ContactUtils.getCommRestrictionCondition(pMedium, false, pStartDate))
+        .buildSql("select count(*) = 0 from CONTACT", "1=2");
+
+    return db.cell(query) != "true";
+}
+
 /**
  * object for handling of a single contact
  * provides static- and instance-functions
diff --git a/process/WsValidation_lib/process.js b/process/WsValidation_lib/process.js
index 0f34bcf034364414e9877eb649cb7608060926e7..13acd375e1b1fa4a647e5fd0d7195370f6c72d21 100644
--- a/process/WsValidation_lib/process.js
+++ b/process/WsValidation_lib/process.js
@@ -42,6 +42,7 @@ WsValidationType.get = function(pKey)
             TYPE_ADDRESS_NOMINATIM: new WsValidationType("TYPE_ADDRESS_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "q"),
             TYPE_ZIP_NOMINATIM: new WsValidationType("TYPE_ZIP_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "postalcode"),
             TYPE_CITY_NOMINATIM: new WsValidationType("TYPE_CITY_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "city"),
+            TYPE_STREET_NOMINATIM: new WsValidationType("TYPE_STREET_NOMINATIM", "nominatim", _processNominatimAddressLookup, _nominatimRequest, "street"),
             
             // Communication validation
             TYPE_PHONE: new WsValidationType("TYPE_PHONE", "phoneValidation", _processCommunicationValidation, _customRequest, "Number")
@@ -156,7 +157,7 @@ WsValidationType.get = function(pKey)
         return this.processResultCallback.call(this, null, pValue);
     }
     
-    function _nominatimRequest(pValue, pCountry)
+    function _nominatimRequest(pValue, pCountry, pCity)
     {
         var nominatimCache;
         if (WsValidationUtils.isWsEnabled(this))
@@ -174,13 +175,13 @@ WsValidationType.get = function(pKey)
                 nominatimCache = JSON.parse(vars.getString("$context.nominatim"));
             }
             
-            if (nominatimCache.last == parameterName + pValue + (pCountry ? pCountry : ""))
+            if (nominatimCache.last == parameterName + pValue + (pCountry ? pCountry : "") +  (pCity ? pCity : "") )
             {
                 return nominatimCache.data;
             }
             else
             {
-                nominatimCache.last = parameterName + pValue + (pCountry ? pCountry : "")
+                nominatimCache.last = parameterName + pValue + (pCountry ? pCountry : "") + (pCity ? pCity : "")
 
                 var url = project.getPreferenceValue("custom." + this.webserviceName + ".url");
 
@@ -206,6 +207,10 @@ WsValidationType.get = function(pKey)
                     {
                         restConf.addQueryParameter("countrycodes", pCountry)
                     }
+                    if (pCity)
+                    {
+                        restConf.addQueryParameter("city", pCity)
+                    }
 
                     restConf.addQueryParameter(parameterName, pValue)
 
@@ -247,17 +252,18 @@ function WsValidationUtils() {}
  * validate the value with the webservice
  * @param {String} pValue to search for
  * @param {WsValidationType|String} pType type used for the search. Can be an WsValidationType or the key of the WsValidationType
- * @param {String} pCountry needed by the webservice e.g. "DE"
+ * @param {String} pCountry needed by some webservices e.g. "DE"
+ * @param {String} pCity needed by some webservices e.g. "Landshut"
  * 
  * @return {object} this is different, based on which webservice-type is used
  */
-WsValidationUtils.validate = function(pValue, pType, pCountry)
+WsValidationUtils.validate = function(pValue, pType, pCountry, pCity)
 {
     // get WsValidationType-Object if it is only the key
     if (typeof pType == "string")
         pType = WsValidationType.get(pType);
     
-    return pType.processRequestCallback.call(pType, pValue, pCountry)
+    return pType.processRequestCallback.call(pType, pValue, pCountry, pCity)
 }
 
 /**
@@ -290,8 +296,7 @@ WsValidationUtils.setAddressFields = function(pFieldToSetToValue)
     
     function _setField(pField, pValue)
     {
-        if (pValue)
-            neon.setFieldValue(pField, pValue);
+        neon.setFieldValue(pField, pValue);
     }
 }