diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b24d71e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,50 @@
+# These are some examples of commonly ignored file patterns.
+# You should customize this list as applicable to your project.
+# Learn more about .gitignore:
+# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
+
+# Node artifact files
+node_modules/
+dist/
+
+# Compiled Java class files
+*.class
+
+# Compiled Python bytecode
+*.py[cod]
+
+# Log files
+*.log
+
+# Package files
+*.jar
+
+# Maven
+target/
+dist/
+
+# JetBrains IDE
+.idea/
+
+# Unit test reports
+TEST*.xml
+
+# Generated by MacOS
+.DS_Store
+
+# Generated by Windows
+Thumbs.db
+
+# Applications
+*.app
+*.exe
+*.war
+
+# Large media files
+*.mp4
+*.tiff
+*.avi
+*.flv
+*.mov
+*.wmv
+
diff --git a/java-code-challenge.iml b/java-code-challenge.iml
new file mode 100644
index 0000000..0c3b6d5
--- /dev/null
+++ b/java-code-challenge.iml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a16280d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.3.1
+
+
+ org.antifraude
+ challenge
+ 1.0-SNAPSHOT
+ antiFraud
+
+ 17
+ 17
+ 17
+ UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-r2dbc
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.postgresql
+ r2dbc-postgresql
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ io.r2dbc
+ r2dbc-pool
+
+
+ org.springframework.kafka
+ spring-kafka
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/antifraude/AntiFraudApplication.java b/src/main/java/org/antifraude/AntiFraudApplication.java
new file mode 100644
index 0000000..e3449b2
--- /dev/null
+++ b/src/main/java/org/antifraude/AntiFraudApplication.java
@@ -0,0 +1,13 @@
+package org.antifraude;
+
+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);
+ }
+
+}
diff --git a/src/main/java/org/antifraude/adapters/config/KafkaConsumerConfig.java b/src/main/java/org/antifraude/adapters/config/KafkaConsumerConfig.java
new file mode 100644
index 0000000..5c05711
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/config/KafkaConsumerConfig.java
@@ -0,0 +1,37 @@
+package org.antifraude.adapters.config;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class KafkaConsumerConfig {
+
+ @Bean
+ public ConsumerFactory consumerFactory() {
+ Map configProps = new HashMap<>();
+ configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "antifraude");
+ configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+ configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+// configProps.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,true);
+// configProps.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "100");
+// configProps.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "15000");
+ return new DefaultKafkaConsumerFactory<>(configProps);
+ }
+
+ @Bean
+ public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() {
+ ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>();
+ factory.setConsumerFactory(consumerFactory());
+ return factory;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/antifraude/adapters/config/KafkaProducerConfig.java b/src/main/java/org/antifraude/adapters/config/KafkaProducerConfig.java
new file mode 100644
index 0000000..5b0c10e
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/config/KafkaProducerConfig.java
@@ -0,0 +1,33 @@
+package org.antifraude.adapters.config;
+
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.common.serialization.StringSerializer;
+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 KafkaProducerConfig {
+ @Bean
+ public ProducerFactory producerFactory() {
+ Map configProps = new HashMap<>();
+ configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ configProps.put(ProducerConfig.RETRIES_CONFIG, 0);
+ configProps.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
+ configProps.put(ProducerConfig.LINGER_MS_CONFIG,1);
+ configProps.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
+ 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());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/antifraude/adapters/in/rest/FinancialTransactionController.java b/src/main/java/org/antifraude/adapters/in/rest/FinancialTransactionController.java
new file mode 100644
index 0000000..b235eb4
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/in/rest/FinancialTransactionController.java
@@ -0,0 +1,47 @@
+package org.antifraude.adapters.in.rest;
+
+import org.antifraude.ports.in.FinancialTransactionUseCase;
+import org.antifraude.ports.in.KafkaUseCase;
+import org.antifraude.domain.dto.FinancialTransactionDTO;
+import org.antifraude.domain.model.FinancialTransaction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Mono;
+
+import java.util.Objects;
+
+
+@RestController
+@RequestMapping("/api/financial-transaction")
+public class FinancialTransactionController {
+
+ private static final Logger logger = LoggerFactory.getLogger(FinancialTransactionController.class.getName());
+ private final FinancialTransactionUseCase financialTransactionUseCase;
+ private final KafkaUseCase kafkaUseCase;
+
+ public FinancialTransactionController(FinancialTransactionUseCase financialTransactionUseCase, KafkaUseCase kafkaUseCase) {
+ this.financialTransactionUseCase = financialTransactionUseCase;
+ this.kafkaUseCase = kafkaUseCase;
+ }
+
+ @PostMapping
+ public Mono> create(@RequestBody FinancialTransaction financialTransaction) {
+ return financialTransactionUseCase.createFinancialTransaction(financialTransaction)
+ .map(createdFinancial -> new ResponseEntity<>(createdFinancial, HttpStatus.CREATED))
+ .doOnSuccess(createdFinancial ->
+ kafkaUseCase.sendMessage("antifraude-topic"
+ , String.valueOf(Objects.requireNonNull(createdFinancial.getBody()).getId())));
+ }
+
+ @GetMapping(value = "/{id}")
+ public Mono> findID(@PathVariable("id") Long financialTransactionId) {
+ logger.info("FinancialTransactionController findID {}", financialTransactionId);
+ return financialTransactionUseCase.findFinancialTransactionByID(financialTransactionId)
+ .map(createdFinancial -> new ResponseEntity<>(createdFinancial, HttpStatus.OK))
+ .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
+ }
+
+}
diff --git a/src/main/java/org/antifraude/adapters/in/rest/MessageConsumer.java b/src/main/java/org/antifraude/adapters/in/rest/MessageConsumer.java
new file mode 100644
index 0000000..945fdaf
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/in/rest/MessageConsumer.java
@@ -0,0 +1,21 @@
+package org.antifraude.adapters.in.rest;
+
+import org.antifraude.ports.in.FinancialTransactionUseCase;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class MessageConsumer {
+
+ private final FinancialTransactionUseCase financialTransactionUseCase;
+
+ @KafkaListener(topics = "antifraude-topic", groupId = "antifraude")
+ public Mono listen(String message) {
+ return financialTransactionUseCase.updateFinancialTransactionByID(Long.valueOf(message));
+ }
+}
diff --git a/src/main/java/org/antifraude/adapters/out/persistence/FinancialTransactionAdapter.java b/src/main/java/org/antifraude/adapters/out/persistence/FinancialTransactionAdapter.java
new file mode 100644
index 0000000..290bad9
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/out/persistence/FinancialTransactionAdapter.java
@@ -0,0 +1,58 @@
+package org.antifraude.adapters.out.persistence;
+
+import org.antifraude.ports.out.LoadFinancialTransactionPort;
+import org.antifraude.domain.dto.FinancialTransactionDTO;
+import org.antifraude.domain.model.FinancialTransaction;
+import org.antifraude.domain.model.StatusTransfer;
+import org.antifraude.domain.model.TransferType;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.util.UUID;
+
+@Slf4j
+@Component
+public class FinancialTransactionAdapter implements LoadFinancialTransactionPort {
+
+ private final FinancialTransactionRepository financialTransactionRepository;
+
+ public FinancialTransactionAdapter(FinancialTransactionRepository financialTransactionRepository) {
+ this.financialTransactionRepository = financialTransactionRepository;
+ }
+
+ @Override
+ public Mono save(FinancialTransaction financialTransaction) {
+ financialTransaction.setTransactionExternalId(UUID.randomUUID());
+ financialTransaction.setTransactionStatusId(StatusTransfer.PENDING.getId());
+ return financialTransactionRepository.save(financialTransaction);
+ }
+
+ @Override
+ public Mono findByID(Long id) {
+ return financialTransactionRepository.findById(id)
+ .map(ft -> FinancialTransactionDTO.builder()
+ .transactionExternalId(ft.getTransactionExternalId())
+ .value(ft.getValue())
+ .createdAt(ft.getCreatedAt())
+ .transactionType(FinancialTransactionDTO.TransactionType.of(
+ TransferType.getValueByID(ft.getTransferTypeId())))
+ .transactionStatus(FinancialTransactionDTO.TransactionStatus
+ .of(StatusTransfer.getValueByID(ft.getTransactionStatusId())))
+ .build());
+
+
+ }
+
+ @Override
+ public Mono update(Long id) {
+ return financialTransactionRepository.findById(id).flatMap(financialTransaction -> {
+ if (financialTransaction.getValue() > 1000) {
+ financialTransaction.setTransactionStatusId(StatusTransfer.REFUSED.getId());
+ } else {
+ financialTransaction.setTransactionStatusId(StatusTransfer.APPROVED.getId());
+ }
+ return financialTransactionRepository.save(financialTransaction);
+ }).then();
+ }
+}
diff --git a/src/main/java/org/antifraude/adapters/out/persistence/FinancialTransactionRepository.java b/src/main/java/org/antifraude/adapters/out/persistence/FinancialTransactionRepository.java
new file mode 100644
index 0000000..e1db65f
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/out/persistence/FinancialTransactionRepository.java
@@ -0,0 +1,10 @@
+package org.antifraude.adapters.out.persistence;
+
+import org.antifraude.domain.model.FinancialTransaction;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface FinancialTransactionRepository extends ReactiveCrudRepository {
+
+}
diff --git a/src/main/java/org/antifraude/adapters/out/persistence/KafkaAdapter.java b/src/main/java/org/antifraude/adapters/out/persistence/KafkaAdapter.java
new file mode 100644
index 0000000..b4ab5a0
--- /dev/null
+++ b/src/main/java/org/antifraude/adapters/out/persistence/KafkaAdapter.java
@@ -0,0 +1,21 @@
+package org.antifraude.adapters.out.persistence;
+
+import org.antifraude.ports.out.LoadKafkaPort;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class KafkaAdapter implements LoadKafkaPort {
+
+ private KafkaTemplate kafkaTemplate;
+
+ @Override
+ public void send(String topic, String message) {
+ log.info("Sending message to topic {}:{}", topic, message);
+ kafkaTemplate.send(topic, message);
+ }
+}
diff --git a/src/main/java/org/antifraude/application/FinancialTransactionService.java b/src/main/java/org/antifraude/application/FinancialTransactionService.java
new file mode 100644
index 0000000..93d05d8
--- /dev/null
+++ b/src/main/java/org/antifraude/application/FinancialTransactionService.java
@@ -0,0 +1,37 @@
+package org.antifraude.application;
+
+import org.antifraude.ports.in.FinancialTransactionUseCase;
+import org.antifraude.ports.out.LoadFinancialTransactionPort;
+import org.antifraude.domain.dto.FinancialTransactionDTO;
+import org.antifraude.domain.model.FinancialTransaction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+@Slf4j
+@Service
+public class FinancialTransactionService implements FinancialTransactionUseCase {
+
+ private final LoadFinancialTransactionPort loadFinancialTransactionPort;
+
+ public FinancialTransactionService(LoadFinancialTransactionPort loadFinancialTransactionPort) {
+ this.loadFinancialTransactionPort = loadFinancialTransactionPort;
+ }
+
+ @Override
+ public Mono createFinancialTransaction(FinancialTransaction financialTransaction) {
+ return loadFinancialTransactionPort.save(financialTransaction);
+ }
+
+ @Override
+ public Mono findFinancialTransactionByID(Long id) {
+ return loadFinancialTransactionPort.findByID(id);
+ }
+
+ @Override
+ public Mono updateFinancialTransactionByID(Long id) {
+ return loadFinancialTransactionPort.update(id);
+ }
+
+
+}
diff --git a/src/main/java/org/antifraude/application/KafkaService.java b/src/main/java/org/antifraude/application/KafkaService.java
new file mode 100644
index 0000000..7a26aad
--- /dev/null
+++ b/src/main/java/org/antifraude/application/KafkaService.java
@@ -0,0 +1,22 @@
+package org.antifraude.application;
+
+import org.antifraude.ports.in.KafkaUseCase;
+import org.antifraude.ports.out.LoadKafkaPort;
+import org.springframework.stereotype.Service;
+
+
+@Service
+public class KafkaService implements KafkaUseCase {
+
+
+ private final LoadKafkaPort loadKafkaPort;
+
+ public KafkaService(LoadKafkaPort loadKafkaPort) {
+ this.loadKafkaPort = loadKafkaPort;
+ }
+
+ @Override
+ public void sendMessage(String topic, String message) {
+ loadKafkaPort.send(topic, message);
+ }
+}
diff --git a/src/main/java/org/antifraude/domain/dto/FinancialTransactionDTO.java b/src/main/java/org/antifraude/domain/dto/FinancialTransactionDTO.java
new file mode 100644
index 0000000..5837de8
--- /dev/null
+++ b/src/main/java/org/antifraude/domain/dto/FinancialTransactionDTO.java
@@ -0,0 +1,48 @@
+package org.antifraude.domain.dto;
+
+import lombok.*;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class FinancialTransactionDTO {
+
+ private UUID transactionExternalId;
+ private TransactionType transactionType;
+ private TransactionStatus transactionStatus;
+ private double value;
+ private LocalDateTime createdAt;
+
+ @Setter
+ @Getter
+ @AllArgsConstructor(access = AccessLevel.PRIVATE)
+ public static class TransactionType {
+ private String name;
+
+ public static TransactionType of(String name) {
+ return new TransactionType(name);
+ }
+ }
+
+ @Setter
+ @Getter
+ @AllArgsConstructor(access = AccessLevel.PRIVATE)
+ public static class TransactionStatus {
+ private String name;
+
+ public static TransactionStatus of(String name) {
+ return new TransactionStatus(name);
+ }
+
+ }
+
+}
+
+
+
+
diff --git a/src/main/java/org/antifraude/domain/model/FinancialTransaction.java b/src/main/java/org/antifraude/domain/model/FinancialTransaction.java
new file mode 100644
index 0000000..34523f3
--- /dev/null
+++ b/src/main/java/org/antifraude/domain/model/FinancialTransaction.java
@@ -0,0 +1,25 @@
+package org.antifraude.domain.model;
+
+import lombok.*;
+import org.springframework.data.annotation.Id;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FinancialTransaction {
+ @Id
+ private Long id;
+ private String accountExternalIdDebit;
+ private String accountExternalIdCredit;
+ private int transactionStatusId;
+ private UUID transactionExternalId;
+ private LocalDateTime createdAt;
+ private int transferTypeId;
+ private int value;
+}
+
diff --git a/src/main/java/org/antifraude/domain/model/StatusTransfer.java b/src/main/java/org/antifraude/domain/model/StatusTransfer.java
new file mode 100644
index 0000000..6024e9c
--- /dev/null
+++ b/src/main/java/org/antifraude/domain/model/StatusTransfer.java
@@ -0,0 +1,26 @@
+package org.antifraude.domain.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum StatusTransfer {
+
+ PENDING(1, "pendiente"),
+ APPROVED(2, "aprobado"),
+ REFUSED(3, "rechazado");
+
+ private final int id;
+ private final String name;
+
+ public static String getValueByID(int id) {
+ for (StatusTransfer status : StatusTransfer.values()) {
+ if (status.getId() == id) {
+ return status.getName();
+ }
+ }
+ return "";
+ }
+
+}
diff --git a/src/main/java/org/antifraude/domain/model/TransferType.java b/src/main/java/org/antifraude/domain/model/TransferType.java
new file mode 100644
index 0000000..869ddc1
--- /dev/null
+++ b/src/main/java/org/antifraude/domain/model/TransferType.java
@@ -0,0 +1,25 @@
+package org.antifraude.domain.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum TransferType {
+ OWN_ACCOUNT(1, "cuenta propia"),
+ OTHER_ACCOUNT_IBK(2, "otras cuentas IBK"),
+ THIRD_PARTY_ACCOUNT(3, "cuenta de terceros");
+
+ private final int id;
+ private final String description;
+
+ public static String getValueByID(int id) {
+ for (TransferType type : TransferType.values()) {
+ if (type.getId() == id) {
+ return type.getDescription();
+ }
+ }
+ return "";
+ }
+
+}
diff --git a/src/main/java/org/antifraude/ports/in/FinancialTransactionUseCase.java b/src/main/java/org/antifraude/ports/in/FinancialTransactionUseCase.java
new file mode 100644
index 0000000..cf5e8fd
--- /dev/null
+++ b/src/main/java/org/antifraude/ports/in/FinancialTransactionUseCase.java
@@ -0,0 +1,13 @@
+package org.antifraude.ports.in;
+
+import org.antifraude.domain.dto.FinancialTransactionDTO;
+import org.antifraude.domain.model.FinancialTransaction;
+import reactor.core.publisher.Mono;
+
+public interface FinancialTransactionUseCase {
+ Mono createFinancialTransaction(FinancialTransaction financialTransaction);
+
+ Mono findFinancialTransactionByID(Long id);
+
+ Mono updateFinancialTransactionByID(Long id);
+}
diff --git a/src/main/java/org/antifraude/ports/in/KafkaUseCase.java b/src/main/java/org/antifraude/ports/in/KafkaUseCase.java
new file mode 100644
index 0000000..125267a
--- /dev/null
+++ b/src/main/java/org/antifraude/ports/in/KafkaUseCase.java
@@ -0,0 +1,5 @@
+package org.antifraude.ports.in;
+
+public interface KafkaUseCase {
+ void sendMessage(String topic, String message);
+}
diff --git a/src/main/java/org/antifraude/ports/out/LoadFinancialTransactionPort.java b/src/main/java/org/antifraude/ports/out/LoadFinancialTransactionPort.java
new file mode 100644
index 0000000..de8435b
--- /dev/null
+++ b/src/main/java/org/antifraude/ports/out/LoadFinancialTransactionPort.java
@@ -0,0 +1,13 @@
+package org.antifraude.ports.out;
+
+import org.antifraude.domain.dto.FinancialTransactionDTO;
+import org.antifraude.domain.model.FinancialTransaction;
+import reactor.core.publisher.Mono;
+
+public interface LoadFinancialTransactionPort {
+ Mono save(FinancialTransaction financialTransaction);
+
+ Mono findByID(Long id);
+
+ Mono update(Long id);
+}
diff --git a/src/main/java/org/antifraude/ports/out/LoadKafkaPort.java b/src/main/java/org/antifraude/ports/out/LoadKafkaPort.java
new file mode 100644
index 0000000..c5a2ed3
--- /dev/null
+++ b/src/main/java/org/antifraude/ports/out/LoadKafkaPort.java
@@ -0,0 +1,5 @@
+package org.antifraude.ports.out;
+
+public interface LoadKafkaPort {
+ void send(String topic, String message);
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..8350253
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,19 @@
+spring:
+ application:
+ name: antiFraud
+ r2dbc:
+ url: r2dbc:postgresql://localhost:5432/antifraudedb
+ username: postgres
+ password: postgres
+ pool:
+ enabled: true
+ kafka:
+ bootstrap-servers: localhost:9092
+ consumer:
+ group-id: antifraude
+ auto-offset-reset: earliest
+ datasource:
+ driver-class-name: org.postgresql.Driver
+ url: jdbc:postgresql://localhost:5432/antifraudedb
+ username: postgres
+ password: postgres
diff --git a/src/main/resources/db/initquery.sql b/src/main/resources/db/initquery.sql
new file mode 100644
index 0000000..027f0ad
--- /dev/null
+++ b/src/main/resources/db/initquery.sql
@@ -0,0 +1,65 @@
+-- Crear la base de datos
+
+create database antifraudedb;
+
+-- Luego seleccionar la base de datos y ejecutar las siguientes queries:
+
+-- drop table financial_transaction;
+
+CREATE TABLE financial_transaction
+(
+ id serial primary key,
+ account_external_id_debit character varying(100) NOT NULL,
+ account_external_id_credit character varying(100) NOT NULL,
+ transaction_external_id character varying(100) NOT NULL,
+ transaction_status_id smallint default 1,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ transfer_type_id smallint,
+ value smallint
+);
+
+insert
+into financial_transaction (account_external_id_debit,
+ account_external_id_credit,
+ transaction_status_id,
+ transaction_external_id,
+ transfer_type_id,
+ value)
+values ('3109aeb4-ee23-43a9-994b-3f9af5a0d00e',
+ '4995c6a9-447b-444d-a040-f356c920a2fd',
+ 1,
+ '464c5eb9-ee12-4b6c-b354-a839aa54d5f9',
+ 1,
+ 130);
+
+insert
+into financial_transaction (account_external_id_debit,
+ account_external_id_credit,
+ transaction_status_id,
+ transaction_external_id,
+ transfer_type_id,
+ value)
+values ('3119aeb4-ee23-43a9-994b-3f9af5a0d00e',
+ '4985c6a9-447b-444d-a040-f356c920a2fd',
+ 2,
+ '465c5eb9-ee12-4b6c-b354-a839aa54d5f9',
+ 2,
+ 150);
+
+insert
+into financial_transaction (account_external_id_debit,
+ account_external_id_credit,
+ transaction_status_id,
+ transaction_external_id,
+ transfer_type_id,
+ value)
+values ('3129aeb4-ee23-43a9-994b-3f9af5a0d00e',
+ '4285c6a9-447b-444d-a040-f356c920a2fd',
+ 3,
+ '435c5eb9-ee12-4b6c-b354-a839aa54d5f9',
+ 3,
+ 1001);
+
+
+select *
+from financial_transaction;