From f360663a142e3dede4bda9d102c260cdc8bf8ae4 Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Wed, 11 Sep 2024 08:12:07 +0200
Subject: [PATCH] move fields from repo to class; refactor repository; cleanup

---
 .../vorgang/command/CommandRepository.java    | 181 +++++++++---------
 .../vorgang/command/PersistedCommand.java     |  21 +-
 .../vorgang/common/db/CriteriaUtil.java       |  41 ++--
 .../vorgang/common/db/MongoDbUtil.java        |  40 ++++
 .../vorgang/command/CommandServiceITCase.java |   7 +-
 5 files changed, 175 insertions(+), 115 deletions(-)
 create mode 100644 vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/MongoDbUtil.java

diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
index a9f57bac1..b2eb48e5b 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
@@ -23,6 +23,8 @@
  */
 package de.ozgcloud.vorgang.command;
 
+import static de.ozgcloud.vorgang.command.PersistedCommand.*;
+import static de.ozgcloud.vorgang.common.db.MongoDbUtil.*;
 import static de.ozgcloud.vorgang.common.db.CriteriaUtil.*;
 import static org.springframework.data.mongodb.core.query.Criteria.*;
 import static org.springframework.data.mongodb.core.query.Query.*;
@@ -39,11 +41,6 @@ import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.FindAndModifyOptions;
 import org.springframework.data.mongodb.core.MongoOperations;
-import org.springframework.data.mongodb.core.aggregation.Aggregation;
-import org.springframework.data.mongodb.core.aggregation.ComparisonOperators.Eq;
-import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch;
-import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch.CaseOperator;
-import org.springframework.data.mongodb.core.aggregation.SetOperation;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
@@ -56,27 +53,16 @@ import de.ozgcloud.command.CommandStatus;
 @Repository
 class CommandRepository {
 
-	private static final String MONGODB_ID = "id";
-	static final String MONGODB_STATUS = "status";
-	private static final String MONGODB_REFERENCE_STATUS = "$status";
-	private static final String MONGODB_FINISHED_AT = "finishedAt";
-	private static final String MONGODB_RELATION_VERSION = "relationVersion";
-	private static final String MONGODB_ERROR_MSG = "errorMessage";
-	private static final String MONGODB_ORDER = "order";
-	private static final String MONGODB_PREVIOUS_STATE = "previousState";
-	private static final String MONGODB_CREATED_AT = "createdAt";
-	private static final String MONGODB_CREATED_BY = "createdBy";
 	private static final String MONGODB_ASSIGNED_TO = "body.assignedTo";
-	private static final String MONGODB_CREATED_RESOURCE = "createdResource";
-	private static final String MONGODB_PARENT_ID = PersistedCommand.FIELD_BODY_OBJECT + "." + PersistedCommand.PROPERTY_PARENT_ID;
-	private static final String MONGODB_COMPLETE_IF_SUBS_COMPLETED = PersistedCommand.FIELD_BODY_OBJECT + "."
+	private static final String MONGODB_PARENT_ID = BODY_OBJECT_FIELD + "." + PersistedCommand.PROPERTY_PARENT_ID;
+	private static final String MONGODB_COMPLETE_IF_SUBS_COMPLETED = BODY_OBJECT_FIELD + "."
 			+ PersistedCommand.PROPERTY_COMPLETE_IF_SUBS_COMPLETED;
 	private static final String MONGODB_CLASS = "_class";
 
 	@Autowired
 	private MongoOperations mongoOperations;
 
-	Command save(Command command) {
+	public Command save(Command command) {
 		return mongoOperations.save(command);
 	}
 
@@ -85,27 +71,22 @@ class CommandRepository {
 	}
 
 	void finishCommand(String commandId, String createdResource) {
-		finishCommand(commandId, new Update().set(MONGODB_CREATED_RESOURCE, createdResource));
+		finishCommand(commandId, new Update().set(PersistedCommand.CREATED_RESOURCE_FIELD, createdResource));
 	}
 
 	private void finishCommand(String commandId, Update update) {
-		mongoOperations.updateFirst(
-				queryByIdAndPending(commandId),
-				update.set(MONGODB_STATUS, CommandStatus.FINISHED).set(MONGODB_FINISHED_AT, ZonedDateTime.now()),
-				Command.class);
+		var enhancedUpdate = update.set(MONGODB_STATUS, CommandStatus.FINISHED).set(FINISHED_AT_FIELD, ZonedDateTime.now());
+		updateFirst(queryByIdAndPending(commandId), enhancedUpdate);
 	}
 
 	private Query queryByIdAndPending(String commandId) {
 		return query(new Criteria().andOperator(
-				criteriaById(commandId),
-				where(MONGODB_STATUS).in(CommandStatus.PENDING, CommandStatus.REVOKE_PENDING)));
+				whereIdIs(commandId),
+				isStatusIn(CommandStatus.PENDING, CommandStatus.REVOKE_PENDING)));
 	}
 
 	void updateCommandStatus(String commandId, CommandStatus status) {
-		mongoOperations.updateFirst(
-				queryById(commandId),
-				new Update().set(MONGODB_STATUS, status),
-				Command.class);
+		updateFirstById(commandId, new Update().set(MONGODB_STATUS, status));
 	}
 
 	public Command updateCommandStatusAndReturnPrevious(String commandId, CommandStatus status) {
@@ -113,21 +94,18 @@ class CommandRepository {
 	}
 
 	void setErrorMessage(String commandId, String errorMsg) {
-		mongoOperations.updateFirst(queryById(commandId),
-				new Update()
-						.set(MONGODB_STATUS, CommandStatus.ERROR)
-						.set(MONGODB_ERROR_MSG, errorMsg)
-						.set(MONGODB_FINISHED_AT, ZonedDateTime.now()),
-				Command.class);
+		var update = new Update()
+				.set(MONGODB_STATUS, CommandStatus.ERROR)
+				.set(ERROR_MSG_FIELD, errorMsg)
+				.set(FINISHED_AT_FIELD, ZonedDateTime.now());
+		updateFirstById(commandId, update);
 	}
 
 	void updateCommandStatusAndVersion(String commandId, CommandStatus status, long relationVersion) {
-		mongoOperations.updateFirst(
-				queryById(commandId),
-				new Update()
-						.set(MONGODB_STATUS, status)
-						.set(MONGODB_RELATION_VERSION, relationVersion),
-				Command.class);
+		var update = new Update()
+				.set(MONGODB_STATUS, status)
+				.set(RELATION_VERSION_FIELD, relationVersion);
+		updateFirstById(commandId, update);
 	}
 
 	Optional<Command> findById(String commandId) {
@@ -135,30 +113,33 @@ class CommandRepository {
 	}
 
 	boolean existsPendingCommands(String vorgangId) {
-		return mongoOperations.exists(buildPendingCommandQuery(vorgangId), Command.class);
+		return exists(buildPendingCommandQuery(vorgangId));
 	}
 
 	List<Command> getPendingCommands(String relationId) {
-		return mongoOperations.find(buildPendingCommandQuery(relationId), Command.class);
+		return find(buildPendingCommandQuery(relationId));
 	}
 
 	private Query buildPendingCommandQuery(String vorgangId) {
-		return query(new Criteria().andOperator(
-				where(PersistedCommand.FIELD_VORGANG_ID).is(vorgangId),
-				where(MONGODB_STATUS).in(CommandStatus.PENDING.name(), CommandStatus.REVOKE_PENDING.name())));
+		return query(new Criteria().andOperator(isVorgangId(vorgangId),
+				isStatusIn(CommandStatus.PENDING.name(), CommandStatus.REVOKE_PENDING.name())));
 	}
 
 	public List<Command> findCommands(String vorgangId, Collection<CommandStatus> status, Optional<Order> order) {
-		return mongoOperations.find(buildCommandsQuery(vorgangId, status, order), Command.class);
+		return find(buildCommandsQuery(vorgangId, status, order));
+	}
+
+	private List<Command> find(Query query) {
+		return mongoOperations.find(query, Command.class);
 	}
 
 	private Query buildCommandsQuery(String vorgangId, Collection<CommandStatus> status, Optional<Order> commandOrder) {
-		var result = query(where(PersistedCommand.FIELD_VORGANG_ID).is(vorgangId));
+		var result = query(isVorgangId(vorgangId));
 
 		if (!status.isEmpty()) {
-			result.addCriteria(new Criteria(MONGODB_STATUS).in(status));
+			result.addCriteria(isStatusIn(status));
 		}
-		commandOrder.map(Order::name).ifPresent(order -> result.addCriteria(new Criteria(MONGODB_ORDER).is(order)));
+		commandOrder.map(Order::name).ifPresent(order -> result.addCriteria(isOrder(order)));
 
 		return result;
 	}
@@ -168,47 +149,51 @@ class CommandRepository {
 	}
 
 	private Query buildCommandsQuery(Order order, CommandStatus status, ZonedDateTime createdBefore) {
-		var result = query(where(MONGODB_ORDER).is(order.name()).and(MONGODB_STATUS).is(status));
-		result.addCriteria(new Criteria(MONGODB_CREATED_AT).lte(createdBefore));
+		var result = query(where(ORDER_FIELD).is(order.name()).and(MONGODB_STATUS).is(status));
+		result.addCriteria(new Criteria(CREATED_AT_FIELD).lte(createdBefore));
 		return result;
 	}
 
 	public void patch(String commandId, Map<String, Object> previousState) {
-		mongoOperations.updateFirst(
-				queryById(commandId),
-				buildItemPatchUpdate(previousState),
-				Command.class);
-	}
-
-	private Update buildItemPatchUpdate(Map<String, Object> valueMap) {
-		Update update = new Update();
-		for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
-			update.set("%s.%s".formatted(MONGODB_PREVIOUS_STATE, entry.getKey()), entry.getValue());
-		}
-		return update;
+		updateFirstById(commandId, buildUpdateFieldsByMap(PersistedCommand.PREVIOUS_STATE_FIELD, previousState));
 	}
 
 	public void deleteAllByVorgang(String vorgangId) {
-		mongoOperations.remove(query(where(PersistedCommand.FIELD_VORGANG_ID).is(vorgangId)), PersistedCommand.COLLECTION_NAME);
+		mongoOperations.remove(query(where(VORGANG_ID_FIELD).is(vorgangId)), Command.COLLECTION_NAME);
 	}
 
 	public boolean existsCommandWithUserId(String userId) {
-		return mongoOperations.exists(query(buildCreatedByOrAssignedToCriteria(userId)), PersistedCommand.COLLECTION_NAME);
+		return exists(query(buildCreatedByOrAssignedToCriteria(userId)));
 	}
 
 	Criteria buildCreatedByOrAssignedToCriteria(String userId) {
-		return new Criteria().orOperator(where(MONGODB_CREATED_BY).is(userId), where(MONGODB_ASSIGNED_TO).is(userId));
+		return new Criteria().orOperator(where(CREATED_BY_FIELD).is(userId), where(MONGODB_ASSIGNED_TO).is(userId));
 	}
 
 	public void addSubCommands(String commandId, Map<String, Object> subCommandValues) {
+		updateFirstById(commandId, buildUpdateFieldsByMap(BODY_OBJECT_FIELD, subCommandValues));
+	}
+
+	private Update buildUpdateFieldsByMap(String field, Map<String, Object> values) {
 		var update = new Update();
-		subCommandValues.forEach((key, value) -> update.set("%s.%s".formatted(PersistedCommand.FIELD_BODY_OBJECT, key), value));
-		mongoOperations.updateFirst(queryById(commandId), update, Command.class);
+		values.forEach((key, value) -> update.set("%s.%s".formatted(field, key), value));
+		return update;
+	}
+
+	private void updateFirstById(String commandId, Update update) {
+		updateFirst(queryById(commandId), update);
+	}
+
+	private void updateFirst(Query query, Update update) {
+		mongoOperations.updateFirst(query, update, Command.class);
 	}
 
 	public boolean isCommandFailed(String commandId) {
-		return mongoOperations.exists(query(new Criteria().andOperator(criteriaById(commandId), where(MONGODB_STATUS).is(CommandStatus.ERROR))),
-				Command.class);
+		return exists(buildCommandIsErrorQuery(commandId));
+	}
+
+	private Query buildCommandIsErrorQuery(String commandId) {
+		return query(new Criteria().andOperator(whereIdIs(commandId), where(MONGODB_STATUS).is(CommandStatus.ERROR)));
 	}
 
 	public Optional<String> getParentId(String commandId) {
@@ -217,8 +202,8 @@ class CommandRepository {
 		return findOne(query).map(Command::getBodyObject).map(this::getParentIdProperty);
 	}
 
-	private Criteria criteriaById(String commandId) {
-		return where(MONGODB_ID).is(commandId);
+	private Criteria whereIdIs(String commandId) {
+		return where(ID_FIELD).is(commandId);
 	}
 
 	String getParentIdProperty(Map<String, Object> body) {
@@ -230,7 +215,7 @@ class CommandRepository {
 	}
 
 	public boolean isCompleteIfSubsCompleted(String commandId) {
-		return mongoOperations.exists(buildQueryCompleteIfSubsCompleted(commandId), Command.class);
+		return exists(buildQueryCompleteIfSubsCompleted(commandId));
 	}
 
 	Query buildQueryCompleteIfSubsCompleted(String commandId) {
@@ -238,11 +223,15 @@ class CommandRepository {
 	}
 
 	public boolean existsNotFinishedSubCommands(String parentId) {
-		return mongoOperations.exists(buildQueryNotInStatus(parentId, CommandStatus.FINISHED, CommandStatus.REVOKED), Command.class);
+		return exists(buildQueryNotInStatus(parentId, CommandStatus.FINISHED, CommandStatus.REVOKED));
+	}
+
+	private boolean exists(Query query) {
+		return mongoOperations.exists(query, Command.class);
 	}
 
 	Query buildQueryNotInStatus(String parentId, CommandStatus status, CommandStatus... statuses) {
-		Object[] excludeStatuses = ArrayUtils.add(statuses, status);
+		var excludeStatuses = ArrayUtils.<Object>add(statuses, status);
 		return query(new Criteria().andOperator(
 				buildIsParentIdCriteria(parentId),
 				where(MONGODB_STATUS).nin(excludeStatuses)));
@@ -257,39 +246,41 @@ class CommandRepository {
 	}
 
 	Query includeIdAndClass(Query query) {
-		query.fields().include(MONGODB_CLASS, MONGODB_ID);
+		query.fields().include(MONGODB_CLASS, ID_FIELD);
 		return query;
 	}
 
 	public Command setRevokeStatus(String id) {
-		return mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevoke(), FindAndModifyOptions.options().returnNew(true), Command.class);
+		return findAndModifyById(id, buildUpdateStatusRevoke());
 	}
 
 	private UpdateDefinition buildUpdateStatusRevoke() {
-		var switchOperation = Switch.switchCases(
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.NEW)).then(CommandStatus.CANCELED),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.PENDING)).then(CommandStatus.REVOKE_PENDING),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING))
-				.defaultTo(MONGODB_REFERENCE_STATUS);
-		return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(switchOperation));
+		return buildConditionalStatusUpdateDefinition(
+				createStatusCaseOperator(CommandStatus.NEW, CommandStatus.CANCELED),
+				createStatusCaseOperator(CommandStatus.PENDING, CommandStatus.REVOKE_PENDING),
+				createStatusCaseOperator(CommandStatus.FINISHED, CommandStatus.REVOKE_PENDING));
 	}
 
 	public Optional<Command> setRevokeStatusIfNotPending(String id) {
-		var updateCommand = mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevokeIfNotPending(),
-				FindAndModifyOptions.options().returnNew(true), Command.class);
-		return Optional.ofNullable(updateCommand);
+		return Optional.ofNullable(findAndModifyById(id, buildUpdateStatusRevokeIfNotPending()));
+	}
+
+	private Command findAndModifyById(String id, UpdateDefinition update) {
+		return findAndModify(queryById(id), update);
+	}
+
+	private Command findAndModify(Query query, UpdateDefinition update) {
+		return mongoOperations.findAndModify(query, update, FindAndModifyOptions.options().returnNew(true), Command.class);
 	}
 
 	private Query queryById(String commandId) {
-		return query(criteriaById(commandId));
+		return query(whereIdIs(commandId));
 	}
 
 	private UpdateDefinition buildUpdateStatusRevokeIfNotPending() {
-		var switchOperation = Switch.switchCases(
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.NEW)).then(CommandStatus.CANCELED),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING)
-		).defaultTo(MONGODB_REFERENCE_STATUS);
-		return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(switchOperation));
+		return buildConditionalStatusUpdateDefinition(
+				createStatusCaseOperator(CommandStatus.NEW, CommandStatus.CANCELED),
+				createStatusCaseOperator(CommandStatus.FINISHED, CommandStatus.REVOKE_PENDING));
 	}
 
-}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java
index 71964af4d..c804970d5 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java
@@ -41,15 +41,28 @@ import lombok.ToString;
 @ToString
 @Getter
 @Builder
-@Document(collection = PersistedCommand.COLLECTION_NAME)
+@Document(collection = Command.COLLECTION_NAME)
 @TypeAlias("Command")
 public class PersistedCommand implements Command {
 
-	public static final String COLLECTION_NAME = "command";
+	public static final String ID_FIELD = "id";
+	public static final String VORGANG_ID_FIELD = "vorgangId";
+	public static final String RELATION_ID_FIELD = "relationId";
+	public static final String RELATION_VERSION_FIELD = "relationVersion";
+	public static final String ORDER_FIELD = "order";
 
-	static final String FIELD_VORGANG_ID = "vorgangId";
+	public static final String CREATED_AT_FIELD = "createdAt";
+	public static final String FINISHED_AT_FIELD = "finishedAt";
+
+	public static final String CREATED_BY_FIELD = "createdBy";
+
+	public static final String BODY_OBJECT_FIELD = "bodyObject";
+
+	public static final String ERROR_MSG_FIELD = "errorMessage";
+
+	public static final String PREVIOUS_STATE_FIELD = "previousState";
+	public static final String CREATED_RESOURCE_FIELD = "createdResource";
 
-	static final String FIELD_BODY_OBJECT = "bodyObject";
 	static final String PROPERTY_PARENT_ID = "parentId";
 	static final String PROPERTY_EXECUTION_MODE = "executionMode";
 	static final String PROPERTY_COMPLETE_IF_SUBS_COMPLETED = "completedIfSubsCompleted";
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java
index 8ae78e4e4..8bcd68421 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java
@@ -23,7 +23,9 @@
  */
 package de.ozgcloud.vorgang.common.db;
 
+import static de.ozgcloud.vorgang.common.db.MongoDbUtil.*;
 import static de.ozgcloud.vorgang.vorgang.Vorgang.*;
+import static org.springframework.data.mongodb.core.query.Criteria.*;
 
 import java.time.LocalDate;
 import java.util.Arrays;
@@ -33,7 +35,9 @@ import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.data.mongodb.core.query.Criteria;
 
+import de.ozgcloud.vorgang.command.PersistedCommand;
 import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 
@@ -49,19 +53,19 @@ public class CriteriaUtil {
 	public static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY = CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY + ".value";
 
 	public static Criteria isId(String id) {
-		return new Criteria(MONGODB_FIELDNAME_ID).is(id);
+		return where(MONGODB_FIELDNAME_ID).is(id);
 	}
 
 	public static Criteria isNotDeleted() {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).ne(Vorgang.Status.DELETED);
+		return where(MONGODB_FIELDNAME_STATUS).ne(Status.DELETED);
 	}
 
 	public static Criteria inOrganisationseinheitenIds(Collection<String> ids) {
-		return new Criteria(FIELD_ORGANISATIONSEINHEIT).in(ids);
+		return where(FIELD_ORGANISATIONSEINHEIT).in(ids);
 	}
 
 	public static Criteria vorgangNotInCreation() {
-		return new Criteria(MONGODB_FIELDNAME_IN_CREATION).is(false);
+		return where(MONGODB_FIELDNAME_IN_CREATION).is(false);
 	}
 
 	public static Criteria vorgangIsAssignedTo(String assignedTo) {
@@ -69,32 +73,32 @@ public class CriteriaUtil {
 	}
 
 	public static Criteria vorgangIsUnassigned() {
-		return new Criteria(MONGODB_FIELDNAME_ASSIGNED_TO).exists(false);
+		return where(MONGODB_FIELDNAME_ASSIGNED_TO).exists(false);
 	}
 
 	public static Criteria vorgangInStatus(List<Status> status) {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).in(status);
+		return where(MONGODB_FIELDNAME_STATUS).in(status);
 	}
 
 	public static Criteria vorgangRemainingStatus() {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).not().in(Status.NEU, Status.ANGENOMMEN, Status.BESCHIEDEN, Status.IN_BEARBEITUNG,
+		return where(MONGODB_FIELDNAME_STATUS).not().in(Status.NEU, Status.ANGENOMMEN, Status.BESCHIEDEN, Status.IN_BEARBEITUNG,
 				Status.WEITERGELEITET);
 	}
 
 	public static Criteria vorgangStatusBearbeitet() {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).in(Status.BESCHIEDEN, Status.WEITERGELEITET);
+		return where(MONGODB_FIELDNAME_STATUS).in(Status.BESCHIEDEN, Status.WEITERGELEITET);
 	}
 
 	public static Criteria vorgangStatusZuBearbeitendeEA() {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).in(Status.NEU, Status.ANGENOMMEN);
+		return where(MONGODB_FIELDNAME_STATUS).in(Status.NEU, Status.ANGENOMMEN);
 	}
 
 	public static Criteria vorgangStatusZuBearbeitende() {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).in(Status.NEU, Status.ANGENOMMEN, Status.IN_BEARBEITUNG);
+		return where(MONGODB_FIELDNAME_STATUS).in(Status.NEU, Status.ANGENOMMEN, Status.IN_BEARBEITUNG);
 	}
 
 	public static Criteria vorgangStatusInBearbeitung() {
-		return new Criteria(MONGODB_FIELDNAME_STATUS).is(Status.IN_BEARBEITUNG);
+		return where(MONGODB_FIELDNAME_STATUS).is(Status.IN_BEARBEITUNG);
 	}
 
 	public static Criteria searchCriteria(String searchString) {
@@ -113,11 +117,11 @@ public class CriteriaUtil {
 	}
 
 	public static Criteria nextWiedervorlageFristInThePast() {
-		return new Criteria(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).lte(LocalDate.now().toString());
+		return where(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).lte(LocalDate.now().toString());
 	}
 
 	public static Criteria nextWiedervorlageFristInTheFuture() {
-		return new Criteria(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).gt(LocalDate.now().toString());
+		return where(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).gt(LocalDate.now().toString());
 	}
 
 	public static Criteria withoutNextWiedervorlageFrist() {
@@ -132,4 +136,15 @@ public class CriteriaUtil {
 		return isId(vorgangId).and(MONGODB_FIELDNAME_VERSION).is(version);
 	}
 
+	public static Criteria isVorgangId(String vorgangId) {
+		return where(PersistedCommand.VORGANG_ID_FIELD).is(vorgangId);
+	}
+
+	public static Criteria isStatusIn(Object... status) {
+		return where(MONGODB_STATUS).in(status);
+	}
+
+	public static Criteria isOrder(String order) {
+		return where(PersistedCommand.ORDER_FIELD).is(order);
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/MongoDbUtil.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/MongoDbUtil.java
new file mode 100644
index 000000000..3ca4658ce
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/MongoDbUtil.java
@@ -0,0 +1,40 @@
+package de.ozgcloud.vorgang.common.db;
+
+import org.springframework.data.mongodb.core.aggregation.Aggregation;
+import org.springframework.data.mongodb.core.aggregation.ComparisonOperators.Eq;
+import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch;
+import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch.CaseOperator;
+import org.springframework.data.mongodb.core.aggregation.SetOperation;
+import org.springframework.data.mongodb.core.query.UpdateDefinition;
+
+import de.ozgcloud.command.CommandStatus;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class MongoDbUtil {
+
+	public static final String MONGODB_STATUS = "status";
+
+	private static final String MONGODB_REFERENCE_STATUS = "$status";
+
+	public static UpdateDefinition buildConditionalStatusUpdateDefinition(CaseOperator... conditions) {
+		return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(createStatusSwitch(conditions)));
+	}
+
+	private static Switch createStatusSwitch(CaseOperator... conditions) {
+		return createSwitch(MONGODB_REFERENCE_STATUS, conditions);
+	}
+
+	private static Switch createSwitch(String field, CaseOperator... conditions) {
+		return Switch.switchCases(conditions).defaultTo(field);
+	}
+
+	public static CaseOperator createStatusCaseOperator(CommandStatus beEqualWith, CommandStatus shouldSetTo) {
+		return createCaseOperator(MONGODB_STATUS, beEqualWith, shouldSetTo);
+	}
+
+	private static CaseOperator createCaseOperator(String field, Object beEqualWith, Object shouldSetTo) {
+		return CaseOperator.when(Eq.valueOf(field).equalToValue(beEqualWith)).then(shouldSetTo);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
index 36429601b..bf4d368b7 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
@@ -47,6 +47,7 @@ import de.ozgcloud.command.CommandStatus;
 import de.ozgcloud.common.test.DataITCase;
 import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
 import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.common.db.MongoDbUtil;
 import de.ozgcloud.vorgang.vorgang.Vorgang;
 import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
@@ -161,13 +162,13 @@ class CommandServiceITCase {
 			return CommandTestFactory.createBuilder().id(null).status(CommandStatus.ERROR)
 					.bodyObject(Map.of(
 							PersistedCommand.PROPERTY_EXECUTION_MODE, SubCommandExecutionMode.PARALLEL.name(),
-							PersistedCommand.PROPERTY_COMPLETE_IF_SUBS_COMPLETED, true
-					)).build();
+							PersistedCommand.PROPERTY_COMPLETE_IF_SUBS_COMPLETED, true))
+					.build();
 		}
 
 		private Command createSubCommand(String parentId) {
 			return CommandTestFactory.createBuilder().id(null).vorgangId(vorgang.getId())
-					.previousState(Map.of(CommandRepository.MONGODB_STATUS, Vorgang.Status.NEU.name()))
+					.previousState(Map.of(MongoDbUtil.MONGODB_STATUS, Vorgang.Status.NEU.name()))
 					.bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, parentId)).build();
 		}
 	}
-- 
GitLab