-
CRUD de Categorias [Create|Read]
- GET
/categories
- POST
/categories
- Regras de Negócio
-
name
não pode estar vazio ⇒ nesse caso, deve retornar status 400 -
name
não pode ser um nome de categoria já existente ⇒ nesse caso deve retornar status 409
-
- Regras de Negócio
- GET
-
CRUD de Jogos [Create|Read]
- GET
/games
- Regras de Negócio
- Caso seja passado um parâmetro
name
na query string da requisição, os jogos devem ser filtrados para retornar somente os que começam com a string passada (case insensitive). Exemplo:- Para a rota
/games?name=ba
, deve ser retornado uma array somente com os jogos que comecem com "ba", como "Banco Imobiliário", "Batalha Naval", etc
- Para a rota
- Caso seja passado um parâmetro
- Regras de Negócio
- POST
/games
- Regras de Negócio
-
name
não pode estar vazio;stockTotal
epricePerDay
devem ser maiores que 0;categoryId
deve ser um id de categoria existente; ⇒ nesses casos, deve retornar status 400 -
name
não pode ser um nome de jogo já existente ⇒ nesse caso deve retornar status 409
-
- Regras de Negócio
- GET
-
CRUD de Clientes [Create|Read|Update]
-
GET
/customers
- Regras de Negócio
- Caso seja passado um parâmetro
cpf
na query string da requisição, os clientes devem ser filtrados para retornar somente os com CPF que comecem com a string passada.
- Caso seja passado um parâmetro
- Regras de Negócio
-
GET
/customers/:id
- Regras de Negócio:
- Se o cliente com id dado não existir, deve responder com status 404
- Regras de Negócio:
-
POST
/customers
- Regras de negócio
-
cpf
deve ser uma string com 11 caracteres numéricos;phone
deve ser uma string com 10 ou 11 caracteres numéricos;name
não pode ser uma string vazia;birthday
deve ser uma data válida; ⇒ nesses casos, deve retornar status 400 -
cpf
não pode ser de um cliente já existente; ⇒ nesse caso deve retornar status 409
-
- Regras de negócio
-
PUT
/customers/:id
- Regras de negócio:
-
cpf
deve ser uma string com 11 caracteres numéricos;phone
deve ser uma string com 10 ou 11 caracteres numéricos;name
não pode ser uma string vazia;birthday
deve ser uma data válida ⇒ nesses casos, deve retornar status 400 -
cpf
não pode ser de um cliente já existente ⇒ nesse caso deve retornar status 409
-
- Regras de negócio:
-
-
CRUD de Aluguéis [Create|Read|Update|Delete]
Schema
-
Formato de um aluguel (tabela
rentals
){ id: 1, customerId: 1, gameId: 1, rentDate: '2021-06-20', // data em que o aluguel foi feito daysRented: 3, // por quantos dias o cliente agendou o aluguel returnDate: null, // data que o cliente devolveu o jogo (null enquanto não devolvido) originalPrice: 4500, // preço total do aluguel em centavos (dias alugados vezes o preço por dia do jogo) delayFee: null // multa total paga por atraso (dias que passaram do prazo vezes o preço por dia do jogo) }
- GET
/rentals
- Response: lista com todos os aluguéis, contendo o
customer
e ogame
do aluguel em questão em cada aluguel[ { id: 1, customerId: 1, gameId: 1, rentDate: "2021-06-20", daysRented: 3, returnDate: null, // troca pra uma data quando já devolvido originalPrice: 4500, delayFee: null, customer: { id: 1, name: "João Alfredo", }, game: { id: 1, name: "Banco Imobiliário", categoryId: 1, categoryName: "Estratégia", }, }, ];
- Regras de Negócio
- Caso seja passado um parâmetro
customerId
na query string da requisição, os aluguéis devem ser filtrados para retornar somente os do cliente solicitado. Exemplo:- Para a rota
/rentals?customerId=1
, deve ser retornado uma array somente com os aluguéis do cliente com id 1
- Para a rota
- Caso seja passado um parâmetro
gameId
na query string da requisição, os aluguéis devem ser filtrados para retornar somente os do jogo solicitado. Exemplo:- Para a rota
/rentals?gameId=1
, deve ser retornado uma array somente com os aluguéis do jogo com id 1
- Para a rota
- Caso seja passado um parâmetro
- Response: lista com todos os aluguéis, contendo o
- POST
/rentals
- Regras de Negócio
- Ao inserir um aluguel, os campos
rentDate
eoriginalPrice
devem ser populados automaticamente antes de salvá-lo:rentDate
: data atual no momento da inserçãooriginalPrice
:daysRented
multiplicado pelo preço por dia do jogo no momento da inserção
- Ao inserir um aluguel, os campos
returnDate
edelayFee
devem sempre começar comonull
- Ao inserir um aluguel, deve verificar se
customerId
se refere a um cliente existente. Se não, deve responder com status 400 - Ao inserir um aluguel, deve verificar se
gameId
se refere a um jogo existente. Se não, deve responder com status 400 -
daysRented
deve ser um número maior que 0. Se não, deve responder com status 400 - Ao inserir um aluguel, deve-se validar que existem jogos disponíveis, ou seja, que não tem alugueis em aberto acima da quantidade de jogos em estoque. Caso contrário, deve retornar status 400
- Ao inserir um aluguel, os campos
- Regras de Negócio
- POST
/rentals/:id/return
- Regras de Negócio
- Ao retornar um aluguel, o campo
returnDate
deve ser populado com a data atual do momento do retorno - Ao retornar um aluguel, o campo
delayFee
deve ser automaticamente populado com um valor equivalente ao número de dias de atraso vezes o preço por dia do jogo no momento do retorno. - Ao retornar um aluguel, deve verificar se o
id
do aluguel fornecido existe. Se não, deve responder com status 404 - Ao retornar um aluguel, deve verificar se o aluguel já não está finalizado. Se estiver, deve responder com status 400
- Ao retornar um aluguel, o campo
- Regras de Negócio
- DELETE
/rentals/:id
- Regras de Negócio
- Ao excluir um aluguel, deve verificar se o
id
fornecido existe. Se não, deve responder com status 404 - Ao excluir um aluguel, deve verificar se o aluguel já não está finalizado (ou seja,
returnDate
já está preenchido). Se estiver, deve responder com status 400
- Ao excluir um aluguel, deve verificar se o
- Regras de Negócio
-
- Paginação
- GET /categories, /games, /customers, /rentals
- Caso seja passado um parâmetro
offset
na query string da requisição, deve-se obter somente os registros no banco após o offset determinado. Ex: se for passadooffset=20
e existirem 100 produtos no banco, só devem ser retornados os 80 últimos (do 21º ao 100º)- Dica: pesquise por SQL OFFSET
- Caso seja passado um parâmetro
limit
na query string da requisição, deve-se limitar a quantidade de registros retornados a esse limite no máximo. Ex: se for passadolimit=30
e existirem 100 produtos no banco, só devem ser retornados os 30 primeiros - Caso tanto
limit
quantooffset
sejam passados, ambos devem ser aplicados. Ex: se for passadooffset=20&limit=30
, caso existam 100 produtos no banco, só devem ser retornados os produtos do 21º ao 50º.
- Caso seja passado um parâmetro
- GET /categories, /games, /customers, /rentals
- Ordenação
- GET /categories, /games, /customers, /rentals
- Caso seja passado um parâmetro
order
na query string da requisição, deve-se retornar os registros ordenados pela coluna passada em ordem ascendente. Ex: se for passadoorder=name
, os registros devem ser ordenados alfabeticamente pela colunaname
- Caso seja passado também um parâmetro
desc
na query string, deve-se inverter esta ordem para descendente. Ex: se for passadoorder=name&desc=true
, os registros devem ser ordenados alfabeticamente invertidos pela colunaname
- Caso seja passado um parâmetro
- GET /categories, /games, /customers, /rentals
- Filtragem por data
- GET /rentals
- Caso seja passado um parâmetro
status
na query string da requisição, os aluguéis devem ser filtrados para retornar somente aqueles que estão naquele estado. Exemplo:- Para a rota
/rentals?status=open
, deve ser retornado uma array somente com os aluguéis não finalizados - Para a rota
/rentals?status=closed
, deve ser retornado uma array somente com os aluguéis finalizados
- Para a rota
- Caso seja passado um parâmetro
startDate
na query string da requisição, os aluguéis devem ser filtrados para retornar somente os que foram feitos a partir daquela data. Exemplo:- Para a rota
/rentals?startDate=2021-06-10
, deve ser retornado uma array somente com os aluguéis comrentDate
maior ou igual a2021-06-10
- Para a rota
- Caso seja passado um parâmetro
- GET /rentals
- Cálculo de faturamento
- GET /rentals/metrics
- Implemente a nova rota acima que deve calcular:
revenue
: o total de receita da loja (somando todos os preços e taxas recebidas nos aluguéis)rentals
: a quantidade total de aluguéisaverage
: e a média de receita por aluguel (divisão do total da receita pela quantidade de aluguéis)
- Por exemplo, se em toda a história a loja teve de faturamento 1 milhão de reais, que vieram de 50 mil aluguéis, o retorno da rota deveria ser: (em centavos)
Dica: pesquise por SQL Sum e Count
{ revenue: 100000000, rentals: 50000, average: 2000 }
- Caso seja passado um parâmetro
startDate
e/ouendDate
na query string da requisição, as métricas devem ser filtradas para retornar somente dados referentes aos aluguéis comrentDate
dentro desse período (a partir dastartDate
inclusive e/ou até a endDate inclusive)
- Implemente a nova rota acima que deve calcular:
- GET /rentals/metrics
- Quantidade de aluguéis
- GET /games, /customers
- Sem aumentar o número de queries feitas no banco, adicione nos retornos das rotas acima, em uma propriedade
rentalsCount
, a quantidade de aluguéis já feitos para aquele cliente ou daquele jogo. Ex: se um jogo já foi alugado 10 vezes, em cada jogo deve ser incluído um camporentalsCount: 10
- Dica: Pesquise por SQL Count e Group By
- Sem aumentar o número de queries feitas no banco, adicione nos retornos das rotas acima, em uma propriedade
- GET /games, /customers
-
Run the setup script
bash ./server/psql_scripts/create-database
-
Configure DATABASE_URL environment variable in
.env
DATABASE_URL=postgres://role:password@localhost:5432/boardcamp