Skip to content

Code challenge from Manuel Guarniz 😬 #479

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 14 commits 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
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// Use IntelliSense para saber los atributos posibles.
// Mantenga el puntero para ver las descripciones de los existentes atributos.
// Para más información, visite: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Iniciar el programa",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/ms-transaction-api/src/index.ts",
"preLaunchTask": "tsc: build - ms-transaction-api/tsconfig.json",
"outFiles": ["${workspaceFolder}/ms-transaction-api/dist/**/*.js"]
}
]
}
125 changes: 121 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Yape Code Challenge :rocket:
# Yape Code Challenge 🚀

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 😄.

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

- [Problem](#problem)
- [Tech Stack](#tech_stack)
Expand Down Expand Up @@ -35,7 +35,7 @@ Every transaction with a value greater than 1000 should be rejected.
<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>Kafka</li>
</ol>

We do provide a `Dockerfile` to help you get started with a dev environment.
Expand Down Expand Up @@ -80,3 +80,120 @@ You can use Graphql;
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.

## Steps to run

1. run docker compose

```bash
docker-compose up --build -d
```
2. you wait to starting services

```bash
# wait 1min
```
3. connect to favorite IDE and run postgresql scripts

```sql
CREATE EXTENSION "uuid-ossp";

CREATE TABLE transaction_types (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL
);

INSERT INTO transaction_types (id, name) VALUES (1, 'transferencia');

create TABLE transaction_statuses (
id INT PRIMARY KEY,
name VARCHAR(20) UNIQUE NOT NULL
);

INSERT INTO transaction_statuses (id, name) VALUES (1, 'pending'), (2, 'approved'), (3, 'rejected');

CREATE TABLE transaction_audit_logs (
id SERIAL PRIMARY KEY,
transaction_id UUID NOT NULL,
previous_status VARCHAR(20),
new_status VARCHAR(20),
changed_at TIMESTAMP DEFAULT NOW(),
reason TEXT,
source_service VARCHAR(50)
);

create TABLE transactions (
id UUID PRIMARY key default uuid_generate_v4(),
account_external_id_debit UUID NOT NULL,
account_external_id_credit UUID NOT NULL,
transaction_type_id INT NOT null references transaction_types(id) on delete no action,
value NUMERIC(10, 2) NOT null,
transaction_status_id INT NOT NULL references transaction_statuses(id) on delete no action,
created_at TIMESTAMP DEFAULT NOW()
);

```
4. create kafka topic

```bash
docker exec -it app-nodejs-codechallenge-kafka-1 kafka-topics --create \
--bootstrap-server kafka:9092 \
--replication-factor 1 \
--partitions 1 \
--topic queue-transaction-validate-stream
```
5. start ms fraud-validation-stream

```bash
docker start app-nodejs-codechallenge-ms-fraud-validation-stream-1
```
6. test application

```bash
# Registration success transfer
curl --location 'http://localhost:8080/api/transaction' \
--header 'Content-Type: application/json' \
--data '{
"accountExternalIdDebit": "4aa80dd2-a68f-40c8-b5bb-8c6afea8d3d6",
"accountExternalIdCredit": "3aa80dd2-a68f-40c8-b5bb-8c6afea8d3d7",
"tranferTypeId": 1,
"value": 999
}'

# Registration reject transfer
curl --location 'http://localhost:8080/api/transaction' \
--header 'Content-Type: application/json' \
--data '{
"accountExternalIdDebit": "5aa80dd2-a68f-40c8-b5bb-8c6afea8d3d7",
"accountExternalIdCredit": "6aa80dd2-a68f-40c8-b5bb-8c6afea8d3d8",
"tranferTypeId": 1,
"value": 1001
}'

# Query transfer status (get transactionId from preview response)
curl --location 'http://localhost:8080/api/transaction/{transactionId}' \
--header 'accept: application/json'

# Showing audit transaction
# SQL
# select * from transaction_audit_logs

```

## Screenshots

1. success transfer

![1745549557618](image/README/1745549557618.png)

![1745549571939](image/README/1745549571939.png)

2. reject transfer

![1745549603795](image/README/1745549603795.png)

![1745549618714](image/README/1745549618714.png)

3. kafka logs

![1745549646067](image/README/1745549646067.png)
36 changes: 36 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,55 @@ services:
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres

zookeeper:
image: confluentinc/cp-zookeeper:5.5.3
environment:
ZOOKEEPER_CLIENT_PORT: 2181

kafka:
image: confluentinc/cp-enterprise-kafka:5.5.3
depends_on: [zookeeper]
environment:
KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_BROKER_ID: 1
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_JMX_PORT: 9991
ports:
- 9092:9092

ms-transaction-api:
build:
context: .
dockerfile: ./ms-transaction-api/Dockerfile
ports:
- "8080:8080"
depends_on:
- postgres
- kafka
environment:
NODE_ENV: production
PORT: 8080
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public
KAFKA_BROKERS: kafka:29092
KAFKA_APPLICATION_ID: appid-transaction-api
KAFKA_TRANSACTION_VALIDATE_TOPIC: queue-transaction-validate-stream

ms-fraud-validation-stream:
build:
context: .
dockerfile: ./ms-fraud-validation-stream/Dockerfile
depends_on:
- postgres
- kafka
- ms-transaction-api
environment:
NODE_ENV: production
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?schema=public
KAFKA_BROKERS: kafka:29092
KAFKA_APPLICATION_ID: appid-transaction-api
KAFKA_APPLICATION_GROUP: group-transaction-api
KAFKA_TRANSACTION_VALIDATE_TOPIC: queue-transaction-validate-stream
Binary file added image/README/1745549557618.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/README/1745549571939.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/README/1745549603795.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/README/1745549618714.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/README/1745549646067.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 63 additions & 0 deletions ms-fraud-validation-stream/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "22"

- name: Install dependencies
run: npm install

- name: Run linter
run: npm run lint

test:
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "22"

- name: Install dependencies
run: npm install

- name: Run tests
run: npm test

build:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "22"

- name: Install dependencies
run: npm install

- name: Build TypeScript
run: npm run build
52 changes: 52 additions & 0 deletions ms-fraud-validation-stream/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Dependencies
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log

# TypeScript
dist/
build/
*.tsbuildinfo

# Environment variables
.env
.env.local
.env.*.local

# IDE - VSCode
.vscode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# System Files
.DS_Store
Thumbs.db

# Logs
logs
*.log

# Coverage directory used by tools like istanbul
coverage/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Prisma
generated/prisma/

# IntellijIDEA
.idea/
8 changes: 8 additions & 0 deletions ms-fraud-validation-stream/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"endOfLine": "auto"
}
27 changes: 27 additions & 0 deletions ms-fraud-validation-stream/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Stage Build
FROM node:22-alpine as builder
RUN echo "Starting build..."
WORKDIR /app

COPY ms-fraud-validation-stream/package*.json ./
COPY ms-fraud-validation-stream/tsconfig.json ./
COPY ms-fraud-validation-stream/prisma ./prisma
COPY ms-fraud-validation-stream/src ./src

RUN npm ci
RUN npx prisma generate
RUN npm run build

# Stage production
FROM node:22-alpine

WORKDIR /app

COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules ./node_modules

ENV NODE_ENV=production

CMD ["node", "./dist/index.js"]
21 changes: 21 additions & 0 deletions ms-fraud-validation-stream/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 mguarniz

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading