diff --git a/.liquibase/Data_alias/basic/2020.0.1/WorkflowSignal/create_WorkflowSignal.xml b/.liquibase/Data_alias/basic/2020.0.1/WorkflowSignal/create_WorkflowSignal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca188068504f512ef0e5c4ee9b52a9a37495dfae
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2020.0.1/WorkflowSignal/create_WorkflowSignal.xml
@@ -0,0 +1,16 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="s.listl" id="18da4f91-3334-47c6-958d-6d0efce52d31">
+        <createTable tableName="WORKFLOWSIGNAL">
+            <column name="WORKFLOWSIGNALID" type="CHAR(36)">
+                <constraints primaryKey="true" primaryKeyName="PK_WORKFLOWSIGNALID"/>
+            </column>
+            <column name="SIGNAL_NAME" type="VARCHAR(255)"/>
+            <column name="OBJECT_TYPE" type="VARCHAR(63)"/>
+            <column name="TRIGGER_EVENT" type="CHAR(36)"/>
+            <column name="PROCESSDEFINITION_KEY" type="VARCHAR(255)"/>
+            <column name="OBJECT_CONDITION" type="NVARCHAR(512)"/>
+        </createTable>
+    </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2020.0.1/changelog.xml b/.liquibase/Data_alias/basic/2020.0.1/changelog.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c3105c90b71f48e03afbe5a3771cbaaa080040da
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2020.0.1/changelog.xml
@@ -0,0 +1,5 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <include file="WorkflowSignal/create_WorkflowSignal.xml" relativeToChangelogFile="true"/>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/documenttemplate.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/documenttemplate.xml
index 8933f0a8440eca284e5f3be7e923a82d4e2875d2..e0c4c76db3132fde71e8bb7414d0a9d13cad7e5d 100644
--- a/.liquibase/Data_alias/basic/_demoData/generatedData/documenttemplate.xml
+++ b/.liquibase/Data_alias/basic/_demoData/generatedData/documenttemplate.xml
@@ -72,7 +72,7 @@
       <column name="DOCUMENTTEMPLATEID" value="9106d24f-8afc-491d-8309-ea20377466ac"/>
       <column name="ISOLANGUAGE" value="deu"/>
       <column name="KIND" value="TEX"/>
-      <column name="NAME" value="Angebotskopftext mit Dank"/>
+      <column name="NAME" value="Angebotsfußtext mit Dank"/>
       <column name="USER_NEW" value="Admin"/>
     </insert>
     <insert tableName="documenttemplate">
diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/salutation.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/salutation.xml
index c15cc52a882a34dc5154561cda39681ec71a9997..e7537efd60b1b160c4b39e5000410371a5caa391 100644
--- a/.liquibase/Data_alias/basic/_demoData/generatedData/salutation.xml
+++ b/.liquibase/Data_alias/basic/_demoData/generatedData/salutation.xml
@@ -50,6 +50,16 @@
       <column name="SEX" value="m"/>
       <column name="SORT" valueNumeric="15"/>
       <column name="TITLE" value="Prof. Dr."/>
+    </insert>
+        <insert tableName="salutation">
+      <column name="HEADLINE" value="Frau Prof. Dr. {fn} {ln}"/>
+      <column name="ISOLANGUAGE" value="deu"/>
+      <column name="LETTERSALUTATION" value="Sehr geehrte Frau Professorin"/>
+      <column name="SALUTATION" value="Frau"/>
+      <column name="SALUTATIONID" value="e8549204-4735-11ea-b77f-2e728ce88125"/>
+      <column name="SEX" value="f"/>
+      <column name="SORT" valueNumeric="7"/>
+      <column name="TITLE" value="Prof. Dr."/>
     </insert>
     <insert tableName="salutation">
       <column name="HEADLINE" value="Madame {fn} {ln}"/>
@@ -100,6 +110,16 @@
       <column name="SORT" valueNumeric="14"/>
       <column name="TITLE" value="Präsident"/>
     </insert>
+    <insert tableName="salutation">
+      <column name="HEADLINE" value="Frau Präsidentin {fn} {ln}"/>
+      <column name="ISOLANGUAGE" value="deu"/>
+      <column name="LETTERSALUTATION" value="Sehr geehrte Frau Präsidentin"/>
+      <column name="SALUTATION" value="Frau"/>
+      <column name="SALUTATIONID" value="e8549614-4735-11ea-b77f-2e728ce88125"/>
+      <column name="SEX" value="f"/>
+      <column name="SORT" valueNumeric="33"/>
+      <column name="TITLE" value="Präsidentin"/>
+    </insert>
     <insert tableName="salutation">
       <column name="HEADLINE" value="Madame Dr.{fn} {ln}"/>
       <column name="ISOLANGUAGE" value="fra"/>
@@ -140,6 +160,16 @@
       <column name="SORT" valueNumeric="12"/>
       <column name="TITLE" value="Professor"/>
     </insert>
+    <insert tableName="salutation">
+      <column name="HEADLINE" value="Frau Professor {fn} {ln}"/>
+      <column name="ISOLANGUAGE" value="deu"/>
+      <column name="LETTERSALUTATION" value="Sehr geehrte Frau Professorin"/>
+      <column name="SALUTATION" value="Frau"/>
+      <column name="SALUTATIONID" value="e85494ac-4735-11ea-b77f-2e728ce88125"/>
+      <column name="SEX" value="f"/>
+      <column name="SORT" valueNumeric="32"/>
+      <column name="TITLE" value="Professorin"/>
+    </insert>
     <insert tableName="salutation">
       <column name="HEADLINE" value="Monsieur Prof.{fn} {ln}"/>
       <column name="ISOLANGUAGE" value="fra"/>
@@ -215,6 +245,16 @@
       <column name="SORT" valueNumeric="2"/>
       <column name="TITLE" value="Bürgermeister"/>
     </insert>
+    <insert tableName="salutation">
+      <column name="HEADLINE" value="Frau Bürgermeisterin {fn} - {ln}"/>
+      <column name="ISOLANGUAGE" value="deu"/>
+      <column name="LETTERSALUTATION" value="Sehr geehrte Frau Bürgermeisterin"/>
+      <column name="SALUTATION" value="Frau"/>
+      <column name="SALUTATIONID" value="e8549740-4735-11ea-b77f-2e728ce88125"/>
+      <column name="SEX" value="f"/>
+      <column name="SORT" valueNumeric="34"/>
+      <column name="TITLE" value="Bürgermeisterin"/>
+    </insert>
     <insert tableName="salutation">
       <column name="HEADLINE" value="Monsieur {fn} {ln}"/>
       <column name="ISOLANGUAGE" value="fra"/>
diff --git a/.liquibase/Data_alias/changelog.xml b/.liquibase/Data_alias/changelog.xml
index cc63bd025f48c03b71ce2b6d2613b52871996905..cc2f1fb471786b8918923569570fca173bbf091f 100644
--- a/.liquibase/Data_alias/changelog.xml
+++ b/.liquibase/Data_alias/changelog.xml
@@ -8,6 +8,7 @@
     <include relativeToChangelogFile="true" file="basic/2019.3.2/changelog.xml"/>
     <include relativeToChangelogFile="true" file="basic/2019.3.3/changelog.xml"/>
     <include relativeToChangelogFile="true" file="basic/2020.0.0/changelog.xml"/>
+    <include relativeToChangelogFile="true" file="basic/2020.0.1/changelog.xml"/>
     
     <!--enable this only when you definetly want to overwrite the existing data with demo records:--> 
     <!--<include relativeToChangelogFile="true" file="basic/_demoData/changelog.xml" context="example"/>-->
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/changelog.xml b/.liquibase/_____SYSTEMALIAS/basic/_demoData/changelog.xml
index 530a16f329daea165aa6844714d15e573ac4bbf6..b5343af53ceb54f5d12f2de963e846fec8afac18 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/_demoData/changelog.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/changelog.xml
@@ -9,4 +9,6 @@
     <include relativeToChangelogFile="true" file="example_asys_users/Herbert_Obermeier.xml"/>
     <include relativeToChangelogFile="true" file="example_asys_users/Lisa_Sommer.xml"/>
     <include relativeToChangelogFile="true" file="example_asys_users/Susanne_Lustig.xml"/>
+    
+    <include relativeToChangelogFile="true" file="example_workflows/OfferCheck.xml"/>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY.xml b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8c57c1502c1fe15b33856c742dd297ded402f722
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY.xml
@@ -0,0 +1,24 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+  <changeSet author="s.listl" id="3c10fdd02a8ab6b4e351080ca76bf710">
+    <preConditions onFail="CONTINUE">
+        <tableExists tableName="ACT_GE_BYTEARRAY"/>
+    </preConditions>
+    <insert tableName="ACT_GE_BYTEARRAY">
+      <column name="ID_" value="2"/>
+      <column name="DEPLOYMENT_ID_" value="1"/>
+      <column name="GENERATED_" valueNumeric="0"/>
+      <column name="REV_" valueNumeric="1"/>
+      <column name="BYTES_" valueBlobFile="ACT_GE_BYTEARRAY/BYTES_/blobFiles/a01ad77d7c18c3d6ea3b6142c270fa83"/>
+      <column name="NAME_" value="offerVerification_neubpmn20.xml"/>
+    </insert>
+    <insert tableName="ACT_GE_BYTEARRAY">
+      <column name="ID_" value="3"/>
+      <column name="DEPLOYMENT_ID_" value="1"/>
+      <column name="GENERATED_" valueNumeric="1"/>
+      <column name="REV_" valueNumeric="1"/>
+      <column name="BYTES_" valueBlobFile="ACT_GE_BYTEARRAY/BYTES_/blobFiles/cd7557c02d22c531ca4fffb99e7d7609"/>
+      <column name="NAME_" value="offerVerification_neuofferVerification_neu.png"/>
+    </insert>
+  </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY/BYTES_/blobFiles/a01ad77d7c18c3d6ea3b6142c270fa83 b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY/BYTES_/blobFiles/a01ad77d7c18c3d6ea3b6142c270fa83
new file mode 100644
index 0000000000000000000000000000000000000000..2656dbe0f41979ef8354ae36c718965faa34fc77
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY/BYTES_/blobFiles/a01ad77d7c18c3d6ea3b6142c270fa83
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
+  <process id="offerVerification_neu" name="Angebotsprüfung_neu" isExecutable="true">
+    <dataObject id="sum" name="sum" itemSubjectRef="xsd:int"></dataObject>
+    <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
+    <userTask id="verification" name="Angebot freigeben" flowable:formFieldValidation="true">
+      <extensionElements>
+        <flowable:formProperty id="approved" name="Freigabe" type="boolean" required="true"></flowable:formProperty>
+      </extensionElements>
+    </userTask>
+    <serviceTask id="sid-CC87EC6A-DEAC-4037-8C9E-DF9D4578227E" name="Angebot aktualisieren" flowable:class="de.adito.aditoweb.server.neon.workflow.WorkflowServiceTask">
+      <extensionElements>
+        <flowable:field name="jditoProcess">
+          <flowable:string><![CDATA[UpdateOffer_workflowService]]></flowable:string>
+        </flowable:field>
+      </extensionElements>
+    </serviceTask>
+    <endEvent id="sid-C0495BDF-7F36-4270-AD93-A1F4877DED25"></endEvent>
+    <sequenceFlow id="sid-E2FF58FD-02C1-42DE-ADD8-FC211E5C0A00" sourceRef="sid-CC87EC6A-DEAC-4037-8C9E-DF9D4578227E" targetRef="sid-C0495BDF-7F36-4270-AD93-A1F4877DED25"></sequenceFlow>
+    <exclusiveGateway id="sid-C15C35AB-CFCD-4D69-9CCF-98ED4F8C8155"></exclusiveGateway>
+    <sequenceFlow id="sid-78F2A2E7-D8F9-47B9-8B27-ECAE653D9A4F" sourceRef="verification" targetRef="sid-CC87EC6A-DEAC-4037-8C9E-DF9D4578227E"></sequenceFlow>
+    <sequenceFlow id="sid-BE050925-7B3F-4895-B1DE-3CD54543D021" sourceRef="sid-C15C35AB-CFCD-4D69-9CCF-98ED4F8C8155" targetRef="verification">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${sum > 1000}]]></conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-C5DDB6C6-6497-40EB-899A-9413ADFEC75B" sourceRef="sid-C15C35AB-CFCD-4D69-9CCF-98ED4F8C8155" targetRef="sid-CC87EC6A-DEAC-4037-8C9E-DF9D4578227E">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${sum < 1001}]]></conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-168B4904-364F-420F-9DAF-39EA1C0F879F" sourceRef="startEvent1" targetRef="sid-C15C35AB-CFCD-4D69-9CCF-98ED4F8C8155"></sequenceFlow>
+  </process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_offerVerification_neu">
+    <bpmndi:BPMNPlane bpmnElement="offerVerification_neu" id="BPMNPlane_offerVerification_neu">
+      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
+        <omgdc:Bounds height="30.0" width="30.0" x="725.0000000000003" y="450.00000000000006"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="verification" id="BPMNShape_verification">
+        <omgdc:Bounds height="80.0" width="99.99999999999994" x="450.00000000000006" y="138.00000000000014"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="sid-CC87EC6A-DEAC-4037-8C9E-DF9D4578227E" id="BPMNShape_sid-CC87EC6A-DEAC-4037-8C9E-DF9D4578227E">
+        <omgdc:Bounds height="80.0" width="100.0" x="690.0000000000001" y="138.00000000000003"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="sid-C0495BDF-7F36-4270-AD93-A1F4877DED25" id="BPMNShape_sid-C0495BDF-7F36-4270-AD93-A1F4877DED25">
+        <omgdc:Bounds height="28.0" width="28.0" x="915.0000000000001" y="164.0000000000001"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="sid-C15C35AB-CFCD-4D69-9CCF-98ED4F8C8155" id="BPMNShape_sid-C15C35AB-CFCD-4D69-9CCF-98ED4F8C8155">
+        <omgdc:Bounds height="40.0" width="40.0" x="720.0000000000002" y="330.0000000000001"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge bpmnElement="sid-C5DDB6C6-6497-40EB-899A-9413ADFEC75B" id="BPMNEdge_sid-C5DDB6C6-6497-40EB-899A-9413ADFEC75B">
+        <omgdi:waypoint x="740.0000000000002" y="330.0000000000001"></omgdi:waypoint>
+        <omgdi:waypoint x="740.0000000000001" y="217.95000000000005"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="sid-168B4904-364F-420F-9DAF-39EA1C0F879F" id="BPMNEdge_sid-168B4904-364F-420F-9DAF-39EA1C0F879F">
+        <omgdi:waypoint x="740.0000000000003" y="450.00000000000006"></omgdi:waypoint>
+        <omgdi:waypoint x="740.0000000000002" y="369.90863794604013"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="sid-BE050925-7B3F-4895-B1DE-3CD54543D021" id="BPMNEdge_sid-BE050925-7B3F-4895-B1DE-3CD54543D021">
+        <omgdi:waypoint x="500.0" y="350.0"></omgdi:waypoint>
+        <omgdi:waypoint x="500.0" y="350.0"></omgdi:waypoint>
+        <omgdi:waypoint x="500.0" y="217.95000000000016"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="sid-E2FF58FD-02C1-42DE-ADD8-FC211E5C0A00" id="BPMNEdge_sid-E2FF58FD-02C1-42DE-ADD8-FC211E5C0A00">
+        <omgdi:waypoint x="789.9499999998825" y="178.00000000000009"></omgdi:waypoint>
+        <omgdi:waypoint x="915.0000000000001" y="178.0000000000001"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="sid-78F2A2E7-D8F9-47B9-8B27-ECAE653D9A4F" id="BPMNEdge_sid-78F2A2E7-D8F9-47B9-8B27-ECAE653D9A4F">
+        <omgdi:waypoint x="549.95" y="178.00000000000014"></omgdi:waypoint>
+        <omgdi:waypoint x="620.0" y="178.00000000000006"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</definitions>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY/BYTES_/blobFiles/cd7557c02d22c531ca4fffb99e7d7609 b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY/BYTES_/blobFiles/cd7557c02d22c531ca4fffb99e7d7609
new file mode 100644
index 0000000000000000000000000000000000000000..fcb85e43d38c5e2773c08844bacdc28be2f56f11
Binary files /dev/null and b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_GE_BYTEARRAY/BYTES_/blobFiles/cd7557c02d22c531ca4fffb99e7d7609 differ
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_RE_DEPLOYMENT.xml b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_RE_DEPLOYMENT.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9852f8a5418497e88cfc45820677fdd73369c37e
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_RE_DEPLOYMENT.xml
@@ -0,0 +1,13 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+  <changeSet author="s.listl" id="bf2a6db428204cf4a5edde8a312339e2">
+    <preConditions onFail="CONTINUE">
+        <tableExists tableName="ACT_RE_DEPLOYMENT"/>
+    </preConditions>
+    <insert tableName="ACT_RE_DEPLOYMENT">
+      <column name="KEY_" value="offerVerification_neu"/>
+      <column name="ID_" value="1"/>
+      <column name="DEPLOY_TIME_" valueDate="2020-02-05T12:15:07"/>
+    </insert>
+  </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_RE_PROCDEF.xml b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_RE_PROCDEF.xml
new file mode 100644
index 0000000000000000000000000000000000000000..96cfbe09146d3d354f46f773abcb7ef68293c0c3
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/ACT_RE_PROCDEF.xml
@@ -0,0 +1,23 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+  <changeSet author="s.listl" id="a5747f71a32ac577810d7f077e05adb1">
+    <preConditions onFail="CONTINUE">
+        <tableExists tableName="ACT_RE_PROCDEF"/>
+    </preConditions>
+    <insert tableName="ACT_RE_PROCDEF">
+      <column name="DGRM_RESOURCE_NAME_" value="offerVerification_neuofferVerification_neu.png"/>
+      <column name="HAS_START_FORM_KEY_" valueNumeric="0"/>
+      <column name="DERIVED_VERSION_" valueNumeric="0"/>
+      <column name="ID_" value="offerVerification_neu:1:4"/>
+      <column name="REV_" valueNumeric="1"/>
+      <column name="VERSION_" valueNumeric="1"/>
+      <column name="NAME_" value="Angebotsprüfung_neu"/>
+      <column name="SUSPENSION_STATE_" valueNumeric="1"/>
+      <column name="KEY_" value="offerVerification_neu"/>
+      <column name="CATEGORY_" value="http://www.flowable.org/processdef"/>
+      <column name="DEPLOYMENT_ID_" value="1"/>
+      <column name="RESOURCE_NAME_" value="offerVerification_neubpmn20.xml"/>
+      <column name="HAS_GRAPHICAL_NOTATION_" valueNumeric="1"/>
+    </insert>
+  </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/OfferCheck.xml b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/OfferCheck.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cedeeb547f504e4d997bca0f162fdcc233a3467b
--- /dev/null
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/example_workflows/OfferCheck.xml
@@ -0,0 +1,6 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <include relativeToChangelogFile="true" file="ACT_RE_DEPLOYMENT.xml"/>
+    <include relativeToChangelogFile="true" file="ACT_GE_BYTEARRAY.xml"/>
+    <include relativeToChangelogFile="true" file="ACT_RE_PROCDEF.xml"/>
+</databaseChangeLog>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES.xml b/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES.xml
index 09a9d06090e29d188f9fdb7bd90bffea5afe23f3..017316291ab9aad426777853ae20f1578a2c9a38 100644
--- a/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES.xml
+++ b/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES.xml
@@ -249,7 +249,7 @@
     <insert tableName="ASYS_BINARIES">
       <column name="BINDATA" valueBlobFile="ASYS_BINARIES/BINDATA/blobFiles/6f1a18491d368b9b87091abcbcfcba15"/>
       <column name="CONTAINERNAME" value="DOCUMENT"/>
-      <column name="DATASIZE" valueNumeric="37361"/>
+      <column name="DATASIZE" valueNumeric="37675"/>
       <column name="DATE_EDIT" valueDate="2019-10-17T09:03:06"/>
       <column name="DATE_NEW" valueDate="2019-10-17T09:03:06"/>
       <column name="FILENAME" value="Geschaeftspapiere.odt"/>
@@ -385,7 +385,7 @@
     <insert tableName="ASYS_BINARIES">
       <column name="BINDATA" valueBlobFile="ASYS_BINARIES/BINDATA/blobFiles/0f474ccbf77d31f899cd5eab5f9a3c24"/>
       <column name="CONTAINERNAME" value="DOCUMENT"/>
-      <column name="DATASIZE" valueNumeric="37251"/>
+      <column name="DATASIZE" valueNumeric="44736"/>
       <column name="DATE_EDIT" valueDate="2019-10-17T09:03:19"/>
       <column name="DATE_NEW" valueDate="2019-10-17T09:03:19"/>
       <column name="FILENAME" value="Kostenübernahmeerklärung.odt"/>
@@ -1317,7 +1317,7 @@
       <column name="DATASIZE" valueNumeric="105"/>
       <column name="DATE_EDIT" valueDate="2019-10-17T09:11:23"/>
       <column name="DATE_NEW" valueDate="2019-10-17T09:11:23"/>
-      <column name="FILENAME" value="Angebotskopftext mit Dank.txt"/>
+      <column name="FILENAME" value="Angebotsfußtext mit Dank.txt"/>
       <column name="ID" value="dc1d9429-831f-4687-9362-d9a01a2a9b68"/>
       <column name="KEYWORD" value="TEMPLATE"/>
       <column name="MIMETYPE" value="text/plain"/>
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/0f474ccbf77d31f899cd5eab5f9a3c24 b/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/0f474ccbf77d31f899cd5eab5f9a3c24
index c1077c94c5e93760a89571b2bc76b380973b566b..5612079f37c55d30eb9353fa48b5800d6f15e0ca 100644
Binary files a/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/0f474ccbf77d31f899cd5eab5f9a3c24 and b/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/0f474ccbf77d31f899cd5eab5f9a3c24 differ
diff --git a/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/6f1a18491d368b9b87091abcbcfcba15 b/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/6f1a18491d368b9b87091abcbcfcba15
index 7390c27c99656b11427153f0d2498a0d9597273e..e99fa62cf86fc7c78dd5ce1e5fc4ec468fd2513f 100644
Binary files a/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/6f1a18491d368b9b87091abcbcfcba15 and b/.liquibase/_____SYSTEMALIAS/basic/_demoData/generatedData/ASYS_BINARIES/BINDATA/blobFiles/6f1a18491d368b9b87091abcbcfcba15 differ
diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod
index 2edb5725aab43b6438d85737e9d31169fb54fc85..0db510492caf395ba443a3fa0d89468ad2d7d2eb 100644
--- a/aliasDefinition/Data_alias/Data_alias.aod
+++ b/aliasDefinition/Data_alias/Data_alias.aod
@@ -3632,8 +3632,20 @@
                 <isUnique v="false" />
                 <index v="false" />
                 <documentation></documentation>
-                <title></title>
+                <title>Status</title>
                 <description></description>
+                <customProperties>
+                  <customBooleanProperty>
+                    <name>log</name>
+                    <global v="false" />
+                    <property v="true" />
+                  </customBooleanProperty>
+                  <customStringProperty>
+                    <name>keyword</name>
+                    <global v="false" />
+                    <property>SalesprojectState</property>
+                  </customStringProperty>
+                </customProperties>
               </entityFieldDb>
             </entityFields>
           </entityDb>
@@ -13466,6 +13478,110 @@
               </entityFieldDb>
             </entityFields>
           </entityDb>
+          <entityDb>
+            <name>WORKFLOWSIGNAL</name>
+            <dbName></dbName>
+            <idColumn>WORKFLOWSIGNALID</idColumn>
+            <idGeneratorType v="0" />
+            <idGeneratorInterval v="1" />
+            <documentation></documentation>
+            <title></title>
+            <description></description>
+            <auditSyncConfig>
+              <name>auditSyncConfig</name>
+              <auditMode v="0" />
+              <syncActive v="false" />
+              <syncComplete v="true" />
+              <syncDirection v="1" />
+              <syncIds></syncIds>
+            </auditSyncConfig>
+            <entityFields>
+              <entityFieldDb>
+                <name>SIGNAL_NAME</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="255" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>WORKFLOWSIGNALID</name>
+                <dbName></dbName>
+                <primaryKey v="true" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="true" />
+                <isUnique v="true" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>TRIGGER_EVENT</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>OBJECT_CONDITION</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="512" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>OBJECT_TYPE</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="63" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>PROCESSDEFINITION_KEY</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="255" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+            </entityFields>
+          </entityDb>
         </entities>
       </entityGroup>
     </aliasDefDb>
diff --git a/entity/CommRestriction_Entity/CommRestriction_Entity.aod b/entity/CommRestriction_Entity/CommRestriction_Entity.aod
index c11d841270f58412ce2ae59ba8b3172b32eb069b..3021b9ac98d22ddd7dfa8c199243185ef8b0203f 100644
--- a/entity/CommRestriction_Entity/CommRestriction_Entity.aod
+++ b/entity/CommRestriction_Entity/CommRestriction_Entity.aod
@@ -66,6 +66,10 @@
           <valueProcess>%aditoprj%/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/containername_param/valueProcess.js</valueProcess>
           <expose v="false" />
         </entityParameter>
+        <entityParameter>
+          <name>ExcludedKeyIdsSubquery_param</name>
+          <valueProcess>%aditoprj%/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js</valueProcess>
+        </entityParameter>
       </children>
     </entityConsumer>
     <entityProvider>
diff --git a/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js b/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..50167db735b55a82144eadc0e440f38b57ce6de7
--- /dev/null
+++ b/entity/CommRestriction_Entity/entityfields/commrestrictionmedium/children/excludedkeyidssubquery_param/valueProcess.js
@@ -0,0 +1,9 @@
+import("system.question");
+import("system.vars");
+import("Sql_lib");
+import("system.result");
+
+var contactId = vars.get("$field.CONTACT_ID");
+var alreadyUsedMediums = new SqlBuilder().select("MEDIUM").from("COMMRESTRICTION").where("COMMRESTRICTION.CONTACT_ID", contactId);
+
+result.string(alreadyUsedMediums);
\ No newline at end of file
diff --git a/entity/Context_entity/Context_entity.aod b/entity/Context_entity/Context_entity.aod
index 92b4a55b9b264a8ced721698129a93bd0baf14a3..f2201393b8ef0ca3b8308c427400cf082cd431c6 100644
--- a/entity/Context_entity/Context_entity.aod
+++ b/entity/Context_entity/Context_entity.aod
@@ -151,6 +151,12 @@
           <fieldName>Contexts</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>591679c2-8fd3-4d05-9ef3-b648373785f7</name>
+          <entityName>WorkflowSignal_entity</entityName>
+          <fieldName>Contexts</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
     </entityProvider>
   </entityFields>
diff --git a/entity/EmployeeRole_entity/entityfields/roles/children/excluderoles_param/valueProcess.js b/entity/EmployeeRole_entity/entityfields/roles/children/excluderoles_param/valueProcess.js
index 4300750f1e372af70f68435c0b2a264176b3bc49..faded8337443300973fc0ab0b855b97e3726689d 100644
--- a/entity/EmployeeRole_entity/entityfields/roles/children/excluderoles_param/valueProcess.js
+++ b/entity/EmployeeRole_entity/entityfields/roles/children/excluderoles_param/valueProcess.js
@@ -1,3 +1,15 @@
+import("system.tools");
+import("system.vars");
 import("system.result");
 
-result.string(JSON.stringify(["INTERNAL_EVERYONE", "INTERNAL_GROUPWARE", "INTERNAL_SNMP", "INTERNAL_DESIGNER", "INTERNAL_TECHNICAL"]));
\ No newline at end of file
+var userTitle = vars.exists("$param.UserTitle_param") && vars.get("$param.UserTitle_param");
+var excludeRolesArray = ["INTERNAL_EVERYONE", "INTERNAL_GROUPWARE", "INTERNAL_SNMP", "INTERNAL_DESIGNER", "INTERNAL_TECHNICAL"];
+
+if (userTitle != "") {
+    var userRoles = tools.getRoles(userTitle);
+    for (i = 0; i < userRoles.length; i++) {
+        excludeRolesArray.push(userRoles[i]);
+    }
+}
+
+result.string(JSON.stringify(excludeRolesArray));
\ No newline at end of file
diff --git a/entity/Employee_entity/grantDeleteProcess.js b/entity/Employee_entity/grantDeleteProcess.js
index e1d6c3c3c66520301af7fcc8215b6c040af0b123..d817b2a09effbf52d467ced477cffc4f62d4e29d 100644
--- a/entity/Employee_entity/grantDeleteProcess.js
+++ b/entity/Employee_entity/grantDeleteProcess.js
@@ -2,5 +2,16 @@ import("Employee_lib");
 import("Document_lib");
 import("system.vars");
 import("system.result");
-// TODO: Commented because of performance problems: in Filter view this Process is called for every row. Waiting for bugfix
-//result.string(!DocumentUtil.hasDocuments("EMPLOYEE", null, EmployeeUtils.sliceUserId(vars.get("$field.UID"))));
\ No newline at end of file
+
+var res = false;
+
+//the current user should not delete himself
+if (EmployeeUtils.getCurrentUserName() != vars.get("$field.TITLE") 
+    && !EmployeeUtils.hasRelations(vars.get("$field.CONTACT_ID")) 
+    && !DocumentUtil.hasDocuments("EMPLOYEE", null, EmployeeUtils.sliceUserId(vars.get("$field.UID")))
+   )
+{
+    res = true;
+}
+
+result.string(res);
\ No newline at end of file
diff --git a/entity/Employee_entity/recordcontainers/jdito/onDelete.js b/entity/Employee_entity/recordcontainers/jdito/onDelete.js
index 212b6d23132d934d2e7169624a2607b58d99a2e0..ab759edc01f99d49bbc901935e5d0805b54cfe10 100644
--- a/entity/Employee_entity/recordcontainers/jdito/onDelete.js
+++ b/entity/Employee_entity/recordcontainers/jdito/onDelete.js
@@ -3,6 +3,6 @@ import("system.vars");
 import("system.tools");
 import("Employee_lib");
 
-//TODO: the current user should not delete himself, put this condition in grantDelete when available
+//the current user should not delete himself
 if (EmployeeUtils.getCurrentUserName() != vars.get("$field.TITLE") && !EmployeeUtils.hasRelations(vars.get("$field.CONTACT_ID")))
     tools.deleteUser(vars.get("$field.TITLE"));
\ No newline at end of file
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index ca40ed92276a0d09ff1e111bc3cf710adc3f521e..126ed926b5fa3f0e51831332e07401bd60d68439 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -559,6 +559,12 @@
           <fieldName>CampaignStatusKeyword</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>66c64130-1997-4565-854e-94802b46dc96</name>
+          <entityName>WorkflowSignal_entity</entityName>
+          <fieldName>TriggerKeyword</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
       <children>
         <entityParameter>
diff --git a/entity/Offer_entity/Offer_entity.aod b/entity/Offer_entity/Offer_entity.aod
index c8d706ecb621275adc7fd92ac581a8a169b42f16..fa78e12fa9e78bd41160b2c99bb31106ee0bfe09 100644
--- a/entity/Offer_entity/Offer_entity.aod
+++ b/entity/Offer_entity/Offer_entity.aod
@@ -225,11 +225,13 @@
     <entityField>
       <name>CONTACT_ORG_ID</name>
       <title>Company</title>
+      <consumer>Organisations</consumer>
       <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/contact_org_id/stateProcess.js</stateProcess>
     </entityField>
     <entityField>
       <name>CONTACT_PERSON_ID</name>
       <title>Person</title>
+      <consumer>Persons</consumer>
       <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/contact_person_id/stateProcess.js</stateProcess>
     </entityField>
     <entityConsumer>
@@ -964,6 +966,22 @@
       <iconId>VAADIN:PLAY</iconId>
       <stateProcess>%aditoprj%/entity/Offer_entity/entityfields/startworkflow/stateProcess.js</stateProcess>
     </entityActionField>
+    <entityConsumer>
+      <name>Organisations</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Organisation_entity</entityName>
+        <fieldName>Organisations</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>Persons</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Person_entity</entityName>
+        <fieldName>Contact</fieldName>
+      </dependency>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -1073,10 +1091,14 @@
         <dbRecordFieldMapping>
           <name>CONTACT_ORG_ID.value</name>
           <recordfield>CONTACT.ORGANISATION_ID</recordfield>
+          <isFilterable v="true" />
+          <isLookupFilter v="false" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>CONTACT_PERSON_ID.value</name>
           <recordfield>CONTACT.PERSON_ID</recordfield>
+          <isFilterable v="true" />
+          <isLookupFilter v="false" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>ADDRESS.value</name>
diff --git a/entity/Offer_entity/afterOperatingState.js b/entity/Offer_entity/afterOperatingState.js
index 95c27335097d5a484f25b37e679dbc332eb8302a..9e011dcf5d5d51fd3c9a78e55b9936e2bec21f10 100644
--- a/entity/Offer_entity/afterOperatingState.js
+++ b/entity/Offer_entity/afterOperatingState.js
@@ -1,3 +1,4 @@
+import("Context_lib");
 import("system.vars");
 import("Workflow_lib");
 
@@ -5,4 +6,5 @@ if (vars.exists("$context.workflowQueue") && vars.get("$context.workflowQueue"))
 {
     WorkflowStarter.inserted(vars.get("$context.workflowQueue"));
     vars.set("$context.workflowQueue", null);
-}
\ No newline at end of file
+}
+WorkflowSignalSender.doInsertedOrUpdated();
\ No newline at end of file
diff --git a/entity/Offer_entity/recordcontainers/db/onDBDelete.js b/entity/Offer_entity/recordcontainers/db/onDBDelete.js
index 1f353a6744202e829f1486293da519903a9a43b0..dbcf3083e10d4f8e2686a00a91f238d27e33c1f1 100644
--- a/entity/Offer_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Offer_entity/recordcontainers/db/onDBDelete.js
@@ -5,4 +5,5 @@ import("system.vars");
 newWhere("OFFERITEM.OFFER_ID", "$field.OFFERID")
     .deleteData();
     
-WorkflowStarter.deleted({sum : Number(vars.get("$field.TotalGross")), status : vars.get("$field.STATUS")});
\ No newline at end of file
+WorkflowStarter.deleted({sum : Number(vars.get("$field.TotalGross")), status : vars.get("$field.STATUS")});
+WorkflowSignalSender.deleted();
\ No newline at end of file
diff --git a/entity/Offer_entity/recordcontainers/db/onDBInsert.js b/entity/Offer_entity/recordcontainers/db/onDBInsert.js
index e889b0d6c55e6902744e0a7469940c9a3a73972f..f65c655ec8749a87aaa568516948de8f37076339 100644
--- a/entity/Offer_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Offer_entity/recordcontainers/db/onDBInsert.js
@@ -1,3 +1,4 @@
+import("system.workflow");
 import("Workflow_lib");
 import("system.db");
 import("system.datetime");
@@ -22,3 +23,4 @@ if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
 
 //start the execution in afterOperatingState, because here the dataset is not yet inserted
 vars.set("$context.workflowQueue", {sum : Number(vars.get("$field.TotalGross")), status : vars.get("$field.STATUS")});
+WorkflowSignalSender.markInserted();
diff --git a/entity/Offer_entity/recordcontainers/db/onDBUpdate.js b/entity/Offer_entity/recordcontainers/db/onDBUpdate.js
index 8f911091e9794cb39984177859555ab3d1438b1d..481f3bcd1ad9144b89734a95b8f774f85a1af2d7 100644
--- a/entity/Offer_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Offer_entity/recordcontainers/db/onDBUpdate.js
@@ -1,7 +1,10 @@
+import("system.workflow");
 import("KeywordRegistry_basic");
 import("system.vars");
 import("Workflow_lib");
 
 var status = vars.get("$local.rowdata")["OFFER.STATUS"];
 if (vars.get("$local.changed").indexOf("OFFER.STATUS") !== -1 && status == $KeywordRegistry.offerStatus$toCheck())
-    WorkflowStarter.updated({sum : Number(vars.get("$field.TotalGross")), status : status});
\ No newline at end of file
+    WorkflowStarter.updated({sum : Number(vars.get("$field.TotalGross")), status : status});
+
+WorkflowSignalSender.markUpdated();
\ No newline at end of file
diff --git a/entity/Offer_entity/recordcontainers/index/query.js b/entity/Offer_entity/recordcontainers/index/query.js
index 103cbd340617b001b89b0835df694c7d773af987..608db62da009bb4eb785ecbd14c9f10f8dbb351d 100644
--- a/entity/Offer_entity/recordcontainers/index/query.js
+++ b/entity/Offer_entity/recordcontainers/index/query.js
@@ -9,18 +9,18 @@ import("Sql_lib");
 import("KeywordRegistry_basic");
 
 var sqlHelper = new SqlMaskingUtils();
-var querySelect = newSelect("OFFERID " // as "_uid_", 
-                        + ", " + sqlHelper.concat([sqlHelper.cast("OFFERCODE", SQLTYPES.CHAR, 10), KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.offerStatus(), "OFFER.STATUS")], " | ") //as "_title_"
+var querySelect = newSelect("OFFER.OFFERID " // as "_uid_", 
+                        + ", " + sqlHelper.concat([sqlHelper.cast("OFFER.OFFERCODE", SQLTYPES.CHAR, 10), KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.offerStatus(), "OFFER.STATUS")], " | ") //as "_title_"
                         + ", " + sqlHelper.concat(["ORGANISATION.NAME", "'| " + translate.text("Description") + ":'", sqlHelper.castLob("OFFER.INFO", 250)]) // as "_description_"  
-                        + ", OFFERCODE"
-                        + ", CUSTOMERCODE " 
+                        + ", OFFER.OFFERCODE"
+                        + ", ORGANISATION.CUSTOMERCODE " 
                         + ", OFFER.CONTACT_ID "
                         + ", CONTACT.ORGANISATION_ID " // as CONTACT_ORG_ID
                         + ", ORGANISATION.NAME") // as "CONTACT_ORG_ID.displayValue"
                     .from("OFFER")
                     .join("CONTACT", "OFFER.CONTACT_ID = CONTACTID")
                     .join("ORGANISATION", "ORGANISATIONID = CONTACT.ORGANISATION_ID")
-                    .orderBy("OFFERCODE");
+                    .orderBy("OFFER.OFFERCODE");
 
 if (vars.exists("$local.idvalue") && vars.get("$local.idvalue") && vars.get("$local.idvalue").length > 0) 
 {
diff --git a/entity/Order_entity/Order_entity.aod b/entity/Order_entity/Order_entity.aod
index bfbbbc2ee17ab039a9cc90350dc19a069c6320bb..a6b28c020c5bee4e6dfa2a6629bbe45a34c14f48 100644
--- a/entity/Order_entity/Order_entity.aod
+++ b/entity/Order_entity/Order_entity.aod
@@ -67,7 +67,6 @@
       <mandatory v="true" />
       <valueProcess>%aditoprj%/entity/Order_entity/entityfields/contact_id/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Order_entity/entityfields/contact_id/displayValueProcess.js</displayValueProcess>
-      <onValueChange>%aditoprj%/entity/Order_entity/entityfields/contact_id/onValueChange.js</onValueChange>
       <onValueChangeTypes>
         <element>MASK</element>
       </onValueChangeTypes>
@@ -189,10 +188,12 @@
     <entityField>
       <name>CONTACT_ORG_ID</name>
       <title>Company</title>
+      <consumer>Organisations</consumer>
     </entityField>
     <entityField>
       <name>CONTACT_PERSON_ID</name>
       <title>Person</title>
+      <consumer>Persons</consumer>
     </entityField>
     <entityConsumer>
       <name>AnyContacts</name>
@@ -459,7 +460,7 @@
     <entityField>
       <name>CANCELLATION</name>
       <documentation>%aditoprj%/entity/Order_entity/entityfields/cancellation/documentation.adoc</documentation>
-      <title>Cancelled</title>
+      <title>${ORDER_CANCELLED}</title>
       <contentType>BOOLEAN</contentType>
       <dropDownProcess>%aditoprj%/entity/Order_entity/entityfields/cancellation/dropDownProcess.js</dropDownProcess>
       <valueProcess>%aditoprj%/entity/Order_entity/entityfields/cancellation/valueProcess.js</valueProcess>
@@ -951,6 +952,22 @@
       <iconId>VAADIN:CURLY_BRACKETS</iconId>
       <stateProcess>%aditoprj%/entity/Order_entity/entityfields/openadminview/stateProcess.js</stateProcess>
     </entityActionField>
+    <entityConsumer>
+      <name>Organisations</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Organisation_entity</entityName>
+        <fieldName>Organisations</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>Persons</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Person_entity</entityName>
+        <fieldName>Contacts</fieldName>
+      </dependency>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Order_entity/entityfields/contact_id/onValueChange.js b/entity/Order_entity/entityfields/contact_id/onValueChange.js
deleted file mode 100644
index 38d1cb778cfbcc7a0cf5d1bc0a55f142e965f213..0000000000000000000000000000000000000000
--- a/entity/Order_entity/entityfields/contact_id/onValueChange.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import("Sql_lib");
-import("system.neon");
-import("system.vars");
-import("Util_lib");
-import("Entity_lib");
-
-var contactid = vars.get("local.value");
-
-var relData = newSelect("ISOLANGUAGE")
-    .from("CONTACT")
-    .whereIfSet("CONTACT.CONTACTID", contactid)
-    .cell(true);
-
-if(relData)   
-    vars.set("$field.ISOLANGUAGE", relData);
-
-neon.setFieldValue("$field.OBJECT_ROWID", null)
\ No newline at end of file
diff --git a/entity/PermissionAction_entity/recordcontainers/jdito/contentProcess.js b/entity/PermissionAction_entity/recordcontainers/jdito/contentProcess.js
index 0b19076ff3bb8f6ded6aa49e810ac8f31da1c1d9..2b4c3b252f1f708de5bec8f3a15d267cea980be3 100644
--- a/entity/PermissionAction_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/PermissionAction_entity/recordcontainers/jdito/contentProcess.js
@@ -9,8 +9,8 @@ var permissionId = vars.exists("$param.PermissionId_param") && vars.get("$param.
 if (permissionId && PermissionUtil.permissionExists(permissionId))
 {
     var permActions = PermissionUtil.getActions([permissionId]);
-    for each (var permActionId in permActions) {
-        actions.push([permActionId[0], PermissionUtil.resolveActionId(permActionId), PermissionUtil.resolveActionId(permActionId)]);    
+    for each (let permActionId in permActions) {
+        actions.push([permActionId, PermissionUtil.resolveActionId(permActionId), PermissionUtil.resolveActionId(permActionId)]);    
     }
     
     var ids = vars.get("$local.idvalues");
diff --git a/entity/PermissionDetail_entity/entityfields/permissionactions/children/permissionid_param/valueProcess.js b/entity/PermissionDetail_entity/entityfields/permissionactions/children/permissionid_param/valueProcess.js
index 046efd6e02b194aa32978c4074d14bab22b83c11..f89d3520f1571cbc1459227f2b645a043755569b 100644
--- a/entity/PermissionDetail_entity/entityfields/permissionactions/children/permissionid_param/valueProcess.js
+++ b/entity/PermissionDetail_entity/entityfields/permissionactions/children/permissionid_param/valueProcess.js
@@ -18,7 +18,7 @@ var permSetId = PermissionUtil.getSet(roleName, entity, accesstype, field);
 var fieldWhereCond = "ASYS_PERMISSIONSET.FIELD_ID is null";
 
 if (field != "") {
-    fieldWhereCond = newWhere("ASYS_PERMISSIONSET.FIELD_ID", field);
+    fieldWhereCond = newWhere("ASYS_PERMISSIONSET.FIELD_ID", field, null, null, alias);
 }
 
 if (permSetId != "") {
diff --git a/entity/PermissionDetail_entity/recordcontainers/jdito/onDelete.js b/entity/PermissionDetail_entity/recordcontainers/jdito/onDelete.js
index 4a73a56fbacb65b7f2a1adbc609a48c6d35eb3d6..3dc265ae56732033c08fe1ef61ee6b513e0810c0 100644
--- a/entity/PermissionDetail_entity/recordcontainers/jdito/onDelete.js
+++ b/entity/PermissionDetail_entity/recordcontainers/jdito/onDelete.js
@@ -32,8 +32,8 @@ switch (accessType) {
         sqlCondDelPermSet.deleteData(true, "ASYS_PERMISSIONSET"); // delete all permission sets
         break;
     default:
-        db.deleteData("ASYS_PERMISSIONACTION", sqlCondDelAction, alias); // delete all actions of the selected permission
-        db.deleteData("ASYS_PERMISSION", sqlCondDelPerm, alias); // delete the selected permission
+        sqlCondDelAction.deleteData(true, "ASYS_PERMISSIONACTION"); // delete all actions of the selected permission
+        sqlCondDelPerm.deleteData(true, "ASYS_PERMISSION"); // delete the selected permission
         break;
 }
 
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index bf4a87910fc9c95a5533dbfd7fec120fa0d71506..31c3172f84e785164019380de2f5e9d5315eb554 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -1033,7 +1033,6 @@ Usually this is used for filtering COMMUNICATION-entries by a specified contact
           <title>Start workflow</title>
           <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/onActionProcess.js</onActionProcess>
           <isObjectAction v="false" />
-          <isSelectionAction v="true" />
           <iconId>VAADIN:PLAY</iconId>
           <stateProcess>%aditoprj%/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js</stateProcess>
         </entityActionField>
diff --git a/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/onActionProcess.js b/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/onActionProcess.js
index fae54f62384d81d7bcb1f116cfe82ef470194ffc..4dd1c6ae0edb893438c881f315071acea64e8dcd 100644
--- a/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/onActionProcess.js
+++ b/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/onActionProcess.js
@@ -1,4 +1,5 @@
 import("system.vars");
 import("Workflow_lib");
+import("system.entities");
 
-WorkflowUtils.openNewInstance(null, vars.get("$sys.selection"));
\ No newline at end of file
+WorkflowUtils.openNewInstance(null, vars.get("$sys.selection"), undefined, vars.get("$sys.filter"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js b/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js
index ef65dd9cffd2d6d81ae54a6ae35636ae946aff22..04070243a6d3b71423219c065c243d09ff16971a 100644
--- a/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js
+++ b/entity/Person_entity/entityfields/campaignactiongroup/children/startmultipleworkflows/stateProcess.js
@@ -1,8 +1,11 @@
+import("system.vars");
 import("system.neon");
 import("Workflow_lib");
 import("system.result");
 
 result.string(WorkflowUtils.engineIsEnabled()
-    ? neon.COMPONENTSTATE_EDITABLE
+    ? vars.get("$sys.datarowcount") > 0
+        ? neon.COMPONENTSTATE_EDITABLE
+        : neon.COMPONENTSTATE_DISABLED
     : neon.COMPONENTSTATE_INVISIBLE
 );
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/salutations/children/language_param/valueProcess.js b/entity/Person_entity/entityfields/salutations/children/language_param/valueProcess.js
index 2cb0f4295d8276abc980683fdc3945bcfd965aee..3b648cd9acceb82cf64a27def50c9aff6c070b18 100644
--- a/entity/Person_entity/entityfields/salutations/children/language_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/salutations/children/language_param/valueProcess.js
@@ -1,4 +1,5 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.LANGUAGE"))
\ No newline at end of file
+if (vars.get("$field.LANGUAGE"))
+    result.string(vars.get("$field.LANGUAGE"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/salutationtitles/children/language_param/valueProcess.js b/entity/Person_entity/entityfields/salutationtitles/children/language_param/valueProcess.js
index 2cb0f4295d8276abc980683fdc3945bcfd965aee..4aace6a64132d1a1849cb68b7a8b491e14176f67 100644
--- a/entity/Person_entity/entityfields/salutationtitles/children/language_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/salutationtitles/children/language_param/valueProcess.js
@@ -1,4 +1,5 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.LANGUAGE"))
\ No newline at end of file
+if (vars.get("$field.LANGUAGE"))
+    result.string(vars.get("$field.LANGUAGE"))
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/salutationtitles/children/salutation_param/valueProcess.js b/entity/Person_entity/entityfields/salutationtitles/children/salutation_param/valueProcess.js
index f098580b1e736016c19e4d5cc776a552e24b55d4..d24ba266458ce5e566efd8729635397fd3ec6315 100644
--- a/entity/Person_entity/entityfields/salutationtitles/children/salutation_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/salutationtitles/children/salutation_param/valueProcess.js
@@ -1,4 +1,5 @@
 import("system.vars");
 import("system.result");
 
-result.string(vars.get("$field.SALUTATION"));
\ No newline at end of file
+if (vars.get("$field.SALUTATION"))
+    result.string(vars.get("$field.SALUTATION"));
\ No newline at end of file
diff --git a/entity/Person_entity/recordcontainers/db/conditionProcess.js b/entity/Person_entity/recordcontainers/db/conditionProcess.js
index 100f909cbf3991bfb9520e924cffbc543bd49acf..a856eee0c297f691d292222ffb1b94f55df14c55 100644
--- a/entity/Person_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Person_entity/recordcontainers/db/conditionProcess.js
@@ -9,7 +9,7 @@ import("system.result");
 import("Sql_lib");
 
 var cond = newWhereIfSet("CONTACT.ORGANISATION_ID", "$param.OrgId_param")
-                .andIfSet("PERSON.CONTACT_ID", "$param.ContactId_param");
+                .andIfSet("CONTACT.CONTACTID", "$param.ContactId_param");
 
 if (vars.exists("$param.ExcludedContactIds_param") && vars.get("$param.ExcludedContactIds_param"))
 {
diff --git a/entity/Productprice_entity/Productprice_entity.aod b/entity/Productprice_entity/Productprice_entity.aod
index b61892f5a4a8dea0a9b276e60ddf25f4fb401ae5..180e3f710beea385178ad2747749b4389f4ff299 100644
--- a/entity/Productprice_entity/Productprice_entity.aod
+++ b/entity/Productprice_entity/Productprice_entity.aod
@@ -289,8 +289,8 @@
         <dbRecordFieldMapping>
           <name>CONTACT_ID.value</name>
           <recordfield>PRODUCTPRICE.CONTACT_ID</recordfield>
-          <isFilterable v="true" />
-          <isLookupFilter v="true" />
+          <isFilterable v="false" />
+          <isLookupFilter v="false" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>VALID_FROM.value</name>
diff --git a/entity/RoleChildren_entity/entityfields/child_role/dropDownProcess.js b/entity/RoleChildren_entity/entityfields/child_role/dropDownProcess.js
index e8c1bbcf927206da45d6bfe07831f3efb0cd25b3..8867a68b1cb4c9e3d8b2d4fdb5b61936c46cdf5b 100644
--- a/entity/RoleChildren_entity/entityfields/child_role/dropDownProcess.js
+++ b/entity/RoleChildren_entity/entityfields/child_role/dropDownProcess.js
@@ -1,16 +1,38 @@
+import("Sql_lib");
+import("system.tools");
 import("system.vars");
-import("system.db");
 import("system.result");
 
-var sqlStr = "select ASYS_ROLES.ROLENAME from ASYS_ROLES";
-var roleNames = db.array(db.COLUMN, sqlStr);
+var newChildRoles = [];
+var alias = SqlUtils.getSystemAlias();
 var parentRole = vars.get("$param.RoleId_param");
-var childRoles = [];
+var allCustomAndProjectRoles = tools.getAllRoles(["CUSTOM", "PROJECT"], true);
 
-for each (let roleName in roleNames) {
-    if (roleName != parentRole) {
-        childRoles.push([roleName, roleName]);
+var childRoles = newSelect("CHILD_ROLE", alias)
+.from("ASYS_ROLES_CHILDREN")
+.where("ASYS_ROLES_CHILDREN.PARENT_ROLE", parentRole)
+.table();
+
+var parentIsAlreadyChildOf = newSelect("PARENT_ROLE", alias)
+.from("ASYS_ROLES_CHILDREN")
+.where("ASYS_ROLES_CHILDREN.CHILD_ROLE", parentRole)
+.table();
+
+for each (let role in allCustomAndProjectRoles) {
+    // dont show current role as possible child in dropdown
+    if (role[3] != parentRole) {
+        newChildRoles.push([role[3], role[3]]);
     }
 }
 
-result.object(childRoles);
\ No newline at end of file
+// check for cyclces in hierarchy, A can't be child of B while it is already parent of B
+for each (let role in parentIsAlreadyChildOf) {
+    newChildRoles = newChildRoles.filter(function(childRole) {
+        if (role == childRole[0]) {
+            return false;
+        }
+        return true;
+    });
+}
+
+result.object(newChildRoles.sort());
\ No newline at end of file
diff --git a/entity/RoleChildren_entity/recordcontainers/jdito/contentProcess.js b/entity/RoleChildren_entity/recordcontainers/jdito/contentProcess.js
index cf0d3c41b7ee397447c6b35fc95c8a5a5f2c6f62..f21fb44def8424121f454521bd9e67d5f87b43ac 100644
--- a/entity/RoleChildren_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/RoleChildren_entity/recordcontainers/jdito/contentProcess.js
@@ -9,15 +9,14 @@ var parentRoleName = vars.exists("$param.RoleId_param") && vars.get("$param.Role
 var children = [];
 
 if (parentRoleName && parentRoleName.indexOf("CUSTOM_") != -1) {
-    // parentRoleName is a viable CUSTOM role
-    var sqlStr = "select CHILD_ROLE, ID from ASYS_ROLES_CHILDREN where PARENT_ROLE = '" + parentRoleName + "'";
-    var childRoles = db.table(sqlStr, alias);
-    if (childRoles.length != 0) {
-        for each (let childRole in childRoles) {
-            children.push([childRole[1], childRole[0], parentRoleName]);
-        }
-    } else {
-        children.push(["", "", parentRoleName]);
+    // roles can only be assigned to CUSTOM roles -> parent role has to be a viable CUSTOM role
+    childRoles = newSelect("ID, CHILD_ROLE", alias)
+        .from("ASYS_ROLES_CHILDREN")
+        .where("ASYS_ROLES_CHILDREN.PARENT_ROLE", parentRoleName)
+        .table();
+
+    for each (let childRole in childRoles) {
+        children.push([childRole[0], childRole[1], parentRoleName]);
     }
 
     var ids = vars.get("$local.idvalues");
diff --git a/entity/RoleChildren_entity/recordcontainers/jdito/onInsert.js b/entity/RoleChildren_entity/recordcontainers/jdito/onInsert.js
index 7fec6ad58d90022619c620cca93d6680a81199a7..60f0bfa215505465723f41d8a605a430a1ccd9da 100644
--- a/entity/RoleChildren_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/RoleChildren_entity/recordcontainers/jdito/onInsert.js
@@ -9,7 +9,6 @@ var parentRoleName = vars.exists("$param.RoleId_param") && vars.get("$param.Role
 if (parentRoleName && parentRoleName.indexOf("CUSTOM_") != -1) {
     var alias = SqlUtils.getSystemAlias();
     var childRole = vars.get("$local.rowdata")["CHILD_ROLE.value"];
-
-    var uid = util.getNewUUID();
+    var uid = vars.get("$field.UID") 
     db.insertData("ASYS_ROLES_CHILDREN", ["CHILD_ROLE", "PARENT_ROLE", "ID"], null, [childRole, parentRoleName, uid], alias);
 }
\ No newline at end of file
diff --git a/entity/Role_entity/Role_entity.aod b/entity/Role_entity/Role_entity.aod
index 667568f4c04e25f9201993424ccdbf18a198c92d..526b317caff9d40519cb133db39afb9f20d4aa77 100644
--- a/entity/Role_entity/Role_entity.aod
+++ b/entity/Role_entity/Role_entity.aod
@@ -126,6 +126,7 @@
     </entityField>
     <entityConsumer>
       <name>RoleChildrens</name>
+      <onValidation>%aditoprj%/entity/Role_entity/entityfields/rolechildrens/onValidation.js</onValidation>
       <dependency>
         <name>dependency</name>
         <entityName>RoleChildren_entity</entityName>
diff --git a/entity/Role_entity/entityfields/rolechildrens/onValidation.js b/entity/Role_entity/entityfields/rolechildrens/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..353d075913c25044b065d4c2d325cdadd3a96315
--- /dev/null
+++ b/entity/Role_entity/entityfields/rolechildrens/onValidation.js
@@ -0,0 +1,70 @@
+import("system.result");
+import("Sql_lib");
+import("system.logging");
+import("system.vars");
+
+var changedRows = vars.get("$field.RoleChildrens.changedRows");
+var insertedRows = vars.get("$field.RoleChildrens.insertedRows");
+
+// check for duplicates
+for each (let row in insertedRows) {
+    if (isRoleAlreadyChildren(row)) {
+        result.string("No duplicates allowed!");
+    }
+}
+
+for each (let row in changedRows) {
+    if (isRoleAlreadyChildren(row)) {
+        result.string("No duplicates allowed!");
+    }
+}
+
+function isRoleAlreadyChildren(pRole) {
+    var alias = SqlUtils.getSystemAlias();
+    var parentRoleName = vars.get("$field.ROLENAME")
+    var childRoles = newSelect("CHILD_ROLE", alias)
+    .from("ASYS_ROLES_CHILDREN")
+    .where("ASYS_ROLES_CHILDREN.PARENT_ROLE", parentRoleName)
+    .table();
+
+    // check for duplicates in database
+    for each (let child in childRoles) {
+        if (child == pRole.CHILD_ROLE) {
+            return true;
+        }
+    }
+    
+    // check for duplicate in changed or inserted rows
+    if (checkDuplicateInObject("CHILD_ROLE", changedRows) || checkDuplicateInObject("CHILD_ROLE", insertedRows))
+        return true;
+    
+    // crosscheck for duplicates in inserted and changed rows
+    for each (let insRow in insertedRows) {
+        for each (let chaRow in changedRows) {
+            if (insRow.CHILD_ROLE == chaRow.CHILD_ROLE) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+function checkDuplicateInObject(propertyName, inputArray) {
+    var seenDuplicate = false,
+    testObject = {};
+
+    inputArray.map(function(item) {
+        var itemPropertyName = item[propertyName];    
+        if (itemPropertyName in testObject) {
+            testObject[itemPropertyName].duplicate = true;
+            item.duplicate = true;
+            seenDuplicate = true;
+        }
+        else {
+            testObject[itemPropertyName] = item;
+            delete item.duplicate;
+        }
+    });
+
+    return seenDuplicate;
+}
\ No newline at end of file
diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod
index 6264e47b1343159fd643eb9d52ff7853825c145d..7c0c796401afeed231e64d8787b8b324f95b4dc5 100644
--- a/entity/Salesproject_entity/Salesproject_entity.aod
+++ b/entity/Salesproject_entity/Salesproject_entity.aod
@@ -60,6 +60,9 @@
       <name>PROJECTCODE</name>
       <documentation>%aditoprj%/entity/Salesproject_entity/entityfields/projectcode/documentation.adoc</documentation>
       <title>Project number</title>
+      <contentType>NUMBER</contentType>
+      <outputFormat>#</outputFormat>
+      <inputFormat>#</inputFormat>
       <state>READONLY</state>
       <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/projectcode/valueProcess.js</valueProcess>
       <onValidation>%aditoprj%/entity/Salesproject_entity/entityfields/projectcode/onValidation.js</onValidation>
diff --git a/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod b/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod
index f7bbe40886f6601c68134ddaefd9114e4861d66d..7a08e145424bf057bbb9823bbbdd4dae3f2e1eb7 100644
--- a/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod
+++ b/entity/WorkflowDefinition_entity/WorkflowDefinition_entity.aod
@@ -171,6 +171,24 @@
       <onActionProcess>%aditoprj%/entity/WorkflowDefinition_entity/entityfields/downloadxml/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:DOWNLOAD</iconId>
     </entityActionField>
+    <entityConsumer>
+      <name>Signals</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>WorkflowSignal_entity</entityName>
+        <fieldName>ProcessDefinitionSignals</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ProcessDefinitionId_param</name>
+          <valueProcess>%aditoprj%/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionid_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>ProcessDefinitionKey_param</name>
+          <valueProcess>%aditoprj%/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionkey_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
diff --git a/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionid_param/valueProcess.js b/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..16c85500b5355a72548030867e3d300661e9d4aa
--- /dev/null
+++ b/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionid_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionkey_param/valueProcess.js b/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionkey_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c5c973d2b247ecef9c21e39584f539bf986176d
--- /dev/null
+++ b/entity/WorkflowDefinition_entity/entityfields/signals/children/processdefinitionkey_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.vars");
+import("system.result");
+
+result.string(vars.get("$field.KEY"));
\ No newline at end of file
diff --git a/entity/WorkflowDefinition_entity/recordcontainers/jdito/onUpdate.js b/entity/WorkflowDefinition_entity/recordcontainers/jdito/onUpdate.js
index 612fa49109ea606288ad2418e8bb7f9ce9f57316..2afd61402ee0fab203bf051660b1c227da1cdfdd 100644
--- a/entity/WorkflowDefinition_entity/recordcontainers/jdito/onUpdate.js
+++ b/entity/WorkflowDefinition_entity/recordcontainers/jdito/onUpdate.js
@@ -1,10 +1,19 @@
+import("system.util");
 import("system.vars");
 import("system.workflow");
+import("Document_lib");
 
 var rowdata = vars.get("$local.rowdata");
 
-vars.get("$local.changed").forEach(function (field)
+if (vars.get("$local.changed").indexOf("ISACTIVE.value") !== -1)
+    workflow.setProcessActive(rowdata["UID.value"], rowdata["ISACTIVE.value"] == "true");
+    
+
+var upload = new FileUpload(vars.get("$field.FILEUPLOAD"));
+if (upload.isFilled())
 {
-    if (field == "ISACTIVE.value")
-        workflow.setProcessActive(rowdata["UID.value"], rowdata["ISACTIVE.value"] == "true");
-});
\ No newline at end of file
+    //the xml could be invalid
+    try {
+        workflow.deployProcess(rowdata["KEY.value"], upload.getBase64DecodedData());
+    } catch (ex) {}
+}
diff --git a/entity/WorkflowInstance_entity/WorkflowInstance_entity.aod b/entity/WorkflowInstance_entity/WorkflowInstance_entity.aod
index 2408a0b0d88507363f86534f0402f8d2afd1ed92..26156dbf3d70b8b9630bc74cd883cb87467cdf39 100644
--- a/entity/WorkflowInstance_entity/WorkflowInstance_entity.aod
+++ b/entity/WorkflowInstance_entity/WorkflowInstance_entity.aod
@@ -106,6 +106,10 @@
       <name>TargetContext_param</name>
       <expose v="true" />
     </entityParameter>
+    <entityParameter>
+      <name>TargetIdFilter_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
diff --git a/entity/WorkflowInstance_entity/recordcontainers/jdito/contentProcess.js b/entity/WorkflowInstance_entity/recordcontainers/jdito/contentProcess.js
index 44de4cc658e251d4b9a7324d4c6967f2a0964009..fa6930da974f88d066111b73f6a3345c788ae81d 100644
--- a/entity/WorkflowInstance_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/WorkflowInstance_entity/recordcontainers/jdito/contentProcess.js
@@ -23,12 +23,18 @@ if (idvalues)
     //no instance could be found, search with the key and use the item with the latest startTime
     if (wfInstances.length === 0)
     {
-        wfInstances = [_getInstances(null, idvalues[0]).reduce(function (prev, curr)
+        var instances = _getInstances(null, idvalues[0]);
+        if (instances.length === 0)
+            wfInstances = [];
+        else
         {
-            if (Date.parse(prev.startTime) > Date.parse(curr.startTime))
-                return prev;
-            return curr;
-        })];
+            wfInstances = [instances.reduce(function (prev, curr)
+            {
+                if (Date.parse(prev.startTime) > Date.parse(curr.startTime))
+                    return prev;
+                return curr;
+            })];
+        }
     }
 }
 else
diff --git a/entity/WorkflowInstance_entity/recordcontainers/jdito/onInsert.js b/entity/WorkflowInstance_entity/recordcontainers/jdito/onInsert.js
index 07d29335208ccb4908b9699002f55d256c36e220..0c2f12489ab8ca2bab6589150163ed8cb3e1876e 100644
--- a/entity/WorkflowInstance_entity/recordcontainers/jdito/onInsert.js
+++ b/entity/WorkflowInstance_entity/recordcontainers/jdito/onInsert.js
@@ -1,16 +1,52 @@
+import("Employee_lib");
+import("system.entities");
+import("Context_lib");
 import("Workflow_lib");
 import("system.vars");
 import("system.workflow");
+import("system.process");
 
 var variables = JSON.parse(vars.getString("$param.ProcessVariables_param"));
-var targetIds;
-if (Array.isArray(variables.targetId))
-    targetIds = variables.targetId.slice();
-else
-    targetIds = [variables.targetId];
+var targetIdFilter = vars.get("$param.TargetIdFilter_param") ? JSON.parse(vars.getString("$param.TargetIdFilter_param")) : null;
+var processKey = vars.get("$local.rowdata")["KEY.value"];
 
-targetIds.forEach(function (id) 
+if (Array.isArray(variables.targetId) && variables.targetId.length > 0)
+    _startForIds(variables.targetId.slice(), variables);
+else if (!Array.isArray(variables.targetId) && variables.targetId)
+    _startForIds([variables.targetId], variables);
+else if (targetIdFilter)
 {
-    variables.targetId = id;
-    workflow.startProcessByKey(vars.get("$local.rowdata")["KEY.value"], variables);
-});
+    var entity = ContextUtils.getEntity(variables.targetContext);
+    var loadConfig = entities.createConfigForLoadingRows()
+        .entity(entity)
+        .fields(["#UID"]);
+
+    if (targetIdFilter.filter)
+        loadConfig.filter(JSON.stringify(targetIdFilter.filter));
+    
+    var rowCount = entities.getRowCount(loadConfig);
+    var pageSize = 1000;
+    for (let startRow = 0; startRow < rowCount; startRow += pageSize)
+    {
+        loadConfig.startrow(startRow).count(pageSize);
+        let targetIds = entities.getRows(loadConfig).map(function (row) {return row["#UID"];});
+        _startForIds(targetIds, variables);
+    }
+    
+//TODO: entities.getRows currently doesn't work on the server
+//    process.executeAsync("startWorkflowInstances_serverProcess", {
+//        processVariables : JSON.stringify(variables),
+//        processKey : processKey,
+//        entityFilter : targetIdFilter.filter ? JSON.stringify(targetIdFilter.filter) : ""
+//    },  false, EmployeeUtils.getCurrentUserName(), process.THREADPRIORITY_NORM, process.TIMERTYPE_SERVER);
+}
+
+function _startForIds (pTargetIds, pVariables)
+{
+    pTargetIds.forEach(function (id) 
+    {
+        pVariables.targetId = id;
+        workflow.startProcessByKey(processKey, pVariables);
+    });
+}
+
diff --git a/entity/WorkflowSignal_entity/WorkflowSignal_entity.aod b/entity/WorkflowSignal_entity/WorkflowSignal_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..294159191527fe53bc9bc5861361c3b05c987992
--- /dev/null
+++ b/entity/WorkflowSignal_entity/WorkflowSignal_entity.aod
@@ -0,0 +1,135 @@
+<?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.13" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.13">
+  <name>WorkflowSignal_entity</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <title>Workflow signal</title>
+  <titlePlural>Signals</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityField>
+      <name>WORKFLOWSIGNALID</name>
+    </entityField>
+    <entityField>
+      <name>SIGNAL_NAME</name>
+      <title>Signal</title>
+      <dropDownProcess>%aditoprj%/entity/WorkflowSignal_entity/entityfields/signal_name/dropDownProcess.js</dropDownProcess>
+    </entityField>
+    <entityField>
+      <name>SCOPE</name>
+      <title>Scope</title>
+    </entityField>
+    <entityParameter>
+      <name>ProcessDefinitionId_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+    </entityParameter>
+    <entityField>
+      <name>OBJECT_TYPE</name>
+      <title>Context</title>
+      <consumer>Contexts</consumer>
+    </entityField>
+    <entityField>
+      <name>TRIGGER_EVENT</name>
+      <title>Trigger</title>
+      <consumer>TriggerKeyword</consumer>
+    </entityField>
+    <entityField>
+      <name>OBJECT_CONDITION</name>
+      <title>Condition</title>
+      <contentType>FILTER_TREE</contentType>
+      <valueProcess>%aditoprj%/entity/WorkflowSignal_entity/entityfields/object_condition/valueProcess.js</valueProcess>
+    </entityField>
+    <entityConsumer>
+      <name>Contexts</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Context_entity</entityName>
+        <fieldName>Exclusive</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityConsumer>
+      <name>TriggerKeyword</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/WorkflowSignal_entity/entityfields/triggerkeyword/children/containername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityProvider>
+      <name>ProcessDefinitionSignals</name>
+      <dependencies>
+        <entityDependency>
+          <name>f08ff63c-296a-4b1f-8264-b6b1e6c1d748</name>
+          <entityName>WorkflowDefinition_entity</entityName>
+          <fieldName>Signals</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+    <entityField>
+      <name>PROCESSDEFINITION_KEY</name>
+      <valueProcess>%aditoprj%/entity/WorkflowSignal_entity/entityfields/processdefinition_key/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>ProcessDefinitionKey_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+    </entityParameter>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <alias>Data_alias</alias>
+      <conditionProcess>%aditoprj%/entity/WorkflowSignal_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <linkInformation>
+        <linkInformation>
+          <name>f6162cb6-c209-4607-8d67-0d630b28feab</name>
+          <tableName>WORKFLOWSIGNAL</tableName>
+          <primaryKey>WORKFLOWSIGNALID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="false" />
+        </linkInformation>
+      </linkInformation>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>WORKFLOWSIGNALID.value</name>
+          <recordfield>WORKFLOWSIGNAL.WORKFLOWSIGNALID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECT_CONDITION.value</name>
+          <recordfield>WORKFLOWSIGNAL.OBJECT_CONDITION</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>OBJECT_TYPE.value</name>
+          <recordfield>WORKFLOWSIGNAL.OBJECT_TYPE</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>SIGNAL_NAME.value</name>
+          <recordfield>WORKFLOWSIGNAL.SIGNAL_NAME</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TRIGGER_EVENT.value</name>
+          <recordfield>WORKFLOWSIGNAL.TRIGGER_EVENT</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TRIGGER_EVENT.displayValue</name>
+          <expression>%aditoprj%/entity/WorkflowSignal_entity/recordcontainers/db/recordfieldmappings/trigger_event.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PROCESSDEFINITION_KEY.value</name>
+          <recordfield>WORKFLOWSIGNAL.PROCESSDEFINITION_KEY</recordfield>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/WorkflowSignal_entity/entityfields/object_condition/valueProcess.js b/entity/WorkflowSignal_entity/entityfields/object_condition/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..8a7128421f3b6e6e5d154b230ca259e4f843dbbd
--- /dev/null
+++ b/entity/WorkflowSignal_entity/entityfields/object_condition/valueProcess.js
@@ -0,0 +1,23 @@
+import("Context_lib");
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("Attribute_lib");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
+{
+    var context = vars.getString("$field.OBJECT_TYPE");
+    var entity = ContextUtils.getEntity(context);
+    var emptyFilter = {entity: entity, filter: {type: "group", operator: "AND", childs: []}};
+
+    var currentFilter = vars.get("$this.value");
+    if (currentFilter)
+        currentFilter = JSON.parse(currentFilter);
+
+    //if the filter field is empty or if the entity was changed, reset the filter
+    if (!currentFilter || currentFilter.entity != emptyFilter.entity)
+    {
+        var condJson = JSON.stringify(emptyFilter);
+        result.string(condJson);
+    }
+}
\ No newline at end of file
diff --git a/entity/WorkflowSignal_entity/entityfields/processdefinition_key/valueProcess.js b/entity/WorkflowSignal_entity/entityfields/processdefinition_key/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..65a94b89933c5105c3abfb125ea08cd1a77c4b29
--- /dev/null
+++ b/entity/WorkflowSignal_entity/entityfields/processdefinition_key/valueProcess.js
@@ -0,0 +1,6 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
+    result.string(vars.get("$param.ProcessDefinitionKey_param"));
\ No newline at end of file
diff --git a/entity/WorkflowSignal_entity/entityfields/signal_name/dropDownProcess.js b/entity/WorkflowSignal_entity/entityfields/signal_name/dropDownProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..f61a89cec96de12e7b0e21d989540d72401de0f4
--- /dev/null
+++ b/entity/WorkflowSignal_entity/entityfields/signal_name/dropDownProcess.js
@@ -0,0 +1,13 @@
+//import("system.result");
+//import("system.workflow");
+//import("system.vars");
+//
+//var processDefinitionId = vars.get("$param.ProcessDefinitionId_param");
+//var signals = processDefinitionId
+//    ? JSON.parse(workflow.getSignalDefinitions(processDefinitionId))
+//    : [];
+//
+//result.object(signals.map(function (signal)
+//{
+//    return [signal.name, signal.name];
+//}));
\ No newline at end of file
diff --git a/entity/WorkflowSignal_entity/entityfields/triggerkeyword/children/containername_param/valueProcess.js b/entity/WorkflowSignal_entity/entityfields/triggerkeyword/children/containername_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..dee07a7bcce5662c3c52ee83659e3c64fcf52d10
--- /dev/null
+++ b/entity/WorkflowSignal_entity/entityfields/triggerkeyword/children/containername_param/valueProcess.js
@@ -0,0 +1,4 @@
+import("KeywordRegistry_basic");
+import("system.result");
+
+result.string($KeywordRegistry.workflowTrigger());
\ No newline at end of file
diff --git a/entity/WorkflowSignal_entity/recordcontainers/db/conditionProcess.js b/entity/WorkflowSignal_entity/recordcontainers/db/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1bae28698e6ca6fea69f1f2327b507defec4368e
--- /dev/null
+++ b/entity/WorkflowSignal_entity/recordcontainers/db/conditionProcess.js
@@ -0,0 +1,6 @@
+import("Sql_lib");
+import("system.result");
+
+var cond = newWhereIfSet("WORKFLOWSIGNAL.PROCESSDEFINITION_KEY", "$param.ProcessDefinitionKey_param");
+
+result.string(cond.toString());
\ No newline at end of file
diff --git a/entity/WorkflowSignal_entity/recordcontainers/db/recordfieldmappings/trigger_event.displayvalue/expression.js b/entity/WorkflowSignal_entity/recordcontainers/db/recordfieldmappings/trigger_event.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..f484f92b06795d86a986de789b39f35047dffbef
--- /dev/null
+++ b/entity/WorkflowSignal_entity/recordcontainers/db/recordfieldmappings/trigger_event.displayvalue/expression.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.workflowTrigger(), "WORKFLOWSIGNAL.TRIGGER_EVENT");
+result.string(sql);
\ No newline at end of file
diff --git a/entity/WorkflowTask_entity/WorkflowTask_entity.aod b/entity/WorkflowTask_entity/WorkflowTask_entity.aod
index f5ded376a8a6456237c30ff4ebfa04221760142a..f7a1b1a9539d11f520ea7dbbf9c294e6a9efcb95 100644
--- a/entity/WorkflowTask_entity/WorkflowTask_entity.aod
+++ b/entity/WorkflowTask_entity/WorkflowTask_entity.aod
@@ -104,18 +104,39 @@
       <title>Link</title>
       <linkedContextProcess>%aditoprj%/entity/WorkflowTask_entity/entityfields/target_id/linkedContextProcess.js</linkedContextProcess>
       <state>READONLY</state>
+      <displayValueProcess>%aditoprj%/entity/WorkflowTask_entity/entityfields/target_id/displayValueProcess.js</displayValueProcess>
     </entityField>
     <entityParameter>
       <name>TaskTitle_param</name>
       <expose v="true" />
     </entityParameter>
+    <entityActionField>
+      <name>claimTask</name>
+      <title>Claim task</title>
+      <onActionProcess>%aditoprj%/entity/WorkflowTask_entity/entityfields/claimtask/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:CLIPBOARD_USER</iconId>
+    </entityActionField>
+    <entityField>
+      <name>ISACTIVE</name>
+      <title>Active</title>
+      <contentType>BOOLEAN</contentType>
+    </entityField>
+    <entityField>
+      <name>CLAIM_TIME</name>
+      <title>Claim date</title>
+      <contentType>DATE</contentType>
+    </entityField>
+    <entityField>
+      <name>PRIORITY</name>
+      <title>Priority</title>
+    </entityField>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
       <name>jdito</name>
       <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
       <isFilterable v="true" />
-      <isSortable v="true" />
+      <isSortable v="false" />
       <contentProcess>%aditoprj%/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
       <onUpdate>%aditoprj%/entity/WorkflowTask_entity/recordcontainers/jdito/onUpdate.js</onUpdate>
       <recordFieldMappings>
@@ -173,7 +194,13 @@
           <name>TARGET_ID.value</name>
         </jDitoRecordFieldMapping>
         <jDitoRecordFieldMapping>
-          <name>TARGET_ID.displayValue</name>
+          <name>CLAIM_TIME.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>ISACTIVE.value</name>
+        </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>PRIORITY.value</name>
         </jDitoRecordFieldMapping>
       </recordFieldMappings>
     </jDitoRecordContainer>
diff --git a/entity/WorkflowTask_entity/entityfields/claimtask/onActionProcess.js b/entity/WorkflowTask_entity/entityfields/claimtask/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c7efdb62d29832c9280837e42b5d03e72c47f33a
--- /dev/null
+++ b/entity/WorkflowTask_entity/entityfields/claimtask/onActionProcess.js
@@ -0,0 +1,5 @@
+import("Employee_lib");
+import("system.vars");
+import("system.workflow");
+
+workflow.claimTask(vars.get("$field.UID"), EmployeeUtils.getCurrentUserId());
\ No newline at end of file
diff --git a/entity/WorkflowTask_entity/entityfields/target_id/displayValueProcess.js b/entity/WorkflowTask_entity/entityfields/target_id/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6114f95287815c744c4e9592fa363eeee8c70005
--- /dev/null
+++ b/entity/WorkflowTask_entity/entityfields/target_id/displayValueProcess.js
@@ -0,0 +1,7 @@
+import("Context_lib");
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+if (vars.get("$sys.viewmode") == neon.FRAME_VIEWMODE_DATASET && vars.get("$field.TARGET_ID"))
+    result.string(ContextUtils.loadContentTitle(ContextUtils.getEntity(vars.get("$field.TARGET_CONTEXT")), vars.get("$field.TARGET_ID")));
diff --git a/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js b/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js
index 9005006abf7ec25a907adc49073eac84509848be..a39ff9cc437f005db187284b4f87b8b6b73b0931 100644
--- a/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/WorkflowTask_entity/recordcontainers/jdito/contentProcess.js
@@ -36,7 +36,7 @@ result.object((function ()
         {
             //This can happen if the task is done, then it can't be loaded. If that's the case, return a dummy row
             var taskTitle = vars.exists("$param.TaskTitle_param") && vars.get("$param.TaskTitle_param") || "";
-            return [[taskId, translate.text("Task done"), taskTitle, "", vars.get("$sys.date"), "", "", "", "", "", "", "", "", "", "", "", ""]];
+            return [[taskId, translate.text("Task done"), taskTitle, "", vars.get("$sys.date"), "", "", "", "", "", "", "", "", "", "", "", "", "", ""]];
         }
     }
     else 
@@ -45,16 +45,22 @@ result.object((function ()
     //        loadConfig.candidateIdentifier(EmployeeUtils.getCurrentUserId());
         tasks = JSON.parse(workflow.getTasks(loadConfig));
     }
-
+    
+    var assigneeCache = {
+        get : function (pKey)
+        {
+            if (!pKey)
+                return "";
+            if (!(pKey in this))
+                this[pKey] = ContextUtils.loadContentTitle("Employee_entity", pKey);
+            return this[pKey];
+        }
+    };
+    
     tasks = tasks.map(function (task)
     {
         var variables = JSON.parse(workflow.getTaskVariables(task.id));
-        var targetTitle = "";
-        if (variables.targetId && variables.targetContext)
-            targetTitle = ContextUtils.loadContentTitle(project.getContextStructure(variables.targetContext).entity, variables.targetId); 
-
-        var assigneeName = task.assignee ? ContextUtils.loadContentTitle("Employee_entity", task.assignee) : "";
-
+        
         return [
             task.id,
             task.name,
@@ -67,12 +73,14 @@ result.object((function ()
             task.description || "",
             task.category || "",
             task.assignee || "",
-            assigneeName,
+            assigneeCache.get(task.assignee),
             task.dueDate ? Date.parse(task.dueDate).toString() : "",
             task.owner || "",
             variables.targetContext || "",
             variables.targetId || "",
-            targetTitle
+            task.claimTime,
+            task.active,
+            task.priority
         ];
     });
 
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index cb85861453796c00b63d267476abcda4f803c6d1..d6cfab21d345b7514e619d3e44ccd9b00ea15118 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -6071,6 +6071,12 @@
     <entry>
       <key>Task done</key>
     </entry>
+    <entry>
+      <key>{SEARCH_INDEX_TITLE}</key>
+    </entry>
+    <entry>
+      <key>${CANCELLED}</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
   <sqlModels>
diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
index 02cbaeb8e0b3ab789f0842d11e0d8410ad4e9be2..8dcdc61707fa3ffe4a65f4477e3b5fb03690430d 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -6,6 +6,10 @@
   <country></country>
   <variant></variant>
   <keyValueMap>
+    <entry>
+      <key>{SEARCH_INDEX_TITLE}</key>
+      <value>Suche</value>
+    </entry>
     <entry>
       <key>Data imported. Contact not found.</key>
       <value>Daten importiert. Keine weiteren Personendaten gefunden.</value>
@@ -201,6 +205,10 @@
       <key>Send</key>
       <value>Senden</value>
     </entry>
+    <entry>
+      <key>${ORDER_CANCELLED}</key>
+      <value>Storniert</value>
+    </entry>
     <entry>
       <key>CONFIRMED</key>
       <value>Gelesen</value>
@@ -1941,7 +1949,7 @@
     </entry>
     <entry>
       <key>Orderitem</key>
-      <value>Bestellposition </value>
+      <value>Belegposten</value>
     </entry>
     <entry>
       <key>The order number already exists!</key>
@@ -4095,7 +4103,7 @@
     </entry>
     <entry>
       <key>Would you really like to clear the forecast and set the state to '%0'?</key>
-      <value>Möchten Sie wirklich den Forecast löschen und den status auf '%0' setzen?</value>
+      <value>Möchten Sie wirklich den Forecast löschen und den Status auf '%0' setzen?</value>
     </entry>
     <entry>
       <key>This cannot be undone!</key>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index 1046ff8c697f07b596951ec0956801e7821eaa8a..90ce4c7dde7e321231c5e7675790cb42502c7730 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -6,6 +6,10 @@
   <country></country>
   <variant></variant>
   <keyValueMap>
+    <entry>
+      <key>${ORDER_CANCELLED}</key>
+      <value>cancelled</value>
+    </entry>
     <entry>
       <key>Company</key>
     </entry>
@@ -4108,6 +4112,7 @@
     </entry>
     <entry>
       <key>{$TICKET_REQUESTOR}</key>
+      <value>Requestor</value>
     </entry>
     <entry>
       <key>Billable</key>
@@ -4150,6 +4155,7 @@
     </entry>
     <entry>
       <key>{$TICKET_STATUS}</key>
+      <value>Status</value>
     </entry>
     <entry>
       <key>DATE_NEW</key>
@@ -4183,6 +4189,8 @@
     </entry>
     <entry>
       <key>{$TICKET_EDITOR}</key>
+      <value>Editor
+</value>
     </entry>
     <entry>
       <key>Support ticket</key>
@@ -6121,6 +6129,10 @@
     <entry>
       <key>Task done</key>
     </entry>
+    <entry>
+      <key>{SEARCH_INDEX_TITLE}</key>
+      <value>Search</value>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/WorkflowSignal/WorkflowSignal.aod b/neonContext/WorkflowSignal/WorkflowSignal.aod
new file mode 100644
index 0000000000000000000000000000000000000000..af6b238d6feb60c6467deb3b70de3624cb81ce94
--- /dev/null
+++ b/neonContext/WorkflowSignal/WorkflowSignal.aod
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1">
+  <name>WorkflowSignal</name>
+  <title>Workflow signal</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterView>WorkflowSignalFilter_view</filterView>
+  <editView>WorkflowSignalEdit_view</editView>
+  <entity>WorkflowSignal_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>5dd8a1ec-6279-4f85-ae49-d3d82a62d1dc</name>
+      <view>WorkflowSignalFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>0709bd97-560a-4a01-8e26-2993388956f3</name>
+      <view>WorkflowSignalEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>9395ba99-8725-43f4-998b-9865916f9a0f</name>
+      <view>WorkflowSignalPreview_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonNotificationType/WorkflowsStarted/WorkflowsStarted.aod b/neonNotificationType/WorkflowsStarted/WorkflowsStarted.aod
new file mode 100644
index 0000000000000000000000000000000000000000..a4104e98672a86f9cdc603aa66ac55af4307082d
--- /dev/null
+++ b/neonNotificationType/WorkflowsStarted/WorkflowsStarted.aod
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0">
+  <name>WorkflowsStarted</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+</neonNotificationType>
diff --git a/neonView/CampaignParticipantFilter_view/CampaignParticipantFilter_view.aod b/neonView/CampaignParticipantFilter_view/CampaignParticipantFilter_view.aod
index f14aec7855cf0255ba1183ce2c66528b8df6f810..b8535da0fa3b1cf54c38afc394d35b24b758dc3a 100644
--- a/neonView/CampaignParticipantFilter_view/CampaignParticipantFilter_view.aod
+++ b/neonView/CampaignParticipantFilter_view/CampaignParticipantFilter_view.aod
@@ -4,7 +4,7 @@
   <title></title>
   <description></description>
   <majorModelMode>DISTRIBUTED</majorModelMode>
-  <filterable v="true" />
+  <filterable v="false" />
   <layout>
     <boxLayout>
       <name>layout</name>
diff --git a/neonView/ContactEdit_view/ContactEdit_view.aod b/neonView/ContactEdit_view/ContactEdit_view.aod
index 57b9d54b6582c3adb5963d5f7dd35e26a693326e..984937de088b6e08d4b4e82cfea5a59239c1d724 100644
--- a/neonView/ContactEdit_view/ContactEdit_view.aod
+++ b/neonView/ContactEdit_view/ContactEdit_view.aod
@@ -44,10 +44,5 @@
       <entityField>Communications</entityField>
       <view>CommunicationMultiEdit_view</view>
     </neonViewReference>
-    <neonViewReference>
-      <name>3e90f469-405f-46e4-9fed-ce017dc0c222</name>
-      <entityField>ContactAddresses</entityField>
-      <view>AdressMultiEdit_view</view>
-    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/IndexSearchView/IndexSearchView.aod b/neonView/IndexSearchView/IndexSearchView.aod
index 18ac9a16b8e5476b2db97df5f40c47b44aa56984..0881d14f771aa6835de89c6d64c5a68522000a60 100644
--- a/neonView/IndexSearchView/IndexSearchView.aod
+++ b/neonView/IndexSearchView/IndexSearchView.aod
@@ -5,7 +5,7 @@
   <dashletConfigurations>
     <neonDashletConfiguration>
       <name>IndexSearchDashlet</name>
-      <title>Indexsearch</title>
+      <title>{SEARCH_INDEX_TITLE}</title>
       <description>Possibility to search for terms</description>
       <fragment>IndexSearchContext/full</fragment>
       <storeRoles />
@@ -13,7 +13,7 @@
       <categories>
         <neonDashletCategory>
           <name>indexsearch</name>
-          <title>Indexsearch</title>
+          <title>{SEARCH_INDEX_TITLE}</title>
         </neonDashletCategory>
       </categories>
     </neonDashletConfiguration>
diff --git a/neonView/PermissionDetailPreview_view/PermissionDetailPreview_view.aod b/neonView/PermissionDetailPreview_view/PermissionDetailPreview_view.aod
index 9c9b03f007f26a30a44a5c063c3cef60cfc46050..c11a516e1055b797d20cb7062f88fc69dba1465c 100644
--- a/neonView/PermissionDetailPreview_view/PermissionDetailPreview_view.aod
+++ b/neonView/PermissionDetailPreview_view/PermissionDetailPreview_view.aod
@@ -17,9 +17,8 @@
     </cardViewTemplate>
     <genericViewTemplate>
       <name>Generic</name>
-      <editMode v="true" />
       <entityField>#ENTITY</entityField>
-      <isEditable v="false" />
+      <isEditable v="true" />
       <fields>
         <entityFieldLink>
           <name>dd33df7a-82e6-49a8-b35f-99d0187970e3</name>
diff --git a/neonView/PersonEdit_view/PersonEdit_view.aod b/neonView/PersonEdit_view/PersonEdit_view.aod
index 31a7ce9e2a1e18af149aa43376ef3dac2501c08b..b620a7e0e35d67ea4fa7bf484890de5aec36b4d0 100644
--- a/neonView/PersonEdit_view/PersonEdit_view.aod
+++ b/neonView/PersonEdit_view/PersonEdit_view.aod
@@ -22,6 +22,10 @@
       <showDrawer v="false" />
       <entityField>#ENTITY</entityField>
       <fields>
+        <entityFieldLink>
+          <name>d8d04e36-de46-48a3-994a-fa72d1f2ea89</name>
+          <entityField>LANGUAGE</entityField>
+        </entityFieldLink>
         <entityFieldLink>
           <name>7a647c90-3a1c-4f8d-9ecd-6bdf35ab2f80</name>
           <entityField>ORGANISATION_CONTACTID</entityField>
@@ -54,10 +58,6 @@
           <name>74de507e-75e0-4957-a4fb-7070fa3c5a4a</name>
           <entityField>DATEOFBIRTH</entityField>
         </entityFieldLink>
-        <entityFieldLink>
-          <name>d8d04e36-de46-48a3-994a-fa72d1f2ea89</name>
-          <entityField>LANGUAGE</entityField>
-        </entityFieldLink>
         <entityFieldLink>
           <name>f8ec0e41-7ead-4c80-878c-df75ce5fce34</name>
           <entityField>STATUS</entityField>
diff --git a/neonView/WorkflowDefinitionMain_view/WorkflowDefinitionMain_view.aod b/neonView/WorkflowDefinitionMain_view/WorkflowDefinitionMain_view.aod
index 8db78b1723af1159e1c454f188856b8e97f44adc..20311ee8d908f6844f16cf562f4fbe80e56f9dea 100644
--- a/neonView/WorkflowDefinitionMain_view/WorkflowDefinitionMain_view.aod
+++ b/neonView/WorkflowDefinitionMain_view/WorkflowDefinitionMain_view.aod
@@ -34,5 +34,10 @@
       <entityField>StartConfigs</entityField>
       <view>WorkflowStartConfigFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>1a6329e9-8992-482b-82b6-fd01e09c6be1</name>
+      <entityField>Signals</entityField>
+      <view>WorkflowSignalFilter_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/WorkflowSignalEdit_view/WorkflowSignalEdit_view.aod b/neonView/WorkflowSignalEdit_view/WorkflowSignalEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..bc9418f3b332f756c78f580e82f6d6dfc56855b0
--- /dev/null
+++ b/neonView/WorkflowSignalEdit_view/WorkflowSignalEdit_view.aod
@@ -0,0 +1,36 @@
+<?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.4" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.4">
+  <name>WorkflowSignalEdit_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>937b8a52-58ab-49d3-80c7-ea98310632dd</name>
+          <entityField>SIGNAL_NAME</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>bc88a7a6-6843-40c0-86ad-265424e98fb1</name>
+          <entityField>TRIGGER_EVENT</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>eb71448c-b176-4b12-a4d7-a46e2f242020</name>
+          <entityField>OBJECT_TYPE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>648536a5-2327-433e-8867-a3d60a0f8787</name>
+          <entityField>OBJECT_CONDITION</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/WorkflowSignalFilter_view/WorkflowSignalFilter_view.aod b/neonView/WorkflowSignalFilter_view/WorkflowSignalFilter_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..bee3e15b46d1454b339d9fe3841fddd6d85409e8
--- /dev/null
+++ b/neonView/WorkflowSignalFilter_view/WorkflowSignalFilter_view.aod
@@ -0,0 +1,31 @@
+<?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.4" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.4">
+  <name>WorkflowSignalFilter_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="true" />
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>Table</name>
+      <entityField>#ENTITY</entityField>
+      <columns>
+        <neonTableColumn>
+          <name>80fa7f03-9064-42f2-95bd-bebc23ca3e62</name>
+          <entityField>SIGNAL_NAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>c23ed9c6-7baa-4742-ba1e-d771f98167d5</name>
+          <entityField>TRIGGER_EVENT</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>44a02634-1b88-49e8-8125-5bc22e31683d</name>
+          <entityField>OBJECT_TYPE</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/WorkflowSignalPreview_view/WorkflowSignalPreview_view.aod b/neonView/WorkflowSignalPreview_view/WorkflowSignalPreview_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..2b648167cc55f5892350e33645fec4ca4c398bf5
--- /dev/null
+++ b/neonView/WorkflowSignalPreview_view/WorkflowSignalPreview_view.aod
@@ -0,0 +1,10 @@
+<?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.4" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.4">
+  <name>WorkflowSignalPreview_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <headerFooterLayout>
+      <name>layout</name>
+    </headerFooterLayout>
+  </layout>
+</neonView>
diff --git a/neonView/WorkflowTaskPreview_view/WorkflowTaskPreview_view.aod b/neonView/WorkflowTaskPreview_view/WorkflowTaskPreview_view.aod
index e8c0235a6fb352faced599759b553d81eb055eec..661e81ca14968a258618510742be351d5ba1bb80 100644
--- a/neonView/WorkflowTaskPreview_view/WorkflowTaskPreview_view.aod
+++ b/neonView/WorkflowTaskPreview_view/WorkflowTaskPreview_view.aod
@@ -47,6 +47,18 @@
           <name>63697864-5b0b-471f-89fc-60621fecbaec</name>
           <entityField>TARGET_ID</entityField>
         </entityFieldLink>
+        <entityFieldLink>
+          <name>232670b6-4923-4e8d-bfa0-8720e57e932a</name>
+          <entityField>ISACTIVE</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>d193bea1-a470-4403-bce7-446e3b398540</name>
+          <entityField>PRIORITY</entityField>
+        </entityFieldLink>
+        <entityFieldLink>
+          <name>f93aeea0-7881-4284-957a-f4a300cdeeef</name>
+          <entityField>OWNER</entityField>
+        </entityFieldLink>
       </fields>
     </genericViewTemplate>
   </children>
diff --git a/process/Attribute_lib/process.js b/process/Attribute_lib/process.js
index 9c2bd2c0a441a26783658242b4dc2e26b310c876..7d3794c3adde49b3ad78259a7da03916aa7e7ba4 100644
--- a/process/Attribute_lib/process.js
+++ b/process/Attribute_lib/process.js
@@ -1057,7 +1057,7 @@ AttributeUsageUtil.insertChildrenUsages = function (pAttributeId, pObjectType)
     function _addInserts (pAttributeId, pObjectType)
     {
         var attributes = newSelect(["AB_ATTRIBUTEID", "ATTRIBUTE_TYPE",
-                                newSelect("count(*) = 0")
+                                newSelect("count(*)")
                                     .from("AB_ATTRIBUTEUSAGE")
                                     .where("AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = AB_ATTRIBUTE.AB_ATTRIBUTEID")
                                     .and("AB_ATTRIBUTEUSAGE.OBJECT_TYPE", pObjectType)])
@@ -1068,7 +1068,7 @@ AttributeUsageUtil.insertChildrenUsages = function (pAttributeId, pObjectType)
 
         attributes.forEach(function (row)
         {
-            if (row[2] == "true")
+            if (row[2] == "0")
             {
                 let maxCount = AttributeTypeUtil.isSingleSelection(row[1])
                     ? "1"
diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js
index 000b21342c59c724b1fa38fcaf718ba4b5881c7d..26d5997206feb96007911d3068aa687a14bf9628 100644
--- a/process/Context_lib/process.js
+++ b/process/Context_lib/process.js
@@ -35,14 +35,29 @@ ContextUtils.getCurrentContextId = function()
  * Returns the title of the context
  * 
  * @param {String} pContextId id of the context
- * @param {boolean} [pTranslate=false] if the title should be translated
+ * @param {boolean} [pAutoTranslate=false] pass "true" if the title should be translated with the current locale
  * 
  * @return {String} title of the context
  */
-ContextUtils.getTitle = function(pContextId, pTranslate)
+ContextUtils.getTitle = function(pContextId, pAutoTranslate)
 {
-    var title = project.getDataModel(project.DATAMODEL_KIND_CONTEXT, pContextId)[1];
-    return pTranslate ? translate.text(title) : title;
+    var dataModel = project.getDataModel(project.DATAMODEL_KIND_CONTEXT, pContextId);
+    var title = dataModel[1];
+    return pAutoTranslate ? translate.text(title) : title;
+}
+
+/**
+ * Returns the translated title of the context
+ * 
+ * @param {String} pContextId id of the context
+ * @param {String} [pLocale=null] the locale for the translation, e.g. "de_DE"
+ * 
+ * @return {String} title of the context, translated to the given (or default) locale
+ */
+ContextUtils.getTranslatedTitle = function(pContextId, pLocale)
+{
+    var title = ContextUtils.getTitle(pContextId, false);
+    return pLocale ? translate.text(title, pLocale) : translate.text(title);
 }
 
 /**
@@ -57,6 +72,19 @@ ContextUtils.getIcon = function(pContextId)
     return project.getDataModel(project.DATAMODEL_KIND_CONTEXT, pContextId)[5];
 }
 
+/**
+ * Returns the entity associated with the context
+ * 
+ * @param {String} pContextId id of the context
+ * @return {String} the entity
+ */
+ContextUtils.getEntity = function (pContextId)
+{
+    if (!pContextId)
+        return null;
+    return project.getContextStructure(pContextId).entity;
+}
+
 /**
  * Returns the title of the entity associated with the context
  * 
@@ -67,8 +95,7 @@ ContextUtils.getIcon = function(pContextId)
  */
 ContextUtils.getEntityTitle = function (pContextId, pTranslate)
 {
-    var entity = project.getContextStructure(pContextId).entity;
-    var title = project.getDataModel(project.DATAMODEL_KIND_ENTITY, entity)[1];
+    var title = project.getDataModel(project.DATAMODEL_KIND_ENTITY, ContextUtils.getEntity(pContextId))[1];
     return pTranslate ? translate.text(title) : title;
 }
 
diff --git a/process/ImporterMappingFunctions_lib/process.js b/process/ImporterMappingFunctions_lib/process.js
index 6aac697100b39082af111adfeeb977d22b833802..47f80a6506c12ec6d36401548fef555824482957 100644
--- a/process/ImporterMappingFunctions_lib/process.js
+++ b/process/ImporterMappingFunctions_lib/process.js
@@ -8,6 +8,7 @@ import("system.util");
 import("system.datetime");
 import("system.logging");
 import("Attribute_lib");
+import("KeywordRegistry_basic");
 import("Sql_lib");
 import("Importer_lib");
 
@@ -60,116 +61,142 @@ function iKeyword(pObject) {
 
 /*
  * Values of the mapping line:
- * Attribute req -- the new attribute name
- * AType req -- the type of the attribute
- * OType opt -- the type of the object (AB_ATTRIBUTEUSAGE)
- * OID opt -- the row id for the object instance (AB_ATTRIBUTERELATION)
- * Value opt -- the value for the object instance (AB_ATTRIBUTERELATION)
+ * attribute (required): The new attribute name.
+ * attributeType (required): The type of the attribute e.g 'GROUP'.
+ * objectType (optional): The type of the object (AB_ATTRIBUTEUSAGE).
+ * objectId (optional): The OBJECT_ROWID for the object instance (AB_ATTRIBUTERELATION).
+ * value (optional): The value for the object instance (AB_ATTRIBUTERELATION).
  *
  * @name iAttribute
  * @param {Object} pObject req the mapping line
  * @return {Boolean} true
  * */
-function iAttribute(pObject) {
+
+function iAttribute(pObject) 
+{
     if (!this.doIfCheck(pObject)) return true;
 
-    var attribute = this.InputRecord[pObject.Attribute];
-    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.Attribute);
-    var atype = this.InputRecord[pObject.AType];
-    if(atype == undefined) atype = this.resolveSymbol(pObject, pObject.AType);
-    var otype = this.InputRecord[pObject.OType];
-    if(otype == undefined) otype = this.resolveSymbol(pObject, pObject.OType);
-    var oid = this.InputRecord[pObject.OID];
-    if(oid == undefined) oid = this.resolveSymbol(pObject, pObject.OID);
-    var value = this.InputRecord[pObject.Value];
-    if(value == undefined) value = this.resolveSymbol(pObject, pObject.Value);
+    var attribute = this.InputRecord[pObject.attribute];
+    var attributeType = this.InputRecord[pObject.attributeType];
+    var objectType = this.InputRecord[pObject.objectType];
+    var objectId = this.InputRecord[pObject.objectId];
+    var value = this.InputRecord[pObject.value];
+    
+    var alias = this.Config.AliasTo;
+    var funcBuffer = this.FuncBuffer.iAttribute;
+    var ab_attribute = this.getTableCase("ab_attribute");
+    var ab_attributeId = this.getColumnCase("ab_attribute.ab_attributeid");
+    var attribute_parent_id = this.getColumnCase("ab_attribute.attribute_parent_id");
+    var attribute_name = this.getColumnCase("ab_attribute.attribute_name");
+    var attribute_type = this.getColumnCase("ab_attribute.attribute_type");
+    var attribute_active = this.getColumnCase("ab_attribute.attribute_active");
+    var ab_attributeUsage = this.getTableCase("ab_attributeusage");
+    var ab_attributeUsageId = this.getColumnCase("ab_attributeusage.ab_attributeusageid");
+    var attrU_ab_attribute_id = this.getColumnCase("ab_attributeusage.ab_attribute_id");
+    var attrU_object_type = this.getColumnCase("ab_attributeusage.object_type");
+    var ab_attributeRelation = this.getTableCase("ab_attributerelation");
+    var attrRel_ab_attribute_id = this.getColumnCase("ab_attributerelation.ab_attribute_id"); 
+    var ab_attributeRelationId = this.getColumnCase("ab_attributerelation.ab_attributerelationid");
+    var object_rowId = this.getColumnCase("ab_attributerelation.object_rowid");
+    var attrRel_object_type = this.getColumnCase("ab_attributerelation.object_type")
     
-    if (!attribute || !atype) return true;
-    atype = atype.toUpperCase();
+    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.attribute);
+    if(attributeType == undefined) attributeType = this.resolveSymbol(pObject, pObject.attributeType);
+    if(objectType == undefined) objectType = this.resolveSymbol(pObject, pObject.objectType);
+    if(objectId == undefined) objectId = this.resolveSymbol(pObject, pObject.objectId);
+    if(value == undefined) value = this.resolveSymbol(pObject, pObject.value);
+    
+    if (!attribute || !attributeType) return true;
+    attributeType = attributeType.toUpperCase();
 
     var valueColumn = "";
     var attributes = attribute.split(".");   
-    var columns = [this.getColumnCase("ab_attributeid"), this.getColumnCase("attribute_parent_id"), this.getColumnCase("attribute_name"), 
-    this.getColumnCase("attribute_type"), this.getColumnCase("attribute_level"), this.getColumnCase("attribute_active")];
+    var columns = [ab_attributeId, attribute_parent_id, attribute_name, attribute_type, attribute_active];
     var type = $AttributeTypes.GROUP.toString();
-    switch (atype) {
-        case $AttributeTypes.TEXT.toString():
-            valueColumn = this.getColumnCase("char_value");
-            break;
-        case $AttributeTypes.DATE.toString():
-            valueColumn = this.getColumnCase("date_value");
-            break;
-        case $AttributeTypes.NUMBER.toString():
-            valueColumn = this.getColumnCase("number_value");
-            break;
-        case $AttributeTypes.BOOLEAN.toString():
-            valueColumn = this.getColumnCase("bool_value");
-            break;
+
+    if ($AttributeTypes[attributeType] == undefined) 
+    {
+        this.writeLog(this.LogLevels.Error, "iAttribute: " + attributeType + " isn't a valid attribute type.");
+        return false;
+    }
+
+    switch (attributeType) 
+    {
         case $AttributeTypes.COMBO.toString():
-            valueColumn = this.getColumnCase("id_value");
+            valueColumn = $AttributeTypes[attributeType].databaseField;
             type = $AttributeTypes.COMBO.toString();
             break;
         default:
-            return true;
+            valueColumn = $AttributeTypes[attributeType].databaseField;
     }
 
-    if (this.FuncBuffer.iAttribute == undefined) this.FuncBuffer.iAttribute = {
-        childs: {}
-    };
-    var pathToFollow = this.FuncBuffer.iAttribute;
-    for (var i = 0; i < attributes.length; i++)  {
-        if (pathToFollow["childs"][attributes[i]] != undefined) {
-            var id = pathToFollow["childs"][attributes[i]]["id"];            
-        } else {
-            pathToFollow["childs"][attributes[i]] = {
-                id: id, 
-                childs: {}
-            };
-            if (i == 0) {
-                var parent = "NULL";  
-                var sql = "select " + this.getColumnCase("ab_attributeid") + " from  " + this.getTableCase("ab_attribute") + " where " 
-                + this.getColumnCase("attribute_name") + " = ? and " + this.getColumnCase("attribute_level") + " = 0";
-                id = db.cell([sql, [[attributes[i], SQLTYPES.VARCHAR]]], this.Config.AliasTo);                         
-            } else {
+    if (funcBuffer == undefined) funcBuffer = {childs: {}};
+    var pathToFollow = funcBuffer;
+
+    for (var i = 0; i < attributes.length; i++) 
+    {    
+        if (pathToFollow["childs"][attributes[i]] != undefined) var id = pathToFollow["childs"][attributes[i]]["id"];
+        else 
+        {
+            pathToFollow["childs"][attributes[i]] = {id: id, childs: {}};
+            
+            if (i == 0) 
+            {
+                var parent = "NULL";
+                // select ab_attributeid from AB_ATTRIBUTE where ATTRIBUTE_NAME = 'Subordinate campaign of' and attribute_parent_id is null
+                id = newSelect(ab_attributeId, alias).from(ab_attribute).where(attribute_name, attributes[i])
+                        .and(attribute_parent_id, "is null").cell();
+            } 
+            else 
+            {
                 parent = pathToFollow["id"];
-                sql = "select " + this.getColumnCase("ab_attributeid") + " from " + this.getTableCase("ab_attribute") + " where " 
-                + this.getColumnCase("attribute_name") + " = ? and " + this.getColumnCase("attribute_parent_id") + " = ?";
-                id = db.cell([sql, [[attributes[i], SQLTYPES.VARCHAR], [parent, SQLTYPES.CHAR]]], this.Config.AliasTo);                         
-            }       
-            if (id == "" || id == null) {
+                id = newSelect(ab_attributeId, alias).from(ab_attribute).where(attribute_name, attributes[i])
+                        .and(attribute_parent_id, parent).cell();
+            }
+            
+            if (id == "" || id == null) 
+            {
                 id = util.getNewUUID();
-                if (attributes.length == i+1) type = atype;
-                //TODO: add insertNoWait to instantly add AB_ATTRIBUTE records; this ensures that nothing is in the funcBuffer that does not exist in the database
+                if (attributes.length == i+1) type = attributeType;
+                //TODO: add insertNoWait to instantly add AB_ATTRIBUTE records; 
+                //this ensures that nothing is in the funcBuffer that does not exist in the database
                 //TODO: check: are COMOB-values added automatically?
-                this.insertData(this.getTableCase("ab_attribute"), columns, null, [id, parent, attributes[i], type, i.toString(), "1"], this.Config.AliasTo);
-            }
-            pathToFollow["childs"][attributes[i]]["id"] = id;
+                var values = [id, parent, attributes[i], type, "1"];
+                this.insertData(ab_attribute, columns, null, values, alias);
+            }   
+            pathToFollow["childs"][attributes[i]]["id"] = id;   
         }
         pathToFollow = pathToFollow["childs"][attributes[i]];
-    } 
+    }
     
-    if (otype) {
-        var aid = id;
-        sql = "select " + this.getColumnCase("ab_attributeusageid") + " from " + this.getTableCase("ab_attributeusage") + " where "
-        + this.getColumnCase("ab_attribute_id") + " = ? and " + this.getColumnCase("object_type") + " = ?";
-        id = db.cell([sql, [[aid, SQLTYPES.CHAR], [otype, SQLTYPES.VARCHAR]]], this.Config.AliasTo);      
-        if (id == "" || id == null) {
-            columns = [this.getColumnCase("ab_attributeusageid"), this.getColumnCase("ab_attribute_id"), this.getColumnCase("object_type")];
-            this.insertData(this.getTableCase("ab_attributeusage"), columns, null, [util.getNewUUID(), aid, otype], this.Config.AliasTo);
+    if (objectType) 
+    {
+        var attributeId = id;
+        id = newSelect(ab_attributeUsageId, alias).from(ab_attributeUsage).where(attrU_ab_attribute_id, attributeId)
+                .and(attrU_object_type, objectType).cell();
+        
+        if (id == "" || id == null) 
+        {
+            columns = [ab_attributeUsageId, attrU_ab_attribute_id, attrU_object_type];
+            values = [util.getNewUUID(), attributeId, objectType];
+            this.insertData(ab_attributeUsage, columns, null, values, alias);
         } 
         
-        if (value && oid) {
-            sql = "select " + this.getColumnCase("ab_attributerelationid") + " from " + this.getTableCase("ab_attributerelation") + " where " 
-            + this.getColumnCase("ab_attribute_id") + " = ? and " + this.getColumnCase("object_rowid") + " = ? and "
-            + this.getColumnCase("object_type") + " = ?";
-            id = db.cell([sql, [[aid, SQLTYPES.CHAR], [oid, SQLTYPES.CHAR], [otype, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
-            if (id == "" || id == null) {
-                columns = [this.getColumnCase("ab_attributerelationid"), this.getColumnCase("ab_attribute_id"), this.getColumnCase("object_type"),
-                this.getColumnCase("object_rowid"), valueColumn];
-                this.insertData(this.getTableCase("ab_attributerelation"), columns, null, [util.getNewUUID(), aid, otype, oid, value], this.Config.AliasTo);
-            } else if (this.Config.ImportCommand.indexOf("update") != -1) {
-                cond = this.getColumnCase("ab_attributerelationid") + " = '" + id + "'";
-                this.updateData(this.getTableCase("ab_attributerelation"), [valueColumn], null, [value], cond, this.Config.AliasTo);
+        if (value && objectId) 
+        {
+            id = newSelect(ab_attributeRelationId, alias).from(ab_attributeRelation).where(attrRel_ab_attribute_id, attributeId)
+                    .and(object_rowId, objectId).and(attrRel_object_type, objectType).cell();
+            
+            if (id == "" || id == null) 
+            {
+                columns = [ab_attributeRelationId, attrRel_ab_attribute_id, attrRel_object_type, object_rowId, valueColumn];
+                values = [util.getNewUUID(), attributeId, objectType, objectId, value];
+                this.insertData(ab_attributeRelation, columns, null, values, alias);
+            } 
+            else if (this.Config.ImportCommand.indexOf("update") != -1)
+            {
+                cond = ab_attributeRelationId + " = '" + id + "'";
+                this.updateData(ab_attributeRelation, [valueColumn], null, [value], cond, alias);
             }
         }
     }    
@@ -178,90 +205,134 @@ function iAttribute(pObject) {
 
 /*
  * Values of the mapping line:
- * Attribute req -- the column index with the new attribute value
- * AType req -- the type of the attribute
- * Container req -- the container name of the keyword
- * Keyword opt -- a new keyword name or an existing KeyId (AB_KEYWORD_ATTRIBUTERELATION)
- * Value opt - the value of the relation (AB_KEYWORD_ATTRIBUTERELATION)
+ * - attribute (required): The column index with the new attribute value.
+ * - attributeType (required): The type of the attribute.
+ * - keywordContainer (required): The container name of the keyword.
+ * - keyword (optional): A new keyword name or an existing KeyId (AB_KEYWORD_ATTRIBUTERELATION).
+ * - value (optional): The value of the relation (AB_KEYWORD_ATTRIBUTERELATION).
  *
  * @name iKeywordAttribute
- * @param {Object} pObject req the mapping line
+ * @param {Object} pObject (required) the mapping line.
  * @return {Boolean} true
  * */
+
 function iKeywordAttribute(pObject) {
     if (!this.doIfCheck(pObject)) return true;
     
-    var attribute = this.InputRecord[pObject.Attribute];
-    if(attribute == undefined) attribute = this.resolveSymbol(pObject, pObject.Attribute);
-    var atype = this.InputRecord[pObject.AType];
-    if(atype == undefined) atype = this.resolveSymbol(pObject, pObject.AType);
-    var container = this.InputRecord[pObject.Container];
-    if(container == undefined) container = this.resolveSymbol(pObject, pObject.Container);
-    var keyword = this.InputRecord[pObject.Keyword];
-    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.Keyword);
-    var value = this.InputRecord[pObject.Value];
-    if(value == undefined) value = this.resolveSymbol(pObject, pObject.Value);
+    var keywordAttribute = this.InputRecord[pObject.attribute];
+    if(keywordAttribute == undefined) keywordAttribute = this.resolveSymbol(pObject, pObject.attribute);
+
+    var keywordAttributeType = this.InputRecord[pObject.attributeType];
+    if(keywordAttributeType == undefined) keywordAttributeType = this.resolveSymbol(pObject, pObject.attributeType);
+
+    var keywordContainer = this.InputRecord[pObject.keywordContainer];
+    if(keywordContainer == undefined) keywordContainer = this.resolveSymbol(pObject, pObject.keywordContainer);
     
-    if (!attribute || !container || !atype) return true;
-    atype = atype.toUpperCase();
+    var keyword = this.InputRecord[pObject.keyword];
+    if(keyword == undefined) keyword = this.resolveSymbol(pObject, pObject.keyword);
+    
+    var keywordAttrRelValue = this.InputRecord[pObject.keywordAttrRelValue];
+    if(keywordAttrRelValue == undefined) keywordAttrRelValue = this.resolveSymbol(pObject, pObject.keywordAttrRelValue);
+    
+    if (!keywordAttribute || !keywordContainer || !keywordAttributeType) return true;
+    keywordAttributeType = keywordAttributeType.toUpperCase();
     
     var valueColumn = "";
-    switch (atype) {
-        case $AttributeTypes.TEXT.toString():
+    
+    switch (keywordAttributeType) {
+        case $KeywordRegistry.keywordAttributeType$char():
             valueColumn = this.getColumnCase("char_value");
             break;
-        case $AttributeTypes.NUMBER.toString():
+        case $KeywordRegistry.keywordAttributeType$number():
             valueColumn = this.getColumnCase("number_value");           
             break;
-        case $AttributeTypes.BOOLEAN.toString():
+        case $KeywordRegistry.keywordAttributeType$bool():
             valueColumn = this.getColumnCase("bool_value");         
             break;
+        case $KeywordRegistry.keywordAttributeType$longChar():
+            valueColumn = this.getColumnCase("long_char_value");
+            break;
         default:
             return true;
     }
     
-    var sql = "select " + this.getColumnCase("ab_keyword_attributeid") + " from  " + this.getTableCase("ab_keyword_attribute") 
-    + " where " + this.getColumnCase("name") + " = ? and " + this.getColumnCase("container") + " = ?";
-    var aid = db.cell([sql, [[attribute, SQLTYPES.VARCHAR], [container, SQLTYPES.VARCHAR]]], this.Config.AliasTo); 
-    if (aid == "" || aid == null) {
-        aid = util.getNewUUID();
-        var columns = [this.getColumnCase("ab_keyword_attributeid"), this.getColumnCase("name"), this.getColumnCase("container"), this.getColumnCase("type")];
-        this.insertData(this.getTableCase("ab_keyword_attribute"), columns, null, [aid, attribute, container, atype], this.Config.AliasTo);
+    var sql = "select " + this.getColumnCase("ab_keyword_attributeid") 
+    + " from  " + this.getTableCase("ab_keyword_attribute") 
+    + " where " + this.getColumnCase("name") 
+    + " = ? and " + this.getColumnCase("container") + " = ?";
+
+    var attributeId = db.cell([sql, [[keywordAttribute, SQLTYPES.VARCHAR], [keywordContainer, SQLTYPES.VARCHAR]]], this.Config.AliasTo); 
+    
+    // Creates the entry in AB_KEYWORD_ATTRIBUTE, case if it not exists.
+    if (attributeId == "" || attributeId == null) {
+        attributeId = util.getNewUUID();
+        var columns = [this.getColumnCase("ab_keyword_attributeid"), 
+        this.getColumnCase("name"), 
+        this.getColumnCase("container"), 
+        this.getColumnCase("kind")];
+
+        this.insertData(this.getTableCase("ab_keyword_attribute"), columns, null, 
+            [attributeId, keywordAttribute, keywordContainer, keywordAttributeType], this.Config.AliasTo);
     }
     
-    if (keyword && value) {   
-        sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
-        + this.getColumnCase("keyid") + " = ?";
-        var kid = db.cell([sql, [[keyword, SQLTYPES.CHAR]]], this.Config.AliasTo);      
+    // Creates the entry in AB_KEYWORD_ENTRY and AB_KEYWORD_ATTRIBUTERELATION, case if it not exists.
+    if (keyword && keywordAttrRelValue) {   
+        sql = "select " + this.getColumnCase("ab_keyword_entryid")
+        + " from " + this.getTableCase("ab_keyword_entry")
+        + " where " + this.getColumnCase("keyid") + " = ?";
+    
+        var keywordId = db.cell([sql, [[keyword, SQLTYPES.CHAR]]], this.Config.AliasTo);      
         
-        if (kid == "" || kid == null) {
-            sql = "select " + this.getColumnCase("keyid") + " from " + this.getTableCase("ab_keyword_entry") + " where " 
-            + this.getColumnCase("container") + " = ? and " + this.getColumnCase("title") + " = ?";
-            kid = db.cell([sql, [[container, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
-            if (kid == "" || kid == null) {
+        if (keywordId == "" || keywordId == null) {
+            
+            sql = "select " + this.getColumnCase("keyid") 
+            + " from " + this.getTableCase("ab_keyword_entry") 
+            + " where " + this.getColumnCase("container") 
+            + " = ? and " + this.getColumnCase("title") + " = ?";
+            
+            keywordId = db.cell([sql, [[keywordContainer, SQLTYPES.VARCHAR], [keyword, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+            
+            if (keywordId == "" || keywordId == null) {
+                
                 columns = [this.getColumnCase("ab_keyword_entryid"), this.getColumnCase("keyid"), this.getColumnCase("container"),
-                this.getColumnCase("title"), this.getColumnCase("sorting"), this.getColumnCase("isactive"), this.getColumnCase("isessential")]; 
+                this.getColumnCase("title"), this.getColumnCase("sorting"), this.getColumnCase("isactive"),
+                this.getColumnCase("isessential")]; 
+                
                 sql = "select max(coalesce(sorting, 0))+1 from ab_keyword_entry where container = ?";
-                var sort = db.cell([sql, [[container, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+                
+                var sort = db.cell([sql, [[keywordContainer, SQLTYPES.VARCHAR]]], this.Config.AliasTo);
+                
                 if(sort == "") sort = "0";
-                kid = util.getNewUUID();
+                
+                keywordId = util.getNewUUID();
+                
                 this.insertData(this.getTableCase("ab_keyword_entry"), columns, null, 
-                    [kid, util.getNewUUID(), container, keyword, sort, "1", "0"], this.Config.AliasTo);
+                    [keywordId, util.getNewUUID(), keywordContainer, keyword, sort, "1", "0"], this.Config.AliasTo);
             }
         }
         
-        sql = "select " + this.getColumnCase("ab_keyword_attributerelationid") + " from " + this.getTableCase("ab_keyword_attributerelation") 
-        + " where " + this.getColumnCase("ab_keyword_entry_id") + " = ? and " + this.getColumnCase("ab_keyword_attribute_id") + " = ?";
-        id = db.cell([sql, [[kid, SQLTYPES.CHAR], [aid, SQLTYPES.CHAR]]], this.Config.AliasTo);
+        // Creates or updates the keyword attributerelation.
+        sql = "select " + this.getColumnCase("ab_keyword_attributerelationid") 
+        + " from " + this.getTableCase("ab_keyword_attributerelation") 
+        + " where " + this.getColumnCase("ab_keyword_entry_id") 
+        + " = ? and " + this.getColumnCase("ab_keyword_attribute_id") + " = ?";
+        
+        id = db.cell([sql, [[keywordId, SQLTYPES.CHAR], [attributeId, SQLTYPES.CHAR]]], this.Config.AliasTo);
+        
         if (id == "" || id == null) {
-            columns = [this.getColumnCase("ab_keyword_attributerelationid"), this.getColumnCase("ab_keyword_entry_id"), 
-            this.getColumnCase("ab_keyword_attribute_id"), valueColumn];
+            columns = [this.getColumnCase("ab_keyword_attributerelationid"), 
+            this.getColumnCase("ab_keyword_entry_id"), 
+            this.getColumnCase("ab_keyword_attribute_id"), 
+            valueColumn];
+                    
             id = util.getNewUUID();
-            this.insertData(this.getTableCase("ab_keyword_attributerelation"), columns, null, [id, kid, aid, value], this.Config.AliasTo);
+            this.insertData(this.getTableCase("ab_keyword_attributerelation"), columns, null,
+                [id, keywordId, attributeId, keywordAttrRelValue], this.Config.AliasTo);
+            
         } else {
             if (this.Config.ImportCommand.indexOf("update") != -1) {
                 cond = this.getColumnCase("ab_keyword_attributerelationid") + " = '" + id + "'";
-                this.updateData(this.getTableCase("ab_keyword_attributerelation"), [valueColumn], null, [value], cond, this.Config.AliasTo);
+                this.updateData(this.getTableCase("ab_keyword_attributerelation"), [valueColumn], null, [keywordAttrRelValue], cond, this.Config.AliasTo);
             }            
         }       
     } 
@@ -279,16 +350,17 @@ function iKeywordAttribute(pObject) {
  * @param {Object} pObject req the mapping line
  * @return {Boolean} true
  * */
+
 function iComm(pObject) {
     if (! this.doIfCheck(pObject)) return true;
-
     var address = this.InputRecord[pObject.Address];
-    if(address == undefined) address = this.resolveSymbol(pObject, pObject.Address);
     var medium = this.InputRecord[pObject.Medium];
-    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.Medium);
     var contact = this.InputRecord[pObject.ContactID];
-    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
     var standard = "0";
+    
+    if(address == undefined) address = this.resolveSymbol(pObject, pObject.address);
+    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.medium);
+    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
     if(pObject.Standard) standard = "1";
     
     if(!address || !medium || !contact) return true;
@@ -308,38 +380,61 @@ function iComm(pObject) {
 
 /*
  * Values of the mapping line:
- * Reason opt -- the reason 
- * Medium req -- the medium id
- * ContactID req -- the id of the entry in the contact table
- * Type req -- yes or no to communication
+ * contact (required): The id of the entry in the contact table.
+ * restrictionMedium (required): The medium id.
+ * restrictionReason (optional): The reason.
+ * startDate (optional): The date when the restrictions begins.
+ * involvedEmployee (optional): The contact which is responsible for the restriction.
  *
  * @name iCommRestriction
- * @param {Object} pObject req the mapping line
+ * @param {Object} pObject (required): Associative Array with required informations.
  * @return {Boolean} true
  * */
-function iCommRestriction(pObject) {
+
+function iCommRestriction(pObject) 
+{
     if (!this.doIfCheck(pObject)) return true;
 
-    var reason = this.InputRecord[pObject.Reason];
-    if(reason == undefined) reason = this.resolveSymbol(pObject, pObject.Reason);
-    var medium = this.InputRecord[pObject.Medium];
-    if(medium == undefined) medium = this.resolveSymbol(pObject, pObject.Medium);
-    var contact = this.InputRecord[pObject.ContactID];
-    if(contact == undefined) contact = this.resolveSymbol(pObject, pObject.ContactID);
-    var type = this.InputRecord[pObject.Type];
-    if(type == undefined) type = this.resolveSymbol(pObject, pObject.Type);
+    var restrictionContact = this.InputRecord[pObject.restrictionContact];
+    var restrictionReason = this.InputRecord[pObject.restrictionReason];
+    var restrictionMedium = this.InputRecord[pObject.restrictionMedium];
+    var restrictionStartDate = this.InputRecord[pObject.restrictionStartDate];
+    var restrictionInvolvedEmployee = this.InputRecord[pObject.restrictionInvolvedEmployee];
+    
+    if(restrictionContact == undefined) restrictionContact = this.resolveSymbol(pObject, pObject.restrictionContact);
+    if(restrictionReason == undefined) restrictionReason = this.resolveSymbol(pObject, pObject.restrictionReason);
+    if(restrictionReason == undefined || restrictionReason == null) restrictionReason = "NULL";
+    if(restrictionMedium == undefined) restrictionMedium = this.resolveSymbol(pObject, pObject.restrictionMedium);
+    if(restrictionStartDate == undefined) restrictionStartDate = this.resolveSymbol(pObject.restrictionStartDate);
+    if(restrictionStartDate == undefined || restrictionStartDate == null) restrictionStartDate = "NULL";
+    if(restrictionInvolvedEmployee == undefined) restrictionInvolvedEmployee = this.resolveSymbol(pObject.restrictionInvolvedEmployee);
+    if(restrictionInvolvedEmployee == undefined || restrictionInvolvedEmployee == null) restrictionInvolvedEmployee = "NULL";
+    
+    if (!restrictionMedium || !restrictionContact) return true;
+
+    var alias = this.Config.AliasTo;
+    var commRestriction = this.getTableCase("commrestriction");
+    var commRestrictionId = this.getColumnCase("commrestriction.commrestrictionid");
+    var contactId = this.getColumnCase("commrestriction.contact_id");
+    var medium = this.getColumnCase("commrestriction.medium");
+    var reason = this.getColumnCase("commrestriction.reason");
+    var startDate = this.getColumnCase("commrestriction.startdate");
+    var involvedEmployee = this.getColumnCase("commrestriction.employee_involved");
+
+    var id = newSelect(commRestrictionId, alias).from(commRestriction).where(contactId, restrictionContact).and(medium, restrictionMedium).cell();
+    var columns = [commRestrictionId, medium, reason, contactId, startDate, involvedEmployee];
+    var values = [id, restrictionMedium, restrictionReason, restrictionContact, restrictionStartDate, restrictionInvolvedEmployee];
+    
+    if (id == "" || id == null) 
+    {
+        values[0] = util.getNewUUID();
+        this.insertData(commRestriction, columns, null, values, alias);       
+    }
+    else
+    {
+        this.updateData(commRestriction, columns, null, values, alias);
+    }
     
-    if (!medium || !contact || !type) return true;
-
-    var sql = "select top 1 " + this.getColumnCase("type") + " from " + this.getTableCase("commrestriction")
-    +" where " + this.getColumnCase("contact_id") + " = ? and " + this.getColumnCase("medium") + " = ? order by " 
-    + this.getColumnCase("date_edit") + " desc, " + this.getColumnCase("date_new") + " desc";
-    var id = db.cell([sql, [[contact, SQLTYPES.CHAR], [medium, SQLTYPES.CHAR]]], this.Config.AliasTo);
-    if (id == "" || id == null || id != type) {
-        if(reason == undefined || reason == null) reason = "NULL";
-        var columns = [this.getColumnCase("commrestrictionid"), this.getColumnCase("medium"), this.getColumnCase("contact_id"), this.getColumnCase("type"), this.getColumnCase("reason")];
-        this.insertData(this.getTableCase("commrestriction"), columns, null, [util.getNewUUID(), medium, contact, type, reason], this.Config.AliasTo);       
-    } 
     return true;
 }
 
diff --git a/process/Importer_lib/process.js b/process/Importer_lib/process.js
index ad800c6581ee472cf3a7e1e90ed9b4f6a67be8a7..430c8e0aa7734b65247a12799a2181d0610594a8 100644
--- a/process/Importer_lib/process.js
+++ b/process/Importer_lib/process.js
@@ -1050,6 +1050,17 @@ function Importer(pConfig)
 
     this.insertData = function(pTable, pColumns, pTypes, pValues, pAlias)
     {
+        // Checks wether the given columns (pColumns) are in the following format: tablename.columnname
+        // and case when then the following code cuts away the string "tablename."-String to get only the column name.
+        // Its required for the continueing processes otherwise a exception will be thrown.
+        for (i = 0; i < pColumns.length; i++) 
+        {
+            if (pColumns[i].indexOf(".", 0) > -1)
+            {
+                pColumns[i] = pColumns[i].substring(pColumns[i].indexOf(".", 0)+1, pColumns[i].length);
+            }
+        }
+        
         var tt = datetime.date();
         var resData = true;
         if(this.Preview == false)
@@ -1089,14 +1100,17 @@ function Importer(pConfig)
                             pValues.push(datetime.date());
                         }
 
-                        this.insertArray.push([this.getTableCase(pTable), pColumns, pTypes, pValues, pAlias]);
+                        var types = pTypes != null ? pTypes : pColumns.map(function (columnName) {
+                            return this.getColumnDataType(this.getTableCase(pTable), this.getColumnCase(columnName));
+                        }, this);
+                        this.insertArray.push([this.getTableCase(pTable), pColumns, types, pValues, pAlias]);
                     }
                 }
             }
             catch(ex)
             {
                 this.writeLog(this.LogLevels.Error, "Exception at insertData for record: " + getRecordString(pColumns, pValues));
-                logging.log(ex);
+                logging.log(ex["rhinoException"] != undefined ? ex["rhinoException"] : ex);
                 resData = false;
             }
         }
@@ -1195,16 +1209,20 @@ function Importer(pConfig)
                             theValues.push(datetime.date());
                             minchanges++;
                         }
+                        var types = theTypes != null ? theTypes : pColumns.map(function (columnName){
+                            return this.getColumnDataType(this.getTableCase(pTable), this.getColumnCase(columnName))
+                        }, this);
+
                         if(this.CompleteUpdate == false)
                         {
                             if(theCols.length > minchanges)
                             {
-                                this.updateArray.push([this.getTableCase(pTable), theCols, theTypes, theValues, pCondition, pAlias]);
+                                this.updateArray.push([this.getTableCase(pTable), theCols, types, theValues, pCondition, pAlias]);
                             }
                         }
                         else
                         {
-                            this.updateArray.push([this.getTableCase(pTable), theCols, theTypes, theValues, pCondition, pAlias]);
+                            this.updateArray.push([this.getTableCase(pTable), theCols, types, theValues, pCondition, pAlias]);
                         }
                     }
                 }
@@ -1212,7 +1230,7 @@ function Importer(pConfig)
             catch(ex)
             {
                 resultData = false;
-                this.writeLog(this.LogLevels.Error, "Exception at updateData for record: " + getRecordString(pColumns, pValues));
+                logging.log(ex["rhinoException"] != undefined ? ex["rhinoException"] : ex);
                 logging.log(ex);
             }
         }
@@ -1481,7 +1499,7 @@ function Importer(pConfig)
             return pName.toLowerCase();
         else
             return pName;
-    }
+    };
 
     //Converts a string with the columnname in upper or lower case
     this.getColumnCase = function(pName)
@@ -1494,6 +1512,20 @@ function Importer(pConfig)
             return pName;
     }
 
+    //Converts a string with the columnname in upper or lower case
+    this.getColumnDataType = function(pTableName, pColumnName)
+    {
+        if (this.DataType[pTableName] == undefined)
+            throw new Error("Importer: getColumnDataType: could not retrieve column data type for table: " + pTableName );
+        
+        var dataType = this.DataType[pTableName][pColumnName];
+        
+        if (dataType == undefined)
+            throw new Error("Importer: getColumnDataType: could not retrieve column data type for table.column: " + pTableName + "." + pColumnName);
+        return dataType;
+    };
+
+
     this.doIfCheck = function(pObject)
     {
         if (pObject.DoIf == undefined) return true;
diff --git a/process/IncomingCallExecutor_lib/process.js b/process/IncomingCallExecutor_lib/process.js
index 7348d5e682d51bc1c48a206e105595fc80514d40..307f4e456b1fb0fbb1d493dc15db8b9c86acdce5 100644
--- a/process/IncomingCallExecutor_lib/process.js
+++ b/process/IncomingCallExecutor_lib/process.js
@@ -288,7 +288,7 @@ IncomingCallExecutor._getContactsFromNumber = function(pNumber, pContactIds)
                         .join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
                         .leftJoin("PERSON", "CONTACT.PERSON_ID = PERSON.PERSONID")
                         .where("CONTACT.STATUS", $KeywordRegistry.contactStatus$active())
-                        .and("CONTACT.CONTACTID", pContactIds, SqlBuilder.IN())
+                        .and("CONTACT.CONTACTID", contactIds, SqlBuilder.IN())
                         .table();
     
     //map to the result how the entities-methods would return it to have less effort later when the mentioned ticket is done
diff --git a/process/Loghistory_lib/process.js b/process/Loghistory_lib/process.js
index 15f076f82fd94d2cd1fb67f8a186b0fb4f7a80de..59036002263ecb1d0e269fc2afc6cb7c6107e742 100644
--- a/process/Loghistory_lib/process.js
+++ b/process/Loghistory_lib/process.js
@@ -346,7 +346,7 @@ LogHistoryExecutor.prototype._getFormattedValue = function (pColumnName, pDescri
     }
     else if (pDescription.translate4Log != null && pDescription.translate4Log != "") 
     {
-        var params = Translate4LogParams.generateParams(this.idValue, pValue.toString(), this.sqlAction, this.translationLanguage);
+        var params = Translate4LogParams.generateParams(this.idValue, pValue != null ? pValue.toString() : null, this.sqlAction, this.translationLanguage);
         var scriptId = "LogHistoryExecutor._getFormattedValue." 
             + this.structureDefinitionAlias + "." + this.affectedTable + "." +  pColumnName + ".translate4Log";
         pValue = process.executeScript(scriptId, pDescription.translate4Log, params, vars.get("$sys.dbalias"));
diff --git a/process/Organisation_lib/process.js b/process/Organisation_lib/process.js
index 187622e897dd0c1a9271d213cd8df7ceed12a065..cc8c3aa44767af1f7a78f10c0c07ab61e8a752a7 100644
--- a/process/Organisation_lib/process.js
+++ b/process/Organisation_lib/process.js
@@ -155,10 +155,7 @@ OrgUtils.openOrgReport = function(pOrgId)
     {
         row[0] = datetime.toDate(row[0], dateFormat);
         // convert html to text
-        if (row[1] == $KeywordRegistry.activityCategory$mail())
-        {
-            row[4] = text.html2text(row[4]);
-        }
+        row[4] = text.html2text(row[4]);
         
         row[1] = KeywordUtils.getViewValue($KeywordRegistry.activityCategory(), row[1]);
         _joinArrayVals(row, 2, 2);
diff --git a/process/Permission_lib/process.js b/process/Permission_lib/process.js
index 6c46a946d7ced16430f2dd07466f241bd5e9938a..cff2ffa1852bc16a54a5f299d150be993d231585 100644
--- a/process/Permission_lib/process.js
+++ b/process/Permission_lib/process.js
@@ -80,7 +80,7 @@ function PermissionUtil () {}
     }
 
     /**
- * Returns the action a given permission action id.
+ * Returns the action of a given permission action id.
  * 
  * @param {String} pActionId id of the action
  * 
diff --git a/process/Product_lib/process.js b/process/Product_lib/process.js
index a41401aa4a63286c05a0fca8c5c9a9cce8516520..d49860b7ac46e5f1f8d093310260d8406de9b0e0 100644
--- a/process/Product_lib/process.js
+++ b/process/Product_lib/process.js
@@ -191,7 +191,7 @@ ProductUtils.getProductDetails = function(pid, priceListFilter, additionalProduc
                             .and(["PRODUCTPRICE", "CURRENCY", "validPP"], priceListFilter.currency)
                             .and(["PRODUCTPRICE", "VALID_FROM", "validPP"], datetime.date().toString(), SqlBuilder.LESS_OR_EQUAL())
                             .and(newWhere()
-                                    .or(["PRODUCTPRICE", "VALID_TO", "validPP"], datetime.date().toString(), SqlBuilder.GREATER_OR_EQUAL())
+                                    .or(["PRODUCTPRICE", "VALID_TO", "validPP"], datetime.today().toString(), SqlBuilder.GREATER_OR_EQUAL())
                                     .or("validPP.VALID_TO is null"))
                             .and(["PRODUCTPRICE", "FROMQUANTITY", "validPP"], priceListFilter.quantity, SqlBuilder.LESS_OR_EQUAL())
                             .and(newWhere()
diff --git a/process/Sql_lib/documentation.adoc b/process/Sql_lib/documentation.adoc
index c3695fa62fe5bda13b6769f9f8f973f25682e893..2017f4b9646c06fe30bd397cb360a2663dede282 100644
--- a/process/Sql_lib/documentation.adoc
+++ b/process/Sql_lib/documentation.adoc
@@ -501,7 +501,7 @@ Here is an example code of a conditionProcess:
 // newWhereIfSet() is used to create a new condition. 
 // The 'IfSet' ignores the condition "CONTACT.ORGANISATION_ID" = "$param.OrgId_param" if "$param.OrgId_param" is null
 var cond = newWhereIfSet("CONTACT.ORGANISATION_ID", "$param.OrgId_param")
-                .andIfSet("PERSON.CONTACT_ID", "$param.ContactId_param"); // if "$param.ContactId_param" is null, this line is ignored
+                .andIfSet("CONTACT.CONTACTID", "$param.ContactId_param"); // if "$param.ContactId_param" is null, this line is ignored
 // --> If both parameters are null (not filled), then the SqlBuilder condition will not contain any condition!
 
 // Now we add a parameter containing a json Array
diff --git a/process/Workflow_lib/process.js b/process/Workflow_lib/process.js
index 67b4340100ad618ec80c194e934d71b8eccbade7..c30ab64c7b24a07b391c859629d805fcb4869c77 100644
--- a/process/Workflow_lib/process.js
+++ b/process/Workflow_lib/process.js
@@ -1,8 +1,10 @@
+import("system.logging");
 import("system.project");
 import("Sql_lib");
 import("system.neon");
 import("Context_lib");
 import("system.vars");
+import("system.entities");
 import("system.workflow");
 import("KeywordRegistry_basic");
 
@@ -33,14 +35,19 @@ WorkflowUtils.getPossibleWorkflowDefinitions = function (pContext, pAction)
  * @param {Object} [pVariables] variables for the process instance
  * @param {String} [pTargetId=$sys.uid] uid of the target object
  * @param {String} [pTargetContext=current context] target context 
+ * @param {String} [pSelectionFilter] filter
  */
-WorkflowUtils.openNewInstance = function (pVariables, pTargetId, pTargetContext)
+WorkflowUtils.openNewInstance = function (pVariables, pTargetId, pTargetContext, pSelectionFilter)
 {
-    pVariables = WorkflowUtils.appendMandatoryVariables(pVariables, pTargetId, pTargetContext)
+    if ((!pTargetId || pTargetId.length === 0) && pSelectionFilter)
+        pTargetId = [];
+    
+    pVariables = WorkflowUtils.appendMandatoryVariables(pVariables, pTargetId, pTargetContext);  
     
     neon.openContext("WorkflowInstance", null, null, neon.OPERATINGSTATE_NEW, {
         "ProcessVariables_param" : JSON.stringify(pVariables),
-        "TargetContext_param" : pVariables.targetContext
+        "TargetContext_param" : pVariables.targetContext,
+        "TargetIdFilter_param" : pSelectionFilter ? JSON.stringify(pSelectionFilter) : ""
     });
 }
 
@@ -77,9 +84,12 @@ WorkflowUtils.appendMandatoryVariables = function (pVariables, pTargetId, pTarge
  */
 WorkflowUtils.engineIsEnabled = function ()
 {
-    return project.getInstanceConfigValue("workflowEngineEnabled", "false") == "true";
+    return String(project.getInstanceConfigValue("workflowEngineEnabled", "false")) == "true";
 }
 
+/**
+ * obsolete
+ */
 function WorkflowStarter () {}
 
 WorkflowStarter.TRIGGER_INSERT = function ()
@@ -123,3 +133,115 @@ WorkflowStarter._startProcessByAction = function (pAction, pVariables, pTargetId
         } catch (err) {}
     });
 }
+
+function WorkflowSignalSender () {}
+
+WorkflowSignalSender.EVENT_INSERT = function ()
+{
+    return $KeywordRegistry.workflowTrigger$create();
+}
+
+WorkflowSignalSender.EVENT_UPDATE = function ()
+{
+    return $KeywordRegistry.workflowTrigger$update();
+}
+
+WorkflowSignalSender.EVENT_DELETE = function ()
+{
+    return $KeywordRegistry.workflowTrigger$delete();
+}
+
+WorkflowSignalSender.markInserted = function (pTargetId, pTargetContext)
+{
+    WorkflowSignalSender._addToQueue(WorkflowSignalSender.EVENT_INSERT(), pTargetId, pTargetContext);
+}
+
+WorkflowSignalSender.markUpdated = function (pTargetId, pTargetContext)
+{
+    WorkflowSignalSender._addToQueue(WorkflowSignalSender.EVENT_UPDATE(), pTargetId, pTargetContext);
+}
+
+WorkflowSignalSender._QUEUE_VARNAME = function ()
+{
+    return "$context.workflowSignalQueue";
+}
+
+WorkflowSignalSender._addToQueue = function (pAction, pTargetId, pTargetContext)
+{
+    var contextVar = WorkflowSignalSender._QUEUE_VARNAME();
+    var queue = [];
+    if (vars.exists(contextVar) && vars.get(contextVar))
+        queue = vars.get(contextVar);
+    
+    queue.push([pAction, pTargetId, pTargetContext]);
+    vars.set(contextVar, queue);
+}
+
+WorkflowSignalSender.doInsertedOrUpdated = function ()
+{
+    var contextVar = WorkflowSignalSender._QUEUE_VARNAME();
+    if (vars.exists(contextVar) && vars.get(contextVar))
+    {
+        vars.get(contextVar).forEach(function (action)
+        {
+            WorkflowSignalSender.actionPerformed.apply(null, action);
+        });
+        vars.set(contextVar, null);
+    }
+}
+
+WorkflowSignalSender.deleted = function (pTargetId, pTargetContext)
+{
+    WorkflowSignalSender.actionPerformed(WorkflowSignalSender.EVENT_DELETE(), pTargetId, pTargetContext);
+}
+
+WorkflowSignalSender.actionPerformed = function (pAction, pTargetId, pTargetContext)
+{
+    if (!pTargetId)
+        pTargetId = vars.get("$sys.uid");
+    if (!pTargetContext)
+        pTargetContext = ContextUtils.getCurrentContextId();
+    
+    var signals = WorkflowSignalSender.getSignalConfig(pTargetContext, pAction);
+    signals.forEach(function (signal)
+    {
+        if (_checkCondition(signal.entity, pTargetId, signal.condition))
+            workflow.signalEventReceived(signal.name);
+    });
+    
+    function _checkCondition (pEntity, pUid, pCondition)
+    {
+        if (!pCondition)
+            return true;
+        
+        var loadConfig = entities.createConfigForLoadingRows()
+            .entity(pEntity)
+            .uid(pUid)
+            .filter(JSON.stringify(pCondition));
+        
+        return entities.getRowCount(loadConfig) > 0;
+    }
+}
+
+WorkflowSignalSender.getSignalConfig = function (pContext, pAction)
+{
+    var entity = ContextUtils.getEntity(pContext);
+    var signals = newSelect("SIGNAL_NAME, OBJECT_CONDITION")
+        .from("WORKFLOWSIGNAL")
+        .where("WORKFLOWSIGNAL.OBJECT_TYPE", pContext)
+        .and("WORKFLOWSIGNAL.TRIGGER_EVENT", pAction)
+        .table();
+    
+    return signals.map(function (signal)
+    {
+        var condition = signal[1]
+            ? JSON.parse(signal[1]).filter
+            : null;
+            
+        return {
+            name : signal[0],
+            entity : entity,
+            condition : condition
+        };
+    });
+}
\ No newline at end of file
diff --git a/process/startWorkflowInstances_serverProcess/process.js b/process/startWorkflowInstances_serverProcess/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..cdb18b037c154aa3e6668bb228e754e5f24099e0
--- /dev/null
+++ b/process/startWorkflowInstances_serverProcess/process.js
@@ -0,0 +1,39 @@
+import("system.util");
+import("system.notification");
+import("system.workflow");
+import("system.entities");
+import("Context_lib");
+import("system.vars");
+
+//!!! Don't use this process, entities.getRows does not yet work on the server !!!
+throw new Error("startWorkflowInstances_serverProcess: no")
+
+var processKey = vars.get("$local.processKey");
+var variables = JSON.parse(vars.get("$local.processVariables"));
+var filter = vars.get("$local.entityFilter");
+
+var entity = ContextUtils.getEntity(variables.targetContext);
+var loadConfig = entities.createConfigForLoadingRows()
+    .entity(entity)
+    .fields(["#UID"]);
+
+if (filter)
+    loadConfig.filter(filter);
+
+var rowCount = entities.getRowCount(loadConfig);
+var pageSize = 400;
+for (let startRow = 0; startRow < rowCount; startRow += pageSize)
+{
+    loadConfig.startrow(startRow).count(pageSize);
+    let targetIds = entities.getRows(loadConfig).map(function (row) {return row["#UID"];});
+    _startForIds(targetIds, variables);
+}
+
+function _startForIds (pTargetIds, pVariables)
+{
+    pTargetIds.forEach(function (id) 
+    {
+        pVariables.targetId = id;
+        workflow.startProcessByKey(processKey, pVariables);
+    });
+}
diff --git a/process/startWorkflowInstances_serverProcess/startWorkflowInstances_serverProcess.aod b/process/startWorkflowInstances_serverProcess/startWorkflowInstances_serverProcess.aod
new file mode 100644
index 0000000000000000000000000000000000000000..5d5de80f53c69c20e9c3190e3d8eb99775217a65
--- /dev/null
+++ b/process/startWorkflowInstances_serverProcess/startWorkflowInstances_serverProcess.aod
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>startWorkflowInstances_serverProcess</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/startWorkflowInstances_serverProcess/process.js</process>
+  <alias>Data_alias</alias>
+  <variants>
+    <element>EXECUTABLE</element>
+  </variants>
+</process>
diff --git a/process/test_iCommRestriction/process.js b/process/test_iCommRestriction/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..3e3c5c98515c35629064e74489141098754033da
--- /dev/null
+++ b/process/test_iCommRestriction/process.js
@@ -0,0 +1,37 @@
+import("system.db");
+import("Importer_lib");
+import("ImporterMappingFunctions_lib");
+
+var importerMapping = {
+    AliasTo: "Data_alias",
+    DataFunction: function (pCurrentBatchNum)
+    {
+        if (pCurrentBatchNum > 1)
+            return null;
+        return [
+        ["a8a5f214-8165-4627-bee2-bceb3578147e", "cfebe176-0a64-428d-b0ec-bba454d2ca3e", "Testing"],
+        ["c7ddf982-0e58-4152-b82b-8f5673b0b729", "cb07397b-a976-4960-b8e5-9edf189c5caf", "Testing"]
+        ];
+    },
+    ImportCommand: "insert+update",
+    Mapping: [
+    [ iCommRestriction, 
+    {
+        contact: 0,
+        restrictionMedium: 1,
+        restrictionReason: 2
+    }
+    ]
+    ]
+};
+
+var imp = new Importer(importerMapping);
+imp.Log = "CONSOLE";
+imp.ImportUser = "IMPORTER_TESTER";
+imp.Preview = false;
+imp.Debug = true;
+imp.LogLevel = imp.LogLevels.Info;
+
+// MariaDB requires lower table cases
+if (db.getDatabaseType("Data_alias") == db.DBTYPE_MARIADB10) imp.TableCase = imp.Cases.Lower;
+imp.process();
\ No newline at end of file
diff --git a/process/test_iCommRestriction/test_iCommRestriction.aod b/process/test_iCommRestriction/test_iCommRestriction.aod
new file mode 100644
index 0000000000000000000000000000000000000000..cc954a462d091f6b3efef2b7797b92a18ae0b2f8
--- /dev/null
+++ b/process/test_iCommRestriction/test_iCommRestriction.aod
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
+  <name>test_iCommRestriction</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/test_iCommRestriction/process.js</process>
+  <variants>
+    <element>EXECUTABLE</element>
+  </variants>
+</process>