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
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/app-nodejs-codechallenge.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 108 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Yape Code Challenge :rocket:

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

Don't forget that the proper way to submit your work is to fork the repo and create a PR :wink: ... have fun !!

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

---

# Problem

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.
Expand All @@ -16,7 +18,7 @@ For now, we have only three transaction statuses:
<ol>
<li>pending</li>
<li>approved</li>
<li>rejected</li>
<li>rejected</li>
</ol>

Every transaction with a value greater than 1000 should be rejected.
Expand All @@ -30,50 +32,131 @@ Every transaction with a value greater than 1000 should be rejected.
Transaction -- Update transaction Status event--> transactionDatabase[(Database)]
```

---

# Tech Stack

<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>
<li>Java 21 con Spring Boot 4.x + WebFlux (Reactivo)</li>
<li>PostgreSQL 17 como base de datos</li>
<li>Kafka para comunicación asíncrona entre microservicios</li>
<li>Redis como capa de caché para alto volumen</li>
<li>R2DBC para conexión reactiva a PostgreSQL</li>
</ol>

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

### Prerrequisitos

- Docker y Docker Compose instalados
- Java 21 (solo para desarrollo local)
- Maven 3.9+ (solo para desarrollo local)

### Levanta todo con un solo comando

```bash
docker-compose up --build
```

Microservicios disponibles:

You must have two resources:
| Servicio | URL / Puerto |
|----------------------|---------------------------|
| Transaction API | http://localhost:8080 |
| PostgreSQL | localhost:5432 |
| Kafka | localhost:9092 |
| Redis | localhost:6379 |

1. Resource to create a transaction that must containt:
---

# APIs Documentation

## Crear una transacción

```http
POST /v1/transactions
Content-Type: application/json
```
## Probar

```bash
curl --location 'http://localhost:8080/v1/transactions' \
--header 'Content-Type: application/json' \
--data '{
"accountExternalIdDebit": "d62a2a4c-65ac-4c61-aacf-59ab55e7c970",
"accountExternalIdCredit": "d62a2a4c-65ac-4c61-aacf-59ab55e7c971",
"transferTypeId": 1,
"value": 100.10
}'

**Response `201 Created`:**
```json
{
"accountExternalIdDebit": "Guid",
"accountExternalIdCredit": "Guid",
"tranferTypeId": 1,
"value": 120
"transactionAmount": 100.10,
"transactionExternalId": "578fa71b-f0f1-490b-8a1c-0645fadd2ba4",
"transactionId": "498329fd-ee36-4525-8b71-f09e56b74a8b"
}
```

2. Resource to retrieve a transaction
---

## Consultar una transacción

```http
GET /v1/transactions/{transactionExternalId}
```
curl --location 'http://localhost:8080/v1/transactions/578fa71b-f0f1-490b-8a1c-0645fadd2ba4'

**Response `200 OK`:**
```json
{
"transactionExternalId": "Guid",
"transactionType": {
"name": ""
},
"transactionStatus": {
"name": ""
},
"value": 120,
"createdAt": "Date"
"transactionExternalId": "578fa71b-f0f1-490b-8a1c-0645fadd2ba4",
"transactionType": {
"name": "Debit"
},
"transactionStatus": {
"name": "Approved"
},
"value": 100.10,
"createdAt": "2026-02-21 16:38:46"
}
```

## Optional
---

# Kafka Events

| Topic | Productor | Consumidor |
|--------------------------------|-----------------------|-----------------------|
| `transaction.created` | Transaction Service | Anti-Fraud Service |
| `transaction.status.updated` | Anti-Fraud Service | Transaction Service |

### `transaction.created`
```json
{
"transactionExternalId": "578fa71b-f0f1-490b-8a1c-0645fadd2ba4",
"value": 120
}
```

### `transaction.status.updated`
```json
{
"transactionExternalId": "578fa71b-f0f1-490b-8a1c-0645fadd2ba4",
"status": "Approved"
}
```

---

# Optional Solution

Para manejar alto volumen de lecturas y escrituras simultáneas se implementó una estrategia de **Cache-Aside con Redis**:

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?
### ¿Cómo funciona?

You can use Graphql;
Cuando crea la transacción, en simultane ejecuta el evento para kafka y guarda los datos de la transaccion en cache, cuando alguien quiere consultar el endoint del detalle de la transaccion, irá primero a cache y ya no a la base de datos, si no existe, irá a la base de datos. Esto en un escensario de alto volumen, beneficia en cuanto tiempos de respuesta. Una vez que el microservicio antifraude, valida la regla para aprobar o rechazar, envia al topico para que el microservicio de transaction actualice el estado y ademas refresca el cache con el estado tambien.
---

# Send us your challenge

Expand Down
2 changes: 2 additions & 0 deletions antifraud-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 antifraud-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 antifraud-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
10 changes: 10 additions & 0 deletions antifraud-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -Dmaven.test.skip=true

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Loading