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
124 changes: 31 additions & 93 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,104 +1,42 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# .gitignore para Java + Spring Boot

# Dependency directories
node_modules/
jspm_packages/
```
# Compiled files
*.class

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo
# Logs
*.log

# Optional npm cache directory
.npm
# Maven
target/

# Optional eslint cache
.eslintcache
# Gradle
.gradle/
build/

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# IntelliJ
.idea/
*.iml
out/

# Optional REPL history
.node_repl_history
# Eclipse
.project
.classpath
.settings/
bin/

# Output of 'npm pack'
*.tgz
# VSCode
.vscode/

# Yarn Integrity file
.yarn-integrity
# OS files
.DS_Store
Thumbs.db

# dotenv environment variables file
# Env files
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port
# Temp
*.tmp
*.swp
*~
```
142 changes: 86 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,82 +1,112 @@
# Yape Code Challenge :rocket:
# Yape Transaction Service

Our code challenge will let you marvel us with your Jedi coding skills :smile:.
## Overview

Don't forget that the proper way to submit your work is to fork the repo and create a PR :wink: ... have fun !!
Event-driven microservices system for processing financial transactions with anti-fraud validation using Apache Kafka.

- [Problem](#problem)
- [Tech Stack](#tech_stack)
- [Send us your challenge](#send_us_your_challenge)
## Architecture

# Problem
The project consists of two microservices:

Every time a financial transaction is created it must be validated by our anti-fraud microservice and then the same service sends a message back to update the transaction status.
For now, we have only three transaction statuses:
**transaction-service** — Core service built with Onion Architecture (DDD). Handles transaction creation, persistence, and status updates.

<ol>
<li>pending</li>
<li>approved</li>
<li>rejected</li>
</ol>
**anti-fraud-service** — Lightweight worker service that consumes transaction events, validates fraud rules, and publishes the result.

Every transaction with a value greater than 1000 should be rejected.
### Event Flow

```mermaid
flowchart LR
Transaction -- Save Transaction with pending Status --> transactionDatabase[(Database)]
Transaction --Send transaction Created event--> Anti-Fraud
Anti-Fraud -- Send transaction Status Approved event--> Transaction
Anti-Fraud -- Send transaction Status Rejected event--> Transaction
Transaction -- Update transaction Status event--> transactionDatabase[(Database)]
```
1. Client creates a transaction via REST API
2. Transaction is saved in PostgreSQL with status PENDING
3. transaction-service publishes event to Kafka topic "transaction.created"
4. anti-fraud-service consumes the event and validates:
- Amount <= 1000 → APPROVED
- Amount > 1000 → REJECTED
5. anti-fraud-service publishes result to Kafka topic "transaction.status"
6. transaction-service consumes the event and updates the status in the database
```

# Tech Stack
### Project Structure

<ol>
<li>Node. You can use any framework you want (i.e. Nestjs with an ORM like TypeOrm or Prisma) </li>
<li>Any database</li>
<li>Kafka</li>
</ol>
```
transaction-service/ → Onion Architecture (DDD)
├── domain/ → Entities, enums, repository interfaces
├── application/ → Use cases, ports (interfaces), DTOs
└── infrastructure/ → JPA, Kafka producers/consumers
└── Presentation Layer/ → REST API, Spring controllers, exceptions handlers

anti-fraud-service/ → Simple structure
├── models/ → TransactionEvent, TransactionStatus enum
└── consumers/ → Kafka consumer + producer logic
```

We do provide a `Dockerfile` to help you get started with a dev environment.
## Tech Stack

You must have two resources:
- Java 21
- Spring Boot 4.x
- Apache Kafka (Confluent 5.5.3)
- PostgreSQL 14
- MapStruct
- Lombok
- Springdoc OpenAPI (Swagger)

1. Resource to create a transaction that must containt:
## Prerequisites

```json
{
"accountExternalIdDebit": "Guid",
"accountExternalIdCredit": "Guid",
"tranferTypeId": 1,
"value": 120
}
- Java 21
- Docker & Docker Compose
- Maven

## Getting Started

### 1. Start infrastructure

```bash
docker-compose up -d
```

2. Resource to retrieve a transaction
This starts PostgreSQL, Zookeeper, and Kafka.

### 2. Run transaction-service

```bash
cd transaction-service
mvn spring-boot:run
```

Runs on `http://localhost:8080`

### 3. Run anti-fraud-service

```bash
cd anti-fraud-service
mvn spring-boot:run
```

Runs as a Kafka worker (no HTTP server).

## API Documentation

Swagger UI available at: `http://localhost:8080/`

### Endpoints

**POST** `/transactions` — Create a new transaction

```json
{
"transactionExternalId": "Guid",
"transactionType": {
"name": ""
},
"transactionStatus": {
"name": ""
},
"value": 120,
"createdAt": "Date"
"accountExternalIdDebit": "uuid",
"accountExternalIdCredit": "uuid",
"transferTypeId": 1,
"value": 500
}
```

## Optional

You can use any approach to store transaction data but you should consider that we may deal with high volume scenarios where we have a huge amount of writes and reads for the same data at the same time. How would you tackle this requirement?

You can use Graphql;
**GET** `/transactions/{id}` — Get transaction by external ID

# Send us your challenge
Returns transaction with current status (PENDING, APPROVED, or REJECTED).

When you finish your challenge, after forking a repository, you **must** open a pull request to our repository. There are no limitations to the implementation, you can follow the programming paradigm, modularization, and style that you feel is the most appropriate solution.
## Kafka Topics

If you have any questions, please let us know.
| Topic | Producer | Consumer | Description |
|---|---|---|---|
| `transaction.created` | transaction-service | anti-fraud-service | New transaction event |
| `transaction.status` | anti-fraud-service | transaction-service | Fraud validation result |
2 changes: 2 additions & 0 deletions anti-fraud-service/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf
33 changes: 33 additions & 0 deletions anti-fraud-service/.gitignore
Original file line number Diff line number Diff line change
@@ -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/
3 changes: 3 additions & 0 deletions anti-fraud-service/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
Loading