Skip to content

Commit

Permalink
Make shouldWorkingHours implementation aware of multiple users
Browse files Browse the repository at this point in the history
fixes #905
  • Loading branch information
honnel committed Oct 29, 2024
1 parent f832503 commit 7378d10
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 16 deletions.
38 changes: 22 additions & 16 deletions src/main/java/de/focusshift/zeiterfassung/report/ReportDay.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
import de.focusshift.zeiterfassung.usermanagement.UserLocalId;
import de.focusshift.zeiterfassung.workingtime.PlannedWorkingHours;

import java.time.Duration;
import java.time.LocalDate;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

record ReportDay(
Expand All @@ -33,24 +36,27 @@ public PlannedWorkingHours plannedWorkingHours() {

public ShouldWorkingHours shouldWorkingHours() {

final double absenceDayLengthValue = detailDayAbsencesByUser.values().stream()
.flatMap(Collection::stream)
.map(ReportDayAbsence::absence)
.map(Absence::dayLength)
.map(DayLength::getValue)
.reduce(0.0, Double::sum);

if (absenceDayLengthValue >= 1.0) {
return ShouldWorkingHours.ZERO;
}

final PlannedWorkingHours plannedWorkingHours = plannedWorkingHours();

if (absenceDayLengthValue == 0.5) {
return new ShouldWorkingHours(plannedWorkingHours.duration().dividedBy(2));
final Map<UserIdComposite, Double> absenceLengthByUser = detailDayAbsencesByUser.entrySet().stream().map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue().stream().map(ReportDayAbsence::absence)
.map(Absence::dayLength)
.map(DayLength::getValue)
.reduce(0.0, Double::sum))).collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));

Duration plannedWorkingHoursOfAllUsers = plannedWorkingHours().duration();

for (final var entry : absenceLengthByUser.entrySet()) {
Duration plannedWorkingHoursOfUser = plannedWorkingHoursByUser.get(entry.getKey()).duration();
if (entry.getValue() >= 1.0) {
plannedWorkingHoursOfAllUsers = plannedWorkingHoursOfAllUsers.minus(plannedWorkingHoursOfUser);
}
if (entry.getValue() == 0.5) {
plannedWorkingHoursOfAllUsers = plannedWorkingHoursOfAllUsers.minus(plannedWorkingHoursOfUser.dividedBy(2));
}
}

return new ShouldWorkingHours(plannedWorkingHours.duration());
return new ShouldWorkingHours(plannedWorkingHoursOfAllUsers);
}

public PlannedWorkingHours plannedWorkingHoursByUser(UserLocalId userLocalId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package de.focusshift.zeiterfassung.report;

import de.focusshift.zeiterfassung.absence.Absence;
import de.focusshift.zeiterfassung.absence.AbsenceColor;
import de.focusshift.zeiterfassung.absence.AbsenceTypeCategory;
import de.focusshift.zeiterfassung.tenancy.user.EMailAddress;
import de.focusshift.zeiterfassung.timeentry.ShouldWorkingHours;
import de.focusshift.zeiterfassung.user.UserId;
import de.focusshift.zeiterfassung.user.UserIdComposite;
import de.focusshift.zeiterfassung.usermanagement.User;
Expand All @@ -17,6 +21,9 @@
import java.util.Map;
import java.util.Set;

import static de.focusshift.zeiterfassung.absence.AbsenceColor.RED;
import static de.focusshift.zeiterfassung.absence.AbsenceTypeCategory.HOLIDAY;
import static de.focusshift.zeiterfassung.absence.DayLength.FULL;
import static org.assertj.core.api.Assertions.assertThat;

class ReportDayTest {
Expand All @@ -40,6 +47,47 @@ void ensureToRemoveBreaks() {
assertThat(reportDay.workDuration().duration()).isEqualTo(Duration.ZERO);
}

@Test
void shouldWorkingHoursReturnsZeroForFullyAbsentUser() {

final UserId batmanId = new UserId("uuid");
final UserLocalId batmanLocalId = new UserLocalId(1337L);
final UserIdComposite batmanIdComposite = new UserIdComposite(batmanId, batmanLocalId);
final User batman = new User(batmanIdComposite, "Bruce", "Wayne", new EMailAddress("[email protected]"), Set.of());

final ZonedDateTime from = dateTime(2021, 1, 4, 1, 0);
final ZonedDateTime to = dateTime(2021, 1, 4, 2, 0);
Absence absence = new Absence(batmanId, from, to, FULL, locale -> "foo", RED, HOLIDAY);

final ReportDay reportDay = new ReportDay(LocalDate.of(2021, 1, 4), Map.of(batmanIdComposite, PlannedWorkingHours.EIGHT), Map.of(batmanIdComposite, List.of()), Map.of(batmanIdComposite, List.of(new ReportDayAbsence(batman, absence))));

assertThat(reportDay.shouldWorkingHours()).isEqualTo(new ShouldWorkingHours(Duration.ZERO));
}

@Test
void shouldWorkingHoursReturnsShouldHoursForOneAbsentUserAndOneWorkingUser() {

final UserId batmanId = new UserId("uuid1");
final UserLocalId batmanLocalId = new UserLocalId(1337L);
final UserIdComposite batmanIdComposite = new UserIdComposite(batmanId, batmanLocalId);
final User batman = new User(batmanIdComposite, "Bruce", "Wayne", new EMailAddress("[email protected]"), Set.of());

final ZonedDateTime from = dateTime(2021, 1, 4, 1, 0);
final ZonedDateTime to = dateTime(2021, 1, 4, 2, 0);
Absence absence = new Absence(batmanId, from, to, FULL, locale -> "foo", RED, HOLIDAY);

final UserId robinId = new UserId("uuid2");
final UserLocalId robinLocalId = new UserLocalId(1337L);
final UserIdComposite robinIdComposite = new UserIdComposite(robinId, robinLocalId);

Map<UserIdComposite, List<ReportDayEntry>> entriesByUser = Map.of(batmanIdComposite, List.of(), robinIdComposite, List.of());
Map<UserIdComposite, List<ReportDayAbsence>> absencesByUser = Map.of(batmanIdComposite, List.of(new ReportDayAbsence(batman, absence)), robinIdComposite, List.of());
Map<UserIdComposite, PlannedWorkingHours> plannedWorkingHoursByUser = Map.of(batmanIdComposite, PlannedWorkingHours.EIGHT, robinIdComposite, new PlannedWorkingHours(Duration.ofHours(4L)));
final ReportDay reportDay = new ReportDay(LocalDate.of(2021, 1, 4), plannedWorkingHoursByUser, entriesByUser, absencesByUser);

assertThat(reportDay.shouldWorkingHours()).isEqualTo(new ShouldWorkingHours(Duration.ofHours(4L)));
}

private static ZonedDateTime dateTime(int year, int month, int dayOfMonth, int hour, int minute) {
return ZonedDateTime.of(LocalDateTime.of(year, month, dayOfMonth, hour, minute), ZONE_ID_BERLIN);
}
Expand Down

0 comments on commit 7378d10

Please sign in to comment.