Skip to content
Snippets Groups Projects
Commit 04590baa authored by OZGCloud's avatar OZGCloud
Browse files

OZG-6991 implement lock vorgang

parent a93d0000
Branches
Tags
No related merge requests found
......@@ -44,6 +44,7 @@ public interface Command {
public String getCreatedBy();
public String getCreatedByName();
public CommandStatus getStatus();
String getCreatedByClient();
public Map<String, Object> getBodyObject();
public Map<String, String> getBody();
......
......@@ -21,6 +21,7 @@ public class TestCommand implements Command {
private ZonedDateTime finishedAt;
private String createdBy;
private String createdByName;
private String createdByClient;
private CommandStatus status;
......
......@@ -63,6 +63,7 @@ public class PersistedCommand implements Command {
private String createdBy;
private String createdByName;
private String createdByClient;
@Setter
private CommandStatus status;
......
......@@ -50,6 +50,7 @@ public class Vorgang {
static final String MONGODB_FIELDNAME_CREATED_AT = "createdAt";
public static final String MONGODB_FIELDNAME_ASSIGNED_TO = "assignedTo";
public static final String MONGODB_FIELDNAME_IN_CREATION = "inCreation";
public static final String MONGODB_FIELDNAME_HEADER = "header";
public static final String FIELD_EINGANGSKENNZ = "eingangs.header.requestId";
public static final String FIELD_AKTENZEICHEN = "aktenzeichen";
......
......@@ -11,6 +11,8 @@ import lombok.Getter;
@TypeAlias("VorgangHeader")
public class VorgangHead {
public static final String FIELD_LOCK = "lock";
private ServiceKonto serviceKonto;
private String organisationsEinheitId;
......
......@@ -23,10 +23,13 @@
*/
package de.ozgcloud.vorgang.vorgang;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
......@@ -45,6 +48,7 @@ import de.ozgcloud.command.Command;
import de.ozgcloud.command.VorgangAssignedEvent;
import de.ozgcloud.command.VorgangCreatedEvent;
import de.ozgcloud.command.VorgangLockedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.vorgang.clientattribute.ClientAttributeMap;
import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
......@@ -58,6 +62,7 @@ public class VorgangService {
private static final String BODY_ASSIGNED_TO_FIELD = "assignedTo";
public static final String BODY_OBJECT_AKTENZEICHEN = "aktenzeichen";
static final String KEY_HEADER_LOCK = "%s.%s".formatted(Vorgang.MONGODB_FIELDNAME_HEADER, VorgangHead.FIELD_LOCK);
@Autowired
private VorgangAuthorizationService vorgangAuthenticationService;
......@@ -226,9 +231,31 @@ public class VorgangService {
}
public void lockVorgang(Command command) {
validateLockCommand(command);
repository.patch(command.getVorgangId(), command.getRelationVersion(), buildLockPatch(command));
publisher.publishEvent(new VorgangLockedEvent(command));
}
void validateLockCommand(Command command) {
if (Objects.isNull(command.getCreatedByClient())) {
throw new TechnicalException("Missing client name in lock command");
}
if (Objects.isNull(getReason(command.getBodyObject()))) {
throw new TechnicalException("Missing reason in lock command");
}
}
Map<String, Object> buildLockPatch(Command command) {
return Map.of(KEY_HEADER_LOCK, Map.of(
Lock.FIELD_CLIENT_NAME, command.getCreatedByClient(),
Lock.FIELD_LOCKED_SINCE, ZonedDateTime.now(ZoneId.of("UTC")),
Lock.FIELD_REASON, getReason(command.getBodyObject())));
}
String getReason(Map<String, Object> commandBody) {
return StringUtils.trimToNull(MapUtils.getString(commandBody, Lock.FIELD_REASON));
}
public void unlockVorgang(Command command) {
// TODO wird implementiert in OZG-6992
// publisher.publishEvent(new CommandRevokedEvent(command));
......
......@@ -29,6 +29,7 @@ import java.util.UUID;
import de.ozgcloud.command.CommandStatus;
import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
import de.ozgcloud.vorgang.callcontext.UserTestFactory;
import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
......@@ -39,6 +40,7 @@ public class CommandTestFactory {
public static final ZonedDateTime CREATED_AT = ZonedDateTime.parse(CREATED_AT_STR);
public static final String CREATED_BY = UserTestFactory.ID;
public static final String CREATED_BY_NAME = UserTestFactory.NAME;
public static final String CREATED_BY_CLIENT = CallContextTestFactory.CLIENT;
public static final CommandStatus STATUS = CommandStatus.PENDING;
public static final String RELATION_ID = VorgangAttachedItemTestFactory.ID;
......@@ -59,6 +61,7 @@ public class CommandTestFactory {
.createdAt(CREATED_AT)
.createdBy(CREATED_BY)
.createdByName(CREATED_BY_NAME)
.createdByClient(CREATED_BY_CLIENT)
.status(STATUS)
.relationId(RELATION_ID)
.relationVersion(RELATION_VERSION)
......
......@@ -28,10 +28,13 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
......@@ -49,6 +52,8 @@ import org.springframework.security.access.AccessDeniedException;
import de.ozgcloud.command.Command;
import de.ozgcloud.command.VorgangAssignedEvent;
import de.ozgcloud.command.VorgangCreatedEvent;
import de.ozgcloud.command.VorgangLockedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
import de.ozgcloud.vorgang.command.CommandTestFactory;
import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
......@@ -507,4 +512,108 @@ class VorgangServiceTest {
verify(repository).setAktenzeichen(VorgangTestFactory.ID, CommandTestFactory.RELATION_VERSION, null);
}
}
@Nested
class TestLockVorgang {
private static final Command LOCK_COMMAND = CommandTestFactory.create();
private static final Map<String, Object> LOCK_PATCH = Map.of("key", "value");
@Captor
private ArgumentCaptor<VorgangLockedEvent> eventCaptor;
@BeforeEach
void init() {
doNothing().when(service).validateLockCommand(any());
doReturn(LOCK_PATCH).when(service).buildLockPatch(any());
}
@Test
void shouldCallValidateLockCommand() {
service.lockVorgang(LOCK_COMMAND);
verify(service).validateLockCommand(LOCK_COMMAND);
}
@Test
void shouldCallBuildLockPatch() {
service.lockVorgang(LOCK_COMMAND);
verify(service).buildLockPatch(LOCK_COMMAND);
}
@Test
void shouldCallRepository() {
service.lockVorgang(LOCK_COMMAND);
verify(repository).patch(VorgangTestFactory.ID, CommandTestFactory.RELATION_VERSION, LOCK_PATCH);
}
@Test
void shouldCallPublishEvent() {
service.lockVorgang(LOCK_COMMAND);
verify(publisher).publishEvent(eventCaptor.capture());
assertThat(eventCaptor.getValue().getCommand()).isSameAs(LOCK_COMMAND);
}
}
@Nested
class TestValidateLockCommand {
@Test
void shouldThrowExceptionOnMissingClient() {
var command = CommandTestFactory.createBuilder().createdByClient(null).build();
assertThrows(TechnicalException.class, () -> service.validateLockCommand(command));
}
@Test
void shouldThrowExceptionOnMissingReason() {
var command = CommandTestFactory.createBuilder().bodyObject(Map.of()).build();
assertThrows(TechnicalException.class, () -> service.validateLockCommand(command));
}
@Test
void shouldAcceptValidCommand() {
var command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
assertDoesNotThrow(() -> service.validateLockCommand(command));
}
}
@Nested
class TestBuildLockPatch {
@Test
void shouldSetClientName() {
var command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
var result = service.buildLockPatch(command);
assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP)
.containsEntry(Lock.FIELD_CLIENT_NAME, CommandTestFactory.CREATED_BY_CLIENT);
}
@Test
void shouldSetLockedSince() {
var command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
var result = service.buildLockPatch(command);
assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP)
.extractingByKey(Lock.FIELD_LOCKED_SINCE, InstanceOfAssertFactories.ZONED_DATE_TIME)
.isCloseTo(ZonedDateTime.now(), within(1, ChronoUnit.SECONDS));
}
@Test
void shouldSetReason() {
var command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
var result = service.buildLockPatch(command);
assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP).containsEntry(Lock.FIELD_REASON, LockTestFactory.REASON);
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment