#carrinho de compras
Pontos-chave
- Neste projeto trabalharemos em termos de recursos. Isso significa que escolhemos um objeto como usuário, livro, blog, etc. de cada vez. Trabalhamos com seu recurso. As etapas seriam:
- Nós criamos seu modelo.
- Nós construímos suas APIs.
- Testamos essas APIs.
- Implantamos essas APIs.
- Integramos essas APIs com frontend.
- Repetiremos as etapas da Etapa 1 à Etapa 5 para cada recurso deste projeto.
- Este projeto está dividido em 4 funcionalidades: Usuário, Produto, Carrinho e Pedido. Você precisa trabalhar em um único recurso de cada vez. Depois que isso for concluído de acordo com as etapas mencionadas acima. Você será instruído a passar para o próximo recurso.
- Neste projeto estamos mudando a forma como enviamos token com uma solicitação. Em vez de usar uma chave de cabeçalho personalizada como x-api-key, você precisa usar o cabeçalho de autorização e enviar o token JWT como token de portador.
- Crie um banco de dados de grupo
groupXDatabase
. Você pode limpar o banco de dados usado anteriormente e retomá-lo. - Desta vez, cada grupo deve ter um único branch git . Coordenem-se entre si, garantindo que cada pessoa seguinte extraia o último código enviado por um colega de equipe. Sua filial será verificada como parte da demonstração. O nome da filial deve seguir a convenção de nomenclatura
project/productsManagementGroupX
- Siga as convenções de nomenclatura exatamente conforme as instruções.
RECURSO I - Usuário
Modelos
{
fname : {string, mandatory},
lname : {string, mandatory},
email : {string, mandatory, valid email, unique},
profileImage : {string, mandatory}, // s3 link
phone : {string, mandatory, unique, valid Indian mobile number},
password : {string, mandatory, minLen 8, maxLen 15}, // encrypted password
address : {
shipping : {
street : {string, mandatory},
city : {string, mandatory},
pincode : {number, mandatory}
},
billing : {
street : {string, mandatory},
city : {string, mandatory},
pincode : {number, mandatory}
}
},
createdAt : {timestamp},
updatedAt : {timestamp}
}
APIs de usuário
POSTAR / registrar
- Crie um documento de usuário a partir do corpo da solicitação. O corpo da solicitação deve conter imagem.
- Faça upload da imagem para o bucket S3 e salve seu URL público no documento do usuário.
- Salve a senha em formato criptografado. (use bcrypt)
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 201. Retorne também o documento do usuário. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
{
" status " : true,
" message " : " User created successfully " ,
" data " : {
" fname " : " John " ,
" lname " : " Doe " ,
" email " : " [email protected] " ,
" profileImage " : " https://classroom-training-bucket.s3.ap-south-1.amazonaws.com/user/copernico-p_kICQCOM4s-unsplash.jpg " ,
" phone " : 9876543210,
" password " : " $2b$10$DpOSGb0B7cT0f6L95RnpWO2P/AtEoE6OF9diIiAEP7QrTMaV29Kmm " ,
" address " : {
" shipping " : {
" street " : " MG Road " ,
" city " : " Indore " ,
" pincode " : 452001
},
" billing " : {
" street " : " MG Road " ,
" city " : " Indore " ,
" pincode " : 452001
}
},
" _id " : " 6162876abdcb70afeeaf9cf5 " ,
" createdAt " : " 2021-10-10T06:25:46.051Z " ,
" updatedAt " : " 2021-10-10T06:25:46.051Z " ,
" __v " : 0
}
}
POSTAR/login
- Permitir que um usuário faça login com seu e-mail e senha.
- Em uma tentativa de login bem-sucedida, retorne o userId e um token JWT contendo o userId, exp, iat.
NOTA: Há uma ligeira alteração no corpo da resposta. Você também deve retornar userId além do token JWT.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200 e o token JWT no corpo da resposta. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
{
" status " : true,
" message " : " User login successfull " ,
" data " : {
" userId " : " 6165f29cfe83625cf2c10a5c " ,
" token " : " eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2MTYyODc2YWJkY2I3MGFmZWVhZjljZjUiLCJpYXQiOjE2MzM4NDczNzYsImV4cCI6MTYzMzg4MzM3Nn0.PgcBPLLg4J01Hyin-zR6BCk7JHBY-RpuWMG_oIK7aV8 "
}
}
GET /user/:userId/profile (autenticação necessária)
- Permitir que um usuário busque detalhes de seu perfil.
- Certifique-se de que o userId no parâmetro url e no token seja o mesmo
- Formato de resposta
- Em caso de sucesso - Retorna o status HTTP 200 e retorna o documento do usuário. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
{
" status " : true,
" message " : " User profile details " ,
" data " : {
" address " : {
" shipping " : {
" street " : " MG Road " ,
" city " : " Indore " ,
" pincode " : 452001
},
" billing " : {
" street " : " MG Road " ,
" city " : " Indore " ,
" pincode " : 452001
}
},
" _id " : " 6162876abdcb70afeeaf9cf5 " ,
" fname " : " John " ,
" lname " : " Doe " ,
" email " : " [email protected] " ,
" profileImage " : " https://classroom-training-bucket.s3.ap-south-1.amazonaws.com/user/copernico-p_kICQCOM4s-unsplash.jpg " ,
" phone " : 9876543210,
" password " : " $2b$10$DpOSGb0B7cT0f6L95RnpWO2P/AtEoE6OF9diIiAEP7QrTMaV29Kmm " ,
" createdAt " : " 2021-10-10T06:25:46.051Z " ,
" updatedAt " : " 2021-10-10T06:25:46.051Z " ,
" __v " : 0
}
}
PUT /user/:userId/profile (autenticação e autorização necessárias)
- Permitir que um usuário atualize seu perfil.
- Um usuário pode atualizar todos os campos
- Certifique-se de que o userId no parâmetro url e no token seja o mesmo
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também o documento do usuário atualizado. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
{
" status " : true,
" message " : " User profile updated " ,
" data " : {
" address " : {
" shipping " : {
" street " : " MG Road " ,
" city " : " Delhi " ,
" pincode " : 110001
},
" billing " : {
" street " : " MG Road " ,
" city " : " Indore " ,
" pincode " : 452010
}
},
" _id " : " 6162876abdcb70afeeaf9cf5 " ,
" fname " : " Jane " ,
" lname " : " Austin " ,
" email " : " [email protected] " ,
" profileImage " : " https://classroom-training-bucket.s3.ap-south-1.amazonaws.com/user/laura-davidson-QBAH4IldaZY-unsplash.jpg " ,
" phone " : 9876543210,
" password " : " $2b$10$jgF/j/clYBq.3uly6Tijce4GEGJn9EIXEcw9NI3prgKwJ/6.sWT6O " ,
" createdAt " : " 2021-10-10T06:25:46.051Z " ,
" updatedAt " : " 2021-10-10T08:47:15.297Z " ,
" __v " : 0
}
}
Nota: Bcrypt Enviar dados de formulário
RECURSO II - Produto
Modelos
{
title : {string, mandatory, unique},
description : {string, mandatory},
price : {number, mandatory, valid number/decimal},
currencyId : {string, mandatory, INR},
currencyFormat : {string, mandatory, Rupee symbol},
isFreeShipping : {boolean, default: false},
productImage : {string, mandatory}, // s3 link
style : {string},
availableSizes : {array of string, at least one size, enum["S", "XS","M","X", "L","XXL", "XL"]},
installments : {number},
deletedAt : {Date, when the document is deleted},
isDeleted : {boolean, default: false},
createdAt : {timestamp},
updatedAt : {timestamp},
}
API de produtos ( sem necessidade de autenticação )
POST/produtos
- Crie um documento de produto a partir do corpo da solicitação.
- Faça upload da imagem do produto para o bucket S3 e salve o URL público da imagem no documento.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 201. Retorne também o documento do produto. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
OBTER /produtos
- Retorna todos os produtos da coleção que não foram excluídos.
- Filtros
- Tamanho (a chave para este filtro será 'tamanho')
- Nome do produto (a chave para este filtro será 'nome'). Você deverá retornar todos os produtos com nome contendo a substring recebida neste filtro
- Preço: maior ou menor que um valor específico. As chaves são 'priceGreaterThan' e 'priceLessThan'.
NOTA: Para solicitação de filtro de preço pode conter ambas ou qualquer uma das chaves. Por exemplo, a consulta na solicitação pode ser semelhante a { priceGreaterThan: 500, priceLessThan: 2000 } ou apenas { priceLessThan: 1000 } )
- Organizar
- Ordenado por preço do produto em ordem crescente ou decrescente. O par de valores-chave será semelhante a {priceSort: 1} ou {priceSort: -1}, por exemplo, /products?size=XL&name=Nit%20grit
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também os documentos do produto. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
OBTER /produtos/:productId
- Retorna detalhes do produto por ID do produto
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também os documentos do produto. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
PUT /produtos/:productId
- Atualiza um produto alterando pelo menos um ou todos os campos
- Verifique se o productId existe (deve ter isDeleted false e está presente na coleção). Caso contrário, retorne um status HTTP 404 com um corpo de resposta como este
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também o documento do produto atualizado. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
DELETE /produtos/:productId
- Exclui um produto por ID do produto, se ainda não tiver sido excluído
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
RECURSO III - Carrinho
Modelos
{
userId : {ObjectId, refs to User, mandatory, unique},
items : [{
productId : {ObjectId, refs to Product model, mandatory},
quantity : {number, mandatory, min 1}
}],
totalPrice : {number, mandatory, comment: "Holds total price of all the items in the cart"},
totalItems : {number, mandatory, comment: "Holds total number of items in the cart"},
createdAt : {timestamp},
updatedAt : {timestamp},
}
APIs de carrinho ( autenticação necessária como token de cabeçalho e portador de autorização )
POST /users/:userId/cart (Adicionar ao carrinho)
- Crie um carrinho para o usuário se ele não existir. Caso contrário, adicione produtos no carrinho.
- Obtenha o ID do carrinho no corpo da solicitação.
- Obtenha productId no corpo da solicitação.
- Certifique-se de que esse carrinho exista.
- Adicione um(s) produto(s) para um usuário no carrinho.
- Certifique-se de que o userId nos parâmetros e no token JWT correspondam.
- Certifique-se de que o usuário exista
- Certifique-se de que os produtos sejam válidos e não excluídos.
- Obtenha detalhes do(s) produto(s) no corpo da resposta.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 201. Retorne também o documento do carrinho. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
PUT /users/:userId/cart (Remover produto / Reduzir a quantidade de um produto do carrinho)
- Atualiza um carrinho diminuindo a quantidade de um produto em 1 ou excluindo um produto do carrinho.
- Obtenha o ID do carrinho no corpo da solicitação.
- Obtenha productId no corpo da solicitação.
- Obtenha a chave 'removeProduct' no corpo da solicitação.
- Certifique-se de que esse carrinho exista.
- A chave 'removeProduct' indica se um produto deve ser removido ({removeProduct: 0}) ou se sua quantidade deve ser diminuída em 1 ({removeProduct: 1}).
- Certifique-se de que o userId nos parâmetros e no token JWT correspondam.
- Certifique-se de que o usuário exista
- Obtenha detalhes do(s) produto(s) no corpo da resposta.
- Verifique se o productId existe e não foi excluído antes de atualizar o carrinho.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também o documento do carrinho atualizado. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
GET /usuários/:userId/carrinho
- Retorna o resumo do carrinho do usuário.
- Certifique-se de que esse carrinho exista.
- Certifique-se de que o userId nos parâmetros e no token JWT correspondam.
- Certifique-se de que o usuário existe
- Obtenha detalhes do(s) produto(s) no corpo da resposta.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne o documento do carrinho. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
DELETE /usuários/:userId/carrinho
- Exclui o carrinho do usuário.
- Certifique-se de que esse carrinho exista.
- Certifique-se de que o userId nos parâmetros e no token JWT correspondam.
- Certifique-se de que o usuário exista
- exclusão do carrinho significa que a matriz de itens está vazia, totalItems é 0, totalPrice é 0.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 204. Retorne uma mensagem adequada. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
RECURSO IV - Ordem
Modelos
{
userId : {ObjectId, refs to User, mandatory},
items : [{
productId : {ObjectId, refs to Product model, mandatory},
quantity : {number, mandatory, min 1}
}],
totalPrice : {number, mandatory, comment: "Holds total price of all the items in the cart"},
totalItems : {number, mandatory, comment: "Holds total number of items in the cart"},
totalQuantity : {number, mandatory, comment: "Holds total number of quantity in the cart"},
cancellable : {boolean, default: true},
status : {string, default: 'pending', enum[pending, completed, cancled]},
deletedAt : {Date, when the document is deleted},
isDeleted : {boolean, default: false},
createdAt : {timestamp},
updatedAt : {timestamp},
}
APIs de checkout/pedido (autenticação e autorização necessárias)
POST /usuários/:userId/pedidos
- Crie um pedido para o usuário
- Certifique-se de que o userId nos parâmetros e no token JWT correspondam.
- Certifique-se de que o usuário exista
- Obtenha detalhes do carrinho no corpo da solicitação
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também o documento do pedido. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
PUT /usuários/:userId/pedidos
- Atualiza o status de um pedido
- Certifique-se de que o userId nos parâmetros e no token JWT correspondam.
- Certifique-se de que o usuário exista
- Obtenha o ID do pedido no corpo da solicitação
- Certifique-se de que o pedido pertence ao usuário
- Certifique-se de que apenas um pedido cancelável possa ser cancelado. Caso contrário, envie uma mensagem de erro e uma resposta apropriadas.
- Formato de resposta
- Em caso de sucesso - Retorne o status HTTP 200. Retorne também o documento do pedido atualizado. A resposta deve ser um objeto JSON como este
- Em caso de erro - Retorna uma mensagem de erro adequada com um código de status HTTP válido. A resposta deve ser um objeto JSON como este
Teste
- Para testar essas APIs, crie uma nova coleção no Postman chamada Project 5 Shopping Cart
- Cada API deve ter uma nova solicitação nesta coleção
- Cada solicitação na coleção deve ser nomeada corretamente. Por exemplo, criar usuário, criar produto, obter produtos etc.
- Cada membro de cada equipe deverá ter seus testes em estado de execução
Consulte o exemplo abaixo
Resposta
Estrutura de resposta bem-sucedida
{
status : true,
message : ' Success ' ,
data : {
}
}
Estrutura de resposta a erros
{
status : false,
message : " "
}
Coleções
Usuários
{
_id : ObjectId("88abc190ef0288abc190ef02"),
fname : ' John ' ,
lname : ' Doe ' ,
email : ' [email protected] ' ,
profileImage : ' http://function-up-test.s3.amazonaws.com/users/user/johndoe.jpg ' , // s3 link
phone : 9876543210,
password : ' $2b$10$O.hrbBPCioVm237nAHYQ5OZy6k15TOoQSFhTT.recHBfQpZhM55Ty ' , // encrypted password
address : {
shipping : {
street : " 110, Ridhi Sidhi Tower " ,
city : " Jaipur " ,
pincode : 400001
}, {mandatory}
billing : {
street : " 110, Ridhi Sidhi Tower " ,
city : " Jaipur " ,
pincode : 400001
}
},
createdAt : " 2021-09-17T04:25:07.803Z " ,
updatedAt : " 2021-09-17T04:25:07.803Z " ,
}
produtos
{
_id : ObjectId("88abc190ef0288abc190ef55"),
title : ' Nit Grit ' ,
description : ' Dummy description ' ,
price : 23.0,
currencyId : ' INR ' ,
currencyFormat : ' ₹ ' ,
isFreeShipping : false,
productImage : ' http://function-up-test.s3.amazonaws.com/products/product/nitgrit.jpg ' , // s3 link
style : ' Colloar ' ,
availableSizes : ["S", "XS","M","X", "L","XXL", "XL"],
installments : 5,
deletedAt : null,
isDeleted : false,
createdAt : " 2021-09-17T04:25:07.803Z " ,
updatedAt : " 2021-09-17T04:25:07.803Z " ,
}
carrinhos
{
" _id " : ObjectId("88abc190ef0288abc190ef88"),
userId : ObjectId("88abc190ef0288abc190ef02"),
items : [{
productId : ObjectId("88abc190ef0288abc190ef55"),
quantity : 2
}, {
productId : ObjectId("88abc190ef0288abc190ef60"),
quantity : 1
}],
totalPrice : 50.99,
totalItems : 2,
createdAt : " 2021-09-17T04:25:07.803Z " ,
updatedAt : " 2021-09-17T04:25:07.803Z " ,
}
pedidos
{
" _id " : ObjectId("88abc190ef0288abc190ef88"),
userId : ObjectId("88abc190ef0288abc190ef02"),
items : [{
productId : ObjectId("88abc190ef0288abc190ef55"),
quantity : 2
}, {
productId : ObjectId("88abc190ef0288abc190ef60"),
quantity : 1
}],
totalPrice : 50.99,
totalItems : 2,
totalQuantity : 3,
cancellable : true,
status : ' pending '
createdAt : " 2021-09-17T04:25:07.803Z " ,
updatedAt : " 2021-09-17T04:25:07.803Z " ,
}