Skip to content

Commit 87591e2

Browse files
committed
feat(routes): API routes woking
1 parent e6753c3 commit 87591e2

15 files changed

+653
-173
lines changed

README.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# working in readme...
2+
# 5th chalenge complete ![complete](https://camo.githubusercontent.com/facfcb6afd684d2c9701c7d6add65f391fdf86fc/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6477796c2f686170692d617574682d6a7774322e7376673f6d61784167653d32353932303030)
3+
4+
## :rocket: Sobre o desafio
5+
6+
Nesse desafio, você deve criar uma aplicação para continuar treinando o que você aprendeu até agora no Node.js junto ao TypeScript, utilizando o conceito de models, repositories e services!
7+
8+
Essa será uma aplicação para armazenar transações financeiras de entrada e saída, que deve permitir o cadastro e a listagem dessas transações.
9+
10+
### Rotas da aplicação
11+
12+
Agora que você já está com o template clonado, e pronto para continuar, você deve verificar os arquivos da pasta `src` e completar onde não possui código com o código para atingir os objetivos de cada rota.
13+
14+
- **`POST /transactions`**: A rota deve receber `title`, `value` e `type` dentro do corpo da requisição, sendo `type` o tipo da transação, que deve ser `income` para entradas (depósitos) e `outcome` para saídas (retiradas). Ao cadastrar uma nova transação, ela deve ser armazenada dentro de um objeto com o seguinte formato :
15+
16+
```json
17+
{
18+
"id": "uuid",
19+
"title": "Salário",
20+
"value": 3000,
21+
"type": "income"
22+
}
23+
```
24+
25+
- **`GET /transactions`**: Essa rota deve retornar uma listagem com todas as transações que você cadastrou até agora, junto com o valor de soma de entradas, retiradas e total de crédito. Essa rota deve retornar um objeto com o formato a seguir:
26+
27+
```json
28+
{
29+
"transactions": [
30+
{
31+
"id": "uuid",
32+
"title": "Salário",
33+
"value": 4000,
34+
"type": "income"
35+
},
36+
{
37+
"id": "uuid",
38+
"title": "Freela",
39+
"value": 2000,
40+
"type": "income"
41+
},
42+
{
43+
"id": "uuid",
44+
"title": "Pagamento da fatura",
45+
"value": 4000,
46+
"type": "outcome"
47+
},
48+
{
49+
"id": "uuid",
50+
"title": "Cadeira Gamer",
51+
"value": 1200,
52+
"type": "outcome"
53+
}
54+
],
55+
"balance": {
56+
"income": 6000,
57+
"outcome": 5200,
58+
"total": 800
59+
}
60+
}
61+
```
62+
63+
**Dica**: Dentro de balance, o income é a soma de todos os valores das transações com `type` income. O outcome é a soma de todos os valores das transações com `type` outcome, e o total é o valor de `income - outcome`.
64+
65+
**Dica 2**: Para fazer a soma dos valores, você pode usar a função [reduce](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) para agrupar as transações pela propriedade `type`, assim você irá conseguir somar todos os valores com facilidade e obter o retorno do `balance`.
66+
67+
### Especificação dos testes
68+
69+
Em cada teste, tem uma breve descrição no que sua aplicação deve cumprir para que o teste passe.
70+
71+
Caso você tenha dúvidas quanto ao que são os testes, e como interpretá-los, dé uma olhada em **[nosso FAQ](https://github.com/Rocketseat/bootcamp-gostack-desafios/tree/master/faq-desafios).**
72+
73+
Para esse desafio temos os seguintes testes:
74+
75+
- **`should be able to create a new transaction`**: Para que esse teste passe, sua aplicação deve permitir que uma transação seja criada, e retorne um json com a transação criada.
76+
77+
- **`should be able to list the transactions`**: Para que esse teste passe, sua aplicação deve permitir que seja retornado um objeto contendo todas as transações junto ao balanço de income, outcome e total das transações que foram criadas até o momento.
78+
79+
- **`should not be able to create outcome transaction without a valid balance`**: Para que esse teste passe, sua aplicação não deve permitir que uma transação do tipo `outcome` extrapole o valor total que o usuário tem em caixa, retornando uma resposta com código HTTP 400 e uma mensagem de erro no seguinte formato: `{ error: string }`
80+
81+
## :calendar: Entrega
82+
83+
Esse desafio deve ser entregue a partir da plataforma da Rocketseat, envie o link do repositório que você fez suas alterações. Após concluir o desafio, fazer um post no Linkedin e postar o código no Github é uma boa forma de demonstrar seus conhecimentos e esforços para evoluir na sua carreira para oportunidades futuras.
84+
85+
## :memo: Licença
86+
87+
Esse projeto está sob a licença MIT. Veja o arquivo [LICENSE](LICENSE) para mais detalhes.
88+
# 4th chalenge complete ![complete](https://camo.githubusercontent.com/facfcb6afd684d2c9701c7d6add65f391fdf86fc/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6477796c2f686170692d617574682d6a7774322e7376673f6d61784167653d32353932303030)
89+
90+
## :rocket: Sobre o desafio
91+
92+
Nesse desafio, você deve criar uma aplicação para continuar treinando o que você aprendeu até agora no Node.js junto ao TypeScript, utilizando o conceito de models, repositories e services!
93+
94+
Essa será uma aplicação para armazenar transações financeiras de entrada e saída, que deve permitir o cadastro e a listagem dessas transações.
95+
96+
### Rotas da aplicação
97+
98+
Agora que você já está com o template clonado, e pronto para continuar, você deve verificar os arquivos da pasta `src` e completar onde não possui código com o código para atingir os objetivos de cada rota.
99+
100+
- **`POST /transactions`**: A rota deve receber `title`, `value` e `type` dentro do corpo da requisição, sendo `type` o tipo da transação, que deve ser `income` para entradas (depósitos) e `outcome` para saídas (retiradas). Ao cadastrar uma nova transação, ela deve ser armazenada dentro de um objeto com o seguinte formato :
101+
102+
```json
103+
{
104+
"id": "uuid",
105+
"title": "Salário",
106+
"value": 3000,
107+
"type": "income"
108+
}
109+
```
110+
111+
- **`GET /transactions`**: Essa rota deve retornar uma listagem com todas as transações que você cadastrou até agora, junto com o valor de soma de entradas, retiradas e total de crédito. Essa rota deve retornar um objeto com o formato a seguir:
112+
113+
```json
114+
{
115+
"transactions": [
116+
{
117+
"id": "uuid",
118+
"title": "Salário",
119+
"value": 4000,
120+
"type": "income"
121+
},
122+
{
123+
"id": "uuid",
124+
"title": "Freela",
125+
"value": 2000,
126+
"type": "income"
127+
},
128+
{
129+
"id": "uuid",
130+
"title": "Pagamento da fatura",
131+
"value": 4000,
132+
"type": "outcome"
133+
},
134+
{
135+
"id": "uuid",
136+
"title": "Cadeira Gamer",
137+
"value": 1200,
138+
"type": "outcome"
139+
}
140+
],
141+
"balance": {
142+
"income": 6000,
143+
"outcome": 5200,
144+
"total": 800
145+
}
146+
}
147+
```
148+
149+
**Dica**: Dentro de balance, o income é a soma de todos os valores das transações com `type` income. O outcome é a soma de todos os valores das transações com `type` outcome, e o total é o valor de `income - outcome`.
150+
151+
**Dica 2**: Para fazer a soma dos valores, você pode usar a função [reduce](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) para agrupar as transações pela propriedade `type`, assim você irá conseguir somar todos os valores com facilidade e obter o retorno do `balance`.
152+
153+
### Especificação dos testes
154+
155+
Em cada teste, tem uma breve descrição no que sua aplicação deve cumprir para que o teste passe.
156+
157+
Caso você tenha dúvidas quanto ao que são os testes, e como interpretá-los, dé uma olhada em **[nosso FAQ](https://github.com/Rocketseat/bootcamp-gostack-desafios/tree/master/faq-desafios).**
158+
159+
Para esse desafio temos os seguintes testes:
160+
161+
- **`should be able to create a new transaction`**: Para que esse teste passe, sua aplicação deve permitir que uma transação seja criada, e retorne um json com a transação criada.
162+
163+
- **`should be able to list the transactions`**: Para que esse teste passe, sua aplicação deve permitir que seja retornado um objeto contendo todas as transações junto ao balanço de income, outcome e total das transações que foram criadas até o momento.
164+
165+
- **`should not be able to create outcome transaction without a valid balance`**: Para que esse teste passe, sua aplicação não deve permitir que uma transação do tipo `outcome` extrapole o valor total que o usuário tem em caixa, retornando uma resposta com código HTTP 400 e uma mensagem de erro no seguinte formato: `{ error: string }`
166+
167+
## :calendar: Entrega
168+
169+
Esse desafio deve ser entregue a partir da plataforma da Rocketseat, envie o link do repositório que você fez suas alterações. Após concluir o desafio, fazer um post no Linkedin e postar o código no Github é uma boa forma de demonstrar seus conhecimentos e esforços para evoluir na sua carreira para oportunidades futuras.
170+
171+
## :memo: Licença
172+
173+
Esse projeto está sob a licença MIT. Veja o arquivo [LICENSE](LICENSE) para mais detalhes.

package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
"license": "MIT",
66
"scripts": {
77
"build": "tsc",
8-
"dev:server": "ts-node-dev --inspect --transpileOnly --ignore-watch node_modules src/server.ts",
8+
"dev:server": "ts-node-dev --inspect --transpile-only --ignore-watch node_modules src/server.ts",
99
"start": "ts-node src/index.ts",
10-
"typeorm": "ts-node-dev ./node_modules/typeorm/cli.js",
10+
"typeorm": "ts-node-dev -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
1111
"test": "cross-env NODE_ENV=test jest"
1212
},
1313
"dependencies": {
@@ -40,8 +40,7 @@
4040
"prettier": "^2.0.4",
4141
"supertest": "^4.0.2",
4242
"ts-jest": "^25.3.1",
43-
"ts-node": "3.3.0",
44-
"ts-node-dev": "^1.0.0-pre.44",
43+
"ts-node-dev": "^1.0.0",
4544
"typescript": "^3.8.3"
4645
}
4746
}

src/config/upload.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import path from 'path';
2+
import multer from 'multer';
3+
import crypto from 'crypto';
4+
5+
const tmpFolder = path.resolve(__dirname, '..', '..', 'tmp');
6+
7+
export default {
8+
directory: tmpFolder,
9+
storage: multer.diskStorage({
10+
destination: tmpFolder,
11+
filename: (request, file, callback) => {
12+
const fileHast = crypto.randomBytes(10).toString('hex');
13+
const filename = `${fileHast}-${file.originalname}`;
14+
15+
return callback(null, filename);
16+
},
17+
}),
18+
};
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { MigrationInterface, QueryRunner, Table } from 'typeorm';
2+
3+
export default class CreateTransaction1606501299627
4+
implements MigrationInterface {
5+
public async up(queryRunner: QueryRunner): Promise<void> {
6+
await queryRunner.createTable(
7+
new Table({
8+
name: 'transactions',
9+
columns: [
10+
{
11+
name: 'id',
12+
type: 'uuid',
13+
isPrimary: true,
14+
generationStrategy: 'uuid',
15+
default: 'uuid_generate_v4()',
16+
},
17+
{
18+
name: 'title',
19+
type: 'varchar',
20+
},
21+
{
22+
name: 'value',
23+
type: 'decimal',
24+
precision: 10,
25+
scale: 2,
26+
},
27+
{
28+
name: 'type',
29+
type: 'varchar',
30+
},
31+
{
32+
name: 'createdAt',
33+
type: 'timestamp',
34+
default: 'now()',
35+
},
36+
{
37+
name: 'updatedAt',
38+
type: 'timestamp',
39+
default: 'now()',
40+
},
41+
],
42+
}),
43+
);
44+
}
45+
46+
public async down(queryRunner: QueryRunner): Promise<void> {
47+
await queryRunner.dropTable('transactions');
48+
}
49+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { MigrationInterface, QueryRunner, Table } from 'typeorm';
2+
3+
export default class CreateCategory1606502442186 implements MigrationInterface {
4+
public async up(queryRunner: QueryRunner): Promise<any> {
5+
await queryRunner.createTable(
6+
new Table({
7+
name: 'categories',
8+
columns: [
9+
{
10+
name: 'id',
11+
type: 'uuid',
12+
isPrimary: true,
13+
generationStrategy: 'uuid',
14+
default: 'uuid_generate_v4()',
15+
},
16+
{
17+
name: 'title',
18+
type: 'varchar',
19+
},
20+
{
21+
name: 'createdAt',
22+
type: 'timestamp',
23+
default: 'now()',
24+
},
25+
{
26+
name: 'updatedAt',
27+
type: 'timestamp',
28+
default: 'now()',
29+
},
30+
],
31+
}),
32+
);
33+
}
34+
35+
public async down(queryRunner: QueryRunner): Promise<any> {
36+
await queryRunner.dropTable('categories');
37+
}
38+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {
2+
MigrationInterface,
3+
QueryRunner,
4+
TableColumn,
5+
TableForeignKey,
6+
} from 'typeorm';
7+
8+
export default class AddCategoryIdToTransactions1606588922223
9+
implements MigrationInterface {
10+
public async up(queryRunner: QueryRunner): Promise<void> {
11+
await queryRunner.addColumn(
12+
'transactions',
13+
new TableColumn({
14+
name: 'categoryId',
15+
type: 'uuid',
16+
isNullable: true,
17+
}),
18+
);
19+
20+
await queryRunner.createForeignKey(
21+
'transactions',
22+
new TableForeignKey({
23+
columnNames: ['categoryId'],
24+
referencedColumnNames: ['id'],
25+
referencedTableName: 'categories',
26+
name: 'TransactionCategories',
27+
onUpdate: 'CASCADE',
28+
onDelete: 'SET NULL',
29+
}),
30+
);
31+
}
32+
33+
public async down(queryRunner: QueryRunner): Promise<void> {
34+
await queryRunner.dropForeignKey('transactions', 'TransactionCategories');
35+
await queryRunner.dropColumn('transactions', 'categoryId');
36+
}
37+
}

src/models/Category.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
1+
import {
2+
Column,
3+
CreateDateColumn,
4+
Entity,
5+
PrimaryGeneratedColumn,
6+
UpdateDateColumn,
7+
} from 'typeorm';
8+
9+
@Entity('categories')
110
class Category {
11+
@PrimaryGeneratedColumn('uuid')
212
id: string;
313

14+
@Column()
415
title: string;
516

6-
created_at: Date;
17+
@CreateDateColumn()
18+
createdAt: Date;
719

8-
updated_at: Date;
20+
@UpdateDateColumn()
21+
updatedAt: Date;
922
}
1023

1124
export default Category;

0 commit comments

Comments
 (0)