Initial commit
17
.editorconfig
Normal file
|
@ -0,0 +1,17 @@
|
|||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
# Matches multiple files with brace expansion notation
|
||||
# Set default charset
|
||||
[*.{js,md}]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
2
.eslintignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
test
|
6
.eslintrc.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "trybe-backend",
|
||||
"rules": {
|
||||
"sonarjs/no-duplicate-string": ["error", 5]
|
||||
}
|
||||
}
|
11
.github/CODEOWNERS
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This is a comment.
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence,
|
||||
# @global-owner1 and @global-owner2 will be requested for
|
||||
# review when someone opens a pull request.
|
||||
# * @global-owner1 @global-owner2
|
||||
|
||||
|
||||
* @tryber/pr-locker
|
105
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dispatch_token:
|
||||
description: 'Token that authorize the dispatch'
|
||||
required: true
|
||||
head_sha:
|
||||
description: 'Head commit SHA that dispatched the workflow'
|
||||
required: true
|
||||
pr_author_username:
|
||||
description: 'Pull Request author username'
|
||||
required: true
|
||||
pr_number:
|
||||
description: 'Pull Request number that dispatched the workflow'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
evaluator:
|
||||
runs-on: self-hosted
|
||||
name: Evaluator
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo
|
||||
ports:
|
||||
- "27017:27017"
|
||||
options: -v ${{ github.workspace }}:/github/workspace
|
||||
steps:
|
||||
- name: Fetch project repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Fetch Blocked Files Checkout action
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: betrybe/blocked-files-checkout-action
|
||||
ref: v2
|
||||
token: ${{ secrets.GIT_HUB_PAT }}
|
||||
path: .github/actions/blocked-files-checkout
|
||||
|
||||
- name: Fetch ESLint evaluator
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: betrybe/eslint-linter-action
|
||||
ref: v3
|
||||
token: ${{ secrets.GIT_HUB_PAT }}
|
||||
path: .github/actions/eslint-evaluator
|
||||
|
||||
- name: Fetch Stylelint evaluator
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: betrybe/stylelint-linter-action
|
||||
ref: v2.1
|
||||
token: ${{ secrets.GIT_HUB_PAT }}
|
||||
path: .github/actions/stylelint-evaluator
|
||||
|
||||
- name: Fetch Jest evaluator
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: betrybe/jest-evaluator-action
|
||||
ref: v9
|
||||
token: ${{ secrets.GIT_HUB_PAT }}
|
||||
path: .github/actions/jest-evaluator
|
||||
|
||||
- name: Fetch Store evaluation
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: betrybe/store-evaluation-action
|
||||
ref: v2
|
||||
token: ${{ secrets.GIT_HUB_PAT }}
|
||||
path: .github/actions/store-evaluation
|
||||
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v1.4.4
|
||||
with:
|
||||
node-version: '12'
|
||||
|
||||
- name: Restore protected files
|
||||
uses: ./.github/actions/blocked-files-checkout
|
||||
with:
|
||||
restore_branch: 'master'
|
||||
|
||||
- name: Run ESLint evaluator
|
||||
uses: ./.github/actions/eslint-evaluator
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr_number: ${{ github.event.inputs.pr_number }}
|
||||
|
||||
- name: Run StyleLint evaluator
|
||||
uses: ./.github/actions/stylelint-evaluator
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr_number: ${{ github.event.inputs.pr_number }}
|
||||
|
||||
- name: Run Jest evaluation
|
||||
id: evaluator
|
||||
uses: ./.github/actions/jest-evaluator
|
||||
with:
|
||||
pr_author_username: ${{ github.event.inputs.pr_author_username }}
|
||||
npm-start: true
|
||||
|
||||
- name: Run Store evaluation
|
||||
uses: ./.github/actions/store-evaluation
|
||||
with:
|
||||
evaluation-data: ${{ steps.evaluator.outputs.result }}
|
||||
environment: staging
|
||||
pr-number: ${{ github.event.inputs.pr_number }}
|
291
.gitignore
vendored
Normal file
|
@ -0,0 +1,291 @@
|
|||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/node,macos,windows,linux,visualstudiocode,intellij
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node,macos,windows,linux,visualstudiocode,intellij
|
||||
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/node,macos,windows,linux,visualstudiocode,intellij
|
56
.trybe/requirements.json
Normal file
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"requirements": [
|
||||
{
|
||||
"description": "1 - Crie um endpoint para o cadastro de produtos",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "2 - Crie um endpoint para listar os produtos",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "3 - Crie um endpoint para atualizar um produto",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "4 - Crie um endpoint para deletar um produto",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "5 - Crie um endpoint para cadastrar vendas",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "6 - Crie um endpoint para listar as vendas",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "7 - Crie um endpoint para atualizar uma venda",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "8 - Crie um endpoint para deletar uma venda",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "9 - Atualize a quantidade de produtos",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "10 - Valide a quantidade de produtos",
|
||||
"bonus": false
|
||||
},
|
||||
{
|
||||
"description": "11 - Escreva testes para seus models",
|
||||
"bonus": true
|
||||
},
|
||||
{
|
||||
"description": "12 - Escreva testes para seus services",
|
||||
"bonus": true
|
||||
},
|
||||
{
|
||||
"description": "13 - Escreva testes para seus controllers",
|
||||
"bonus": true
|
||||
}
|
||||
]
|
||||
}
|
759
README.md
Normal file
|
@ -0,0 +1,759 @@
|
|||
### Termos e acordos
|
||||
|
||||
Ao iniciar este projeto, você concorda com as diretrizes do Código de Ética e Conduta e do Manual da Pessoa Estudante da Trybe
|
||||
|
||||
# Boas vindas ao repositório do projeto Store Manager!
|
||||
|
||||
Você já usa o GitHub diariamente para desenvolver os exercícios, certo? Agora, para desenvolver os projetos, você deverá seguir as instruções a seguir. Fique atento a cada passo, e se tiver qualquer dúvida, nos envie por Slack! #vqv 🚀
|
||||
|
||||
Aqui você vai encontrar os detalhes de como estruturar o desenvolvimento do seu projeto a partir deste repositório, utilizando uma branch específica e um Pull Request para colocar seus códigos.
|
||||
|
||||
---
|
||||
|
||||
# Sumário
|
||||
|
||||
- [Habilidades](#habilidades)
|
||||
- [Entregáveis](#entregáveis)
|
||||
- [O que deverá ser desenvolvido](#o-que-deverá-ser-desenvolvido)
|
||||
- [Desenvolvimento](#desenvolvimento)
|
||||
- [Data de entrega](#data-de-entrega)
|
||||
- [Instruções para entregar seu projeto](#instruções-para-entregar-seu-projeto)
|
||||
- [Antes de começar a desenvolver](#antes-de-começar-a-desenvolver)
|
||||
- [Durante o desenvolvimento](#durante-o-desenvolvimento)
|
||||
- [Como desenvolver](#como-desenvolver)
|
||||
- [Padrões e conexões](#padrões-e-conexões)
|
||||
- [Conexão com o Banco](#conexão-com-o-banco)
|
||||
- [Tabelas](#tabelas)
|
||||
- [Requisitos do projeto](#requisitos-do-projeto)
|
||||
- [Linter](#linter)
|
||||
- [Lista de requisitos](#lista-de-requisitos)
|
||||
|
||||
`Obrigatórios`
|
||||
- [1 - Crie um endpoint para o cadastro de produtos](#1---crie-um-endpoint-para-o-cadastro-de-produtos)
|
||||
- [2 - Crie um endpoint para listar os produtos](#2---crie-um-endpoint-para-listar-os-produtos)
|
||||
- [3 - Crie um endpoint para atualizar um produto](#3---crie-um-endpoint-para-atualizar-um-produto)
|
||||
- [4 - Crie um endpoint para deletar um produto](#4---crie-um-endpoint-para-deletar-um-produto)
|
||||
- [5 - Crie um endpoint para cadastrar vendas](#5---crie-um-endpoint-para-cadastrar-vendas)
|
||||
- [6 - Crie um endpoint para listar as vendas](#6---crie-um-endpoint-para-listar-as-vendas)
|
||||
- [7 - Crie um endpoint para atualizar uma venda](#7---crie-um-endpoint-para-atualizar-uma-venda)
|
||||
- [8 - Crie um endpoint para deletar uma venda](#8---crie-um-endpoint-para-deletar-uma-venda)
|
||||
- [9 - Atualize a quantidade de produtos](#9---atualize-a-quantidade-de-produtos)
|
||||
- [10 - Valide a quantidade de produtos](#10---valide-a-quantidade-de-produtos)
|
||||
|
||||
`Bônus`
|
||||
|
||||
- [11 - Escreva testes para seus models](#11---escreva-testes-para-seus-models)
|
||||
- [12 - Escreva testes para seus services](#12---escreva-testes-para-seus-services)
|
||||
- [13 - Escreva testes para seus controllers](#13---escreva-testes-para-seus-controllers)
|
||||
- [Depois de terminar o desenvolvimento](#depois-de-terminar-o-desenvolvimento)
|
||||
- [Revisando um pull request](#revisando-um-pull-request)
|
||||
- [Avisos Finais](#avisos-finais)
|
||||
|
||||
---
|
||||
|
||||
# Habilidades
|
||||
|
||||
Nesse projeto, você será capaz de:
|
||||
|
||||
- Entender o funcionamento da camada de Model;
|
||||
- Delegar responsabilidades específicas para essa camada;
|
||||
- Conectar sua aplicação com diferentes bancos de dados;
|
||||
- Estruturar uma aplicação em camadas;
|
||||
- Delegar responsabilidades específicas para cada parte do seu app;
|
||||
- Melhorar manutenibilidade e reusabilidade do seu código;
|
||||
- Entender e aplicar os padrões REST;
|
||||
- Escrever assinaturas para APIs intuitivas e facilmente entendíveis.
|
||||
|
||||
# Entregáveis
|
||||
|
||||
Para entregar o seu projeto você deverá criar um Pull Request neste repositório.
|
||||
|
||||
Lembre-se que você pode consultar nosso conteúdo sobre
|
||||
[Git & GitHub](https://course.betrybe.com/intro/git/) sempre que precisar!
|
||||
|
||||
---
|
||||
|
||||
## O que deverá ser desenvolvido
|
||||
|
||||
Você vai desenvolver sua primeira API utilizando a arquitetura MSC!
|
||||
|
||||
A 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.
|
||||
|
||||
---
|
||||
|
||||
## Desenvolvimento
|
||||
|
||||
Você vai desenvolver todas as camadas da API (Models, Services caso necessário, e Controllers).
|
||||
|
||||
Atravé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 😜).
|
||||
|
||||
Você deve utilizar o banco MongoDB para a gestão de dados. Além disso, a API deve ser RESTful.
|
||||
|
||||
⚠️ **Dicas Importantes** ⚠️:
|
||||
|
||||
- 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.
|
||||
|
||||
- Para **todos os endpoints** garanta que:
|
||||
|
||||
- Caso o recurso não seja encontrado, sua API retorne o status HTTP adequado com o body `{ message: '<recurso> não encontrado' }`.
|
||||
- Em caso de erro, sua API retorne o status HTTP adequado com o body `{ err: { message: <mensagem de erro>, code: <código do erro> } }`.
|
||||
- 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.
|
||||
- Em caso de dados inválidos, sua API retorne o status HTTP adequado, com o body `{ err: { message: 'Dados inválidos', code: <código do erro> } }`.
|
||||
- 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`.
|
||||
- Para gerar os objetos de erro personalizados, você pode utilizar uma biblioteca de erros, como o [`boom`](https://www.npmjs.com/package/@hapi/boom).
|
||||
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
- 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.
|
||||
|
||||
---
|
||||
|
||||
## Data de Entrega
|
||||
|
||||
- Serão `X` dias de projeto.
|
||||
- Data de entrega para avaliação final do projeto: `DD/MM/YYYY - 14:00h`.
|
||||
|
||||
---
|
||||
|
||||
# Instruções para entregar seu projeto
|
||||
|
||||
## Antes de começar a desenvolver
|
||||
|
||||
1. Clone o repositório
|
||||
|
||||
- `git clone https://github.com/tryber/sd-0x-store-manager.git`.
|
||||
- Entre na pasta do repositório que você acabou de clonar:
|
||||
- `cd sd-0x-store-manager`
|
||||
|
||||
2. Instale as dependências [**Caso existam**]
|
||||
|
||||
- `npm install`
|
||||
|
||||
Atenção :warning: Não rode o comando npm audit fix! Ele atualiza várias dependências do projeto, e essa atualização gera conflitos com o avaliador.
|
||||
|
||||
3. Crie uma branch a partir da branch `master`
|
||||
|
||||
- Verifique que você está na branch `master`
|
||||
- Exemplo: `git branch`
|
||||
- Se não estiver, mude para a branch `master`
|
||||
- Exemplo: `git checkout master`
|
||||
- Agora crie uma branch à qual você vai submeter os `commits` do seu projeto
|
||||
- Você deve criar uma branch no seguinte formato: `nome-de-usuario-nome-do-projeto`
|
||||
- Exemplo: `git checkout -b joaozinho-sd-0x-store-manager`
|
||||
|
||||
4. Adicione as mudanças ao _stage_ do Git e faça um `commit`
|
||||
|
||||
- Verifique que as mudanças ainda não estão no _stage_
|
||||
- Exemplo: `git status` (deve aparecer listada a pasta _joaozinho_ em vermelho)
|
||||
- Adicione o novo arquivo ao _stage_ do Git
|
||||
- Exemplo:
|
||||
- `git add .` (adicionando todas as mudanças - _que estavam em vermelho_ - ao stage do Git)
|
||||
- `git status` (deve aparecer listado o arquivo _joaozinho/README.md_ em verde)
|
||||
- Faça o `commit` inicial
|
||||
- Exemplo:
|
||||
- `git commit -m 'iniciando o projeto x'` (fazendo o primeiro commit)
|
||||
- `git status` (deve aparecer uma mensagem tipo _nothing to commit_ )
|
||||
|
||||
5. Adicione a sua branch com o novo `commit` ao repositório remoto
|
||||
|
||||
- Usando o exemplo anterior: `git push -u origin joaozinho-sd-0x-store-manager`
|
||||
|
||||
6. Crie um novo `Pull Request` _(PR)_
|
||||
|
||||
- Vá até a página de _Pull Requests_ do [repositório no GitHub](https://github.com/tryber/sd-0x-store-manager/pulls)
|
||||
- Clique no botão verde _"New pull request"_
|
||||
- Clique na caixa de seleção _"Compare"_ e escolha a sua branch **com atenção**
|
||||
- Clique no botão verde _"Create pull request"_
|
||||
- Adicione uma descrição para o _Pull Request_ e clique no botão verde _"Create pull request"_
|
||||
- **Não se preocupe em preencher mais nada por enquanto!**
|
||||
- Volte até a [página de _Pull Requests_ do repositório](https://github.com/tryber/sd-0x-store-manager/pulls) e confira que o seu _Pull Request_ está criado
|
||||
|
||||
---
|
||||
|
||||
## Durante o desenvolvimento
|
||||
|
||||
* ⚠ **PULL REQUESTS COM ISSUES NO LINTER NÃO SERÃO AVALIADAS, ATENTE-SE PARA RESOLVÊ-LAS ANTES DE FINALIZAR O DESENVOLVIMENTO!** ⚠
|
||||
|
||||
* Faça `commits` das alterações que você fizer no código regularmente
|
||||
|
||||
* Lembre-se de sempre após um (ou alguns) `commits` atualizar o repositório remoto
|
||||
|
||||
* Os comandos que você utilizará com mais frequência são:
|
||||
1. `git status` _(para verificar o que está em vermelho - fora do stage - e o que está em verde - no stage)_
|
||||
2. `git add` _(para adicionar arquivos ao stage do Git)_
|
||||
3. `git commit` _(para criar um commit com os arquivos que estão no stage do Git)_
|
||||
5. `git push -u nome-da-branch` _(para enviar o commit para o repositório remoto na primeira vez que fizer o `push` de uma nova branch)_
|
||||
4. `git push` _(para enviar o commit para o repositório remoto após o passo anterior)_
|
||||
|
||||
---
|
||||
|
||||
# Como desenvolver
|
||||
|
||||
## Padrões e conexões
|
||||
|
||||
## ⚠️ Leia-os atentamente e siga à risca o que for pedido. ⚠️
|
||||
|
||||
### Todos os seus endpoints devem estar no padrão REST
|
||||
|
||||
- Use os verbos HTTP adequados para cada operação.
|
||||
|
||||
- Agrupe e padronize suas URL em cada recurso.
|
||||
|
||||
- Garanta que seus endpoints sempre retornem uma resposta, havendo sucesso nas operações ou não.
|
||||
|
||||
- Retorne os códigos de status corretos (recurso criado, erro de validação, autorização, etc).
|
||||
|
||||
### Cada camada da sua API deve estar em sua respectiva pasta
|
||||
|
||||
- Models devem estar na pasta `models`, **na raiz do projeto**
|
||||
|
||||
- Services devem estar na pasta `services`, **na raiz do projeto**
|
||||
|
||||
- Controllers devem estar na pasta `controllers`, **na raiz do projeto**
|
||||
|
||||
### Arquivo index.js
|
||||
|
||||
Há um arquivo `index.js` no repositório. Não remova, nele, o seguinte trecho de código:
|
||||
|
||||
```javascript
|
||||
app.get('/', (request, response) => {
|
||||
response.send();
|
||||
});
|
||||
```
|
||||
|
||||
Isso está configurado para o avaliador funcionar.
|
||||
|
||||
### Conexão com o Banco:
|
||||
|
||||
A conexão do banco local deverá conter os seguintes parâmetros:
|
||||
|
||||
```javascript
|
||||
const MONGO_DB_URL = 'mongodb://localhost:27017/StoreManager';
|
||||
const DB_NAME = 'StoreManager';
|
||||
```
|
||||
|
||||
Para o avaliador funcionar altere a conexão do banco para:
|
||||
|
||||
```javascript
|
||||
const MONGO_DB_URL = 'mongodb://mongodb:27017/StoreManager';
|
||||
const DB_NAME = 'StoreManager';
|
||||
```
|
||||
|
||||
### Tabelas
|
||||
|
||||
O banco terá duas tabelas: produtos e vendas
|
||||
|
||||
A tabela de produtos deverá ter o seguinte nome: `products`
|
||||
|
||||
Os campos da tabela `products` terão esse formato:
|
||||
|
||||
```json
|
||||
{ "name": "Produto Silva", "quantity": 10 }
|
||||
```
|
||||
|
||||
A resposta do insert que deve retornar após a criação é parecida essa:
|
||||
|
||||
```json
|
||||
{ "_id": ObjectId("5f43cbf4c45ff5104986e81d"), "name": "Produto Silva", "quantity": 10 }
|
||||
```
|
||||
|
||||
(O \_id será gerado automaticamente)
|
||||
|
||||
A tabela de vendas deverá ter o seguinte nome: `sales`
|
||||
|
||||
Os campos da tabela `sales` terão esse formato:
|
||||
|
||||
```json
|
||||
{ "itensSold": [{ "productId": "5f43cbf4c45ff5104986e81d", "quantity": 2 }] }
|
||||
```
|
||||
|
||||
A resposta do insert que deve retornar após a criação é parecida essa:
|
||||
|
||||
```json
|
||||
{
|
||||
"_id": ObjectId("5f43cc53c45ff5104986e81e"),
|
||||
"itensSold": [{ "productId": "5f43cbf4c45ff5104986e81d", "quantity": 2 }]
|
||||
}
|
||||
```
|
||||
|
||||
(O \_id será gerado automaticamente)
|
||||
|
||||
# Requisitos do projeto
|
||||
|
||||
## Linter
|
||||
|
||||
Usaremos o [ESLint](https://eslint.org/) para fazer a análise estática do seu código.
|
||||
|
||||
Este projeto já vem com as dependências relacionadas ao _linter_ configuradas no arquivos `package.json`.
|
||||
|
||||
Para 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.
|
||||
|
||||
Você 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).
|
||||
|
||||
---
|
||||
|
||||
## Testes
|
||||
|
||||
Usaremos o [Jest]() e o [Frisby] para fazer os testes de api.
|
||||
|
||||
Este projeto já vem configurado e com suas dependências
|
||||
|
||||
Para poder executar os testes basta executar comando `npm tests` e o resultado será igual o abaixo:
|
||||
|
||||
![Testes](./public/testejestfrisby.png)
|
||||
|
||||
## Dica: desativando testes
|
||||
|
||||
Especialmente 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:
|
||||
|
||||
```js
|
||||
it.skip('it includes the text `Movie Cards Library` inside a h1 tag', () => {
|
||||
wrapper = shallow(<Header />);
|
||||
|
||||
expect(wrapper.find('header h1').text()).toBe('Movie Cards Library');
|
||||
});
|
||||
```
|
||||
|
||||
Na saída da execução dos testes, você verá um <img src="./public/orange-circle.png" width="15px"> indicando que o teste está sendo pulado:
|
||||
|
||||
![image](./public/skipped-test.png)
|
||||
|
||||
Uma estratégia é pular todos os testes no início e ir implementando um teste de cada vez, removendo dele a função `skip`.
|
||||
|
||||
⚠️ Lembre-se de não entregar o projeto com nenhum teste ignorado. Testes ignorados serão tratados como testes falhando.
|
||||
|
||||
## Lista de requisitos
|
||||
|
||||
### 1 - Crie um endpoint para o cadastro de produtos
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/products`);
|
||||
|
||||
- Os produtos enviados devem ser salvos em uma **collection** do MongoDB;
|
||||
|
||||
- O endpoint deve receber a seguinte estrutura:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "product_name",
|
||||
"quantity": "product_quantity"
|
||||
}
|
||||
```
|
||||
|
||||
O retorno da API de um produto cadastrado com sucesso deverá ser:
|
||||
|
||||
```json
|
||||
{
|
||||
"_id": "5f43a7ca92d58904914656b6",
|
||||
"name": "Produto do Batista",
|
||||
"quantity": 100
|
||||
}
|
||||
```
|
||||
|
||||
#### Requisição de Cadastro de Produtos:
|
||||
|
||||
O projeto deve rodar na porta `http://localhost:3000`
|
||||
|
||||
![Criar produtos](./public/criarProdutos.png)
|
||||
|
||||
#### Observações Técnicas:
|
||||
|
||||
- `name` deve ser uma _string_ com mais de 5 caracteres e deve ser único;
|
||||
|
||||
- `quantity` deve ser um número inteiro maior que 0;
|
||||
|
||||
- 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
|
||||
|
||||
- A resposta do endpoint em caso de sucesso deve ser o produto criado.
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que não é possível criar um produto com o nome menor que 5 caracteres
|
||||
- Se o produto tiver o nome menor que cinco caracteres o resultado retornado deverá ser conforme exibido abaixo, com um status http `422`:
|
||||
|
||||
![Nome menor que 5](./public/nomeMenorQue5.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que não é possível criar um produto com o mesmo nome de outro já existente
|
||||
|
||||
- Se o produto tiver o mesmo nome o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Mesmo nome](./public/mesmonome.png)
|
||||
|
||||
- Será validado que não é possível criar um produto com quantidade menor que zero
|
||||
|
||||
- Se o produto tiver uma quantidade menor que zero o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Menor que 0](./public/menorque0.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que não é possível criar um produto com quantidade igual a zero
|
||||
|
||||
- Se o produto tiver uma quantidade igual a zero o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Igual a zero](./public/igualazero.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que não é possível criar um produto com uma string no campo quantidade
|
||||
|
||||
- Se o produto tiver uma quantidade com o valor em string o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Quantidade como string](./public/quantidadecomostring.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que é possível criar um produto com sucesso
|
||||
|
||||
- Se o produto for cadastrado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com status http `201`:
|
||||
|
||||
![Criar produtos](./public/criarProdutos.png)
|
||||
|
||||
### 2 - Crie um endpoint para listar os produtos
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/products`) ou (`/products/:id`);
|
||||
|
||||
- Através do caminho `/products`, todos os produtos devem ser retornados;
|
||||
|
||||
- Através do caminho `/products/:id`, apenas o produto com o `id` presente na URL deve ser retornado;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que todos produtos estão sendo retornados
|
||||
|
||||
- Se a lista retornar com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Lista de produtos](./public/listadeprodutos.png)
|
||||
|
||||
- Será validado que é possível listar um determinado produto
|
||||
|
||||
- Se a lista retornar com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Listar um produto](./public/produtoespecifico.png)
|
||||
|
||||
- Será validado que não é possível listar um produto que não existe
|
||||
|
||||
- Se a lista retornar com falha, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Produto não existe](./public/produtonaoexiste.png)
|
||||
|
||||
### 3 - Crie um endpoint para atualizar um produto
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/products/:id`);
|
||||
|
||||
- O corpo da requisição deve seguir a mesma estrutura do método responsável por adicionar um produto;
|
||||
|
||||
- Apenas o produto com o `id` presente na URL deve ser atualizado;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que não é possível atualizar um produto com o nome menor que 5 caracteres
|
||||
|
||||
- Se o produto tiver o nome menor que cinco caracteres, o resultado retornado deverá ser conforme exibido abaixo, com status `422`:
|
||||
|
||||
![Atualizar com nome menor que cinco](./public/atualizarcomnomemenorque5.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que não é possível atualizar um produto com quantidade menor que zero
|
||||
|
||||
- Se o produto tiver o quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Atualizar menor que zero](./public/atualizarmenorque0.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que não é possível atualizar um produto com quantidade igual a zero
|
||||
|
||||
- Se o produto tiver o quantidade igual a zero, o resultado mostrado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Atualizar igual a zero](./public/atualizarigual0.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que não é possível atualizar um produto com uma string no campo quantidade
|
||||
|
||||
- Se o produto tiver o quantidade como string, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Atualizar com string](./public/atualizarcomostring.png)
|
||||
(As contrabarras `\` estão escapando as aspas de dentro da string)
|
||||
|
||||
- Será validado que é possível atualizar um produto com sucesso]**
|
||||
|
||||
- Se o produto atualizado com sucesso, o resultado mostrretornadoado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Atualizado com sucesso](./public/atualizarcomsucesso.png)
|
||||
|
||||
### 4 - Crie um endpoint para deletar um produto
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/products/:id`);
|
||||
|
||||
- Apenas o produto com o `id` presente na URL deve ser deletado;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que é possível deletar um produto com sucesso
|
||||
|
||||
- Se o produto deletado com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Deletar um produto](./public/deletarumproduto.png)
|
||||
|
||||
- Será validado que não é possível deletar um produto que não existe
|
||||
|
||||
- Se o produto não for deletado com sucesso, o resultado retornado deverá ser esse e com status http `422`:
|
||||
|
||||
![Deletar um produto que não existe](./public/deletarumprodutoquenaoexiste.png)
|
||||
|
||||
### 5 - Crie um endpoint para cadastrar vendas
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/sales`);
|
||||
|
||||
- As vendas enviadas devem ser salvas em uma `collection` do MongoDB;
|
||||
|
||||
- Deve ser possível cadastrar a venda de vários produtos através da uma mesma requisição;
|
||||
|
||||
- O endpoint deve receber a seguinte estrutura:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"productId": "product_id",
|
||||
"quantity": "product_quantity",
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
O retorno de uma venda cadastrada com sucesso deverá ser:
|
||||
|
||||
```json
|
||||
{
|
||||
"_id": "5f43ba333200020b101fe4a0",
|
||||
"itensSold": [
|
||||
{
|
||||
"productId": "5f43ba273200020b101fe49f",
|
||||
"quantity": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Observações Técnicas:
|
||||
|
||||
- O `productId` devem ser igual ao `id` de um produto anteriormente cadastrado;
|
||||
|
||||
- `quantity` deve ser um número inteiro maior que 0;
|
||||
|
||||
- Cada venda deve ter um id que seja único e gerado no momento em que o recurso for criado;
|
||||
|
||||
- A resposta do endpoint em caso de sucesso deve ser a(s) venda(s) criada(s).
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que não é possível cadastrar vendas com quantidade menor que zero
|
||||
|
||||
- Se a venda tiver uma quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Vendas menor que zero](./public/comprasmenorquezero.png)
|
||||
|
||||
- Será validado que não é possível cadastrar vendas com quantidade igual a zero
|
||||
|
||||
- Se a venda tiver uma quantidade igual a zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Vendas igual a zero](./public/comprasigualazero.png)
|
||||
|
||||
- Será validado que não é possível cadastrar vendas com uma string no campo quantidade
|
||||
|
||||
- Se a venda tiver uma quantidade com valor, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Vendas com string](./public/comprascomstring.png)
|
||||
|
||||
- Será validado que é possível criar uma venda com sucesso
|
||||
|
||||
- Se a venda foi feita com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Cadastro de venda com sucesso](./public/cadastrodevendacomsucesso.png)
|
||||
|
||||
- Será validado que é possível criar várias vendas com sucesso
|
||||
|
||||
- Se as vendas foi feita com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Cadastrar varias compras](./public/variascompras.png)
|
||||
|
||||
### 6 - Crie um endpoint para listar as vendas
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/sales`) ou (`/sales/:id`);
|
||||
|
||||
- Através do caminho `/sales`, todas as vendas devem ser retornadas;
|
||||
|
||||
- Através do caminho `/sales/:id`, apenas a venda com o `id` presente na URL deve ser retornada;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que todas as vendas estão sendo retornadas
|
||||
|
||||
- Se todas vendas estão sendo listadas, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Listar todas as vendas](./public/todasvendas.png)
|
||||
|
||||
- Será validado que é possível listar uma determinada venda
|
||||
|
||||
- Se a venda esta sendo listada, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Listar uma venda](./public/listaumavenda.png)
|
||||
|
||||
- Será validado que não é possível listar uma venda inexistente
|
||||
|
||||
- Se a venda não esta sendo listada, o resultado retornado deverá ser conforme exibido abaixo, com status http `404`:
|
||||
|
||||
![Listar uma venda que não existe](./public/vendanaoexiste.png)
|
||||
|
||||
### 7 - Crie um endpoint para atualizar uma venda
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/sales/:id`);
|
||||
|
||||
- O corpo da requisição deve receber a seguinte estrutura:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"productId": "5f3ff849d94d4a17da707008",
|
||||
"quantity": 3
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
- `quantity` deve ser um número inteiro maior que 0;
|
||||
|
||||
- Apenas a venda com o `id` presente na URL deve ser atualizada;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que não é possível atualizar vendas com quantidade menor que zero
|
||||
|
||||
- Se a venda tiver uma quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Atualizar venda menor que zero](./public/atualizarvendamenorquezero.png)
|
||||
|
||||
- Será validado que não é possível atualizar vendas com quantidade igual a zero
|
||||
|
||||
- Se a venda tiver uma quantidade igual a zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Atualizar venda igual zero](./public/atualizarvendaigualzero.png)
|
||||
|
||||
- Será validado que não é possível atualizar vendas com uma string no campo quantidade
|
||||
|
||||
- Se a venda tiver uma quantidade do tipo string, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Atualizar venda com string](./public/atualizarvendacomstring.png)
|
||||
|
||||
- Será validado que é possível atualizar uma vendas com sucesso
|
||||
|
||||
- Se a venda for atualizada com sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `200`:
|
||||
|
||||
![Atualizar uma venda com sucesso](./public/atualizarvendacomsucesso.png)
|
||||
|
||||
### 8 - Crie um endpoint para deletar uma venda
|
||||
|
||||
- O endpoint deve ser acessível através do caminho (`/sales/:id`);
|
||||
|
||||
- Apenas a venda com o `id` presente na URL deve ser deletado;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que é possível deletar uma venda com sucesso
|
||||
|
||||
- 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:
|
||||
|
||||
![Deletar uma venda com sucesso](./public/deletarumavendacomsucesso.png)
|
||||
|
||||
- Será validado que não é possível deletar uma venda que não existe
|
||||
|
||||
- Se a venda não foi deletada sucesso, o resultado retornado deverá ser conforme exibido abaixo, com status http `422`:
|
||||
|
||||
![Deletar uma venda que não existe](./public/deletarumavendaquenaoexiste.png)
|
||||
|
||||
### 9 - Atualize a quantidade de produtos
|
||||
|
||||
- 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;
|
||||
|
||||
- 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;
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que é possível a quantidade do produto atualize ao fazer uma compra
|
||||
|
||||
- Ao fazer uma determinada venda, a quantidade do produto deverá ser atualizada.
|
||||
|
||||
- Será validado que é possível a quantidade do produto atualize ao deletar uma compra
|
||||
|
||||
- Ao fazer deletar uma determinada venda, a quantidade do produto deverá ser atualizada para a quantidade que tinha antes de ter feito essa venda.
|
||||
|
||||
### 10 - Valide a quantidade de produtos
|
||||
|
||||
- Um produto nunca deve ter a quantidade em estoque menor que 0;
|
||||
|
||||
- Quando uma venda for realizada, garanta que a quantidade sendo vendida está disponível no estoque
|
||||
|
||||
**O que será verificado:**
|
||||
|
||||
- Será validado que o estoque do produto nunca fique com a quantidade menor que zero
|
||||
|
||||
- Um produto não poderá ficar com a quantidade menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com status http `404`:
|
||||
|
||||
![Compra maior que a quantidade](./public/compramaiorqueaquantidade.png)
|
||||
|
||||
## Bônus
|
||||
|
||||
## 11 - Escreva testes para seus models
|
||||
|
||||
- Utilize o mocha, chai e sinon para escrever seus testes
|
||||
|
||||
- Coloque todos os testes de models no arquivo `test/unit/models.js`
|
||||
|
||||
- Será validado que cobertura total das linhas dos arquivos na pasta `models` é maior ou igual a 80%
|
||||
|
||||
## 12 - Escreva testes para seus services
|
||||
|
||||
- Utilize o mocha, chai e sinon para escrever seus testes
|
||||
|
||||
- Coloque todos os testes de services no arquivo `test/unit/services.js`
|
||||
|
||||
- Será validado que cobertura total das linhas dos arquivos na pasta `services` é maior ou igual a 80%
|
||||
|
||||
## 13 - Escreva testes para seus controllers
|
||||
|
||||
- Utilize o mocha, chai e sinon para escrever seus testes
|
||||
|
||||
- Coloque todos os testes de controllers no arquivo `test/unit/controllers.js`
|
||||
|
||||
- Será validado que cobertura total das linhas dos arquivos na pasta `controllers` é maior ou igual a 80%
|
||||
|
||||
---
|
||||
|
||||
## Depois de terminar o desenvolvimento
|
||||
|
||||
Para **"entregar"** seu projeto, siga os passos a seguir:
|
||||
|
||||
* Vá até a página **DO SEU** _Pull Request_, adicione a label de _"code-review"_ e marque seus colegas
|
||||
* No menu à direita, clique no _link_ **"Labels"** e escolha a _label_ **code-review**
|
||||
* No menu à direita, clique no _link_ **"Assignees"** e escolha **o seu usuário**
|
||||
* No menu à direita, clique no _link_ **"Reviewers"** e digite `students`, selecione o time `tryber/students-sd-00`
|
||||
|
||||
Se ainda houver alguma dúvida sobre como entregar seu projeto, [aqui tem um video explicativo](https://vimeo.com/362189205).
|
||||
|
||||
⚠ Lembre-se que garantir que todas as _issues_ comentadas pelo **Lint** estão resolvidas! ⚠
|
||||
|
||||
---
|
||||
|
||||
## Revisando um pull request
|
||||
|
||||
À medida que você e as outras pessoas que estudam na Trybe forem entregando os projetos, vocês receberão um alerta via Slack para também fazer a revisão dos Pull Requests dos seus colegas. Fiquem atentos às mensagens do "Pull Reminders" no Slack!
|
||||
|
||||
Use o material que você já viu sobre [Code Review](https://course.betrybe.com/real-life-engineer/code-review/) para te ajudar a revisar os projetos que chegaram para você.
|
||||
|
||||
---
|
||||
|
||||
# Avisos finais
|
||||
|
||||
Ao finalizar e submeter o projeto, não se esqueça de avaliar sua experiência preenchendo o formulário. Leva menos de 3 minutos!
|
||||
|
||||
Link: [FORMULÁRIO DE AVALIAÇÃO DE PROJETO](https://be-trybe.typeform.com/to/ZTeR4IbH)
|
||||
|
||||
O avaliador automático não necessariamente avalia seu projeto na ordem em que os requisitos aparecem no readme. Isso acontece para deixar o processo de avaliação mais rápido. Então, não se assuste se isso acontecer, ok?
|
4
index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
// não remova esse endpoint, e para o avaliador funcionar
|
||||
app.get('/', (_request, response) => {
|
||||
response.send();
|
||||
});
|
24018
package-lock.json
generated
Normal file
43
package.json
Normal file
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "sd-0x-store-manager",
|
||||
"version": "1.0.0",
|
||||
"description": "Simple CRUD to sales and products",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "jest --runInBand",
|
||||
"test:mocha": "nyc --all --include models --include services --include controllers mocha test/unit/*.js --exit",
|
||||
"start": "nodemon index.js",
|
||||
"lint": "eslint --no-inline-config --no-error-on-unmatched-pattern -c .eslintrc.json . --ext .js, .jsx"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tryber/sd-02-project-store-manager.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tryber/sd-02-project-store-manager/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tryber/sd-02-project-store-manager#readme",
|
||||
"dependencies": {
|
||||
"@hapi/boom": "^9.1.0",
|
||||
"@hapi/joi": "^17.1.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"express-rescue": "^1.1.26",
|
||||
"faker": "^4.1.0",
|
||||
"frisby": "^2.1.2",
|
||||
"jest": "^26.4.1",
|
||||
"mongodb": "^3.5.9",
|
||||
"nodemon": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.3.4",
|
||||
"eslint-config-trybe-backend": "^1.0.3",
|
||||
"mocha": "^8.4.0",
|
||||
"mongodb-memory-server": "^6.9.6",
|
||||
"nyc": "^15.1.0",
|
||||
"sinon": "^11.1.1"
|
||||
}
|
||||
}
|
BIN
public/atualizarcomnomemenorque5.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
public/atualizarcomostring.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
public/atualizarcomsucesso.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
public/atualizarigual0.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
public/atualizarmenorque0.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
public/atualizarvendacomstring.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
public/atualizarvendacomsucesso.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
public/atualizarvendaigualzero.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
public/atualizarvendamenorquezero.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
public/cadastrodevendacomsucesso.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
public/compramaiorqueaquantidade.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
public/comprascomstring.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
public/comprasigualazero.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
public/comprasmenorquezero.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
public/criarProdutos.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
public/deletarumavendacomsucesso.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
public/deletarumavendaquenaoexiste.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
public/deletarumproduto.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
public/deletarumprodutoquenaoexiste.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
public/igualazero.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
public/listadeprodutos.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
public/listarumproduto.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
public/listaumavenda.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
public/menorque0.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
public/mesmonome.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
public/nomeMenorQue5.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
public/orange-circle.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
public/produtoespecifico.png
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
public/produtonaoexiste.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
public/quantidadecomostring.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
public/skipped-test.png
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
public/testejestfrisby.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
public/todasvendas.png
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
public/variascompras.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
public/vendanaoexiste.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
public/vendanaoexistente.png
Normal file
After Width: | Height: | Size: 55 KiB |
61
test/bonus.test.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
const fs = require('fs').promises;
|
||||
const util = require('util');
|
||||
const { exec: callbackExec } = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
const exec = util.promisify(callbackExec);
|
||||
|
||||
const mongoDbUrl = 'mongodb://localhost:27017';
|
||||
const url = 'http://localhost:3000';
|
||||
const NPX_NYC_COMMAND =
|
||||
(unit) => `npx nyc --all --include ${unit} --reporter json-summary mocha test/unit/${unit}.js --exit`;
|
||||
|
||||
function readCoverageFile() {
|
||||
const COVERAGE_FILE_PATH = path.join(__dirname, '..', 'coverage', 'coverage-summary.json');
|
||||
return fs.readFile(COVERAGE_FILE_PATH).then(JSON.parse);
|
||||
}
|
||||
|
||||
describe('11 - Escreva testes para seus models', () => {
|
||||
beforeAll(async () => {
|
||||
await exec(NPX_NYC_COMMAND('models'));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await exec('rm -rf coverage .nyc_output');
|
||||
});
|
||||
|
||||
it('Será validado que cobertura total das linhas dos arquivos na pasta `models` é maior ou igual a 80%', async () => {
|
||||
const coverageResults = await readCoverageFile();
|
||||
expect(coverageResults.total.lines.pct).toBeGreaterThanOrEqual(80);
|
||||
});
|
||||
});
|
||||
|
||||
describe('12 - Escreva testes para seus services', () => {
|
||||
beforeAll(async () => {
|
||||
await exec(NPX_NYC_COMMAND('services'));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await exec('rm -rf coverage .nyc_output');
|
||||
});
|
||||
|
||||
it('Será validado que cobertura total das linhas dos arquivos na pasta `services` é maior ou igual a 80%', async () => {
|
||||
const coverageResults = await readCoverageFile();
|
||||
expect(coverageResults.total.lines.pct).toBeGreaterThanOrEqual(80);
|
||||
});
|
||||