Set reviewer targets

This commit is contained in:
Andreas Svanberg 2023-12-05 12:52:41 +01:00
parent 7495931891
commit 5f298b3828
9 changed files with 273 additions and 0 deletions

@ -25,6 +25,8 @@ import se.su.dsv.scipro.report.GradingReportTemplateRepo;
import se.su.dsv.scipro.report.GradingReportTemplateRepoImpl;
import se.su.dsv.scipro.report.OppositionReportRepo;
import se.su.dsv.scipro.report.OppositionReportRepoImpl;
import se.su.dsv.scipro.reviewing.ReviewerTargetRepository;
import se.su.dsv.scipro.reviewing.ReviewerTargetRepositoryImpl;
import se.su.dsv.scipro.system.FooterAddressRepo;
import se.su.dsv.scipro.system.FooterAddressRepoImpl;
import se.su.dsv.scipro.system.FooterLinkRepo;
@ -53,5 +55,6 @@ public class RepositoryModule extends AbstractModule {
bind(FooterLinkRepo.class).to(FooterLinkRepoImpl.class);
bind(FooterAddressRepo.class).to(FooterAddressRepoImpl.class);
bind(FinalSeminarRepository.class).to(FinalSeminarRepositoryImpl.class);
bind(ReviewerTargetRepository.class).to(ReviewerTargetRepositoryImpl.class);
}
}

@ -0,0 +1,11 @@
package se.su.dsv.scipro.reviewing;
import java.time.LocalDate;
public record DateRange(LocalDate from, LocalDate to) {
public DateRange {
if (from.isAfter(to)) {
throw new IllegalArgumentException("from must be before or equal to to");
}
}
}

@ -0,0 +1,11 @@
package se.su.dsv.scipro.reviewing;
import se.su.dsv.scipro.system.User;
import java.time.LocalDate;
public interface ReviewerCapacityService {
void assignTarget(User reviewer, DateRange dateRange, int target);
int getTarget(User reviewer, LocalDate date);
}

@ -0,0 +1,34 @@
package se.su.dsv.scipro.reviewing;
import se.su.dsv.scipro.system.User;
import javax.inject.Inject;
import java.time.LocalDate;
class ReviewerCapacityServiceImpl implements ReviewerCapacityService {
private final ReviewerTargetRepository reviewerTargetRepository;
@Inject
ReviewerCapacityServiceImpl(ReviewerTargetRepository reviewerTargetRepository) {
this.reviewerTargetRepository = reviewerTargetRepository;
}
@Override
public void assignTarget(User reviewer, DateRange dateRange, int target) {
ReviewerTarget reviewerTarget = new ReviewerTarget();
reviewerTarget.setReviewer(reviewer);
reviewerTarget.setFromDate(dateRange.from());
reviewerTarget.setToDate(dateRange.to());
reviewerTarget.setTarget(target);
reviewerTargetRepository.save(reviewerTarget);
}
@Override
public int getTarget(User reviewer, LocalDate date) {
return reviewerTargetRepository.getReviewerTargets(reviewer, date)
.stream()
.mapToInt(ReviewerTarget::getTarget)
.max()
.orElse(0);
}
}

@ -0,0 +1,96 @@
package se.su.dsv.scipro.reviewing;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import se.su.dsv.scipro.system.DomainObject;
import se.su.dsv.scipro.system.User;
import java.time.LocalDate;
import java.util.Objects;
@Entity
@Table(name = "reviewer_target")
public class ReviewerTarget extends DomainObject {
@Id
@GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY)
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "reviewer_id", nullable = false)
private User reviewer;
@Column(name = "target", nullable = false)
private int target;
@Column(name = "from_date", nullable = false)
private java.time.LocalDate fromDate;
@Column(name = "to_date", nullable = false)
private java.time.LocalDate toDate;
@Override
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public User getReviewer() {
return reviewer;
}
public void setReviewer(User reviewer) {
this.reviewer = reviewer;
}
public int getTarget() {
return target;
}
public void setTarget(int target) {
this.target = target;
}
public LocalDate getFromDate() {
return fromDate;
}
public void setFromDate(LocalDate fromDate) {
this.fromDate = fromDate;
}
public LocalDate getToDate() {
return toDate;
}
public void setToDate(LocalDate toDate) {
this.toDate = toDate;
}
@Override
public String toString() {
return "ReviewerTarget{" + "id=" + id + ", reviewer=" + reviewer + ", target=" + target + ", fromDate=" + fromDate + ", toDate=" + toDate + '}';
}
@Override
public boolean equals(Object o) {
return o instanceof ReviewerTarget that
&& target == that.target
&& Objects.equals(id, that.id)
&& Objects.equals(reviewer, that.reviewer)
&& Objects.equals(fromDate, that.fromDate)
&& Objects.equals(toDate, that.toDate);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), id, reviewer, target, fromDate, toDate);
}
}

@ -0,0 +1,12 @@
package se.su.dsv.scipro.reviewing;
import se.su.dsv.scipro.system.User;
import java.time.LocalDate;
import java.util.List;
public interface ReviewerTargetRepository {
void save(ReviewerTarget reviewerTarget);
List<ReviewerTarget> getReviewerTargets(User reviewer, LocalDate date);
}

@ -0,0 +1,36 @@
package se.su.dsv.scipro.reviewing;
import jakarta.persistence.EntityManager;
import se.su.dsv.scipro.system.AbstractRepository;
import se.su.dsv.scipro.system.User;
import javax.inject.Inject;
import javax.inject.Provider;
import java.time.LocalDate;
import java.util.List;
public class ReviewerTargetRepositoryImpl extends AbstractRepository implements ReviewerTargetRepository {
@Inject
public ReviewerTargetRepositoryImpl(Provider<EntityManager> em) {
super(em);
}
@Override
public void save(ReviewerTarget reviewerTarget) {
EntityManager entityManager = em();
if (entityManager.contains(reviewerTarget)) {
entityManager.merge(reviewerTarget);
} else {
entityManager.persist(reviewerTarget);
}
}
@Override
public List<ReviewerTarget> getReviewerTargets(User reviewer, LocalDate date) {
return from(QReviewerTarget.reviewerTarget)
.where(QReviewerTarget.reviewerTarget.reviewer.eq(reviewer)
.and(QReviewerTarget.reviewerTarget.fromDate.loe(date))
.and(QReviewerTarget.reviewerTarget.toDate.goe(date)))
.fetch();
}
}

@ -19,5 +19,6 @@ public class ReviewingModule extends AbstractModule {
bind(ReviewerDeadlineSettingsService.class).to(ReviewerDeadlineSettingsServiceImpl.class);
bind(ReviewerDeadlineSettingsRepository.class).to(ReviewerDeadlineSettingsRepositoryImpl.class);
bind(ReviewerDeadlineFollowupService.class).to(ReviewerDeadlineFollowupServiceImpl.class);
bind(ReviewerCapacityService.class).to(ReviewerCapacityServiceImpl.class);
}
}

@ -0,0 +1,69 @@
package se.su.dsv.scipro.reviewing;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.test.IntegrationTest;
import javax.inject.Inject;
import java.time.LocalDate;
import java.time.Month;
import static org.junit.jupiter.api.Assertions.*;
class ReviewerCapacityServiceTest extends IntegrationTest {
private static DateRange VT24 = new DateRange(LocalDate.of(2024, Month.JANUARY, 1), LocalDate.of(2024, Month.JUNE, 30));
@Inject
ReviewerCapacityService service;
private User reviewer;
@BeforeEach
void setUp() {
User reviewer = User.builder()
.firstName("John")
.lastName("Doe")
.emailAddress("john@example.com")
.build();
this.reviewer = save(reviewer);
}
@Test
void saves_assigned_targets() {
// when
int target = 8;
service.assignTarget(reviewer, VT24, target);
// then
assertEquals(target, service.getTarget(reviewer, VT24.from()));
}
@Test
void given_multiple_overlapping_period_the_target_is_the_highest() {
// given
int target = 8;
int higherTarget = 10;
service.assignTarget(reviewer, VT24, target);
service.assignTarget(reviewer, VT24, higherTarget);
// when
int actual = service.getTarget(reviewer, VT24.from());
// then
assertEquals(higherTarget, actual);
}
@Test
void target_is_zero_if_nothing_is_assigned() {
// when
int actual = service.getTarget(reviewer, VT24.from());
// then
assertEquals(0, actual);
}
}