Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ad3c034
feat(api): create PUT /transaction route
joaogolias May 30, 2024
3ec4e42
feat(api): setting up ValidationPipe and creating core models converters
joaogolias May 30, 2024
66fb68a
feat(database): setting up TypeORM and creating transactions in database
joaogolias May 30, 2024
9e8bfd5
fix(naming): fixing files name to stardantize naming strategy
joaogolias May 30, 2024
c1ceb5f
chore(sqs): ucreating lAWS SQS queues from lLocalStack image in docker
joaogolias May 30, 2024
3247df5
feat(messaging): set up Transaction SQS producer and producing messag…
joaogolias May 30, 2024
424fdb4
refactor(messaging): refactoring producer in order to follow dependen…
joaogolias May 30, 2024
e64b4c2
feat(messaging): set up Transaction SQS consumers and creating Servic…
joaogolias May 30, 2024
9ee2314
feat(messaging): creating a merchant payable from a merchant trandaction
joaogolias May 31, 2024
78ef383
feat(api): implementing endpoint that summarized payables by merchant
joaogolias May 31, 2024
7fe3595
sytles(lint): applying lint and format
joaogolias May 31, 2024
5421ce6
styles(log): adding logger in all endpoints and consumers
joaogolias May 31, 2024
023885e
style(lint): running lint and prettier
joaogolias May 31, 2024
a750584
refactor(dotenv): substituted same variables to env file and set up d…
joaogolias Jun 1, 2024
9f11d8e
style(lint): applying lint and prettier
joaogolias Jun 1, 2024
55fa748
refactor(dto): standartized dto names
joaogolias Jun 1, 2024
1f1a9cc
refactor(sqs): creating SQS sublayer in messaging
joaogolias Jun 1, 2024
9e76f57
refactor(business): isolating logic related to summary of payables in…
joaogolias Jun 1, 2024
1901051
test(api): finished tests for api layer
joaogolias Jun 1, 2024
f8b376a
test(business): implemented unit tests for business layer
joaogolias Jun 1, 2024
f9139e0
test(data): implementes unit tests for repositories
joaogolias Jun 1, 2024
4068716
test(services): implemented unit tests for service layer
joaogolias Jun 1, 2024
34fd057
refactor(naming): fixing typo in contracts folder
joaogolias Jun 1, 2024
f56ed3e
docs(readme): updating readme
joaogolias Jun 1, 2024
0e63dce
removing unecessary logs
joaogolias Jun 2, 2024
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Docker volumes
infrastructure/**/*/volume/*
245 changes: 172 additions & 73 deletions README.md

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions infrastructure/local/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: '3.3'

services:
postgres:
container_name: tech-challenge-ecosystem-db
image: postgres:15.6
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: r00t
POSTGRES_DB: tech-challenge-ecosystem-db
ports:
- "5432:5432"

localstack:
container_name: partners-service-local-stack
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566"
- "127.0.0.1:4510-4559:4510-4559"
environment:
- DEBUG=${DEBUG-}
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
- ./localstackBootstrap:/etc/localstack/init/ready.d
30 changes: 30 additions & 0 deletions infrastructure/local/localstackBootstrap/sqs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash

set -euo pipefail

# enable debug
# set -x

echo "configuring sqs"
echo "==================="

LOCALSTACK_HOST=localhost
AWS_REGION=us-east-1

create_dlq() {
local DLQ_NAME_TO_CREATE=$1
aws --endpoint-url=http://${LOCALSTACK_HOST}:4566 --region ${AWS_REGION} sqs create-queue --queue-name ${DLQ_NAME_TO_CREATE}
}

create_queue() {
local QUEUE_NAME_TO_CREATE=$1
local DLQ_NAME=$2
local DLQ_ARN="\\\"arn:aws:sqs:us-east-1:000000000000:${DLQ_NAME}\\\""
local QUEUE_ATTRIBUTES='{ "RedrivePolicy": "{\"deadLetterTargetArn\":'"$DLQ_ARN"',\"maxReceiveCount\":\"1\"}"}'

aws --endpoint-url=http://${LOCALSTACK_HOST}:4566 --region ${AWS_REGION} sqs create-queue --queue-name ${QUEUE_NAME_TO_CREATE} \
--attributes "$QUEUE_ATTRIBUTES"
}

create_dlq "transactions-dlq"
create_queue "transactions-queue" "transactions-dlq"
25 changes: 25 additions & 0 deletions tech-challenge-ecosystem/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
56 changes: 56 additions & 0 deletions tech-challenge-ecosystem/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# compiled output
/dist
/node_modules
/build

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

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

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# temp directory
.temp
.tmp

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

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
1 change: 1 addition & 0 deletions tech-challenge-ecosystem/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.19.0
4 changes: 4 additions & 0 deletions tech-challenge-ecosystem/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}
73 changes: 73 additions & 0 deletions tech-challenge-ecosystem/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
</p>

[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
[circleci-url]: https://circleci.com/gh/nestjs/nest

<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->

## Description

[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.

## Installation

```bash
$ yarn install
```

## Running the app

```bash
# development
$ yarn run start

# watch mode
$ yarn run start:dev

# production mode
$ yarn run start:prod
```

## Test

```bash
# unit tests
$ yarn run test

# e2e tests
$ yarn run test:e2e

# test coverage
$ yarn run test:cov
```

## Support

Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).

## Stay in touch

- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)

## License

Nest is [MIT licensed](LICENSE).
8 changes: 8 additions & 0 deletions tech-challenge-ecosystem/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}
79 changes: 79 additions & 0 deletions tech-challenge-ecosystem/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "tech-challenge-ecosystem",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@ssut/nestjs-sqs": "^2.2.0",
"@types/uuid": "^9.0.8",
"aws-sdk": "^2.1630.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dayjs": "^1.11.11",
"dotenv": "^16.4.5",
"pg": "^8.11.5",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"typeorm": "^0.3.20"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s",
"!**/*.(providers|module).(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
34 changes: 34 additions & 0 deletions tech-challenge-ecosystem/src/api/controller/payable.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Controller, Get, Inject, Logger, Query } from '@nestjs/common';
import {
PAYABLE_SERVICE_PROVIDE,
PayableService,
} from '../../core/services/payable/payable.service';
import { PayableSummaryFilterDTO } from '../models/payable.summary.filter.dto';
import { PayableSummaryDTO } from '../models/payable.summary.dto';

@Controller('/payable')
export class PayableController {
constructor(
@Inject(PAYABLE_SERVICE_PROVIDE)
private readonly payableService: PayableService,
) {}

private logger = new Logger(PayableController.name);

@Get('/summary')
async summarizeByMerchant(@Query() queryFilters: PayableSummaryFilterDTO) {
this.logger.log(
`Summarizing payables with queries: ${JSON.stringify(queryFilters)}`,
);

const summaries = await this.payableService.summarizeByMerchant(
Number(queryFilters.merchantId),
new Date(queryFilters.startDate),
new Date(queryFilters.endDate),
);

this.logger.log(`Summarized payables successfully`);

return PayableSummaryDTO.fromSummarizedPayables(summaries);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CardDTO } from '../../../models/card.dto';

export class CardDTOFixture {
public static default(): CardDTO {
const cardInput = new CardDTO();
cardInput.number = '1234567898754321';
cardInput.holder = 'John Smith';
cardInput.expirationDate = '12/2028';
cardInput.cvv = '012';
return cardInput;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SummarizedPayablesFixture } from './summarized.payable.fixture';

export class PayableServiceFixture {
summarizeByMerchant = jest.fn(() =>
Promise.resolve([SummarizedPayablesFixture.default()]),
);
}

export const payableServiceFixture = new PayableServiceFixture();
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PayableStatus } from '../../../../core/models/payable';
import { SummarizedPayables } from '../../../../core/models/summarized.payables';

export class SummarizedPayablesFixture {
public static default() {
return new SummarizedPayables(PayableStatus.PAID, 98, 100, 2);
}
}
Loading