Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Archivierungsfunktion #867

Closed
wants to merge 11 commits into from
Closed
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
4 changes: 4 additions & 0 deletions backend/src/main/java/ch/puzzle/okr/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ private Constants() {
public static final String QUARTER = "Quarter";
public static final String TEAM = "Team";
public static final String USER = "User";
public static final String BACKLOG = "Backlog";
public static final Long BACKLOG_QUARTER_ID = 999L;
public static final String ARCHIVE = "Archiv";
public static final Long ARCHIVE_QUARTER_ID = 998L;
}
3 changes: 2 additions & 1 deletion backend/src/main/java/ch/puzzle/okr/dto/ObjectiveDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
import java.time.LocalDateTime;

public record ObjectiveDto(Long id, int version, String title, Long teamId, Long quarterId, String quarterLabel,
String description, State state, LocalDateTime createdOn, LocalDateTime modifiedOn, boolean writeable) {
String description, State state, LocalDateTime createdOn, LocalDateTime modifiedOn, boolean writeable,
boolean archived) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ public ObjectiveMapper(TeamBusinessService teamBusinessService, QuarterBusinessS
this.quarterBusinessService = quarterBusinessService;
}

// TODO: Adjust Unit Tests of ObjectiveMapper after merge of multitenancy-main
lkleisa marked this conversation as resolved.
Show resolved Hide resolved

public ObjectiveDto toDto(Objective objective) {
return new ObjectiveDto(objective.getId(), objective.getVersion(), objective.getTitle(),
objective.getTeam().getId(), objective.getQuarter().getId(), objective.getQuarter().getLabel(),
objective.getDescription(), objective.getState(), objective.getCreatedOn(), objective.getModifiedOn(),
objective.isWriteable());
objective.isWriteable(), objective.isArchived());
}

public Objective toObjective(ObjectiveDto objectiveDto) {
return Objective.Builder.builder().withId(objectiveDto.id()).withVersion(objectiveDto.version())
.withTitle(objectiveDto.title()).withTeam(teamBusinessService.getTeamById(objectiveDto.teamId()))
.withDescription(objectiveDto.description()).withModifiedOn(LocalDateTime.now())
.withState(objectiveDto.state()).withCreatedOn(objectiveDto.createdOn())
.withQuarter(quarterBusinessService.getQuarterById(objectiveDto.quarterId())).build();
.withQuarter(quarterBusinessService.getQuarterById(objectiveDto.quarterId()))
.withArchived(objectiveDto.archived()).build();
}
}
26 changes: 22 additions & 4 deletions backend/src/main/java/ch/puzzle/okr/models/Objective.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public class Objective implements WriteableInterface {
@ManyToOne
private User modifiedBy;

private boolean archived = false;

private transient boolean writeable;

public Objective() {
Expand All @@ -68,6 +70,7 @@ private Objective(Builder builder) {
setState(builder.state);
setCreatedOn(builder.createdOn);
setModifiedBy(builder.modifiedBy);
setArchived(builder.archived);
}

public Long getId() {
Expand Down Expand Up @@ -150,6 +153,14 @@ public void setModifiedBy(User modifiedBy) {
this.modifiedBy = modifiedBy;
}

public boolean isArchived() {
return archived;
}

public void setArchived(boolean archived) {
this.archived = archived;
}

@Override
public boolean isWriteable() {
return writeable;
Expand All @@ -165,7 +176,7 @@ public String toString() {
return "Objective{" + "id=" + id + ", version=" + version + ", title='" + title + '\'' + ", createdBy="
+ createdBy + ", team=" + team + ", quarter=" + quarter + ", description='" + description + '\''
+ ", modifiedOn=" + modifiedOn + ", state=" + state + ", createdOn=" + createdOn + ", modifiedBy="
+ modifiedBy + ", writeable=" + writeable + '\'' + '}';
+ modifiedBy + ", archived=" + archived + ", writeable=" + writeable + '\'' + '}';
}

@Override
Expand All @@ -180,13 +191,14 @@ public boolean equals(Object o) {
&& Objects.equals(team, objective.team) && Objects.equals(quarter, objective.quarter)
&& Objects.equals(description, objective.description)
&& Objects.equals(modifiedOn, objective.modifiedOn) && state == objective.state
&& Objects.equals(createdOn, objective.createdOn) && Objects.equals(modifiedBy, objective.modifiedBy);
&& Objects.equals(createdOn, objective.createdOn) && Objects.equals(modifiedBy, objective.modifiedBy)
&& Objects.equals(archived, objective.archived);
}

@Override
public int hashCode() {
return Objects.hash(id, version, title, createdBy, team, quarter, description, modifiedOn, state, createdOn,
modifiedBy);
return Objects.hash(id, version, title, state, description, team, quarter, createdBy, createdOn, modifiedOn,
modifiedBy, archived);
}

public static final class Builder {
Expand All @@ -201,6 +213,7 @@ public static final class Builder {
private State state;
private LocalDateTime createdOn;
private User modifiedBy;
private boolean archived;

private Builder() {
}
Expand Down Expand Up @@ -264,6 +277,11 @@ public Builder withModifiedBy(User modifiedBy) {
return this;
}

public Builder withArchived(boolean archived) {
this.archived = archived;
return this;
}

public Objective build() {
return new Objective(this);
}
Expand Down
30 changes: 21 additions & 9 deletions backend/src/main/java/ch/puzzle/okr/models/overview/Overview.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class Overview implements WriteableInterface {
@Enumerated(EnumType.STRING)
private State objectiveState;
private LocalDateTime objectiveCreatedOn;
private boolean objectiveArchived;
private Long quarterId;
private String quarterLabel;
private String keyResultTitle;
Expand Down Expand Up @@ -49,6 +50,7 @@ private Overview(Builder builder) {
objectiveTitle = builder.objectiveTitle;
objectiveState = builder.objectiveState;
objectiveCreatedOn = builder.objectiveCreatedOn;
objectiveArchived = builder.objectiveArchived;
quarterId = builder.quarterId;
quarterLabel = builder.quarterLabel;
keyResultTitle = builder.keyResultTitle;
Expand Down Expand Up @@ -89,6 +91,10 @@ public LocalDateTime getObjectiveCreatedOn() {
return objectiveCreatedOn;
}

public boolean isObjectiveArchived() {
return objectiveArchived;
}

public Long getQuarterId() {
return quarterId;
}
Expand Down Expand Up @@ -157,15 +163,15 @@ public void setWriteable(boolean writeable) {

@Override
public String toString() {
return "Overview{" + "overviewId=" + overviewId + ", teamVersion='" + teamVersion + ", teamName='" + teamName
+ '\'' + ", objectiveTitle='" + objectiveTitle + '\'' + ", objectiveState=" + objectiveState
+ ", objectiveCreatedOn=" + objectiveCreatedOn + ", quarterId=" + quarterId + ", quarterLabel='"
+ quarterLabel + '\'' + ", keyResultTitle='" + keyResultTitle + '\'' + ", keyResultType='"
+ keyResultType + '\'' + ", baseline=" + baseline + ", stretchGoal=" + stretchGoal + ", unit='" + unit
+ '\'' + ", commitZone='" + commitZone + '\'' + ", targetZone='" + targetZone + '\'' + ", stretchZone='"
+ stretchZone + '\'' + ", checkInValue=" + checkInValue + ", checkInZone='" + checkInZone + '\''
+ ", confidence=" + confidence + ", createdOn=" + checkInCreatedOn + ", writeable=" + writeable + '\''
+ '}';
return "Overview{" + "overviewId=" + overviewId + ", teamName='" + teamName + '\'' + ", teamVersion="
+ teamVersion + ", objectiveTitle='" + objectiveTitle + '\'' + ", objectiveState=" + objectiveState
+ ", objectiveCreatedOn=" + objectiveCreatedOn + ", objectiveArchived=" + objectiveArchived
+ ", quarterId=" + quarterId + ", quarterLabel='" + quarterLabel + '\'' + ", keyResultTitle='"
+ keyResultTitle + '\'' + ", keyResultType='" + keyResultType + '\'' + ", baseline=" + baseline
+ ", stretchGoal=" + stretchGoal + ", unit='" + unit + '\'' + ", commitZone='" + commitZone + '\''
+ ", targetZone='" + targetZone + '\'' + ", stretchZone='" + stretchZone + '\'' + ", checkInValue="
+ checkInValue + ", checkInZone='" + checkInZone + '\'' + ", confidence=" + confidence
+ ", checkInCreatedOn=" + checkInCreatedOn + ", writeable=" + writeable + '}';
}

public static final class Builder {
Expand All @@ -175,6 +181,7 @@ public static final class Builder {
private String objectiveTitle;
private State objectiveState;
private LocalDateTime objectiveCreatedOn;
private boolean objectiveArchived;
private Long quarterId;
private String quarterLabel;
private String keyResultTitle;
Expand Down Expand Up @@ -227,6 +234,11 @@ public Builder withObjectiveCreatedOn(LocalDateTime objectiveCreatedOn) {
return this;
}

public Builder withObjectiveArchived(boolean objectiveArchived) {
this.objectiveArchived = objectiveArchived;
return this;
}

public Builder withQuarterId(Long quarterId) {
this.quarterId = quarterId;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ public KeyResultAuthorizationService(KeyResultBusinessService keyResultBusinessS
super(keyResultBusinessService, authorizationService);
}

@Override
public KeyResult getEntityById(Long id) {
AuthorizationUser authorizationUser = getAuthorizationService().getAuthorizationUser();
hasRoleReadById(id, authorizationUser);
KeyResult keyResult = getBusinessService().getEntityById(id);
if (!keyResult.getObjective().isArchived()) {
keyResult.setWriteable(isWriteable(keyResult, authorizationUser));
}
return keyResult;
}

@Override
protected void hasRoleReadById(Long id, AuthorizationUser authorizationUser) {
getAuthorizationService().hasRoleReadByKeyResultId(id, authorizationUser);
Expand All @@ -45,7 +56,9 @@ public List<CheckIn> getAllCheckInsByKeyResult(Long keyResultId) {
AuthorizationUser authorizationUser = getAuthorizationService().getAuthorizationUser();
getAuthorizationService().hasRoleReadByKeyResultId(keyResultId, authorizationUser);
List<CheckIn> checkIns = getBusinessService().getAllCheckInsByKeyResult(keyResultId);
setRoleCreateOrUpdateCheckIn(checkIns, authorizationUser);
if (!checkIns.get(0).getKeyResult().getObjective().isArchived()) {
setRoleCreateOrUpdateCheckIn(checkIns, authorizationUser);
}
return checkIns;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ public Objective duplicateEntity(Long id, Objective objective) {
return getBusinessService().duplicateObjective(id, objective, authorizationUser);
}

@Override
public Objective getEntityById(Long id) {
AuthorizationUser authorizationUser = getAuthorizationService().getAuthorizationUser();
hasRoleReadById(id, authorizationUser);
Objective objective = getBusinessService().getEntityById(id);
if (!objective.isArchived()) {
objective.setWriteable(isWriteable(objective, authorizationUser));
}
return objective;
}

@Override
protected void hasRoleReadById(Long id, AuthorizationUser authorizationUser) {
getAuthorizationService().hasRoleReadByObjectiveId(id, authorizationUser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static ch.puzzle.okr.Constants.ARCHIVE_QUARTER_ID;
import static ch.puzzle.okr.service.authorization.AuthorizationService.hasRoleWriteAll;

@Service
Expand All @@ -28,7 +30,10 @@ public List<Overview> getFilteredOverview(Long quarterId, List<Long> teamIds, St
AuthorizationUser authorizationUser = authorizationService.getAuthorizationUser();
List<Overview> overviews = overviewBusinessService.getFilteredOverview(quarterId, teamIds, objectiveQuery,
authorizationUser);
setRoleCreateOrUpdateTeam(overviews, authorizationUser);
// TODO Search for 998 in all Flyway/SQL Scripts and check that it is everywhere considered
if (Objects.isNull(quarterId) || !quarterId.equals(ARCHIVE_QUARTER_ID)) {
setRoleCreateOrUpdateTeam(overviews, authorizationUser);
}
return overviews;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public ObjectiveBusinessService(@Lazy KeyResultBusinessService keyResultBusiness
this.completedBusinessService = completedBusinessService;
}

public List<Objective> getAllObjectives() {
return objectivePersistenceService.findAll();
}

public Objective getEntityById(Long id) {
validator.validateOnGet(id);
return objectivePersistenceService.findById(id);
Expand All @@ -55,6 +59,7 @@ public Objective updateEntity(Long id, Objective objective, AuthorizationUser au
objective.setCreatedOn(savedObjective.getCreatedOn());
objective.setModifiedBy(authorizationUser.user());
objective.setModifiedOn(LocalDateTime.now());
objective.setArchived(false);
String not = " ";
if (isImUsed(objective, savedObjective)) {
objective.setQuarter(savedObjective.getQuarter());
Expand Down Expand Up @@ -87,6 +92,7 @@ private static boolean hasQuarterChanged(Objective objective, Objective savedObj
public Objective createEntity(Objective objective, AuthorizationUser authorizationUser) {
objective.setCreatedBy(authorizationUser.user());
objective.setCreatedOn(LocalDateTime.now());
objective.setArchived(false);
validator.validateOnCreate(objective);
return objectivePersistenceService.save(objective);
}
Expand Down Expand Up @@ -121,4 +127,13 @@ public void deleteEntityById(Long id) {
.forEach(keyResult -> keyResultBusinessService.deleteEntityById(keyResult.getId()));
objectivePersistenceService.deleteById(id);
}

@Transactional
public void archiveEntity(Long id) {
Objective savedObjective = objectivePersistenceService.findById(id);
if (savedObjective != null) {
savedObjective.setArchived(true);
objectivePersistenceService.save(savedObjective);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package ch.puzzle.okr.service.business;

import ch.puzzle.okr.models.Objective;
import ch.puzzle.okr.models.Quarter;
import ch.puzzle.okr.service.persistence.QuarterPersistenceService;
import ch.puzzle.okr.service.validation.QuarterValidationService;
import jakarta.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -15,12 +17,16 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static ch.puzzle.okr.Constants.*;

@Service
public class QuarterBusinessService {
private static final Logger logger = LoggerFactory.getLogger(QuarterBusinessService.class);

private final QuarterPersistenceService quarterPersistenceService;
private final ObjectiveBusinessService objectiveBusinessService;
private final QuarterValidationService validator;

@Value("${okr.quarter.business.year.start}")
Expand All @@ -30,8 +36,9 @@ public class QuarterBusinessService {
private String quarterFormat;

public QuarterBusinessService(QuarterPersistenceService quarterPersistenceService,
QuarterValidationService validator) {
ObjectiveBusinessService objectiveBusinessService, QuarterValidationService validator) {
this.quarterPersistenceService = quarterPersistenceService;
this.objectiveBusinessService = objectiveBusinessService;
this.validator = validator;
}

Expand All @@ -42,8 +49,10 @@ public Quarter getQuarterById(Long quarterId) {

public List<Quarter> getQuarters() {
List<Quarter> mostCurrentQuarterList = quarterPersistenceService.getMostCurrentQuarters();
lkleisa marked this conversation as resolved.
Show resolved Hide resolved
Quarter backlog = quarterPersistenceService.findByLabel("Backlog");
Quarter backlog = quarterPersistenceService.findByLabel(BACKLOG);
Quarter archive = quarterPersistenceService.findByLabel(ARCHIVE);
mostCurrentQuarterList.add(0, backlog);
mostCurrentQuarterList.add(archive);
return mostCurrentQuarterList;
}

Expand Down Expand Up @@ -75,12 +84,14 @@ private int getStartOfBusinessYear(YearMonth startOfQuarter, int quarter) {
return startOfQuarter.minusMonths((quarter - 1) * 3L).getYear();
}

private void generateQuarter(LocalDateTime start, String label) {
@Transactional
protected void generateQuarter(LocalDateTime start, String label) {
YearMonth yearMonth = YearMonth.from(start);
Quarter quarter = Quarter.Builder.builder().withLabel(label).withStartDate(start.toLocalDate())
.withEndDate(yearMonth.plusMonths(2).atEndOfMonth()).build();
validator.validateOnGeneration(quarter);
quarterPersistenceService.save(quarter);
moveObjectsFromNonMostCurrentQuartersIntoArchive();
}

private boolean inLastMonthOfQuarter(int currentQuarter, int nextQuarter) {
Expand All @@ -105,6 +116,21 @@ Map<Integer, Integer> generateQuarters() {
return quarters;
}

@Transactional
protected void moveObjectsFromNonMostCurrentQuartersIntoArchive() {
List<Quarter> mostCurrentQuarterList = quarterPersistenceService.getMostCurrentQuarters();
List<Objective> allObjectives = objectiveBusinessService.getAllObjectives();

allObjectives.forEach(objective -> {
if (!mostCurrentQuarterList.contains(objective.getQuarter())
&& !Objects.equals(objective.getQuarter().getId(), BACKLOG_QUARTER_ID)) {
objectiveBusinessService.archiveEntity(objective.getId());
}
});
logger.info("Update archived Objectives");
}

@Transactional
@Scheduled(cron = "0 59 23 L * ?") // Cron expression for 23:59:00 on the last day of every month
public void scheduledGenerationQuarters() {
Map<Integer, Integer> quarters = generateQuarters();
Expand Down
Loading
Loading