Skip to content

Eduardo Quispe - Transaction challange #498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
Binary file added .DS_Store
Binary file not shown.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist/
node_modules/
.env
.vscode/
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CLIENT_GATEWAY_PORT=3000
KAFKA_BROKER=kafka:29092
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh text eol=lf
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ dist

# TernJS port file
.tern-port

# Prisma
.prisma/
generated/
82 changes: 82 additions & 0 deletions README.challande.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Yape Code Challenge :rocket:

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.
For now, we have only three transaction statuses:

<ol>
<li>pending</li>
<li>approved</li>
<li>rejected</li>
</ol>

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

```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)]
```

# 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>
</ol>

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

You must have two resources:

1. Resource to create a transaction that must containt:

```json
{
"accountExternalIdDebit": "Guid",
"accountExternalIdCredit": "Guid",
"tranferTypeId": 1,
"value": 120
}
```

2. Resource to retrieve a transaction

```json
{
"transactionExternalId": "Guid",
"transactionType": {
"name": ""
},
"transactionStatus": {
"name": ""
},
"value": 120,
"createdAt": "Date"
}
```

## 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;

# Send us your challenge

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.

If you have any questions, please let us know.
212 changes: 171 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,160 @@
# Yape Code Challenge :rocket:
# Proyecto: Microservicio de Transacciones Financieras con Validación Antifraude y Kafka

## Descripción

Este proyecto implementa un sistema de transacciones financieras distribuidas con validación antifraude, utilizando el patrón **CQRS, EVENT SOURCING** con Kafka como un event store (por motivos de la prueba). La implementación de estos patrones es por el requerimiento de que pueda estar optimizado para un tráfico alto. Los microservicios están desacoplados y se comunican mediante **Kafka** para garantizar la consistencia de las transacciones y el manejo eficiente de errores.

El sistema consta de varios microservicios que colaboran para crear, validar y actualizar transacciones:

- **ms-transaction-cm**: Crea las transacciones y actualiza el estado en la BD de escritura.
- **ms-anti-fraud**: Valida las transacciones (rechaza aquellas con un valor mayor a 1000).
- **ms-transaction-qr**: Permite consultar el estado de las transacciones.
- **api-gateway**: Permite tener un único punto de acceso y derivar las solicitudes a los microservicios correspondientes.
- **Kafka**: Sistema de mensajería para la comunicación entre los microservicios.

## Tecnologías Usadas

- **NestJS**: Framework de Node.js para la construcción de microservicios.
- **Kafka**: Sistema de mensajería para la comunicación asíncrona entre microservicios.
- **PostgreSQL**: Base de datos para almacenar las transacciones.
- **Prisma**: ORM para interactuar con la base de datos en NestJS.
- **Docker**: Para crear un entorno de desarrollo aislado.

## Arquitectura Big Picture

![App Screenshot](https://i.ibb.co/YT28dB4G/Diagrama-sin-ti-tulo.jpg)

1. La aplicación solicita al backend crear una nueva transacción, el API-GATEWAY redirige al microservicio correspondiente.
2. Mediante Kafka, el API-GATEWAY redigire la petición al microservicio ms-transaction-cm.
3. El microservicio crea la transacción en la base de datos "transaction_command_db" y devuelve al usuario la resuesta con los datos de la transacción,
4. 4.1. 4.2. A su vez, el microservicio ms-transaction-cm emite un evento asíncrono de la creación de la transacción al microservicio ms-transaction-qr y ms-anti-fraud, para que puedan actualizar la base de datos de lectura "transaction_query_db" y validar la transacción correspondientemente.
5. El microservicio ms-anti-fraud luego de valida asincronamente la transacción, notifica al ms-transaction-cm el resultado.
6. El microservicio ms-transaction-cm actualiza la base de datos "transaction_command_db" y a su vez emite un evento asíncrono al ms-transaction-qr para que actualize los datos de la transacción.
7. Con el ID de la transacción el app podrá obtener los datos de la transacción en cualquier momento.

## Requisitos

1. **Docker** y **Docker Compose** para la configuración de los microservicios, Kafka y las bases de datos.

## Variables de entorno

| Proyecto | Variable | Descripción | Valor por defecto |
| ----------------- | -------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------- |
| postgres-command | POSTGRES_DB | Nombre de la base de datos | transaction_command_db |
| postgres-command | POSTGRES_USER | Usuario de la base de datos | postgres |
| postgres-command | POSTGRES_PASSWORD | Contraseña de la base de datos | postgres |
| postgres-query | POSTGRES_DB | Nombre de la base de datos | transaction_query_db |
| postgres-query | POSTGRES_USER | Usuario de la base de datos | postgres |
| postgres-query | POSTGRES_PASSWORD | Contraseña de la base de datos | postgres |
| zookeeper | ZOOKEEPER_CLIENT_PORT | Puerto del zookeeper | 2181 |
| kafka | KAFKA_ZOOKEEPER_CONNECT | Conexión al zookeeper | zookeeper:2181 |
| kafka | KAFKA_ADVERTISED_LISTENERS | Lista de listeners | PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 |
| kafka | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP | Protocolo de seguridad | PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT |
| kafka | KAFKA_BROKER_ID | ID del broker | 1 |
| kafka | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR | Factor de replicación del topic | 1 |
| kafka | KAFKA_JMX_PORT | Puerto JMX | 9991 |
| api-gateway | CLIENT_GATEWAY_PORT | Puerto del gateway | 3000 |
| api-gateway | KAFKA_BROKER | Broker de kafka | kafka:29092 |
| ms-transaction-qr | PORT | Puerto del microservicio | 3001 |
| ms-transaction-qr | DATABASE_URL | URL de la base de datos | postgresql://postgres:postgres@postgres-query:5432/transaction_query_db?schema=public |
| ms-transaction-qr | KAFKA_BROKER | Broker de kafka | kafka:29092 |
| ms-transaction-cm | PORT | Puerto del microservicio | 3002 |
| ms-transaction-cm | DATABASE_URL | URL de la base de datos | postgresql://postgres:postgres@postgres-command:5432/transaction_command_db?schema=public |
| ms-transaction-cm | KAFKA_BROKER | Broker de kafka | kafka:29092 |
| ms-anti-fraud | PORT | Puerto del microservicio | 3003 |
| ms-anti-fraud | KAFKA_BROKER | Broker de kafka | kafka:29092 |
| |

## Instalación y Configuración

### 1. Clonar el Repositorio

Clona este repositorio en tu máquina local:

```bash
git clone https://github.com/{username}/app-nodejs-codechallenge.git
cd app-nodejs-codechallenge
```

Moverse de la rama `main` a la rama `feat/transaction`

```bash
git checkout feat/transaction
```

### 2. Iniciar el proyecto

#### 2.1. Modo desarrollo

Si se esta ejecutando el proyecto en modo producción, es necesario detener los servicios antes de iniciar el modo desarrollo.

```bash
docker-compose stop
```

Para iniciar el proyecto en modo desarrollo, ejecuta el siguiente comando:

Our code challenge will let you marvel us with your Jedi coding skills :smile:.
```bash
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build
```

Este comando iniciará todos los servicios necesarios para ejecutar el proyecto en modo desarrollo.

Don't forget that the proper way to submit your work is to fork the repo and create a PR :wink: ... have fun !!
En caso de que se requiera iniciar los servicios individualmente, puede utilizar los siguientes comandos:

- [Problem](#problem)
- [Tech Stack](#tech_stack)
- [Send us your challenge](#send_us_your_challenge)
```bash
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build ms-transaction-cm
```

```bash
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build ms-transaction-qr
```

# Problem
```bash
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build ms-anti-fraud
```

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:
```bash
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build api-gateway
```

<ol>
<li>pending</li>
<li>approved</li>
<li>rejected</li>
</ol>
#### 2.2. Modo producción

Every transaction with a value greater than 1000 should be rejected.
Si se esta ejecutando el proyecto en modo desarrollo, es necesario detener los servicios antes de iniciar el modo producción.

```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)]
```bash
docker-compose stop
```

# Tech Stack
Para iniciar el proyecto en modo producción, ejecuta el siguiente comando:

<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>
```bash
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --build -d
```

We do provide a `Dockerfile` to help you get started with a dev environment.
Este comando iniciará todos los servicios necesarios para ejecutar el proyecto en modo producción.

You must have two resources:
## Ejecución

1. Resource to create a transaction that must containt:
### 1. Crear una nueva transacción

#### Request

```bash
URL POST
http://localhost:3000/transaction/create
```

```json
{
"accountExternalIdDebit": "Guid",
"accountExternalIdCredit": "Guid",
"tranferTypeId": 1,
"accountExternalIdDebit": "Guid", // UUID cualquiera
"accountExternalIdCredit": "Guid", // UUID cualquiera
"transferTypeId": 1,
"value": 120
}
```

2. Resource to retrieve a transaction
#### Response

```json
{
Expand All @@ -69,14 +170,43 @@ You must have two resources:
}
```

## Optional
### 2. Consultar la transacción

#### Request

#### Request

```bash
URL GET
http://localhost:3000/transaction/detail/{transactionExternalId}
```

#### Response

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?
```json
{
"transactionExternalId": "Guid",
"transactionType": {
"name": ""
},
"transactionStatus": {
"name": ""
},
"value": 120,
"createdAt": "Date"
}
```

You can use Graphql;
## Siguientes pasos

# Send us your challenge
- [ ] Separar los microservicios por capas, una capa canal y otra multicanal.
- [ ] Definir los microservicios de acuerdo a su rol, ejemplo: UX, Open Insurance, Negocio, Batch, etc.
- [ ] Implementar un Api management para la organización y seguridad de los microservicios.
- [ ] Implementar el patron Saga para la orquestación de transacciones.
- [ ] Para la BD de lectura, se puede utilizar Redis como base de datos.
- [ ] Implementar la autenticación y autorización de los microservicios.
- [ ] Implementar un sistema de alertas para la monitorización de los microservicios.

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.
## Conclusión

If you have any questions, please let us know.
Este proyecto es un ejemplo de cómo se pueden implementar microservicios distribuidos con Kafka y CQRS para una aplicación de transacciones financieras. El código fuente está disponible en el repositorio de GitHub y se puede clonar y ejecutar en su propio equipo.
Loading