improving workflow fault tolerance
This commit is contained in:
1
pom.xml
1
pom.xml
@@ -169,7 +169,6 @@
|
|||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
<version>3.1.5</version>
|
<version>3.1.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
package zw.qantra.tm.configs;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
|
||||||
import com.fasterxml.jackson.datatype.joda.JodaModule;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
|
|
||||||
import io.nflow.engine.config.EngineConfiguration;
|
|
||||||
import io.nflow.engine.config.NFlow;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Primary;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class NflowConfiguration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the primary, application-wide ObjectMapper.
|
|
||||||
* <p>
|
|
||||||
* This bean is marked as {@code @Primary} to ensure it's the default for dependency injection
|
|
||||||
* throughout the application. It's configured using Spring Boot's {@link Jackson2ObjectMapperBuilder},
|
|
||||||
* which automatically registers modules for Java 8 Time, Optional, etc., if they are on the classpath.
|
|
||||||
* It also includes any custom {@link Module} beans defined in the application context.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param builder The default Jackson2ObjectMapperBuilder, pre-configured by Spring Boot.
|
|
||||||
* @param customModules A list of all custom Jackson {@link Module} beans found in the application context.
|
|
||||||
* @return A customized {@link com.fasterxml.jackson.databind.ObjectMapper}.
|
|
||||||
*/
|
|
||||||
@Primary
|
|
||||||
@Bean
|
|
||||||
public ObjectMapper primaryObjectMapper(Jackson2ObjectMapperBuilder builder, List<Module> customModules) {
|
|
||||||
builder.modules(customModules);
|
|
||||||
builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the default ObjectMapper used by the nFlow REST API.
|
|
||||||
* <p>
|
|
||||||
* This bean definition ensures that the nFlow REST endpoints use the same consistent,
|
|
||||||
* primary ObjectMapper as the rest of the application.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
@Bean("nflowRestObjectMapper")
|
|
||||||
public ObjectMapper nflowRestObjectMapper(ObjectMapper primaryObjectMapper) {
|
|
||||||
return primaryObjectMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides the default ObjectMapper used by the nFlow Engine for variable serialization.
|
|
||||||
* <p>
|
|
||||||
* This is the key fix for `InvalidDefinitionException` with `LocalDateTime` in workflow variables.
|
|
||||||
* It ensures the engine uses our fully configured primary ObjectMapper.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
@Bean("nflowEngineObjectMapper")
|
|
||||||
public ObjectMapper nflowEngineObjectMapper(ObjectMapper primaryObjectMapper) {
|
|
||||||
return primaryObjectMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@NFlow
|
|
||||||
public EngineConfiguration.EngineObjectMapperSupplier nflowObjectMapper() {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
|
|
||||||
mapper.registerModule(new JodaModule());
|
|
||||||
mapper.registerModule(new Jdk8Module());
|
|
||||||
mapper.registerModule(new JSR310Module());
|
|
||||||
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
|
||||||
return () -> mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -107,6 +107,7 @@ public class ConfigController {
|
|||||||
.externalId("78f1f497-c9eb-401c-b22c-884756e68e40")
|
.externalId("78f1f497-c9eb-401c-b22c-884756e68e40")
|
||||||
.integrationProcessorLabel("STEWARD")
|
.integrationProcessorLabel("STEWARD")
|
||||||
.accountFieldName("Phone Number")
|
.accountFieldName("Phone Number")
|
||||||
|
.percentageCommission(6)
|
||||||
.build(),
|
.build(),
|
||||||
Provider.builder()
|
Provider.builder()
|
||||||
.description("NetOne Airtime")
|
.description("NetOne Airtime")
|
||||||
@@ -117,6 +118,7 @@ public class ConfigController {
|
|||||||
.externalId("95d485a7-39c9-4559-8a27-6521969abe8f")
|
.externalId("95d485a7-39c9-4559-8a27-6521969abe8f")
|
||||||
.integrationProcessorLabel("STEWARD")
|
.integrationProcessorLabel("STEWARD")
|
||||||
.accountFieldName("Phone Number")
|
.accountFieldName("Phone Number")
|
||||||
|
.percentageCommission(5.5)
|
||||||
.build(),
|
.build(),
|
||||||
Provider.builder()
|
Provider.builder()
|
||||||
.description("Prepaid Zesa")
|
.description("Prepaid Zesa")
|
||||||
@@ -127,6 +129,7 @@ public class ConfigController {
|
|||||||
.externalId("0f67f7cc-b62b-4fb5-915f-6740b2afdba6")
|
.externalId("0f67f7cc-b62b-4fb5-915f-6740b2afdba6")
|
||||||
.integrationProcessorLabel("STEWARD")
|
.integrationProcessorLabel("STEWARD")
|
||||||
.accountFieldName("Meter Number")
|
.accountFieldName("Meter Number")
|
||||||
|
.percentageCommission(1.5)
|
||||||
.build(),
|
.build(),
|
||||||
Provider.builder()
|
Provider.builder()
|
||||||
.description("Econet Broadband")
|
.description("Econet Broadband")
|
||||||
@@ -137,6 +140,7 @@ public class ConfigController {
|
|||||||
.externalId("287863e2-a791-4106-b629-79dadc9a6779")
|
.externalId("287863e2-a791-4106-b629-79dadc9a6779")
|
||||||
.integrationProcessorLabel("STEWARD")
|
.integrationProcessorLabel("STEWARD")
|
||||||
.accountFieldName("Phone Number")
|
.accountFieldName("Phone Number")
|
||||||
|
.percentageCommission(6)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
providerService.getProviderRepository().saveAll(providers);
|
providerService.getProviderRepository().saveAll(providers);
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ public class OnboardingController {
|
|||||||
var instance = workflowInstanceFactory.newWorkflowInstanceBuilder()
|
var instance = workflowInstanceFactory.newWorkflowInstanceBuilder()
|
||||||
.setType(RegistrationWorkflow.TYPE)
|
.setType(RegistrationWorkflow.TYPE)
|
||||||
.setExternalId(request.getUsername() + "-" + new Instant().getMillis())
|
.setExternalId(request.getUsername() + "-" + new Instant().getMillis())
|
||||||
|
.setBusinessKey(request.getUsername())
|
||||||
.putStateVariable("body", request)
|
.putStateVariable("body", request)
|
||||||
.setNextActivation(DateTime.now())
|
.setNextActivation(DateTime.now())
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -1,18 +1,31 @@
|
|||||||
package zw.qantra.tm.domain.controllers;
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
import zw.qantra.tm.domain.services.EmailService;
|
import zw.qantra.tm.domain.services.EmailService;
|
||||||
|
import zw.qantra.tm.domain.services.TransactionService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/test")
|
@RequestMapping("/test")
|
||||||
@CrossOrigin(origins = "*")
|
@CrossOrigin(origins = "*")
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class TestController {
|
public class TestController {
|
||||||
@Autowired
|
private final EmailService emailService;
|
||||||
private EmailService emailService;
|
private final TransactionService transactionService;
|
||||||
|
|
||||||
|
@PostMapping("/dbtest")
|
||||||
|
public ResponseEntity<Object> dbtest(@RequestBody Transaction transaction) {
|
||||||
|
transactionService.save(transaction);
|
||||||
|
transaction.setType(RequestType.REQUEST);
|
||||||
|
transactionService.save(transaction);
|
||||||
|
return ResponseEntity.ok(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/hello/{email}")
|
@GetMapping("/hello/{email}")
|
||||||
public ResponseEntity<String> helloEndpoint(@PathVariable String email) {
|
public ResponseEntity<String> helloEndpoint(@PathVariable String email) {
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package zw.qantra.tm.domain.controllers;
|
package zw.qantra.tm.domain.controllers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.i18n.phonenumbers.NumberParseException;
|
||||||
|
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||||
|
import com.google.i18n.phonenumbers.Phonenumber;
|
||||||
import io.nflow.engine.internal.workflow.ObjectStringMapper;
|
import io.nflow.engine.internal.workflow.ObjectStringMapper;
|
||||||
import io.nflow.engine.service.WorkflowInstanceService;
|
import io.nflow.engine.service.WorkflowInstanceService;
|
||||||
import io.nflow.engine.workflow.instance.WorkflowInstance;
|
import io.nflow.engine.workflow.instance.WorkflowInstance;
|
||||||
@@ -176,12 +179,21 @@ public class TransactonController {
|
|||||||
|
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<Object> confirm(@RequestBody Transaction transaction) throws ExecutionException, InterruptedException {
|
public ResponseEntity<Object> confirm(@RequestBody Transaction transaction)
|
||||||
|
throws ExecutionException, InterruptedException, NumberParseException {
|
||||||
LogUtils.logPrettyJson(logger, "incoming transaction", transaction);
|
LogUtils.logPrettyJson(logger, "incoming transaction", transaction);
|
||||||
|
|
||||||
|
// phone must begin with '+'
|
||||||
|
// need to format the debit phone number since it's the business key
|
||||||
|
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
|
||||||
|
Phonenumber.PhoneNumber number = phoneUtil.parse(transaction.getDebitPhone(), "");
|
||||||
|
String formattedPhoneNumber = phoneUtil.format(number, PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||||
|
|
||||||
var instance = workflowInstanceFactory.newWorkflowInstanceBuilder()
|
var instance = workflowInstanceFactory.newWorkflowInstanceBuilder()
|
||||||
.setType(TransactionWorkflow.TYPE)
|
.setType(TransactionWorkflow.TYPE)
|
||||||
.setExternalId(transaction.getUserId() + "-" + new Instant().getMillis())
|
.setExternalId(transaction.getUserId() + "-" + new Instant().getMillis())
|
||||||
.putStateVariable("confirmation", transaction)
|
.setBusinessKey(formattedPhoneNumber)
|
||||||
|
.putStateVariable("confirmation", Utils.toJson(transaction))
|
||||||
.setNextActivation(DateTime.now())
|
.setNextActivation(DateTime.now())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -40,5 +40,6 @@ public class BaseEntity {
|
|||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
|
||||||
private LocalDateTime updatedAt; // Or Date, Timestamp
|
private LocalDateTime updatedAt; // Or Date, Timestamp
|
||||||
|
|
||||||
private Boolean deleted = false;
|
@Column(columnDefinition = "BOOLEAN DEFAULT FALSE")
|
||||||
|
private Boolean deleted;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
|||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.hibernate.annotations.SQLRestriction;
|
import org.hibernate.annotations.SQLRestriction;
|
||||||
|
import org.springframework.data.domain.Persistable;
|
||||||
import zw.qantra.tm.domain.enums.AuthType;
|
import zw.qantra.tm.domain.enums.AuthType;
|
||||||
import zw.qantra.tm.domain.enums.CurrencyType;
|
import zw.qantra.tm.domain.enums.CurrencyType;
|
||||||
import zw.qantra.tm.domain.enums.RequestType;
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
import zw.qantra.tm.domain.enums.Status;
|
import zw.qantra.tm.domain.enums.Status;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Getter
|
@Getter
|
||||||
@@ -18,7 +20,6 @@ import java.math.BigDecimal;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
@SQLRestriction("deleted = false")
|
|
||||||
public class Transaction extends BaseEntity {
|
public class Transaction extends BaseEntity {
|
||||||
private String userId;
|
private String userId;
|
||||||
private String trace;
|
private String trace;
|
||||||
@@ -101,5 +102,4 @@ public class Transaction extends BaseEntity {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private Object additionalData;
|
private Object additionalData;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -13,4 +13,5 @@ import java.util.UUID;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface TransactionRepository extends JpaRepository<Transaction, UUID>, JpaSpecificationExecutor<Transaction> {
|
public interface TransactionRepository extends JpaRepository<Transaction, UUID>, JpaSpecificationExecutor<Transaction> {
|
||||||
Transaction findByTraceAndType(String trace, RequestType type);
|
Transaction findByTraceAndType(String trace, RequestType type);
|
||||||
|
Optional<Transaction> findByReference(String reference);
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ public class TransactionService {
|
|||||||
return transactionRepository.findAll(spec, pageable);
|
return transactionRepository.findAll(spec, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transaction save(Transaction transaction){
|
public Transaction save(Transaction transaction) {
|
||||||
return transactionRepository.save(transaction);
|
return transactionRepository.save(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import zw.qantra.tm.rest.RestService;
|
|||||||
import zw.qantra.tm.utils.Utils;
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service("CONFIRM_ECONET")
|
@Service("CONFIRM_ECONET")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -80,7 +81,7 @@ public class EconetConfirmationProcessor implements TransactionProcessorInterfac
|
|||||||
transaction.setErrorMessage((String) body.get("errorMessage"));
|
transaction.setErrorMessage((String) body.get("errorMessage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return transactionService.save(transaction);
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
package zw.qantra.tm.domain.services.processors.handlers;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
|
||||||
import zw.qantra.tm.domain.enums.Status;
|
|
||||||
import zw.qantra.tm.domain.models.Recipient;
|
|
||||||
import zw.qantra.tm.domain.services.RecipientService;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class RecipientsUpdateHandler implements LogicHandler<Transaction, Transaction> {
|
|
||||||
|
|
||||||
private final RecipientService recipientService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Transaction process(Transaction transaction) {
|
|
||||||
System.out.println("processing recipients");
|
|
||||||
|
|
||||||
if(transaction.getStatus() == Status.SUCCESS){
|
|
||||||
List<Recipient> recipients = recipientService.getRecipient(transaction.getCreditAccount(), transaction.getUserId());
|
|
||||||
|
|
||||||
Recipient recipient = null;
|
|
||||||
if(recipients.size() > 0){
|
|
||||||
recipient = recipients.get(0);
|
|
||||||
}else{
|
|
||||||
recipient = new Recipient();
|
|
||||||
recipient.setAccount(transaction.getCreditAccount());
|
|
||||||
recipient.setUserId(transaction.getUserId());
|
|
||||||
}
|
|
||||||
|
|
||||||
recipient.setLatestProviderLabel(transaction.getProviderLabel());
|
|
||||||
if(transaction.getCreditName() != null && !transaction.getCreditName().isEmpty()){
|
|
||||||
recipient.setName(transaction.getCreditName());
|
|
||||||
}
|
|
||||||
if(transaction.getCreditEmail() != null && !transaction.getCreditEmail().isEmpty()){
|
|
||||||
recipient.setEmail(transaction.getCreditEmail());
|
|
||||||
}
|
|
||||||
if(transaction.getCreditPhone() != null && !transaction.getCreditPhone().isEmpty()){
|
|
||||||
recipient.setPhoneNumber(transaction.getCreditPhone());
|
|
||||||
}
|
|
||||||
|
|
||||||
String stringToInitial = transaction.getCreditName() != null && !transaction.getCreditName().isEmpty()
|
|
||||||
? transaction.getCreditName() : transaction.getBillName();
|
|
||||||
|
|
||||||
recipient.setInitials(stringToInitial.substring(0, 2).toUpperCase());
|
|
||||||
recipientService.save(recipient);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package zw.qantra.tm.domain.services.processors.handlers;
|
|
||||||
|
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
|
||||||
|
|
||||||
public class ValidationHandler implements LogicHandler<Transaction, Transaction> {
|
|
||||||
@Override
|
|
||||||
public Transaction process(Transaction transaction) {
|
|
||||||
System.out.println("processing validation");
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -74,9 +74,12 @@ public class TransactionWorkflow extends WorkflowDefinition {
|
|||||||
|
|
||||||
public NextAction calculateCharges(StateExecution execution) {
|
public NextAction calculateCharges(StateExecution execution) {
|
||||||
try {
|
try {
|
||||||
Transaction transaction = execution.getVariable("confirmation", Transaction.class);
|
LinkedHashMap map = execution.getVariable("confirmation", LinkedHashMap.class);
|
||||||
|
byte[] json = objectMapper.writeValueAsBytes(map);
|
||||||
|
Transaction transaction = objectMapper.readValue(json, Transaction.class);
|
||||||
|
|
||||||
process(transaction, "calculateCharges");
|
process(transaction, "calculateCharges");
|
||||||
execution.setVariable("body", transaction);
|
execution.setVariable("body", Utils.toJson(transaction));
|
||||||
|
|
||||||
return NextAction.moveToState(CLEANUP, "Charge calculation complete");
|
return NextAction.moveToState(CLEANUP, "Charge calculation complete");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -87,9 +90,12 @@ public class TransactionWorkflow extends WorkflowDefinition {
|
|||||||
|
|
||||||
public NextAction cleanup(StateExecution execution) {
|
public NextAction cleanup(StateExecution execution) {
|
||||||
try {
|
try {
|
||||||
Transaction transaction = execution.getVariable("body", Transaction.class);
|
LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class);
|
||||||
|
byte[] json = objectMapper.writeValueAsBytes(map);
|
||||||
|
Transaction transaction = objectMapper.readValue(json, Transaction.class);
|
||||||
|
|
||||||
process(transaction, "cleanup");
|
process(transaction, "cleanup");
|
||||||
execution.setVariable("body", transaction);
|
execution.setVariable("body", Utils.toJson(transaction));
|
||||||
|
|
||||||
return NextAction.moveToState(CONFIRM, "Cleanup complete");
|
return NextAction.moveToState(CONFIRM, "Cleanup complete");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -100,7 +106,9 @@ public class TransactionWorkflow extends WorkflowDefinition {
|
|||||||
|
|
||||||
public NextAction confirm(StateExecution execution) {
|
public NextAction confirm(StateExecution execution) {
|
||||||
try {
|
try {
|
||||||
Transaction transaction = execution.getVariable("body", Transaction.class);
|
LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class);
|
||||||
|
byte[] json = objectMapper.writeValueAsBytes(map);
|
||||||
|
Transaction transaction = objectMapper.readValue(json, Transaction.class);
|
||||||
|
|
||||||
transaction.setWorkflowId(execution.getWorkflowInstanceId());
|
transaction.setWorkflowId(execution.getWorkflowInstanceId());
|
||||||
transaction = process(transaction, "confirm");
|
transaction = process(transaction, "confirm");
|
||||||
@@ -117,9 +125,7 @@ public class TransactionWorkflow extends WorkflowDefinition {
|
|||||||
byte[] json = objectMapper.writeValueAsBytes(map);
|
byte[] json = objectMapper.writeValueAsBytes(map);
|
||||||
Transaction transaction = objectMapper.readValue(json, Transaction.class);
|
Transaction transaction = objectMapper.readValue(json, Transaction.class);
|
||||||
|
|
||||||
transaction.setWorkflowId(execution.getWorkflowInstanceId());
|
process(transaction, "recipientsUpdate");
|
||||||
transaction = process(transaction, "recipientsUpdate");
|
|
||||||
execution.setVariable("body", Utils.toJson(transaction));
|
|
||||||
return NextAction.moveToState(CONFIRM_SUCCESS, "Transaction confirmed successfully");
|
return NextAction.moveToState(CONFIRM_SUCCESS, "Transaction confirmed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import zw.qantra.tm.utils.Utils;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service("confirm")
|
@Service("confirm")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -28,8 +29,8 @@ public class ConfirmHandler implements HandlerInterface {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object process(Transaction transaction) throws Exception {
|
public Object process(Transaction transaction) throws Exception {
|
||||||
transaction = transactionService.save(transaction);
|
|
||||||
|
|
||||||
|
transactionService.save(transaction);
|
||||||
TransactionEvent transactionEvent = TransactionEvent.builder()
|
TransactionEvent transactionEvent = TransactionEvent.builder()
|
||||||
.transactionId(transaction.getId().toString())
|
.transactionId(transaction.getId().toString())
|
||||||
.event(transaction.getType().name())
|
.event(transaction.getType().name())
|
||||||
@@ -43,7 +44,7 @@ public class ConfirmHandler implements HandlerInterface {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// MAIN TRANSACTION LOGIC!
|
// MAIN TRANSACTION LOGIC!
|
||||||
transactionProcessorInterface.process(transaction);
|
transaction = (Transaction) transactionProcessorInterface.process(transaction);
|
||||||
transaction.setConfirmationStatus(transaction.getStatus());
|
transaction.setConfirmationStatus(transaction.getStatus());
|
||||||
|
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
@@ -60,15 +61,8 @@ public class ConfirmHandler implements HandlerInterface {
|
|||||||
transactionEvent.setMessage(transaction.getErrorMessage());
|
transactionEvent.setMessage(transaction.getErrorMessage());
|
||||||
transactionEventService.save(transactionEvent);
|
transactionEventService.save(transactionEvent);
|
||||||
|
|
||||||
transaction = transactionService.save(transaction);
|
Transaction t1 = Utils.deepCopy(transaction, Transaction.class);
|
||||||
// fetch additionalData
|
transactionService.save(transaction);
|
||||||
AdditionalData data = additionalDataService.getAdditionalDataRepository()
|
return t1;
|
||||||
.findByTransactionIdAndRequestType(
|
|
||||||
transaction.getId().toString(), RequestType.CONFIRM).orElse(null);
|
|
||||||
if(data != null) {
|
|
||||||
transaction.setAdditionalData(Utils.fromJson(data.getJsonString(), List.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
return transaction;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import zw.qantra.tm.domain.services.*;
|
|||||||
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
|
||||||
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
|
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
|
||||||
import zw.qantra.tm.exceptions.ApiException;
|
import zw.qantra.tm.exceptions.ApiException;
|
||||||
|
|
||||||
@Service("integration")
|
@Service("integration")
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
spring.application.name=tm
|
spring.application.name=tm
|
||||||
spring.main.allow-bean-definition-overriding=true
|
|
||||||
debug=false
|
debug=false
|
||||||
|
|
||||||
logging.level.org.springframework.boot.autoconfigure=INFO
|
logging.level.org.springframework.boot.autoconfigure=INFO
|
||||||
|
|||||||
Reference in New Issue
Block a user