Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
target
*.releaseBackup
release.properties


### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
*.log

### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.
55 changes: 55 additions & 0 deletions ms-anti-fraud/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?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>
<parent>
<groupId>pe.interbank</groupId>
<artifactId>java-code-challenge</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>ms-anti-fraud</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.3</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>pe.interbank</groupId>
<artifactId>utils</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

</project>
11 changes: 11 additions & 0 deletions ms-anti-fraud/src/main/java/pe/interbank/AntifraudApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pe.interbank;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AntifraudApplication {
public static void main(String[] args) {
SpringApplication.run(AntifraudApplication.class, args);
}
}
35 changes: 35 additions & 0 deletions ms-anti-fraud/src/main/java/pe/interbank/config/KafkaConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package pe.interbank.config;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class KafkaConfig {

@Value("${spring.kafka.bootstrap-servers}")
private String bootstrapServers;

@Bean
public ProducerFactory<String, String> producerFactory() {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return new DefaultKafkaProducerFactory<>(configProps);
}

@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package pe.interbank.kafka;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.KafkaListener;
import pe.interbank.model.Transaction;
import pe.interbank.service.AntiFraudService;
import pe.interbank.util.JsonUtils;

import static pe.interbank.util.Contants.GROUP_ID_INTERBANK;
import static pe.interbank.util.Contants.TOPIC_TRANSACTION_CREATED;

@Configuration
public class ValidateTransactionConsumer {

private static final Logger logger = org.slf4j.LoggerFactory.getLogger(ValidateTransactionConsumer.class);

@Autowired
private AntiFraudService antiFraudService;

private final JsonUtils jsonUtils;

public ValidateTransactionConsumer(JsonUtils jsonUtils) {
this.jsonUtils = jsonUtils;
}

@KafkaListener(topics = TOPIC_TRANSACTION_CREATED, groupId = GROUP_ID_INTERBANK)
public void consumeTransaction(String message) {
logger.info("Consumed message: {}", message);
antiFraudService.validateTransaction(jsonUtils.fromJson(message, Transaction.class)).subscribe();
}
}
16 changes: 16 additions & 0 deletions ms-anti-fraud/src/main/java/pe/interbank/model/Transaction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package pe.interbank.model;

import lombok.Data;

import java.util.Date;

@Data
public class Transaction {

private String accountExternalId;
private int tranferTypeId;
private Double value;
private String status;
private Date createdAt;
private Date updatedAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package pe.interbank.service;

import pe.interbank.model.Transaction;
import reactor.core.publisher.Mono;

public interface AntiFraudService {
Mono<Void> validateTransaction(Transaction transaction);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package pe.interbank.service.impl;

import org.slf4j.Logger;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import pe.interbank.model.Transaction;
import pe.interbank.service.AntiFraudService;
import pe.interbank.util.JsonUtils;
import pe.interbank.util.StatusTransaction;
import reactor.core.publisher.Mono;

import static pe.interbank.util.Contants.MAX_AMOUNT;
import static pe.interbank.util.Contants.TOPIC_TRANSACTION_VALIDATED;

@Service
public class AntiFraudServiceImpl implements AntiFraudService {

private static final Logger logger = org.slf4j.LoggerFactory.getLogger(AntiFraudServiceImpl.class);

private final KafkaTemplate<String, String> kafkaTemplate;
private final JsonUtils jsonUtils;

public AntiFraudServiceImpl(KafkaTemplate<String, String> kafkaTemplate, JsonUtils jsonUtils) {
this.kafkaTemplate = kafkaTemplate;
this.jsonUtils = jsonUtils;
}

@Override
public Mono<Void> validateTransaction(Transaction transaction) {
logger.info("Validating transaction: {}", transaction);

updateTransactionStatus(transaction);

String transactionValidated = jsonUtils.toJson(transaction);

return Mono.fromFuture(kafkaTemplate.send(TOPIC_TRANSACTION_VALIDATED, transactionValidated))
.doOnSuccess(s -> logger.info("Transaction VALIDATED sent to kafka: {}", transactionValidated))
.then();
}

private void updateTransactionStatus(Transaction transaction) {
if (transaction.getValue() > MAX_AMOUNT) {
transaction.setStatus(StatusTransaction.RECHAZADO.getDescription());
} else {
transaction.setStatus(StatusTransaction.APROBADO.getDescription());
}
}
}
30 changes: 30 additions & 0 deletions ms-anti-fraud/src/main/java/pe/interbank/util/JsonUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package pe.interbank.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

@Component
public class JsonUtils {
private final ObjectMapper objectMapper;

public JsonUtils(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}

public String toJson(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException("Error converting object to JSON", e);
}
}

public <T> T fromJson(String json, Class<T> clazz) {
try {
return objectMapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException("Error parsing JSON", e);
}
}
}
8 changes: 8 additions & 0 deletions ms-anti-fraud/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
server:
port: 7070
# Kafka
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
retries: 1
71 changes: 71 additions & 0 deletions ms-transaction/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?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>
<parent>
<groupId>pe.interbank</groupId>
<artifactId>java-code-challenge</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>ms-transaction</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>pe.interbank</groupId>
<artifactId>utils</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

</dependencies>

<build>

</build>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pe.interbank;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TransactionApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionApplication.class, args);
}
}
Loading