Skip to content

Commit 4f3d838

Browse files
committed
introduce repository to get sum of timeEntry durations
1 parent 9871061 commit 4f3d838

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package de.focusshift.zeiterfassung.overtime;
2+
3+
import de.focusshift.zeiterfassung.timeentry.TimeEntryEntity;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
7+
import java.time.Duration;
8+
import java.time.Instant;
9+
import java.util.List;
10+
11+
interface OvertimeRepository extends JpaRepository<TimeEntryEntity, Long> {
12+
13+
/**
14+
* Returns Durations of all TimeEntries for the given criteria.
15+
*
16+
* @param isBreak whether to handle break entries or others
17+
* @param userId to handle TimeEntries from
18+
* @param dateExclusive handle all TimeEntries until dateExclusive
19+
* @return list of TimeEntry durations
20+
*/
21+
@Query("select t.end - t.start from TimeEntryEntity t where t.isBreak = :isBreak and t.owner = :userId and t.start < :dateExclusive")
22+
List<Duration> getDurationsToDate(boolean isBreak, String userId, Instant dateExclusive);
23+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package de.focusshift.zeiterfassung.overtime;
2+
3+
import de.focusshift.zeiterfassung.TestContainersBase;
4+
import de.focusshift.zeiterfassung.tenancy.tenant.TenantService;
5+
import de.focusshift.zeiterfassung.tenancy.user.EMailAddress;
6+
import de.focusshift.zeiterfassung.tenancy.user.TenantUser;
7+
import de.focusshift.zeiterfassung.tenancy.user.TenantUserService;
8+
import de.focusshift.zeiterfassung.timeentry.TimeEntryService;
9+
import de.focusshift.zeiterfassung.user.UserId;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.boot.test.context.SpringBootTest;
14+
import org.springframework.security.core.Authentication;
15+
import org.springframework.security.core.context.SecurityContext;
16+
import org.springframework.security.core.context.SecurityContextHolder;
17+
import org.springframework.security.core.context.SecurityContextImpl;
18+
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
19+
import org.springframework.security.oauth2.core.user.OAuth2User;
20+
import org.springframework.transaction.annotation.Transactional;
21+
22+
import java.time.Duration;
23+
import java.time.LocalDate;
24+
import java.time.LocalTime;
25+
import java.time.ZoneId;
26+
import java.time.ZonedDateTime;
27+
import java.util.List;
28+
import java.util.Set;
29+
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.mockito.Mockito.mock;
32+
33+
@SpringBootTest
34+
@Transactional
35+
class OvertimeRepositoryIT extends TestContainersBase {
36+
37+
@Autowired
38+
private OvertimeRepository sut;
39+
40+
@Autowired
41+
private TenantService tenantService;
42+
43+
@Autowired
44+
private TenantUserService tenantUserService;
45+
46+
@Autowired
47+
private TimeEntryService timeEntryService;
48+
49+
@BeforeEach
50+
void setUp() {
51+
tenantService.create("ab143c2f");
52+
prepareSecurityContextWithTenantId("ab143c2f");
53+
}
54+
55+
@Test
56+
void ensureGetDurationsToDate() {
57+
58+
final TenantUser batman = tenantUserService.createNewUser("1a432ba3-cb93-463b-813b-8e065c1e0a24", "Bruce", "Wayne", new EMailAddress("batman@example.org"), Set.of());
59+
final TenantUser clark = tenantUserService.createNewUser("2256a744-31f9-4f87-8189-fe0d471e6537", "Kent", "Clark", new EMailAddress("Clark@example.org"), Set.of());
60+
final UserId userId = new UserId(batman.id());
61+
62+
final LocalDate date = LocalDate.now();
63+
final ZoneId utc = ZoneId.of("UTC");
64+
65+
timeEntryService.createTimeEntry(new UserId(clark.id()), "comment", ZonedDateTime.of(date, LocalTime.of(20, 30), utc), ZonedDateTime.of(date, LocalTime.of(21, 0), utc), false);
66+
timeEntryService.createTimeEntry(userId, "comment", ZonedDateTime.of(date, LocalTime.of(20, 30), utc), ZonedDateTime.of(date, LocalTime.of(21, 0), utc), false);
67+
timeEntryService.createTimeEntry(userId, "comment", ZonedDateTime.of(date, LocalTime.of(21, 0), utc), ZonedDateTime.of(date, LocalTime.of(22, 0), utc), false);
68+
timeEntryService.createTimeEntry(userId, "comment", ZonedDateTime.of(date, LocalTime.of(22, 0), utc), ZonedDateTime.of(date, LocalTime.of(23, 0), utc), true);
69+
70+
final List<Duration> durationsNoBreak = sut.getDurationsToDate(false, batman.id(), date.plusDays(1).atStartOfDay(utc).toInstant());
71+
assertThat(durationsNoBreak).containsExactly(Duration.ofMinutes(30), Duration.ofHours(1));
72+
73+
final List<Duration> durationsIsBreak = sut.getDurationsToDate(true, batman.id(), date.plusDays(1).atStartOfDay(utc).toInstant());
74+
assertThat(durationsIsBreak).containsExactly(Duration.ofHours(1));
75+
}
76+
77+
private static void prepareSecurityContextWithTenantId(final String tenantId) {
78+
79+
final OAuth2User oAuth2User = mock(OAuth2User.class);
80+
final Authentication authentication = new OAuth2AuthenticationToken(oAuth2User, List.of(), tenantId);
81+
82+
final SecurityContext securityContext = new SecurityContextImpl();
83+
securityContext.setAuthentication(authentication);
84+
SecurityContextHolder.setContext(securityContext);
85+
}
86+
}

0 commit comments

Comments
 (0)