split bounded contexts into separate maven modules
This commit is contained in:
17
loan-agreement/Dockerfile
Normal file
17
loan-agreement/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM maven:3.8.5-openjdk-17 as build
|
||||
|
||||
COPY ../pom.xml .
|
||||
|
||||
RUN mvn -B dependency:go-offline
|
||||
|
||||
COPY ../src src
|
||||
|
||||
RUN mvn -B package
|
||||
|
||||
FROM openjdk:11-jre-slim-buster
|
||||
|
||||
COPY --from=build ../target/loan-agreement.jar .
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["java", "-jar", "loan-agreement.jar"]
|
||||
159
loan-agreement/pom.xml
Normal file
159
loan-agreement/pom.xml
Normal file
@@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.weinbrecht.luc.bpm.architecture.loan.agreement</groupId>
|
||||
<artifactId>loan-agreement</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<version.springboot>2.6.4</version.springboot>
|
||||
<version.camunda>7.17.0</version.camunda>
|
||||
<version.junit5>5.8.2</version.junit5>
|
||||
<version.lombok>1.18.24</version.lombok>
|
||||
<version.domainprimitives>0.1.0</version.domainprimitives>
|
||||
<version.bpmAssert>1.1.0</version.bpmAssert>
|
||||
<version.camundaMockito>6.17.0</version.camundaMockito>
|
||||
<version.okhttp>4.9.3</version.okhttp>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${version.springboot}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.camunda.bpm</groupId>
|
||||
<artifactId>camunda-bom</artifactId>
|
||||
<version>${version.camunda}</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.camunda.bpm.springboot</groupId>
|
||||
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.camunda.bpm.springboot</groupId>
|
||||
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.camunda.bpm.springboot</groupId>
|
||||
<artifactId>camunda-bpm-spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.domain-primitives</groupId>
|
||||
<artifactId>domainprimitives-java</artifactId>
|
||||
<version>${version.domainprimitives}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${version.lombok}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${version.junit5}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${version.junit5}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${version.junit5}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.camunda.bpm.extension</groupId>
|
||||
<artifactId>camunda-bpm-junit5</artifactId>
|
||||
<version>${version.bpmAssert}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.camunda.community.mockito</groupId>
|
||||
<artifactId>camunda-platform-7-mockito</artifactId>
|
||||
<version>${version.camundaMockito}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${version.okhttp}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<version>${version.okhttp}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${version.springboot}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String... args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common;
|
||||
|
||||
public class ProcessConstants {
|
||||
|
||||
public static final String PROCESS_DEFINITION = "Loan_Agreement";
|
||||
public static final String LOAN_START_EVENT_MESSAGE_REF = "loanAgreementReceivedMessage";
|
||||
public static final String LOAN_AGREEMENT_NUMBER = "loanAgreementNumber";
|
||||
|
||||
public static final String RECOMMENDATION_START_EVENT_MESSAGE_REF = "crossSellingPotentialDiscoveredMessage";
|
||||
public static final String RECOMMENDATION_CUSTOMER_NUMBER = "customerNumber";
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementStatusCommand;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.camunda.bpm.engine.delegate.DelegateExecution;
|
||||
import org.camunda.bpm.engine.delegate.JavaDelegate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.LOAN_AGREEMENT_NUMBER;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class ApproveLoanAgreement implements JavaDelegate {
|
||||
|
||||
private final LoanAgreementStatusCommand loanAgreementStatusCommand;
|
||||
|
||||
@Override
|
||||
public void execute(DelegateExecution delegateExecution) {
|
||||
Long loanAgreementNumber = (Long) delegateExecution.getVariable(LOAN_AGREEMENT_NUMBER);
|
||||
loanAgreementStatusCommand.accept(new LoanAgreementNumber(loanAgreementNumber));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementStatusCommand;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.camunda.bpm.engine.delegate.DelegateExecution;
|
||||
import org.camunda.bpm.engine.delegate.JavaDelegate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.LOAN_AGREEMENT_NUMBER;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class RejectionLoanAgreement implements JavaDelegate {
|
||||
|
||||
private final LoanAgreementStatusCommand loanAgreementStatusCommand;
|
||||
|
||||
@Override
|
||||
public void execute(DelegateExecution delegateExecution) {
|
||||
Long loanAgreementNumber = (Long) delegateExecution.getVariable(LOAN_AGREEMENT_NUMBER);
|
||||
loanAgreementStatusCommand.reject(new LoanAgreementNumber(loanAgreementNumber));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.camunda.bpm.engine.RuntimeService;
|
||||
import org.camunda.bpm.engine.delegate.DelegateExecution;
|
||||
import org.camunda.bpm.engine.delegate.JavaDelegate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.*;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class SendCrossSellingRecommendation implements JavaDelegate {
|
||||
|
||||
private final RuntimeService runtimeService;
|
||||
private final LoanAgreementQuery loanAgreementQuery;
|
||||
|
||||
@Override
|
||||
public void execute(DelegateExecution execution) {
|
||||
Long loanNumber = (Long) execution.getVariable(LOAN_AGREEMENT_NUMBER);
|
||||
LoanAgreement loanAgreement = loanAgreementQuery.loadByNumber(new LoanAgreementNumber(loanNumber));
|
||||
|
||||
Map<String, Object> processVariables = new HashMap<>();
|
||||
processVariables.put(RECOMMENDATION_CUSTOMER_NUMBER, loanAgreement.getRecipient().getCustomerNumber().getValue());
|
||||
|
||||
runtimeService.startProcessInstanceByMessage(
|
||||
RECOMMENDATION_START_EVENT_MESSAGE_REF,
|
||||
buildCrossSellingBusinessKey(loanNumber, execution.getBusinessKey()),
|
||||
processVariables
|
||||
);
|
||||
}
|
||||
|
||||
private String buildCrossSellingBusinessKey(Long loanNumber, String caseId) {
|
||||
return caseId + "-" + loanNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementCreation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("loan/agreement/")
|
||||
class LoanAgreementController {
|
||||
|
||||
private final LoanAgreementCreation loanAgreementCreation;
|
||||
private final LoanAgreementMapper mapper;
|
||||
|
||||
@PostMapping("/{caseId}")
|
||||
public void create(@RequestBody LoanAgreementResource loanAgreementResource,
|
||||
@PathVariable String caseId) {
|
||||
loanAgreementCreation.create(mapper.mapToDomain(loanAgreementResource), new CaseId(caseId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.Amount;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CustomerNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.MailAddress;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Name;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("LoanAgreementMapperWeb")
|
||||
class LoanAgreementMapper {
|
||||
public LoanAgreement mapToDomain(LoanAgreementResource loanAgreementResource) {
|
||||
return new LoanAgreement(
|
||||
new Recipient(
|
||||
new CustomerNumber(loanAgreementResource.getCustomerNumber()),
|
||||
new Name(loanAgreementResource.getName()),
|
||||
new MailAddress(loanAgreementResource.getMailAddress())
|
||||
),
|
||||
new Amount(loanAgreementResource.getAmount())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
class LoanAgreementResource {
|
||||
private String customerNumber;
|
||||
private String name;
|
||||
private String mailAddress;
|
||||
private Integer amount;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface LoanAgreementCRUDRepository extends CrudRepository<LoanAgreementEntity, Long> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import static javax.persistence.GenerationType.AUTO;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
class LoanAgreementEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy= AUTO)
|
||||
private Long id;
|
||||
private Integer amount;
|
||||
private String customerNumber;
|
||||
private String name;
|
||||
private String mailAddress;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.Amount;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CustomerNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.MailAddress;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Name;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("LoanAgreementMapperDb")
|
||||
class LoanAgreementMapper {
|
||||
public LoanAgreementEntity mapToDb(LoanAgreement loanAgreement) {
|
||||
LoanAgreementEntity loanAgreementEntity = new LoanAgreementEntity();
|
||||
loanAgreementEntity.setAmount(loanAgreement.getAmount().getValue());
|
||||
Recipient recipient = loanAgreement.getRecipient();
|
||||
loanAgreementEntity.setCustomerNumber(recipient.getCustomerNumber().getValue());
|
||||
loanAgreementEntity.setName(recipient.getName().getValue());
|
||||
loanAgreementEntity.setMailAddress(recipient.getMailAddress().getValue());
|
||||
return loanAgreementEntity;
|
||||
}
|
||||
|
||||
public LoanAgreement mapToDomain(LoanAgreementEntity loanAgreementEntity) {
|
||||
return new LoanAgreement(
|
||||
new LoanAgreementNumber(loanAgreementEntity.getId()),
|
||||
new Recipient(
|
||||
new CustomerNumber(loanAgreementEntity.getCustomerNumber()),
|
||||
new Name(loanAgreementEntity.getName()),
|
||||
new MailAddress(loanAgreementEntity.getMailAddress())
|
||||
),
|
||||
new Amount(loanAgreementEntity.getAmount())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
class LoanAgreementNotFoundException extends RuntimeException {
|
||||
public LoanAgreementNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementCommand;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
class LoanAgreementRepository implements LoanAgreementCommand, LoanAgreementQuery {
|
||||
|
||||
private final LoanAgreementCRUDRepository crudRepository;
|
||||
private final LoanAgreementMapper mapper;
|
||||
|
||||
@Override
|
||||
public LoanAgreement save(LoanAgreement loanAgreement) {
|
||||
LoanAgreementEntity savedLoanAgreement = crudRepository.save(mapper.mapToDb(loanAgreement));
|
||||
return mapper.mapToDomain(savedLoanAgreement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanAgreement loadByNumber(LoanAgreementNumber loanAgreementNumber) {
|
||||
return crudRepository.findById(loanAgreementNumber.getValue())
|
||||
.map(mapper::mapToDomain)
|
||||
.orElseThrow(() -> new LoanAgreementNotFoundException(
|
||||
format("Could not find loan agreement to number %s", loanAgreementNumber.getValue())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.legacy;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementDistributor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LoanAgreementDistributorClient implements LoanAgreementDistributor {
|
||||
@Override
|
||||
public void sendLoanAgreement(LoanAgreement loanAgreement, boolean accepted) {
|
||||
log.info("Sending loan agreement with number {} and status [{}] to legacy system",
|
||||
loanAgreement.getLoanAgreementNumber().getValue(), accepted);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.recommendation;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.RecommendationTrigger;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static reactor.core.publisher.Mono.just;
|
||||
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
class RecommendationClient implements RecommendationTrigger {
|
||||
|
||||
private final WebClient webClient;
|
||||
|
||||
@Autowired
|
||||
public RecommendationClient(@Value("${custom.recommendation.address:localhost:8081}") String recommendationAddress) {
|
||||
this.webClient = WebClient.create("http://" + recommendationAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLoanAgreement(CaseId caseId, LoanAgreement loanAgreement) {
|
||||
RecommendationResource recommendationResource = new RecommendationResource();
|
||||
recommendationResource.setLoanAgreementNumber(loanAgreement.getLoanAgreementNumber().getValue());
|
||||
recommendationResource.setCustomerNumber(loanAgreement.getRecipient().getCustomerNumber().getValue());
|
||||
|
||||
webClient.post().uri("/recommendation/" + caseId.getValue())
|
||||
.body(just(recommendationResource), RecommendationResource.class)
|
||||
.retrieve()
|
||||
.bodyToMono(Void.class)
|
||||
.block();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.recommendation;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
class RecommendationResource {
|
||||
private Long loanAgreementNumber;
|
||||
private String customerNumber;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import io.github.domainprimitives.type.ValueObject;
|
||||
|
||||
import static io.github.domainprimitives.validation.Constraints.isGreatThanOrEqual;
|
||||
|
||||
|
||||
public class Amount extends ValueObject<Integer> {
|
||||
public Amount(Integer value) {
|
||||
super(value, isGreatThanOrEqual(100));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o != null && this.getClass() == o.getClass()) {
|
||||
ValueObject<Integer> valueObject = (ValueObject)o;
|
||||
return (valueObject.getValue()).equals(this.getValue());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import io.github.domainprimitives.type.ValueObject;
|
||||
|
||||
import static io.github.domainprimitives.validation.Constraints.isNotBlank;
|
||||
|
||||
public class CaseId extends ValueObject<String> {
|
||||
public CaseId(String value) {
|
||||
super(value, isNotBlank());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import io.github.domainprimitives.type.ValueObject;
|
||||
|
||||
import static io.github.domainprimitives.validation.Constraints.isNotBlank;
|
||||
|
||||
public class CustomerNumber extends ValueObject<String> {
|
||||
public CustomerNumber(String value) {
|
||||
super(value, isNotBlank());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
import io.github.domainprimitives.object.Aggregate;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LoanAgreement extends Aggregate {
|
||||
|
||||
private LoanAgreementNumber loanAgreementNumber;
|
||||
private final Recipient recipient;
|
||||
private final Amount amount;
|
||||
|
||||
public LoanAgreement(Recipient recipient, Amount amount) {
|
||||
this.recipient = recipient;
|
||||
this.amount = amount;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
public LoanAgreement(LoanAgreementNumber loanAgreementNumber, Recipient recipient, Amount amount) {
|
||||
this(recipient, amount);
|
||||
this.loanAgreementNumber = loanAgreementNumber;
|
||||
|
||||
validateNotNull(loanAgreementNumber, "Loan Agreement Number");
|
||||
evaluateValidations();
|
||||
}
|
||||
|
||||
protected void validate() {
|
||||
validateNotNull(recipient, "Recipient");
|
||||
validateNotNull(amount, "Loan Amount");
|
||||
evaluateValidations();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import io.github.domainprimitives.type.ValueObject;
|
||||
|
||||
import static io.github.domainprimitives.validation.Constraints.isNotNullLong;
|
||||
|
||||
public class LoanAgreementNumber extends ValueObject<Long> {
|
||||
public LoanAgreementNumber(Long value) {
|
||||
super(value, isNotNullLong());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient;
|
||||
|
||||
import io.github.domainprimitives.type.ValueObject;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static io.github.domainprimitives.validation.Constraints.isPattern;
|
||||
|
||||
public class MailAddress extends ValueObject<String> {
|
||||
|
||||
public static final String VALID_EMAIL_ADDRESS_REGEX =
|
||||
Pattern.compile("^[a-zA-Z0-9_!#$%&’*+=?`{|}~^.-]+@[a-zA-Z0-9.-]+$",
|
||||
Pattern.CASE_INSENSITIVE).pattern();
|
||||
|
||||
|
||||
public MailAddress(String value) {
|
||||
super(value, isPattern(VALID_EMAIL_ADDRESS_REGEX));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient;
|
||||
|
||||
import io.github.domainprimitives.type.ValueObject;
|
||||
|
||||
import static io.github.domainprimitives.validation.Constraints.hasMinLength;
|
||||
|
||||
public class Name extends ValueObject<String> {
|
||||
public Name(String value) {
|
||||
super(value, hasMinLength(3));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CustomerNumber;
|
||||
import io.github.domainprimitives.object.ComposedValueObject;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Recipient extends ComposedValueObject {
|
||||
|
||||
private final CustomerNumber customerNumber;
|
||||
private final Name name;
|
||||
private final MailAddress mailAddress;
|
||||
|
||||
public Recipient(CustomerNumber customerNumber, Name name, MailAddress mailAddress) {
|
||||
this.customerNumber = customerNumber;
|
||||
this.name = name;
|
||||
this.mailAddress = mailAddress;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validate() {
|
||||
validateNotNull(customerNumber, "Customer Number");
|
||||
validateNotNull(name, "Name");
|
||||
validateNotNull(mailAddress, "Mail Address");
|
||||
evaluateValidations();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.service;
|
||||
|
||||
public class LoanAgreementException extends RuntimeException {
|
||||
|
||||
public LoanAgreementException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LoanAgreementException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.service;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementCreation;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementStatusCommand;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementCommand;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementDistributor;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementQuery;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.RecommendationTrigger;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LoanAgreementService implements LoanAgreementCreation, LoanAgreementStatusCommand {
|
||||
|
||||
private final LoanAgreementCommand loanAgreementCommand;
|
||||
private final RecommendationTrigger recommendationTrigger;
|
||||
private final LoanAgreementDistributor loanAgreementDistributor;
|
||||
private final LoanAgreementQuery loanAgreementQuery;
|
||||
|
||||
@Override
|
||||
public void create(LoanAgreement loanAgreement, CaseId caseId) {
|
||||
try {
|
||||
LoanAgreement savedLoanAgreement = loanAgreementCommand.save(loanAgreement);
|
||||
recommendationTrigger.startLoanAgreement(caseId, savedLoanAgreement);
|
||||
} catch (Exception e) {
|
||||
throw new LoanAgreementException("Cloud not save the loan agreement", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(LoanAgreementNumber loanAgreementNumber) {
|
||||
loanAgreementDistributor.sendLoanAgreement(loanAgreementQuery.loadByNumber(loanAgreementNumber), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reject(LoanAgreementNumber loanAgreementNumber) {
|
||||
loanAgreementDistributor.sendLoanAgreement(loanAgreementQuery.loadByNumber(loanAgreementNumber), false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
|
||||
public interface LoanAgreementCreation {
|
||||
void create(LoanAgreement loanAgreement, CaseId caseId);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
|
||||
public interface LoanAgreementStatusCommand {
|
||||
void accept(LoanAgreementNumber loanAgreementNumber);
|
||||
void reject(LoanAgreementNumber loanAgreementNumber);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
|
||||
public interface LoanAgreementCommand {
|
||||
LoanAgreement save(LoanAgreement loanAgreement);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
|
||||
public interface LoanAgreementDistributor {
|
||||
void sendLoanAgreement(LoanAgreement loanAgreement, boolean accepted);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
|
||||
public interface LoanAgreementQuery {
|
||||
LoanAgreement loadByNumber(LoanAgreementNumber loanAgreementNumber);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
|
||||
public interface RecommendationTrigger {
|
||||
void startLoanAgreement(CaseId caseId, LoanAgreement loanAgreement);
|
||||
}
|
||||
13
loan-agreement/src/main/resources/application.yaml
Normal file
13
loan-agreement/src/main/resources/application.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:file:./camunda-loan-agreement-h2-database
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: create-drop
|
||||
|
||||
camunda.bpm.admin-user:
|
||||
id: admin
|
||||
password: pw
|
||||
generic-properties:
|
||||
properties:
|
||||
initializeTelemetry: false
|
||||
36
loan-agreement/src/main/resources/approve_agreement.dmn
Normal file
36
loan-agreement/src/main/resources/approve_agreement.dmn
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/" xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/" xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/" xmlns:modeler="http://camunda.org/schema/modeler/1.0" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/2.0" xmlns:camunda="http://camunda.org/schema/1.0/dmn" id="Definitions_11dxtis" name="DRD" namespace="http://camunda.org/schema/1.0/dmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
|
||||
<decision id="approvement-check" name="Approve Loan Agreement">
|
||||
<decisionTable id="DecisionTable_0ffqkch">
|
||||
<input id="Input_1" biodi:width="192" camunda:inputVariable="loanAgreementNumber">
|
||||
<inputExpression id="InputExpression_1" typeRef="integer">
|
||||
<text>loanAgreementNumber</text>
|
||||
</inputExpression>
|
||||
</input>
|
||||
<output id="Output_1" name="approved" typeRef="boolean" biodi:width="192" />
|
||||
<rule id="DecisionRule_0p9ijdl">
|
||||
<inputEntry id="UnaryTests_1qou5p9">
|
||||
<text>>= 5</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1hlf608">
|
||||
<text>false</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_1arucld">
|
||||
<inputEntry id="UnaryTests_1vqubek">
|
||||
<text>< 5</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1ovr1wt">
|
||||
<text>true</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
</decisionTable>
|
||||
</decision>
|
||||
<dmndi:DMNDI>
|
||||
<dmndi:DMNDiagram>
|
||||
<dmndi:DMNShape dmnElementRef="approvement-check">
|
||||
<dc:Bounds height="80" width="180" x="160" y="100" />
|
||||
</dmndi:DMNShape>
|
||||
</dmndi:DMNDiagram>
|
||||
</dmndi:DMNDI>
|
||||
</definitions>
|
||||
158
loan-agreement/src/main/resources/loan_agreement.bpmn
Normal file
158
loan-agreement/src/main/resources/loan_agreement.bpmn
Normal file
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1yngi5u" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
|
||||
<bpmn:collaboration id="Collaboration_0w4ikjr">
|
||||
<bpmn:participant id="Participant_1p6ilgg" name="Loan Agreement example" processRef="Loan_Agreement" />
|
||||
<bpmn:participant id="Participant_0y932pu" name="Third-party-legacy System" />
|
||||
<bpmn:participant id="Participant_0z5fkq5" name="Third-party-legacy System" />
|
||||
<bpmn:messageFlow id="Flow_1ytdopc" sourceRef="RejectLoanAgreementServiceTask" targetRef="Participant_0y932pu" />
|
||||
<bpmn:messageFlow id="Flow_1ax0a41" sourceRef="ApproveLoanAgreementServiceTask" targetRef="Participant_0z5fkq5" />
|
||||
</bpmn:collaboration>
|
||||
<bpmn:process id="Loan_Agreement" name="Loan Agreement" isExecutable="true">
|
||||
<bpmn:businessRuleTask id="ApproveAgreementRuleTask" name="Approve agreement" camunda:resultVariable="approved" camunda:decisionRef="approvement-check" camunda:mapDecisionResult="singleEntry">
|
||||
<bpmn:extensionElements />
|
||||
<bpmn:incoming>Flow_1rrsueh</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_00ukhfv</bpmn:outgoing>
|
||||
</bpmn:businessRuleTask>
|
||||
<bpmn:exclusiveGateway id="IsApprovedGateway" name="Is agreement approved?">
|
||||
<bpmn:incoming>Flow_00ukhfv</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0xpo6jp</bpmn:outgoing>
|
||||
<bpmn:outgoing>Flow_1hri7xc</bpmn:outgoing>
|
||||
</bpmn:exclusiveGateway>
|
||||
<bpmn:serviceTask id="ApproveLoanAgreementServiceTask" name="Approve loan agreement" camunda:delegateExpression="${approveLoanAgreement}">
|
||||
<bpmn:incoming>Flow_1hri7xc</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1uqmps7</bpmn:outgoing>
|
||||
</bpmn:serviceTask>
|
||||
<bpmn:startEvent id="LoanAgreementReciedStartEvent" name="loan agreement recived" camunda:asyncAfter="true">
|
||||
<bpmn:outgoing>Flow_1rrsueh</bpmn:outgoing>
|
||||
<bpmn:messageEventDefinition id="MessageEventDefinition_1j9r08u" messageRef="Message_0o102df" />
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1uqmps7" sourceRef="ApproveLoanAgreementServiceTask" targetRef="SendCrossSellingEvent" />
|
||||
<bpmn:sequenceFlow id="Flow_1hri7xc" name="yes" sourceRef="IsApprovedGateway" targetRef="ApproveLoanAgreementServiceTask">
|
||||
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved}</bpmn:conditionExpression>
|
||||
</bpmn:sequenceFlow>
|
||||
<bpmn:sequenceFlow id="Flow_0xpo6jp" name="no" sourceRef="IsApprovedGateway" targetRef="RejectLoanAgreementServiceTask">
|
||||
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!approved}</bpmn:conditionExpression>
|
||||
</bpmn:sequenceFlow>
|
||||
<bpmn:sequenceFlow id="Flow_00ukhfv" sourceRef="ApproveAgreementRuleTask" targetRef="IsApprovedGateway" />
|
||||
<bpmn:sequenceFlow id="Flow_1rrsueh" sourceRef="LoanAgreementReciedStartEvent" targetRef="ApproveAgreementRuleTask" />
|
||||
<bpmn:serviceTask id="RejectLoanAgreementServiceTask" name="Rejection loan agreement" camunda:delegateExpression="${rejectionLoanAgreement}">
|
||||
<bpmn:incoming>Flow_0xpo6jp</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0eif63m</bpmn:outgoing>
|
||||
</bpmn:serviceTask>
|
||||
<bpmn:sequenceFlow id="Flow_0eif63m" sourceRef="RejectLoanAgreementServiceTask" targetRef="LoanAgreementNotApprovedEndEvent" />
|
||||
<bpmn:endEvent id="LoanAgreementApprovedEndEvent" name="loan agreement approved">
|
||||
<bpmn:incoming>Flow_1pvaqlv</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1pvaqlv" sourceRef="SendCrossSellingEvent" targetRef="LoanAgreementApprovedEndEvent" />
|
||||
<bpmn:intermediateThrowEvent id="SendCrossSellingEvent" name="Send cross-selling recommendaiton">
|
||||
<bpmn:incoming>Flow_1uqmps7</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1pvaqlv</bpmn:outgoing>
|
||||
<bpmn:messageEventDefinition id="MessageEventDefinition_0drw25h" camunda:delegateExpression="${sendCrossSellingRecommendation}" />
|
||||
</bpmn:intermediateThrowEvent>
|
||||
<bpmn:endEvent id="LoanAgreementNotApprovedEndEvent" name="loan agreement not approved">
|
||||
<bpmn:incoming>Flow_0eif63m</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
</bpmn:process>
|
||||
<bpmn:message id="Message_0o102df" name="loanAgreementReceivedMessage" />
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_0w4ikjr">
|
||||
<bpmndi:BPMNShape id="Participant_1p6ilgg_di" bpmnElement="Participant_1p6ilgg" isHorizontal="true">
|
||||
<dc:Bounds x="160" y="177" width="820" height="255" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1rrsueh_di" bpmnElement="Flow_1rrsueh">
|
||||
<di:waypoint x="258" y="237" />
|
||||
<di:waypoint x="330" y="237" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_00ukhfv_di" bpmnElement="Flow_00ukhfv">
|
||||
<di:waypoint x="430" y="237" />
|
||||
<di:waypoint x="485" y="237" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0xpo6jp_di" bpmnElement="Flow_0xpo6jp">
|
||||
<di:waypoint x="510" y="262" />
|
||||
<di:waypoint x="510" y="360" />
|
||||
<di:waypoint x="600" y="360" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="519" y="308" width="13" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1hri7xc_di" bpmnElement="Flow_1hri7xc">
|
||||
<di:waypoint x="535" y="237" />
|
||||
<di:waypoint x="600" y="237" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="559" y="219" width="18" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1uqmps7_di" bpmnElement="Flow_1uqmps7">
|
||||
<di:waypoint x="700" y="237" />
|
||||
<di:waypoint x="772" y="237" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0eif63m_di" bpmnElement="Flow_0eif63m">
|
||||
<di:waypoint x="700" y="360" />
|
||||
<di:waypoint x="772" y="360" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1pvaqlv_di" bpmnElement="Flow_1pvaqlv">
|
||||
<di:waypoint x="808" y="237" />
|
||||
<di:waypoint x="882" y="237" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="Activity_1244zx8_di" bpmnElement="ApproveAgreementRuleTask">
|
||||
<dc:Bounds x="330" y="197" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Gateway_0xmpbgn_di" bpmnElement="IsApprovedGateway" isMarkerVisible="true">
|
||||
<dc:Bounds x="485" y="212" width="50" height="50" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="478" y="182" width="65" height="27" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_13yt0mp_di" bpmnElement="ApproveLoanAgreementServiceTask">
|
||||
<dc:Bounds x="600" y="197" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1uvc9z4_di" bpmnElement="RejectLoanAgreementServiceTask">
|
||||
<dc:Bounds x="600" y="320" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_086ty8n_di" bpmnElement="LoanAgreementReciedStartEvent">
|
||||
<dc:Bounds x="222" y="219" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="202" y="262" width="77" height="27" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0mxjaa5_di" bpmnElement="LoanAgreementApprovedEndEvent">
|
||||
<dc:Bounds x="882" y="219" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="862" y="262" width="77" height="27" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_1hg5yw3_di" bpmnElement="SendCrossSellingEvent">
|
||||
<dc:Bounds x="772" y="219" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="750" y="262" width="82" height="40" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_1i3yo9j_di" bpmnElement="LoanAgreementNotApprovedEndEvent">
|
||||
<dc:Bounds x="772" y="342" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="752" y="385" width="77" height="27" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Participant_1s9mw1a_di" bpmnElement="Participant_0y932pu" isHorizontal="true">
|
||||
<dc:Bounds x="500" y="460" width="300" height="60" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="BPMNShape_1ilsqo5" bpmnElement="Participant_0z5fkq5" isHorizontal="true">
|
||||
<dc:Bounds x="500" y="80" width="300" height="60" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1ytdopc_di" bpmnElement="Flow_1ytdopc">
|
||||
<di:waypoint x="650" y="400" />
|
||||
<di:waypoint x="650" y="460" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1ax0a41_di" bpmnElement="Flow_1ax0a41">
|
||||
<di:waypoint x="650" y="197" />
|
||||
<di:waypoint x="650" y="140" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
||||
@@ -0,0 +1,126 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process.ApproveLoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process.RejectionLoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process.SendCrossSellingRecommendation;
|
||||
import org.camunda.bpm.dmn.engine.DmnDecisionTableResult;
|
||||
import org.camunda.bpm.engine.runtime.ProcessInstance;
|
||||
import org.camunda.bpm.engine.test.Deployment;
|
||||
import org.camunda.bpm.extension.junit5.test.ProcessEngineExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.LOAN_AGREEMENT_NUMBER;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat;
|
||||
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.decisionService;
|
||||
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.execute;
|
||||
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.job;
|
||||
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.runtimeService;
|
||||
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.withVariables;
|
||||
import static org.camunda.community.mockito.DelegateExpressions.registerJavaDelegateMock;
|
||||
import static org.camunda.community.mockito.DelegateExpressions.verifyJavaDelegateMock;
|
||||
|
||||
@ExtendWith(ProcessEngineExtension.class)
|
||||
class ProcessTest {
|
||||
|
||||
public static final String PROCESS_DEFINITION = "Loan_Agreement";
|
||||
|
||||
private static final String START_EVENT = "LoanAgreementReciedStartEvent";
|
||||
private static final String APPROVE_RULE_TASK = "ApproveAgreementRuleTask";
|
||||
private static final String APPROVE_AGREEMENT_SERVICE_TASK = "ApproveLoanAgreementServiceTask";
|
||||
private static final String SEND_CROSS_SELLING_EVENT = "SendCrossSellingEvent";
|
||||
private static final String APPROVED_END_EVENT = "LoanAgreementApprovedEndEvent";
|
||||
|
||||
private static final String REJECT_AGREEMENT_SERVICE_TASK = "RejectLoanAgreementServiceTask";
|
||||
private static final String NOT_APPROVED_END_EVENT = "LoanAgreementNotApprovedEndEvent";
|
||||
|
||||
private static final String DMN_DEFINITION = "approvement-check";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
registerJavaDelegateMock(ApproveLoanAgreement.class);
|
||||
registerJavaDelegateMock(RejectionLoanAgreement.class);
|
||||
registerJavaDelegateMock(SendCrossSellingRecommendation.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deployment(resources = { "loan_agreement.bpmn", "approve_agreement.dmn"})
|
||||
void shouldExecuteProcess_happy_path() {
|
||||
ProcessInstance processInstance = runtimeService().startProcessInstanceByKey(
|
||||
PROCESS_DEFINITION,
|
||||
withVariables(LOAN_AGREEMENT_NUMBER, 1L)
|
||||
);
|
||||
assertThat(processInstance).isActive();
|
||||
|
||||
assertThat(processInstance).isWaitingAt(START_EVENT);
|
||||
|
||||
execute(job());
|
||||
|
||||
assertThat(processInstance)
|
||||
.hasPassed(START_EVENT,
|
||||
APPROVE_RULE_TASK,
|
||||
APPROVE_AGREEMENT_SERVICE_TASK,
|
||||
SEND_CROSS_SELLING_EVENT,
|
||||
APPROVED_END_EVENT);
|
||||
|
||||
verifyJavaDelegateMock(SendCrossSellingRecommendation.class).executed();
|
||||
verifyJavaDelegateMock(ApproveLoanAgreement.class).executed();
|
||||
|
||||
assertThat(processInstance).isEnded();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deployment(resources = { "loan_agreement.bpmn", "approve_agreement.dmn"})
|
||||
void shouldExecuteProcess_exceptional_path() {
|
||||
ProcessInstance processInstance = runtimeService().startProcessInstanceByKey(
|
||||
PROCESS_DEFINITION,
|
||||
withVariables(LOAN_AGREEMENT_NUMBER, 8L)
|
||||
);
|
||||
assertThat(processInstance).isActive();
|
||||
|
||||
assertThat(processInstance).isWaitingAt(START_EVENT);
|
||||
|
||||
execute(job());
|
||||
|
||||
assertThat(processInstance)
|
||||
.hasPassed(START_EVENT,
|
||||
APPROVE_RULE_TASK,
|
||||
REJECT_AGREEMENT_SERVICE_TASK,
|
||||
NOT_APPROVED_END_EVENT);
|
||||
|
||||
verifyJavaDelegateMock(RejectionLoanAgreement.class).executed();
|
||||
|
||||
assertThat(processInstance).isEnded();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideProcessVariablesForDMN")
|
||||
@Deployment(resources = "approve_agreement.dmn")
|
||||
void testApprovementDMN(Long input, boolean expected) {
|
||||
Map<String, Object> variables = withVariables(LOAN_AGREEMENT_NUMBER, input);
|
||||
|
||||
DmnDecisionTableResult tableResult = decisionService().evaluateDecisionTableByKey(DMN_DEFINITION, variables);
|
||||
|
||||
assertThat(tableResult.getFirstResult()).contains(entry("approved", expected));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> provideProcessVariablesForDMN() {
|
||||
return Stream.of(
|
||||
Arguments.of(1L, true),
|
||||
Arguments.of(2L, true),
|
||||
Arguments.of(3L, true),
|
||||
Arguments.of(4L, true),
|
||||
Arguments.of(5L, false),
|
||||
Arguments.of(6L, false)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementStatusCommand;
|
||||
import org.camunda.bpm.engine.delegate.DelegateExecution;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.LOAN_AGREEMENT_NUMBER;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@MockitoSettings
|
||||
class ApproveLoanAgreementTest {
|
||||
@InjectMocks
|
||||
private ApproveLoanAgreement classUnderTest;
|
||||
|
||||
@Mock
|
||||
private LoanAgreementStatusCommand loanAgreementStatusCommand;
|
||||
|
||||
@Test
|
||||
void should_call_command_and_reject() {
|
||||
LoanAgreementNumber loanAgreementNumber = new LoanAgreementNumber(1L);
|
||||
DelegateExecution delegateExecution = mock(DelegateExecution.class);
|
||||
when(delegateExecution.getVariable(LOAN_AGREEMENT_NUMBER)).thenReturn(loanAgreementNumber.getValue());
|
||||
|
||||
classUnderTest.execute(delegateExecution);
|
||||
|
||||
verify(loanAgreementStatusCommand).accept(loanAgreementNumber);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementStatusCommand;
|
||||
import org.camunda.bpm.engine.delegate.DelegateExecution;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.LOAN_AGREEMENT_NUMBER;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@MockitoSettings
|
||||
class RejectionLoanAgreementTest {
|
||||
|
||||
@InjectMocks
|
||||
private RejectionLoanAgreement classUnderTest;
|
||||
|
||||
@Mock
|
||||
private LoanAgreementStatusCommand loanAgreementStatusCommand;
|
||||
|
||||
@Test
|
||||
void should_call_command_and_reject() {
|
||||
LoanAgreementNumber loanAgreementNumber = new LoanAgreementNumber(1L);
|
||||
DelegateExecution delegateExecution = mock(DelegateExecution.class);
|
||||
when(delegateExecution.getVariable(LOAN_AGREEMENT_NUMBER)).thenReturn(loanAgreementNumber.getValue());
|
||||
|
||||
classUnderTest.execute(delegateExecution);
|
||||
|
||||
verify(loanAgreementStatusCommand).reject(loanAgreementNumber);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.process;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementQuery;
|
||||
import org.camunda.bpm.engine.RuntimeService;
|
||||
import org.camunda.bpm.engine.delegate.DelegateExecution;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.common.ProcessConstants.*;
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreementWithNumber;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@MockitoSettings
|
||||
class SendCrossSellingRecommendationTest {
|
||||
|
||||
@InjectMocks
|
||||
private SendCrossSellingRecommendation classUnderTest;
|
||||
|
||||
@Mock
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
@Mock
|
||||
LoanAgreementQuery loanAgreementQuery;
|
||||
|
||||
@Test
|
||||
void should_load_data_and_start_process_by_message() {
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
String caseId = "11";
|
||||
DelegateExecution delegateExecution = mock(DelegateExecution.class);
|
||||
when(delegateExecution.getBusinessKey()).thenReturn(caseId);
|
||||
when(delegateExecution.getVariable(LOAN_AGREEMENT_NUMBER))
|
||||
.thenReturn(loanAgreement.getLoanAgreementNumber().getValue());
|
||||
when(loanAgreementQuery.loadByNumber(loanAgreement.getLoanAgreementNumber())).thenReturn(loanAgreement);
|
||||
|
||||
classUnderTest.execute(delegateExecution);
|
||||
|
||||
Map<String, Object> processVariables = new HashMap<>();
|
||||
processVariables.put(RECOMMENDATION_CUSTOMER_NUMBER, loanAgreement.getRecipient().getCustomerNumber().getValue());
|
||||
verify(runtimeService).startProcessInstanceByMessage(
|
||||
RECOMMENDATION_START_EVENT_MESSAGE_REF,
|
||||
caseId + "-" + loanAgreement.getLoanAgreementNumber().getValue(),
|
||||
processVariables
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.Amount;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CustomerNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.MailAddress;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Name;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.in.LoanAgreementCreation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
|
||||
|
||||
@WebMvcTest(LoanAgreementController.class)
|
||||
@Import(LoanAgreementMapper.class)
|
||||
class LoanAgreementControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private LoanAgreementCreation loanAgreementCreation;
|
||||
|
||||
@Test
|
||||
void should_class_creation_on_post() throws Exception {
|
||||
String requestJson = "{\"customerNumber\": \"A1\",\"name\": \"Tester\",\"mailAddress\": \"tester@web.io\",\"amount\": 1100}";
|
||||
|
||||
mockMvc.perform(
|
||||
post("/loan/agreement/1")
|
||||
.contentType(APPLICATION_JSON_VALUE)
|
||||
.content(requestJson)
|
||||
)
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk());
|
||||
verify(loanAgreementCreation).create(
|
||||
new LoanAgreement(
|
||||
new Recipient(
|
||||
new CustomerNumber("A1"),
|
||||
new Name("Tester"),
|
||||
new MailAddress("tester@web.io")
|
||||
),
|
||||
new Amount(1100)
|
||||
),
|
||||
new CaseId("1"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class LoanAgreementMapperTest {
|
||||
|
||||
private LoanAgreementMapper classUnderTest = new LoanAgreementMapper();
|
||||
|
||||
@Test
|
||||
void should_map_all_fields() {
|
||||
LoanAgreementResource loanAgreementResource = createLoanAgreementResource();
|
||||
|
||||
LoanAgreement result = classUnderTest.mapToDomain(loanAgreementResource);
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getAmount().getValue()).isEqualTo(loanAgreementResource.getAmount());
|
||||
assertThat(result.getRecipient().getName().getValue()).isEqualTo(loanAgreementResource.getName());
|
||||
assertThat(result.getRecipient().getMailAddress().getValue()).isEqualTo(loanAgreementResource.getMailAddress());
|
||||
assertThat(result.getRecipient().getCustomerNumber().getValue()).isEqualTo(loanAgreementResource.getCustomerNumber());
|
||||
}
|
||||
|
||||
private LoanAgreementResource createLoanAgreementResource() {
|
||||
LoanAgreementResource loanAgreementResource = new LoanAgreementResource();
|
||||
loanAgreementResource.setAmount(400);
|
||||
loanAgreementResource.setCustomerNumber("A11");
|
||||
loanAgreementResource.setMailAddress("tester@web.io");
|
||||
loanAgreementResource.setName("Tester");
|
||||
return loanAgreementResource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
class LoanAgreementCRUDRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
private LoanAgreementCRUDRepository classUnderTest;
|
||||
|
||||
@Test
|
||||
void should_safe_entity() {
|
||||
LoanAgreementEntity result = classUnderTest.save(new LoanAgreementEntity());
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getId()).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db.TestDataGenerator.createLoanAgreementEntity;
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreement;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class LoanAgreementMapperTest {
|
||||
|
||||
private LoanAgreementMapper classUnderTest = new LoanAgreementMapper();
|
||||
|
||||
@Test
|
||||
void should_map_all_fields_to_db() {
|
||||
LoanAgreement loanAgreement = createLoanAgreement();
|
||||
|
||||
LoanAgreementEntity result = classUnderTest.mapToDb(loanAgreement);
|
||||
|
||||
assertThat(result.getAmount()).isEqualTo(loanAgreement.getAmount().getValue());
|
||||
assertThat(result.getName()).isEqualTo(loanAgreement.getRecipient().getName().getValue());
|
||||
assertThat(result.getMailAddress()).isEqualTo(loanAgreement.getRecipient().getMailAddress().getValue());
|
||||
assertThat(result.getCustomerNumber()).isEqualTo(loanAgreement.getRecipient().getCustomerNumber().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_map_all_fields_to_domain() {
|
||||
LoanAgreementEntity loanAgreementEntity = createLoanAgreementEntity();
|
||||
|
||||
LoanAgreement result = classUnderTest.mapToDomain(loanAgreementEntity);
|
||||
|
||||
assertThat(result.getLoanAgreementNumber().getValue()).isEqualTo(loanAgreementEntity.getId());
|
||||
assertThat(result.getAmount().getValue()).isEqualTo(loanAgreementEntity.getAmount());
|
||||
assertThat(result.getRecipient().getName().getValue()).isEqualTo(loanAgreementEntity.getName());
|
||||
assertThat(result.getRecipient().getMailAddress().getValue()).isEqualTo(loanAgreementEntity.getMailAddress());
|
||||
assertThat(result.getRecipient().getCustomerNumber().getValue()).isEqualTo(loanAgreementEntity.getCustomerNumber());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db.TestDataGenerator.createLoanAgreementEntity;
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreement;
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreementWithNumber;
|
||||
import static java.util.Optional.empty;
|
||||
import static java.util.Optional.of;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Answers.CALLS_REAL_METHODS;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@MockitoSettings
|
||||
class LoanAgreementRepositoryTest {
|
||||
|
||||
@InjectMocks
|
||||
private LoanAgreementRepository classUnderTest;
|
||||
|
||||
@Mock
|
||||
private LoanAgreementCRUDRepository crudRepository;
|
||||
|
||||
@Mock(answer = CALLS_REAL_METHODS)
|
||||
private LoanAgreementMapper mapper;
|
||||
|
||||
@Test
|
||||
void should_call_crud_repo_and_safe() {
|
||||
LoanAgreement loanAgreement = createLoanAgreement();
|
||||
LoanAgreementEntity dbEntity = createLoanAgreementEntity();
|
||||
when(crudRepository.save(mapper.mapToDb(loanAgreement))).thenReturn(dbEntity);
|
||||
|
||||
LoanAgreement result = classUnderTest.save(loanAgreement);
|
||||
|
||||
assertThat(result).isEqualTo(createLoanAgreementWithNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_call_crud_repo_and_find_by_id() {
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
when(crudRepository.findById(loanAgreement.getLoanAgreementNumber().getValue()))
|
||||
.thenReturn(of(createLoanAgreementEntity()));
|
||||
|
||||
LoanAgreement result = classUnderTest.loadByNumber(loanAgreement.getLoanAgreementNumber());
|
||||
|
||||
assertThat(result).isEqualTo(loanAgreement);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_call_crud_repo_and_find_by_id_throw_custom_exception_if_not_found() {
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
when(crudRepository.findById(loanAgreement.getLoanAgreementNumber().getValue())).thenReturn(empty());
|
||||
|
||||
assertThrows(LoanAgreementNotFoundException.class,
|
||||
() -> classUnderTest.loadByNumber(loanAgreement.getLoanAgreementNumber()));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.db;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreementWithNumber;
|
||||
|
||||
class TestDataGenerator {
|
||||
public static LoanAgreementEntity createLoanAgreementEntity() {
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
LoanAgreementEntity loanAgreementEntity = new LoanAgreementEntity();
|
||||
loanAgreementEntity.setId(loanAgreement.getLoanAgreementNumber().getValue());
|
||||
loanAgreementEntity.setAmount(loanAgreement.getAmount().getValue());
|
||||
loanAgreementEntity.setName(loanAgreement.getRecipient().getName().getValue());
|
||||
loanAgreementEntity.setCustomerNumber(loanAgreement.getRecipient().getCustomerNumber().getValue());
|
||||
loanAgreementEntity.setMailAddress(loanAgreement.getRecipient().getMailAddress().getValue());
|
||||
return loanAgreementEntity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.out.recommendation;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreement;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class RecommendationClientTest {
|
||||
|
||||
private RecommendationClient classUnderTest;
|
||||
|
||||
public static MockWebServer mockBackEnd;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws IOException {
|
||||
mockBackEnd = new MockWebServer();
|
||||
mockBackEnd.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() throws IOException {
|
||||
mockBackEnd.shutdown();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void initialize() {
|
||||
String baseUrl = String.format("localhost:%s", mockBackEnd.getPort());
|
||||
classUnderTest = new RecommendationClient(baseUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_class_runtime_service_to_start() throws Exception {
|
||||
CaseId caseId = new CaseId("11");
|
||||
LoanAgreement loanAgreement = createLoanAgreement();
|
||||
RecommendationResource recommendationResource = new RecommendationResource();
|
||||
recommendationResource.setLoanAgreementNumber(loanAgreement.getLoanAgreementNumber().getValue());
|
||||
recommendationResource.setCustomerNumber(loanAgreement.getRecipient().getCustomerNumber().getValue());
|
||||
String requestJson = "{\"loanAgreementNumber\":" + loanAgreement.getLoanAgreementNumber().getValue() +
|
||||
",\"customerNumber\":\"" + loanAgreement.getRecipient().getCustomerNumber().getValue() + "\"}";
|
||||
|
||||
mockBackEnd.enqueue(new MockResponse()
|
||||
.addHeader("Content-Type", "application/json"));
|
||||
|
||||
classUnderTest.startLoanAgreement(caseId, loanAgreement);
|
||||
|
||||
RecordedRequest recordedRequest = mockBackEnd.takeRequest();
|
||||
assertThat(recordedRequest.getMethod()).isEqualTo("POST");
|
||||
assertThat(recordedRequest.getPath()).isEqualTo("/recommendation/" + caseId);
|
||||
assertThat(recordedRequest.getBody().readUtf8()).isEqualTo(requestJson);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
import io.github.domainprimitives.validation.InvariantException;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createRecipient;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LoanAgreementTest {
|
||||
|
||||
@Test
|
||||
void should_create_valid_object() {
|
||||
Recipient recipient = createRecipient();
|
||||
Amount amount = new Amount(300);
|
||||
|
||||
LoanAgreement loanAgreement = new LoanAgreement(recipient, amount);
|
||||
|
||||
assertThat(loanAgreement).isNotNull();
|
||||
Assertions.assertThat(loanAgreement.getRecipient()).isEqualTo(recipient);
|
||||
assertThat(loanAgreement.getAmount()).isEqualTo(amount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_create_valid_object_with_numer() {
|
||||
Recipient recipient = createRecipient();
|
||||
Amount amount = new Amount(300);
|
||||
LoanAgreementNumber loanAgreementNumber = new LoanAgreementNumber(1L);
|
||||
|
||||
LoanAgreement loanAgreement = new LoanAgreement(loanAgreementNumber, recipient, amount);
|
||||
|
||||
assertThat(loanAgreement).isNotNull();
|
||||
Assertions.assertThat(loanAgreement.getRecipient()).isEqualTo(recipient);
|
||||
assertThat(loanAgreement.getAmount()).isEqualTo(amount);
|
||||
assertThat(loanAgreement.getLoanAgreementNumber()).isEqualTo(loanAgreementNumber);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_create_valid_object_with_number() {
|
||||
Recipient recipient = createRecipient();
|
||||
Amount amount = new Amount(300);
|
||||
LoanAgreementNumber loanAgreementNumber = new LoanAgreementNumber(1L);
|
||||
|
||||
LoanAgreement loanAgreement = new LoanAgreement(loanAgreementNumber, recipient, amount);
|
||||
|
||||
assertNotNull(loanAgreement);
|
||||
assertEquals(loanAgreement.getLoanAgreementNumber(), loanAgreementNumber);
|
||||
assertEquals(loanAgreement.getRecipient(), recipient);
|
||||
assertEquals(loanAgreement.getAmount(), amount);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class InvariantTest {
|
||||
@Test
|
||||
void should_throw_invariant_exception_if_recipient_is_null() {
|
||||
Amount amount = new Amount(300);
|
||||
assertThrows(InvariantException.class, () -> new LoanAgreement(null, amount));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_invariant_exception_if_amount_is_null() {
|
||||
assertThrows(InvariantException.class, () -> new LoanAgreement(createRecipient(), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_invariant_exception_if_number_is_null() {
|
||||
Amount amount = new Amount(300);
|
||||
assertThrows(InvariantException.class, () -> new LoanAgreement(null, createRecipient(), amount));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.MailAddress;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Name;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
import io.github.domainprimitives.validation.InvariantException;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class RecipientTest {
|
||||
|
||||
@Test
|
||||
void should_create_valid_object() {
|
||||
Name name = new Name("Tester");
|
||||
MailAddress mailAddress = new MailAddress("tester@web.io");
|
||||
CustomerNumber customerNumber = new CustomerNumber("A-1");
|
||||
|
||||
Recipient recipient = new Recipient(customerNumber, name, mailAddress);
|
||||
|
||||
assertThat(recipient).isNotNull();
|
||||
assertThat(recipient.getCustomerNumber()).isEqualTo(customerNumber);
|
||||
assertThat(recipient.getName()).isEqualTo(name);
|
||||
assertThat(recipient.getMailAddress()).isEqualTo(mailAddress);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class InvariantTest {
|
||||
@Test
|
||||
void should_throw_invariant_exception_if_customer_number_is_null() {
|
||||
Name name = new Name("Tester");
|
||||
MailAddress mailAddress = new MailAddress("tester@web.io");
|
||||
|
||||
assertThrows(InvariantException.class, () -> new Recipient(null, name, mailAddress));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_invariant_exception_if_name_is_null() {
|
||||
MailAddress mailAddress = new MailAddress("tester@web.io");
|
||||
CustomerNumber customerNumber = new CustomerNumber("A-1");
|
||||
|
||||
assertThrows(InvariantException.class, () -> new Recipient(customerNumber, null, mailAddress));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_invariant_exception_if_mail_is_null() {
|
||||
Name name = new Name("Tester");
|
||||
CustomerNumber customerNumber = new CustomerNumber("A-1");
|
||||
|
||||
assertThrows(InvariantException.class, () -> new Recipient(customerNumber, name, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.MailAddress;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Name;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.recipient.Recipient;
|
||||
|
||||
public class TestdataGenerator {
|
||||
|
||||
public static Recipient createRecipient() {
|
||||
return new Recipient(new CustomerNumber("A-1"), new Name("Tester"), new MailAddress("tester@newweb.io"));
|
||||
}
|
||||
|
||||
public static LoanAgreement createLoanAgreement() {
|
||||
return new LoanAgreement(
|
||||
new LoanAgreementNumber(1L),
|
||||
new Recipient(
|
||||
new CustomerNumber("A-1"),
|
||||
new Name("Tester"),
|
||||
new MailAddress("tester@web.de")
|
||||
),
|
||||
new Amount(400)
|
||||
);
|
||||
}
|
||||
|
||||
public static LoanAgreement createLoanAgreementWithNumber() {
|
||||
return new LoanAgreement(
|
||||
new LoanAgreementNumber(1L),
|
||||
new Recipient(
|
||||
new CustomerNumber("A-1"),
|
||||
new Name("Tester"),
|
||||
new MailAddress("tester@web.de")
|
||||
),
|
||||
new Amount(400)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.service;
|
||||
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.CaseId;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreement;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.LoanAgreementNumber;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementCommand;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementDistributor;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.LoanAgreementQuery;
|
||||
import de.weinbrecht.luc.bpm.architecture.loan.agreement.usecase.out.RecommendationTrigger;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreement;
|
||||
import static de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.model.TestdataGenerator.createLoanAgreementWithNumber;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@MockitoSettings
|
||||
class LoanAgreementServiceTest {
|
||||
|
||||
@InjectMocks
|
||||
private LoanAgreementService classUnderTest;
|
||||
|
||||
@Mock
|
||||
private LoanAgreementCommand loanAgreementCommand;
|
||||
|
||||
@Mock
|
||||
private RecommendationTrigger recommendationTrigger;
|
||||
|
||||
@Mock
|
||||
private LoanAgreementDistributor loanAgreementDistributor;
|
||||
|
||||
@Mock
|
||||
private LoanAgreementQuery loanAgreementQuery;
|
||||
|
||||
@Test
|
||||
void should_safe_and_set_loan_number_on_creation() {
|
||||
LoanAgreement loanAgreement = createLoanAgreement();
|
||||
LoanAgreement savedLoanAgreement = createLoanAgreementWithNumber();
|
||||
when(loanAgreementCommand.save(loanAgreement)).thenReturn(savedLoanAgreement);
|
||||
CaseId caseId = new CaseId("12");
|
||||
|
||||
classUnderTest.create(loanAgreement, caseId);
|
||||
|
||||
verify(recommendationTrigger).startLoanAgreement(caseId, savedLoanAgreement);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_catch_exception_and_throw_custom_one_on_creation() {
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
CaseId caseId = new CaseId("12");
|
||||
when(loanAgreementCommand.save(loanAgreement)).thenThrow(RuntimeException.class);
|
||||
|
||||
assertThrows(LoanAgreementException.class,
|
||||
() -> classUnderTest.create(loanAgreement, caseId));
|
||||
|
||||
verify(recommendationTrigger, never()).startLoanAgreement(caseId, any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_call_distributor_and_set_status_accepted() {
|
||||
LoanAgreementNumber loanAgreementNumber = new LoanAgreementNumber(1L);
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
when(loanAgreementQuery.loadByNumber(loanAgreementNumber)).thenReturn(loanAgreement);
|
||||
|
||||
classUnderTest.accept(loanAgreementNumber);
|
||||
|
||||
verify(loanAgreementDistributor).sendLoanAgreement(loanAgreement, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_call_distributor_and_set_status_reject() {
|
||||
LoanAgreementNumber loanAgreementNumber = new LoanAgreementNumber(1L);
|
||||
LoanAgreement loanAgreement = createLoanAgreementWithNumber();
|
||||
when(loanAgreementQuery.loadByNumber(loanAgreementNumber)).thenReturn(loanAgreement);
|
||||
|
||||
classUnderTest.reject(loanAgreementNumber);
|
||||
|
||||
verify(loanAgreementDistributor).sendLoanAgreement(loanAgreement, false);
|
||||
}
|
||||
}
|
||||
5
loan-agreement/src/test/resources/application.yaml
Normal file
5
loan-agreement/src/test/resources/application.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
spring.datasource.url: jdbc:h2:file:./camunda-h2-database
|
||||
|
||||
camunda.bpm.admin-user:
|
||||
id: admin
|
||||
password: pw
|
||||
22
loan-agreement/src/test/resources/camunda.cfg.xml
Normal file
22
loan-agreement/src/test/resources/camunda.cfg.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="processEngineConfiguration" class="org.camunda.bpm.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
|
||||
|
||||
<property name="jdbcUrl" value="jdbc:h2:mem:camunda;DB_CLOSE_DELAY=1000" />
|
||||
<property name="jdbcDriver" value="org.h2.Driver" />
|
||||
<property name="jdbcUsername" value="sa" />
|
||||
<property name="jdbcPassword" value="" />
|
||||
|
||||
<!-- Database configurations -->
|
||||
<property name="databaseSchemaUpdate" value="true" />
|
||||
|
||||
<!-- job executor configurations -->
|
||||
<property name="jobExecutorActivate" value="false" />
|
||||
|
||||
<property name="history" value="full" />
|
||||
</bean>
|
||||
</beans>
|
||||
63
loan-agreement/src/test/resources/logback-test.xml
Normal file
63
loan-agreement/src/test/resources/logback-test.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- encoders are assigned the type
|
||||
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.apache.ibatis" level="info" />
|
||||
<!--
|
||||
<logger name="org.apache.ibatis" level="DEBUG"/>
|
||||
-->
|
||||
|
||||
<logger name="javax.activation" level="info" />
|
||||
|
||||
<logger name="org.springframework" level="info" />
|
||||
|
||||
<logger name="org.camunda" level="info" />
|
||||
<!--
|
||||
<logger name="org.camunda" level="DEBUG"/>
|
||||
-->
|
||||
|
||||
<logger name="org.camunda.bpm.engine.test" level="debug" />
|
||||
|
||||
<!--
|
||||
<logger name="org.camunda.bpm.engine.bpmn.parser" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.bpmn.behavior" level="debug" />
|
||||
|
||||
<logger name="org.camunda.bpm.engine.cmmn.transformer" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.cmmn.behavior" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.cmmn.operation" level="debug" />
|
||||
|
||||
<logger name="org.camunda.bpm.engine.cmd" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.persistence" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.persistence.entity" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.history.event" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.batch.history" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.batch" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.history" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.cmmn.entity.repository" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.cmmn.entity.runtime" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.impl.dmn.entity.repository" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.tx" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.cfg" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.jobexecutor" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.context" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.core" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.pvm" level="debug" />
|
||||
|
||||
<logger name="org.camunda.bpm.engine.metrics" level="debug" />
|
||||
<logger name="org.camunda.bpm.engine.util" level="debug" />
|
||||
|
||||
<logger name="org.camunda.bpm.application" level="debug" />
|
||||
<logger name="org.camunda.bpm.container" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="debug">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user