Skip to content

Commit

Permalink
Work state transition (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
haiphucnguyen authored Nov 30, 2024
1 parent 2f3c5b5 commit c5076f1
Show file tree
Hide file tree
Showing 32 changed files with 579 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.persistence.MappedSuperclass;
import java.io.Serializable;
import java.time.Instant;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
Expand Down Expand Up @@ -46,6 +47,7 @@ public abstract class AbstractAuditingEntity<T> implements Serializable {
private User createdByUser;

@CreatedDate
@Builder.Default
@Column(name = "created_at", updatable = false)
private Instant createdAt = Instant.now();

Expand All @@ -58,6 +60,7 @@ public abstract class AbstractAuditingEntity<T> implements Serializable {
private User modifiedByUser;

@LastModifiedDate
@Builder.Default
@Column(name = "modified_at")
private Instant modifiedAt = Instant.now();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.flexwork.modules.collab.domain;

import io.flexwork.modules.audit.AbstractAuditingEntity;
import io.flexwork.modules.usermanagement.domain.User;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -10,7 +11,6 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -22,7 +22,7 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Notification {
public class Notification extends AbstractAuditingEntity<Long> {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -31,9 +31,6 @@ public class Notification {
@Column(nullable = false)
private String content;

@Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMPTZ")
private LocalDateTime createdAt;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.flexwork.modules.collab.service.dto;

import java.time.LocalDateTime;
import java.time.Instant;
import lombok.Builder;
import lombok.Data;

Expand All @@ -9,7 +9,8 @@
public class NotificationDTO {
private Long id;
private String content;
private LocalDateTime createdAt;
private Long userId;
private boolean isRead;
private Instant createdAt;
private Instant modifiedAt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public class ValueDefinition {
private String description;

@Column(name = "is_default", nullable = false)
@Builder.Default
private Boolean isDefault = false;

@Column(name = "created_at", nullable = false, updatable = false)
@Builder.Default
private LocalDateTime createdAt = LocalDateTime.now();
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,27 @@ public class Team {
private Organization organization;

@EqualsAndHashCode.Exclude
@Builder.Default
@ManyToMany(mappedBy = "teams")
private Set<User> users = new HashSet<>();

@EqualsAndHashCode.Exclude
@Builder.Default
@OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<UserTeam> teamMembers = new HashSet<>();

@EqualsAndHashCode.Exclude
@Builder.Default
@OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<UserTeam> userTeams = new HashSet<>();

@EqualsAndHashCode.Exclude
@Builder.Default
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Workflow> workflows = new HashSet<>();

@EqualsAndHashCode.Exclude
@Builder.Default
@OneToMany(mappedBy = "team", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<TeamWorkflowSelection> workflowUsages = new HashSet<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand Down Expand Up @@ -51,8 +52,6 @@ public class TeamRequest extends AbstractAuditingEntity<Long> {

private String requestDescription;

private String currentState;

@Column(nullable = false, length = 50)
@Enumerated(EnumType.STRING)
private TeamRequestPriority priority;
Expand All @@ -69,10 +68,17 @@ public class TeamRequest extends AbstractAuditingEntity<Long> {
@Column(name = "actual_completion_date")
private LocalDate actualCompletionDate;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "current_state_id")
private WorkflowState currentState;

@Column(name = "channel")
@Convert(converter = TicketChannelConverter.class)
private TicketChannel channel;

@Column(name = "is_new", nullable = false)
private Boolean isNew = true;

@Column(name = "is_completed", nullable = false)
private boolean isCompleted = false;
private Boolean isCompleted = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "fw_workflow_transition")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "fw_workflow_transition")
public class WorkflowTransition {

@Id
Expand All @@ -29,11 +29,20 @@ public class WorkflowTransition {
@JoinColumn(name = "workflow_id", nullable = false)
private Workflow workflow;

private String sourceState;
private String targetState;
@ManyToOne
@JoinColumn(name = "source_state_id", nullable = false)
private WorkflowState sourceState;

@ManyToOne
@JoinColumn(name = "target_state_id", nullable = false)
private WorkflowState targetState;

@Column(name = "event_name", nullable = false)
private String eventName;

@Column(name = "sla_duration")
private Long slaDuration;

@Column(name = "escalate_on_violation", nullable = false)
private Boolean escalateOnViolation;
private boolean escalateOnViolation;
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package io.flexwork.modules.teams.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -29,10 +30,23 @@ public class WorkflowTransitionHistory {
@JoinColumn(name = "team_request_id", nullable = false)
private TeamRequest teamRequest;

private String fromState;
private String toState;
@ManyToOne
@JoinColumn(name = "from_state_id", nullable = false)
private WorkflowState fromState;

@ManyToOne
@JoinColumn(name = "to_state_id", nullable = false)
private WorkflowState toState;

@Column(name = "event_name", nullable = false)
private String eventName;
private LocalDateTime transitionDate;
private LocalDateTime slaDueDate;

@Column(name = "transition_date", nullable = false)
private ZonedDateTime transitionDate;

@Column(name = "sla_due_date")
private ZonedDateTime slaDueDate;

@Column(name = "status")
private String status;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.flexwork.modules.audit.EntityFieldHandler;
import io.flexwork.modules.collab.domain.EntityType;
import io.flexwork.modules.teams.domain.TicketChannel;
import io.flexwork.modules.teams.repository.WorkflowStateRepository;
import io.flexwork.modules.teams.service.dto.TeamRequestDTO;
import io.flexwork.modules.usermanagement.repository.UserRepository;
import java.util.Optional;
Expand All @@ -14,8 +15,12 @@ public class TeamRequestFieldHandlerRegistry extends AbstractEntityFieldHandlerR

private final UserRepository userRepository;

public TeamRequestFieldHandlerRegistry(UserRepository userRepository) {
private final WorkflowStateRepository workflowStateRepository;

public TeamRequestFieldHandlerRegistry(
UserRepository userRepository, WorkflowStateRepository workflowStateRepository) {
this.userRepository = userRepository;
this.workflowStateRepository = workflowStateRepository;
}

@Override
Expand All @@ -35,7 +40,18 @@ protected void initializeFieldHandlers() {
addFieldHandler(
"actualCompletionDate",
new EntityFieldHandler<TeamRequestDTO>("Actual Completion Date"));
addFieldHandler("currentState", new EntityFieldHandler<TeamRequestDTO>("Current State"));
addFieldHandler(
"currentStateId",
new EntityFieldHandler<TeamRequestDTO>(
"State",
(objectVal, fieldVal) ->
Optional.ofNullable(fieldVal)
.flatMap(
id ->
workflowStateRepository
.findById((Long) id)
.map(state -> state.getStateName()))
.orElse("")));
addFieldHandler(
"assignUserId",
new EntityFieldHandler<>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.flexwork.modules.teams.domain.TeamRequest;
import io.flexwork.modules.teams.service.dto.PriorityDistributionDTO;
import io.flexwork.modules.teams.service.dto.SlaDurationDTO;
import io.flexwork.modules.teams.service.dto.TicketDistributionDTO;
import java.util.List;
import java.util.Optional;
Expand All @@ -20,10 +19,10 @@
public interface TeamRequestRepository
extends JpaRepository<TeamRequest, Long>, JpaSpecificationExecutor<TeamRequest> {

@EntityGraph(attributePaths = {"team", "requestUser", "assignUser", "workflow"})
@EntityGraph(attributePaths = {"team", "requestUser", "assignUser", "workflow", "currentState"})
Page<TeamRequest> findAll(Specification<TeamRequest> spec, Pageable pageable);

@EntityGraph(attributePaths = {"team", "requestUser", "assignUser", "workflow"})
@EntityGraph(attributePaths = {"team", "requestUser", "assignUser", "workflow", "currentState"})
Optional<TeamRequest> findById(@Param("id") Long id);

@EntityGraph(attributePaths = {"team", "requestUser", "assignUser", "workflow"})
Expand Down Expand Up @@ -60,23 +59,6 @@ public interface TeamRequestRepository
""")
Optional<TeamRequest> findNextEntity(@Param("requestId") Long requestId);

@Query(
"""
SELECT new io.flexwork.modules.teams.service.dto.SlaDurationDTO(
tr.sourceState,
tr.targetState,
tr.slaDuration,
tr.eventName
)
FROM TeamRequest r
JOIN WorkflowTransition tr
ON r.workflow.id = tr.workflow.id
AND r.currentState = tr.sourceState
WHERE r.id = :teamRequestId
""")
List<SlaDurationDTO> findSlaDurationsForCurrentState(
@Param("teamRequestId") Long teamRequestId);

/**
* Finds all distinct workflow IDs associated with team requests.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.flexwork.modules.teams.repository;

import io.flexwork.modules.teams.domain.WorkflowState;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -13,6 +12,4 @@ public interface WorkflowStateRepository extends JpaRepository<WorkflowState, Lo
@Query(
"SELECT ws FROM WorkflowState ws WHERE ws.workflow.id = :workflowId AND ws.isInitial = true")
WorkflowState findInitialStateByWorkflowId(@Param("workflowId") Long workflowId);

List<WorkflowState> findByWorkflowId(Long workflowId);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
package io.flexwork.modules.teams.repository;

import io.flexwork.modules.teams.domain.WorkflowTransitionHistory;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface WorkflowTransitionHistoryRepository
extends JpaRepository<WorkflowTransitionHistory, Long> {}
extends JpaRepository<WorkflowTransitionHistory, Long> {

/**
* Finds and sorts the workflow transition history for a specific team request.
*
* @param teamRequestId the ID of the team request
* @return a list of WorkflowTransitionHistory sorted by transitionDate
*/
@Query(
"SELECT wth FROM WorkflowTransitionHistory wth "
+ "WHERE wth.teamRequest.id = :teamRequestId "
+ "ORDER BY wth.transitionDate ASC")
List<WorkflowTransitionHistory> findByTeamRequestId(@Param("teamRequestId") Long teamRequestId);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
package io.flexwork.modules.teams.repository;

import io.flexwork.modules.teams.domain.WorkflowState;
import io.flexwork.modules.teams.domain.WorkflowTransition;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface WorkflowTransitionRepository extends JpaRepository<WorkflowTransition, Long> {}
public interface WorkflowTransitionRepository extends JpaRepository<WorkflowTransition, Long> {
/**
* Finds all valid target workflow states for a given workflow and current state.
*
* @param workflowId the ID of the workflow
* @param sourceStateId the name of the current state
* @return a list of WorkflowState objects representing valid target states
*/
@Query(
"SELECT ws FROM WorkflowState ws "
+ "JOIN WorkflowTransition wt ON ws.id = wt.targetState.id "
+ "WHERE wt.workflow.id = :workflowId AND wt.sourceState.id = :sourceStateId")
List<WorkflowState> findValidTargetStates(
@Param("workflowId") Long workflowId, @Param("sourceStateId") Long sourceStateId);

Optional<WorkflowTransition> findByWorkflowIdAndSourceStateIdAndTargetStateId(
Long workflowId, Long sourceStateId, Long targetStateId);
}
Loading

0 comments on commit c5076f1

Please sign in to comment.