diff --git a/Jenkinsfile b/Jenkinsfile
index b494923b65ddf758299ed0c7412cd278ab4840ab..caeb98bd4c0bd9b352aa6cbcf77d0bee2b00af34 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,8 +1,3 @@
-def FAILED_STAGE
-def IMAGE_TAG
-def VERSION
-def E2E_FAILED
-
 pipeline {
     agent {
         node {
@@ -14,6 +9,10 @@ pipeline {
         BLUE_OCEAN_URL = "https://jenkins.ozg-sh.de/blue/organizations/jenkins/goofy/detail/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/pipeline"
         RELEASE_REGEX = /\d+.\d+.\d+/
         SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/
+        FAILED_STAGE = ""
+        IMAGE_TAG = ""
+        VERSION = ""
+        E2E_FAILED = ""
     }
 
     options {
@@ -295,8 +294,8 @@ pipeline {
     post {
         failure {
             script {
-                if (env.BRANCH_NAME == 'master') {
-                    slackSend(color: "danger", message: "Goofy: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <${BLUE_OCEAN_URL}|${env.BUILD_NUMBER}>")
+                if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'release') {
+                    sendFailureMessage()
                 }
             }
         }
@@ -555,4 +554,27 @@ Void waitForKeycloakClientCreation(realm) {
     while(sh(script: shScript, returnStatus: true)) {
         sh 'sleep 5'
     }
+}
+
+Void sendFailureMessage() {
+    def room = ''
+    def data = """{"msgtype":"m.text", \
+                    "body":"Goofy: Build Failed. Stage: ${FAILED_STAGE} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}", \
+                    "format": "org.matrix.custom.html", \
+                    "formatted_body":"Goofy: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>"}"""
+       
+    if (env.BRANCH_NAME == 'master') {
+        room = "!iQPAvQIiRwRpNOszjw:matrix.ozg-sh.de"
+    }
+    else if (env.BRANCH_NAME == 'release') {
+        room = "!oWZpUGTFsxkJIYNfYg:matrix.ozg-sh.de"
+    }
+
+    sh "curl -XPOST -H 'authorization: Bearer ${getElementAccessToken()}' -d '${data}' https://matrix.ozg-sh.de/_matrix/client/v3/rooms/$room/send/m.room.message"
+}
+
+String getElementAccessToken() {
+    withCredentials([string(credentialsId: 'element-login-json', variable: 'LOGIN_JSON')]) {
+        return readJSON ( text: sh (script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token
+    }
 }
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/navigation/navigation.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/navigation/navigation.e2e-spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c0fcd0535bd473b973157f8a0d997b311fcc572c
--- /dev/null
+++ b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/navigation/navigation.e2e-spec.ts
@@ -0,0 +1,38 @@
+import { NavigationE2EComponent } from 'apps/goofy-e2e/src/components/navigation/navigation.e2e.component';
+import { VorgangListE2EComponent } from 'apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component';
+import { MainPage, waitForSpinnerToDisappear } from 'apps/goofy-e2e/src/page-objects/main.po';
+import { dropCollections } from 'apps/goofy-e2e/src/support/cypress-helper';
+import { exist, notExist } from 'apps/goofy-e2e/src/support/cypress.util';
+import { loginAsEmil } from 'apps/goofy-e2e/src/support/user-util';
+
+describe('Navigation', () => {
+	const mainPage: MainPage = new MainPage();
+	const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
+
+	const navigation: NavigationE2EComponent = mainPage.getNavigation();
+
+	before(() => {
+		loginAsEmil();
+
+		waitForSpinnerToDisappear();
+		exist(vorgangList.getRoot());
+	})
+
+	after(() => {
+		dropCollections();
+	})
+
+	describe('navigation item myVorgaenge', () => {
+
+		it('should not exists', () => {
+			notExist(navigation.getMyVorgaengeItem());
+		})
+	})
+
+	describe('navigation item allVorgaenge', () => {
+
+		it('should exists', () => {
+			exist(navigation.getAllVorgaengeItem());
+		})
+	})
+})
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts
index 8f5b997336681229f082ca75e91d259aac2ff6f5..ea0f9b68a56773b16844691ab359166c59cd0ab3 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts
@@ -36,6 +36,20 @@ describe('Navigation', () => {
 		dropCollections();
 	})
 
+	describe('navigation item myVorgaenge', () => {
+
+		it('should exists', () => {
+			exist(navigation.getMyVorgaengeItem());
+		})
+	})
+
+	describe('navigation item allVorgaenge', () => {
+
+		it('should exists', () => {
+			exist(navigation.getAllVorgaengeItem());
+		})
+	})
+
 	describe('click on my vorgaenge', () => {
 
 		it('should hide not to user assigned vorgaenge', () => {
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts
index 04c011a405433385a98d2539c52698ddf192bcd7..0db5f5c30dcf4202691e4baf5576b27a26020e78 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts
@@ -98,7 +98,7 @@ describe('Vorgang-detailansicht filtered by organisationseinheit', () => {
 		})
 	})
 
-	describe('on user zonk', () => {
+	describe.skip('on user zonk', () => {
 		const authorizedUrl: string = vorgangUrlVisibleToKOrdner;
 		const forbiddenUrl: string = vorgangUrlVisibleToKFinder;
 
diff --git a/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts b/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts
index e348fc3066c57679a84f5def9ef4bfc30db95e96..da289d23b08b39fc784ab6f47c0b1f9752a2b35e 100644
--- a/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts
+++ b/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts
@@ -8,7 +8,8 @@ import { Observable } from "rxjs";
 export class KommentarFormService extends AbstractFormService {
 
 	static readonly TEXT = 'text';
-	static readonly FIELD_PATH_PREFIX = 'command.body';
+
+	static readonly FIELD_PATH_PREFIX = 'kommentar';
 
 	constructor(formBuilder: FormBuilder, private kommentarService: KommentarService) {
 		super(formBuilder);
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
index 57ab3de2f31a77602503da3fcf7d9b7412890279..5ab808bee6238f93a364ee6ed49803d0cc9b1de3 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
@@ -12,7 +12,7 @@ export class WiedervorlageFormService extends AbstractFormService {
 	static readonly FIELD_FRIST = 'frist';
 	static readonly FIELD_ATTACHMENTS = 'attachments';
 
-	static readonly FIELD_PATH_PREFIX = 'command.body';
+	static readonly FIELD_PATH_PREFIX = 'wiedervorlage';
 
 	constructor(
 		formBuilder: FormBuilder,
diff --git a/goofy-client/pom.xml b/goofy-client/pom.xml
index d15e3eeb0414f326b8c9706fae66c062a8599b56..faad162ec16c487a9fbecefeff21c89a4683b9fa 100644
--- a/goofy-client/pom.xml
+++ b/goofy-client/pom.xml
@@ -5,7 +5,7 @@
 	<parent>
 		<groupId>de.itvsh.ozg</groupId>
 		<artifactId>goofy</artifactId>
-		<version>0.26.0-SNAPSHOT</version>
+		<version>0.27.0-SNAPSHOT</version>
 	</parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/goofy-server/pom.xml b/goofy-server/pom.xml
index df7eac60260003e0a8035c7a0d4d09cf33e850cd..00c500a456dd955aad006695ea5f4d62b6e2f2b5 100644
--- a/goofy-server/pom.xml
+++ b/goofy-server/pom.xml
@@ -7,7 +7,7 @@
 	<parent>
 		<groupId>de.itvsh.ozg</groupId>
 		<artifactId>goofy</artifactId>
-		<version>0.26.0-SNAPSHOT</version>
+		<version>0.27.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>goofy-server</artifactId>
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java
index f394e86ca7234a76fca635adbb013a6558f16aed..97b2c40373c78b5024cc55eb7c6b5d917240e935 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java
@@ -45,16 +45,20 @@ public class RootController {
 						linkTo(VorgangController.class).withRel(REL_VORGAENGE),
 						linkTo(methodOn(UserProfileController.class).findUsers(null)).withRel(REL_SEARCH_USER),
 						linkTo(DownloadTokenController.class).withRel(REL_DOWNLOAD_TOKEN),
-						buildVorgangListByPageLink(REL_SEARCH, Optional.empty()),
+						buildVorgangListByPageLink(REL_SEARCH, Optional.empty()))
+				.ifMatch(this::hasVerwaltungRole).addLinks(
 						buildVorgangListByPageLink(REL_MY_VORGAENGE, Optional.of(currentUserService.getUserId())),
 						buildVorgangListByPageLink(REL_SEARCH_MY_VORGAENGE, Optional.of(currentUserService.getUserId())))
 				.buildModel();
 	}
 
-	private boolean hasRole() {
+	boolean hasRole() {
+		return hasVerwaltungRole() || currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER);
+	}
+
+	boolean hasVerwaltungRole() {
 		return currentUserService.hasRole(UserRole.VERWALTUNG_USER)
-				|| currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)
-				|| currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER);
+				|| currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE);
 	}
 
 	private Link buildVorgangListByPageLink(String linkRel, Optional<UserId> assignedTo) {
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItem.java b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..68f99ec311c1e56478cd9bed891c5f4dd2b55955
--- /dev/null
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItem.java
@@ -0,0 +1,21 @@
+package de.itvsh.goofy.common.attacheditem;
+
+import java.util.Map;
+
+import de.itvsh.goofy.common.command.CommandBody;
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class VorgangAttachedItem implements CommandBody {
+
+	private String id;
+	private long version;
+
+	private String client;
+	private String vorgangId;
+	private String itemName;
+
+	private Map<String, Object> item;
+}
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemService.java
new file mode 100644
index 0000000000000000000000000000000000000000..de236d619f152683cf74c467abb009421d8f143d
--- /dev/null
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemService.java
@@ -0,0 +1,76 @@
+package de.itvsh.goofy.common.attacheditem;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.itvsh.goofy.common.command.Command;
+import de.itvsh.goofy.common.command.CommandBody;
+import de.itvsh.goofy.common.command.CommandBodyMapper;
+import de.itvsh.goofy.common.command.CommandOrder;
+import de.itvsh.goofy.common.command.CommandService;
+import de.itvsh.goofy.common.command.CreateCommand;
+import de.itvsh.goofy.kommentar.Kommentar;
+import de.itvsh.goofy.wiedervorlage.Wiedervorlage;
+
+@Service
+public class VorgangAttachedItemService {
+
+	@Autowired
+	private CommandBodyMapper commandBodyMapper;
+	@Autowired
+	private CommandService commandService;
+
+	static final String WIEDERVORLAGE_ITEM_NAME = "Wiedervorlage";
+	static final String KOMMENTAR_ITEM_NAME = "Kommentar";
+
+	public Command createNewWiedervorlage(Wiedervorlage wiedervorlage, String vorgangId) {
+		var vorgangAttachedItem = buildVorgangAttachedItem(wiedervorlage, vorgangId, WIEDERVORLAGE_ITEM_NAME);
+
+		return commandService.createCommand(buildCreateCommand(vorgangId, vorgangAttachedItem));
+	}
+
+	public Command createNewKommentar(Kommentar kommentar, String vorgangId) {
+		var vorgangAttachedItem = buildVorgangAttachedItem(kommentar, vorgangId, KOMMENTAR_ITEM_NAME);
+
+		return commandService.createCommand(buildCreateCommand(vorgangId, vorgangAttachedItem));
+	}
+
+	CreateCommand buildCreateCommand(String vorgangId, CommandBody body) {
+		return CreateCommand.builder()
+				.vorgangId(vorgangId)
+				.relationId(vorgangId)
+				.order(CommandOrder.CREATE_ATTACHED_ITEM)
+				.body(body)
+				.build();
+	}
+
+	public Command editKommentar(Kommentar kommentar, String kommentarId, long kommentarVersion) {
+		var vorgangAttachedItem = buildVorgangAttachedItem(kommentar, kommentar.getVorgangId(), KOMMENTAR_ITEM_NAME);
+
+		return commandService.createCommand(buildUpdateCommand(kommentar.getVorgangId(), kommentarId, vorgangAttachedItem), kommentarVersion);
+	}
+
+	public Command editWiedervorlage(Wiedervorlage wiedervorlage, String wiedervorlageId, long wiedervorlageVersion) {
+		var vorgangAttachedItem = buildVorgangAttachedItem(wiedervorlage, wiedervorlage.getVorgangId(), WIEDERVORLAGE_ITEM_NAME);
+
+		return commandService.createCommand(buildUpdateCommand(wiedervorlage.getVorgangId(), wiedervorlageId, vorgangAttachedItem),
+				wiedervorlageVersion);
+	}
+
+	VorgangAttachedItem buildVorgangAttachedItem(CommandBody body, String vorgangId, String itemName) {
+		return VorgangAttachedItem.builder()
+				.vorgangId(vorgangId)
+				.itemName(itemName)
+				.item(commandBodyMapper.fromObjectToMap(body))
+				.build();
+	}
+
+	CreateCommand buildUpdateCommand(String vorgangId, String kommentarId, CommandBody body) {
+		return CreateCommand.builder()
+				.vorgangId(vorgangId)
+				.relationId(kommentarId)
+				.order(CommandOrder.UPDATE_ATTACHED_ITEM)
+				.body(body)
+				.build();
+	}
+}
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java
index 703a17d43d415bfcd5d39da8b002796399825f44..094c88df95e860744c2764df2e87820823ca155d 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java
@@ -1,10 +1,12 @@
 package de.itvsh.goofy.common.command;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -18,27 +20,13 @@ import de.itvsh.ozg.pluto.grpc.command.GrpcCommandBodyField;
 @Mapper
 public interface CommandBodyMapper {
 
-	final Predicate<Entry<Object, Object>> HAS_NOT_NULL_VALUE = entry -> Objects.nonNull(entry.getValue());
 	final Predicate<Entry<Object, Object>> IS_NOT_CLASS_VALUE = entry -> !StringUtils.equals("class", entry.getKey().toString());
+	final Predicate<Entry<Object, Object>> IS_NOT_VERSION_VALUE = entry -> !StringUtils.equals("version", entry.getKey().toString());
 
 	static final String VORGANG_ID_PROPERTY = "vorgangId";
 	static final String ITEM_NAME_PROPERTY = "itemName";
 	static final String ITEM_PROPERTY = "item";
 
-	default Map<String, Object> fromObjectToMap(Object object) {
-		return new BeanMap(object).entrySet().stream()
-				.filter(HAS_NOT_NULL_VALUE)
-				.filter(IS_NOT_CLASS_VALUE)
-				.collect(Collectors.toMap(entry -> entry.getKey().toString(), this::checkEnumValue));
-	}
-
-	private Object checkEnumValue(Entry<Object, Object> entry) {
-		if (entry.getValue() instanceof Enum<?> enumValue) {
-			return enumValue.name();
-		}
-		return entry.getValue();
-	}
-
 	default GrpcCommandBody mapToBody(Map<String, String> bodyMap) {
 		if (Objects.isNull(bodyMap)) {
 			return GrpcCommandBody.getDefaultInstance();
@@ -68,12 +56,24 @@ public interface CommandBodyMapper {
 		}
 
 		return bodyMap.entrySet().stream()
-				.filter(HAS_NOT_NULL_VALUE)
 				.filter(IS_NOT_CLASS_VALUE)
-				.map(entry -> GrpcCommandBodyField.newBuilder().setName(entry.getKey().toString()).setValue(entry.getValue().toString()).build())
+				.map(this::buildBodyField)
 				.collect(Collectors.toList());
 	}
 
+	default GrpcCommandBodyField buildBodyField(Entry<Object, Object> entry) {
+		var bodyFieldMapper = GrpcCommandBodyField.newBuilder().setName(entry.getKey().toString());
+
+		if (Objects.nonNull(entry.getValue())) {
+			bodyFieldMapper.setValue(getNullableStringValue(entry.getValue()));
+		}
+		return bodyFieldMapper.build();
+	}
+
+	default String getNullableStringValue(Object entryValue) {
+		return Optional.ofNullable(entryValue).map(Object::toString).orElse(null);
+	}
+
 	default Map<String, String> map(GrpcCommandBody body) {
 		return body.getFieldList().stream().collect(Collectors.toMap(GrpcCommandBodyField::getName, GrpcCommandBodyField::getValue));
 	}
@@ -82,6 +82,20 @@ public interface CommandBodyMapper {
 		return Map.of(
 				VORGANG_ID_PROPERTY, command.getVorgangId(),
 				ITEM_NAME_PROPERTY, itemName,
-				ITEM_PROPERTY, new BeanMap(command.getBody()));
+				ITEM_PROPERTY, fromObjectToMap(command.getBody()));
+	}
+
+	default Map<String, Object> fromObjectToMap(Object object) {
+		return new BeanMap(object).entrySet().stream()
+				.filter(IS_NOT_CLASS_VALUE)
+				.filter(IS_NOT_VERSION_VALUE)
+				.collect(HashMap::new, (map, entry) -> map.put(entry.getKey().toString(), checkEnumValue(entry.getValue())), Map::putAll);
+	}
+
+	private Object checkEnumValue(Object entryValue) {
+		if (entryValue instanceof Enum<?> enumValue) {
+			return enumValue.name();
+		}
+		return entryValue;
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java
index d6c45c11a6021bddc0cb4cbb7ac6b89189c6200f..ad32f9c4794525c36f50f6d5ab79d82d3de45e99 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java
@@ -78,13 +78,16 @@ public class CommandController {
 		@PostMapping
 		public ResponseEntity<Void> createCommand(@PathVariable String vorgangId, @PathVariable String relationId,
 				@PathVariable long relationVersion, @RequestBody CreateCommand command) {
-			command = command.toBuilder().vorgangId(vorgangId).relationId(relationId).build();
+			command = command.toBuilder()
+					.vorgangId(vorgangId)
+					.relationId(relationId)
+					.build();
 
 			if (isSendPostfachMailOrder(command)) {
 				command = prepareCommandForPostfachNachricht(command, vorgangId);
 			}
 
-			var created = createCommand(command, relationVersion);
+			var created = service.createCommand(command, relationVersion);
 
 			return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build();
 		}
@@ -115,16 +118,12 @@ public class CommandController {
 			return vorgangController.getVorgang(vorgangId);
 		}
 
-		public Command createCommand(CreateCommand command, long version) {
-			return service.createCommand(command, version);
-		}
-
-		public Command createCommand(CreateCommand command, String itemName) {
-			return service.createCommand(command, itemName);
+		public Command createCommandWithoutRelation(CreateCommand command) {
+			return service.createCommandWithoutRelation(command);
 		}
 
-		public Command createCommandWithoutValidation(CreateCommand command, String itemName) {
-			return service.createCommandWithoutValidation(command, itemName);
+		public Command createCommandWithoutValidation(CreateCommand command, String itemName, long relationVersion) {
+			return service.createCommandWithoutValidation(command, itemName, relationVersion);
 		}
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java
index bc35a6d14771b3822737b95cf2efa5d5b2677cf1..2e23b23ba4ac35cea37447aa882ce3d52b3f7f1c 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java
@@ -32,8 +32,8 @@ public class CommandRemoteService {
 	@Autowired
 	private GrpcObjectMapper objectMapper;
 
-	public Command createCommand(CreateCommand command, long version) {
-		return doCreateCommand(buildCreateCommandRequest(command, version));
+	public Command createCommand(CreateCommand command) {
+		return doCreateCommand(buildCreateCommandRequest(command));
 	}
 
 	public Command createCommand(CreateCommand command, String itemName) {
@@ -46,30 +46,30 @@ public class CommandRemoteService {
 		return mapper.toCommand(response.getCommand());
 	}
 
-	GrpcCreateCommandRequest buildCreateCommandRequest(CreateCommand command, long version) {
+	GrpcCreateCommandRequest buildCreateCommandRequest(CreateCommand command) {
+		return buildCreateRequestBuilder(command)
+				.setBodyObj(objectMapper.fromMap(bodyMapper.fromObjectToMap(command.getBody())))
+				.build();
+	}
+
+	GrpcCreateCommandRequest buildCreateAttachedItemCommandRequest(CreateCommand command, String itemName) {
+		return buildCreateRequestBuilder(command)
+				.setBodyObj(objectMapper.fromMap(bodyMapper.mapToBodyMap(command, itemName)))
+				.build();
+	}
+
+	GrpcCreateCommandRequest.Builder buildCreateRequestBuilder(CreateCommand command) {
 		var requestBuilder = GrpcCreateCommandRequest.newBuilder()
 				.setCallContext(contextService.createCallContext())
 				.setVorgangId(command.getVorgangId())
 				.setRelationId(command.getRelationId())
-				.setRelationVersion(version)
-				.addAllBody(bodyMapper.mapToBodyFields(command.getBody()))
-				.setBodyObj(objectMapper.fromMap(bodyMapper.fromObjectToMap(command.getBody())))
-				.setOrderString(command.getOrder().name());
+				.setRelationVersion(command.getRelationVersion())
+				.setOrderString(command.getOrder().name())
+				.addAllBody(bodyMapper.mapToBodyFields(command.getBody()));
 
 		Optional.ofNullable(command.getRedirectRequest()).map(mapper::toGrpcRedirectRequest).ifPresent(requestBuilder::setRedirectRequest);
 
-		return requestBuilder.build();
-	}
-
-	GrpcCreateCommandRequest buildCreateAttachedItemCommandRequest(CreateCommand command, String itemName) {
-		return GrpcCreateCommandRequest.newBuilder()
-				.setCallContext(contextService.createCallContext())
-				.setRelationId(command.getVorgangId())
-				.setRelationVersion(-1)
-				.setVorgangId(command.getVorgangId())
-				.setOrder(GrpcOrder.valueOf(command.getOrder().name()))
-				.setBodyObj(objectMapper.fromMap(bodyMapper.mapToBodyMap(command, itemName)))
-				.build();
+		return requestBuilder;
 	}
 
 	public Command revokeCommand(String commandId) {
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java
index 5d27b7f6d9e16955e61eefbe3ffbfce0272e7740..a70772101744018f0ec92d7669ae7b1334fe2ffd 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java
@@ -11,22 +11,36 @@ import org.springframework.validation.annotation.Validated;
 
 import lombok.NonNull;
 
-@Service
 @Validated
-class CommandService {
+@Service
+public class CommandService {
+
+	static final long NO_RELATION_VERSION = -1;
 
 	@Autowired
 	private CommandRemoteService remoteService;
 
-	public Command createCommand(@Valid CreateCommand command, long version) {
-		return remoteService.createCommand(command, version);
+	public Command createCommand(CreateCommand command) {
+		command = command.toBuilder().relationVersion(NO_RELATION_VERSION).build();
+
+		return remoteService.createCommand(command);
 	}
 
-	public Command createCommand(@Valid CreateCommand command, String itemName) {
-		return remoteService.createCommand(command, itemName);
+	public Command createCommand(@Valid CreateCommand command, long relationVersion) {
+		command = command.toBuilder().relationVersion(relationVersion).build();
+
+		return remoteService.createCommand(command);
 	}
 
-	public Command createCommandWithoutValidation(CreateCommand command, String itemName) {
+	public Command createCommandWithoutRelation(CreateCommand command) {
+		command = command.toBuilder().relationVersion(NO_RELATION_VERSION).build();
+
+		return remoteService.createCommand(command);
+	}
+
+	public Command createCommandWithoutValidation(CreateCommand command, String itemName, long relationVersion) {
+		command = command.toBuilder().relationVersion(relationVersion).build();
+
 		return remoteService.createCommand(command, itemName);
 	}
 
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java
index ce4bec48e195335fabb156ac73d405dfa437d6ec..c63125db8f2dc0cd58fb283d688e550ce8cf99ef 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java
@@ -28,6 +28,7 @@ public class CreateCommand {
 
 	private String vorgangId;
 	private String relationId;
+	private long relationVersion;
 	private CommandOrder order;
 
 	@Valid
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java
index 89eb1615fb6c468455689c949429c01e664907e6..9937eb74be669db72fbade1341a720cdeab908e7 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java
@@ -30,6 +30,8 @@ public class Kommentar implements CommandBody {
 
 	@JsonIgnore
 	private String id;
+	@JsonIgnore
+	private long version;
 
 	@JsonIgnore
 	private String vorgangId;
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java
index b9040667714e68b01695b0ee0290d02d29e6b3cf..394259041336c6de405cf1a332948404d25922ad 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java
@@ -2,8 +2,6 @@ package de.itvsh.goofy.kommentar;
 
 import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
 
-import java.time.ZonedDateTime;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -14,48 +12,28 @@ import org.springframework.web.bind.annotation.RestController;
 
 import de.itvsh.goofy.common.command.Command;
 import de.itvsh.goofy.common.command.CommandController;
-import de.itvsh.goofy.common.command.CommandController.CommandByRelationController;
-import de.itvsh.goofy.common.command.CommandOrder;
-import de.itvsh.goofy.common.command.CreateCommand;
-import de.itvsh.goofy.common.user.CurrentUserService;
 
 @RestController
 @RequestMapping(KommentarCommandController.KOMMENTAR_COMMANDS)
 public class KommentarCommandController {
 
-	static final String KOMMENTAR_COMMANDS = "/api/kommentars/{kommentarId}/commands";
-	static final String NOT_SET = "-1";
+	static final String KOMMENTAR_COMMANDS = "/api/kommentars/{kommentarId}/{kommentarVersion}/commands";
 
 	@Autowired
 	private KommentarService service;
 
-	@Autowired
-	private CommandByRelationController commandByRelationController;
-
 	@PostMapping
-	public ResponseEntity<Void> createCommand(@RequestBody KommentarCommand kommentarCommand, @PathVariable String kommentarId) {
-		var command = commandByRelationController.createCommand(buildCommand(service.getById(kommentarId), kommentarCommand),
-				KommentarRemoteService.ITEM_NAME);
-		return buildResponseLink(command);
+	public ResponseEntity<Void> editKommentar(@RequestBody KommentarCommand kommentarCommand, @PathVariable String kommentarId,
+			@PathVariable long kommentarVersion) {
+		var createdCommand = service.editKommentar(kommentarCommand.getKommentar(), kommentarId, kommentarVersion);
+
+		return buildResponseLink(createdCommand);
 	}
 
 	private ResponseEntity<Void> buildResponseLink(Command createdKommentarCommand) {
 		return ResponseEntity.created(linkTo(CommandController.class).slash(createdKommentarCommand.getId()).toUri()).build();
 	}
 
-	CreateCommand buildCommand(Kommentar kommentar, KommentarCommand command) {
-		var commandBuilder = CreateCommand.builder()
-				.order(CommandOrder.UPDATE_ATTACHED_ITEM)
-				.relationId(NOT_SET)
-				.vorgangId(kommentar.getVorgangId());
-
-		return commandBuilder.body(updateKommandByCommand(kommentar, command)).build();
-	}
-
-	private Kommentar updateKommandByCommand(Kommentar kommentar, KommentarCommand command) {
-		return kommentar.toBuilder().text(command.getKommentar().getText()).build();
-	}
-
 	@RestController
 	@RequestMapping(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG)
 	public static class KommentarCommandByVorgangController {
@@ -63,33 +41,13 @@ public class KommentarCommandController {
 		static final String KOMMENTAR_COMMANDS_BY_VORGANG = "/api/vorgangs/{vorgangId}/kommentarCommands";
 
 		@Autowired
-		private CommandByRelationController commandByRelationController;
-
-		@Autowired
-		private CurrentUserService userService;
+		private KommentarService service;
 
-		@PostMapping()
-		public ResponseEntity<Void> createCommand(@RequestBody KommentarCommand command, @PathVariable String vorgangId) {
-			var createdCommand = commandByRelationController.createCommand(buildCommand(vorgangId, command), KommentarRemoteService.ITEM_NAME);
+		@PostMapping
+		public ResponseEntity<Void> createKommentar(@RequestBody KommentarCommand command, @PathVariable String vorgangId) {
+			var createdCommand = service.createKommentar(command.getKommentar(), vorgangId);
 
 			return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build();
 		}
-
-		CreateCommand buildCommand(String vorgangId, KommentarCommand command) {
-			return CreateCommand.builder()
-					.vorgangId(vorgangId)
-					.order(CommandOrder.CREATE_ATTACHED_ITEM)
-					.relationId(NOT_SET)
-					.body(buildBody(command.getKommentar()))
-					.build();
-		}
-
-		Kommentar buildBody(Kommentar kommentar) {
-			return kommentar.toBuilder()
-					.createdAt(ZonedDateTime.now().withNano(0))
-					.createdBy(userService.getUserId().toString())
-					.build();
-		}
-
 	}
-}
+}
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java
index c36561d38afa4080e10c69b1782aa37e57095400..395c02868b9a1a1cf6c3f9656c6a19b50366af43 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java
@@ -9,25 +9,36 @@ import org.mapstruct.MappingConstants;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.ReportingPolicy;
 import org.mapstruct.ValueMapping;
+import org.springframework.beans.factory.annotation.Autowired;
 
+import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
+import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
-public interface KommentarMapper {
+abstract class KommentarMapper {
 
 	static final String ID = "id";
 	static final String TEXT = "text";
 	static final String CREATED_BY = "createdBy";
 	static final String CREATED_AT = "createdAt";
 
+	@Autowired
+	private GrpcObjectMapper grpcObjectMapper;
+
 	@Mapping(target = "kommentar", ignore = true)
 	@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
 	@ValueMapping(source = "UNDEFINED", target = MappingConstants.NULL)
-	KommentarCommand toKommentarCommand(GrpcCommand command);
+	abstract KommentarCommand toKommentarCommand(GrpcCommand command);
+
+	public Kommentar fromItem(GrpcVorgangAttachedItem vorgangAttachedItem) {
+		return fromItemMap(grpcObjectMapper.mapFromGrpc(vorgangAttachedItem.getItem()), vorgangAttachedItem.getVersion());
+	}
 
-	default Kommentar fromItemMap(Map<String, Object> map) {
+	Kommentar fromItemMap(Map<String, Object> map, long version) {
 		return Kommentar.builder()
 				.id((String) map.get(ID))
+				.version(version)
 				.createdAt(ZonedDateTime.parse((String) map.get(CREATED_AT)))
 				.createdBy((String) map.get(CREATED_BY))
 				.text((String) map.get(TEXT))
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java
index fda3d28ec5f38a9055c7ab517cf284cc5d52bfe3..f1fda7f7fe86d4ef4e4e257c96e08b69a7dc5759 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java
@@ -22,7 +22,7 @@ class KommentarModelAssembler implements RepresentationModelAssembler<Kommentar,
 	@Override
 	public EntityModel<Kommentar> toModel(Kommentar kommentar) {
 		var selfLink = linkTo(KommentarController.class).slash(kommentar.getId());
-		var commandLink = linkTo(methodOn(KommentarCommandController.class).createCommand(null, kommentar.getId()));
+		var commandLink = linkTo(methodOn(KommentarCommandController.class).editKommentar(null, kommentar.getId(), kommentar.getVersion()));
 
 		return ModelBuilder.fromEntity(kommentar).addLink(selfLink.withSelfRel())
 				.addLink(commandLink.withRel(REL_EDIT))
@@ -32,6 +32,7 @@ class KommentarModelAssembler implements RepresentationModelAssembler<Kommentar,
 	public CollectionModel<EntityModel<Kommentar>> toCollectionModel(Stream<Kommentar> entities, String vorgangId) {
 		return CollectionModel.of(entities.map(this::toModel).collect(Collectors.toList()),
 				linkTo(KommentarController.class).withSelfRel(),
-				linkTo(methodOn(KommentarCommandByVorgangController.class).createCommand(null, vorgangId)).withRel(REL_CREATE));
+				linkTo(methodOn(KommentarCommandByVorgangController.class).createKommentar(null, vorgangId))
+						.withRel(REL_CREATE));
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java
index 2e2d6c6cb0ce3dab68978db6e72f06bafcb51ef7..c6873ea395c1988420c1bef8057ae5f95b125276 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java
@@ -6,31 +6,25 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import de.itvsh.goofy.GoofyServerApplication;
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
 import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
 import de.itvsh.ozg.pluto.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceBlockingStub;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
 class KommentarRemoteService {
+
 	static final String ITEM_NAME = "Kommentar";
 
 	@GrpcClient(GoofyServerApplication.GRPC_CLIENT)
 	private VorgangAttachedItemServiceBlockingStub vorgangAttachedItemServiceStub;
 	@Autowired
 	private KommentarMapper mapper;
-	@Autowired
-	private GrpcObjectMapper grpcObjectMapper;
 
 	public Stream<Kommentar> findByVorgangId(String vorgangId) {
-		GrpcFindVorgangAttachedItemResponse response = vorgangAttachedItemServiceStub
-				.find(buildFindRequest(vorgangId));
+		var response = vorgangAttachedItemServiceStub.find(buildFindRequest(vorgangId));
 
-		return response.getVorgangAttachedItemsList().stream()
-				.map(item -> grpcObjectMapper.mapFromGrpc(item.getItem()))
-				.map(mapper::fromItemMap);
+		return response.getVorgangAttachedItemsList().stream().map(mapper::fromItem);
 	}
 
 	GrpcFindVorgangAttachedItemRequest buildFindRequest(String vorgangId) {
@@ -42,8 +36,8 @@ class KommentarRemoteService {
 
 	public Kommentar getById(String kommentarId) {
 		var response = vorgangAttachedItemServiceStub.getById(buildRequest(kommentarId));
-		var kommentar = mapper.fromItemMap(grpcObjectMapper.mapFromGrpc(response.getVorgangAttachedItem().getItem()));
-		return kommentar.toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build();
+
+		return mapper.fromItem(response.getVorgangAttachedItem()).toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build();
 	}
 
 	private GrpcVorgangAttachedItemRequest buildRequest(String kommentarId) {
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java
index 8b14e5f2262ef7a7628d9c2526f3704fa9654707..1a6627031e2d66b5b420705f339c10c0ece767c4 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java
@@ -1,17 +1,46 @@
 package de.itvsh.goofy.kommentar;
 
+import java.time.ZonedDateTime;
 import java.util.stream.Stream;
 
+import javax.validation.Valid;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
-@Service
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService;
+import de.itvsh.goofy.common.command.Command;
+import de.itvsh.goofy.common.user.CurrentUserService;
+
 @Validated
+@Service
 class KommentarService {
 
 	@Autowired
 	private KommentarRemoteService remoteService;
+	@Autowired
+	private CurrentUserService currentUserService;
+	@Autowired
+	private VorgangAttachedItemService vorgangAttachedItemService;
+
+	public Command createKommentar(@Valid Kommentar kommentar, String vorgangId) {
+		return vorgangAttachedItemService.createNewKommentar(addCreated(kommentar), vorgangId);
+	}
+
+	Kommentar addCreated(Kommentar kommentar) {
+		return kommentar.toBuilder()
+				.createdAt(ZonedDateTime.now().withNano(0))
+				.createdBy(currentUserService.getUserId().toString())
+				.build();
+	}
+
+	public Command editKommentar(@Valid Kommentar kommentar, String kommentarId, long kommentarVersion) {
+		var loadedKommentar = getById(kommentarId);
+		var preparedKommentar = loadedKommentar.toBuilder().text(kommentar.getText()).build();
+
+		return vorgangAttachedItemService.editKommentar(preparedKommentar, kommentarId, kommentarVersion);
+	}
 
 	public Stream<Kommentar> findByVorgangId(String vorgangId) {
 		return remoteService.findByVorgangId(vorgangId);
@@ -20,4 +49,4 @@ class KommentarService {
 	public Kommentar getById(String kommentarId) {
 		return remoteService.getById(kommentarId);
 	}
-}
+}
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java b/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java
index 4bd0a32d73aa3817555633bbc1b936d2a80c6952..aba1528f495b685b32fababbaeff557f283b4eae 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java
@@ -19,7 +19,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import de.itvsh.goofy.common.binaryfile.BinaryFileController;
-import de.itvsh.goofy.common.command.Command;
 import de.itvsh.goofy.common.command.CommandController;
 import de.itvsh.goofy.common.command.CommandController.CommandByRelationController;
 import de.itvsh.goofy.common.command.CreateCommand;
@@ -90,16 +89,15 @@ public class PostfachMailController {
 		@PostMapping
 		public ResponseEntity<Void> createCommand(@PathVariable String vorgangId, @PathVariable String postfachMailId,
 				@RequestBody CreateCommand command) {
-			command = command.toBuilder().vorgangId(vorgangId).relationId(postfachMailId).build();
-			var created = createCommand(command);
+			command = command.toBuilder()
+					.vorgangId(vorgangId)
+					.relationId(postfachMailId)
+					.build();
+			var created = commandByRelationController.createCommandWithoutRelation(command);
 
 			service.resendPostfachMail(created.getId(), postfachMailId);
 
 			return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build();
 		}
-
-		Command createCommand(CreateCommand command) {
-			return commandByRelationController.createCommand(command, -1);
-		}
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java b/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java
index 89b9dee2f56e78d599b55ac73c0ece2cedc2e803..072324a882b2bbbecb773f88723ab3f0a4cf8b01 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java
@@ -18,14 +18,12 @@ import de.itvsh.goofy.common.user.UserRole;
 import de.itvsh.goofy.vorgang.Vorgang.VorgangStatus;
 import de.itvsh.goofy.vorgang.VorgangWithEingang;
 import de.itvsh.goofy.vorgang.forwarding.ForwardingController;
-import de.itvsh.goofy.wiedervorlage.WiedervorlageCommandController.WiedervorlageCommandByVorgangController;
 
 @Component
 public class VorgangWithEingangCommandProzessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> {
 
 	static final LinkRelation REL_VORGANG_FORWARD = LinkRelation.of("forward");
 	static final LinkRelation REL_PENDING_COMMANDS = LinkRelation.of("pending-commands");
-	static final LinkRelation REL_CREATE_WIEDERVORLAGE = LinkRelation.of("create-wiedervorlage");
 
 	@Autowired
 	private CurrentUserService userService;
@@ -45,9 +43,6 @@ public class VorgangWithEingangCommandProzessor implements RepresentationModelPr
 				.addLink(linkTo(
 						methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(), vorgang.getVersion(),
 								null)).withRel(REL_VORGANG_FORWARD))
-				.ifMatch(() -> userService.hasRole(UserRole.VERWALTUNG_USER))
-				.addLink(linkTo(methodOn(WiedervorlageCommandByVorgangController.class).createCommand(null, vorgang.getId()))
-						.withRel(REL_CREATE_WIEDERVORLAGE))
 				.ifMatch(this::existsPendingCommands)
 				.addLink(linkTo(methodOn(CommandController.class).getPendingCommands(true, vorgang.getId())).withRel(REL_PENDING_COMMANDS))
 				.buildModel();
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java
index f842842587530ad75cabe1c5246ec2bfdc2d6f08..950343c58851a274800b7b848f384f9241df6864 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java
@@ -42,6 +42,8 @@ public class Wiedervorlage implements CommandBody {
 
 	@JsonIgnore
 	private String vorgangId;
+	@JsonIgnore
+	private long version;
 
 	@JsonProperty(access = Access.READ_ONLY)
 	private boolean done;
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java
index e6270b5ad8ab05eeee8c8729d03aaa4e223102b2..95eee8f6422f37e547f8f059b22196c28b1d855b 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java
@@ -2,7 +2,6 @@ package de.itvsh.goofy.wiedervorlage;
 
 import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
 
-import java.time.ZonedDateTime;
 import java.util.Objects;
 
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,14 +18,12 @@ import de.itvsh.goofy.common.command.CommandController;
 import de.itvsh.goofy.common.command.CommandController.CommandByRelationController;
 import de.itvsh.goofy.common.command.CommandOrder;
 import de.itvsh.goofy.common.command.CreateCommand;
-import de.itvsh.goofy.common.user.CurrentUserService;
 
 @RestController
 @RequestMapping(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS)
 public class WiedervorlageCommandController {
 
-	static final String WIEDERVORLAGE_COMMANDS = "/api/wiedervorlages/{wiedervorlageId}/commands";
-	static final String NOT_SET = "-1";
+	static final String WIEDERVORLAGE_COMMANDS = "/api/wiedervorlages/{wiedervorlageId}/{wiedervorlageVersion}/commands";
 
 	@Autowired
 	private CommandByRelationController commandByRelationController;
@@ -35,8 +32,9 @@ public class WiedervorlageCommandController {
 	private WiedervorlageService service;
 
 	@PostMapping
-	public ResponseEntity<Void> createCommand(@RequestBody WiedervorlageCommand command, @PathVariable String wiedervorlageId) {
-		var commandWithUpdatedWiedervorlage = buildCommand(service.getById(wiedervorlageId), command);
+	public ResponseEntity<Void> updateWiedervorlage(@RequestBody WiedervorlageCommand command, @PathVariable String wiedervorlageId,
+			@PathVariable long wiedervorlageVersion) {
+		var commandWithUpdatedWiedervorlage = buildCommand(service.getById(wiedervorlageId), command, wiedervorlageVersion);
 
 		var createdCommand = createByOrder(commandWithUpdatedWiedervorlage, command.getOrder());
 
@@ -45,10 +43,11 @@ public class WiedervorlageCommandController {
 		return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build();
 	}
 
-	CreateCommand buildCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command) {
+	CreateCommand buildCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command, long wiedervorlageVersion) {
 		var commandBuilder = CreateCommand.builder()
 				.order(CommandOrder.UPDATE_ATTACHED_ITEM)
-				.relationId(NOT_SET)
+				.relationId(wiedervorlage.getId())
+				.relationVersion(wiedervorlageVersion)
 				.vorgangId(wiedervorlage.getVorgangId());
 
 		switch (command.getOrder()) {
@@ -65,9 +64,10 @@ public class WiedervorlageCommandController {
 
 	Command createByOrder(CreateCommand command, CommandOrder commandOrder) {
 		if (shouldBeValidated(commandOrder)) {
-			return commandByRelationController.createCommand(command, WiedervorlageRemoteService.ITEM_NAME);
+			return service.editWiedervorlage((Wiedervorlage) command.getBody(), command.getRelationId(), command.getRelationVersion());
 		} else {
-			return commandByRelationController.createCommandWithoutValidation(command, WiedervorlageRemoteService.ITEM_NAME);
+			return commandByRelationController.createCommandWithoutValidation(command, WiedervorlageRemoteService.ITEM_NAME,
+					command.getRelationVersion());
 		}
 	}
 
@@ -89,39 +89,18 @@ public class WiedervorlageCommandController {
 
 		static final String WIEDERVORLAGE_COMMANDS_BY_VORGANG = "/api/vorgangs/{vorgangId}/wiedervorlageCommands";
 
-		@Autowired
-		private CommandByRelationController commandByRelationController;
-
-		@Autowired
-		private CurrentUserService userService;
-
 		@Autowired
 		private WiedervorlageService service;
 
 		@PostMapping
-		public ResponseEntity<Void> createCommand(@RequestBody WiedervorlageCommand command, @PathVariable String vorgangId) {
-			var createdCommand = commandByRelationController.createCommand(buildCommand(vorgangId, command), WiedervorlageRemoteService.ITEM_NAME);
+		public ResponseEntity<Void> createWiedervorlage(@RequestBody WiedervorlageCommand command, @PathVariable String vorgangId) {
+			var preparedWiedervorlage = stripAttachmentFileUriToId(command.getWiedervorlage());
+			var createdCommand = service.createWiedervorlage(preparedWiedervorlage, vorgangId);
 
-			service.updateNextFrist(command.getWiedervorlage(), vorgangId);
+			service.updateNextFrist(preparedWiedervorlage, vorgangId);
 
 			return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build();
 		}
-
-		CreateCommand buildCommand(String vorgangId, WiedervorlageCommand command) {
-			return CreateCommand.builder()
-					.vorgangId(vorgangId)
-					.order(CommandOrder.CREATE_ATTACHED_ITEM)
-					.body(buildBody(command.getWiedervorlage()))
-					.build();
-		}
-
-		Wiedervorlage buildBody(Wiedervorlage wiedervorlage) {
-			wiedervorlage = wiedervorlage.toBuilder()
-					.createdAt(ZonedDateTime.now().withNano(0))
-					.createdBy(userService.getUserId().toString())
-					.build();
-			return stripAttachmentFileUriToId(wiedervorlage);
-		}
 	}
 
 	// TODO Durch LinkedResource am attachment Attribute ersetzen
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java
index 6213f6439493801330c7546683e2ffc6cb9a8a9b..3dd222c011ec78ab460a2911d869fc364cc09ca6 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java
@@ -11,15 +11,21 @@ import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.ReportingPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import de.itvsh.goofy.common.binaryfile.FileId;
 import de.itvsh.goofy.common.binaryfile.FileIdMapper;
+import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
+import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
 @Mapper(uses = { FileIdMapper.class }, unmappedTargetPolicy = ReportingPolicy.WARN, //
 		unmappedSourcePolicy = ReportingPolicy.WARN, //
 		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, //
 		collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
-public interface WiedervorlageMapper {
+abstract class WiedervorlageMapper {
+
+	@Autowired
+	private GrpcObjectMapper grpcObjectMapper;
 
 	static final String ID = "id";
 	static final String DONE = "done";
@@ -31,9 +37,14 @@ public interface WiedervorlageMapper {
 	static final String FRIST = "frist";
 	static final String ATTACHMENTS = "attachments";
 
-	default Wiedervorlage fromItemMap(Map<String, Object> itemMap) {
+	public Wiedervorlage fromItem(GrpcVorgangAttachedItem item) {
+		return fromItemMap(grpcObjectMapper.mapFromGrpc(item.getItem()), item.getVersion());
+	}
+
+	Wiedervorlage fromItemMap(Map<String, Object> itemMap, long version) {
 		return Wiedervorlage.builder()
 				.id((String) itemMap.get(ID))
+				.version(version)
 				.done(Boolean.valueOf((String) itemMap.get(DONE)))
 				.createdBy((String) itemMap.get(CREATED_BY))
 				.createdAt(ZonedDateTime.parse((String) itemMap.get(CREATED_AT)))
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java
index 7743f050749d885035e39b3db23aa75d0c88ef6c..6bbdd7c7eca4940433d2149f7a6632e8d9d4da1e 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java
@@ -34,7 +34,8 @@ class WiedervorlageModelAssembler implements RepresentationModelAssembler<Wieder
 	@Override
 	public EntityModel<Wiedervorlage> toModel(Wiedervorlage wiedervorlage) {
 		var selfLink = linkTo(WiedervorlageController.class).slash(wiedervorlage.getId());
-		var commandLink = linkTo(methodOn(WiedervorlageCommandController.class).createCommand(null, wiedervorlage.getId()));
+		var commandLink = linkTo(
+				methodOn(WiedervorlageCommandController.class).updateWiedervorlage(null, wiedervorlage.getId(), wiedervorlage.getVersion()));
 
 		return ModelBuilder.fromEntity(wiedervorlage).addLink(selfLink.withSelfRel())
 				.addLink(commandLink.withRel(REL_EDIT))
@@ -48,7 +49,8 @@ class WiedervorlageModelAssembler implements RepresentationModelAssembler<Wieder
 	public CollectionModel<EntityModel<Wiedervorlage>> toCollectionModel(Stream<Wiedervorlage> entities, String vorgangId) {
 		return CollectionModel.of(entities.map(this::toModel).collect(Collectors.toList()),
 				linkTo(WiedervorlageController.class).withSelfRel(),
-				linkTo(methodOn(WiedervorlageCommandByVorgangController.class).createCommand(null, vorgangId)).withRel(REL_CREATE),
+				linkTo(methodOn(WiedervorlageCommandByVorgangController.class).createWiedervorlage(null, vorgangId))
+						.withRel(REL_CREATE),
 				linkTo(BinaryFileController.class).slash(vorgangId).slash("wiedervorlageAttachment").slash("file")
 						.withRel(REL_UPLOAD_FILE));
 	}
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java
index b39b3f0d9ef9efe82cb1f3a43d0fa15d84ab2a4c..73bc379fdacc8d16bd19750017c5ed90c35abae8 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java
@@ -10,7 +10,6 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
 
 import de.itvsh.goofy.GoofyServerApplication;
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
 import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
 import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
@@ -37,16 +36,12 @@ public class WiedervorlageRemoteService {
 	@Autowired
 	private WiedervorlageMapper mapper;
 	@Autowired
-	private GrpcObjectMapper grpcObjectMapper;
-	@Autowired
 	private ApplicationContext context;
 
 	public Stream<Wiedervorlage> findByVorgangId(String vorgangId) {
 		var response = vorgangAttachedItemServiceStub.find(buildFindRequest(vorgangId));
 
-		return response.getVorgangAttachedItemsList().stream()
-				.map(item -> grpcObjectMapper.mapFromGrpc(item.getItem()))
-				.map(mapper::fromItemMap);
+		return response.getVorgangAttachedItemsList().stream().map(mapper::fromItem);
 	}
 
 	GrpcFindVorgangAttachedItemRequest buildFindRequest(String vorgangId) {
@@ -58,8 +53,8 @@ public class WiedervorlageRemoteService {
 
 	public Wiedervorlage getById(String wiedervorlageId) {
 		var response = vorgangAttachedItemServiceStub.getById(GrpcVorgangAttachedItemRequest.newBuilder().setId(wiedervorlageId).build());
-		var wiedervorlage = mapper.fromItemMap(grpcObjectMapper.mapFromGrpc(response.getVorgangAttachedItem().getItem()));
-		return wiedervorlage.toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build();
+
+		return mapper.fromItem(response.getVorgangAttachedItem()).toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build();
 	}
 
 	public void updateNextFrist(String vorgangId, Optional<LocalDate> nextFrist) {
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java
index 4d6961375b53686657df8aa323f17c06f8eddd96..e508c813a169c3ed9570239ff1add9df2491c2ae 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java
@@ -1,15 +1,24 @@
 package de.itvsh.goofy.wiedervorlage;
 
 import java.time.LocalDate;
+import java.time.ZonedDateTime;
 import java.util.Comparator;
 import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
+import javax.validation.Valid;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService;
+import de.itvsh.goofy.common.command.Command;
+import de.itvsh.goofy.common.user.CurrentUserService;
 
+@Validated
 @Service
 class WiedervorlageService {
 
@@ -17,6 +26,25 @@ class WiedervorlageService {
 
 	@Autowired
 	private WiedervorlageRemoteService remoteService;
+	@Autowired
+	private VorgangAttachedItemService vorgangAttachedItemService;
+	@Autowired
+	private CurrentUserService currentUserService;
+
+	public Command createWiedervorlage(@Valid Wiedervorlage wiedervorlage, String vorgangId) {
+		return vorgangAttachedItemService.createNewWiedervorlage(addCreated(wiedervorlage), vorgangId);
+	}
+
+	Wiedervorlage addCreated(Wiedervorlage wiedervorlage) {
+		return wiedervorlage.toBuilder()
+				.createdAt(ZonedDateTime.now().withNano(0))
+				.createdBy(currentUserService.getUserId().toString())
+				.build();
+	}
+
+	public Command editWiedervorlage(@Valid Wiedervorlage wiedervorlage, String wiedervorlageId, long wiedervorlageVersion) {
+		return vorgangAttachedItemService.editWiedervorlage(wiedervorlage, wiedervorlageId, wiedervorlageVersion);
+	}
 
 	public Wiedervorlage getById(String wiedervorlageId) {
 		return remoteService.getById(wiedervorlageId);
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java
index 778e0dc261ca83baefff24df794e4e346fb7c403..bd32012c381f870f397df66abc0485a793c5c0db 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java
@@ -14,6 +14,7 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.springframework.boot.info.BuildProperties;
 import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.Link;
@@ -24,12 +25,14 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import static org.assertj.core.api.Assertions.*;
 
 import de.itvsh.goofy.common.user.CurrentUserService;
+import de.itvsh.goofy.common.user.UserRole;
 import de.itvsh.goofy.common.user.UserTestFactory;
 
 class RootControllerTest {
 
 	private final String PATH = "/api";
 
+	@Spy
 	@InjectMocks // NOSONAR
 	private RootController controller;
 	@Mock
@@ -50,13 +53,13 @@ class RootControllerTest {
 	@Nested
 	class TestLinks {
 
-		@DisplayName("with any role")
+		@DisplayName("with any verwaltung role")
 		@Nested
-		class TestWithAnyRole {
+		class TestWithVerwaltungRole {
 
 			@BeforeEach
 			void mockCurrentUserService() {
-				when(currentUserService.hasRole(anyString())).thenReturn(true);
+				doReturn(true).when(controller).hasVerwaltungRole();
 			}
 
 			@Test
@@ -115,6 +118,32 @@ class RootControllerTest {
 			}
 		}
 
+		@DisplayName("with role " + UserRole.EINHEITLICHER_ANSPRECHPARTNER)
+		@Nested
+		class TestWithEinheitlicherAnsprechpartnerRole {
+
+			@BeforeEach
+			void mock() {
+				when(currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(true);
+
+				doReturn(false).when(controller).hasVerwaltungRole();
+			}
+
+			@Test
+			void shoulNotHaveMyVorgaengeLink() {
+				var model = controller.getRootResource();
+
+				assertThat(model.getLink(RootController.REL_MY_VORGAENGE)).isNotPresent();
+			}
+
+			@Test
+			void shoulNotHaveSearchMyVorgaengeLink() {
+				var model = controller.getRootResource();
+
+				assertThat(model.getLink(RootController.REL_SEARCH_MY_VORGAENGE)).isNotPresent();
+			}
+		}
+
 		@DisplayName("with no role")
 		@Nested
 		class TestWithNoRole {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..119c69476263cf2451c055d215dfefcb07ce74cb
--- /dev/null
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemServiceTest.java
@@ -0,0 +1,275 @@
+package de.itvsh.goofy.common.attacheditem;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+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.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import static org.assertj.core.api.Assertions.*;
+
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItem;
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService;
+import de.itvsh.goofy.common.command.Command;
+import de.itvsh.goofy.common.command.CommandBodyMapper;
+import de.itvsh.goofy.common.command.CommandOrder;
+import de.itvsh.goofy.common.command.CommandService;
+import de.itvsh.goofy.common.command.CommandTestFactory;
+import de.itvsh.goofy.common.command.CreateCommand;
+import de.itvsh.goofy.kommentar.Kommentar;
+import de.itvsh.goofy.kommentar.KommentarTestFactory;
+import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
+import de.itvsh.goofy.wiedervorlage.Wiedervorlage;
+import de.itvsh.goofy.wiedervorlage.WiedervorlageTestFactory;
+
+class VorgangAttachedItemServiceTest {
+
+	@Spy
+	@InjectMocks
+	private VorgangAttachedItemService service;
+	@Mock
+	private CommandBodyMapper commandBodyMapper;
+	@Mock
+	private CommandService commandService;
+
+	@DisplayName("Create new wiedervorlage")
+	@Nested
+	class TestCreateNewWiedervorlage {
+
+		private Wiedervorlage wiedervorlage = WiedervorlageTestFactory.create();
+
+		@BeforeEach
+		void mockServices() {
+			doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any());
+			doReturn(CommandTestFactory.createCreateCommand()).when(service).buildCreateCommand(any(), any());
+		}
+
+		@Test
+		void shouldBuildVorgangAttachedItem() {
+			callCreateNewWiedervorlage();
+
+			verify(service).buildVorgangAttachedItem(wiedervorlage, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME);
+		}
+
+		@Test
+		void shouldBuildCreateCommand() {
+			callCreateNewWiedervorlage();
+
+			verify(service).buildCreateCommand(eq(VorgangHeaderTestFactory.ID), any(VorgangAttachedItem.class));
+		}
+
+		@Test
+		void shouldCallCommandService() {
+			callCreateNewWiedervorlage();
+
+			verify(commandService).createCommand(any(CreateCommand.class));
+		}
+
+		private Command callCreateNewWiedervorlage() {
+			return service.createNewWiedervorlage(wiedervorlage, VorgangHeaderTestFactory.ID);
+		}
+	}
+
+	@DisplayName("Edit wiedervorlage")
+	@Nested
+	class TestEditWiedervorlage {
+
+		private Wiedervorlage wiedervorlage = WiedervorlageTestFactory.create();
+
+		@BeforeEach
+		void mockService() {
+			doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any());
+			doReturn(CommandTestFactory.createCreateCommand()).when(service).buildUpdateCommand(any(), any(), any());
+		}
+
+		@Test
+		void shouldBuildVorgangAttachedItem() {
+			callEditWiedervorlage();
+
+			verify(service).buildVorgangAttachedItem(wiedervorlage, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME);
+		}
+
+		@Test
+		void shouldBuildCreateCommand() {
+			callEditWiedervorlage();
+
+			verify(service).buildUpdateCommand(eq(VorgangHeaderTestFactory.ID), eq(WiedervorlageTestFactory.ID), any(VorgangAttachedItem.class));
+		}
+
+		@Test
+		void shouldCallCommandService() {
+			callEditWiedervorlage();
+
+			verify(commandService).createCommand(any(CreateCommand.class), eq(WiedervorlageTestFactory.VERSION));
+		}
+
+		private Command callEditWiedervorlage() {
+			return service.editWiedervorlage(wiedervorlage, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION);
+		}
+
+	}
+
+	@DisplayName("Create new kommentar")
+	@Nested
+	class TestCreateNewKommentar {
+
+		private Kommentar kommentar = KommentarTestFactory.create();
+
+		@BeforeEach
+		void mockServices() {
+			doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any());
+			doReturn(CommandTestFactory.createCreateCommand()).when(service).buildCreateCommand(any(), any());
+		}
+
+		@Test
+		void shouldBuildVorgangAttachedItem() {
+			callCreateNewKommentar();
+
+			verify(service).buildVorgangAttachedItem(kommentar, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.KOMMENTAR_ITEM_NAME);
+		}
+
+		@Test
+		void shouldBuildCreateCommand() {
+			callCreateNewKommentar();
+
+			verify(service).buildCreateCommand(eq(VorgangHeaderTestFactory.ID), any(VorgangAttachedItem.class));
+		}
+
+		@Test
+		void shouldCallCommandService() {
+			callCreateNewKommentar();
+
+			verify(commandService).createCommand(any(CreateCommand.class));
+		}
+
+		private Command callCreateNewKommentar() {
+			return service.createNewKommentar(kommentar, VorgangHeaderTestFactory.ID);
+		}
+	}
+
+	@DisplayName("Edit kommentar")
+	@Nested
+	class TestEditKommentar {
+
+		private Kommentar kommentar = KommentarTestFactory.create();
+
+		@BeforeEach
+		void mockService() {
+			doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any());
+			doReturn(CommandTestFactory.createCreateCommand()).when(service).buildUpdateCommand(any(), any(), any());
+		}
+
+		@Test
+		void shouldBuildVorgangAttachedItem() {
+			callEditKommentar();
+
+			verify(service).buildVorgangAttachedItem(kommentar, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.KOMMENTAR_ITEM_NAME);
+		}
+
+		@Test
+		void shouldBuildCreateCommand() {
+			callEditKommentar();
+
+			verify(service).buildUpdateCommand(eq(VorgangHeaderTestFactory.ID), eq(KommentarTestFactory.ID), any(VorgangAttachedItem.class));
+		}
+
+		@Test
+		void shouldCallCommandService() {
+			callEditKommentar();
+
+			verify(commandService).createCommand(any(CreateCommand.class), eq(KommentarTestFactory.VERSION));
+		}
+
+		private Command callEditKommentar() {
+			return service.editKommentar(kommentar, KommentarTestFactory.ID, KommentarTestFactory.VERSION);
+		}
+	}
+
+	@DisplayName("build vorgang attached item")
+	@Nested
+	class TestBuildVorgangAttachedItem {
+
+		private static final Wiedervorlage BODY = WiedervorlageTestFactory.create();
+
+		@BeforeEach
+		void mockServices() {
+			when(commandBodyMapper.fromObjectToMap(any())).thenReturn(VorgangAttachedItemTestFactory.ITEM);
+		}
+
+		@Test
+		void shouldCallCommandBodyMapper() {
+			buildVorgangAttachedItem();
+
+			verify(commandBodyMapper).fromObjectToMap(BODY);
+		}
+
+		@Test
+		void shouldContainsVorgangId() {
+			var vorgangAttachedItem = buildVorgangAttachedItem();
+
+			assertThat(vorgangAttachedItem.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID);
+		}
+
+		@Test
+		void shouldContainsItemName() {
+			var vorgangAttachedItem = buildVorgangAttachedItem();
+
+			assertThat(vorgangAttachedItem.getItemName()).isEqualTo(VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME);
+		}
+
+		@Test
+		void shouldContainsItem() {
+			var vorgangAttachedItem = buildVorgangAttachedItem();
+
+			assertThat(vorgangAttachedItem.getItem()).isEqualTo(VorgangAttachedItemTestFactory.ITEM);
+		}
+
+		private VorgangAttachedItem buildVorgangAttachedItem() {
+			return service.buildVorgangAttachedItem(BODY, VorgangHeaderTestFactory.ID,
+					VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME);
+		}
+	}
+
+	@DisplayName("build createCommand")
+	@Nested
+	class TestBuildCreateCommand {
+
+		@Test
+		void shouldContainsVorgangId() throws Exception {
+			var createCommand = buildCommand();
+
+			assertThat(createCommand.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID);
+		}
+
+		@Test
+		void shouldContainsRelationId() throws Exception {
+			var createCommand = buildCommand();
+
+			assertThat(createCommand.getRelationId()).isEqualTo(VorgangHeaderTestFactory.ID);
+		}
+
+		@Test
+		void shouldContainsOrder() throws Exception {
+			var createCommand = buildCommand();
+
+			assertThat(createCommand.getOrder()).isEqualTo(CommandOrder.CREATE_ATTACHED_ITEM);
+		}
+
+		@Test
+		void shouldContainsBody() throws Exception {
+			var createCommand = buildCommand();
+
+			assertThat(((VorgangAttachedItem) createCommand.getBody())).usingRecursiveComparison()
+					.isEqualTo(VorgangAttachedItemTestFactory.create());
+		}
+
+		private CreateCommand buildCommand() {
+			return service.buildCreateCommand(VorgangHeaderTestFactory.ID, VorgangAttachedItemTestFactory.create());
+		}
+	}
+}
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ea3c9250428a4fb96f62434c21b8abebecb4416
--- /dev/null
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemTestFactory.java
@@ -0,0 +1,28 @@
+package de.itvsh.goofy.common.attacheditem;
+
+import java.util.Map;
+import java.util.UUID;
+
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItem;
+
+public class VorgangAttachedItemTestFactory {
+
+	public static final String ID = UUID.randomUUID().toString();
+	public static final long VERSION = 42;
+	public static final String CLIENT = "Goofy";
+	public static final String ITEM_NAME = "ItemName";
+	public static final Map<String, Object> ITEM = Map.of("oneKey", "oneValue");
+
+	public static VorgangAttachedItem create() {
+		return createBuilder().build();
+	}
+
+	public static VorgangAttachedItem.VorgangAttachedItemBuilder createBuilder() {
+		return VorgangAttachedItem.builder()
+				.id(ID)
+				.version(VERSION)
+				.client(CLIENT)
+				.itemName(ITEM_NAME)
+				.item(ITEM);
+	}
+}
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java
index 13d0d22456f477f570a97c73bc50e1991d947272..6f1e3eeeedae9ce2bdd44d2089de4bd7132a81fc 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java
@@ -35,40 +35,44 @@ class CommandBodyMapperTest {
 	class TestFromObjectToMap {
 
 		@Test
-		void shouldMapAllFieldsExceptClass() {
+		void shouldMapAllValues() {
+			var commandAsObject = CommandTestFactory.create();
+
+			var mappedMap = mapper.fromObjectToMap(commandAsObject);
+
+			assertThat(mappedMap).hasSize(12)
+					.containsEntry("id", CommandTestFactory.ID)
+					.containsEntry("status", CommandTestFactory.STATUS.name())
+					.containsEntry("order", CommandTestFactory.ORDER.name())
+					.containsEntry("relationId", CommandTestFactory.RELATION_ID)
+					.containsEntry("vorgangId", CommandTestFactory.VORGANG_ID);
+		}
+
+		@Test
+		void shouldNotMapClass() {
 			var commandAsObject = CommandTestFactory.create();
 
 			var mappedMap = mapper.fromObjectToMap(commandAsObject);
 
-			assertThat(mappedMap).hasSize(5).doesNotContainKey("class");
+			assertThat(mappedMap).doesNotContainKey("class");
 		}
 
 		@Test
-		void shouldNotMapNullValue() {
+		void shouldMapNullValue() {
 			var commandAsObject = CommandTestFactory.createBuilder().status(null).build();
 
 			var mappedMap = mapper.fromObjectToMap(commandAsObject);
 
-			assertThat(mappedMap)
-					.hasSize(4)
-					.doesNotContainKey("status")
-					.containsEntry("order", CommandTestFactory.ORDER.name())
-					.containsEntry("relationId", CommandTestFactory.RELATION_ID)
-					.containsEntry("vorgangId", CommandTestFactory.VORGANG_ID);
+			assertThat(mappedMap).containsEntry("status", null);
 		}
 
 		@Test
-		void shouldMapAllValues() {
-			var commandAsObject = CommandTestFactory.create();
+		void shouldNotMapVersion() {
+			var commandAsObject = WiedervorlageTestFactory.create();
 
 			var mappedMap = mapper.fromObjectToMap(commandAsObject);
 
-			assertThat(mappedMap)
-					.hasSize(5)
-					.containsEntry("status", CommandTestFactory.STATUS.name())
-					.containsEntry("order", CommandTestFactory.ORDER.name())
-					.containsEntry("relationId", CommandTestFactory.RELATION_ID)
-					.containsEntry("vorgangId", CommandTestFactory.VORGANG_ID);
+			assertThat(mappedMap).doesNotContainKey("version");
 		}
 	}
 
@@ -150,10 +154,11 @@ class CommandBodyMapperTest {
 		}
 
 		@Test
-		void shouldFilterEntriesWithNullValue() {
+		void shouldMapNullAsEmptyValue() {
 			var result = mapper.mapToBodyFields(buildBodyMapWithNullValue());
 
-			assertThat(result).isEmpty();
+			assertThat(result).hasSize(1);
+			assertThat(result.get(0).getValue()).isEmpty();
 		}
 
 		private Map<Object, Object> buildBodyMapWithNullValue() {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java
index 1d701b2269b468c4d63d4a3f13309c47d7e930af..a920b70120ac24cb3e397292a8ea963d49200f03 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java
@@ -160,8 +160,11 @@ class CommandControllerTest {
 			void callService() throws Exception {
 				doRequest();
 
-				verify(service).createCommand(createCommandCaptor.capture(), eq(VorgangHeaderTestFactory.VERSION));
+				verify(service).createCommand(createCommandCaptor.capture(), eq(CommandTestFactory.RELATION_VERSION));
 				assertThat(createCommandCaptor.getValue().getOrder()).isEqualTo(CommandTestFactory.ORDER);
+				assertThat(createCommandCaptor.getValue().getVorgangId()).isEqualTo(CommandTestFactory.VORGANG_ID);
+				assertThat(createCommandCaptor.getValue().getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
+				assertThat(createCommandCaptor.getValue().getRelationVersion()).isZero();
 			}
 
 			@DisplayName("should have location header")
@@ -248,33 +251,35 @@ class CommandControllerTest {
 			}
 		}
 
+		@DisplayName("Create by vorgang with relation id")
 		@Nested
-		class CreateByVorgangAndItemName {
+		class TestCreateByVorgangWithoutRelationId {
 
-			private static final String ITEM_NAME = "Wiedervorlage";
 			private final CreateCommand command = CommandTestFactory.createCreateCommand();
 
-			@Nested
-			class WithValidation {
-
-				@Test
-				void shouldCallService() {
-					controller.createCommand(command, ITEM_NAME);
+			@Test
+			void shouldCallSerice() {
+				controller.createCommandWithoutRelation(command);
 
-					verify(service).createCommand(command, ITEM_NAME);
-				}
+				verify(service).createCommandWithoutRelation(command);
 			}
+		}
+
+		@Nested
+		class CreateByVorgangAndItemName {
+
+			private static final String ITEM_NAME = "Wiedervorlage";
+			private final CreateCommand command = CommandTestFactory.createCreateCommand();
 
 			@Nested
 			class WithoutValidation {
 
 				@Test
 				void shouldCallService() {
-					controller.createCommandWithoutValidation(command, ITEM_NAME);
+					controller.createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION);
 
-					verify(service).createCommandWithoutValidation(command, ITEM_NAME);
+					verify(service).createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION);
 				}
-
 			}
 		}
 	}
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java
index ca0b874eddb7bf5fd8c6e99427081766af79a5f8..0aff0b1a2396b22a28acae4957f99cb21cc7ca37 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java
@@ -1,6 +1,5 @@
 package de.itvsh.goofy.common.command;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -22,6 +21,8 @@ import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.ValidationMessageCodes;
 import de.itvsh.goofy.common.user.UserTestFactory;
 import de.itvsh.goofy.postfach.PostfachMailTestFactory;
@@ -52,14 +53,14 @@ public class CommandITCase {
 
 		@BeforeEach
 		void initTests() {
-			when(commandRemoteService.createCommand(any(), anyLong())).thenReturn(CommandTestFactory.create());
+			when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create());
 		}
 
 		@Test
 		void shouldExtractUserId() throws Exception {
 			createCommand();
 
-			verify(commandRemoteService).createCommand(commandCaptor.capture(), anyLong());
+			verify(commandRemoteService).createCommand(commandCaptor.capture());
 			assertThat(commandCaptor.getValue().getBody()).hasFieldOrPropertyWithValue("assignedTo", UserTestFactory.ID);
 		}
 
@@ -180,7 +181,7 @@ public class CommandITCase {
 
 				@BeforeEach
 				void initMockCommand() {
-					when(commandRemoteService.createCommand(any(CreateCommand.class), anyLong())).thenReturn(CommandTestFactory.create());
+					when(commandRemoteService.createCommand(any(CreateCommand.class))).thenReturn(CommandTestFactory.create());
 				}
 
 				@Test
@@ -232,7 +233,7 @@ public class CommandITCase {
 
 				@Test
 				void shouldProceedOnValidInput() throws Exception {
-					when(commandRemoteService.createCommand(any(CreateCommand.class), anyLong())).thenReturn(CommandTestFactory.create());
+					when(commandRemoteService.createCommand(any(CreateCommand.class))).thenReturn(CommandTestFactory.create());
 
 					var content = PostfachMailTestFactory.buildSendPostfachMailContent();
 
@@ -243,7 +244,7 @@ public class CommandITCase {
 
 		ResultActions doRequest(String content) throws Exception {
 			return mockMvc.perform(post("/api/vorgangs/" + CommandTestFactory.VORGANG_ID + "/relations/" + CommandTestFactory.RELATION_ID + "/"
-					+ CommandTestFactory.VERSION + "/commands")
+					+ CommandTestFactory.RELATION_VERSION + "/commands")
 							.contentType(MediaType.APPLICATION_JSON)
 							.content(content));
 		}
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java
index 3b9794b4c12d1a7d2d96c35e805e0c758b02c2b6..3e687d3a2c49b701a06b0547d922a4e57cb4a2fe 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java
@@ -78,28 +78,28 @@ class CommandRemoteServiceTest {
 
 			@BeforeEach
 			void initTest() {
-				doReturn(request).when(service).buildCreateCommandRequest(any(), anyLong());
+				doReturn(request).when(service).buildCreateCommandRequest(any());
 				when(commandServiceStub.createCommand(any())).thenReturn(GrpcCommandResponse.newBuilder().build());
 				when(mapper.toCommand(any())).thenReturn(resultCommand);
 			}
 
 			@Test
 			void shouldCreateRequest() {
-				service.createCommand(createCommand, CommandTestFactory.VERSION);
+				service.createCommand(createCommand);
 
-				verify(service).buildCreateCommandRequest(createCommand, CommandTestFactory.VERSION);
+				verify(service).buildCreateCommandRequest(createCommand);
 			}
 
 			@Test
 			void shouldCallServiceStub() {
-				service.createCommand(createCommand, CommandTestFactory.VERSION);
+				service.createCommand(createCommand);
 
 				verify(commandServiceStub).createCommand(request);
 			}
 
 			@Test
 			void shouldReturnResultCommand() {
-				var result = service.createCommand(createCommand, CommandTestFactory.VERSION);
+				var result = service.createCommand(createCommand);
 
 				assertThat(result).isSameAs(resultCommand);
 			}
@@ -177,7 +177,7 @@ class CommandRemoteServiceTest {
 				when(mapper.toGrpcRedirectRequest(any())).thenReturn(grpcRedirectRequest);
 				var command = CommandTestFactory.createCreateCommandBuilder().redirectRequest(RedirectRequestTestFactory.create()).build();
 
-				var request = service.buildCreateCommandRequest(command, CommandTestFactory.VERSION);
+				var request = service.buildCreateCommandRequest(command);
 
 				assertThat(request.getRedirectRequest()).isNotNull().isSameAs(grpcRedirectRequest);
 			}
@@ -185,16 +185,14 @@ class CommandRemoteServiceTest {
 			@ParameterizedTest
 			@EnumSource
 			void shouldHaveOrder(CommandOrder order) {
-				var request = service.buildCreateCommandRequest(CommandTestFactory.createCreateCommandBuilder().order(order).build(),
-						CommandTestFactory.VERSION);
+				var request = service.buildCreateCommandRequest(CommandTestFactory.createCreateCommandBuilder().order(order).build());
 
 				assertThat(request.getOrderString()).isEqualTo(order.name());
 			}
 
 			private GrpcCreateCommandRequest buildRequest() {
 				return service.buildCreateCommandRequest(
-						CommandTestFactory.createCreateCommandBuilder().body(RedirectRequestTestFactory.create()).build(),
-						CommandTestFactory.VERSION);
+						CommandTestFactory.createCreateCommandBuilder().body(RedirectRequestTestFactory.create()).build());
 			}
 		}
 	}
@@ -262,17 +260,17 @@ class CommandRemoteServiceTest {
 			}
 
 			@Test
-			void shouldContainsVorgangIdAsRelationId() {
+			void shouldContainsRelationId() {
 				var request = buildRequest();
 
-				assertThat(request.getRelationId()).isEqualTo(CommandTestFactory.VORGANG_ID);
+				assertThat(request.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
 			}
 
 			@Test
 			void shouldContainsRelationVersion() {
 				var request = buildRequest();
 
-				assertThat(request.getRelationVersion()).isEqualTo(-1);
+				assertThat(request.getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION);
 			}
 
 			@Test
@@ -283,10 +281,10 @@ class CommandRemoteServiceTest {
 			}
 
 			@Test
-			void shouldContainsOrder() {
+			void shouldContainsOrderString() {
 				var request = buildRequest();
 
-				assertThat(request.getOrder()).isEqualTo(GrpcOrder.VORGANG_ANNEHMEN);
+				assertThat(request.getOrderString()).isEqualTo(GrpcOrder.VORGANG_ANNEHMEN.name());
 			}
 
 			private GrpcCreateCommandRequest buildRequest() {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java
index acd0c9ad4631dfe38a8eddc7a2f293dd66e2b706..4c49293df735c22d7bb628daa17870c1285aa927 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java
@@ -1,6 +1,5 @@
 package de.itvsh.goofy.common.command;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
@@ -11,6 +10,8 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
 class CommandServiceTest {
@@ -28,27 +29,61 @@ class CommandServiceTest {
 
 		private final CreateCommand command = CommandTestFactory.createCreateCommand();
 
-		@Test
-		void shouldCallRemoteServiceWithVersion() {
-			service.createCommand(command, CommandTestFactory.VERSION);
+		@Nested
+		class TestWithCreateCommandOnly {
+
+			@Test
+			void shouldCallRemoteService() {
+				service.createCommand(command);
+
+				verify(remoteService).createCommand(any(CreateCommand.class));
+			}
 
-			verify(remoteService).createCommand(command, CommandTestFactory.VERSION);
+			@Test
+			void shouldHaveSetRelationVersion() {
+				service.createCommand(command);
+
+				verify(remoteService).createCommand(createCommandCaptor.capture());
+				assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandService.NO_RELATION_VERSION);
+			}
 		}
 
-		@Test
-		void shouldHaveVorgangId() {
-			service.createCommand(command, CommandTestFactory.VERSION);
+		@Nested
+		class TestWithRelationVersion {
+
+			@Test
+			void shouldCallRemoteService() {
+				service.createCommand(command, CommandTestFactory.RELATION_VERSION);
+
+				verify(remoteService).createCommand(any(CreateCommand.class));
+			}
 
-			verify(remoteService).createCommand(createCommandCaptor.capture(), anyLong());
-			assertThat(createCommandCaptor.getValue().getVorgangId()).isEqualTo(CommandTestFactory.VORGANG_ID);
+			@Test
+			void shouldHaveSetRelationVersion() {
+				service.createCommand(command, CommandTestFactory.RELATION_VERSION);
+
+				verify(remoteService).createCommand(createCommandCaptor.capture());
+				assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION);
+			}
 		}
 
-		@Test
-		void shouldHaveRelationId() {
-			service.createCommand(command, CommandTestFactory.VERSION);
+		@Nested
+		class TestWithoutRelationVersion {
+
+			@Test
+			void shouldCallRemoteService() {
+				service.createCommandWithoutRelation(command);
+
+				verify(remoteService).createCommand(any(CreateCommand.class));
+			}
 
-			verify(remoteService).createCommand(createCommandCaptor.capture(), anyLong());
-			assertThat(createCommandCaptor.getValue().getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
+			@Test
+			void shouldHaveSetRelationVersion() {
+				service.createCommandWithoutRelation(command);
+
+				verify(remoteService).createCommand(createCommandCaptor.capture());
+				assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandService.NO_RELATION_VERSION);
+			}
 		}
 	}
 
@@ -59,24 +94,21 @@ class CommandServiceTest {
 		private final CreateCommand command = CommandTestFactory.createCreateCommand();
 
 		@Nested
-		class WithValidation {
+		class WithoutValidation {
 
 			@Test
 			void shouldCallRemoteService() {
-				service.createCommand(command, ITEM_NAME);
+				service.createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION);
 
-				verify(remoteService).createCommand(command, ITEM_NAME);
+				verify(remoteService).createCommand(any(CreateCommand.class), eq(ITEM_NAME));
 			}
-		}
-
-		@Nested
-		class WithoutValidation {
 
 			@Test
-			void shouldCallRemoteService() {
-				service.createCommandWithoutValidation(command, ITEM_NAME);
+			void shouldHaveSetRelationVersion() {
+				service.createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION);
 
-				verify(remoteService).createCommand(command, ITEM_NAME);
+				verify(remoteService).createCommand(createCommandCaptor.capture(), eq(ITEM_NAME));
+				assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION);
 			}
 		}
 	}
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java
index 0cebc6cf3ae6aa0cc843a73ded18ab21614c22e0..84072f84de42653a03d1f050b6c20c2dd2f46d74 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java
@@ -13,7 +13,7 @@ public class CommandTestFactory {
 	public static final CommandOrder ORDER = CommandOrder.VORGANG_ANNEHMEN;
 
 	public static final String RELATION_ID = ForwardingTestFactory.ID;
-	public static final long VERSION = VorgangHeaderTestFactory.VERSION;
+	public static final long RELATION_VERSION = VorgangHeaderTestFactory.VERSION;
 
 	public static Command create() {
 		return createBuilder().build();
@@ -36,6 +36,7 @@ public class CommandTestFactory {
 		return CreateCommand.builder()
 				.vorgangId(VORGANG_ID)
 				.relationId(RELATION_ID)
+				.relationVersion(RELATION_VERSION)
 				.order(ORDER);
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java
index dd713bdae5e65d6ada50b375071cc6adefb25c4c..fb8a5c667c83e35d0b986946b6a2c45cb59116ff 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java
@@ -1,15 +1,20 @@
 package de.itvsh.goofy.common.user;
 
+import java.util.UUID;
+
 import de.itvsh.goofy.vorgang.ZustaendigeStelleTestFactory;
 
 public class GoofyUserTestFactory {
 
+	public static final UserId ID = UserId.from(UUID.randomUUID().toString());
+
 	public static GoofyUser create() {
 		return createBuilder().build();
 	}
 
 	public static GoofyUser.GoofyUserBuilder createBuilder() {
 		return GoofyUser.builder()
+				.id(ID)
 				.organisationseinheitId(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java
index 3eb84c3ec6ae60f487ba067875086369004b81bc..f9332017ddd6264e6dd06c77e9d5f6126fd40282 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java
@@ -1,14 +1,11 @@
 package de.itvsh.goofy.kommentar;
 
 import static de.itvsh.goofy.kommentar.KommentarCommandTestFactory.*;
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
-import java.util.UUID;
-
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -16,17 +13,14 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.springframework.http.MediaType;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import de.itvsh.goofy.common.command.CommandController.CommandByRelationController;
-import de.itvsh.goofy.common.command.CommandOrder;
 import de.itvsh.goofy.common.command.CommandTestFactory;
 import de.itvsh.goofy.common.command.CreateCommand;
-import de.itvsh.goofy.common.user.CurrentUserService;
-import de.itvsh.goofy.common.user.UserId;
 import de.itvsh.goofy.kommentar.KommentarCommandController.KommentarCommandByVorgangController;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
@@ -38,53 +32,37 @@ class KommentarCommandControllerTest {
 	@Nested
 	class TestCreateKommentarCommandByVorgang {
 
+		@Spy
 		@InjectMocks
 		private KommentarCommandByVorgangController controller;
 		@Mock
 		private KommentarService service;
-		@Mock
-		private CommandByRelationController commandByRelationController;
-		@Mock
-		private CurrentUserService userService;
 
 		private MockMvc mockMvc;
 
 		@BeforeEach
 		void init() {
 			mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
-			when(userService.getUserId()).thenReturn(UserId.from(UUID.randomUUID()));
-			when(commandByRelationController.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create());
-		}
 
-		@Test
-		void shouldReturnCreated() throws Exception {
-			doRequest().andExpect(status().isCreated());
+			when(service.createKommentar(any(), any())).thenReturn(CommandTestFactory.create());
 		}
 
 		@Test
 		void shouldCallService() throws Exception {
 			doRequest();
 
-			verify(commandByRelationController).createCommand(any(), eq(KommentarRemoteService.ITEM_NAME));
+			verify(service).createKommentar(any(Kommentar.class), eq(VorgangHeaderTestFactory.ID));
 		}
 
 		@Test
-		void shouldGiveCommandToService() throws Exception {
-			doRequest();
-
-			verify(commandByRelationController).createCommand(commandCaptor.capture(), anyString());
-			var command = commandCaptor.getValue();
-
-			assertThat(command).usingRecursiveComparison()
-					.ignoringFields("body", "status")
-					.isEqualTo(CommandTestFactory.createBuilder().order(CommandOrder.CREATE_ATTACHED_ITEM)
-							.relationId(KommentarCommandController.NOT_SET)
-							.id(null).build());
+		void shouldReturnCreated() throws Exception {
+			doRequest().andExpect(status().isCreated());
 		}
 
 		private ResultActions doRequest() throws Exception {
-			return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID)
-					.content(createValidRequestContent()).contentType(MediaType.APPLICATION_JSON))
+			return mockMvc.perform(
+					post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID)
+							.content(createValidRequestContent()).contentType(MediaType.APPLICATION_JSON))
 					.andExpect(status().is2xxSuccessful());
 		}
 	}
@@ -92,13 +70,12 @@ class KommentarCommandControllerTest {
 	@Nested
 	class TestCreateEditKommentarCommand {
 
-		final String REPONSE_HEADER = "http://localhost/api/commands/" + KommentarCommandTestFactory.ID;
+		private final static String REPONSE_HEADER = "http://localhost/api/commands/" + KommentarCommandTestFactory.ID;
 
+		@Spy
 		@InjectMocks
 		private KommentarCommandController controller;
 		@Mock
-		private CommandByRelationController commandByRelationController;
-		@Mock
 		private KommentarService service;
 
 		private MockMvc mockMvc;
@@ -106,34 +83,20 @@ class KommentarCommandControllerTest {
 		@BeforeEach
 		void init() {
 			mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
-			when(commandByRelationController.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create());
-			when(service.getById(any())).thenReturn(KommentarTestFactory.createBuilder().vorgangId(VorgangHeaderTestFactory.ID).build());
-		}
 
-		@Test
-		void shouldReturnCreated() throws Exception {
-			doRequest().andExpect(status().isCreated());
+			when(service.editKommentar(any(), any(), anyLong())).thenReturn(CommandTestFactory.create());
 		}
 
 		@Test
 		void shouldCallService() throws Exception {
 			doRequest();
 
-			verify(service).getById(any());
+			verify(service).editKommentar(any(Kommentar.class), eq(KommentarTestFactory.ID), eq(KommentarTestFactory.VERSION));
 		}
 
 		@Test
-		void shouldGiveCommandToService() throws Exception {
-			doRequest();
-
-			verify(commandByRelationController).createCommand(commandCaptor.capture(), anyString());
-			var command = commandCaptor.getValue();
-
-			assertThat(command).usingRecursiveComparison()
-					.ignoringFields("body", "status")
-					.isEqualTo(CommandTestFactory.createBuilder().order(CommandOrder.UPDATE_ATTACHED_ITEM)
-							.relationId(KommentarCommandController.NOT_SET).id(null)
-							.build());
+		void shouldReturnCreated() throws Exception {
+			doRequest().andExpect(status().isCreated());
 		}
 
 		@Test
@@ -143,7 +106,7 @@ class KommentarCommandControllerTest {
 
 		ResultActions doRequest() throws Exception {
 			String content = createValidRequestContent();
-			return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID)
+			return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID, KommentarTestFactory.VERSION)
 					.content(content).contentType(MediaType.APPLICATION_JSON))
 					.andExpect(status().is2xxSuccessful());
 		}
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java
index 37c96c2c937358f455fab7fcc967503267cf42ab..ef360511deca6b6b066d4e30a18be240a536be03 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java
@@ -46,14 +46,14 @@ class KommentarCommandITCase {
 		@BeforeEach
 		void initTest() {
 			when(remoteService.getById(any())).thenReturn(KommentarTestFactory.create());
-			when(commandRemoteService.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create());
+			when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create());
 		}
 
 		@Test
 		void shouldCreateCommand() throws Exception {
 			doRequestByKommentarId(createValidRequestContent()).andExpect(status().isCreated());
 
-			verify(commandRemoteService).createCommand(any(), eq(KommentarRemoteService.ITEM_NAME));
+			verify(commandRemoteService).createCommand(any());
 		}
 
 		@WithMockUser
@@ -68,7 +68,7 @@ class KommentarCommandITCase {
 
 				doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.text"))
+						.andExpect(jsonPath("$.issues.[0].field").value("kommentar.text"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
@@ -78,7 +78,7 @@ class KommentarCommandITCase {
 				String content = buildContentWithText(StringUtils.EMPTY);
 
 				doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity())
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.text"));
+						.andExpect(jsonPath("$.issues.[0].field").value("kommentar.text"));
 
 			}
 
@@ -100,7 +100,7 @@ class KommentarCommandITCase {
 		}
 
 		private ResultActions doRequestByKommentarId(String content) throws Exception {
-			return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID)
+			return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID, KommentarTestFactory.VERSION)
 					.contentType(MediaType.APPLICATION_JSON)
 					.content(content));
 		}
@@ -110,17 +110,19 @@ class KommentarCommandITCase {
 	@Nested
 	class TestCreateCommandByVorgangId {
 
+		private static final long RELATION_ID_ON_CREATE = -1;
+
 		@BeforeEach
 		void initTest() {
 			when(remoteService.getById(any())).thenReturn(KommentarTestFactory.create());
-			when(commandRemoteService.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create());
+			when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create());
 		}
 
 		@Test
 		void shouldCreateCommand() throws Exception {
 			doRequestByVorgangId(createValidRequestContent()).andExpect(status().isCreated());
 
-			verify(commandRemoteService).createCommand(any(), eq(KommentarRemoteService.ITEM_NAME));
+			verify(commandRemoteService).createCommand(any());
 		}
 
 		@WithMockUser
@@ -135,7 +137,7 @@ class KommentarCommandITCase {
 
 				doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.text"))
+						.andExpect(jsonPath("$.issues.[0].field").value("kommentar.text"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
@@ -145,7 +147,7 @@ class KommentarCommandITCase {
 				String content = buildContentWithText(StringUtils.EMPTY);
 
 				doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity())
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.text"));
+						.andExpect(jsonPath("$.issues.[0].field").value("kommentar.text"));
 
 			}
 
@@ -167,9 +169,10 @@ class KommentarCommandITCase {
 		}
 
 		private ResultActions doRequestByVorgangId(String content) throws Exception {
-			return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID)
-					.contentType(MediaType.APPLICATION_JSON)
-					.content(content));
+			return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID,
+					RELATION_ID_ON_CREATE)
+							.contentType(MediaType.APPLICATION_JSON)
+							.content(content));
 		}
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java
index 74380e47bbbb5e6315f72c9cac7853d6aaf961a2..b059c5ec3dd1177dfd22673b6aa73594abf671e5 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java
@@ -1,17 +1,58 @@
 package de.itvsh.goofy.kommentar;
 
-import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
 
+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.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import static org.assertj.core.api.Assertions.*;
+
+import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory;
+import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 
 class KommentarMapperTest {
 
+	@Spy
+	@InjectMocks
 	private KommentarMapper mapper = Mappers.getMapper(KommentarMapper.class);
+	@Mock
+	private GrpcObjectMapper grpcObjectMapper;
 
+	@DisplayName("Map from item")
+	@Nested
+	class TestFromItem {
+
+		@BeforeEach
+		void mockMapper() {
+			when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(KommentarTestFactory.createAsMap());
+		}
+
+		@Test
+		void shouldCallGrpcObjectMapper() {
+			mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create());
+
+			verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM);
+		}
+
+		@Test
+		void shouldCallMapperFromItemMap() {
+			mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create());
+
+			verify(mapper).fromItemMap(KommentarTestFactory.createAsMap(), KommentarTestFactory.VERSION);
+		}
+	}
+
+	@DisplayName("Map from item map")
 	@Nested
 	class TestFromItemMap {
+
 		@Test
 		void shouldMapId() {
 			var kommentar = map();
@@ -19,6 +60,13 @@ class KommentarMapperTest {
 			assertThat(kommentar.getId()).isEqualTo(KommentarTestFactory.ID);
 		}
 
+		@Test
+		void shouldMapVersion() {
+			var kommentar = map();
+
+			assertThat(kommentar.getVersion()).isEqualTo(KommentarTestFactory.VERSION);
+		}
+
 		@Test
 		void shouldMapCreatedBy() {
 			var kommentar = map();
@@ -42,6 +90,6 @@ class KommentarMapperTest {
 	}
 
 	private Kommentar map() {
-		return mapper.fromItemMap(KommentarTestFactory.createAsMap());
+		return mapper.fromItemMap(KommentarTestFactory.createAsMap(), KommentarTestFactory.VERSION);
 	}
 }
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java
index 250e85a35dc78caf6645cf7119933390e194a127..9e605466c1e115ca671e7152d75376ba46ada19d 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java
@@ -1,7 +1,5 @@
 package de.itvsh.goofy.kommentar;
 
-import static org.assertj.core.api.Assertions.*;
-
 import java.util.Collections;
 
 import org.junit.jupiter.api.Nested;
@@ -13,6 +11,8 @@ import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.Link;
 import org.springframework.hateoas.server.EntityLinks;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.user.UserProfileTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
@@ -31,7 +31,9 @@ class KommentarModelAssemblerTest {
 	class TestLinksOnModel {
 
 		final String COMMAND_BY_KOMMENTAR_PATH = //
-				KommentarCommandController.KOMMENTAR_COMMANDS.replace("{kommentarId}", KommentarTestFactory.ID);
+				KommentarCommandController.KOMMENTAR_COMMANDS
+						.replace("{kommentarId}", KommentarTestFactory.ID)
+						.replace("{kommentarVersion}", String.valueOf(KommentarTestFactory.VERSION));
 
 		@Test
 		void shouldHaveSelfLink() {
@@ -73,7 +75,8 @@ class KommentarModelAssemblerTest {
 			var link = collectionModel.getLink(KommentarModelAssembler.REL_CREATE);
 
 			assertThat(link).isPresent();
-			assertThat(link.get().getHref()).isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/kommentarCommands");
+			assertThat(link.get().getHref()).isEqualTo(
+					"/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/kommentarCommands");
 		}
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java
index 6b8c32c2b10a75d57a416b112e405f229cc339cd..364b8af57e85a8873ad4f58d55988c094d21b392 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
 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.InjectMocks;
@@ -14,7 +15,6 @@ import org.mockito.Spy;
 
 import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
 import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
 import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem;
@@ -27,24 +27,23 @@ class KommentarRemoteServiceTest {
 	@Spy
 	@InjectMocks
 	private KommentarRemoteService service;
-
 	@Mock
 	private VorgangAttachedItemServiceBlockingStub vorgangAttachedItemServiceStub;
 	@Mock
 	private KommentarMapper mapper;
-	@Mock
-	private GrpcObjectMapper grpcObjectMapper;
 
 	private GrpcVorgangAttachedItem kommentar = GrpcVorgangAttachedItemTestFactory.create();
 
+	@DisplayName("Find by vorgangId")
 	@Nested
 	class TestFindByVorgangId {
 
 		private GrpcFindVorgangAttachedItemRequest request = GrpcFindVorgangAttachedItemRequest.newBuilder()
-				.setVorgangId(VorgangHeaderTestFactory.ID).setItemName(KommentarRemoteService.ITEM_NAME).build();
+				.setVorgangId(VorgangHeaderTestFactory.ID)
+				.setItemName(KommentarRemoteService.ITEM_NAME)
+				.build();
 		private GrpcFindVorgangAttachedItemResponse response = GrpcFindVorgangAttachedItemResponse.newBuilder()
 				.clearVorgangAttachedItems()
-				.addVorgangAttachedItems(kommentar)
 				.addVorgangAttachedItems(kommentar).build();
 
 		@BeforeEach
@@ -61,10 +60,10 @@ class KommentarRemoteServiceTest {
 
 		@Test
 		void shouldCallMapper() {
-			Stream<Kommentar> result = service.findByVorgangId(VorgangHeaderTestFactory.ID);
+			var result = service.findByVorgangId(VorgangHeaderTestFactory.ID);
 			collectStreamElementsToTriggerLazyStream(result);
 
-			verify(mapper, times(2)).fromItemMap(any());
+			verify(mapper).fromItem(any());
 		}
 
 		private void collectStreamElementsToTriggerLazyStream(Stream<Kommentar> stream) {
@@ -72,17 +71,20 @@ class KommentarRemoteServiceTest {
 		}
 	}
 
+	@DisplayName("Find by id")
 	@Nested
 	class TestGetById {
-		GrpcVorgangAttachedItemResponse response = GrpcVorgangAttachedItemResponse.newBuilder()
-				.setVorgangAttachedItem(GrpcVorgangAttachedItemTestFactory.create()).build();
-		GrpcVorgangAttachedItemRequest request = GrpcVorgangAttachedItemRequest.newBuilder().setId(KommentarTestFactory.ID).build();
+		private GrpcVorgangAttachedItemResponse response = GrpcVorgangAttachedItemResponse.newBuilder()
+				.setVorgangAttachedItem(GrpcVorgangAttachedItemTestFactory.create())
+				.build();
+		private GrpcVorgangAttachedItemRequest request = GrpcVorgangAttachedItemRequest.newBuilder()
+				.setId(KommentarTestFactory.ID)
+				.build();
 
 		@BeforeEach
 		void mockStub() {
 			when(vorgangAttachedItemServiceStub.getById(any())).thenReturn(response);
-			when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(KommentarTestFactory.createAsMap());
-			when(mapper.fromItemMap(any())).thenReturn(KommentarTestFactory.create());
+			when(mapper.fromItem(any())).thenReturn(KommentarTestFactory.create());
 		}
 
 		@Test
@@ -96,7 +98,7 @@ class KommentarRemoteServiceTest {
 		void shouldCallMapper() {
 			service.getById(KommentarTestFactory.ID);
 
-			verify(mapper).fromItemMap(any());
+			verify(mapper).fromItem(any());
 		}
 	}
 }
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java
index d7193d38b9d8ba7ae8385d7e2414f0e42a2d45e8..ab903893f2acdc5e4566c6606bf40c432388a609 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java
@@ -1,21 +1,145 @@
 package de.itvsh.goofy.kommentar;
 
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+
+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 static org.assertj.core.api.Assertions.*;
 
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService;
+import de.itvsh.goofy.common.command.Command;
+import de.itvsh.goofy.common.command.CommandTestFactory;
+import de.itvsh.goofy.common.user.CurrentUserService;
+import de.itvsh.goofy.common.user.GoofyUserTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
 class KommentarServiceTest {
 
+	@Spy
 	@InjectMocks
 	private KommentarService service;
-
 	@Mock
 	private KommentarRemoteService remoteService;
+	@Mock
+	private VorgangAttachedItemService vorgangAttachedItemService;
+	@Mock
+	private CurrentUserService currentUserService;
+
+	@DisplayName("Create kommentar")
+	@Nested
+	class TestCreateKommentar {
+
+		@DisplayName("should")
+		@Nested
+		class TestCalls {
+
+			@BeforeEach
+			void mockServices() {
+				doReturn(KommentarTestFactory.create()).when(service).addCreated(any());
+				when(vorgangAttachedItemService.createNewKommentar(any(), any())).thenReturn(CommandTestFactory.create());
+			}
+
+			@DisplayName("add created")
+			@Test
+			void shouldAddCreated() {
+				callCreateKommentar();
+
+				verify(service).addCreated(any(Kommentar.class));
+			}
+
+			@DisplayName("call vorgangattacheditem service")
+			@Test
+			void shouldCallVorgangAttachedItemService() {
+				callCreateKommentar();
+
+				verify(vorgangAttachedItemService).createNewKommentar(any(Kommentar.class), eq(VorgangHeaderTestFactory.ID));
+			}
+		}
+
+		@DisplayName("Add created")
+		@Nested
+		class TestAddCreated {
+
+			@BeforeEach
+			void mockServices() {
+				when(currentUserService.getUserId()).thenReturn(GoofyUserTestFactory.ID);
+			}
+
+			@Test
+			void shouldSetCreatedAt() throws Exception {
+				var kommentar = callAddCreated();
+
+				assertThat(kommentar.getCreatedAt()).isNotNull().isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
+			}
+
+			@Test
+			void shouldSetCreatedBy() throws Exception {
+				var kommentar = callAddCreated();
+
+				assertThat(kommentar.getCreatedBy()).isEqualTo(GoofyUserTestFactory.ID.toString());
+			}
+
+			private Kommentar callAddCreated() {
+				return service.addCreated(KommentarTestFactory.createBuilder().createdAt(null).createdBy(null).build());
+			}
+		}
+
+		private Command callCreateKommentar() {
+			return service.createKommentar(KommentarTestFactory.create(), VorgangHeaderTestFactory.ID);
+		}
+	}
+
+	@DisplayName("Edit kommentar")
+	@Nested
+	class TestEditKommentar {
+
+		@Captor
+		private ArgumentCaptor<Kommentar> kommentarCaptor;
+
+		@BeforeEach
+		void mockKommentarService() {
+			when(remoteService.getById(anyString())).thenReturn(KommentarTestFactory.createBuilder().text("text needs to be override").build());
+		}
+
+		@Test
+		void shouldCallGetById() {
+			callEditKommentar();
+
+			verify(service).getById(KommentarTestFactory.ID);
+		}
+
+		@Test
+		void shouldReplaceText() {
+			callEditKommentar();
+
+			verify(vorgangAttachedItemService).editKommentar(kommentarCaptor.capture(), eq(KommentarTestFactory.ID),
+					eq(KommentarTestFactory.VERSION));
+			assertThat(kommentarCaptor.getValue().getText()).isEqualTo(KommentarTestFactory.TEXT);
+		}
+
+		@Test
+		void shouldCallVorgangAttachedItemService() {
+			callEditKommentar();
+
+			verify(vorgangAttachedItemService).editKommentar(any(Kommentar.class), eq(KommentarTestFactory.ID), eq(KommentarTestFactory.VERSION));
+		}
+
+		private Command callEditKommentar() {
+			return service.editKommentar(KommentarTestFactory.create(), KommentarTestFactory.ID, KommentarTestFactory.VERSION);
+		}
+	}
 
 	@Nested
 	class TestGetById {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java
index 99abb0b24b22ca5ab6743ae4de507409dfdf0995..aee4801acc0698a5b90c1e4994552608fae227b5 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java
@@ -8,12 +8,14 @@ import com.thedeanda.lorem.Lorem;
 import com.thedeanda.lorem.LoremIpsum;
 
 import de.itvsh.goofy.common.user.UserProfileTestFactory;
+import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
 public class KommentarTestFactory {
 
 	private static Lorem lorem = LoremIpsum.getInstance();
 
 	public static final String ID = UUID.randomUUID().toString();
+	public static final long VERSION = 73;
 
 	public static final String CREATED_BY = UserProfileTestFactory.ID.toString();
 	public static final String CREATED_AT_STR = "2021-01-10T10:30:00Z";
@@ -28,6 +30,8 @@ public class KommentarTestFactory {
 	public static Kommentar.KommentarBuilder createBuilder() {
 		return Kommentar.builder()
 				.id(ID)
+				.vorgangId(VorgangHeaderTestFactory.ID)
+				.version(VERSION)
 				.text(TEXT)
 				.createdBy(CREATED_BY)
 				.createdAt(CREATED_AT);
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java
index dc3c4932db2382e4713c473d9fbcdb2980fd1ed7..77f85fb625a2744ebe45085cd8731efaf93104c1 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java
@@ -8,6 +8,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import org.junit.jupiter.api.BeforeEach;
 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.springframework.http.MediaType;
@@ -40,9 +42,19 @@ class PostfachMailCommandControllerTest {
 	@Nested
 	class TestCreateCommand {
 
+		@Captor
+		private ArgumentCaptor<CreateCommand> createCommandCaptor;
+
 		@BeforeEach
 		void mockController() {
-			when(commandByRelationController.createCommand(any(CreateCommand.class), anyLong())).thenReturn(CommandTestFactory.create());
+			when(commandByRelationController.createCommandWithoutRelation(any(CreateCommand.class))).thenReturn(CommandTestFactory.create());
+		}
+
+		@Test
+		void shouldCallCommandByRelationController() throws Exception {
+			doRequest();
+
+			verify(commandByRelationController).createCommandWithoutRelation(createCommandCaptor.capture());
 		}
 
 		@Test
@@ -63,13 +75,4 @@ class PostfachMailCommandControllerTest {
 					.content(PostfachMailTestFactory.buildResendPostfachMailContent()));
 		}
 	}
-
-	@Test
-	void shouldCallCommandByRelationController() {
-		var createCommand = CommandTestFactory.createCreateCommand();
-
-		controller.createCommand(createCommand);
-
-		verify(commandByRelationController).createCommand(createCommand, -1);
-	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java
index 78b56c924b1bd1f4991f47d5bfc40cb3c5b0704a..216ba59a1db199deb47cbdf31d9f6b8189c50ce7 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java
@@ -15,6 +15,7 @@ public class GrpcVorgangAttachedItemTestFactory {
 	public final static String ITEM_NAME = LoremIpsum.getInstance().getWords(1);
 	public final static String ITEM_KEY = LoremIpsum.getInstance().getWords(1);
 	public final static String ITEM_VALUE = LoremIpsum.getInstance().getWords(1);
+	public final static long VERSION = 73;
 
 	public static final GrpcObject ITEM = GrpcObject.newBuilder()
 			.addProperty(GrpcProperty.newBuilder()
@@ -33,6 +34,7 @@ public class GrpcVorgangAttachedItemTestFactory {
 				.setClient(CLIENT)
 				.setVorgangId(VorgangHeaderTestFactory.ID)
 				.setItemName(ITEM_NAME)
-				.setItem(ITEM);
+				.setItem(ITEM)
+				.setVersion(VERSION);
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java
index 2c34ae5ee0a1ae740a3510031d6427eac5a2ffeb..54a15a5328b13dfe251e5a7afe6ca9935655978c 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java
@@ -1,11 +1,9 @@
 package de.itvsh.goofy.vorgang.command;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Collections;
-import java.util.Optional;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
@@ -22,6 +20,8 @@ import org.springframework.hateoas.Link;
 import org.springframework.hateoas.LinkRelation;
 import org.springframework.security.test.context.support.WithMockUser;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.command.CommandController;
 import de.itvsh.goofy.common.user.CurrentUserService;
 import de.itvsh.goofy.common.user.UserRole;
@@ -187,31 +187,4 @@ class VorgangWithEingangCommandProzessorTest {
 					.isEqualTo("/api/commands?pending=true&vorgangId=" + VorgangHeaderTestFactory.ID);
 		}
 	}
-
-	@Nested
-	class TestCreateWiedervorlageLink {
-
-		@Test
-		void shouldHaveCreateWiedervorlageLink() {
-			when(userService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(true);
-			when(userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(false);
-
-			EntityModel<VorgangWithEingang> model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create()));
-			var link = model.getLink(VorgangWithEingangCommandProzessor.REL_CREATE_WIEDERVORLAGE);
-
-			assertThat(link).isPresent().get().extracting(Link::getHref)
-					.isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/wiedervorlageCommands");
-		}
-
-		@Test
-		void shouldNotHaveCreateWiedervorlageLink() {
-			when(userService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(false);
-			when(userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(false);
-
-			Optional<Link> model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create()))
-					.getLink(VorgangWithEingangCommandProzessor.REL_CREATE_WIEDERVORLAGE);
-
-			assertThat(model).isNotPresent();
-		}
-	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java
index 1bfc0085bc36578ff105d9ecac9a2b788f3b39fc..d15a8312ffff46ba61638a047f00a14df3768072 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java
@@ -1,14 +1,10 @@
 package de.itvsh.goofy.wiedervorlage;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
-import java.time.ZonedDateTime;
-import java.time.temporal.ChronoUnit;
-
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -23,14 +19,10 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import de.itvsh.goofy.common.binaryfile.BinaryFileTestFactory;
-import de.itvsh.goofy.common.binaryfile.FileId;
 import de.itvsh.goofy.common.command.CommandController.CommandByRelationController;
-import de.itvsh.goofy.common.command.CommandOrder;
 import de.itvsh.goofy.common.command.CommandTestFactory;
 import de.itvsh.goofy.common.command.CreateCommand;
 import de.itvsh.goofy.common.user.CurrentUserService;
-import de.itvsh.goofy.common.user.UserTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 import de.itvsh.goofy.wiedervorlage.WiedervorlageCommandController.WiedervorlageCommandByVorgangController;
 
@@ -61,23 +53,17 @@ class WiedervorlageCommandByVorgangControllerTest {
 
 		@BeforeEach
 		void mockUserService() {
-			when(userService.getUserId()).thenReturn(UserTestFactory.ID);
+			when(service.createWiedervorlage(any(), any())).thenReturn(CommandTestFactory.create());
 		}
 
 		@Nested
 		class ServiceMethod {
 
-			@BeforeEach
-			void initMocks() {
-				when(commandByRelationController.createCommand(any(), any())).thenReturn(CommandTestFactory.create());
-			}
-
 			@Test
-			void shouldCallCommandByRelationController() throws Exception {
+			void shouldCallService() throws Exception {
 				doRequest();
 
-				verify(commandByRelationController).createCommand(any(CreateCommand.class),
-						eq(WiedervorlageRemoteService.ITEM_NAME));
+				verify(service).createWiedervorlage(any(Wiedervorlage.class), eq(VorgangHeaderTestFactory.ID));
 			}
 
 			@Test
@@ -92,75 +78,6 @@ class WiedervorlageCommandByVorgangControllerTest {
 				doRequest().andExpect(status().isCreated());
 			}
 		}
-
-		@Nested
-		class BuildCreateCommand {
-
-			@Test
-			void shouldContainsOrder() throws Exception {
-				var createCommand = buildCommand();
-
-				assertThat(createCommand.getOrder()).isEqualTo(CommandOrder.CREATE_ATTACHED_ITEM);
-			}
-
-			@Test
-			void shouldContainsVorgangId() throws Exception {
-				var createCommand = buildCommand();
-
-				assertThat(createCommand.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID);
-			}
-
-			@Test
-			void shouldContainsBody() throws Exception {
-				var createCommand = buildCommand();
-
-				assertThat(((Wiedervorlage) createCommand.getBody())).usingRecursiveComparison().ignoringFields("createdAt", "createdBy")
-						.isEqualTo(WiedervorlageTestFactory.create());
-			}
-
-			private CreateCommand buildCommand() {
-				return controller.buildCommand(VorgangHeaderTestFactory.ID, WiedervorlageCommandTestFactory.create());
-			}
-		}
-
-		@Nested
-		class BuildBody {
-
-			private final Wiedervorlage wiedervorlage = WiedervorlageTestFactory.create();
-
-			@Test
-			void shouldSetCreatedAt() {
-				var enrichedWiedervorlage = buildBody(wiedervorlage.toBuilder().createdAt(null).build());
-
-				assertThat(enrichedWiedervorlage.getCreatedAt()).isCloseTo(ZonedDateTime.now().withNano(0),
-						within(2, ChronoUnit.SECONDS));
-			}
-
-			@Test
-			void shouldSetCreatedBy() {
-				var enrichedWiedervorlage = buildBody(wiedervorlage.toBuilder().createdBy(null).build());
-
-				assertThat(enrichedWiedervorlage.getCreatedBy()).isEqualTo(UserTestFactory.ID.toString());
-			}
-
-			@Nested
-			class StripAttachmentFileUriToId {
-
-				@Test
-				void shouldStripFileUriToFileId() {
-					var fileIdAsUri = FileId.from("api/irgendwas/dazwischen/" + BinaryFileTestFactory.ID);
-					var wiedervorlageWithAttachmentAsFileUri = WiedervorlageTestFactory.createBuilder().attachment(fileIdAsUri).build();
-
-					var wiedervorlage = buildBody(wiedervorlageWithAttachmentAsFileUri);
-
-					assertThat(wiedervorlage.getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID);
-				}
-			}
-
-			private Wiedervorlage buildBody(Wiedervorlage wiedervorlage) {
-				return controller.buildBody(wiedervorlage);
-			}
-		}
 	}
 
 	private ResultActions doRequest() throws Exception {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java
index 3e1834ad47c6dc23488c91e236b0717e2305228e..892c2c68b614fa0c57f8b1b17645a2310e1645ea 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java
@@ -1,6 +1,5 @@
 package de.itvsh.goofy.wiedervorlage;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -20,7 +19,10 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.binaryfile.BinaryFileTestFactory;
+import de.itvsh.goofy.common.binaryfile.FileId;
 import de.itvsh.goofy.common.command.Command;
 import de.itvsh.goofy.common.command.CommandController.CommandByRelationController;
 import de.itvsh.goofy.common.command.CommandOrder;
@@ -95,9 +97,17 @@ class WiedervorlageCommandControllerTest {
 				doRequest().andExpect(header().string("Location", RESPONSE_HEADER));
 			}
 
+			@Test
+			void shouldBuildCommand() throws Exception {
+				doRequest();
+
+				verify(controller).buildCommand(any(Wiedervorlage.class), any(WiedervorlageCommand.class), eq(WiedervorlageTestFactory.VERSION));
+			}
+
 			private ResultActions doRequest() throws Exception {
-				return mockMvc.perform(post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID)
-						.content(WiedervorlageCommandTestFactory.createValidRequestContent()).contentType(MediaType.APPLICATION_JSON))
+				return mockMvc.perform(
+						post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION)
+								.content(WiedervorlageCommandTestFactory.createValidRequestContent()).contentType(MediaType.APPLICATION_JSON))
 						.andExpect(status().is2xxSuccessful());
 			}
 		}
@@ -116,7 +126,14 @@ class WiedervorlageCommandControllerTest {
 			void shouldHaveRelationId() {
 				var command = callBuildCommand();
 
-				assertThat(command.getRelationId()).isEqualTo(WiedervorlageCommandController.NOT_SET);
+				assertThat(command.getRelationId()).isEqualTo(WiedervorlageTestFactory.ID);
+			}
+
+			@Test
+			void shouldHaveRelationVersion() {
+				var command = callBuildCommand();
+
+				assertThat(command.getRelationVersion()).isEqualTo(WiedervorlageTestFactory.VERSION);
 			}
 
 			@Test
@@ -216,7 +233,7 @@ class WiedervorlageCommandControllerTest {
 			}
 
 			CreateCommand callBuildCommand(WiedervorlageCommand command) {
-				return controller.buildCommand(WiedervorlageTestFactory.create(), command);
+				return controller.buildCommand(WiedervorlageTestFactory.create(), command, WiedervorlageTestFactory.VERSION);
 			}
 		}
 
@@ -230,7 +247,8 @@ class WiedervorlageCommandControllerTest {
 				void shouldCallCreateCommand() {
 					createCommandByOrder(CommandOrder.EDIT_WIEDERVORLAGE);
 
-					verify(commandByRelationController).createCommand(any(), eq(WiedervorlageRemoteService.ITEM_NAME));
+					verify(service).editWiedervorlage(any(Wiedervorlage.class), eq(CommandTestFactory.RELATION_ID),
+							eq(CommandTestFactory.RELATION_VERSION));
 				}
 			}
 
@@ -241,7 +259,8 @@ class WiedervorlageCommandControllerTest {
 				void shouldCallCreateCommandWithoutValidation() {
 					createCommandByOrder(CommandOrder.WIEDERVORLAGE_ERLEDIGEN);
 
-					verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME));
+					verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME),
+							eq(CommandTestFactory.RELATION_VERSION));
 				}
 			}
 
@@ -252,13 +271,29 @@ class WiedervorlageCommandControllerTest {
 				void shouldCallCreateCommandWithoutValidation() {
 					createCommandByOrder(CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN);
 
-					verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME));
+					verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME),
+							eq(CommandTestFactory.RELATION_VERSION));
 				}
 			}
 
 			private Command createCommandByOrder(CommandOrder order) {
-				return controller.createByOrder(CommandTestFactory.createCreateCommand(), order);
+				return controller.createByOrder(
+						CommandTestFactory.createCreateCommandBuilder().body(WiedervorlageTestFactory.create()).build(), order);
 			}
 		}
 	}
+
+	@Nested
+	class StripAttachmentFileUriToId {
+
+		@Test
+		void shouldStripFileUriToFileId() {
+			var fileIdAsUri = FileId.from("api/irgendwas/dazwischen/" + BinaryFileTestFactory.ID);
+			var wiedervorlageWithAttachmentAsFileUri = WiedervorlageTestFactory.createBuilder().attachment(fileIdAsUri).build();
+
+			var wiedervorlage = WiedervorlageCommandController.stripAttachmentFileUriToId(wiedervorlageWithAttachmentAsFileUri);
+
+			assertThat(wiedervorlage.getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID);
+		}
+	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java
index 145aa620085692c67cf8f5a5739e69ed4e9b5c16..b4271cc9c0001e0b8046a0ba66186097fa46025d 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java
@@ -71,7 +71,7 @@ class WiedervorlageCommandITCase {
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff"))
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
@@ -81,7 +81,7 @@ class WiedervorlageCommandITCase {
 				String content = buildContentWithBetreff("a");
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff"));
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff"));
 
 			}
 
@@ -112,7 +112,7 @@ class WiedervorlageCommandITCase {
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.frist"))
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_DATE_PAST));
 			}
 
@@ -123,7 +123,7 @@ class WiedervorlageCommandITCase {
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.frist"))
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
@@ -134,9 +134,10 @@ class WiedervorlageCommandITCase {
 		}
 
 		private ResultActions doRequest(String content) throws Exception {
-			return mockMvc.perform(post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID)
-					.contentType(MediaType.APPLICATION_JSON)
-					.content(content));
+			return mockMvc.perform(
+					post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION)
+							.contentType(MediaType.APPLICATION_JSON)
+							.content(content));
 		}
 	}
 
@@ -145,9 +146,11 @@ class WiedervorlageCommandITCase {
 	@Nested
 	class TestCreateCreateCommand {
 
+		private static final long RELATION_ID_ON_CREATE = -1;
+
 		@BeforeEach
 		void initTest() {
-			when(commandRemoteService.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create());
+			when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create());
 			when(wiedervorlageRemoteService.getById(anyString())).thenReturn(WiedervorlageTestFactory.create());
 		}
 
@@ -155,7 +158,7 @@ class WiedervorlageCommandITCase {
 		void shouldCreateCommand() throws Exception {
 			doRequest(createValidRequestContent()).andExpect(status().isCreated());
 
-			verify(commandRemoteService).createCommand(any(), anyString());
+			verify(commandRemoteService).createCommand(any());
 		}
 
 		@WithMockUser
@@ -170,7 +173,7 @@ class WiedervorlageCommandITCase {
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff"))
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
@@ -180,7 +183,7 @@ class WiedervorlageCommandITCase {
 				String content = buildContentWithBetreff("a");
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff"));
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff"));
 
 			}
 
@@ -212,7 +215,7 @@ class WiedervorlageCommandITCase {
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.frist"))
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_DATE_PAST));
 			}
 
@@ -224,16 +227,17 @@ class WiedervorlageCommandITCase {
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
 						.andExpect(jsonPath("$.issues.length()").value(1))
-						.andExpect(jsonPath("$.issues.[0].field").value("command.body.frist"))
+						.andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist"))
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
 		}
 
 		private ResultActions doRequest(String content) throws Exception {
-			return mockMvc.perform(post(WiedervorlageCommandByVorgangController.WIEDERVORLAGE_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID)
-					.contentType(MediaType.APPLICATION_JSON)
-					.content(content));
+			return mockMvc.perform(post(WiedervorlageCommandByVorgangController.WIEDERVORLAGE_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID,
+					RELATION_ID_ON_CREATE)
+							.contentType(MediaType.APPLICATION_JSON)
+							.content(content));
 		}
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java
index c01ecfd503854baedb44893b6fd49692f3deb5cc..3b21f24d6a98eb7c2808706afdc8dcd35648ca81 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java
@@ -1,26 +1,62 @@
 package de.itvsh.goofy.wiedervorlage;
 
-import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
 
 import java.util.HashMap;
 import java.util.List;
 
+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.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
+import org.mockito.Mock;
 import org.mockito.Spy;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.binaryfile.BinaryFileTestFactory;
 import de.itvsh.goofy.common.binaryfile.FileIdMapper;
+import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory;
+import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 
 class WiedervorlageMapperTest {
 
+	@Spy
 	@InjectMocks
 	private WiedervorlageMapper mapper = Mappers.getMapper(WiedervorlageMapper.class);
 	@Spy
 	private FileIdMapper fileIdMapper = Mappers.getMapper(FileIdMapper.class);
+	@Mock
+	private GrpcObjectMapper grpcObjectMapper;
+
+	@DisplayName("Map from item")
+	@Nested
+	class TestFromItem {
+
+		@BeforeEach
+		void mockMapper() {
+			when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(WiedervorlageTestFactory.createAsMap());
+		}
+
+		@Test
+		void shouldCallGrpcObjectMapper() {
+			mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create());
+
+			verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM);
+		}
+
+		@Test
+		void shouldCallMapperFromItemMap() {
+			mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create());
+
+			verify(mapper).fromItemMap(WiedervorlageTestFactory.createAsMap(), GrpcVorgangAttachedItemTestFactory.VERSION);
+		}
+	}
 
+	@DisplayName("Map from item map")
 	@Nested
 	class TestFromItemMap {
 
@@ -31,6 +67,13 @@ class WiedervorlageMapperTest {
 			assertThat(wiedervorlage.getId()).isEqualTo(WiedervorlageTestFactory.ID);
 		}
 
+		@Test
+		void shouldMapVersion() {
+			var wiedervorlage = map();
+
+			assertThat(wiedervorlage.getVersion()).isEqualTo(WiedervorlageTestFactory.VERSION);
+		}
+
 		@Test
 		void shouldMapDone() {
 			var wiedervorlage = map();
@@ -82,7 +125,7 @@ class WiedervorlageMapperTest {
 				wiedervorlageWithoutAttachments.putAll(WiedervorlageTestFactory.createAsMap());
 				wiedervorlageWithoutAttachments.remove(WiedervorlageMapper.ATTACHMENTS);
 
-				var wiedervorlage = mapper.fromItemMap(wiedervorlageWithoutAttachments);
+				var wiedervorlage = mapper.fromItemMap(wiedervorlageWithoutAttachments, WiedervorlageTestFactory.VERSION);
 
 				assertThat(wiedervorlage.getAttachments()).isEmpty();
 			}
@@ -96,7 +139,7 @@ class WiedervorlageMapperTest {
 
 			@Test
 			void shouldMapAttachmentList() {
-				var wiedervorlage = mapper.fromItemMap(createWiedervorlageAsMapWithMultipleAttachments());
+				var wiedervorlage = mapper.fromItemMap(createWiedervorlageAsMapWithMultipleAttachments(), WiedervorlageTestFactory.VERSION);
 
 				assertThat(wiedervorlage.getAttachments()).hasSize(2);
 				assertThat(wiedervorlage.getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID);
@@ -112,7 +155,7 @@ class WiedervorlageMapperTest {
 		}
 
 		private Wiedervorlage map() {
-			return mapper.fromItemMap(WiedervorlageTestFactory.createAsMap());
+			return mapper.fromItemMap(WiedervorlageTestFactory.createAsMap(), WiedervorlageTestFactory.VERSION);
 		}
 	}
 }
\ No newline at end of file
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java
index 7aeb26900300ecbf2698e4b0b60000839e685274..9106cf6495d827777b93143782f93cdc6d52dd1e 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java
@@ -1,7 +1,5 @@
 package de.itvsh.goofy.wiedervorlage;
 
-import static org.assertj.core.api.Assertions.*;
-
 import java.util.Collections;
 
 import org.junit.jupiter.api.Nested;
@@ -12,6 +10,8 @@ import org.springframework.hateoas.EntityModel;
 import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.server.EntityLinks;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.file.OzgFileTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
@@ -28,8 +28,9 @@ class WiedervorlageModelAssemblerTest {
 	@Nested
 	class TestLinksOnModel {
 
-		private final String COMMAND_BY_WIEDERVORLAGE_PATH = WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS.replace("{wiedervorlageId}",
-				WiedervorlageTestFactory.ID);
+		private static final String COMMAND_BY_WIEDERVORLAGE_PATH = WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS
+				.replace("{wiedervorlageId}", WiedervorlageTestFactory.ID)
+				.replace("{wiedervorlageVersion}", String.valueOf(WiedervorlageTestFactory.VERSION));
 
 		@Test
 		void shouldHaveSelfLink() {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java
index ab6761aaee84a45d2ca86ffdf0051715abb25ea4..307fa72a02e549754a8dac1940e5bb4f38c5bd45 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java
@@ -1,6 +1,5 @@
 package de.itvsh.goofy.wiedervorlage;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
@@ -20,10 +19,11 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.context.ApplicationContext;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.ApplicationTestFactory;
 import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
 import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
 import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
 import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
@@ -47,8 +47,6 @@ class WiedervorlageRemoteServiceTest {
 	@Mock
 	private WiedervorlageMapper mapper;
 	@Mock
-	private GrpcObjectMapper grpcObjectMapper;
-	@Mock
 	private ApplicationContext applicationContext;
 
 	@Nested
@@ -78,21 +76,14 @@ class WiedervorlageRemoteServiceTest {
 
 				@BeforeEach
 				void mockGrpcMapper() {
-					when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(WiedervorlageTestFactory.createAsMap());
-				}
-
-				@Test
-				void shouldCallForGrpcObject() {
-					callFindById();
-
-					verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM);
+					when(mapper.fromItem(any())).thenReturn(WiedervorlageTestFactory.create());
 				}
 
 				@Test
 				void shouldCallForWiedervorlage() {
 					callFindById();
 
-					verify(mapper).fromItemMap(WiedervorlageTestFactory.createAsMap());
+					verify(mapper).fromItem(GrpcVorgangAttachedItemTestFactory.create());
 				}
 
 				private void callFindById() {
@@ -141,8 +132,7 @@ class WiedervorlageRemoteServiceTest {
 		@BeforeEach
 		void initMocks() {
 			when(vorgangAttachedItemServiceStub.getById(any())).thenReturn(response);
-			when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(WiedervorlageTestFactory.createAsMap());
-			when(mapper.fromItemMap(any())).thenReturn(WiedervorlageTestFactory.create());
+			when(mapper.fromItem(any())).thenReturn(WiedervorlageTestFactory.create());
 		}
 
 		@Test
@@ -152,18 +142,11 @@ class WiedervorlageRemoteServiceTest {
 			verify(vorgangAttachedItemServiceStub).getById(request);
 		}
 
-		@Test
-		void shouldCallGrpcObjectMapper() {
-			service.getById(WiedervorlageTestFactory.ID);
-
-			verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM);
-		}
-
 		@Test
 		void shouldCallWiedervorlageMapper() {
 			service.getById(WiedervorlageTestFactory.ID);
 
-			verify(mapper).fromItemMap(WiedervorlageTestFactory.createAsMap());
+			verify(mapper).fromItem(GrpcVorgangAttachedItemTestFactory.create());
 		}
 
 		@Test
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java
index 1609042fd1f5e58458f8dffa0dd91f1970e9c338..a3621a9d1f74a6170e124c36ad487de1520e733f 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java
@@ -1,22 +1,33 @@
 package de.itvsh.goofy.wiedervorlage;
 
-import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.time.LocalDate;
+import java.time.ZonedDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.Optional;
 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.ArgumentMatchers;
+import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
+import static org.assertj.core.api.Assertions.*;
+
+import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService;
+import de.itvsh.goofy.common.command.Command;
+import de.itvsh.goofy.common.command.CommandService;
+import de.itvsh.goofy.common.command.CommandTestFactory;
+import de.itvsh.goofy.common.user.CurrentUserService;
+import de.itvsh.goofy.common.user.GoofyUserTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
 class WiedervorlageServiceTest {
@@ -24,9 +35,98 @@ class WiedervorlageServiceTest {
 	@Spy
 	@InjectMocks
 	private WiedervorlageService service;
-
 	@Mock
 	private WiedervorlageRemoteService remoteService;
+	@Mock
+	private VorgangAttachedItemService vorgangAttachedItemService;
+	@Mock
+	private CommandService commandService;
+	@Mock
+	private CurrentUserService currentUserService;
+
+	@DisplayName("Create wiedervorlage")
+	@Nested
+	class TestCreateWiedervorlage {
+
+		@DisplayName("should")
+		@Nested
+		class TestCalls {
+
+			@BeforeEach
+			void mockServices() {
+				doReturn(WiedervorlageTestFactory.create()).when(service).addCreated(any());
+				when(vorgangAttachedItemService.createNewWiedervorlage(any(), any())).thenReturn(CommandTestFactory.create());
+			}
+
+			@DisplayName("add created")
+			@Test
+			void shouldAddCreated() {
+				callCreateWiedervorlage();
+
+				verify(service).addCreated(any(Wiedervorlage.class));
+			}
+
+			@DisplayName("call vorgangattacheditem service")
+			@Test
+			void shouldCallVorgangAttachedItemService() {
+				callCreateWiedervorlage();
+
+				verify(vorgangAttachedItemService).createNewWiedervorlage(any(Wiedervorlage.class), eq(VorgangHeaderTestFactory.ID));
+			}
+		}
+
+		@DisplayName("Add created")
+		@Nested
+		class TestAddCreated {
+
+			@BeforeEach
+			void mockServices() {
+				when(currentUserService.getUserId()).thenReturn(GoofyUserTestFactory.ID);
+			}
+
+			@Test
+			void shouldSetCreatedAt() throws Exception {
+				var wiedervorlage = callAddCreated();
+
+				assertThat(wiedervorlage.getCreatedAt()).isNotNull().isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
+			}
+
+			@Test
+			void shouldSetCreatedBy() throws Exception {
+				var wiedervorlage = callAddCreated();
+
+				assertThat(wiedervorlage.getCreatedBy()).isEqualTo(GoofyUserTestFactory.ID.toString());
+			}
+
+			private Wiedervorlage callAddCreated() {
+				return service.addCreated(WiedervorlageTestFactory.createBuilder().createdAt(null).createdBy(null).build());
+			}
+		}
+
+		private Command callCreateWiedervorlage() {
+			return service.createWiedervorlage(WiedervorlageTestFactory.create(), VorgangHeaderTestFactory.ID);
+		}
+	}
+
+	@DisplayName("Edit wiedervorlage")
+	@Nested
+	class TestEditWiedervorlage {
+
+		@Captor
+		private ArgumentCaptor<Wiedervorlage> wiedervorlageCaptor;
+
+		@Test
+		void shouldCallVorgangAttachedItemService() {
+			callEditWiedervorlage();
+
+			verify(vorgangAttachedItemService).editWiedervorlage(any(Wiedervorlage.class), eq(WiedervorlageTestFactory.ID),
+					eq(WiedervorlageTestFactory.VERSION));
+		}
+
+		private Command callEditWiedervorlage() {
+			return service.editWiedervorlage(WiedervorlageTestFactory.create(), WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION);
+		}
+	}
 
 	@Nested
 	class TestGetById {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java
index 70efe8c69be101ce3dceeb1fbd71e92a34630067..60a2d19554191e09fbab178d699cec4e078a2cfd 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java
@@ -13,7 +13,7 @@ import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 public class WiedervorlageTestFactory {
 
 	public static final String ID = UUID.randomUUID().toString();
-
+	public static final long VERSION = 73;
 	public static final boolean DONE = false;
 	public static final String CREATED_BY = UUID.randomUUID().toString();
 	public static final String CREATED_BY_NAME = LoremIpsum.getInstance().getName();
@@ -32,6 +32,7 @@ public class WiedervorlageTestFactory {
 	public static Wiedervorlage.WiedervorlageBuilder createBuilder() {
 		return Wiedervorlage.builder()
 				.id(ID)
+				.version(VERSION)
 				.done(DONE)
 				.betreff(BETREFF)
 				.beschreibung(BESCHREIBUNG)
diff --git a/pom.xml b/pom.xml
index d777589e440e5c9b114b123c98bd5de9706b6a01..c1ef0b7be4e8c3bcca6e7bf3c32d8fb63af4bb04 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,14 +5,14 @@
 
 	<groupId>de.itvsh.ozg</groupId>
 	<artifactId>goofy</artifactId>
-	<version>0.26.0-SNAPSHOT</version>
+	<version>0.27.0-SNAPSHOT</version>
 	<name>Goofy Parent</name>
 	<packaging>pom</packaging>
 
 	<parent>
 		<groupId>de.itvsh.kop.common</groupId>
 		<artifactId>kop-common-parent</artifactId>
-		<version>1.1.3-SNAPSHOT</version>
+		<version>1.1.3</version>
 	</parent>
 
 	<modules>
@@ -24,7 +24,7 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
-		<pluto.version>0.26.0-SNAPSHOT</pluto.version>
+		<pluto.version>0.27.0-SNAPSHOT</pluto.version>
 	</properties>
 
 	<dependencyManagement>