{"id":28368562,"url":"https://github.com/denisfloyd/gostack-typeorm-upload","last_synced_at":"2026-05-17T11:31:50.822Z","repository":{"id":141616213,"uuid":"503730217","full_name":"denisfloyd/gostack-typeorm-upload","owner":"denisfloyd","description":"Desafio 06: Banco de dados e upload de arquivos no Node.js","archived":false,"fork":false,"pushed_at":"2022-03-26T14:34:10.000Z","size":1483,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-27T21:24:46.605Z","etag":null,"topics":["nodeapi","nodejs","typeorm","typescript","upload"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/denisfloyd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-06-15T11:07:21.000Z","updated_at":"2022-07-08T18:03:18.000Z","dependencies_parsed_at":"2023-07-04T19:47:05.321Z","dependency_job_id":null,"html_url":"https://github.com/denisfloyd/gostack-typeorm-upload","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/denisfloyd/gostack-typeorm-upload","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisfloyd%2Fgostack-typeorm-upload","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisfloyd%2Fgostack-typeorm-upload/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisfloyd%2Fgostack-typeorm-upload/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisfloyd%2Fgostack-typeorm-upload/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/denisfloyd","download_url":"https://codeload.github.com/denisfloyd/gostack-typeorm-upload/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denisfloyd%2Fgostack-typeorm-upload/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33136679,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T09:28:26.183Z","status":"ssl_error","status_checked_at":"2026-05-17T09:27:52.702Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nodeapi","nodejs","typeorm","typescript","upload"],"created_at":"2025-05-29T04:11:10.026Z","updated_at":"2026-05-17T11:31:50.815Z","avatar_url":"https://github.com/denisfloyd.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg alt=\"GoStack\" src=\"https://storage.googleapis.com/golden-wind/bootcamp-gostack/header-desafios.png\" /\u003e\n\n\u003ch3 align=\"center\"\u003e\n  Desafio 06: Banco de dados e upload de arquivos no Node.js\n\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e“Só deseje as coisas as quais você está disposto a lutar”!\u003c/blockquote\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"GitHub language count\" src=\"https://img.shields.io/github/languages/count/rocketseat/bootcamp-gostack-desafios?color=%2304D361\"\u003e\n\n  \u003ca href=\"https://rocketseat.com.br\"\u003e\n    \u003cimg alt=\"Made by Rocketseat\" src=\"https://img.shields.io/badge/made%20by-Rocketseat-%2304D361\"\u003e\n  \u003c/a\u003e\n\n  \u003cimg alt=\"License\" src=\"https://img.shields.io/badge/license-MIT-%2304D361\"\u003e\n\n  \u003ca href=\"https://github.com/Rocketseat/bootcamp-gostack-desafios/stargazers\"\u003e\n    \u003cimg alt=\"Stargazers\" src=\"https://img.shields.io/github/stars/rocketseat/bootcamp-gostack-desafios?style=social\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#rocket-sobre-o-desafio\"\u003eSobre o desafio\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"#como-executar\"\u003eComo executar\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"#calendar-entrega\"\u003eEntrega\u003c/a\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"#memo-licença\"\u003eLicença\u003c/a\u003e\n\u003c/p\u003e\n\n## :rocket: Sobre o desafio\n\nNesse desafio, você deve continuar desenvolvendo a aplicação de gestão de transações, treinando o que você aprendeu até agora no Node.js junto ao TypeScript, mas dessa vez incluindo o uso de banco de dados com o TypeORM e envio de arquivos com o Multer!\n\nEssa será uma aplicação que deve armazenar transações financeiras de entrada e saída e permitir o cadastro e a listagem dessas transações, além de permitir a geração de relatórios a partir do envio de um arquivo csv.\n\n## Como executar\n\n1. Faça o clone do projeto na sua máquina;\n2. Na raiz do projeto, execute o comando `yarn` para baixar as dependências;\n3. Execute `yarn test` para rodar os testes;\n4. Execute `yarn dev:server` para rodar o projeto;\n5. Abra o Insomnia para testar as rotas `transactions` com os métodos `POST`,`GET` e `DELETE`, e testa a rota `/transactions/import` para importar o arquivo que está na pasta `src/__tests__/import_template.csv`, deixe como MultipartForm, adicione o atributo: `file` com o arquivo `import_template.csv`.\n\n### Template da aplicação\n\nPara te ajudar nesse desafio, criamos para você um modelo que você deve utilizar como um template do Github.\n\nO template está disponível na seguinte url: **[Acessar Template](https://github.com/Rocketseat/gostack-template-typeorm-upload)**\n\n**Dica**: Caso não saiba utilizar repositórios do Github como template, temos um guia em **[nosso FAQ](https://github.com/Rocketseat/bootcamp-gostack-desafios/tree/master/faq-desafios).**\n\nAgora navegue até a pasta criada e abra no Visual Studio Code, lembre-se de executar o comando `yarn` no seu terminal para instalar todas as dependências.\n\n### Rotas da aplicação\n\nAgora 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.\n\n- **`POST /transactions`**: A rota deve receber `title`, `value`, `type`, e `category` dentro do corpo da requisição, sendo o `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 do seu banco de dados, possuindo os campos `id`, `title`, `value`, `type`, `category_id`, `created_at`, `updated_at`.\n\n**Dica**: Para a categoria, você deve criar uma nova tabela, que terá os campos `id`, `title`, `created_at`, `updated_at`.\n\n**Dica 2**: Antes de criar uma nova categoria, sempre verifique se já existe uma categoria com o mesmo título. Caso ela exista, use o `id` já existente no banco de dados.\n\n```json\n{\n  \"id\": \"uuid\",\n  \"title\": \"Salário\",\n  \"value\": 3000,\n  \"type\": \"income\",\n  \"category\": \"Alimentação\"\n}\n```\n\n**Dica**: Para criar uma categoria, sempre verifique antes se a categoria já existe no banco de dados. Por exemplo, se a categoria \"Alimentação\" não existir no banco de dados, crie essa categoria no mesmo momento, e utilize o id criado. Caso ela já exista, utilize o `id` que já está presente no banco de dados.\n\n- **`GET /transactions`**: Essa rota deve retornar uma listagem com todas as transações que você cadastrou até agora, junto com o valor da soma de entradas, retiradas e total de crédito. Essa rota deve retornar um objeto com o formato a seguir:\n\n```json\n{\n  \"transactions\": [\n    {\n      \"id\": \"uuid\",\n      \"title\": \"Salário\",\n      \"value\": 4000,\n      \"type\": \"income\",\n      \"category\": {\n        \"id\": \"uuid\",\n        \"title\": \"Salary\"\n      }\n    },\n    {\n      \"id\": \"uuid\",\n      \"title\": \"Freela\",\n      \"value\": 2000,\n      \"type\": \"income\",\n      \"category\": {\n        \"id\": \"uuid\",\n        \"title\": \"Others\"\n      }\n    },\n    {\n      \"id\": \"uuid\",\n      \"title\": \"Pagamento da fatura\",\n      \"value\": 4000,\n      \"type\": \"outcome\",\n      \"category\": {\n        \"id\": \"uuid\",\n        \"title\": \"Others\"\n      }\n    },\n    {\n      \"id\": \"uuid\",\n      \"title\": \"Cadeira Gamer\",\n      \"value\": 1200,\n      \"type\": \"outcome\",\n      \"category\": {\n        \"id\": \"uuid\",\n        \"title\": \"Recreation\"\n      }\n    }\n  ],\n  \"balance\": {\n    \"income\": 6000,\n    \"outcome\": 5200,\n    \"total\": 800\n  }\n}\n```\n\n**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`.\n\n**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`.\n\n- **`DELETE /transactions/:id`**: A rota deve deletar uma transação com o `id` presente nos parâmetros da rota;\n\n* **`POST /transactions/import`**: A rota deve permitir a importação de um arquivo com formato `.csv` contendo as mesmas informações necessárias para criação de uma transação `id`, `title`, `value`, `type`, `category_id`, `created_at`, `updated_at`, onde cada linha do arquivo CSV deve ser um novo registro para o banco de dados, e por fim retorne todas as `transactions` que foram importadas para seu banco de dados. O arquivo csv, deve seguir o seguinte [modelo](./assets/file.csv)\n\n### Específicação dos testes\n\nEm cada teste, tem uma breve descrição no que sua aplicação deve cumprir para que o teste passe.\n\nCaso 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).**\n\nPara esse desafio, temos os seguintes testes:\n\n\u003ch4 align=\"center\"\u003e\n  ⚠️ Antes de rodar os testes, crie um banco de dados com o nome \"gostack_desafio06_tests\" para que todos os testes possam executar corretamente ⚠️\n\u003c/h4\u003e\n\n- **`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 criado.\n\n* **`should create tags when inserting new transactions`**: Para que esse teste passe, sua aplicação deve permitir que ao criar uma nova transação com uma categoria que não existe, essa seja criada e inserida no campo category_id da transação com o `id` que acabou de ser criado.\n\n- **`should not create tags when they already exists`**: Para que esse teste passe, sua aplicação deve permitir que ao criar uma nova transação com uma categoria que já existe, seja atribuído ao campo category_id da transação com o `id` dessa categoria existente, não permitindo a criação de categorias com o mesmo `title`.\n\n* **`should be able to list the transactions`**: Para que esse teste passe, sua aplicação deve permitir que seja retornado um array de objetos contendo todas as transações junto ao balanço de income, outcome e total das transações que foram criadas até o momento.\n\n- **`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 (total de income), retornando uma resposta com código HTTP 400 e uma mensagem de erro no seguinte formato: `{ error: string }`.\n\n* **`should be able to delete a transaction`**: Para que esse teste passe, você deve permitir que a sua rota de delete exclua uma transação, e ao fazer a exclusão, ele retorne uma resposta vazia, com status 204.\n\n- **`should be able to import transactions`**: Para que esse teste passe, sua aplicação deve permitir que seja importado um arquivo csv, contendo o seguinte [modelo](./assets/file.csv). Com o arquivo importado, você deve permitir que seja criado no banco de dados todos os registros e categorias que estavam presentes nesse arquivo, e retornar todas as transactions que foram importadas.\n\n## :calendar: Entrega\n\nEsse desafio deve ser entregue a partir da plataforma Skylab, 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.\n\n## :memo: Licença\n\nEsse projeto está sob a licença MIT. Veja o arquivo [LICENSE](LICENSE.md) para mais detalhes.\n\n---\n\nFeito com 💜 by Rocketseat :wave: [Entre na nossa comunidade!](https://discordapp.com/invite/gCRAFhc)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenisfloyd%2Fgostack-typeorm-upload","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenisfloyd%2Fgostack-typeorm-upload","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenisfloyd%2Fgostack-typeorm-upload/lists"}