Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug/1255 Duplicating a objective does not bring all properties of the KeyResults #1294

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
68d057b
Refactor duplicating methods to include values of keyResult
ManuelMoeri Jan 13, 2025
7407955
Modify duplicateObjectiveDto to only include ids
ManuelMoeri Jan 13, 2025
667eb41
fix actionlist shared refrence error
nevio18324 Jan 14, 2025
de7820f
fix action being asigned to the wrong action
nevio18324 Jan 14, 2025
0b69b85
run formatter
nevio18324 Jan 14, 2025
39d7d44
fix duplicate tests
nevio18324 Jan 14, 2025
8761c7c
make new method to duplicate Actionlists
nevio18324 Jan 14, 2025
56d64ff
make shouldDupllicateActionList check if every attribute was copied e…
nevio18324 Jan 14, 2025
02ebb53
fix duplicate keyresult tests
nevio18324 Jan 14, 2025
0581fa8
run formatter
nevio18324 Jan 14, 2025
7da0700
write new e2e test testing if all keyresult attributes get duplicated
nevio18324 Jan 14, 2025
f337afb
fix duplicate so you can choose which key results you wanna duplicate
nevio18324 Jan 14, 2025
c4ef623
remove not needed commented line
nevio18324 Jan 14, 2025
b71dcb9
remove id out of pathvariable for duplicate
nevio18324 Jan 14, 2025
290459f
run formatter
nevio18324 Jan 14, 2025
bcd75a0
fix id still being passed as a param in objective form
nevio18324 Jan 14, 2025
b51f091
fix duplicateObjective mapping
nevio18324 Jan 14, 2025
2b99de1
remove unused import
nevio18324 Jan 14, 2025
dfb9714
remove outdated comment
nevio18324 Jan 14, 2025
e5de435
revert formatter changes
nevio18324 Jan 14, 2025
6e04718
remove unnecessary wait
nevio18324 Jan 14, 2025
f915735
remove action list attribute
nevio18324 Jan 14, 2025
a4071d3
Finish logic of duplicating objectives with the action plan
ManuelMoeri Jan 15, 2025
54ea73c
Delete unused test, add two new ones and apply formatters
ManuelMoeri Jan 15, 2025
67a586d
Fix tests and enhance logic
ManuelMoeri Jan 15, 2025
c1afcff
Format code
ManuelMoeri Jan 15, 2025
d9ce1a1
Resolve conversations
ManuelMoeri Jan 15, 2025
1cb243f
remove any from Objective controller duplicate test
nevio18324 Jan 16, 2025
aa034c5
refactor shouldDuplicateMetricKeyResult test
nevio18324 Jan 16, 2025
554ba39
Continue refactoring of logic and fix a couple of tests
ManuelMoeri Jan 16, 2025
b406d97
Fix last backend test
ManuelMoeri Jan 16, 2025
2420339
Add test for ordinal keyResult as well
ManuelMoeri Jan 16, 2025
9f6842d
Remove it.only in cypress tests
ManuelMoeri Jan 16, 2025
12b8a05
Enhance naming of param
ManuelMoeri Jan 16, 2025
7573ec8
Make naming of KeyResultId param more clear
ManuelMoeri Jan 16, 2025
95b113b
Replace else if with switch statement
ManuelMoeri Jan 16, 2025
fe7c39f
Make test paramaterized to check for empty and null
ManuelMoeri Jan 16, 2025
f153414
Format code
ManuelMoeri Jan 16, 2025
69a988c
Improve parameterized test name
MasterEvarior Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Continue refactoring of logic and fix a couple of tests
  • Loading branch information
ManuelMoeri committed Jan 16, 2025
commit 554ba396fc13ee9da69f1f98e13c8e13cc5df2f1
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Entity
Expand Down Expand Up @@ -204,7 +203,6 @@ public abstract static class Builder<T> {
private LocalDateTime createdOn;
private LocalDateTime modifiedOn;
private final String keyResultType;
private List<Action> actionList;

protected Builder(String keyResultType) {
this.keyResultType = keyResultType;
Expand Down Expand Up @@ -255,11 +253,6 @@ public T withModifiedOn(LocalDateTime modifiedOn) {
return (T) this;
}

public T withActionList(List<Action> actionList) {
this.actionList = actionList;
return (T) this;
}

public abstract KeyResult build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ public void deleteEntitiesByKeyResultId(Long keyResultId) {
getActionsByKeyResultId(keyResultId).forEach(action -> deleteEntityById(action.getId()));
}

public List<Action> createDuplicates(KeyResult oldKeyResult, KeyResult newKeyResult) {
public List<Action> duplicateActions(KeyResult oldKeyResult, KeyResult newKeyResult) {
List<Action> actionList = actionPersistenceService
.getActionsByKeyResultIdOrderByPriorityAsc(oldKeyResult.getId());
if (actionList == null) {
return Collections.emptyList();
}

return actionList.stream().map(action -> {
List<Action> duplicatedActions = new ArrayList<>();

actionList.forEach(action -> {
Action newAction = Action.Builder
.builder()
.withAction(action.getActionPoint())
Expand All @@ -94,7 +96,10 @@ public List<Action> createDuplicates(KeyResult oldKeyResult, KeyResult newKeyRes
.withKeyResult(newKeyResult)
.build();
validator.validate(newAction);
return newAction;
}).toList();
actionPersistenceService.save(newAction);
duplicatedActions.add(newAction);
});

return duplicatedActions;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package ch.puzzle.okr.service.business;

import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC;
import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL;

import ch.puzzle.okr.models.Action;
import ch.puzzle.okr.models.Objective;
import ch.puzzle.okr.models.authorization.AuthorizationUser;
Expand Down Expand Up @@ -141,7 +144,26 @@ public List<KeyResult> getKeyResultsOwnedByUser(long id) {
return keyResultPersistenceService.getKeyResultsOwnedByUser(id);
}

public KeyResult makeCopyOfKeyResultMetric(KeyResult keyResult, Objective duplicatedObjective) {
@Transactional
public KeyResult duplicateKeyResult(AuthorizationUser authorizationUser, KeyResult keyResult,
Objective duplicatedObjective) {
KeyResult newKeyResult;

if (keyResult.getKeyResultType().equals(KEY_RESULT_TYPE_METRIC)) {
KeyResult keyResultMetric = makeCopyOfKeyResultMetric(keyResult, duplicatedObjective);
newKeyResult = createEntity(keyResultMetric, authorizationUser);
} else if (keyResult.getKeyResultType().equals(KEY_RESULT_TYPE_ORDINAL)) {
KeyResult keyResultOrdinal = makeCopyOfKeyResultOrdinal(keyResult, duplicatedObjective);
newKeyResult = createEntity(keyResultOrdinal, authorizationUser);
} else {
throw new UnsupportedOperationException("Unsupported KeyResultType: " + keyResult.getKeyResultType());
}
ManuelMoeri marked this conversation as resolved.
Show resolved Hide resolved

actionBusinessService.duplicateActions(keyResult, newKeyResult);
return newKeyResult;
}

private KeyResult makeCopyOfKeyResultMetric(KeyResult keyResult, Objective duplicatedObjective) {
return KeyResultMetric.Builder
.builder() //
.withObjective(duplicatedObjective) //
Expand All @@ -154,7 +176,7 @@ public KeyResult makeCopyOfKeyResultMetric(KeyResult keyResult, Objective duplic
.build();
}

public KeyResult makeCopyOfKeyResultOrdinal(KeyResult keyResult, Objective duplicatedObjective) {
private KeyResult makeCopyOfKeyResultOrdinal(KeyResult keyResult, Objective duplicatedObjective) {
return KeyResultOrdinal.Builder
.builder() //
.withObjective(duplicatedObjective) //
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
package ch.puzzle.okr.service.business;

import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_METRIC;
import static ch.puzzle.okr.Constants.KEY_RESULT_TYPE_ORDINAL;

import ch.puzzle.okr.models.Action;
import ch.puzzle.okr.models.Objective;
import ch.puzzle.okr.models.authorization.AuthorizationUser;
import ch.puzzle.okr.models.keyresult.KeyResult;
import ch.puzzle.okr.models.keyresult.KeyResultMetric;
import ch.puzzle.okr.models.keyresult.KeyResultOrdinal;
import ch.puzzle.okr.service.persistence.ActionPersistenceService;
import ch.puzzle.okr.service.persistence.ObjectivePersistenceService;
import ch.puzzle.okr.service.validation.ObjectiveValidationService;
import jakarta.transaction.Transactional;
Expand All @@ -28,20 +21,17 @@ public class ObjectiveBusinessService implements BusinessServiceInterface<Long,
private final ObjectiveValidationService validator;
private final KeyResultBusinessService keyResultBusinessService;
private final CompletedBusinessService completedBusinessService;
private final ActionPersistenceService actionPersistenceService;
private final ActionBusinessService actionBusinessService;

public ObjectiveBusinessService(@Lazy KeyResultBusinessService keyResultBusinessService,
ObjectiveValidationService validator,
ObjectivePersistenceService objectivePersistenceService,
CompletedBusinessService completedBusinessService,
ActionPersistenceService actionPersistenceService,
ActionBusinessService actionBusinessService) {
ManuelMoeri marked this conversation as resolved.
Show resolved Hide resolved
this.keyResultBusinessService = keyResultBusinessService;
this.validator = validator;
this.objectivePersistenceService = objectivePersistenceService;
this.completedBusinessService = completedBusinessService;
this.actionPersistenceService = actionPersistenceService;
this.actionBusinessService = actionBusinessService;
}

Expand Down Expand Up @@ -123,39 +113,22 @@ public Objective createEntity(Objective objective, AuthorizationUser authorizati
* @param authorizationUser
* AuthorizationUser
* @param keyResultIds
* KeyResultIds to get and copy
* KeyResultIds to get and duplicate
ManuelMoeri marked this conversation as resolved.
Show resolved Hide resolved
* @return New Objective with copied KeyResults form the source Objective
*/
@Transactional
public Objective duplicateObjective(Objective objective, AuthorizationUser authorizationUser,
List<Long> keyResultIds) {
Objective duplicatedObjective = createEntity(objective, authorizationUser);
for (Long keyResult : keyResultIds) {
duplicateKeyResult(authorizationUser,
keyResultBusinessService.getEntityById(keyResult),
duplicatedObjective);
keyResultBusinessService
.duplicateKeyResult(authorizationUser,
keyResultBusinessService.getEntityById(keyResult),
duplicatedObjective);
}
return duplicatedObjective;
}

public void duplicateKeyResult(AuthorizationUser authorizationUser, KeyResult keyResult,
Objective duplicatedObjective) {
KeyResult newKeyResult = null;

if (keyResult.getKeyResultType().equals(KEY_RESULT_TYPE_METRIC)) {
KeyResult keyResultMetric = keyResultBusinessService.makeCopyOfKeyResultMetric(keyResult, duplicatedObjective);
newKeyResult = keyResultBusinessService.createEntity(keyResultMetric, authorizationUser);
} else if (keyResult.getKeyResultType().equals(KEY_RESULT_TYPE_ORDINAL)) {
KeyResult keyResultOrdinal = keyResultBusinessService.makeCopyOfKeyResultOrdinal(keyResult, duplicatedObjective);
newKeyResult = keyResultBusinessService.createEntity(keyResultOrdinal, authorizationUser);
} else {
throw new UnsupportedOperationException("Unsupported KeyResultType: " + keyResult.getKeyResultType());
}

List<Action> copiedActions = actionBusinessService.createDuplicates(keyResult, newKeyResult);
copiedActions.forEach(actionPersistenceService::save);
}

@Transactional
public void deleteEntityById(Long id) {
validator.validateOnDelete(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package ch.puzzle.okr.controller;

import static ch.puzzle.okr.test.KeyResultTestHelpers.keyResultMetricDto;
import static ch.puzzle.okr.test.KeyResultTestHelpers.keyResultOrdinalDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

import ch.puzzle.okr.deserializer.DeserializerHelper;
import ch.puzzle.okr.dto.ObjectiveDto;
import ch.puzzle.okr.mapper.ObjectiveMapper;
Expand All @@ -10,6 +18,8 @@
import ch.puzzle.okr.service.authorization.ActionAuthorizationService;
import ch.puzzle.okr.service.authorization.AuthorizationService;
import ch.puzzle.okr.service.authorization.ObjectiveAuthorizationService;
import java.time.LocalDateTime;
import java.util.List;
import org.hamcrest.core.Is;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -29,17 +39,6 @@
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.server.ResponseStatusException;

import java.time.LocalDateTime;
import java.util.List;

import static ch.puzzle.okr.test.KeyResultTestHelpers.keyResultMetricDto;
import static ch.puzzle.okr.test.KeyResultTestHelpers.keyResultOrdinalDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@WithMockUser(value = "spring")
@ExtendWith(MockitoExtension.class)
@WebMvcTest(ObjectiveController.class)
Expand Down Expand Up @@ -113,27 +112,27 @@ class ObjectiveControllerIT {
.withModifiedOn(LocalDateTime.MAX)
.build();
private static final ObjectiveDto objective1Dto = new ObjectiveDto(5L,
1,
OBJECTIVE_TITLE_1,
1L,
1L,
"GJ 22/23-Q2",
DESCRIPTION,
State.DRAFT,
LocalDateTime.MAX,
LocalDateTime.MAX,
true);
1,
OBJECTIVE_TITLE_1,
1L,
1L,
"GJ 22/23-Q2",
DESCRIPTION,
State.DRAFT,
LocalDateTime.MAX,
LocalDateTime.MAX,
true);
private static final ObjectiveDto objective2Dto = new ObjectiveDto(7L,
1,
OBJECTIVE_TITLE_2,
1L,
1L,
"GJ 22/23-Q2",
DESCRIPTION,
State.DRAFT,
LocalDateTime.MIN,
LocalDateTime.MIN,
true);
1,
OBJECTIVE_TITLE_2,
1L,
1L,
"GJ 22/23-Q2",
DESCRIPTION,
State.DRAFT,
LocalDateTime.MIN,
LocalDateTime.MIN,
true);

@Autowired
private MockMvc mvc;
Expand Down Expand Up @@ -184,16 +183,16 @@ void shouldThrowNotFoundWhenGettingObjectiveWithNonExistentId() throws Exception
@Test
void shouldReturnCreatedObjectiveWhenCreatingNewObjective() throws Exception {
ObjectiveDto testObjective = new ObjectiveDto(null,
1,
"Program Faster",
1L,
1L,
"GJ 22/23-Q2",
"Just be faster",
State.DRAFT,
null,
null,
true);
1,
"Program Faster",
1L,
1L,
"GJ 22/23-Q2",
"Just be faster",
State.DRAFT,
null,
null,
true);

BDDMockito.given(objectiveMapper.toDto(any())).willReturn(testObjective);
BDDMockito.given(objectiveAuthorizationService.createEntity(any())).willReturn(fullObjective);
Expand All @@ -214,7 +213,7 @@ void shouldThrowResponseStatusExceptionWhenCreatingObjectiveWithNullValues() thr
BDDMockito
.given(objectiveAuthorizationService.createEntity(any()))
.willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Missing attribute title when creating objective"));
"Missing attribute title when creating objective"));

mvc
.perform(post(URL_BASE_OBJECTIVE)
Expand All @@ -228,16 +227,16 @@ void shouldThrowResponseStatusExceptionWhenCreatingObjectiveWithNullValues() thr
@Test
void shouldReturnUpdatedObjectiveWhenUpdatingObjective() throws Exception {
ObjectiveDto testObjective = new ObjectiveDto(1L,
1,
TITLE,
1L,
1L,
"GJ 22/23-Q2",
UPDATED_DESCRIPTION,
State.NOTSUCCESSFUL,
LocalDateTime.MIN,
LocalDateTime.MAX,
true);
1,
TITLE,
1L,
1L,
"GJ 22/23-Q2",
UPDATED_DESCRIPTION,
State.NOTSUCCESSFUL,
LocalDateTime.MIN,
LocalDateTime.MAX,
true);
Objective objective = Objective.Builder
.builder()
.withId(1L)
Expand All @@ -264,16 +263,16 @@ void shouldReturnUpdatedObjectiveWhenUpdatingObjective() throws Exception {
@Test
void shouldReturnImUsed() throws Exception {
ObjectiveDto testObjectiveDto = new ObjectiveDto(1L,
1,
TITLE,
1L,
1L,
"GJ 22/23-Q2",
UPDATED_DESCRIPTION,
State.SUCCESSFUL,
LocalDateTime.MAX,
LocalDateTime.MAX,
true);
1,
TITLE,
1L,
1L,
"GJ 22/23-Q2",
UPDATED_DESCRIPTION,
State.SUCCESSFUL,
LocalDateTime.MAX,
LocalDateTime.MAX,
true);
Objective objectiveImUsed = Objective.Builder
.builder()
.withId(1L)
Expand Down Expand Up @@ -301,7 +300,7 @@ void shouldReturnNotFoundWhenUpdatingObjectiveByNonExistentId() throws Exception
BDDMockito
.given(objectiveAuthorizationService.updateEntity(anyLong(), any()))
.willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND,
"Failed objective -> Attribut is invalid"));
"Failed objective -> Attribut is invalid"));

mvc
.perform(put(URL_OBJECTIVE_10)
Expand All @@ -317,7 +316,7 @@ void shouldReturnBadRequest() throws Exception {
BDDMockito
.given(objectiveAuthorizationService.updateEntity(anyLong(), any()))
.willThrow(new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Failed objective -> Attribut is invalid"));
"Failed objective -> Attribut is invalid"));

mvc
.perform(put(URL_OBJECTIVE_10).with(SecurityMockMvcRequestPostProcessors.csrf()))
Expand Down Expand Up @@ -351,7 +350,9 @@ void shouldReturnIsCreatedWhenObjectiveWasDuplicated() throws Exception {
BDDMockito.given(keyResultMapper.toDto(any(KeyResultMetric.class), any())).willReturn(keyResultMetricDto);
BDDMockito.given(keyResultMapper.toDto(any(KeyResultOrdinal.class), any())).willReturn(keyResultOrdinalDto);
BDDMockito.given(objectiveAuthorizationService.getAuthorizationService()).willReturn(authorizationService);
BDDMockito.given(objectiveAuthorizationService.duplicateEntity(objective1, List.of(1L, 2L))).willReturn(objective1);
BDDMockito
.given(objectiveAuthorizationService.duplicateEntity(objective1, List.of(1L, 2L)))
.willReturn(objective1);
BDDMockito.given(objectiveMapper.toDto(objective1)).willReturn(objective1Dto);

mvc
Expand Down
Loading