{"id":21301186,"url":"https://github.com/adrianomonteiroweb/store-manager","last_synced_at":"2026-05-18T00:09:03.188Z","repository":{"id":109835032,"uuid":"517061771","full_name":"adrianomonteiroweb/store-manager","owner":"adrianomonteiroweb","description":"Projeto Trybe para desenvolvimento de API utilizando a arquitetura MSC","archived":false,"fork":false,"pushed_at":"2022-07-23T13:17:37.000Z","size":2506,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-27T23:43:27.204Z","etag":null,"topics":["api","api-rest","msc","nodejs","rest-api"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"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/adrianomonteiroweb.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-23T13:12:48.000Z","updated_at":"2022-07-23T13:18:10.000Z","dependencies_parsed_at":"2023-04-29T10:16:36.832Z","dependency_job_id":null,"html_url":"https://github.com/adrianomonteiroweb/store-manager","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/adrianomonteiroweb/store-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianomonteiroweb%2Fstore-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianomonteiroweb%2Fstore-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianomonteiroweb%2Fstore-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianomonteiroweb%2Fstore-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adrianomonteiroweb","download_url":"https://codeload.github.com/adrianomonteiroweb/store-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrianomonteiroweb%2Fstore-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33160168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T22:39:12.733Z","status":"ssl_error","status_checked_at":"2026-05-17T22:39:10.741Z","response_time":107,"last_error":"SSL_read: 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":["api","api-rest","msc","nodejs","rest-api"],"created_at":"2024-11-21T15:44:23.032Z","updated_at":"2026-05-18T00:09:03.164Z","avatar_url":"https://github.com/adrianomonteiroweb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Projeto Store Manager!\n\nProjeto Trybe para desenvolvimento de API utilizando a arquitetura MSC. 🚀\n\n# Sumário\n\n- [Habilidades](#habilidades)\n- [Entregáveis](#entregáveis)\n  - [O que deverá ser desenvolvido](#o-que-deverá-ser-desenvolvido)\n  - [Desenvolvimento](#desenvolvimento)\n  - [Data de entrega](#data-de-entrega)\n- [Instruções para entregar seu projeto](#instruções-para-entregar-seu-projeto)\n  - [Antes de começar a desenvolver](#antes-de-começar-a-desenvolver)\n  - [Durante o desenvolvimento](#durante-o-desenvolvimento)\n- [Como desenvolver](#como-desenvolver)\n  - [Padrões e conexões](#padrões-e-conexões)\n  - [Conexão com o Banco](#conexão-com-o-banco)\n  - [Tabelas](#tabelas)\n- [Requisitos do projeto](#requisitos-do-projeto)\n\n  - [Linter](#linter)\n  - [Lista de requisitos](#lista-de-requisitos)\n\n    `Obrigatórios`\n\n    - [1 - Crie um endpoint para o cadastro de produtos](#1---crie-um-endpoint-para-o-cadastro-de-produtos)\n    - [2 - Crie um endpoint para listar os produtos](#2---crie-um-endpoint-para-listar-os-produtos)\n    - [3 - Crie um endpoint para atualizar um produto](#3---crie-um-endpoint-para-atualizar-um-produto)\n    - [4 - Crie um endpoint para deletar um produto](#4---crie-um-endpoint-para-deletar-um-produto)\n    - [5 - Crie um endpoint para cadastrar vendas](#5---crie-um-endpoint-para-cadastrar-vendas)\n    - [6 - Crie um endpoint para listar as vendas](#6---crie-um-endpoint-para-listar-as-vendas)\n    - [7 - Crie um endpoint para atualizar uma venda](#7---crie-um-endpoint-para-atualizar-uma-venda)\n    - [8 - Crie um endpoint para deletar uma venda](#8---crie-um-endpoint-para-deletar-uma-venda)\n    - [9 - Atualize a quantidade de produtos](#9---atualize-a-quantidade-de-produtos)\n    - [10 - Valide a quantidade de produtos](#10---valide-a-quantidade-de-produtos)\n\n    `Bônus`\n\n    - [11 - Escreva testes para seus models](#11---escreva-testes-para-seus-models)\n    - [12 - Escreva testes para seus services](#12---escreva-testes-para-seus-services)\n    - [13 - Escreva testes para seus controllers](#13---escreva-testes-para-seus-controllers)\n\n- [Depois de terminar o desenvolvimento](#depois-de-terminar-o-desenvolvimento)\n- [Revisando um pull request](#revisando-um-pull-request)\n- [Avisos Finais](#avisos-finais)\n\n---\n\n# Habilidades\n\nNesse projeto, você será capaz de:\n\n- Entender o funcionamento da camada de Model;\n- Delegar responsabilidades específicas para essa camada;\n- Conectar sua aplicação com diferentes bancos de dados;\n- Estruturar uma aplicação em camadas;\n- Delegar responsabilidades específicas para cada parte do seu app;\n- Melhorar manutenibilidade e reusabilidade do seu código;\n- Entender e aplicar os padrões REST;\n- Escrever assinaturas para APIs intuitivas e facilmente entendíveis.\n\n# Entregáveis\n\nPara entregar o seu projeto você deverá criar um Pull Request neste repositório.\n\nLembre-se que você pode consultar nosso conteúdo sobre\n[Git \u0026 GitHub](https://course.betrybe.com/intro/git/) sempre que precisar!\n\n---\n\n## O que deverá ser desenvolvido\n\nVocê vai desenvolver sua primeira API utilizando a arquitetura MSC!\n\nA API a ser construída trata-se de um sistema de gerenciamento de vendas, onde será possível criar, visualizar, deletar e atualizar produtos e vendas.\n\n---\n\n## Desenvolvimento\n\nVocê vai desenvolver todas as camadas da API (Models, Services caso necessário, e Controllers).\n\nAtravés dessa aplicação, será possível realizar as operações básicas que se pode fazer em um determinado banco de dados: Criação, Leitura, Atualização e Exclusão (ou `CRUD`, para as pessoas mais mais íntimas 😜).\n\nVocê deve utilizar o banco MongoDB para a gestão de dados. Além disso, a API deve ser RESTful.\n\n⚠️ **Dicas Importantes** ⚠️:\n\n- Deve ser possível que a pessoa usuária, independente de cadastramento ou login, possa adicionar, ler, deletar e atualizar produtos no seu estoque. O usuário deve poder também enviar vendas para o sistema. Essas vendas devem validar se o produto em questão existe. Deve, também, ser possível ler, deletar e atualizar vendas.\n\n- Para **todos os endpoints** garanta que:\n\n  - Caso o recurso não seja encontrado, sua API retorne o status HTTP adequado com o body `{ message: '\u003crecurso\u003e não encontrado' }`.\n  - Em caso de erro, sua API retorne o status HTTP adequado com o body `{ err: { message: \u003cmensagem de erro\u003e, code: \u003ccódigo do erro\u003e } }`.\n    - O código do erro deve ser determinado por você e deve seguir o mesmo padrão para toda a aplicação. Por exemplo: `'not_found'`, `'invalid_data'` e afins.\n  - Em caso de dados inválidos, sua API retorne o status HTTP adequado, com o body `{ err: { message: 'Dados inválidos', code: \u003ccódigo do erro\u003e } }`.\n  - Todos os retornos de erro devem seguir o mesmo formato. Para erros que requerem dados adicionais (por exemplo, para informar quais campos estão incorretos) utilize a propriedade `data` dentro do objeto `err`.\n  - Para gerar os objetos de erro personalizados, você pode utilizar uma biblioteca de erros, como o [`boom`](https://www.npmjs.com/package/@hapi/boom).\n\n- Você pode utilizar middlewares e objetos de erro personalizados para que não tenha que repetir a lógica de tratamento de erro em vários lugares. Não se esqueça também do [express-rescue](https://www.npmjs.com/package/express-rescue), ele pode facilitar muito o trabalho de tratar erros.\n\n- Quando estiver na dúvida sobre qual status HTTP utilizar, você pode consultar sites como o [httpstatuses.com](https://httpstatuses.com/), [restapitutorial.com](https://www.restapitutorial.com/httpstatuscodes.html) ou a [documentação sobre o assunto no MDN](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status). Com o tempo, você vai lembrar com facilidade o significado dos códigos mais comuns.\n\n- Para realizar a validação dos dados, você pode utilizar middlewares como [`Joi`](https://www.npmjs.com/package/@hapi/joi) ou o [`Expresso Validator`](https://www.npmjs.com/package/@expresso/validator). Caso prefira, você também pode realizar a validação de forma manual.\n\n# Como desenvolver\n\n## Padrões e conexões\n\n## ⚠️ Leia-os atentamente e siga à risca o que for pedido. ⚠️\n\n### Todos os seus endpoints devem estar no padrão REST\n\n- Use os verbos HTTP adequados para cada operação.\n\n- Agrupe e padronize suas URL em cada recurso.\n\n- Garanta que seus endpoints sempre retornem uma resposta, havendo sucesso nas operações ou não.\n\n- Retorne os códigos de status corretos (recurso criado, erro de validação, autorização, etc).\n\n### Cada camada da sua API deve estar em sua respectiva pasta\n\n- Models devem estar na pasta `models`, **na raiz do projeto**\n\n- Services devem estar na pasta `services`, **na raiz do projeto**\n\n- Controllers devem estar na pasta `controllers`, **na raiz do projeto**\n\n### Arquivo index.js\n\nHá um arquivo `index.js` no repositório. Não remova, nele, o seguinte trecho de código:\n\n```javascript\napp.get(\"/\", (request, response) =\u003e {\n  response.send();\n});\n```\n\nIsso está configurado para o avaliador funcionar.\n\n### Conexão com o Banco:\n\n**⚠️ IMPORTANTE! ⚠️**\n\nO avaliador não consegue ler as informações que estão no local (localhost).\nPortanto, para realizar a conexão com o banco, utilize os seguintes parâmetros:\n\n```javascript\nrequire(\"dotenv\").config();\nconst MONGO_DB_URL = `mongodb://${\n  process.env.HOST || \"mongodb\"\n}:27017/StoreManager`;\nconst DB_NAME = \"StoreManager\";\n```\n\nAlém disso, **renomeie o arquivo `.env.dev` para `.env`**.\n\nCom essas configurações, enquanto estiver na máquina local, o banco será executado normalmente via localhost (possibilitando os testes via `npm test`).\nComo o arquivo `.env` não será enviado para o GitHub (não se preocupe com isso, pois já está configurado no `.gitignore`), o avaliador não executará o banco via localhost e realizará a avaliação corretamente.\n\n### Tabelas\n\nO banco terá duas tabelas: produtos e vendas\n\nA tabela de produtos deverá ter o seguinte nome: `products`\n\nOs campos da tabela `products` terão esse formato:\n\n```json\n{ \"name\": \"Produto Silva\", \"quantity\": 10 }\n```\n\nA resposta do insert que deve retornar após a criação é parecida essa:\n\n```json\n{ \"_id\": ObjectId(\"5f43cbf4c45ff5104986e81d\"), \"name\": \"Produto Silva\", \"quantity\": 10 }\n```\n\n(O \\_id será gerado automaticamente)\n\nA tabela de vendas deverá ter o seguinte nome: `sales`\n\nOs campos da tabela `sales` terão esse formato:\n\n```json\n{ \"itensSold\": [{ \"productId\": \"5f43cbf4c45ff5104986e81d\", \"quantity\": 2 }] }\n```\n\nA resposta do insert que deve retornar após a criação é parecida essa:\n\n```json\n{\n  \"_id\": ObjectId(\"5f43cc53c45ff5104986e81e\"),\n  \"itensSold\": [{ \"productId\": \"5f43cbf4c45ff5104986e81d\", \"quantity\": 2 }]\n}\n```\n\n(O \\_id será gerado automaticamente)\n\n# Requisitos do projeto\n\n## Linter\n\nUsaremos o [ESLint](https://eslint.org/) para fazer a análise estática do seu código.\n\nEste projeto já vem com as dependências relacionadas ao _linter_ configuradas no arquivos `package.json`.\n\nPara poder rodar os `ESLint` em um projeto basta executar o comando `npm install` dentro do projeto e depois `npm run lint`. Se a análise do `ESLint` encontrar problemas no seu código, tais problemas serão mostrados no seu terminal. Se não houver problema no seu código, nada será impresso no seu terminal.\n\nVocê pode também instalar o plugin do `ESLint` no `VSCode`, bastar ir em extensions e baixar o [plugin `ESLint`](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint).\n\n---\n\n## Testes\n\nUsaremos o [Jest]() e o [Frisby] para fazer os testes de api.\n\nEste projeto já vem configurado e com suas dependências\n\nPara poder executar os testes basta executar comando `npm tests` e o resultado será igual o abaixo:\n\n![Testes](./public/testejestfrisby.png)\n\n## Dica: desativando testes\n\nEspecialmente no início, quando a maioria dos testes está falhando, a saída após executar os testes é bastante poluída. Você pode desabilitar temporariamente um teste utilizando a função `skip` junto à função `it`. Como o nome indica, esta função \"pula\" um teste:\n\n```js\nit.skip(\"it includes the text `Movie Cards Library` inside a h1 tag\", () =\u003e {\n  wrapper = shallow(\u003cHeader /\u003e);\n\n  expect(wrapper.find(\"header h1\").text()).toBe(\"Movie Cards Library\");\n});\n```\n\nNa saída da execução dos testes, você verá um \u003cimg src=\"./public/orange-circle.png\" width=\"15px\"\u003e indicando que o teste está sendo pulado:\n\n![image](./public/skipped-test.png)\n\nUma estratégia é pular todos os testes no início e ir implementando um teste de cada vez, removendo dele a função `skip`.\n\n⚠️ Lembre-se de não entregar o projeto com nenhum teste ignorado. Testes ignorados serão tratados como testes falhando.\n\n## Lista de requisitos\n\n### 1 - Crie um endpoint para o cadastro de produtos\n\n- O endpoint deve ser acessível através do caminho (`/products`);\n\n- Os produtos enviados devem ser salvos em uma **collection** do MongoDB;\n\n- O endpoint deve receber a seguinte estrutura:\n\n```json\n{\n  \"name\": \"product_name\",\n  \"quantity\": \"product_quantity\"\n}\n```\n\nO retorno da API de um produto cadastrado com sucesso deverá ser:\n\n```json\n{\n  \"_id\": \"5f43a7ca92d58904914656b6\",\n  \"name\": \"Produto do Batista\",\n  \"quantity\": 100\n}\n```\n\n#### Requisição de Cadastro de Produtos:\n\nO projeto deve rodar na porta `http://localhost:3000`\n\n![Criar produtos](./public/criarProdutos.png)\n\n#### Observações Técnicas:\n\n- `name` deve ser uma _string_ com mais de 5 caracteres e deve ser único;\n\n- `quantity` deve ser um número inteiro maior que 0;\n\n- Cada produto deve ter um id que seja único e gerado no momento em que o recurso for criado. Você pode utilizar o ID gerado pelo MongoDB\n\n- A resposta do endpoint em caso de sucesso deve ser o produto criado.\n\n**O que será verificado:**\n\n- Será validado que não é possível criar um produto com o nome menor que 5 caracteres\n  - Se o produto tiver o nome menor que cinco caracteres o resultado retornado deverá ser conforme exibido abaixo, com um status http `422`:\n\n![Nome menor que 5](./public/nomeMenorQue5.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que não é possível criar um produto com o mesmo nome de outro já existente\n\n  - Se o produto tiver o mesmo nome o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Mesmo nome](./public/mesmonome.png)\n\n- Será validado que não é possível criar um produto com quantidade menor que zero\n\n  - Se o produto tiver uma quantidade menor que zero o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Menor que 0](./public/menorque0.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que não é possível criar um produto com quantidade igual a zero\n\n  - Se o produto tiver uma quantidade igual a zero o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Igual a zero](./public/igualazero.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que não é possível criar um produto com uma string no campo quantidade\n\n  - Se o produto tiver uma quantidade com o valor em string o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Quantidade como string](./public/quantidadecomostring.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que é possível criar um produto com sucesso\n\n  - Se o produto for cadastrado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com status http `201`:\n\n![Criar produtos](./public/criarProdutos.png)\n\n### 2 - Crie um endpoint para listar os produtos\n\n- O endpoint deve ser acessível através do caminho (`/products`) ou (`/products/:id`);\n\n- Através do caminho `/products`, todos os produtos devem ser retornados;\n\n- Através do caminho `/products/:id`, apenas o produto com o `id` presente na URL deve ser retornado;\n\n**O que será verificado:**\n\n- Será validado que todos produtos estão sendo retornados\n\n  - Se a lista retornar com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Lista de produtos](./public/listadeprodutos.png)\n\n- Será validado que é possível listar um determinado produto\n\n  - Se a lista retornar com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Listar um produto](./public/produtoespecifico.png)\n\n- Será validado que não é possível listar um produto que não existe\n\n  - Se a lista retornar com falha, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Produto não existe](./public/produtonaoexiste.png)\n\n### 3 - Crie um endpoint para atualizar um produto\n\n- O endpoint deve ser acessível através do caminho (`/products/:id`);\n\n- O corpo da requisição deve seguir a mesma estrutura do método responsável por adicionar um produto;\n\n- Apenas o produto com o `id` presente na URL deve ser atualizado;\n\n**O que será verificado:**\n\n- Será validado que não é possível atualizar um produto com o nome menor que 5 caracteres\n\n  - Se o produto tiver o nome menor que cinco caracteres, o resultado retornado deverá ser conforme exibido abaixo, com status `422`:\n\n![Atualizar com nome menor que cinco](./public/atualizarcomnomemenorque5.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que não é possível atualizar um produto com quantidade menor que zero\n\n  - Se o produto tiver o quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Atualizar menor que zero](./public/atualizarmenorque0.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que não é possível atualizar um produto com quantidade igual a zero\n\n  - Se o produto tiver o quantidade igual a zero, o resultado mostrado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Atualizar igual a zero](./public/atualizarigual0.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que não é possível atualizar um produto com uma string no campo quantidade\n\n  - Se o produto tiver o quantidade como string, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Atualizar com string](./public/atualizarcomostring.png)\n(As contrabarras `\\` estão escapando as aspas de dentro da string)\n\n- Será validado que é possível atualizar um produto com sucesso]\\*\\*\n\n  - Se o produto atualizado com sucesso, o resultado mostrretornadoado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Atualizado com sucesso](./public/atualizarcomsucesso.png)\n\n### 4 - Crie um endpoint para deletar um produto\n\n- O endpoint deve ser acessível através do caminho (`/products/:id`);\n\n- Apenas o produto com o `id` presente na URL deve ser deletado;\n\n**O que será verificado:**\n\n- Será validado que é possível deletar um produto com sucesso\n\n  - Se o produto deletado com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Deletar um produto](./public/deletarumproduto.png)\n\n- Será validado que não é possível deletar um produto que não existe\n\n  - Se o produto não for deletado com sucesso, o resultado retornado deverá ser esse e com status http `422`:\n\n![Deletar um produto que não existe](./public/deletarumprodutoquenaoexiste.png)\n\n### 5 - Crie um endpoint para cadastrar vendas\n\n- O endpoint deve ser acessível através do caminho (`/sales`);\n\n- As vendas enviadas devem ser salvas em uma `collection` do MongoDB;\n\n- Deve ser possível cadastrar a venda de vários produtos através da uma mesma requisição;\n\n- O endpoint deve receber a seguinte estrutura:\n\n```json\n[\n  {\n  \"productId\": \"product_id\",\n  \"quantity\": \"product_quantity\",\n  },\n  ...\n]\n```\n\nO retorno de uma venda cadastrada com sucesso deverá ser:\n\n```json\n{\n  \"_id\": \"5f43ba333200020b101fe4a0\",\n  \"itensSold\": [\n    {\n      \"productId\": \"5f43ba273200020b101fe49f\",\n      \"quantity\": 2\n    }\n  ]\n}\n```\n\n#### Observações Técnicas:\n\n- O `productId` devem ser igual ao `id` de um produto anteriormente cadastrado;\n\n- `quantity` deve ser um número inteiro maior que 0;\n\n- Cada venda deve ter um id que seja único e gerado no momento em que o recurso for criado;\n\n- A resposta do endpoint em caso de sucesso deve ser a(s) venda(s) criada(s).\n\n**O que será verificado:**\n\n- Será validado que não é possível cadastrar vendas com quantidade menor que zero\n\n  - Se a venda tiver uma quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Vendas menor que zero](./public/comprasmenorquezero.png)\n\n- Será validado que não é possível cadastrar vendas com quantidade igual a zero\n\n  - Se a venda tiver uma quantidade igual a zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Vendas igual a zero](./public/comprasigualazero.png)\n\n- Será validado que não é possível cadastrar vendas com uma string no campo quantidade\n\n  - Se a venda tiver uma quantidade com valor, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Vendas com string](./public/comprascomstring.png)\n\n- Será validado que é possível criar uma venda com sucesso\n\n  - Se a venda foi feita com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Cadastro de venda com sucesso](./public/cadastrodevendacomsucesso.png)\n\n- Será validado que é possível criar várias vendas com sucesso\n\n  - Se as vendas foi feita com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Cadastrar varias compras](./public/variascompras.png)\n\n### 6 - Crie um endpoint para listar as vendas\n\n- O endpoint deve ser acessível através do caminho (`/sales`) ou (`/sales/:id`);\n\n- Através do caminho `/sales`, todas as vendas devem ser retornadas;\n\n- Através do caminho `/sales/:id`, apenas a venda com o `id` presente na URL deve ser retornada;\n\n**O que será verificado:**\n\n- Será validado que todas as vendas estão sendo retornadas\n\n  - Se todas vendas estão sendo listadas, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Listar todas as vendas](./public/todasvendas.png)\n\n- Será validado que é possível listar uma determinada venda\n\n- Se a venda esta sendo listada, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Listar uma venda](./public/listaumavenda.png)\n\n- Será validado que não é possível listar uma venda inexistente\n\n  - Se a venda não esta sendo listada, o resultado retornado deverá ser conforme exibido abaixo, com status http `404`:\n\n![Listar uma venda que não existe](./public/vendanaoexiste.png)\n\n### 7 - Crie um endpoint para atualizar uma venda\n\n- O endpoint deve ser acessível através do caminho (`/sales/:id`);\n\n- O corpo da requisição deve receber a seguinte estrutura:\n\n```json\n[\n  {\n    \"productId\": \"5f3ff849d94d4a17da707008\",\n    \"quantity\": 3\n  }\n]\n```\n\n- `quantity` deve ser um número inteiro maior que 0;\n\n- Apenas a venda com o `id` presente na URL deve ser atualizada;\n\n**O que será verificado:**\n\n- Será validado que não é possível atualizar vendas com quantidade menor que zero\n\n  - Se a venda tiver uma quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Atualizar venda menor que zero](./public/atualizarvendamenorquezero.png)\n\n- Será validado que não é possível atualizar vendas com quantidade igual a zero\n\n  - Se a venda tiver uma quantidade igual a zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Atualizar venda igual zero](./public/atualizarvendaigualzero.png)\n\n- Será validado que não é possível atualizar vendas com uma string no campo quantidade\n\n  - Se a venda tiver uma quantidade do tipo string, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Atualizar venda com string](./public/atualizarvendacomstring.png)\n\n- Será validado que é possível atualizar uma vendas com sucesso\n\n  - Se a venda for atualizada com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:\n\n![Atualizar uma venda com sucesso](./public/atualizarvendacomsucesso.png)\n\n### 8 - Crie um endpoint para deletar uma venda\n\n- O endpoint deve ser acessível através do caminho (`/sales/:id`);\n\n- Apenas a venda com o `id` presente na URL deve ser deletado;\n\n**O que será verificado:**\n\n- Será validado que é possível deletar uma venda com sucesso\n\n  - Se a venda foi deletada sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200` e será verificado depois que a venda não existe, com um GET nesse `id`, e este deverá retornar status http `404`, como é validado no requisito 6:\n\n![Deletar uma venda com sucesso](./public/deletarumavendacomsucesso.png)\n\n- Será validado que não é possível deletar uma venda que não existe\n\n  - Se a venda não foi deletada sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:\n\n![Deletar uma venda que não existe](./public/deletarumavendaquenaoexiste.png)\n\n### 9 - Atualize a quantidade de produtos\n\n- Ao realizar uma venda, atualizá-la ou deletá-la, você deve também atualizar a quantidade do produto em questão presente na `collection` responsável pelos produtos;\n\n- Por exemplo: suponha que haja um produto chamado _Bola de Futebol_ e a sua propriedade `quantity` tenha o valor _10_. Caso seja feita uma venda com _8_ unidades desse produto, a quantidade do produto deve ser atualizada para _2_ , pois 10 - 8 = 2;\n\n**O que será verificado:**\n\n- Será validado que é possível a quantidade do produto atualize ao fazer uma compra\n\n  - Ao fazer uma determinada venda, a quantidade do produto deverá ser atualizada.\n\n- Será validado que é possível a quantidade do produto atualize ao deletar uma compra\n\n  - Ao fazer deletar uma determinada venda, a quantidade do produto deverá ser atualizada para a quantidade que tinha antes de ter feito essa venda.\n\n### 10 - Valide a quantidade de produtos\n\n- Um produto nunca deve ter a quantidade em estoque menor que 0;\n\n- Quando uma venda for realizada, garanta que a quantidade sendo vendida está disponível no estoque\n\n**O que será verificado:**\n\n- Será validado que o estoque do produto nunca fique com a quantidade menor que zero\n\n  - Um produto não poderá ficar com a quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `404`:\n\n![Compra maior que a quantidade](./public/compramaiorqueaquantidade.png)\n\n## Bônus\n\n## 11 - Escreva testes para seus models\n\n- Utilize o mocha, chai e sinon para escrever seus testes\n\n- Coloque todos os testes de models no arquivo `test/unit/models.js`\n\n- Será validado que cobertura total das linhas dos arquivos na pasta `models` é maior ou igual a 60% e ao menos 45 linhas são cobertas pelos testes.\n\n## 12 - Escreva testes para seus services\n\n- Utilize o mocha, chai e sinon para escrever seus testes\n\n- Coloque todos os testes de services no arquivo `test/unit/services.js`\n\n- Será validado que cobertura total das linhas dos arquivos na pasta `services` é maior ou igual a 60% e ao menos 24 linhas são cobertas pelos testes\n\n## 13 - Escreva testes para seus controllers\n\n- Utilize o mocha, chai e sinon para escrever seus testes\n\n- Coloque todos os testes de controllers no arquivo `test/unit/controllers.js`\n\n- Será validado que cobertura total das linhas dos arquivos na pasta `controllers` é maior ou igual a 60% e ao menos 24 linhas são cobertas pelos testes\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrianomonteiroweb%2Fstore-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadrianomonteiroweb%2Fstore-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrianomonteiroweb%2Fstore-manager/lists"}