Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pull request desafio Igor Belo #312

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions currency_api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Currency API

Esta é uma API simples para conversão de moedas e gerenciamento de moedas fictícias.

## Configuração

1. Certifique-se de ter o Python instalado em sua máquina. Você pode baixá-lo em [python.org](https://www.python.org/downloads/).

2. Clone este repositório:

```bash
git clone https://caminho/para/o/repositório
```

3. Navegue até o diretório do projeto:

```bash
cd currency_api
```

4. Crie um ambiente virtual (opcional, mas recomendado):

```bash
python -m venv venv
```

5. Ative o ambiente virtual:

- No Windows:

```bash
venv\Scripts\activate
```

- No macOS e Linux:

```bash
source venv/bin/activate
```

6. Instale as dependências do projeto:

```bash
pip install -r requirements.txt
```

7. Configure as variáveis de ambiente (opcional):

- Renomeie o arquivo `.env.example` para `.env`
- Edite o arquivo `.env` conforme necessário

## Executando a API

Para executar a API localmente, siga estas etapas:

1. Certifique-se de estar no diretório raiz do projeto e com o ambiente virtual ativado.

2. Execute o arquivo `run.py`:

```bash
python run.py
```

A API estará disponível em `http://localhost:5000/`.

## Uso da API

A API possui os seguintes endpoints:

- `/convert`: Endpoint para converter uma quantidade de uma moeda para outra.
- Parâmetros da query string:
- `from`: Código da moeda de origem.
- `to`: Código da moeda de destino.
- `amount`: Quantidade a ser convertida.

- `/currencies`: Endpoint para listar todas as moedas cadastradas.
- Métodos suportados: GET

- `/currencies`: Endpoint para adicionar uma nova moeda ao sistema.
- Métodos suportados: POST
- Corpo da requisição deve ser um JSON com os campos `code`, `name` e `rate_to_usd`.

- `/currencies/<currency_id>`: Endpoint para excluir uma moeda existente pelo ID.
- Métodos suportados: DELETE
20 changes: 20 additions & 0 deletions currency_api/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import Config

db = SQLAlchemy()

def create_app():
app = Flask(__name__)
app.config.from_object(Config)

with app.app_context():
db.init_app(app)
from .models import Currency

from .routes import bp as api_bp
app.register_blueprint(api_bp)

db.create_all()

return app
11 changes: 11 additions & 0 deletions currency_api/app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from . import db

class Currency(db.Model):
id = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(3), unique=True, nullable=False)
name = db.Column(db.String(50), unique=True, nullable=False)
rate_to_usd = db.Column(db.Float, nullable=False)

def __repr__(self):
return f'<Currency {self.code}>'

71 changes: 71 additions & 0 deletions currency_api/app/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from flask import Blueprint, request, jsonify
from .models import Currency
from . import db

bp = Blueprint('api', __name__)

@bp.route('/convert', methods=['GET'])
def convert():
from_currency = request.args.get('from')
to_currency = request.args.get('to')
amount = float(request.args.get('amount'))

if not from_currency or not to_currency or not amount:
return jsonify({"error": "Missing required parameters"}), 400

from_currency = from_currency.upper()
to_currency = to_currency.upper()

from_curr = Currency.query.filter_by(code=from_currency).first()
to_curr = Currency.query.filter_by(code=to_currency).first()

if not from_curr or not to_curr:
return jsonify({"error": "Currency not supported"}), 400

converted_amount = (amount / from_curr.rate_to_usd) * to_curr.rate_to_usd
return jsonify({"result": converted_amount}), 200

@bp.route('/currencies', methods=['GET'])
def list_currencies():
currencies = Currency.query.all()
currency_list = [{
'code': currency.code,
'name': currency.name,
'rate_to_usd': currency.rate_to_usd
} for currency in currencies]
return jsonify(currency_list), 200

@bp.route('/currencies', methods=['POST'])
def add_currency():
data = request.get_json()

# Verificação dos dados recebidos
if not data or not 'code' in data or not 'name' in data or not 'rate_to_usd' in data:
return jsonify({'error': 'Missing required fields'}), 400

code = data['code'].upper()
name = data['name']
try:
rate_to_usd = float(data['rate_to_usd'])
except ValueError:
return jsonify({'error': 'Invalid rate_to_usd value'}), 400

new_currency = Currency(code=code, name=name, rate_to_usd=rate_to_usd)

try:
db.session.add(new_currency)
db.session.commit()
return jsonify({'message': 'Currency added successfully'}), 201
except Exception as e:
db.session.rollback()
return jsonify({'error': 'Failed to add currency', 'details': str(e)}), 500

@bp.route('/currencies/<int:currency_id>', methods=['DELETE'])
def delete_currency(currency_id):
currency = Currency.query.get(currency_id)
if currency:
db.session.delete(currency)
db.session.commit()
return jsonify({'message': 'Currency deleted successfully'}), 200
else:
return jsonify({'error': 'Currency not found'}), 404
6 changes: 6 additions & 0 deletions currency_api/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from secrets import SECRET_KEY

class Config:
SQLALCHEMY_DATABASE_URI = 'sqlite:///currency.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = SECRET_KEY
Binary file added currency_api/requirements.txt
Binary file not shown.
80 changes: 80 additions & 0 deletions currency_api/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import threading
import time
import requests
from app import create_app, db
from app.models import Currency

# Função para atualizar as taxas de câmbio
def update_exchange_rates():
app = create_app()
with app.app_context():
# Verifica se a moeda "HURB" existe no banco de dados e adiciona-a se necessário
hurb_currency = Currency.query.filter_by(code='HURB').first()
if not hurb_currency:
hurb_currency = Currency(code='HURB', name='HURB', rate_to_usd=15.0)
db.session.add(hurb_currency)
db.session.commit()
print("Moeda fictícia HURB adicionada com sucesso.")
else:
print("Moeda fictícia HURB já existe no banco de dados.")

#Loop para atualizar os valores
while True:
try:
# Obter os preços do Bitcoin (BTC) e Ethereum (ETH) da API CoinGecko
response = requests.get('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd')
if response.status_code == 200:
data = response.json()
btc_price = data.get('bitcoin', {}).get('usd')
eth_price = data.get('ethereum', {}).get('usd')

# Adicionar ou atualizar os preços do BTC e ETH no banco de dados
btc_currency = Currency.query.filter_by(code='BTC').first()
if btc_currency:
btc_currency.rate_to_usd = btc_price
else:
new_btc_currency = Currency(code='BTC', name='Bitcoin', rate_to_usd=btc_price)
db.session.add(new_btc_currency)

eth_currency = Currency.query.filter_by(code='ETH').first()
if eth_currency:
eth_currency.rate_to_usd = eth_price
else:
new_eth_currency = Currency(code='ETH', name='Ethereum', rate_to_usd=eth_price)
db.session.add(new_eth_currency)

# Obter as taxas de câmbio da API v6.exchangerate-api.com
api_key = '1680c81c8217ed00e6d66163'
response = requests.get(f'https://v6.exchangerate-api.com/v6/{api_key}/latest/USD')
if response.status_code == 200:
data = response.json()
rates = data.get('conversion_rates', {})
currencies_to_update = ['USD', 'BRL', 'EUR']
for currency_code in currencies_to_update:
rate = rates.get(currency_code)
if rate is not None:
currency = Currency.query.filter_by(code=currency_code).first()
if currency:
currency.rate_to_usd = rate
else:
# Se a moeda não existir no banco de dados, vamos adicioná-la
new_currency = Currency(code=currency_code, name=currency_code, rate_to_usd=rate)
db.session.add(new_currency)
db.session.commit()
print("Valores atualizados com sucesso.")
else:
print("Falha ao buscar taxas de câmbio.")
else:
print("Falha ao buscar preços do Bitcoin e Ethereum.")
except Exception as e:
print(f"Erro ao atualizar Valores: {e}")
time.sleep(10) # Espera 10 segundos antes de atualizar novamente

# Iniciar a função de atualização em uma thread em segundo plano
update_thread = threading.Thread(target=update_exchange_rates)
update_thread.daemon = True
update_thread.start()

if __name__ == "__main__":
app = create_app()
app.run(host='0.0.0.0', port=5000)
Empty file added currency_api/tests/__init__py
Empty file.
82 changes: 82 additions & 0 deletions currency_api/tests/test_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import json
from flask import Flask
import pytest
from app.models import Currency

def test_list_currencies(client: Any, app: Flask):
# Adicionando algumas moedas de exemplo ao banco de dados
currency1 = Currency(code='AAA', name='Currency AAA', rate_to_usd=1.0)
currency2 = Currency(code='BBB', name='Currency BBB', rate_to_usd=2.0)
currency3 = Currency(code='CCC', name='Currency CCC', rate_to_usd=3.0)
db.session.add_all([currency1, currency2, currency3])
db.session.commit()

# Fazendo solicitação GET para a rota /currencies
response = client.get('/currencies')

# Verificando se o status code é 200 OK
assert response.status_code == 200

# Verificando se os dados retornados correspondem às moedas adicionadas
data = json.loads(response.data.decode('utf-8'))
assert len(data) == 3
assert data[0]['code'] == 'AAA'
assert data[1]['code'] == 'BBB'
assert data[2]['code'] == 'CCC'

# Você pode adicionar mais verificações conforme necessário

def test_convert_currency(client: Any, app: Flask):
# Adicionando algumas moedas de exemplo ao banco de dados
currency1 = Currency(code='USD', name='US Dollar', rate_to_usd=1.0)
currency2 = Currency(code='EUR', name='Euro', rate_to_usd=0.85)
currency3 = Currency(code='GBP', name='British Pound', rate_to_usd=0.72)
db.session.add_all([currency1, currency2, currency3])
db.session.commit()

# Fazendo solicitação GET para a rota /convert com parâmetros de exemplo
response = client.get('/convert?from=USD&to=EUR&amount=100')

# Verificando se o status code é 200 OK
assert response.status_code == 200

# Verificando se o resultado da conversão está correto
data = json.loads(response.data.decode('utf-8'))
assert 'result' in data
assert data['result'] == 85.0

# Você pode adicionar mais verificações conforme necessário

def test_add_currency(client: Any, app: Flask):
# Dados de exemplo para adicionar uma nova moeda
new_currency_data = {
'code': 'JPY',
'name': 'Japanese Yen',
'rate_to_usd': 110.0
}

# Fazendo solicitação POST para a rota /currencies com os dados de exemplo
response = client.post('/currencies', json=new_currency_data)

# Verificando se o status code é 201 Created
assert response.status_code == 201

# Verificando se a moeda foi adicionada corretamente
assert Currency.query.filter_by(code='JPY').first() is not None

# Você pode adicionar mais verificações conforme necessário

def test_delete_currency(client: Any, app: Flask):
# Adicionando uma moeda de exemplo ao banco de dados
currency = Currency(code='JPY', name='Japanese Yen', rate_to_usd=110.0)
db.session.add(currency)
db.session.commit()

# Fazendo solicitação DELETE para a rota /currencies/<int:currency_id> com o ID da moeda de exemplo
response = client.delete('/currencies/{}'.format(currency.id))

# Verificando se o status code é 200 OK
assert response.status_code == 200

# Verificando se a moeda foi excluída corretamente
assert Currency.query.filter_by(code='JPY').first() is None