Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.net.URI;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

@Controller("/services/review-assignments")
@Secured(SecurityRule.IS_AUTHENTICATED)
Expand Down Expand Up @@ -60,6 +62,26 @@ public Mono<HttpResponse<ReviewAssignment>> createReviewAssignment(@Body @Valid

}

/**
* Create and save multiple new {@link ReviewAssignment}s and associate them with a given {@link ReviewPeriod}.
*
* @param reviewPeriodId a {@link UUID} representing the review period to associate the review assignments with
* @param assignments a List of {@link ReviewAssignmentDTO} representing the desired review assignments
* @return a streamable response containing the list of stored {@link ReviewAssignment}
*/
@Post("/{reviewPeriodId}")
@RequiredPermission(Permission.CAN_CREATE_REVIEW_ASSIGNMENTS)
public Mono<HttpResponse<List<ReviewAssignment>>> createReviewAssignment(@NotNull UUID reviewPeriodId, @Body @Valid List<ReviewAssignmentDTO> assignments) {

return Mono.fromCallable(() -> reviewAssignmentServices.saveAll(reviewPeriodId,
assignments.stream().map(ReviewAssignmentDTO::convertToEntity).collect(Collectors.toList()),
Boolean.TRUE))
.publishOn(Schedulers.fromExecutor(eventLoopGroup))
.map(reviewAssignments -> (HttpResponse<List<ReviewAssignment>>) HttpResponse.created(reviewAssignments))
.subscribeOn(Schedulers.fromExecutor(ioExecutorService));

}

/**
* Retrieve a {@link ReviewAssignment} given its id.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ public interface ReviewAssignmentRepository extends CrudRepository<ReviewAssignm
Set<ReviewAssignment> findByReviewPeriodId(UUID reviewPeriodId);

Set<ReviewAssignment> findByReviewPeriodIdAndReviewerId(UUID reviewPeriodId, UUID reviewerId);

void deleteByReviewPeriodId(UUID reviewPeriodId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import io.micronaut.core.annotation.Nullable;

import java.util.List;
import java.util.Set;
import java.util.UUID;

public interface ReviewAssignmentServices {
ReviewAssignment save(ReviewAssignment reviewAssignment);
List<ReviewAssignment> saveAll(UUID reviewPeriodId, List<ReviewAssignment> reviewAssignments, Boolean deleteExisting);
ReviewAssignment findById(UUID id);

ReviewAssignment update(ReviewAssignment reviewAssignment);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package com.objectcomputing.checkins.services.reviews;

import com.objectcomputing.checkins.exceptions.AlreadyExistsException;
import com.objectcomputing.checkins.exceptions.BadArgException;
import com.objectcomputing.checkins.exceptions.PermissionException;
import com.objectcomputing.checkins.services.memberprofile.MemberProfileRepository;
import io.micronaut.core.annotation.Nullable;
import jakarta.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.*;

@Singleton
public class ReviewAssignmentServicesImpl implements ReviewAssignmentServices {
Expand Down Expand Up @@ -47,6 +43,29 @@ public ReviewAssignment save(ReviewAssignment reviewAssignment) {
return newAssignment;
}

@Override
public List<ReviewAssignment> saveAll(UUID reviewPeriodId, List<ReviewAssignment> reviewAssignments, Boolean deleteExisting) {

if(deleteExisting) {
LOG.warn(String.format("Deleting all review assignments for review period %s", reviewPeriodId));
reviewAssignmentRepository.deleteByReviewPeriodId(reviewPeriodId);
}

List<ReviewAssignment> newAssignments = new ArrayList<>();
if (reviewAssignments != null) {
for (ReviewAssignment reviewAssignment : reviewAssignments) {
if (reviewAssignment.getId() != null) {
throw new BadArgException(String.format("Found unexpected id %s for review assignment. New entities must not contain an id.",
reviewAssignment.getId()));
}
reviewAssignment.setReviewPeriodId(reviewPeriodId);
}

reviewAssignmentRepository.saveAll(reviewAssignments).forEach(newAssignments::add);
}
return newAssignments;
}

@Override
public ReviewAssignment findById(@NotNull UUID id) {
return reviewAssignmentRepository.findById(id).orElse(null);
Expand All @@ -73,7 +92,7 @@ public Set<ReviewAssignment> findAllByReviewPeriodIdAndReviewerId(UUID reviewPer

@Override
public ReviewAssignment update(ReviewAssignment reviewAssignment) {
LOG.warn(String.format("Updating entity %s", reviewAssignment));
LOG.info(String.format("Updating entity %s", reviewAssignment));
if (reviewAssignment.getId() != null && reviewAssignmentRepository.findById(reviewAssignment.getId()).isPresent()) {
return reviewAssignmentRepository.update(reviewAssignment);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public ReviewPeriod update(@NotNull ReviewPeriod reviewPeriod) {
if (!currentUserServices.isAdmin()) {
throw new PermissionException("You do not have permission to access this resource");
}
LOG.warn(String.format("Updating entity %s", reviewPeriod));
LOG.info(String.format("Updating entity %s", reviewPeriod));
if (reviewPeriod.getId() != null && reviewPeriodRepository.findById(reviewPeriod.getId()).isPresent()) {
return reviewPeriodRepository.update(reviewPeriod);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.*;

import static com.objectcomputing.checkins.services.role.RoleType.Constants.ADMIN_ROLE;
import static com.objectcomputing.checkins.services.role.RoleType.Constants.MEMBER_ROLE;
Expand Down Expand Up @@ -66,6 +63,55 @@ public void testPOSTCreateAReviewAssignment() {
assertEquals(String.format("%s/%s", request.getPath(), body.getId()), response.getHeaders().get("location"));
}

@Test
public void testPOSTCreateMultipleReviewAssignments() {
ReviewPeriod reviewPeriod = createADefaultReviewPeriod();

ReviewAssignmentDTO reviewAssignmentDTO = new ReviewAssignmentDTO();
reviewAssignmentDTO.setRevieweeId(UUID.randomUUID());
reviewAssignmentDTO.setReviewerId(UUID.randomUUID());
reviewAssignmentDTO.setReviewPeriodId(reviewPeriod.getId());
reviewAssignmentDTO.setApproved(false);

ReviewAssignmentDTO reviewAssignmentDTO2 = new ReviewAssignmentDTO();
reviewAssignmentDTO2.setRevieweeId(UUID.randomUUID());
reviewAssignmentDTO2.setReviewerId(UUID.randomUUID());
reviewAssignmentDTO2.setReviewPeriodId(reviewPeriod.getId());
reviewAssignmentDTO2.setApproved(false);

List<ReviewAssignmentDTO> reviewAssignments = List.of(reviewAssignmentDTO, reviewAssignmentDTO2);

final HttpRequest<List<ReviewAssignmentDTO>> request = HttpRequest.
POST(String.format("/%s", reviewPeriod.getId()), reviewAssignments).basicAuth(ADMIN_ROLE, ADMIN_ROLE);
final HttpResponse<List<ReviewAssignment>> response = client.toBlocking().exchange(request, Argument.listOf(ReviewAssignment.class));

assertNotNull(response);
var body = response.body();
assertNotNull(body);
assertEquals(HttpStatus.CREATED, response.getStatus());
assertEquals(2, Objects.requireNonNull(response.body()).size());
assertTrue(body.stream().anyMatch(ra -> ra.getRevieweeId().equals(reviewAssignmentDTO.getRevieweeId())));
assertTrue(body.stream().anyMatch(ra -> ra.getRevieweeId().equals(reviewAssignmentDTO2.getRevieweeId())));
assertTrue(body.stream().allMatch(ra -> ra.getReviewPeriodId().equals(reviewPeriod.getId())));
assertTrue(body.stream().allMatch(ra -> {
assert ra.getApproved() != null;
return ra.getApproved().equals(false);
}));


final HttpRequest<Object> request2 = HttpRequest.
GET(String.format("/period/%s", reviewPeriod.getId())).basicAuth(ADMIN_ROLE, ADMIN_ROLE);

final HttpResponse<List<ReviewAssignment>> response2 = client.toBlocking().exchange(request2, Argument.listOf(ReviewAssignment.class));

assertNotNull(response2.body());
body = response2.body();
assertEquals(2, Objects.requireNonNull(response2.body()).size());
assertTrue(body.stream().anyMatch(ra -> ra.getRevieweeId().equals(reviewAssignmentDTO.getRevieweeId())));
assertTrue(body.stream().anyMatch(ra -> ra.getRevieweeId().equals(reviewAssignmentDTO2.getRevieweeId())));
assertEquals(HttpStatus.OK, response2.getStatus());
}

@Test
public void testGETGetByIdHappyPath() {
ReviewAssignment reviewAssignment = createADefaultReviewAssignment();
Expand Down