Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
haiphucnguyen committed Dec 10, 2024
1 parent e9e9e6e commit 27aa978
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 18 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ plugins {
id "base"
id "idea"
id "com.gorylenko.gradle-git-properties"
id "com.github.ben-manes.versions" version "0.51.0"
}

version = "0.0.1-SNAPSHOT"
description = "The flexible configurable crm service"

assert System.properties["java.specification.version"] == "21" || "22" || "23"
Expand Down
1 change: 0 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
rootProject.name=flexwork-app
profile=dev
projectVersion=0.0.1

# gradle plugin version
gitPropertiesPluginVersion=2.4.2
Expand Down
8 changes: 4 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
[versions]
mapstructVersion = "1.6.2"
mapstructVersion = "1.6.3"
archunitJunit5Version = "1.3.0"
lombokVersion = "1.18.34"
lombokVersion = "1.18.36"
liquibaseVersion = "4.30.0"
assertJVersion = "3.26.3"
jcloudsVersion = "2.6.0"
dotEnvVersion = "3.0.2"
logbackVersion = "1.5.9"
junitVersion = "5.11.2"
junitVersion = "5.11.3"
mockitoVersion = "5.2.0"
mockitoJunitVersion = "5.14.1"
jsonApiVersion = "2.1.3"
parssonVersion="1.1.7"
springbootVersion = "3.3.5"
springbootVersion = "3.4.0"
springDependencyManagementVersion="1.1.6"
jhisterVersion = "8.7.1"
j2HtmlVersion = "1.6.0"
Expand Down
2 changes: 0 additions & 2 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ plugins {
id "org.jetbrains.kotlin.jvm"
}

version = "0.0.1-SNAPSHOT"

description = ""

assert System.properties["java.specification.version"] == "21" || "22" || "23"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,19 @@ public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Buil
.requestMatchers(mvc.pattern("/management/prometheus"))
.permitAll()
.requestMatchers(mvc.pattern("/management/**"))
.hasAuthority(AuthoritiesConstants.ADMIN))
.hasAuthority(
AuthoritiesConstants.ADMIN)) // Enforces ROLE_ADMIN
.httpBasic(withDefaults()) // Enable Basic Authentication
.oauth2ResourceServer(
oauth2 -> oauth2.jwt(withDefaults())) // Enable OAuth2 Resource Server
.sessionManagement(
session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling(
exceptions ->
exceptions
.authenticationEntryPoint(
new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler()))
.oauth2ResourceServer(oauth2 -> oauth2.jwt(withDefaults()));
.accessDeniedHandler(new BearerTokenAccessDeniedHandler()));
return http.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.flexwork.modules.teams.repository;

import io.flexwork.modules.teams.domain.TeamWorkflowSelection;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TeamWorkflowSelectionRepository
extends JpaRepository<TeamWorkflowSelection, Long> {}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import static io.flexwork.query.QueryUtils.createSpecification;

import io.flexwork.modules.teams.domain.Team;
import io.flexwork.modules.teams.domain.TeamWorkflowSelection;
import io.flexwork.modules.teams.domain.Workflow;
import io.flexwork.modules.teams.domain.WorkflowState;
import io.flexwork.modules.teams.domain.WorkflowTransition;
import io.flexwork.modules.teams.domain.WorkflowVisibility;
import io.flexwork.modules.teams.repository.TeamWorkflowSelectionRepository;
import io.flexwork.modules.teams.repository.WorkflowRepository;
import io.flexwork.modules.teams.repository.WorkflowStateRepository;
import io.flexwork.modules.teams.repository.WorkflowTransitionRepository;
Expand Down Expand Up @@ -35,6 +39,8 @@ public class WorkflowService {

private final WorkflowTransitionRepository workflowTransitionRepository;

private final TeamWorkflowSelectionRepository teamWorkflowSelectionRepository;

private final WorkflowMapper workflowMapper;

private final WorkflowStateMapper workflowStateMapper;
Expand All @@ -45,12 +51,14 @@ public WorkflowService(
WorkflowRepository workflowRepository,
WorkflowStateRepository workflowStateRepository,
WorkflowTransitionRepository workflowTransitionRepository,
TeamWorkflowSelectionRepository teamWorkflowSelectionRepository,
WorkflowMapper workflowMapper,
WorkflowStateMapper workflowStateMapper,
WorkflowTransitionMapper workflowTransitionMapper) {
this.workflowRepository = workflowRepository;
this.workflowStateRepository = workflowStateRepository;
this.workflowTransitionRepository = workflowTransitionRepository;
this.teamWorkflowSelectionRepository = teamWorkflowSelectionRepository;
this.workflowMapper = workflowMapper;
this.workflowStateMapper = workflowStateMapper;
this.workflowTransitionMapper = workflowTransitionMapper;
Expand Down Expand Up @@ -329,4 +337,157 @@ public List<WorkflowDTO> listGlobalWorkflowsNotLinkedToTeam(Long teamId) {
.map(workflowMapper::toDto)
.toList();
}

@Transactional
public WorkflowDetailedDTO createWorkflowByReference(
Long teamId, Long referencedWorkflowId, WorkflowDTO workflowDTO) {
// Fetch the referenced workflow
Workflow referencedWorkflow =
workflowRepository
.findById(referencedWorkflowId)
.orElseThrow(
() ->
new EntityNotFoundException(
"Referenced workflow not found with id: "
+ referencedWorkflowId));

// Validate that the referenced workflow is either PUBLIC or TEAM visibility
if (!referencedWorkflow.getVisibility().equals(WorkflowVisibility.PUBLIC)
&& !referencedWorkflow.getVisibility().equals(WorkflowVisibility.TEAM)) {
throw new IllegalStateException("Only PUBLIC or TEAM workflows can be referenced.");
}

// Create the new workflow
Workflow newWorkflow = new Workflow();
newWorkflow.setName(workflowDTO.getName());
newWorkflow.setRequestName(workflowDTO.getRequestName());
newWorkflow.setDescription(workflowDTO.getDescription());
newWorkflow.setOwner(Team.builder().id(teamId).build());
newWorkflow.setVisibility(
WorkflowVisibility.PRIVATE); // New workflows default to PRIVATE visibility
newWorkflow.setParentWorkflow(Workflow.builder().id(referencedWorkflow.getId()).build());
newWorkflow.setClonedFromGlobal(false); // It's a reference, not a clone
newWorkflow.setLevel1EscalationTimeout(referencedWorkflow.getLevel1EscalationTimeout());
newWorkflow.setLevel2EscalationTimeout(referencedWorkflow.getLevel2EscalationTimeout());
newWorkflow.setLevel3EscalationTimeout(referencedWorkflow.getLevel3EscalationTimeout());
workflowRepository.save(newWorkflow);

// Link the new workflow with the team in fw_team_workflow_selection
TeamWorkflowSelection teamWorkflowSelection = new TeamWorkflowSelection();
teamWorkflowSelection.setTeam(Team.builder().id(teamId).build());
teamWorkflowSelection.setWorkflow(Workflow.builder().id(newWorkflow.getId()).build());
teamWorkflowSelectionRepository.save(teamWorkflowSelection);

// Fetch states and transitions of the referenced workflow
List<WorkflowState> referencedStates =
workflowStateRepository.findByWorkflowId(referencedWorkflow.getId());
List<WorkflowTransition> referencedTransitions =
workflowTransitionRepository.findByWorkflowId(referencedWorkflow.getId());

// Map the referenced workflow to WorkflowDetailedDTO
WorkflowDetailedDTO result = workflowMapper.toDetailedDto(newWorkflow);
result.setStates(referencedStates.stream().map(workflowStateMapper::toDto).toList());
result.setTransitions(
referencedTransitions.stream().map(workflowTransitionMapper::toDto).toList());

return result;
}

@Transactional
public WorkflowDetailedDTO createWorkflowByCloning(
Long teamId, Long workflowToCloneId, WorkflowDTO workflowDTO) {
// Fetch the workflow to be cloned
Workflow workflowToClone =
workflowRepository
.findById(workflowToCloneId)
.orElseThrow(
() ->
new EntityNotFoundException(
"Workflow to clone not found with id: "
+ workflowToCloneId));

// Validate that the workflow to clone is either PUBLIC or TEAM visibility
if (!workflowToClone.getVisibility().equals(WorkflowVisibility.PUBLIC)
&& !workflowToClone.getVisibility().equals(WorkflowVisibility.TEAM)) {
throw new IllegalStateException("Only PUBLIC or TEAM workflows can be cloned.");
}

// Step 1: Create the new workflow
Workflow newWorkflow = new Workflow();
newWorkflow.setName(workflowDTO.getName());
newWorkflow.setRequestName(workflowDTO.getRequestName());
newWorkflow.setDescription(workflowDTO.getDescription());
newWorkflow.setOwner(Team.builder().id(teamId).build());
newWorkflow.setVisibility(
WorkflowVisibility.PRIVATE); // Cloned workflows default to PRIVATE visibility
newWorkflow.setParentWorkflow(
Workflow.builder()
.id(workflowToClone.getId())
.build()); // Reference the parent workflow
newWorkflow.setClonedFromGlobal(true); // Mark as cloned
newWorkflow.setLevel1EscalationTimeout(workflowToClone.getLevel1EscalationTimeout());
newWorkflow.setLevel2EscalationTimeout(workflowToClone.getLevel2EscalationTimeout());
newWorkflow.setLevel3EscalationTimeout(workflowToClone.getLevel3EscalationTimeout());
workflowRepository.save(newWorkflow);

// Link the new workflow with the team in fw_team_workflow_selection
TeamWorkflowSelection teamWorkflowSelection = new TeamWorkflowSelection();
teamWorkflowSelection.setTeam(Team.builder().id(teamId).build());
teamWorkflowSelection.setWorkflow(Workflow.builder().id(newWorkflow.getId()).build());
teamWorkflowSelectionRepository.save(teamWorkflowSelection);

// Step 2: Clone the states
List<WorkflowState> statesToClone =
workflowStateRepository.findByWorkflowId(workflowToClone.getId());
Map<Long, WorkflowState> clonedStatesMap = new HashMap<>();
for (WorkflowState state : statesToClone) {
WorkflowState clonedState = new WorkflowState();
clonedState.setWorkflow(newWorkflow);
clonedState.setStateName(state.getStateName());
clonedState.setIsInitial(state.getIsInitial());
clonedState.setIsFinal(state.getIsFinal());
workflowStateRepository.save(clonedState);
clonedStatesMap.put(state.getId(), clonedState); // Map old state ID to new state
}

// Step 3: Clone the transitions
List<WorkflowTransition> transitionsToClone =
workflowTransitionRepository.findByWorkflowId(workflowToClone.getId());
for (WorkflowTransition transition : transitionsToClone) {
WorkflowTransition clonedTransition = new WorkflowTransition();
clonedTransition.setWorkflow(newWorkflow);
clonedTransition.setSourceState(
clonedStatesMap.get(transition.getSourceState().getId()));
clonedTransition.setTargetState(
clonedStatesMap.get(transition.getTargetState().getId()));
clonedTransition.setEventName(transition.getEventName());
clonedTransition.setSlaDuration(transition.getSlaDuration());
clonedTransition.setEscalateOnViolation(transition.isEscalateOnViolation());
workflowTransitionRepository.save(clonedTransition);
}

// Step 4: Map the cloned workflow to WorkflowDetailedDTO
WorkflowDetailedDTO clonedWorkflow = workflowMapper.toDetailedDto(newWorkflow);
clonedWorkflow.setStates(
clonedStatesMap.values().stream().map(workflowStateMapper::toDto).toList());
clonedWorkflow.setTransitions(
transitionsToClone.stream()
.map(
transition -> {
WorkflowTransitionDTO dto =
workflowTransitionMapper.toDto(transition);
dto.setSourceStateId(
clonedStatesMap
.get(transition.getSourceState().getId())
.getId());
dto.setTargetStateId(
clonedStatesMap
.get(transition.getTargetState().getId())
.getId());
return dto;
})
.toList());

return clonedWorkflow;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,25 @@ public ResponseEntity<WorkflowDetailedDTO> updateWorkflow(

return ResponseEntity.ok(updatedWorkflow);
}

@PostMapping("/create-workflow-reference")
public ResponseEntity<WorkflowDetailedDTO> createWorkflowByReference(
@PathVariable Long teamId,
@RequestParam Long referencedWorkflowId,
@RequestBody WorkflowDTO workflowDTO) {
WorkflowDetailedDTO createdWorkflow =
workflowService.createWorkflowByReference(
teamId, referencedWorkflowId, workflowDTO);
return ResponseEntity.status(HttpStatus.CREATED).body(createdWorkflow);
}

@PostMapping("/create-workflow-clone")
public ResponseEntity<WorkflowDetailedDTO> createWorkflowByCloning(
@PathVariable Long teamId,
@RequestParam Long workflowToCloneId,
@RequestBody WorkflowDTO workflowDTO) {
WorkflowDetailedDTO clonedWorkflow =
workflowService.createWorkflowByCloning(teamId, workflowToCloneId, workflowDTO);
return ResponseEntity.status(HttpStatus.CREATED).body(clonedWorkflow);
}
}
10 changes: 5 additions & 5 deletions server/src/main/resources/config/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
# ===================================================================


logging:
structured.format.console: logstash
level:
ROOT: DEBUG
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.loader.plan.exe: DEBUG
org.hibernate.loader.plan.collection: DEBUG
ROOT: WARN
sql: DEBUG # built-in group sql include org.springframework.jdbc.core, org.hibernate.SQL
io.undertow: ERROR
io.flexwork: DEBUG

spring:
Expand Down
1 change: 1 addition & 0 deletions server/src/main/resources/config/application-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# ===================================================================

logging:
structured.format.console: logstash
level:
ROOT: INFO
io.flexwork: INFO
Expand Down
1 change: 0 additions & 1 deletion tools/liquibase/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ plugins {
}

group = 'io.flexwork'
version = '0.0.1-SNAPSHOT'

repositories {
mavenCentral()
Expand Down
1 change: 0 additions & 1 deletion tools/platform/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ plugins {
}

group = 'io.flexwork'
version = '0.0.1-SNAPSHOT'

repositories {
mavenCentral()
Expand Down

0 comments on commit 27aa978

Please sign in to comment.