Skip to content

Commit

Permalink
use enum for WorksOnPublicHoliday
Browse files Browse the repository at this point in the history
  • Loading branch information
bseber committed Apr 3, 2024
1 parent bdf790c commit b1ce660
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ private void prepareWorkingTimeCreateOrEditModel(Model model, String query, Long

model.addAttribute("section", "working-time-edit");
model.addAttribute("workingTime", workingTimeDto);
model.addAttribute("globalFederalState", federalStateSettings.federalState());
// number is required for the messages choice pattern which does not work with boolean
model.addAttribute("globalWorksOnPublicHoliday", federalStateSettings.worksOnPublicHoliday() ? 1 : 0);
model.addAttribute("federalStateSelect", federalStateSelectDto(workingTimeDto.getFederalState(), true));
Expand Down Expand Up @@ -337,7 +336,7 @@ private static WorkingTimeDto workingTimeToDto(WorkingTime workingTime) {
dto.setMinValidFrom(workingTime.minValidFrom().orElse(null));
dto.setMaxValidFrom(workingTime.validTo().orElse(null));
dto.setFederalState(workingTime.federalState());
dto.setWorksOnPublicHoliday(workingTime.isWorksOnPublicHolidayGlobal() ? null : workingTime.worksOnPublicHoliday());
dto.setWorksOnPublicHoliday(workingTime.worksOnPublicHoliday().asBoolean());
dto.setUserId(workingTime.userIdComposite().localId().value());
dto.setWorkday(workingTime.actualWorkingDays().stream().map(DayOfWeek::name).map(String::toLowerCase).toList());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import static java.util.Comparator.nullsLast;
import static java.util.Comparator.reverseOrder;
import static java.util.HashMap.newHashMap;
import static java.util.Objects.requireNonNullElseGet;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
import static org.slf4j.LoggerFactory.getLogger;
Expand Down Expand Up @@ -65,7 +64,7 @@ public Optional<WorkingTime> getWorkingTimeById(WorkingTimeId workingTimeId) {
final UserLocalId userLocalId = new UserLocalId(entity.getUserId());
final User user = findUser(userLocalId);
final List<WorkingTimeEntity> allEntitiesSorted = findAllWorkingTimeEntitiesSorted(userLocalId);
return entityToWorkingTime(entity, user.userIdComposite(), allEntitiesSorted, this::getGlobalFederalStateSettings);
return entityToWorkingTime(entity, user.userIdComposite(), allEntitiesSorted, new CachedSupplier<>(this::getGlobalFederalStateSettings));
});
}

Expand All @@ -74,13 +73,12 @@ public List<WorkingTime> getAllWorkingTimesByUser(UserLocalId userLocalId) {

final User user = findUser(userLocalId);
final List<WorkingTimeEntity> sortedEntities = findAllWorkingTimeEntitiesSorted(userLocalId);
final CachedSupplier<FederalStateSettings> federalStateSettingSupplier = new CachedSupplier<>(this::getGlobalFederalStateSettings);

if (sortedEntities.isEmpty()) {
return List.of(createDefaultWorkingTime(user.userIdComposite()));
return List.of(createDefaultWorkingTime(user.userIdComposite(), federalStateSettingSupplier));
}

final CachedSupplier<FederalStateSettings> federalStateSettingSupplier = new CachedSupplier<>(this::getGlobalFederalStateSettings);

return sortedEntities.stream()
.map(entity -> entityToWorkingTime(entity, user.userIdComposite(), sortedEntities, federalStateSettingSupplier))
.toList();
Expand Down Expand Up @@ -113,7 +111,7 @@ public WorkingTime createWorkingTime(UserLocalId userLocalId, LocalDate validFro
final WorkingTimeEntity saved = repository.save(entity);
final List<WorkingTimeEntity> allEntitiesSorted = findAllWorkingTimeEntitiesSorted(userLocalId);

return entityToWorkingTime(saved, user.userIdComposite(), allEntitiesSorted, this::getGlobalFederalStateSettings);
return entityToWorkingTime(saved, user.userIdComposite(), allEntitiesSorted, new CachedSupplier<>(this::getGlobalFederalStateSettings));
}

@Override
Expand All @@ -140,7 +138,7 @@ public WorkingTime updateWorkingTime(WorkingTimeId workingTimeId, @Nullable Loca
final WorkingTimeEntity saved = repository.save(entity);
final List<WorkingTimeEntity> allEntitiesSorted = findAllWorkingTimeEntitiesSorted(userLocalId);

return entityToWorkingTime(saved, user.userIdComposite(), allEntitiesSorted, this::getGlobalFederalStateSettings);
return entityToWorkingTime(saved, user.userIdComposite(), allEntitiesSorted, new CachedSupplier<>(this::getGlobalFederalStateSettings));
}

@Override
Expand Down Expand Up @@ -357,7 +355,8 @@ private WorkingTime defaultWorkingTime(UserIdComposite userIdComposite, Supplier
return WorkingTime.builder(userIdComposite, null)
.current(true)
.federalState(FederalState.GLOBAL)
.worksOnPublicHoliday(federalStateSettingsSupplier.get().worksOnPublicHoliday(), true)
.federalStateSettingsSupplier(new CachedSupplier<>(federalStateSettingsSupplier))
.worksOnPublicHoliday(WorksOnPublicHoliday.GLOBAL)
.monday(eight)
.tuesday(eight)
.wednesday(eight)
Expand All @@ -368,20 +367,19 @@ private WorkingTime defaultWorkingTime(UserIdComposite userIdComposite, Supplier
.build();
}

private WorkingTime createDefaultWorkingTime(UserIdComposite userIdComposite) {
final Supplier<FederalStateSettings> settingsSupplier = this::getGlobalFederalStateSettings;
final WorkingTime defaultWorkingTime = defaultWorkingTime(userIdComposite, settingsSupplier);
private WorkingTime createDefaultWorkingTime(UserIdComposite userIdComposite, CachedSupplier<FederalStateSettings> federalStateSettingSupplier) {
final WorkingTime defaultWorkingTime = defaultWorkingTime(userIdComposite, federalStateSettingSupplier);
final WorkingTimeEntity toSave = workingTimeToEntity(defaultWorkingTime);
final WorkingTimeEntity persisted = repository.save(toSave);
return entityToWorkingTime(persisted, userIdComposite, List.of(persisted), settingsSupplier);
return entityToWorkingTime(persisted, userIdComposite, List.of(persisted), federalStateSettingSupplier);
}

private FederalStateSettings getGlobalFederalStateSettings() {
return federalStateSettingsService.getFederalStateSettings();
}

private List<WorkingTime> entitiesToWorkingTimes(List<WorkingTimeEntity> entities, UserIdComposite userIdComposite,
Supplier<FederalStateSettings> federalStateSettingsSupplier) {
CachedSupplier<FederalStateSettings> federalStateSettingsSupplier) {
return entities.stream()
.map(entity -> entityToWorkingTime(entity, userIdComposite, entities, federalStateSettingsSupplier))
.toList();
Expand All @@ -390,19 +388,16 @@ private List<WorkingTime> entitiesToWorkingTimes(List<WorkingTimeEntity> entitie
@SuppressWarnings("java:S4276") // we need Supplier because we don't have a CachedBooleanSupplier
private WorkingTime entityToWorkingTime(WorkingTimeEntity entity, UserIdComposite userIdComposite,
List<WorkingTimeEntity> allEntitiesSorted,
Supplier<FederalStateSettings> federalStateSettingsSupplier) {

final Boolean entityWorksOnPublicHoliday = entity.isWorksOnPublicHoliday();
final boolean worksOnPublicHoliday = requireNonNullElseGet(entityWorksOnPublicHoliday, () -> federalStateSettingsSupplier.get().worksOnPublicHoliday());
CachedSupplier<FederalStateSettings> federalStateSettingsSupplier) {

return WorkingTime.builder(userIdComposite, new WorkingTimeId(entity.getId()))
.current(isCurrent(entity, allEntitiesSorted))
.validFrom(entity.getValidFrom())
.validTo(getValidToDate(entity, allEntitiesSorted))
.minValidFrom(getMinValidFromDate(entity, allEntitiesSorted))
.federalState(entity.getFederalState())
.globalFederalStateSupplier(() -> federalStateSettingsSupplier.get().federalState())
.worksOnPublicHoliday(worksOnPublicHoliday, entityWorksOnPublicHoliday == null)
.federalStateSettingsSupplier(federalStateSettingsSupplier)
.worksOnPublicHoliday(WorksOnPublicHoliday.fromBoolean(entity.isWorksOnPublicHoliday()))
.monday(Duration.parse(entity.getMonday()))
.tuesday(Duration.parse(entity.getTuesday()))
.wednesday(Duration.parse(entity.getWednesday()))
Expand All @@ -424,7 +419,7 @@ private WorkingTimeEntity workingTimeToEntity(WorkingTime workingTime) {
entity.setUserId(workingTime.userLocalId().value());
entity.setValidFrom(workingTime.validFrom().orElse(null));
entity.setFederalState(workingTime.federalState());
entity.setWorksOnPublicHoliday(workingTime.isWorksOnPublicHolidayGlobal() ? null : workingTime.worksOnPublicHoliday());
entity.setWorksOnPublicHoliday(workingTime.worksOnPublicHoliday().asBoolean());
entity.setMonday(workdayToDurationString(workingTime.getMonday()));
entity.setTuesday(workdayToDurationString(workingTime.getTuesday()));
entity.setWednesday(workdayToDurationString(workingTime.getWednesday()));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.focusshift.zeiterfassung.workingtime;

import de.focusshift.zeiterfassung.publicholiday.FederalState;
import de.focusshift.zeiterfassung.settings.FederalStateSettings;
import de.focusshift.zeiterfassung.user.HasUserIdComposite;
import de.focusshift.zeiterfassung.user.UserIdComposite;
import jakarta.annotation.Nullable;
Expand Down Expand Up @@ -29,6 +30,7 @@
import static java.time.DayOfWeek.TUESDAY;
import static java.time.DayOfWeek.WEDNESDAY;
import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNullElseGet;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.toSet;
import static org.apache.commons.collections4.map.UnmodifiableMap.unmodifiableMap;
Expand All @@ -45,9 +47,8 @@ public final class WorkingTime implements HasUserIdComposite {
private final LocalDate validTo;
private final LocalDate minValidFrom;
private final FederalState federalState;
private final Supplier<FederalState> globalFederalStateSupplier;
private final boolean worksOnPublicHoliday;
private final boolean worksOnPublicHolidayGlobal;
private final Supplier<FederalStateSettings> federalStateSettingsSupplier;
private final WorksOnPublicHoliday worksOnPublicHoliday;
private final EnumMap<DayOfWeek, PlannedWorkingHours> workdays;

private WorkingTime(Builder builder) {
Expand All @@ -58,9 +59,8 @@ private WorkingTime(Builder builder) {
this.validTo = builder.validTo;
this.minValidFrom = builder.minValidFrom;
this.federalState = builder.federalState;
this.globalFederalStateSupplier = builder.globalFederalStateSupplier;
this.federalStateSettingsSupplier = builder.globalFederalStateSettingsSupplier;
this.worksOnPublicHoliday = builder.worksOnPublicHoliday;
this.worksOnPublicHolidayGlobal = builder.worksOnPublicHolidayGlobal;
this.workdays = builder.workDays;
}

Expand Down Expand Up @@ -121,22 +121,19 @@ public FederalState federalState() {
* never {@linkplain FederalState#GLOBAL}, can be {@linkplain FederalState#NONE}
*/
public FederalState actualFederalState() {
return federalState.equals(GLOBAL) ? globalFederalStateSupplier.get() : federalState;
return federalState.equals(GLOBAL) ? federalStateSettingsSupplier.get().federalState() : federalState;
}

/**
* Whether the related person works on public holidays or not.
* Check {@linkplain WorkingTime#isWorksOnPublicHolidayGlobal()} if it is the system-wide setting or not.
*/
public boolean worksOnPublicHoliday() {
public WorksOnPublicHoliday worksOnPublicHoliday() {
return worksOnPublicHoliday;
}

/**
* Whether the {@linkplain WorkingTime#worksOnPublicHoliday()} value is the system-wide setting or not.
*/
public boolean isWorksOnPublicHolidayGlobal() {
return worksOnPublicHolidayGlobal;
public boolean actualWorksOnPublicHoliday() {
return requireNonNullElseGet(worksOnPublicHoliday.asBoolean(),
() -> federalStateSettingsSupplier.get().worksOnPublicHoliday());
}

public Map<DayOfWeek, PlannedWorkingHours> workdays() {
Expand Down Expand Up @@ -266,9 +263,8 @@ public static class Builder {
private LocalDate validTo;
private LocalDate minValidFrom;
private FederalState federalState;
private Supplier<FederalState> globalFederalStateSupplier;
private boolean worksOnPublicHoliday;
private boolean worksOnPublicHolidayGlobal;
private WorksOnPublicHoliday worksOnPublicHoliday;
private Supplier<FederalStateSettings> globalFederalStateSettingsSupplier;
private final EnumMap<DayOfWeek, PlannedWorkingHours> workDays = new EnumMap<>(Map.of(
MONDAY, PlannedWorkingHours.ZERO,
TUESDAY, PlannedWorkingHours.ZERO,
Expand Down Expand Up @@ -309,14 +305,13 @@ public Builder federalState(FederalState federalState) {
return this;
}

public Builder globalFederalStateSupplier(Supplier<FederalState> globalFederalStateSupplier) {
this.globalFederalStateSupplier = globalFederalStateSupplier;
public Builder worksOnPublicHoliday(WorksOnPublicHoliday worksOnPublicHoliday) {
this.worksOnPublicHoliday = worksOnPublicHoliday;
return this;
}

public Builder worksOnPublicHoliday(boolean worksOnPublicHoliday, boolean isGlobal) {
this.worksOnPublicHoliday = worksOnPublicHoliday;
this.worksOnPublicHolidayGlobal = isGlobal;
public Builder federalStateSettingsSupplier(Supplier<FederalStateSettings> globalFederalStateSettingsSupplier) {
this.globalFederalStateSettingsSupplier = globalFederalStateSettingsSupplier;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private WorkingTimeCalendar toWorkingTimeCalendar(LocalDate from, LocalDate toEx
final DateRange workingTimeDateRange = getDateRange(from, workingTime, nextEnd);

for (LocalDate localDate : workingTimeDateRange) {
if (workingTime.worksOnPublicHoliday() || !isPublicHoliday.test(localDate, workingTime.actualFederalState())) {
if (workingTime.actualWorksOnPublicHoliday() || !isPublicHoliday.test(localDate, workingTime.actualFederalState())) {
plannedWorkingHoursByDate.put(localDate, workingTime.getForDayOfWeek(localDate.getDayOfWeek()));
} else {
plannedWorkingHoursByDate.put(localDate, PlannedWorkingHours.ZERO);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package de.focusshift.zeiterfassung.workingtime;

import de.focusshift.zeiterfassung.settings.FederalStateSettings;
import jakarta.annotation.Nullable;

import static java.lang.Boolean.TRUE;

/**
* Defines whether a person works on a public holiday or not, or if the global setting should be used.
*/
public enum WorksOnPublicHoliday {

/**
* global settings should be considered. can be obtained by {@linkplain FederalStateSettings#worksOnPublicHoliday()}
*/
GLOBAL(null),

/**
* overrides global settings with `true`
*/
YES(TRUE),

/**
* overrides global settings with `false`
*/
NO(Boolean.FALSE);

private final Boolean boolValue;

WorksOnPublicHoliday(Boolean boolValue) {
this.boolValue = boolValue;
}

/**
* @return the boolean value for this enum, {@code null} when {@linkplain WorksOnPublicHoliday#GLOBAL}
*/
@Nullable
public Boolean asBoolean() {
return boolValue;
}

public boolean isTrue() {
return YES.equals(this);
}

public static WorksOnPublicHoliday fromBoolean(@Nullable Boolean boolValue) {
return switch (boolValue) {
case null -> GLOBAL;
case Boolean b -> TRUE.equals(b) ? YES : NO;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import de.focusshift.zeiterfassung.workingtime.WorkingTime;
import de.focusshift.zeiterfassung.workingtime.WorkingTimeId;
import de.focusshift.zeiterfassung.workingtime.WorkingTimeService;
import de.focusshift.zeiterfassung.workingtime.WorksOnPublicHoliday;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -36,6 +37,7 @@
import java.util.UUID;

import static de.focusshift.zeiterfassung.publicholiday.FederalState.GERMANY_BADEN_WUERTTEMBERG;
import static de.focusshift.zeiterfassung.publicholiday.FederalState.GERMANY_BAYERN;
import static de.focusshift.zeiterfassung.publicholiday.FederalState.GERMANY_BERLIN;
import static java.time.DayOfWeek.FRIDAY;
import static java.time.DayOfWeek.MONDAY;
Expand Down Expand Up @@ -247,7 +249,7 @@ void ensureGetEditPage() throws Exception {
.thenReturn(new FederalStateSettings(GERMANY_BERLIN, true));

final WorkingTimeId workingTimeId = new WorkingTimeId(UUID.randomUUID());
final WorkingTime workingTime = WorkingTime.builder(userIdComposite, workingTimeId).build();
final WorkingTime workingTime = WorkingTime.builder(userIdComposite, workingTimeId).worksOnPublicHoliday(WorksOnPublicHoliday.GLOBAL).build();
when(workingTimeService.getWorkingTimeById(workingTimeId)).thenReturn(Optional.of(workingTime));

perform(
Expand Down Expand Up @@ -280,6 +282,7 @@ void ensureGetEditPage(boolean globalWorksOnPublicHoliday, Integer expectedValue

final WorkingTimeId workingTimeId = new WorkingTimeId(UUID.randomUUID());
final WorkingTime workingTime = WorkingTime.builder(userIdComposite, workingTimeId)
.worksOnPublicHoliday(WorksOnPublicHoliday.GLOBAL)
.build();

when(workingTimeService.getWorkingTimeById(workingTimeId)).thenReturn(Optional.of(workingTime));
Expand Down Expand Up @@ -414,7 +417,6 @@ void ensureEditWithValidationError() throws Exception {
)))
.andExpect(model().attribute("selectedUser", new UserDto(42, "Clark", "Kent", "Clark Kent", "[email protected]")))
.andExpect(model().attribute("workingTime", expectedWorkingTimeDto))
.andExpect(model().attribute("globalFederalState", GERMANY_BERLIN))
.andExpect(model().attribute("globalFederalStateMessageKey", "federalState.GERMANY_BERLIN"))
.andExpect(model().attribute("personSearchFormAction", is("/users/42")));

Expand Down Expand Up @@ -470,7 +472,7 @@ void ensureEditWithValidationErrorAllowedToEditX(String authority, boolean editW
@Test
void ensureEditWithValidationErrorJavaScript() throws Exception {

when(federalStateSettingsService.getFederalStateSettings()).thenReturn(federalStateSettings(GERMANY_BERLIN));
when(federalStateSettingsService.getFederalStateSettings()).thenReturn(federalStateSettings(GERMANY_BAYERN));

final WorkingTimeId workingTimeId = new WorkingTimeId(UUID.randomUUID());

Expand Down Expand Up @@ -518,8 +520,7 @@ void ensureEditWithValidationErrorJavaScript() throws Exception {
)))
.andExpect(model().attribute("selectedUser", new UserDto(42, "Clark", "Kent", "Clark Kent", "[email protected]")))
.andExpect(model().attribute("workingTime", expectedWorkingTimeDto))
.andExpect(model().attribute("globalFederalState", GERMANY_BERLIN))
.andExpect(model().attribute("globalFederalStateMessageKey", "federalState.GERMANY_BERLIN"))
.andExpect(model().attribute("globalFederalStateMessageKey", "federalState.GERMANY_BAYERN"))
.andExpect(model().attribute("personSearchFormAction", is("/users/42")));

verifyNoInteractions(workingTimeService);
Expand Down
Loading

0 comments on commit b1ce660

Please sign in to comment.