diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java
deleted file mode 100644
index 08b847bcd744850f07e2128f98ea770dabb889ef..0000000000000000000000000000000000000000
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.alfa.historie;
-
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.commons.collections.MapUtils;
-import org.springframework.stereotype.Component;
-
-import de.ozgcloud.alfa.common.command.Command;
-import de.ozgcloud.alfa.common.command.CommandBodyMapper;
-import de.ozgcloud.alfa.common.command.LegacyOrder;
-import de.ozgcloud.alfa.wiedervorlage.Wiedervorlage;
-
-/**
- * Bitte zukuenftig als Implementierung von {@link HistorieProcessor} in den
- * jeweiligen fachlichen packages umsetzen.
- *
- * TODO: Aktuellen Code auf Processoren umstellen
- */
-@Component
-class HistorieCommandHandler {
-
-	public Command translateOrder(Command command) {
-		HistorieCommandHandler translator = new HistorieCommandHandler();
-		return switch (command.getCommandOrder()) {
-			case CREATE_ATTACHED_ITEM:
-				yield translator.mapCreateOrder(command);
-			case UPDATE_ATTACHED_ITEM:
-				yield translator.mapUpdateOrder(command);
-			case PATCH_ATTACHED_ITEM:
-				yield translator.mapPatchOrder(command);
-			default:
-				yield command;
-		};
-	}
-
-	private Command mapCreateOrder(Command command) {
-		var resultBuilder = command.toBuilder();
-		var itemName = getItemName(command);
-
-		itemName.ifPresent(name -> {
-			if (name.equals(Wiedervorlage.class.getSimpleName())) {
-				resultBuilder.order(LegacyOrder.CREATE_WIEDERVORLAGE).build();
-			}
-		});
-
-		return resultBuilder.build();
-	}
-
-	private Command mapUpdateOrder(Command command) {
-		var resultBuilder = command.toBuilder();
-		var itemName = getItemName(command);
-
-		itemName.ifPresent(name -> {
-			if (name.equals(Wiedervorlage.class.getSimpleName())) {
-				resultBuilder.order(LegacyOrder.EDIT_WIEDERVORLAGE).build();
-			}
-		});
-
-		return resultBuilder.build();
-	}
-
-	private Optional<String> getItemName(Command command) {
-		return Optional.ofNullable(MapUtils.getString(command.getBody(), CommandBodyMapper.ITEM_NAME_PROPERTY));
-	}
-
-	private Command mapPatchOrder(Command command) {
-		var resultBuilder = command.toBuilder();
-		var isDone = getDoneValue(command);
-
-		isDone.ifPresent(done -> {
-			if (done.booleanValue()) {
-				resultBuilder.order(LegacyOrder.WIEDERVORLAGE_ERLEDIGEN).build();
-			} else {
-				resultBuilder.order(LegacyOrder.WIEDERVORLAGE_WIEDEREROEFFNEN).build();
-			}
-		});
-
-		return resultBuilder.build();
-	}
-
-	private Optional<Boolean> getDoneValue(Command command) {
-		return Optional.ofNullable(MapUtils.getBoolean(getItemMap(command), Wiedervorlage.DONE_FIELD));
-	}
-
-	@SuppressWarnings("unchecked")
-	private Map<String, Object> getItemMap(Command command) {
-		return MapUtils.getMap(command.getBody(), CommandBodyMapper.ITEM_PROPERTY);
-	}
-}
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieService.java
index 47da447b7ba760e58d7614f3397012334174fbd6..89cee62e20fe8102680db68687af819b1df58bc2 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieService.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/historie/HistorieService.java
@@ -37,26 +37,17 @@ import lombok.RequiredArgsConstructor;
 class HistorieService {
 
 	private final CommandService commandService;
-	private final HistorieCommandHandler historieCommandHandler;
 	private final List<HistorieProcessor> processors;
 
 	public Stream<Command> findFinishedCommands(String vorgangId) {
-		var commands = commandService.findFinishedCommands(vorgangId)
-				.map(historieCommandHandler::translateOrder).toList();
+		var commands = commandService.findFinishedCommands(vorgangId);
 		return processCommands(commands);
 	}
 
-	private Stream<Command> processCommands(List<Command> commands) {
-		return new CommandHistorieProcessor().process(commands).stream();
-	}
-
-	class CommandHistorieProcessor {
-		private List<Command> processedCommands;
-
-		public List<Command> process(List<Command> commands) {
-			processedCommands = commands;
-			processors.forEach(processor -> processedCommands = processor.process(processedCommands.stream()).toList());
-			return processedCommands;
+	Stream<Command> processCommands(Stream<Command> commands) {
+		for (var processor : processors) {
+			commands = processor.process(commands);
 		}
+		return commands;
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageHistorieProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageHistorieProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..0403aae0fbef7e4fc1f796377064153a30d8df1c
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageHistorieProcessor.java
@@ -0,0 +1,86 @@
+package de.ozgcloud.alfa.wiedervorlage;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.commons.collections.MapUtils;
+
+import de.ozgcloud.alfa.common.command.Command;
+import de.ozgcloud.alfa.common.command.CommandBodyMapper;
+import de.ozgcloud.alfa.common.command.CommandOrder;
+import de.ozgcloud.alfa.common.command.LegacyOrder;
+import de.ozgcloud.alfa.historie.HistorieProcessor;
+
+class WiedervorlageHistorieProcessor implements HistorieProcessor {
+
+	@Override
+	public Stream<Command> process(Stream<Command> commands) {
+		return commands
+				.map(this::translateCreateAttachedItem)
+				.map(this::translateUpdateAttachedItem)
+				.map(this::translatePatchAttachedItem);
+	}
+
+	Command translateCreateAttachedItem(Command command) {
+		if (isCreateWiederVorlage(command)) {
+			return command.toBuilder().order(LegacyOrder.CREATE_WIEDERVORLAGE).build();
+		}
+		return command;
+	}
+
+	private boolean isCreateWiederVorlage(Command command) {
+		return CommandOrder.CREATE_ATTACHED_ITEM == command.getCommandOrder()
+				&& isWiedervorlageItem(command);
+	}
+
+	Command translateUpdateAttachedItem(Command command) {
+		if (isEditWiedervorlage(command)) {
+			return command.toBuilder().order(LegacyOrder.EDIT_WIEDERVORLAGE).build();
+		}
+		return command;
+	}
+
+	private boolean isEditWiedervorlage(Command command) {
+		return CommandOrder.UPDATE_ATTACHED_ITEM == command.getCommandOrder()
+				&& isWiedervorlageItem(command);
+	}
+
+	Command translatePatchAttachedItem(Command command) {
+		if (isPatchWiedervorlage(command)) {
+			return translatePatchWiedervorlage(command);
+		}
+		return command;
+	}
+
+	private boolean isPatchWiedervorlage(Command command) {
+		return CommandOrder.PATCH_ATTACHED_ITEM == command.getCommandOrder() && isWiedervorlageItem(command);
+	}
+
+	private boolean isWiedervorlageItem(Command command) {
+		return getItemName(command).filter(name -> name.equals(Wiedervorlage.class.getSimpleName())).isPresent();
+	}
+
+	private Optional<String> getItemName(Command command) {
+		return Optional.ofNullable(MapUtils.getString(command.getBody(), CommandBodyMapper.ITEM_NAME_PROPERTY));
+	}
+
+	Command translatePatchWiedervorlage(Command command) {
+		return getDoneValue(command).map(isDone -> resolvePatchWiedervorlage(command, isDone)).orElse(command);
+
+	}
+
+	private Optional<Boolean> getDoneValue(Command command) {
+		return Optional.ofNullable(MapUtils.getBoolean(getItemMap(command), Wiedervorlage.DONE_FIELD));
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, Object> getItemMap(Command command) {
+		return MapUtils.getMap(command.getBody(), CommandBodyMapper.ITEM_PROPERTY);
+	}
+
+	private Command resolvePatchWiedervorlage(Command command, Boolean isDone) {
+		return isDone.booleanValue() ? command.toBuilder().order(LegacyOrder.WIEDERVORLAGE_ERLEDIGEN).build()
+				: command.toBuilder().order(LegacyOrder.WIEDERVORLAGE_WIEDEREROEFFNEN).build();
+	}
+}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieCommandHandlerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieCommandHandlerTest.java
deleted file mode 100644
index f20fd916c3770331e76cd435527864d8ebefa185..0000000000000000000000000000000000000000
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieCommandHandlerTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.alfa.historie;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Spy;
-
-import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItem;
-import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemService;
-import de.ozgcloud.alfa.common.command.Command;
-import de.ozgcloud.alfa.common.command.CommandOrder;
-import de.ozgcloud.alfa.common.command.CommandService;
-import de.ozgcloud.alfa.common.command.CommandTestFactory;
-import de.ozgcloud.alfa.common.command.LegacyOrder;
-import de.ozgcloud.alfa.wiedervorlage.Wiedervorlage;
-
-class HistorieCommandHandlerTest {
-
-	@Spy
-	@InjectMocks
-	private HistorieCommandHandler handler;
-
-	@Mock
-	private VorgangAttachedItemService vorgangAttachedItemService;
-
-	@Mock
-	private CommandService commandService;
-
-	@DisplayName("translate order")
-	@Nested
-	class TestTranslateOrders {
-
-		@ParameterizedTest
-		@CsvSource(value = { "WIEDERVORLAGE_ERLEDIGEN;true", "WIEDERVORLAGE_WIEDEREROEFFNEN;false" }, delimiter = ';')
-		void shouldTranslateToWiedervolageErledigenOrWiedervolageWiedereroeffnen(String target, String doneValue) {
-			var command = handler.translateOrder(
-					createCommand(Wiedervorlage.class.getSimpleName(), CommandOrder.PATCH_ATTACHED_ITEM, Boolean.valueOf(doneValue)));
-
-			assertThat(command.getOrder()).isEqualTo(target);
-		}
-
-		@Test
-		void shouldHandleMissingDone() {
-			var command = handler.translateOrder(createCommand(Wiedervorlage.class.getSimpleName(), CommandOrder.PATCH_ATTACHED_ITEM));
-
-			assertThat(command.getCommandOrder()).isEqualTo(CommandOrder.PATCH_ATTACHED_ITEM);
-		}
-
-		@Test
-		void shouldHandleUnkownOrder() {
-			var command = handler
-					.translateOrder(createCommand(Wiedervorlage.class.getSimpleName(), CommandOrder.VORGANG_ABSCHLIESSEN));
-
-			assertThat(command.getCommandOrder()).isEqualTo(CommandOrder.VORGANG_ABSCHLIESSEN);
-		}
-
-		@Test
-		void shouldHandleMissingItemName() {
-			var command = CommandTestFactory.createBuilder().order(LegacyOrder.EDIT_KOMMENTAR).body(Map.of("item", Map.of("value", "test")))
-					.build();
-
-			var translatedCommand = handler.translateOrder(command);
-
-			assertThat(translatedCommand.getOrder()).isEqualTo(LegacyOrder.EDIT_KOMMENTAR);
-		}
-
-		private Command createCommand(String itemName, CommandOrder order) {
-			return CommandTestFactory.createBuilder().order(order.name())
-					.body(Map.of(VorgangAttachedItem.FIELD_ITEM_NAME, itemName, "item", Map.of("value", "test"))).build();
-		}
-
-		private Command createCommand(String itemName, CommandOrder order, boolean done) {
-			return CommandTestFactory.createBuilder().order(order.name())
-					.body(Map.of(VorgangAttachedItem.FIELD_ITEM_NAME, itemName, "item", Map.of("done", done)))
-					.build();
-		}
-
-	}
-
-}
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieServiceTest.java
index ffe2a8e7ef026a28d33615d123a73ce559cc6791..725768dcbcf608b24d78caccb7397a6eb5d4788b 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieServiceTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/historie/HistorieServiceTest.java
@@ -29,25 +29,18 @@ import static org.mockito.Mockito.*;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.UUID;
 import java.util.stream.Stream;
 
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
 import de.ozgcloud.alfa.common.command.Command;
-import de.ozgcloud.alfa.common.command.CommandOrder;
 import de.ozgcloud.alfa.common.command.CommandService;
 import de.ozgcloud.alfa.common.command.CommandTestFactory;
-import de.ozgcloud.alfa.loeschanforderung.DeleteLoeschAnforderung;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
 
 class HistorieServiceTest {
@@ -57,102 +50,85 @@ class HistorieServiceTest {
 	private HistorieService service;
 	@Mock
 	private CommandService commandService;
-	@Mock
-	private HistorieCommandHandler historieCommandHandler;
 	@Spy
 	private List<HistorieProcessor> processors = new ArrayList<>();
 	@Mock
-	private HistorieProcessor processor;
+	private HistorieProcessor firstProcessor;
+	@Mock
+	private HistorieProcessor secondProcessor;
 
-	@DisplayName("Find finished commands")
 	@Nested
 	class TestFindFinishedCommands {
 
+		private final Stream<Command> commands = Stream.of(CommandTestFactory.create());
+
 		@BeforeEach
-		void mockProcessor() {
-			processors.add(processor);
+		void setUpMock() {
+			when(commandService.findFinishedCommands(any())).thenReturn(commands);
 		}
 
-		@DisplayName("process flow")
-		@Nested
-		class TestProcessFlow {
+		@Test
+		void shouldCallCommandServiceForFinishedCommands() {
+			findFinishedCommands();
 
-			private Command responseCommand = CommandTestFactory.create();
+			verify(commandService).findFinishedCommands(VorgangHeaderTestFactory.ID);
+		}
 
-			@Captor
-			private ArgumentCaptor<Stream<Command>> commandCaptor;
+		@Test
+		void shouldCallProcessCommands() {
+			findFinishedCommands();
 
-			@BeforeEach
-			void initMock() {
-				when(commandService.findFinishedCommands(any())).thenReturn(List.of(responseCommand).stream());
-				when(historieCommandHandler.translateOrder(any())).thenAnswer(i -> i.getArgument(0));
+			verify(service).processCommands(commands);
+		}
+
+		@Test
+		void shouldReturnProcessedCommands() {
+			var processedCommands = Stream.of(CommandTestFactory.create());
+			doReturn(processedCommands).when(service).processCommands(commands);
 
-			}
+			var finishedCommands = findFinishedCommands();
 
-			@Test
-			void shouldCallService() {
-				service.findFinishedCommands(CommandTestFactory.VORGANG_ID).toList();
+			assertThat(finishedCommands).isSameAs(processedCommands);
+		}
 
-				verify(commandService).findFinishedCommands(VorgangHeaderTestFactory.ID);
-			}
+		private Stream<Command> findFinishedCommands() {
+			return service.findFinishedCommands(VorgangHeaderTestFactory.ID);
+		}
+	}
 
-			@Test
-			void shouldTranslateCommandOrderByCommandHandler() {
-				service.findFinishedCommands(CommandTestFactory.VORGANG_ID).toList();
+	@Nested
+	class TestProcessCommands {
 
-				verify(historieCommandHandler).translateOrder(responseCommand);
-			}
+		private final Stream<Command> inputCommands = Stream.of(CommandTestFactory.create());
+		private final Stream<Command> processedOnceCommands = Stream.of(CommandTestFactory.create());
+		private final Stream<Command> processedTwiceCommands = Stream.of(CommandTestFactory.create());
 
-			@Test
-			void shouldProcessCommands() {
-				service.findFinishedCommands(CommandTestFactory.VORGANG_ID).toList();
+		@BeforeEach
+		void setProcessorMocks() {
+			processors.addAll(List.of(firstProcessor, secondProcessor));
+			when(firstProcessor.process(any())).thenReturn(processedOnceCommands);
+			when(secondProcessor.process(any())).thenReturn(processedTwiceCommands);
+		}
 
-				verify(processor).process(commandCaptor.capture());
-				assertThat(commandCaptor.getValue()).containsExactly(responseCommand);
-			}
+		@Test
+		void shouldProcessCommands() {
+			service.processCommands(inputCommands);
 
-			@Test
-			void shouldReturnProcessedCommands() {
-				var processedCommands = Stream.of(CommandTestFactory.create());
-				when(processor.process(any())).thenReturn(processedCommands);
+			verify(firstProcessor).process(inputCommands);
+		}
 
-				var commands = service.findFinishedCommands(CommandTestFactory.VORGANG_ID).toList();
+		@Test
+		void shouldDoSubsequentProcessing() {
+			service.processCommands(inputCommands);
 
-				assertThat(commands).isEqualTo(processedCommands);
-			}
+			verify(secondProcessor).process(processedOnceCommands);
 		}
 
-		@DisplayName("Filter deleteLoeschAnforderung body commands")
-		@Nested
-		class TestFilterDeleteLoeschAnforderungBodyCommands {
-
-			private final String deleteAttachedItemCommandId = UUID.randomUUID().toString();
-			private final String changeStatusCommandId = UUID.randomUUID().toString();
-			private final Map<String, Object> bodyMap = Map.of(DeleteLoeschAnforderung.DELETE_ATTACHED_ITEM_COMMAND_ID_FIELD,
-					deleteAttachedItemCommandId,
-					DeleteLoeschAnforderung.CHANGE_STATUS_COMMAND_ID_FIELD, changeStatusCommandId);
-			private final Command deleteLoeschAnforderungCommand = CommandTestFactory.createBuilder()
-					.order(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN.name())
-					.body(bodyMap).build();
-			private final Command deleteAttachedItemCommand = CommandTestFactory.createBuilder().id(deleteAttachedItemCommandId).build();
-			private final Command changeStatusCommandICommand = CommandTestFactory.createBuilder().id(changeStatusCommandId).build();
-
-			private final List<Command> finishedCommands = List.of(deleteLoeschAnforderungCommand, deleteAttachedItemCommand,
-					changeStatusCommandICommand);
-
-			@BeforeEach
-			void mock() {
-				when(commandService.findFinishedCommands(any())).thenReturn(finishedCommands.stream());
-				when(historieCommandHandler.translateOrder(any())).thenAnswer(i -> i.getArgument(0));
-				when(processor.process(any())).thenAnswer(i -> i.getArgument(0));
-			}
-
-			@Test
-			void shouldFilterCommandsRelatedInBody() {
-				var commands = service.findFinishedCommands(CommandTestFactory.VORGANG_ID).toList();
-
-				assertThat(commands).hasSize(1).containsExactly(deleteLoeschAnforderungCommand);
-			}
+		@Test
+		void shouldReturnCommandsAfterProcessing() {
+			var resultCommands = service.processCommands(inputCommands);
+
+			assertThat(resultCommands).isEqualTo(processedTwiceCommands);
 		}
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageHistorieProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageHistorieProcessorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..78662dc0cd55e2936abb48ea4bc597b4af52167d
--- /dev/null
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageHistorieProcessorTest.java
@@ -0,0 +1,261 @@
+package de.ozgcloud.alfa.wiedervorlage;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.mockito.stubbing.Answer;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.alfa.common.command.Command;
+import de.ozgcloud.alfa.common.command.CommandBodyMapper;
+import de.ozgcloud.alfa.common.command.CommandOrder;
+import de.ozgcloud.alfa.common.command.CommandTestFactory;
+import de.ozgcloud.alfa.common.command.LegacyOrder;
+import io.jsonwebtoken.lang.Collections;
+
+class WiedervorlageHistorieProcessorTest {
+
+	@Spy
+	private WiedervorlageHistorieProcessor processor;
+
+	@Nested
+	class TestProcess {
+
+		private final Command command = CommandTestFactory.create();
+		private final Command translatedCommand = CommandTestFactory.create();
+		private final Answer<Command> doNotTranslate = invocation -> invocation.getArgument(0);
+
+		@BeforeEach
+		void mockDefault() {
+			doAnswer(doNotTranslate).when(processor).translateCreateAttachedItem(any());
+			doAnswer(doNotTranslate).when(processor).translateUpdateAttachedItem(any());
+			doAnswer(doNotTranslate).when(processor).translatePatchAttachedItem(any());
+		}
+
+		@Test
+		void shouldPropagateAllOrders() {
+
+			var commands = processor.process(Stream.of(command));
+
+			assertThat(commands).containsExactly(command);
+		}
+
+		@Test
+		void shouldTranslateCreateAttachedItem() {
+			processor.process(Stream.of(command)).toList();
+
+			verify(processor).translateCreateAttachedItem(command);
+		}
+
+		@Test
+		void shouldReturnTranslatedCreateAttachedItem() {
+			doReturn(translatedCommand).when(processor).translateCreateAttachedItem(any());
+
+			var commands = processor.process(Stream.of(command)).toList();
+
+			assertThat(commands).containsExactly(translatedCommand);
+			reset(processor);
+		}
+
+		@Test
+		void shouldTranslateUpdateAttachedItem() {
+			processor.process(Stream.of(command)).toList();
+
+			verify(processor).translateUpdateAttachedItem(command);
+		}
+
+		@Test
+		void shouldReturnTranslatedUpdateAttachedItem() {
+			doReturn(translatedCommand).when(processor).translateUpdateAttachedItem(any());
+
+			var commands = processor.process(Stream.of(command)).toList();
+
+			assertThat(commands).containsExactly(translatedCommand);
+			reset(processor);
+		}
+
+		@Test
+		void shouldTranslatePatchAttachedItem() {
+			processor.process(Stream.of(command)).toList();
+
+			verify(processor).translatePatchAttachedItem(command);
+		}
+
+		@Test
+		void shouldReturnTranslatedPatchAttachedItem() {
+			doReturn(translatedCommand).when(processor).translatePatchAttachedItem(any());
+
+			var commands = processor.process(Stream.of(command)).toList();
+
+			assertThat(commands).containsExactly(translatedCommand);
+			reset(processor);
+		}
+	}
+
+	@Nested
+	class TestTranslateCreateAttachedItem {
+
+		private final Map<String, ?> commandBody = Map.of(CommandBodyMapper.ITEM_NAME_PROPERTY, Wiedervorlage.class.getSimpleName());
+		private final Command createWiedervorlageCommand = CommandTestFactory.createBuilder()
+				.order(CommandOrder.CREATE_ATTACHED_ITEM.name())
+				.body(commandBody)
+				.build();
+
+		@Test
+		void shouldTranslateOrderToCreateWiedervorlage() {
+			var expectedCommand = createWiedervorlageCommand.toBuilder().order(LegacyOrder.CREATE_WIEDERVORLAGE).build();
+
+			var translatedCommand = processor.translateCreateAttachedItem(createWiedervorlageCommand);
+
+			assertThat(translatedCommand).usingRecursiveComparison().isEqualTo(expectedCommand);
+		}
+
+		@Test
+		void shouldNotTranslateOtherOrderCommands() {
+			var command = createWiedervorlageCommand.toBuilder().order(LoremIpsum.getInstance().getWords(1)).build();
+
+			var translatedCommand = processor.translateCreateAttachedItem(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+
+		@Test
+		void shouldNotTranslateOtherAttachedItems() {
+			var otherCommandBody = Map.of(CommandBodyMapper.ITEM_NAME_PROPERTY, LoremIpsum.getInstance().getWords(1));
+			var command = createWiedervorlageCommand.toBuilder().body(otherCommandBody).build();
+
+			var translatedCommand = processor.translateCreateAttachedItem(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+	}
+
+	@Nested
+	class TestTranslateUpdateAttachedItem {
+
+		private final Map<String, ?> commandBody = Map.of(CommandBodyMapper.ITEM_NAME_PROPERTY, Wiedervorlage.class.getSimpleName());
+		private final Command editWiedervorlageCommand = CommandTestFactory.createBuilder()
+				.order(CommandOrder.UPDATE_ATTACHED_ITEM.name())
+				.body(commandBody)
+				.build();
+
+		@Test
+		void shouldTranslateOrderToEditWiedervorlage() {
+			var expectedCommand = editWiedervorlageCommand.toBuilder().order(LegacyOrder.EDIT_WIEDERVORLAGE).build();
+
+			var translatedCommand = processor.translateUpdateAttachedItem(editWiedervorlageCommand);
+
+			assertThat(translatedCommand).usingRecursiveComparison().isEqualTo(expectedCommand);
+		}
+
+		@Test
+		void shouldNotTranslateOtherOrderCommands() {
+			var command = editWiedervorlageCommand.toBuilder().order(LoremIpsum.getInstance().getWords(1)).build();
+
+			var translatedCommand = processor.translateUpdateAttachedItem(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+
+		@Test
+		void shouldNotTranslateOtherAttachedItems() {
+			var otherCommandBody = Map.of(CommandBodyMapper.ITEM_NAME_PROPERTY, LoremIpsum.getInstance().getWords(1));
+			var command = editWiedervorlageCommand.toBuilder().body(otherCommandBody).build();
+
+			var translatedCommand = processor.translateUpdateAttachedItem(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+	}
+
+	@Nested
+	class TestTranslatePatchAttachedItem {
+
+		private final Map<String, ?> commandBody = Map.of(CommandBodyMapper.ITEM_NAME_PROPERTY, Wiedervorlage.class.getSimpleName());
+		private final Command patchWiedervorlageCommand = CommandTestFactory.createBuilder()
+				.order(CommandOrder.PATCH_ATTACHED_ITEM.name())
+				.body(commandBody)
+				.build();
+
+		@Test
+		void shouldCallTranslatePatchWiedervorlage() {
+			processor.translatePatchAttachedItem(patchWiedervorlageCommand);
+
+			verify(processor).translatePatchWiedervorlage(patchWiedervorlageCommand);
+		}
+
+		@Test
+		void shouldReturnTranslatedCommand() {
+			var translatedCommand = CommandTestFactory.create();
+			doReturn(translatedCommand).when(processor).translatePatchWiedervorlage(any());
+
+			var resultCommand = processor.translatePatchAttachedItem(patchWiedervorlageCommand);
+
+			assertThat(resultCommand).isSameAs(translatedCommand);
+		}
+
+		@Test
+		void shouldNotTranslateOtherOrderCommands() {
+			var command = patchWiedervorlageCommand.toBuilder().order(LoremIpsum.getInstance().getWords(1)).build();
+
+			var translatedCommand = processor.translatePatchAttachedItem(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+
+		@Test
+		void shouldNotTranslateOtherAttachedItems() {
+			var otherCommandBody = Map.of(CommandBodyMapper.ITEM_NAME_PROPERTY, LoremIpsum.getInstance().getWords(1));
+			var command = patchWiedervorlageCommand.toBuilder().body(otherCommandBody).build();
+
+			var translatedCommand = processor.translatePatchAttachedItem(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+	}
+
+	@Nested
+	class TestTranslatePatchWiedervorlage {
+
+		@Test
+		void shouldReturnWiedervorlageErledigenCommand() {
+			var commandBody = Map.of(CommandBodyMapper.ITEM_PROPERTY, Map.of(Wiedervorlage.DONE_FIELD, true));
+			var command = CommandTestFactory.createBuilder().body(commandBody).build();
+			var expectedCommand = command.toBuilder().order(LegacyOrder.WIEDERVORLAGE_ERLEDIGEN);
+
+			var translatedCommand = processor.translatePatchWiedervorlage(command);
+
+			assertThat(translatedCommand).usingRecursiveComparison().isEqualTo(expectedCommand);
+		}
+
+		@Test
+		void shouldReturnWiedervorlageWiedereroeffnenCommand() {
+			var commandBody = Map.of(CommandBodyMapper.ITEM_PROPERTY, Map.of(Wiedervorlage.DONE_FIELD, false));
+			var command = CommandTestFactory.createBuilder().body(commandBody).build();
+			var expectedCommand = command.toBuilder().order(LegacyOrder.WIEDERVORLAGE_WIEDEREROEFFNEN);
+
+			var translatedCommand = processor.translatePatchWiedervorlage(command);
+
+			assertThat(translatedCommand).usingRecursiveComparison().isEqualTo(expectedCommand);
+		}
+
+		@Test
+		void shouldNotTranslateOnMissingBoolean() {
+			var commandBody = Map.of(CommandBodyMapper.ITEM_PROPERTY, Collections.emptyMap());
+			var command = CommandTestFactory.createBuilder().body(commandBody).build();
+
+			var translatedCommand = processor.translatePatchWiedervorlage(command);
+
+			assertThat(translatedCommand).isSameAs(command);
+		}
+	}
+}