completed nflow integration into onboarding
This commit is contained in:
@@ -1,26 +1,25 @@
|
||||
package zw.qantra.tm.domain.controllers;
|
||||
|
||||
import io.nflow.engine.service.WorkflowInstanceInclude;
|
||||
import io.nflow.engine.internal.dao.WorkflowInstanceDao;
|
||||
import io.nflow.engine.service.WorkflowInstanceService;
|
||||
import io.nflow.engine.workflow.instance.QueryWorkflowInstances;
|
||||
import io.nflow.engine.workflow.instance.WorkflowInstance;
|
||||
import io.nflow.engine.workflow.instance.WorkflowInstanceAction;
|
||||
import io.nflow.engine.workflow.instance.WorkflowInstanceFactory;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Instant;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import zw.qantra.tm.domain.dtos.AuthResponse;
|
||||
import zw.qantra.tm.domain.dtos.LoginRequest;
|
||||
import zw.qantra.tm.domain.dtos.RegisterRequest;
|
||||
import zw.qantra.tm.domain.dtos.VerifyRequest;
|
||||
import zw.qantra.tm.domain.dtos.*;
|
||||
import zw.qantra.tm.domain.services.OtpService;
|
||||
import zw.qantra.tm.domain.services.UserService;
|
||||
import zw.qantra.tm.domain.workflows.RegistrationWorkflow;
|
||||
import zw.qantra.tm.domain.workflows.WorkflowUtils;
|
||||
import zw.qantra.tm.utils.Utils;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@@ -34,20 +33,46 @@ public class OnboardingController {
|
||||
private final WorkflowInstanceService workflowInstanceService;
|
||||
private final WorkflowInstanceFactory workflowInstanceFactory;
|
||||
private final WorkflowUtils workflowUtils;
|
||||
private final OtpService otpService;
|
||||
|
||||
@PostMapping("/check/{username}")
|
||||
public ResponseEntity check(@PathVariable String username) {
|
||||
QueryWorkflowInstances query = new QueryWorkflowInstances.Builder()
|
||||
.setExternalId(username)
|
||||
.setIncludeCurrentStateVariables(true)
|
||||
.setIncludeActions(true)
|
||||
.build();
|
||||
List<WorkflowInstance> workflowInstanceList =
|
||||
new ArrayList<>(workflowInstanceService.listWorkflowInstances(query));
|
||||
if(!workflowInstanceList.isEmpty()){
|
||||
WorkflowInstance instance = workflowInstanceList.get(0);
|
||||
WorkflowInstanceAction action = instance.actions.get(0);
|
||||
WorkflowStatusDto statusDto = new WorkflowStatusDto();
|
||||
statusDto.setWorkflowId(instance.id);
|
||||
statusDto.setState(instance.state);
|
||||
statusDto.setStateText(instance.stateText);
|
||||
statusDto.setStatus(instance.status.toString());
|
||||
statusDto.setStage(action.state);
|
||||
return ResponseEntity.ok(statusDto);
|
||||
}
|
||||
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<Object> register(@Valid @RequestBody RegisterRequest request)
|
||||
throws ExecutionException, InterruptedException {
|
||||
var instance = workflowInstanceFactory.newWorkflowInstanceBuilder()
|
||||
.setType(RegistrationWorkflow.TYPE)
|
||||
.setExternalId(request.getUsername() + "-" + System.currentTimeMillis())
|
||||
.setExternalId(request.getUsername() + "-" + new Instant().getMillis())
|
||||
.putStateVariable("body", request)
|
||||
.build();
|
||||
|
||||
long workflowId = workflowInstanceService.insertWorkflowInstance(instance);
|
||||
|
||||
CompletableFuture<Object> future = workflowUtils
|
||||
.waitForState(workflowId, "sendOtp", 30000, 1000);
|
||||
.waitForState(workflowId, new String[]{"sendOtp", "failed"},
|
||||
30000, 1000);
|
||||
Object response = future.get();
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
@@ -56,6 +81,7 @@ public class OnboardingController {
|
||||
@PostMapping("/verify")
|
||||
public ResponseEntity<Object> verify(@Valid @RequestBody VerifyRequest request)
|
||||
throws ExecutionException, InterruptedException {
|
||||
|
||||
// Create an update to move the workflow to the next state
|
||||
WorkflowInstance update = new WorkflowInstance.Builder()
|
||||
.setId(request.getWorkflowId())
|
||||
@@ -74,14 +100,43 @@ public class OnboardingController {
|
||||
workflowInstanceService.updateWorkflowInstance(update, action);
|
||||
|
||||
CompletableFuture<Object> future = workflowUtils
|
||||
.waitForState(request.getWorkflowId(), "verifyOtp", 30000, 1000);
|
||||
.waitForState(request.getWorkflowId(), new String[]{"done", "failed"},
|
||||
30000, 50);
|
||||
Object response = future.get();
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@PostMapping("/resend")
|
||||
public ResponseEntity<Object> resend(@RequestBody OtpRequest otpRequest)
|
||||
throws ExecutionException, InterruptedException {
|
||||
// Create an update to move the workflow to the next state
|
||||
WorkflowInstance update = new WorkflowInstance.Builder()
|
||||
.setId(otpRequest.getWorkflowId())
|
||||
.setState("resendOtp") // The state you want to transition to
|
||||
.setNextActivation(DateTime.now()) // Schedule immediate execution
|
||||
.setStateVariables(new HashMap<>(){{ put("body", Utils.toJson(otpRequest)); }})
|
||||
.setStateText("Resumed from manual state")
|
||||
.build();
|
||||
|
||||
WorkflowInstanceAction action = new WorkflowInstanceAction.Builder(update)
|
||||
.setType(WorkflowInstanceAction.WorkflowActionType.externalChange)
|
||||
.setExecutionEnd(DateTime.now())
|
||||
.build();
|
||||
|
||||
// Apply the update
|
||||
workflowInstanceService.updateWorkflowInstance(update, action);
|
||||
|
||||
CompletableFuture<Object> future = workflowUtils
|
||||
.waitForState(otpRequest.getWorkflowId(), new String[]{"resendOtp", "failed"},
|
||||
30000, 50);
|
||||
Object response = future.get();
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<AuthResponse> login(@Valid @RequestBody LoginRequest request) {
|
||||
public ResponseEntity<Object> login(@Valid @RequestBody LoginRequest request) {
|
||||
AuthResponse response = userService.login(request);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
10
src/main/java/zw/qantra/tm/domain/dtos/OtpRequest.java
Normal file
10
src/main/java/zw/qantra/tm/domain/dtos/OtpRequest.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package zw.qantra.tm.domain.dtos;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class OtpRequest {
|
||||
private String username;
|
||||
private String phone;
|
||||
private Long workflowId;
|
||||
}
|
||||
@@ -14,4 +14,5 @@ public class PasswordRequest {
|
||||
@NotBlank(message = "Password is required")
|
||||
@Size(min = 6, message = "Password must be at least 6 characters")
|
||||
private String password;
|
||||
private Long workflowId;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ public class RegisterRequest {
|
||||
@NotBlank(message = "Username is required")
|
||||
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String photoUrl;
|
||||
private Long workflowId;
|
||||
|
||||
@NotBlank(message = "Email is required")
|
||||
@Email(message = "Email should be valid")
|
||||
private String email;
|
||||
|
||||
@@ -11,6 +11,7 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
public class StateResponse {
|
||||
private String state;
|
||||
private String status;
|
||||
private Object body;
|
||||
private String message;
|
||||
private String workflowId;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package zw.qantra.tm.domain.dtos;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class WorkflowStatusDto {
|
||||
private Long workflowId;
|
||||
private String state;
|
||||
private String stateText;
|
||||
private String status;
|
||||
private String stage;
|
||||
}
|
||||
38
src/main/java/zw/qantra/tm/domain/dtos/erp/CustomerDto.java
Normal file
38
src/main/java/zw/qantra/tm/domain/dtos/erp/CustomerDto.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package zw.qantra.tm.domain.dtos.erp;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CustomerDto {
|
||||
@JsonProperty("doctype")
|
||||
private String doctype;
|
||||
|
||||
@JsonProperty("customer_name")
|
||||
private String customerName;
|
||||
|
||||
@JsonProperty("customer_group")
|
||||
private String customerGroup;
|
||||
|
||||
@JsonProperty("territory")
|
||||
private String territory;
|
||||
|
||||
@JsonProperty("customer_type")
|
||||
private String customerType;
|
||||
|
||||
@JsonProperty("language")
|
||||
private String language;
|
||||
|
||||
@JsonProperty("mobile_no")
|
||||
private String mobileNo;
|
||||
|
||||
@JsonProperty("email_id")
|
||||
private String emailId;
|
||||
|
||||
@JsonProperty("docstatus")
|
||||
private Integer docstatus;
|
||||
}
|
||||
@@ -25,7 +25,10 @@ public class User extends BaseEntity implements UserDetails {
|
||||
@Column(unique = true, nullable = false)
|
||||
private String email;
|
||||
private String phone;
|
||||
|
||||
private String erpCustomerRef;
|
||||
private String photoUrl;
|
||||
private Long workflowId;
|
||||
|
||||
@Column(name = "first_name")
|
||||
private String firstName;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package zw.qantra.tm.domain.services;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
@@ -17,10 +18,16 @@ import zw.qantra.tm.utils.JwtUtils;
|
||||
@RequiredArgsConstructor
|
||||
public class UserService implements UserDetailsService {
|
||||
|
||||
@Getter
|
||||
private final UserRepository userRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final JwtUtils jwtUtils;
|
||||
|
||||
public User fetchUserByUsername(String username) {
|
||||
return userRepository.findByUsername(username)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return userRepository.findByUsername(username)
|
||||
@@ -43,6 +50,8 @@ public class UserService implements UserDetailsService {
|
||||
user.setFirstName(request.getFirstName());
|
||||
user.setLastName(request.getLastName());
|
||||
user.setPhone(request.getPhone());
|
||||
user.setWorkflowId(request.getWorkflowId());
|
||||
user.setPhotoUrl(request.getPhotoUrl());
|
||||
|
||||
User savedUser = userRepository.save(user);
|
||||
String token = jwtUtils.generateToken(savedUser);
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
package zw.qantra.tm.domain.workflows;
|
||||
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
import io.nflow.engine.workflow.definition.WorkflowStateType;
|
||||
import org.joda.time.DateTime;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import io.nflow.engine.workflow.definition.NextAction;
|
||||
import io.nflow.engine.workflow.definition.StateExecution;
|
||||
import io.nflow.engine.workflow.definition.WorkflowDefinition;
|
||||
import zw.qantra.tm.domain.dtos.EmailRequest;
|
||||
import zw.qantra.tm.domain.dtos.VerifyRequest;
|
||||
import zw.qantra.tm.domain.dtos.*;
|
||||
import zw.qantra.tm.domain.dtos.erp.CustomerDto;
|
||||
import zw.qantra.tm.domain.models.Otp;
|
||||
import zw.qantra.tm.domain.models.User;
|
||||
import zw.qantra.tm.domain.services.OtpService;
|
||||
import zw.qantra.tm.domain.services.UserService;
|
||||
import io.nflow.engine.workflow.curated.State;
|
||||
import zw.qantra.tm.domain.dtos.AuthResponse;
|
||||
import zw.qantra.tm.domain.dtos.RegisterRequest;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validator;
|
||||
import zw.qantra.tm.rest.RestService;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
@@ -43,6 +51,16 @@ public class RegistrationWorkflow extends WorkflowDefinition {
|
||||
private String infobipUrl;
|
||||
@Value("${infobip.apikey}")
|
||||
private String infobipApiKey;
|
||||
@Value("${erpnext.url}")
|
||||
private String erpnextUrl;
|
||||
@Value("${erpnext.api.key}")
|
||||
private String erpnextApiKey;
|
||||
@Value("${erpnext.api.secret}")
|
||||
private String erpnextApiSecret;
|
||||
@Value("${erpnext.username}")
|
||||
private String erpnextUsername;
|
||||
@Value("${erpnext.password}")
|
||||
private String erpnextPassword;
|
||||
|
||||
public static final String TYPE = "registrationWorkflow";
|
||||
|
||||
@@ -50,10 +68,9 @@ public class RegistrationWorkflow extends WorkflowDefinition {
|
||||
public static final State REGISTER = new State("register");
|
||||
public static final State SEND_OTP = new State("sendOtp", WorkflowStateType.manual);
|
||||
public static final State VERIFY_OTP = new State("verifyOtp");
|
||||
public static final State OTP_SUCCESS = new State("otpSuccess", WorkflowStateType.manual);
|
||||
public static final State RESEND_OTP = new State("resendOtp", WorkflowStateType.manual);
|
||||
public static final State SET_PIN = new State("setPin", WorkflowStateType.normal);
|
||||
public static final State UPDATE_ERP = new State("updateErp", WorkflowStateType.normal);
|
||||
public static final State OTP_SUCCESS = new State("otpSuccess");
|
||||
public static final State UPDATE_ERP = new State("updateErp");
|
||||
public static final State FAILED = new State("failed", WorkflowStateType.manual);
|
||||
public static final State DONE = new State("done", WorkflowStateType.end);
|
||||
|
||||
@@ -63,10 +80,9 @@ public class RegistrationWorkflow extends WorkflowDefinition {
|
||||
permit(BEGIN, REGISTER);
|
||||
permit(REGISTER, SEND_OTP);
|
||||
permit(SEND_OTP, VERIFY_OTP);
|
||||
permit(RESEND_OTP, VERIFY_OTP);
|
||||
permit(VERIFY_OTP, OTP_SUCCESS, FAILED);
|
||||
permit(RESEND_OTP, OTP_SUCCESS, FAILED);
|
||||
permit(OTP_SUCCESS, SET_PIN, FAILED);
|
||||
permit(SET_PIN, UPDATE_ERP);
|
||||
permit(OTP_SUCCESS, UPDATE_ERP, FAILED);
|
||||
permit(UPDATE_ERP, DONE);
|
||||
}
|
||||
|
||||
@@ -93,7 +109,19 @@ public class RegistrationWorkflow extends WorkflowDefinition {
|
||||
return NextAction.moveToState(FAILED, errorMessage.toString());
|
||||
}
|
||||
|
||||
// todo: add this to the appropriate action
|
||||
// update phone number format
|
||||
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
|
||||
try {
|
||||
String phone = payload.getPhone();
|
||||
Phonenumber.PhoneNumber zimProto = phoneUtil.parse(phone, "ZW");
|
||||
phone = String.valueOf(zimProto.getCountryCode()) + String.valueOf(zimProto.getNationalNumber());
|
||||
payload.setPhone(phone);
|
||||
} catch (NumberParseException e) {
|
||||
System.err.println("NumberParseException was thrown: " + e.toString());
|
||||
return NextAction.moveToState(FAILED, "Invalid phone number");
|
||||
}
|
||||
|
||||
execution.setVariable("registerRequest", payload);
|
||||
execution.setVariable("body", payload);
|
||||
|
||||
return NextAction.moveToState(SEND_OTP, "Initial registration success for: " + payload.getUsername());
|
||||
@@ -117,6 +145,7 @@ public class RegistrationWorkflow extends WorkflowDefinition {
|
||||
|
||||
log.info("otp generated successfully: {}", otp.getOtp());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("Error sending OTP: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@@ -132,18 +161,93 @@ public class RegistrationWorkflow extends WorkflowDefinition {
|
||||
return NextAction.moveToState(OTP_SUCCESS, "OTP verified successfully");
|
||||
}
|
||||
|
||||
public void otpSuccess(StateExecution execution) {
|
||||
log.info("OTP verified successfully");
|
||||
public void resendOtp(StateExecution execution) {
|
||||
OtpRequest otpRequest = execution.getVariable("body", OtpRequest.class);
|
||||
Otp otp = otpService.generateOtp(otpRequest.getUsername(), "REGISTRATION");
|
||||
String string = getSMSString(otpRequest.getPhone(), otp.getOtp());
|
||||
|
||||
log.info("otp generated successfully: {}", otp.getOtp());
|
||||
}
|
||||
|
||||
public NextAction setPin(StateExecution execution) {
|
||||
RegisterRequest response = execution.getVariable("body", RegisterRequest.class);
|
||||
return NextAction.stopInState(UPDATE_ERP, "PIN set successfully for: " + response.getUsername());
|
||||
public NextAction otpSuccess(StateExecution execution) {
|
||||
log.info("OTP verified successfully");
|
||||
log.info("Begin user registration");
|
||||
|
||||
VerifyRequest request = execution.getVariable("body", VerifyRequest.class);
|
||||
try {
|
||||
RegisterRequest registerRequest = execution.getVariable("registerRequest", RegisterRequest.class);
|
||||
|
||||
registerRequest.setWorkflowId(request.getWorkflowId());
|
||||
execution.setVariable("registerRequest", registerRequest);
|
||||
|
||||
userService.register(registerRequest);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return NextAction.moveToState(FAILED, "Failed to register user: " + e.getMessage());
|
||||
}
|
||||
|
||||
return NextAction.moveToState(UPDATE_ERP, "User creation successfully for: " + request.getUsername());
|
||||
}
|
||||
|
||||
public NextAction updateErp(StateExecution execution) {
|
||||
RegisterRequest response = execution.getVariable("body", RegisterRequest.class);
|
||||
return NextAction.stopInState(DONE, "ERP updated successfully for: " + response.getUsername());
|
||||
RegisterRequest registerRequest = execution.getVariable("registerRequest", RegisterRequest.class);
|
||||
|
||||
// login to erp
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Type", "application/json");
|
||||
headers.add("Accept", "application/json");
|
||||
|
||||
Map<String, String> loginRequest = Map.of(
|
||||
"usr", erpnextUsername,
|
||||
"pwd", erpnextPassword);
|
||||
|
||||
String sid = "";
|
||||
|
||||
try {
|
||||
ResponseEntity response = restService.postAsEntity(
|
||||
erpnextUrl + "/method/login", loginRequest, headers, LinkedHashMap.class);
|
||||
|
||||
sid = response.getHeaders().getFirst("Set-Cookie");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return NextAction.retryAfter(DateTime.now().plusSeconds(30), "Failed to login to ERP: " + e.getMessage());
|
||||
}
|
||||
|
||||
// create customer in erp
|
||||
String basicAuth = "Basic " + Base64.getEncoder().encodeToString(
|
||||
(erpnextApiKey + ":" + erpnextApiSecret).getBytes(StandardCharsets.UTF_8));
|
||||
headers.add("Authorization", basicAuth);
|
||||
headers.add("Cookie", sid);
|
||||
|
||||
CustomerDto customerDto = CustomerDto.builder()
|
||||
.doctype("Customer")
|
||||
.customerName(registerRequest.getFirstName() + " " + registerRequest.getLastName())
|
||||
.customerGroup("Commercial")
|
||||
.territory("All Territories")
|
||||
.customerType("Individual")
|
||||
.language("en")
|
||||
.mobileNo(registerRequest.getPhone())
|
||||
.emailId(registerRequest.getEmail())
|
||||
.docstatus(1)
|
||||
.build();
|
||||
|
||||
try {
|
||||
LinkedHashMap response = restService.postAs(
|
||||
erpnextUrl + "/v2/document/Customer", customerDto, headers, LinkedHashMap.class);
|
||||
|
||||
LinkedHashMap data = (LinkedHashMap) response.get("data");
|
||||
String customerId = (String) data.get("name");
|
||||
|
||||
User user = userService.fetchUserByUsername(registerRequest.getUsername());
|
||||
user.setErpCustomerRef(customerId);
|
||||
userService.getUserRepository().save(user);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
return NextAction.retryAfter(DateTime.now().plusSeconds(30), "Failed to update ERP: " + e.getMessage());
|
||||
}
|
||||
|
||||
return NextAction.stopInState(DONE, "ERP updated successfully for: " + registerRequest.getUsername());
|
||||
}
|
||||
|
||||
String getSMSString(String to, String otp) {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package zw.qantra.tm.domain.workflows;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import io.nflow.engine.service.WorkflowInstanceInclude.*;
|
||||
import io.nflow.engine.workflow.instance.WorkflowInstanceAction;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import io.nflow.engine.service.WorkflowInstanceService;
|
||||
@@ -21,7 +24,7 @@ import static io.nflow.engine.service.WorkflowInstanceInclude.*;
|
||||
public class WorkflowUtils {
|
||||
private final WorkflowInstanceService workflowInstanceService;
|
||||
|
||||
public CompletableFuture<Object> waitForState(long workflowId, String state, int timeout, int pollingInterval) {
|
||||
public CompletableFuture<Object> waitForState(long workflowId, String[] states, int timeout, int pollingInterval) {
|
||||
CompletableFuture<Object> future = new CompletableFuture<>();
|
||||
|
||||
while(!future.isDone()){ // check if the future is done
|
||||
@@ -31,8 +34,12 @@ public class WorkflowUtils {
|
||||
1L);
|
||||
try {
|
||||
Thread.sleep(pollingInterval);
|
||||
if(instance.state.equalsIgnoreCase(state) &&
|
||||
instance.status.equals(WorkflowInstance.WorkflowInstanceStatus.manual)){
|
||||
List<String> stateList = Arrays.stream(states).toList();
|
||||
List<WorkflowInstance.WorkflowInstanceStatus> statusList =
|
||||
Arrays.asList(WorkflowInstance.WorkflowInstanceStatus.manual,
|
||||
WorkflowInstance.WorkflowInstanceStatus.finished);
|
||||
if(stateList.contains(instance.state) &&
|
||||
statusList.contains(instance.status)){
|
||||
future.complete(getStateResponse(instance, "success"));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@@ -48,10 +55,12 @@ public class WorkflowUtils {
|
||||
}
|
||||
|
||||
public StateResponse getStateResponse(WorkflowInstance instance, String message){
|
||||
WorkflowInstanceAction action = instance.actions.get(instance.actions.size()-1);
|
||||
return StateResponse.builder()
|
||||
.state(instance.state)
|
||||
.status(instance.status.toString())
|
||||
.body(Utils.fromJson(instance.getStateVariable("body"), Map.class))
|
||||
.message(instance.getStateVariable("message"))
|
||||
.message(action.stateText)
|
||||
.workflowId(instance.id.toString())
|
||||
.externalId(instance.externalId)
|
||||
.build();
|
||||
|
||||
Reference in New Issue
Block a user