From 25e771f6889586babf1552c9f2f9c489392e704f Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Fri, 17 May 2024 11:14:31 -0500 Subject: [PATCH] reto de transacciones enviadas a fraude --- .gitignore | 33 +++++++ anti-fraud-app/pom.xml | 58 ++++++++++++ .../anti/fraud/app/AntiFraudApplication.java | 16 ++++ .../fraud/app/config/JpaConfiguration.java | 11 +++ .../anti/fraud/app/config/KafkaConfig.java | 50 ++++++++++ .../app/controller/AntiFraudController.java | 24 +++++ .../fraud/app/facade/AntiFraudFacade.java | 20 ++++ .../suscriptor/KafkaConsumerService.java | 25 +++++ .../src/main/resources/application.properties | 29 ++++++ .../src/main/resources/bootstrap.yml | 9 ++ anti-fraud-core/pom.xml | 44 +++++++++ .../fraud/core/domain/AntiFraudDetail.java | 28 ++++++ .../anti/fraud/core/domain/BaseEntity.java | 27 ++++++ .../anti/fraud/core/domain/Transaction.java | 35 +++++++ .../fraud/core/domain/TransactionStatus.java | 23 +++++ .../fraud/core/domain/TransactionType.java | 23 +++++ .../fraud/core/dto/FraudDetailRequestDto.java | 18 ++++ .../kafka/publiser/KafkaProducerService.java | 26 ++++++ .../fraud/core/mapper/AntiFraudMapper.java | 19 ++++ .../core/repository/AntiFraudRepository.java | 7 ++ .../fraud/core/service/AntiFraudService.java | 9 ++ .../core/service/AntiFraudServiceImpl.java | 67 +++++++++++++ docker-compose.yml | 2 +- pom.xml | 93 +++++++++++++++++++ 24 files changed, 695 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 anti-fraud-app/pom.xml create mode 100644 anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/AntiFraudApplication.java create mode 100644 anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/JpaConfiguration.java create mode 100644 anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/KafkaConfig.java create mode 100644 anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/controller/AntiFraudController.java create mode 100644 anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/facade/AntiFraudFacade.java create mode 100644 anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/kafka/suscriptor/KafkaConsumerService.java create mode 100644 anti-fraud-app/src/main/resources/application.properties create mode 100644 anti-fraud-app/src/main/resources/bootstrap.yml create mode 100644 anti-fraud-core/pom.xml create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/AntiFraudDetail.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/BaseEntity.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/Transaction.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionStatus.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionType.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/dto/FraudDetailRequestDto.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/kafka/publiser/KafkaProducerService.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/mapper/AntiFraudMapper.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/repository/AntiFraudRepository.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudService.java create mode 100644 anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudServiceImpl.java create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/anti-fraud-app/pom.xml b/anti-fraud-app/pom.xml new file mode 100644 index 0000000..a84653e --- /dev/null +++ b/anti-fraud-app/pom.xml @@ -0,0 +1,58 @@ + + + + java-code-challenge + com.interbank.anti.fraud + 1.0.0 + ../pom.xml + + 4.0.0 + + anti-fraud-app + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + com.interbank.anti.fraud + anti-fraud-core + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.interbank.anti.fraud.app.AntiFraudApplication + + + + org.springframework.boot + spring-boot-maven-plugin + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + + + -Xlint:all + -Xlint:-processing + + true + true + + + + + diff --git a/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/AntiFraudApplication.java b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/AntiFraudApplication.java new file mode 100644 index 0000000..b1b7abb --- /dev/null +++ b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/AntiFraudApplication.java @@ -0,0 +1,16 @@ +package com.interbank.anti.fraud.app; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication(scanBasePackages = "com.interbank.anti.fraud") +public class AntiFraudApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + new SpringApplicationBuilder(AntiFraudApplication.class) + .initializers() + .run(args); + } + +} diff --git a/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/JpaConfiguration.java b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/JpaConfiguration.java new file mode 100644 index 0000000..4827961 --- /dev/null +++ b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/JpaConfiguration.java @@ -0,0 +1,11 @@ +package com.interbank.anti.fraud.app.config; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +@EnableJpaRepositories("com.interbank.anti.fraud.core.repository") +@EntityScan("com.interbank.anti.fraud") +public class JpaConfiguration { +} diff --git a/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/KafkaConfig.java b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/KafkaConfig.java new file mode 100644 index 0000000..bf093f2 --- /dev/null +++ b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/config/KafkaConfig.java @@ -0,0 +1,50 @@ +package com.interbank.anti.fraud.app.config; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.*; + +import java.util.HashMap; +import java.util.Map; + +@EnableKafka +@Configuration +public class KafkaConfig { + + @Bean + public ProducerFactory producerFactory() { + Map configProps = new HashMap<>(); + configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + 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 kafkaTemplate() { + return new KafkaTemplate<>(producerFactory()); + } + + @Bean + public ConsumerFactory consumerFactory() { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "group-prueba-fraude"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + return new DefaultKafkaConsumerFactory<>(props); + } + + @Bean + public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory()); + return factory; + } +} diff --git a/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/controller/AntiFraudController.java b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/controller/AntiFraudController.java new file mode 100644 index 0000000..ed3e9ec --- /dev/null +++ b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/controller/AntiFraudController.java @@ -0,0 +1,24 @@ +package com.interbank.anti.fraud.app.controller; + +import com.interbank.anti.fraud.app.facade.AntiFraudFacade; +import com.interbank.anti.fraud.core.dto.FraudDetailRequestDto; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/anti-fraud") +public class AntiFraudController { + private final AntiFraudFacade antiFraudFacade; + + @PostMapping("/register") + public ResponseEntity registerOperation(@RequestBody FraudDetailRequestDto fraudDetailRequestDto) { + antiFraudFacade.registerOperation(fraudDetailRequestDto); + return new ResponseEntity<>(HttpStatus.CREATED); + } +} diff --git a/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/facade/AntiFraudFacade.java b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/facade/AntiFraudFacade.java new file mode 100644 index 0000000..2d1d3f2 --- /dev/null +++ b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/facade/AntiFraudFacade.java @@ -0,0 +1,20 @@ +package com.interbank.anti.fraud.app.facade; + +import com.interbank.anti.fraud.core.dto.FraudDetailRequestDto; +import com.interbank.anti.fraud.core.service.AntiFraudService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class AntiFraudFacade { + + private final AntiFraudService antiFraudService; + + public void registerOperation(FraudDetailRequestDto fraudDetailRequestDto) { + this.antiFraudService.registerOperation(fraudDetailRequestDto); + } + +} diff --git a/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/kafka/suscriptor/KafkaConsumerService.java b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/kafka/suscriptor/KafkaConsumerService.java new file mode 100644 index 0000000..129d1f7 --- /dev/null +++ b/anti-fraud-app/src/main/java/com/interbank/anti/fraud/app/kafka/suscriptor/KafkaConsumerService.java @@ -0,0 +1,25 @@ +package com.interbank.anti.fraud.app.kafka.suscriptor; + +import com.interbank.anti.fraud.core.service.AntiFraudService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class KafkaConsumerService { + private final AntiFraudService antiFraudService; + + @KafkaListener(topics = "fraud-topic", groupId = "group-prueba-fraude") + public void listen(String message) { + try { + log.info("[ANTI-FRAUD-KAFKA] Recived init..."); + antiFraudService.validOperation(Long.parseLong(message)); + log.info("[ANTI-FRAUD-KAFKA] Recived end"); + } catch (Exception e) { + log.error("[ANTI-FRAUD-KAFKA] message:{}, trace:{}", e.getMessage(), e); + } + } +} diff --git a/anti-fraud-app/src/main/resources/application.properties b/anti-fraud-app/src/main/resources/application.properties new file mode 100644 index 0000000..6e1174b --- /dev/null +++ b/anti-fraud-app/src/main/resources/application.properties @@ -0,0 +1,29 @@ +spring.application.name=anti-fraud +server.port=8090 +# Configuración de postgresql +spring.datasource.url=jdbc:postgresql://localhost:5432/AntiFraud +spring.datasource.username=postgres +spring.datasource.password=admin +spring.datasource.driver-class-name=org.postgresql.Driver + +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true + +# Configuración del servidor Kafka +spring.kafka.consumer.bootstrap-servers=localhost:9092 +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.enable-auto-commit=false +spring.kafka.consumer.max-poll-records=500 +spring.kafka.consumer.properties.spring.json.trusted.packages=* + +spring.kafka.listener.concurrency=5 + +# Configuración del productor Kafka +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer + +# Configuración del consumidor Kafka +spring.kafka.consumer.group-id=group-prueba-fraude +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer diff --git a/anti-fraud-app/src/main/resources/bootstrap.yml b/anti-fraud-app/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..58889c5 --- /dev/null +++ b/anti-fraud-app/src/main/resources/bootstrap.yml @@ -0,0 +1,9 @@ +server: + port: 8080 + servlet: + context-path: /anti-fraud +spring: + application: + name: anti-fraud + main: + allow-bean-definition-overriding: true \ No newline at end of file diff --git a/anti-fraud-core/pom.xml b/anti-fraud-core/pom.xml new file mode 100644 index 0000000..f7729c2 --- /dev/null +++ b/anti-fraud-core/pom.xml @@ -0,0 +1,44 @@ + + + + java-code-challenge + com.interbank.anti.fraud + 1.0.0 + + + anti-fraud-core + + + + org.mapstruct + mapstruct + 1.4.2.Final + + + 4.0.0 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.interbank.anti.fraud.app.AntiFraudApplication + + + + org.apache.maven.plugins + maven-compiler-plugin + + + -Xlint:all + -Xlint:-processing + + true + true + + + + + diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/AntiFraudDetail.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/AntiFraudDetail.java new file mode 100644 index 0000000..74a1350 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/AntiFraudDetail.java @@ -0,0 +1,28 @@ +package com.interbank.anti.fraud.core.domain; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; + +@Entity +@Getter +@Setter +public class AntiFraudDetail extends BaseEntity implements Serializable { + + private static final long serialVersionUID = 2934008372670552374L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String accountExternalIdDebit; + private String accountExternalIdCredit; + private String tranferTypeId; + private String value; + private String status; +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/BaseEntity.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/BaseEntity.java new file mode 100644 index 0000000..7a2ee72 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/BaseEntity.java @@ -0,0 +1,27 @@ +package com.interbank.anti.fraud.core.domain; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.io.Serializable; +import java.time.LocalDateTime; + +@Getter +@Setter +@ToString +@MappedSuperclass +@EntityListeners({AuditingEntityListener.class}) +public class BaseEntity implements Serializable { + private static final long serialVersionUID = -6990628184361464179L; + + @Column(name = "createdAt", updatable = false) + @CreatedDate + protected LocalDateTime createdAt; + +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/Transaction.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/Transaction.java new file mode 100644 index 0000000..db2f484 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/Transaction.java @@ -0,0 +1,35 @@ +package com.interbank.anti.fraud.core.domain; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +@Getter +@Setter +public class Transaction extends BaseEntity implements Serializable { + private static final long serialVersionUID = -2306754104177671615L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "transaction_external_debit_id", nullable = false, unique = true) + private String accountExternalIdDebit; + + @Column(name = "transaction_external_credit_id", nullable = false, unique = true) + private String accountExternalIdCredit; + + @ManyToOne + @JoinColumn(name = "transaction_type_id", nullable = false) + private TransactionType transactionType; + + @ManyToOne + @JoinColumn(name = "transaction_status_id", nullable = false) + private TransactionStatus transactionStatus; + + private String value; + +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionStatus.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionStatus.java new file mode 100644 index 0000000..5ebad60 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionStatus.java @@ -0,0 +1,23 @@ +package com.interbank.anti.fraud.core.domain; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; + +@Entity +@Getter +@Setter +public class TransactionStatus implements Serializable { + private static final long serialVersionUID = -2019964429428375411L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionType.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionType.java new file mode 100644 index 0000000..d9a618a --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/domain/TransactionType.java @@ -0,0 +1,23 @@ +package com.interbank.anti.fraud.core.domain; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; + +@Entity +@Getter +@Setter +public class TransactionType implements Serializable { + private static final long serialVersionUID = -9155383972594866250L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/dto/FraudDetailRequestDto.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/dto/FraudDetailRequestDto.java new file mode 100644 index 0000000..e9f6cb9 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/dto/FraudDetailRequestDto.java @@ -0,0 +1,18 @@ +package com.interbank.anti.fraud.core.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +@Getter +@Setter +public class FraudDetailRequestDto implements Serializable { + private static final long serialVersionUID = -2441982926762095330L; + + private String accountExternalIdDebit; + private String accountExternalIdCredit; + private Integer tranferTypeId; + private Integer value; + +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/kafka/publiser/KafkaProducerService.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/kafka/publiser/KafkaProducerService.java new file mode 100644 index 0000000..b18384f --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/kafka/publiser/KafkaProducerService.java @@ -0,0 +1,26 @@ +package com.interbank.anti.fraud.core.kafka.publiser; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class KafkaProducerService { + + @Autowired + private KafkaTemplate kafkaTemplate; + + private static final String TOPIC = "fraud-topic"; + + public void sendMessage(String message) { + try { + log.info("[ANTI-FRAUD] send Kafka init..."); + kafkaTemplate.send(TOPIC, message); + log.info("[ANTI-FRAUD] send Kafka end"); + } catch (Exception e) { + log.error("[ANTI-FRAUD-SEND] message:{}, trace:{}", e.getMessage(), e); + } + } +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/mapper/AntiFraudMapper.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/mapper/AntiFraudMapper.java new file mode 100644 index 0000000..bf3b7a3 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/mapper/AntiFraudMapper.java @@ -0,0 +1,19 @@ +package com.interbank.anti.fraud.core.mapper; + +import com.interbank.anti.fraud.core.domain.Transaction; +import com.interbank.anti.fraud.core.dto.FraudDetailRequestDto; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AntiFraudMapper { + AntiFraudMapper MAPPER = Mappers.getMapper(AntiFraudMapper.class); + + @Mapping(target = "accountExternalIdDebit", source = "accountExternalIdDebit") + @Mapping(target = "accountExternalIdCredit", source = "accountExternalIdCredit") + @Mapping(target = "transactionType.name", source = "tranferTypeId") + @Mapping(target = "transactionStatus.name", defaultValue = "PENDIENTE") + @Mapping(target = "value", source = "value") + Transaction buildToAntiFraudDetail(FraudDetailRequestDto fraudDetailRequestDto); +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/repository/AntiFraudRepository.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/repository/AntiFraudRepository.java new file mode 100644 index 0000000..41a0c31 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/repository/AntiFraudRepository.java @@ -0,0 +1,7 @@ +package com.interbank.anti.fraud.core.repository; + +import com.interbank.anti.fraud.core.domain.Transaction; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AntiFraudRepository extends JpaRepository { +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudService.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudService.java new file mode 100644 index 0000000..f46eb87 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudService.java @@ -0,0 +1,9 @@ +package com.interbank.anti.fraud.core.service; + +import com.interbank.anti.fraud.core.dto.FraudDetailRequestDto; + +public interface AntiFraudService { + void registerOperation(FraudDetailRequestDto fraudDetailRequestDto); + + void validOperation(Long id); +} diff --git a/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudServiceImpl.java b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudServiceImpl.java new file mode 100644 index 0000000..b127578 --- /dev/null +++ b/anti-fraud-core/src/main/java/com/interbank/anti/fraud/core/service/AntiFraudServiceImpl.java @@ -0,0 +1,67 @@ +package com.interbank.anti.fraud.core.service; + +import com.interbank.anti.fraud.core.domain.Transaction; +import com.interbank.anti.fraud.core.dto.FraudDetailRequestDto; +import com.interbank.anti.fraud.core.kafka.publiser.KafkaProducerService; +import com.interbank.anti.fraud.core.mapper.AntiFraudMapper; +import com.interbank.anti.fraud.core.repository.AntiFraudRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +@Slf4j +@RequiredArgsConstructor +@Service +public class AntiFraudServiceImpl implements AntiFraudService { + private static final String RECIBIDO = "RECIBIDO"; + private static final String RECHAZADO = "RECHAZADO"; + private static final String APROBADO = "APROBADO"; + private static final String VALUE_FRAUD = "1000"; + + + private final AntiFraudRepository antiFraudRepository; + private final KafkaProducerService kafkaProducerService; + + @Override + public void registerOperation(FraudDetailRequestDto fraudDetailRequestDto) { + log.info("[ANTI-FRAUD] Register init..."); + Transaction transaction = AntiFraudMapper.MAPPER.buildToAntiFraudDetail(fraudDetailRequestDto); + transaction.setCreatedAt(LocalDateTime.now()); + + Transaction transactionDetail = antiFraudRepository.save(transaction); + + kafkaProducerService.sendMessage(transactionDetail.getId().toString()); + + log.info("[ANTI-FRAUD] Register end"); + } + + @Override + public void validOperation(Long id) { + Transaction transaction = antiFraudRepository.findById(id).orElse(new Transaction()); + + updateStatus(transaction, RECIBIDO); + + log.info("[ANTI-FRAUD] validate init..."); + validFraudTransaction(transaction); + + } + + private void updateStatus(Transaction transaction, String status) { + transaction.getTransactionStatus().setName(status); + + antiFraudRepository.saveAndFlush(transaction); + } + + private void validFraudTransaction(Transaction transaction) { + if (VALUE_FRAUD.equals(transaction.getTransactionStatus().getName())) { + updateStatus(transaction, RECHAZADO); + log.info("[ANTI-FRAUD] validate end. id: {}, status: {}", transaction.getId(), RECHAZADO); + } else { + updateStatus(transaction, APROBADO); + log.info("[ANTI-FRAUD] validate end. id: {}, status: {}", transaction.getId(), APROBADO); + } + } + +} diff --git a/docker-compose.yml b/docker-compose.yml index a59bedf..b4935ee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ services: - "5432:5432" environment: - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres + - POSTGRES_PASSWORD=admin zookeeper: image: confluentinc/cp-zookeeper:5.5.3 environment: diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..814cb9a --- /dev/null +++ b/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + + com.interbank.anti.fraud + java-code-challenge + 1.0.0 + anti-fraud + Projecto para casos antifraude + pom + + + anti-fraud-core + anti-fraud-app + + + + 1.0.0 + 11 + 1.4.2.Final + + + + + + com.interbank.anti.fraud + anti-fraud-core + ${anti-fraud.version} + + + com.interbank.anti.fraud + anti-fraud-app + ${anti-fraud.version} + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + provided + + + + + + + org.springframework.kafka + spring-kafka + + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.postgresql + postgresql + 42.3.1 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + +