diff --git a/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod b/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod
index 8f088d36615ee56043631b62277a508976268c50..76ea4711ebda2c2dfbaa5585ed538ad0583f06d3 100644
--- a/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod
+++ b/entity/CampaignAddParticipants_entity/CampaignAddParticipants_entity.aod
@@ -19,6 +19,7 @@
       <consumer>CampaignConsumer</consumer>
       <mandatory v="true" />
       <state>EDITABLE</state>
+      <stateProcess>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaign_id/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaign_id/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaign_id/displayValueProcess.js</displayValueProcess>
       <onValueChange>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaign_id/onValueChange.js</onValueChange>
@@ -38,6 +39,7 @@
       <state>EDITABLE</state>
       <displayValueProcess>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaignstep_id/displayValueProcess.js</displayValueProcess>
       <onValueChange>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaignstep_id/onValueChange.js</onValueChange>
+      <onValidation>%aditoprj%/entity/CampaignAddParticipants_entity/entityfields/campaignstep_id/onValidation.js</onValidation>
     </entityField>
     <entityField>
       <name>campaignParticipantMessage</name>
diff --git a/entity/CampaignAddParticipants_entity/entityfields/addparticipants/onActionProcess.js b/entity/CampaignAddParticipants_entity/entityfields/addparticipants/onActionProcess.js
index b299466750aeaa2162df03031f3dc9098cdf5967..ceeb7e8662d98a71b9a214fd5cd0fbb100c5c8c3 100644
--- a/entity/CampaignAddParticipants_entity/entityfields/addparticipants/onActionProcess.js
+++ b/entity/CampaignAddParticipants_entity/entityfields/addparticipants/onActionProcess.js
@@ -1,3 +1,5 @@
+import("system.logging");
+import("Util_lib");
 import("system.neon");
 import("Sql_lib");
 import("system.vars");
@@ -7,67 +9,32 @@ import("Campaign_lib");
 
 var cols = [];
 
-var participantCondition = "";
-var participantRowIds = JSON.parse(vars.getString("$param.campaignParticipantsRowIds_param"));
-var conditionSourceTableName = vars.getString("$param.dataSourceTableName_param");
 
-var isUpdate = vars.get("$field.isUpdate");
+
+var contactIds = JSON.parse(vars.get("$field.campaignparticipantContactIds"));
+var isUpdate = Utils.toBoolean(vars.get("$param.isUpdate_param"));
+
 var campaignId = vars.getString("$field.CAMPAIGN_ID");
 var newCampaignStepId = vars.getString("$field.CAMPAIGNSTEP_ID");
 
 var colNamesCampaignParticipantLog = CampaignUtils.getParticipantLogInsertColumnNames();
 
-if(participantRowIds != null && participantRowIds.length > 0)
-{
-    var contactIdsToHandle = participantRowIds;
-    
-    if(isUpdate == "false")
-        contactIdsToHandle = JSON.parse(vars.get("$field.campaignparticipantContactIds"));
-    
-    _handleRowIds(contactIdsToHandle, campaignId);
-}
-else
+if(contactIds != null && contactIds.length > 0)
 {
-    participantCondition = JSON.parse(vars.getString("$param.campaignParticipantsCondition_param")).condition;
-    _handleCondition(campaignId, conditionSourceTableName, participantCondition);
+    _handleRowIds(contactIds, campaignId);
 }
+
 neon.refreshAll();
 if (!vars.exists("$param.currentCampaignId_param") || !vars.get("$param.currentCampaignId_param"))
     neon.openContext("Campaign", "CampaignMain_view", [campaignId], neon.OPERATINGSTATE_VIEW, null);
 
-function _handleCondition(pCampaignId, pTargetTableName, pCondition)
-{
-    var contactIdsToHandle = [];
-    var contextComingFrom = "Person";
-    
-    if(pTargetTableName == "ORGANISATION")
-    {
-        pCondition += "  and PERSON.PERSONID is NULL";
-        contextComingFrom = "Organisation";
-    }
-        
-    /*
-     * If it's an update of participants, get the participants defined by the condition in the selected campaign
-     * Because they already are participants, no restrictions apply to the affected IDs.
-     * 
-     * Otherwise the participants ought to be inserted. The only restriction right now is, hat the participants to be inserted
-     * can't already be in this specific campaign. Therefore all IDs hat are defined by the condition and not in the campaign are selected.
-     */
-    if(isUpdate == "true")
-    {
-        contactIdsToHandle = CampaignUtils.GetContactIdsInCampaignByCondition(pCampaignId, pCondition);
-    }
-    else
-        contactIdsToHandle = CampaignUtils.GetContactIdsNotInCampaignByCondition(pCampaignId, pCondition, contextComingFrom);
-    
-    _handleRowIds(contactIdsToHandle, pCampaignId);
-}
+
 
 function _handleRowIds(pParticipantRowIds, pCampaignId)
 {
     var oldStepIds = {};
     
-    if(isUpdate == "true")
+    if(isUpdate)
     {
         cols = [
             "CAMPAIGNSTEP_ID",
@@ -75,7 +42,7 @@ function _handleRowIds(pParticipantRowIds, pCampaignId)
             "DATE_EDIT"
         ];
     
-        var oldSteps = newSelect("CAMPAIGNPARTICIPANTID, CAMPAIGNSTEP_ID")
+        var oldSteps = newSelect("CONTACT_ID, CAMPAIGNSTEP_ID")
                             .from("CAMPAIGNPARTICIPANT")
                             .whereIfSet("CAMPAIGNPARTICIPANT.CONTACT_ID", pParticipantRowIds, SqlBuilder.IN())
                             .and("CAMPAIGNPARTICIPANT.CAMPAIGN_ID", pCampaignId)
@@ -105,9 +72,10 @@ function _handleRowIds(pParticipantRowIds, pCampaignId)
     {
         var campaignParticipantLogId = util.getNewUUID();
         var valsCampaignParticipantLog;
-        if(isUpdate == "true")
+        if(isUpdate)
         {
             var oldCampaignStepId = oldStepIds[pParticipantRowIds[participant]] || "";
+
             
             var updatedValues = [
                 newCampaignStepId,
@@ -116,8 +84,7 @@ function _handleRowIds(pParticipantRowIds, pCampaignId)
             ];
 
             var condition = newWhere("CAMPAIGNPARTICIPANT.CONTACT_ID", pParticipantRowIds[participant])
-                                .and("CAMPAIGNPARTICIPANT.CAMPAIGN_ID", pCampaignId)
-                                .or("CAMPAIGNPARTICIPANT.CAMPAIGNPARTICIPANTID", pParticipantRowIds[participant]);
+                                .and("CAMPAIGNPARTICIPANT.CAMPAIGN_ID", pCampaignId);
                                  
             valsCampaignParticipantLog = [
                 campaignParticipantLogId,
@@ -159,8 +126,7 @@ function _handleRowIds(pParticipantRowIds, pCampaignId)
             logArray.push(["CAMPAIGNPARTICIPANTLOG", colNamesCampaignParticipantLog, null, valsCampaignParticipantLog]);
         }
     }
-    
-    if(isUpdate == "true")
+    if(isUpdate)
     {
         db.updates(statementArray)
     }
diff --git a/entity/CampaignAddParticipants_entity/entityfields/campaign_id/onValidation.js b/entity/CampaignAddParticipants_entity/entityfields/campaign_id/onValidation.js
index c596003e424ef1b3ec890598ce9a8ecadedc4ec4..f4f7ad8fa87f0ce1c5983c6913e0c14fc7d4f3ff 100644
--- a/entity/CampaignAddParticipants_entity/entityfields/campaign_id/onValidation.js
+++ b/entity/CampaignAddParticipants_entity/entityfields/campaign_id/onValidation.js
@@ -1,24 +1,17 @@
+import("Util_lib");
 import("system.vars");
 import("system.result");
 import("Sql_lib");
 import("system.translate");
 
+var validCount = JSON.parse(vars.get("$field.campaignparticipantContactIds")).length;
+var maxCount = vars.get("$field.campaignStepMaxParticipantCount");
+var isUpdate = Utils.toBoolean(vars.get("$param.isUpdate_param"));
 
-if (vars.get("$param.campaignParticipantsRowIds_param") != null && vars.get("$param.campaignParticipantsRowIds_param") != "")
-{
-    let participants = JSON.parse(vars.get("$param.campaignParticipantsRowIds_param"));
+if (vars.get("$field.CAMPAIGN_ID")){
 
-    if(participants.length > 0)
-    {
-        let thisParticipantCount = newSelect("COUNT(*)")
-                                        .from("CAMPAIGNPARTICIPANT")
-                                        .where("CAMPAIGNPARTICIPANT.CAMPAIGN_ID", vars.get("$field.CAMPAIGN_ID"))
-                                        .and("CAMPAIGNPARTICIPANT.CONTACT_ID", participants, SqlBuilder.IN())
-                                        .cell();
-
-        if(parseInt(thisParticipantCount) > 0)
-        {
-            result.string(translate.text("Participant is already participating"));
-        }
+    
+    if (validCount == 0 && !isUpdate){
+        result.string(translate.text("All of the chosen records are already in the campaign"));
     }
 }
diff --git a/entity/CampaignAddParticipants_entity/entityfields/campaign_id/stateProcess.js b/entity/CampaignAddParticipants_entity/entityfields/campaign_id/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..31931105f9e8011ac8e49b1ec3e9443c6ec2095b
--- /dev/null
+++ b/entity/CampaignAddParticipants_entity/entityfields/campaign_id/stateProcess.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.neon");
+import("system.vars");
+
+
+if(vars.exists("$param.currentCampaignId_param") && vars.get("$param.currentCampaignId_param"))
+{
+    result.string(neon.COMPONENTSTATE_READONLY);
+}
+else result.string(neon.COMPONENTSTATE_EDITABLE);
\ No newline at end of file
diff --git a/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js b/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js
index d1c7824536e06bed2ffb8d47a1b93cc8f1260253..6511d5abbe134859e02af1b780da968a76fdd7ba 100644
--- a/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js
+++ b/entity/CampaignAddParticipants_entity/entityfields/campaignparticipantcontactids/valueProcess.js
@@ -1,3 +1,4 @@
+import("Util_lib");
 import("system.eMath");
 import("system.result");
 import("system.vars");
@@ -6,10 +7,10 @@ import("FilterViewAction_lib");
 import("Campaign_lib");
 
 
-if(vars.get("$field.CAMPAIGN_ID"))
+if(vars.get("$field.CAMPAIGN_ID") && vars.get("$field.CAMPAIGNSTEP_ID"))
 {
     var contactIds, filteredContactIds;
-    var isUpdate = vars.getString("$param.isUpdate_param");
+    var isUpdate = Utils.toBoolean(vars.get("$param.isUpdate_param"));
     var comingfrom = vars.getString("$param.dataSourceTableName_param");
     var selection = JSON.parse(vars.getString("$param.campaignParticipantsRowIds_param"));
     
@@ -28,17 +29,18 @@ if(vars.get("$field.CAMPAIGN_ID"))
     {
         if (vars.get("$param.campaignParticipantsCondition_param"))
         {
+            
             var contactFilterCondition = JSON.parse(vars.get("$param.campaignParticipantsCondition_param")).condition;
-            contactIds = CampaignUtils.GetContactIdsInCampaignByCondition(vars.get("$field.CAMPAIGN_ID"), contactFilterCondition);
+            contactIds = CampaignUtils.GetContactIdsNotInCampaignStepByCondition(vars.get("$field.CAMPAIGNSTEP_ID"),vars.get("$field.CAMPAIGN_ID"), contactFilterCondition);
         } 
         else
         {
-            contactIds = selection;
+            contactIds = CampaignUtils.GetContactIdsNotInCampaignStepByRowIds(vars.get("$field.CAMPAIGNSTEP_ID"), selection);
         }
     }
     else 
     {
-        contactIds = CampaignUtils.GetContactIdsNotInCampaignByRowIds(vars.get("$field.CAMPAIGN_ID"), JSON.parse(selection));
+        contactIds = CampaignUtils.GetContactIdsNotInCampaignByRowIds(vars.get("$field.CAMPAIGN_ID"), selection);
     }
     
     result.string(JSON.stringify(contactIds));
diff --git a/entity/CampaignAddParticipants_entity/entityfields/campaignstep_id/onValidation.js b/entity/CampaignAddParticipants_entity/entityfields/campaignstep_id/onValidation.js
new file mode 100644
index 0000000000000000000000000000000000000000..29f8f42cc56cd1e466728103419fe1cc5a893226
--- /dev/null
+++ b/entity/CampaignAddParticipants_entity/entityfields/campaignstep_id/onValidation.js
@@ -0,0 +1,21 @@
+import("Campaign_lib");
+import("Util_lib");
+import("system.vars");
+import("system.result");
+import("Sql_lib");
+import("system.translate");
+
+var validCount = JSON.parse(vars.get("$field.campaignparticipantContactIds")).length;
+var maxCount = vars.get("$field.campaignStepMaxParticipantCount");
+
+var isUpdate = Utils.toBoolean(vars.get("$param.isUpdate_param"));
+
+if (vars.get("$field.CAMPAIGN_ID")){
+    var currentCount = CampaignUtils.getParticipantCountForStep(vars.get("$field.CAMPAIGNSTEP_ID"),vars.get("$field.CAMPAIGN_ID"));
+    if ( (validCount+currentCount) > maxCount)
+        result.string(translate.text("Not enough room in campaignstep"));
+    
+    if (validCount == 0 && isUpdate){
+        result.string(translate.text("All of the chosen records are already in the campaignstep"));
+    }
+}
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index bf3e51e64ed34bf5bd755d4e402cba16e6761737..1fc9a21e9d608dff16a653d76fef388a63123cab 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -8406,6 +8406,9 @@
     <entry>
       <key>Redirect needs a full Url with http/https</key>
     </entry>
+    <entry>
+      <key>Not enough room in campaignstep</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 17bae142f1e9bee4aa6f13cb3db1efab8e75f674..3a6dbc11f1f96b584186cc24f0c6b29d832e1b0c 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -42,6 +42,10 @@
       <key>Value is too big, the maximum is %0</key>
       <value>Wert ist zu groß, das Maximum ist %0</value>
     </entry>
+    <entry>
+      <key>Not enough room in campaignstep</key>
+      <value>In der Kampagnenstufe ist nicht genug Platz vorhanden</value>
+    </entry>
     <entry>
       <key>The max participants count can not be equal or less then 0</key>
       <value>Die maximale Teilnehmerzahl muss größer 0 sein!</value>
@@ -571,6 +575,10 @@
       <key>Object selection</key>
       <value>Objektauswahl</value>
     </entry>
+    <entry>
+      <key>All of the chosen records are already in the campaign</key>
+      <value>Alle ausgewählten Datensätze sind schon in der Kampagne.</value>
+    </entry>
     <entry>
       <key>Send</key>
       <value>Senden</value>
@@ -1163,6 +1171,10 @@
       <key>Steps</key>
       <value>Stufen</value>
     </entry>
+    <entry>
+      <key>All of the chosen records are already in the campaignstep</key>
+      <value>Alle ausgewählten Datensätze sind schon in der Kampagnenstufe.</value>
+    </entry>
     <entry>
       <key>Days inactive</key>
       <value>Tage inaktiv</value>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index 05ef67a837886b28d381207d97e0ce040a1df08b..775c68dacdaa8027b09cc035d8132b22dd07b3d7 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -8336,7 +8336,7 @@
     </entry>
     <entry>
       <key>Value must be an integer</key>
-    </entry>
+    </entry>    
     <entry>
       <key>Buyer</key>
     </entry>
@@ -8490,6 +8490,9 @@
     <entry>
       <key>Redirect needs a full Url with http/https</key>
     </entry>
+    <entry>
+      <key>Not enough room in campaignstep</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/process/Campaign_lib/process.js b/process/Campaign_lib/process.js
index 7606f5621de2acaf083d346df68143384f7d297b..f488f0ee653f84eb47ab793219f9965bfd6d6a04 100644
--- a/process/Campaign_lib/process.js
+++ b/process/Campaign_lib/process.js
@@ -512,6 +512,27 @@ CampaignUtils.GetContactIdsNotInCampaignByRowIds = function(pCampaignId, pPartic
                 .arrayColumn();
 }
 
+
+/**
+ * Returns the contact ids which aren't in the given campaignstep.<br>
+ * 
+ * @param {String} pCampaignStepId                      <p>
+ *                                                  The id of the campaignstep.<br>
+ * @param {String[]} pParticipantRowIds             <p>
+ *                                                  The participant ids (campaignparticipantids).<br>
+ * @return {String[]}                               <p>
+ *                                                  The contact ids which arent in the<br>
+ *                                                  given campaignstep.<br>                                                                                                  
+ */
+CampaignUtils.GetContactIdsNotInCampaignStepByRowIds = function(pCampaignStepId, pParticipantRowIds)
+{   
+    return newSelect("CAMPAIGNPARTICIPANT.CONTACT_ID")
+                .from("CAMPAIGNPARTICIPANT")
+                .where("CAMPAIGNPARTICIPANT.CAMPAIGNPARTICIPANTID", pParticipantRowIds, SqlBuilder.IN())
+                .and("CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID",pCampaignStepId,SqlBuilder.NOT_EQUAL())
+                .arrayColumn();
+}
+
 /**
  * Returns the contact ids which arent in the campaign<br>
  * with the given campaign id.<br>
@@ -537,7 +558,7 @@ CampaignUtils.GetContactIdsNotInCampaignByCondition = function(pCampaignId, pCon
                     .from("CONTACT");
 
     if (origin == "Person")
-       query.leftJoin("PERSON", "CONTACT.PERSON_ID = PERSON.PERSONID");
+       query.join("PERSON", "CONTACT.PERSON_ID = PERSON.PERSONID");
 
     query.join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
         .leftJoin("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID")
@@ -556,6 +577,41 @@ CampaignUtils.GetContactIdsNotInCampaignByCondition = function(pCampaignId, pCon
     return query.arrayColumn();
 }
 
+/**
+ * Returns the contact ids which arent in a different campaignstep of the same campaign<br>
+ * with the given campaign id.<br>
+ * 
+ * @param {String} pCampaignStepId                      <p>
+ *                                                  The id of the campaignstep.<br>
+ * @param {String} pCampaignId                      <p>
+ *                                                  The id of the campaign.<br>
+ * @param {String} pCondition (optional)            <p>
+ *                                                  An condition which is used to limit the search contact results.<br>
+ * @return {String[]}                               <p>
+ *                                                  The contact ids that arent in the campaignstep.<br>                                                                                                                                                    
+ */
+CampaignUtils.GetContactIdsNotInCampaignStepByCondition = function(pCampaignStepId,pCampaignId, pCondition)
+{
+
+    var subselect = newSelect("CAMPAIGNPARTICIPANT.CONTACT_ID")
+        .from("CAMPAIGNPARTICIPANT")
+        .where("CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID", pCampaignStepId);
+    
+        var query = newSelect("CONTACT.CONTACTID")
+        .from("CONTACT")
+        .join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
+        .join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
+        .leftJoin("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID")
+        .where("CAMPAIGNPARTICIPANT.CAMPAIGN_ID",pCampaignId )
+        .and("CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID",pCampaignStepId,SqlBuilder.NOT_EQUAL());
+            
+
+    if(pCondition != "")
+        query.and(pCondition);
+
+    return query.arrayColumn();
+}
+
 /**
  * Returns the contact ids which are in the campaign,<br>
  * with the given campaign id.<br>