- Este é projeto de um teste técnico de back-end, aonde envolve o desenvolvimento de uma API RESTful, permitindo o cadastro de usuários externos, ao efetuar login, permite o cadastro de clientes e produtos, bem como o registro de vendas de produtos aos clientes. O projeto utiliza o framework AdonisJs para estruturar a API com uma arquitetura em camadas (MVC), sem views. Lucid é utilizado como ORM, com Bcrypt para criptografia de senha e JWT para autenticação de token, aderindo aos princípios de APIs RESTful e ao padrão MVC.
O projeto foi desenvolvido utilizando as seguintes tecnologias:
-
Copie o repositório para uma pasta local usando o terminal com o seguinte comando:
git clone git@github.com:juliocmatias/adonis-be.git
Se o Git não estiver instalado, ele pode ser instalado usando este comando no bash do Debian/Ubuntu:
Debian/Ubuntu:
sudo apt-get install git
Para outros kernels, siga as instruções no site do Git.
windows/powershell:
winget install --id Git.Git -e --source winget
Ou você pode seguir a documentação do site do Git para mais opções de instalação.
-
Instale as dependências do projeto com o comando:
npm install
Este método de instalação de pendências só funciona se o pacote de instalação do Node for o npm. Se você usar outro, basta substituir o npm pelo pacote utilizado.
Você precisa ter o Node instalado para poder instalar os pacotes de dependência. Se você não o tiver, pode executar o comando se o seu sistema operacional for Linux:
sudo apt update sudo apt install nodejs sudo apt install npm
Caso contrário, siga as instruções de instalação no site do Node.js.
⚠️ Para que a aplicação funcione corretamente, a versão do Node deve ser >= 18.
⚠️ Também é importante lembrar que, para rodar a API usando Docker, você precisará tê-lo instalado e configurado na sua máquina. Consulte a documentação para saber mais sobre Docker. Além disso, é necessário ter o Docker Compose instalado e configurado no seu computador. Para instalar a versão do seu sistema operacional, clique aqui Docker Compose.
⚠️ Sinta-se à vontade para abrir o projeto na sua IDE preferida, mas você pode executá-lo normalmente no terminal.
- Configure o arquivo .env:
cp .env.example .env
Este comando copiará o arquivo .env.example para .env, que é o arquivo que contém as variáveis de ambiente do projeto. Você pode abri-lo no seu editor de texto preferido e configurá-lo como quiser. Se não quiser, ele já vem com as configurações necessárias para que a aplicação funcione.
⚠️ Você pode usar o Docker para iniciar os contêineres da API e do banco de dados MySQL. Este projeto vem com os arquivosDockerfile
edocker-compose.yml
configurados. Se você optar por usar a API via terminal com um banco de dados instalado localmente ou na nuvem, deve configurar corretamente o arquivo.env
para que a aplicação funcione corretamente.
🐋 Docker
⚠️ Antes de começar, seu docker-compose precisa estar na versão 1.29 ou superior.. Veja aqui ou na documentação como instalá-lo. No primeiro artigo, você pode substituir onde está1.26.0
por1.29.2
.
⚠️ É importante notar que os contêineres serão executados na porta 3333 para a API e 3306 para o banco de dados MySQL. Portanto, se você estiver usando essas portas, basta alterá-las no arquivo .env.
-
Para que a API comece a funcionar, primeiro você precisa executar o docker-compose:
docker-compose up -d
-
Ao executar este comando, aguarde até que a API esteja funcional, verificando através do log do contêiner adonis_app com o comando:
docker logs -f adonis_app
Ao digitar este comando, um log deverá aparecer no terminal com as mesmas informações da imagem abaixo. Mostrando que a API está operacional.
-
Uma vez que a aplicação esteja operacional, as migrations e seeders serão processadas. E a API estará operacional para receber requisições.
⚠️ Devido ao arquivomysql-dev-init.sql
localizado na pastadockerConfig
, o docker-compose está configurado para executar as queries desse arquivo, criando um usuário e um banco de dados. Se você desejar alterar o usuário na variável de ambiente e o nome do banco de dados, este arquivo também deve ser editado, e os contêineres devem ser derrubados e reiniciados, sendo reconstruídos. -
Se você precisar resetar o banco de dados da API, execute o comando:
npm run db:reset
Este comando irá deletar todos os dados do banco de dados e rodar novamente as migrations e seeders.
💻 Terminal
Para rodar a API via terminal, como já mencionado, você precisa colocar as informações necessárias no arquivo .env para que a API se conecte ao banco de dados MySQL. Ao escolher esta opção, você deve fornecer as informações necessárias para que a API seja funcional.
⚠️ Antes de executar qualquer comando, é necessário garantir que a conexão com o banco de dados esteja funcionando e que um banco de dados já tenha sido criado. Preste atenção ao nome fornecido na variável de ambiente em .env:DB_DATABASE
.
-
Execute no terminal:
npm run dev
Este comando iniciará a API em modo de desenvolvimento, e você poderá acessá-la via
http://localhost:3333
, se essa for a porta configurada. Se quiser alterar a porta, você pode fazê-lo no arquivo .env. Desta forma, a API estará funcional e pronta para receber requisições. -
Para resetar a API, execute o comando:
npm run db:reset
-
Para parar a API no terminal, pressione Ctrl + C ou no caso do macOS Cmd + C.
Se você usa o VSCode como sua IDE, você pode usar a extensão Thunder Client para fazer requisições para a API. Na raiz do projeto, há um arquivo chamado
thunder-collection_adonis_be.json
com uma coleção de rotas pré-configuradas; basta importá-lo na extensão para utilizá-lo.
🫂 Diagrama de Entidade e Relacionamento
- O diagrama mostra o relacionamento entre as entidades no banco de dados, onde um usuário pode ter muitos clientes, e um cliente pode ter muitas vendas. O produto também pode ter muitas vendas, e a venda pode ter apenas um cliente e um produto. Utilizei o diagrama para orientar a criação das migrações, baseando-me nas informações fornecidas sobre cada entidade.
-
A API utiliza tokens JWT para autenticação de rotas, os quais devem ser enviados através do token de autenticação Bearer.
-
A API possui as seguintes rotas:
⚠️ Para as entidades de endereço e telefone, não foram criadas rotas, controladores e serviços, pois foquei nos principais requisitos do desafio para entregá-lo no prazo. No entanto, a migração com relacionamentos e os modelos foram implementados.
📖 Routers
Método | Endpoint | Descrição | Autenticação |
---|---|---|---|
POST | /user | criar um novo usuário | NÃO |
PUT | /user/:id | atualizar um usuário pelo id | SIM |
PATCH | /user/:id | atualizar campos específicos de um usuário pelo id | SIM |
Método | Endpoint | Descrição | Autenticação |
---|---|---|---|
POST | /login | fazer login do usuário | NÃO |
Método | Endpoint | Descrição | Autenticação |
---|---|---|---|
GET | /client | listar todos os clientes | SIM |
GET | /client/:clientId/sales | listar todas as vendas de um cliente por id e filtrar por data por mês e ano | SIM |
POST | /client | criar um novo cliente | SIM |
PUT | /client/:id | atualizar um cliente pelo id | SIM |
PATCH | /client/:id | atualizar campos específicos de um cliente pelo id | SIM |
DELETE | /client/:id | excluir um cliente pelo id e automaticamente excluir todas as vendas deste cliente | SIM |
Método | Endpoint | Descrição | Autenticação |
---|---|---|---|
GET | /product | listar todos os produtos | SIM |
POST | /product | criar um novo produto | SIM |
PUT | /product/:id | atualizar um produto pelo id | SIM |
PATCH | /product/:id | atualizar campos específicos de um produto pelo id | SIM |
DELETE | /product/:id | excluir um produto pelo id (soft delete) | SIM |
Método | Endpoint | Descrição | Autenticação |
---|---|---|---|
GET | /sale | listar todas as vendas com cliente e produto | SIM |
POST | /sale | criar uma nova venda | SIM |
DELETE | /sale/:id | excluir uma venda pelo id | SIM |
🌎 Requisição e Resposta
Users
Criar um novo usuário
- Método: POST
- Endpoint: /user
- Descrição: Criar um novo usuário
- Autenticação: NÃO
- body:
{
"email": "johndoe@doe.com",
"password": "123456"
}
-
Validação:
- email: obrigatório, único, formato de e-mail válido
- password: obrigatório, min:6
-
Exemplo de requisição:
-
Método: POST
-
URL:
http://localhost:3333/user
-
Exemplo de resposta:
-
Status: 201
{
"id": 1,
"email": "johndoe@doe.com"
}
- status: 400
{
"message": "Invalid formato for email"
}
- status: 409
{
"message": "Email already exists"
}
- status: 500
{
"message": "Internal server error"
}
Atualizar um usuário por ID
⚠️ Como Adonis usa o mesmo método no controlador para PUT e PATCH, que é update, esta rota aceitará tanto o método PUT para atualizar todas as propriedades quanto o método PATCH para atualizar apenas uma.
- Método: PUT
- Endpoint: /user/:id
- Descrição: Atualizar um usuário por ID
- Autenticação: SIM
- body:
{
"email": "exemple@exemple.com",
"password": "123456"
}
-
params:
- id: obrigatório, numero
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Validação:
- email: obrigatório se não passado a senha, único, formato email valido
- password: obrigatório se não passado o email, min:6
-
Exemplo de requisição:
-
Método: PUT
-
URL:
http://localhost:3333/user/1
-
Exemplo de resposta:
-
Status: 200
{
"id": 1,
"email": "exemple@exemple.com"
}
- status: 400
{
"message": "Invalid formato for email"
}
- status: 401
{
"message": "Token not provided"
}
- status: 409
{
"message": "Email already exists"
}
- status: 500
{
"message": "Internal server error"
}
Login
- Método: POST
- Endpoint: /login
- Descrição: fazer login do usuário
- Autenticação: NÃO
- body:
{
"email": "user@user.com",
"password": "123456"
}
-
Validação:
- email: obrigatório, formato email valido
- password: obrigatório, min:6
-
Exemplo de requisição:
-
Método: POST
-
URL:
http://localhost:3333/login
-
Exemplo de resposta:
-
Status: 200
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZW1haWwiOiJ1c2VyQHVzZXIuY29tIiwiaWF0IjoxNzIwMTU5MDAxLCJleHAiOjE3MjEwMjMwMDF9.3UQBzWrJXSSaoipfKWBU1f0-hMt_-JDbE8EhIMCfKSE"
}
- status: 400
{
"message": "Invalid formato for email"
}
- status: 401
{
"message": "Invalid email or password"
}
- status: 500
{
"message": "Internal server error"
}
Clients
Listar todos os clientes
⚠️ Os clientes serão ordenados por id!
- Método: GET
- Endpoint: /client
- Descrição: Liste todos os clientes ordenados por id asc
- Autenticação: SIM
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Exemplo de requisição:
-
Método: GET
-
URL:
http://localhost:3333/client
-
Exemplo de resposta:
-
Status: 200
[
{
"id": 1,
"name": "John Snow",
"taxId": "12345678912"
},
{
"id": 2,
"name": "Daenerys Targaryen",
"taxId": "98765432112"
}
]
- status: 401
{
"message": "Token not provided"
}
- status: 500
{
"message": "Internal server error"
}
lista um cliente por id e suas vendas
- Método: GET
- Endpoint: /client/:clientId/sales
- Descrição: lista um cliente por id e suas vendas e filtre por data por mês e ano
- Autenticação: SIM
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
query params:
- month: não obrigatório, número, min:1, max:12
- year: não obrigatório, número, min:1900, max: ano atual
Exemplo de requisição:
- Método: GET
- URL:
http://localhost:3333/client/1/sales?month=1&year=2021
⚠️ As vendas serão ordenadas por data, mostrando sempre primeiro a mais recente!
- Exemplo de resposta:
200 - Query Params não Informado
- Status: 200
- Query Params: não Informado
{
"id": 1,
"name": "John Snow",
"taxId": "12345678912",
"sales": [
{
"id": 3,
"clientId": 1,
"productId": 1,
"quantity": 10,
"price": "10.00",
"totalPrice": "100.00",
"date": "2021-02-02T00:00:00.000Z"
},
{
"id": 4,
"clientId": 1,
"productId": 2,
"quantity": 10,
"price": "20.00",
"totalPrice": "200.00",
"date": "2021-02-01T00:00:00.000Z"
},
{
"id": 2,
"clientId": 1,
"productId": 2,
"quantity": 10,
"price": "20.00",
"totalPrice": "200.00",
"date": "2021-01-02T00:00:00.000Z"
},
{
"id": 1,
"clientId": 1,
"productId": 1,
"quantity": 10,
"price": "10.00",
"totalPrice": "100.00",
"date": "2021-01-01T00:00:00.000Z"
}
]
}
200 - Query Params Informado
⚠️ A resposta será igual à anterior, mas com as vendas filtradas pelo mês e ano informados nos parâmetros da consulta.
⚠️ Para filtrar por mês e ano é obrigatório o envio das duas queries; enviar apenas um fará com que o filtro não funcione corretamente.
- Status: 200
- Query Params: Informado
{
"id": 1,
"name": "John Snow",
"taxId": "12345678912",
"sales": [
{
"id": 2,
"clientId": 1,
"productId": 2,
"quantity": 10,
"price": "20.00",
"totalPrice": "200.00",
"date": "2021-01-02T00:00:00.000Z"
},
{
"id": 1,
"clientId": 1,
"productId": 1,
"quantity": 10,
"price": "10.00",
"totalPrice": "100.00",
"date": "2021-01-01T00:00:00.000Z"
}
]
}
- status: 400
{
"message": "Invalid month or year"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Client not found"
}
- status: 500
{
"message": "Internal server error"
}
cria um novo cliente
- Método: POST
- Endpoint: /client
- Descrição: Cria um novo cliente
- Autenticação: SIM
- body exemplo:
{
"name": "John Snow",
"taxId": "12345678912"
}
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Validação:
- name: obrigatório, min:3
- taxId: obrigatório, único, exact:11
Exemplo de requisição:
- Método: POST
- URL:
http://localhost:3333/client
-
Exemplo de resposta:
-
Status: 201
{
"id": 1
}
- status: 400
{
"message": "Name and taxId are obrigatório"
}
- status: 409
{
"message": "Client already exists"
}
- status: 500
{
"message": "Internal server error"
}
Atualiza cliente por id
⚠️ Como Adonis usa o mesmo método no controlador para PUT e PATCH, que é update, esta rota aceitará tanto o método PUT para atualizar todas as propriedades quanto o método PATCH para atualizar apenas uma.
- Método: PUT
- Endpoint: /client/:id
- Descrição: Atualiza cliente por id
- Autenticação: SIM
- body exemplo:
{
"name": "John Snow",
"taxId": "12345678912"
}
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Validação:
- name: não obrigatório, min:3
- taxId: não obrigatório, único, exact:11
Exemplo de requisição:
- Método: PUT
- URL:
http://localhost:3333/client/1
-
Exemplo de resposta:
-
Status: 200
{
"message": "Client updated"
}
- status: 400
{
"message": "Name must be at least 3 characters"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Client not found"
}
- status: 409
{
"message": "Client already exists"
}
- status: 500
{
"message": "Internal server error"
}
Deleta cliente por id
⚠️ Quando um cliente é excluído, todas as vendas associadas a esse cliente também serão excluídas devido às configurações de chave estrangeira na migration de sales.
- Método: DELETE
- Endpoint: /client/:id
- Descrição: Deleta cliente por id e excluir automaticamente todas as vendas deste cliente
- Autenticação: SIM
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
Exemplo de requisição:
- Método: DELETE
- URL:
http://localhost:3333/client/1
-
Exemplo de resposta:
-
Status: 200
{
"message": "Client deleted"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Client not found"
}
- status: 500
{
"message": "Internal server error"
}
Products
Lista todos produtos
⚠️ Produtos ordenados em ordem alfabética!
- Método: GET
- Endpoint: /product
- Descrição: Lista todos produtos ordenando por id asc
- Autenticação: SIM
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
query params:
- all: não obrigatório, boolean, exemplo: all=true
- deleted: não obrigatório, boolean, exemplo: deleted=true
⚠️ Ao passar a query all=true, serão mostrados todos os produtos, sejam eles excluídos (soft delete) ou não. Se você quiser apenas os deletados, passe a query deleted=true. Se quiser apenas os disponíveis, não passe nenhuma query. Se ambos forem enviados, todos os produtos, excluídos ou não, serão mostrados. Se um valor diferente de true for passado na query all, apenas os produtos disponíveis serão mostrados. Se o valor da query deleted não for igual a true, os produtos deletados não serão mostrados.
- Exemplo de requisição:
- Método: GET
- URL:
http://localhost:3333/product?all=true
- Exemplo de resposta:
200 - Query Params não Informado - Produtos não deletados
- Status: 200
- Query Params: não Informado
[
{
"id": 1,
"name": "Product 1",
"quantity": 100,
"price": "10.00",
"deleted": 0
},
{
"id": 2,
"name": "Product 2",
"quantity": 200,
"price": "20.00",
"deleted": 0
}
]
200 - Query Params Informados - Produtos deletados
- Status: 200
- Query Params: somente deleted=true
[
{
"id": 3,
"name": "Iron Throne",
"quantity": 100,
"price": "3000.00",
"deleted": 1
},
{
"id": 4,
"name": "Longclaw",
"quantity": 100,
"price": "3000.00",
"deleted": 1
}
]
200 - Query Params Informado - Todos Produtos
- Status: 200
- Query Params: all=true
[
{
"id": 3,
"name": "Iron Throne",
"quantity": 100,
"price": "3000.00",
"deleted": 1
},
{
"id": 4,
"name": "Longclaw",
"quantity": 100,
"price": "3000.00",
"deleted": 1
},
{
"id": 1,
"name": "Product 1",
"quantity": 100,
"price": "10.00",
"deleted": 0
},
{
"id": 2,
"name": "Product 2",
"quantity": 200,
"price": "20.00",
"deleted": 0
}
]
- status: 401
{
"message": "Token not provided"
}
- status: 500
{
"message": "Internal server error"
}
Pega produtos por id
- Método: GET
- Endpoint: /product/:id
- Descrição: Pega produtos por id
- Autenticação: SIM
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
Exemplo de requisição:
- Método: GET
- URL:
http://localhost:3333/product/1
-
Exemplo de resposta:
-
Status: 200
{
"id": 1,
"name": "Product 1",
"quantity": 100,
"price": "10.00",
"deleted": 0
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Product not found"
}
- status: 500
{
"message": "Internal server error"
}
Cria um novo produto
- Método: POST
- Endpoint: /product
- Descrição: Cria um novo produto
- Autenticação: SIM
- body exemplo:
{
"name": "Product 1",
"quantity": 100,
"price": "10.00"
}
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Validação:
- name: obrigatório, min:3
- quantity: obrigatório, número
- price: obrigatório, número
Exemplo de requisição:
- Método: POST
- URL:
http://localhost:3333/product
-
Exemplo de resposta:
-
Status: 201
{
"id": 1
}
- status: 400
{
"message": "Missing required fields"
}
- status: 401
{
"message": "Token not provided"
}
- status: 500
{
"message": "Internal server error"
}
Atualiza produto por id
⚠️ Como Adonis usa o mesmo método no controlador para PUT e PATCH, que é update, esta rota aceitará tanto o método PUT para atualizar todas as propriedades quanto o método PATCH para atualizar apenas uma.
- Método: PUT
- Endpoint: /product/:id
- Descrição: Atualiza produto por id
- Autenticação: SIM
- body exemplo:
{
"name": "Product 1",
"quantity": 100,
"price": "10.00"
}
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Validação:
- name: não obrigatório, min:3
- quantity: não obrigatório, número
- price: não obrigatório, número
Exemplo de requisição:
- Método: PUT
- URL:
http://localhost:3333/product/1
-
Exemplo de resposta:
-
Status: 200
{
"message": "Product updated"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Product not found"
}
- status: 500
{
"message": "Internal server error"
}
Deleta produto por id
⚠️ A Soft delete foi implementada para que, quando um produto for excluído, ele não seja realmente removido do banco de dados. Seu registro é retido, com a coluna deleted definida como 1 quando deleted e como 0 (default) quando disponível.
- Método: DELETE
- Endpoint: /product/:id
- Descrição: Deleta produto por id (soft delete)
- Autenticação: SIM
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
Exemplo de requisição:
- Método: DELETE
- URL:
http://localhost:3333/product/1
-
Exemplo de resposta:
-
Status: 200
{
"message": "Product deleted"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Product not found"
}
- status: 500
{
"message": "Internal server error"
}
Sales
Lista todas as vendas
⚠️ As vendas serão ordenadas por id asc!
- Método: GET
- Endpoint: /sale
- Descrição: Lista todas as vendas com cliente e produto
- Autenticação: SIM
- autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
Exemplo de requisição:
- Método: GET
- URL:
http://localhost:3333/sale
- Exemplo de resposta:
200 - Sales
- Status: 200
[
{
"id": 1,
"clientId": 1,
"productId": 1,
"quantity": 10,
"price": "10.00",
"totalPrice": "100.00",
"date": "2021-01-01T00:00:00.000Z",
"client": {
"id": 1,
"name": "John Snow",
"taxId": "12345678912"
},
"product": {
"id": 1,
"name": "Product 1",
"quantity": 100,
"price": "10.00",
"deleted": 0
}
},
{
"id": 8,
"clientId": 2,
"productId": 1,
"quantity": 20,
"price": "10.00",
"totalPrice": "200.00",
"date": "2021-02-01T00:00:00.000Z",
"client": {
"id": 2,
"name": "Daenerys Targaryen",
"taxId": "98765432112"
},
"product": {
"id": 1,
"name": "Product 1",
"quantity": 100,
"price": "10.00",
"deleted": 0
}
}
]
- status: 401
{
"message": "Token not provided"
}
- status: 500
{
"message": "Internal server error"
}
Cria uma nova venda
- Método: POST
- Endpoint: /sale
- Descrição: Cria uma nova venda
- Autenticação: SIM
- body exemplo:
{
"clientId": 1,
"productId": 1,
"quantity": 10,
"date": "2024-03-01"
}
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
-
Validação:
- clientId: obrigatório, número
- productId: obrigatório, número
- quantity: obrigatório, número
- date: não obrigatório, data valida
⚠️ O campo data não é obrigatório e caso não seja informado será utilizada a data atual. Se fornecido, deve estar no formato dateTime (2024-03-01T00:00:00) ou em um formato de data válido (2024-03-01).
⚠️ Ao criar uma venda será verificado se o produto está disponível (não excluído) e se há quantidade suficiente para concretizar a venda. Nesse caso, a quantidade será decrementada no banco de dados.
⚠️ Se a quantidade for totalmente igual a zero após a venda, o produto será excluído automaticamente do banco de dados(Soft delete).
⚠️ O preço será obtido diretamente do modelo do Produto, sem a necessidade de passá-lo como parâmetro. Assim, o preço total também será calculado automaticamente, dispensando sua passagem como parâmetro.
Exemplo de requisição:
- Método: POST
- URL:
http://localhost:3333/sale
-
Exemplo de resposta:
-
Status: 201
{
"clientId": 1,
"productId": 1,
"quantity": 2,
"price": "10.00",
"totalPrice": 20,
"date": "2024-03-01T00:00:00.000+00:00",
"id": 10
}
- status: 400
{
"message": "Client, product, and quantity are obrigatório"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Client or product not found"
}
- status: 500
{
"message": "Internal server error"
}
Deleta uma venda por id
- Método: DELETE
- Endpoint: /sale/:id
- Descrição: Deleta uma venda por id
- Autenticação: SIM
-
params:
- id: obrigatório, número
-
autenticação: Bearer Token
- token: obrigatório
- formato: Bearer token
- Obtenha o token na rota de login
⚠️ Ao excluir uma venda, a quantidade do produto será incrementada no banco de dados, restaurando o valor que foi decrementado quando a venda foi realizada. Se o produto foi excluído por falta de estoque, ele ficará disponível novamente.
Exemplo de requisição:
- Método: DELETE
- URL:
http://localhost:3333/sale/1
-
Exemplo de resposta:
-
Status: 200
{
"message": "Sale deleted"
}
- status: 401
{
"message": "Token not provided"
}
- status: 404
{
"message": "Sale not found"
}
- status: 500
{
"message": "Internal server error"
}