Uma api que tem como objetivo automatizar uma tarefa super repetitiva, a saída e entrada dos produtos de uma loja. Além disso, fornece também o recurso de controle de estoque, que é calculado a partir do momento que uma entrada é registrada para tal produto.
A criação da API é feita com o Express, utilizando o ORM Prisma para efetuar as queries no PostgreSQL.
Todos os dados são validados com a biblioteca Zod, as senhas registradas são criptografadas com bcrypt, e além disso, o token JWT é utilizado para autenticação.
Nesse projeto foi implementado o padrão Either (estrutura de dados que representa dois tipos diferentes, Success e Failure), facilitando a manipulação e tratativa dos erros da aplicação.
Para finalizar, são feito alguns testes unitários com o Vitest.
- Criação de lojas no sistema
- Autenticação com JWT
- Linkagem dos produtos com uma única loja
# clone o repositório
$ git clone https://github.com/bastosmatheus/api-control-stock
# arquivo .env
DATABASE_URL="postgresql://username:password@localhost:5432/yourdatabase?schema=public"
# depois de clonado, procure a pasta do projeto
$ cd api-control-stock
# instale todas as dependências
$ npm install
# execute o projeto
$ npm run start
ROUTE | DESCRIPTION |
---|---|
RESPOSTAS DE SUCESSO | |
POST /products | cria um produto, veja mais na resposta da requisição |
POST /entrances | cria uma entrada para determinado produto, veja detalhes da requisição |
POST /exits | informa uma saída de um produto, veja mais na resposta da requisição |
POST /devolutions | registra detalhes da devolução de um produto, veja detalhes da requisição |
POST /defectiveproducts | registra detalhes de um produto defeituoso, veja mais na resposta da requisição |
POST /stores | cria uma loja, veja detalhes da requisição |
GET /products/:id | retorna todos os produtos registrado na API, veja resposta da requisição |
RESPOSTAS COM ERROS | |
GET /products/:idInexistente | erro ao passar um id inexistente para o get, veja mais na resposta da requisição |
POST /products | falha ao tentar registrar um produto que já existe no banco de dados, veja mais na resposta da requisição |
PUT /entrances/:id | erro ao passar um id de produto errado, veja mais na resposta da requisição |
PUT /exits/:id | falha ao passar um tipo errado da descrição, veja mais na resposta da requisição |
POST /defectiveproducts | erro ao tentar registrar um produto defeituoso sem um campo obrigatório, veja mais na resposta da requisição |
Ao criar uma loja (store), o usuário recebe um token de autenticação JWT, que é necessário para fazer as requisições de criação, atualização e deleção de produtos (products).
REQUISIÇÃO
{
"name_product": "Barra de cereal",
"price_product": 2.4,
"id_store": 1
}
RESPOSTA
{
"message": "Produto criado com sucesso",
"type": "OK",
"statusCode": 200,
"productCreated": {
"id": 3,
"name_product": "Barra de cereal",
"price_product": 2.4,
"quantity_product_stock": 0,
"id_store": 1
}
}
REQUISIÇÃO
{
"supplier": "maTheus fornecedor",
"quantity_products": 200,
"price_total": 480,
"id_product": 3
}
RESPOSTA
{
"message": "Entrada criada com sucesso",
"type": "OK",
"statusCode": 200,
"entranceCreated": {
"id": 17,
"supplier": "maTheus fornecedor",
"quantity_products": 200,
"price_total": 480,
"entrance_date": "2024-03-18T00:00:00.000Z",
"id_product": 3
}
}
REQUISIÇÃO
{
"description": "Usuário comprou uma barra de cereal",
"quantity_products": 1,
"price_total": 2.4,
"id_product": 3
}
RESPOSTA
{
"message": "Saída criada com sucesso",
"type": "OK",
"statusCode": 200,
"exitCreated": {
"id": 11,
"description": "Usuário comprou uma barra de cereal",
"quantity_products": 1,
"price_total": 2.4,
"exit_date": "2024-03-18T00:00:00.000Z",
"id_product": 3
}
}
REQUISIÇÃO
{
"description": "Barra de cereal veio quebrada",
"quantity_products": 1,
"id_entrance": 17
}
RESPOSTA
{
"message": "Devolução criada com sucesso",
"type": "OK",
"statusCode": 200,
"devolutionCreated": {
"id": 3,
"description": "Barra de cereal veio quebrada",
"quantity_products": 1,
"devolution_date": "2024-03-18T00:00:00.000Z",
"id_entrance": 17
}
}
REQUISIÇÃO
{
"description": "Barra de cereal com bixinhos dentro",
"quantity_products": 1,
"id_entrance": 17
}
RESPOSTA
{
"message": "Produto com defeito criado com sucesso",
"type": "OK",
"statusCode": 200,
"defectiveProductCreated": {
"id": 5,
"description": "Barra de cereal com bixinhos dentro",
"quantity_products": 1,
"id_entrance": 17
}
}
REQUISIÇÃO
{
"name_store": "mtCompany",
"email": "mthscompany@gmail.com",
"password": "102030"
}
RESPOSTA
{
"message": "Loja criada com sucesso",
"type": "Created",
"statusCode": 201,
"storeCreated": {
"id": 5,
"name_store": "mtCompany",
"email": "mthscompany@gmail.com",
"password": "$2b$10$l/YKKyezrYU/18RjG7cxlOjl1HWaLH/neDz4.hFmJhQAYEBofcI/2",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lX3N0b3JlIjoibXRDb21wYW55IiwiaWQiOjUsImlhdCI6MTcxMzM5MDkwNCwiZXhwIjoxNzE1OTgyOTA0fQ.1K7qHrdMuJdlZ3xSpYbsN2ub9s-DCZ6wg-hMUVFX8l8"
}
}
RESPOSTA
{
"type": "OK",
"statusCode": 200,
"product": {
"id": 3,
"name_product": "Barra de ceral",
"price_product": 2.4,
"quantity_product_stock": 280,
"id_store": 1,
"entrance": [
{
"id": 17,
"supplier": "maTheus fornecedor",
"quantity_products": 1,
"price_total": 2.4,
"entrance_date": "2024-03-18T00:00:00.000Z",
"id_product": 3,
"defective_product": [
{
"id": 5,
"description": "Barra de cereal com bixinhos dentro",
"quantity_products": 1,
"id_entrance": 17
}
],
"devolution": [
{
"id": 3,
"description": "Barra de cereal veio quebrada",
"quantity_products": 1,
"devolution_date": "2024-03-18T00:00:00.000Z",
"id_entrance": 17
}
]
}
],
"exit": [
{
"id": 11,
"description": "Usuário comprou uma barra de cereal",
"quantity_products": 1,
"price_total": 2.4,
"exit_date": "2024-03-18T00:00:00.000Z",
"id_product": 3
}
]
}
}
Além dessas respostas de sucesso, a API também conta com algumas respostas informando erros, tanto de requisições, quanto de regras de negócio, veja agora:
RESPOSTA
{
"message": "Nenhum produto foi encontrado com o ID: {idInexistente}",
"type": "Not Found",
"statusCode": 404
}
REQUISIÇÃO
{
"name_product": "Barra de cereal",
"price_product": 2.4,
"id_store": 1
}
RESPOSTA
{
"message": "Já existe um produto com esse nome: Barra de cereal",
"type": "Conflict",
"statusCode": 409
}
REQUISIÇÃO
{
"supplier": "maTheus fornecedor",
"quantity_products": 1,
"price_total": 2.4,
"id_product": {id_productInexistente}
}
RESPOSTA
{
"message": "Nenhum produto foi encontrado com o ID: {id_productInexistente}",
"type": "Not Found",
"statusCode": 404
}
REQUISIÇÃO
{
"description": null,
"quantity_products": 1,
"price_total": 2.4,
"id_product": 3
}
RESPOSTA
{
"message": "A descrição da saída do(s) produto(s) deve ser uma string",
"type": "Unprocessable Entity",
"statusCode": 422
}
REQUISIÇÃO
{
"quantity_products": 1,
"id_entrance": 17
}
RESPOSTA
{
"message": "Informe o defeito desse produto",
"type": "Unprocessable Entity",
"statusCode": 422
}