diff --git a/server/foxbank_server/apis/__init__.py b/server/foxbank_server/apis/__init__.py index ab0f6f8..cf10cd0 100644 --- a/server/foxbank_server/apis/__init__.py +++ b/server/foxbank_server/apis/__init__.py @@ -5,6 +5,7 @@ from .accounts import bp as acc_bp from .login import bp as login_bp from .transactions import bp as transactions_bp from .notifications import bp as notifications_bp +from .forex import bp as forex_bp class ApiWithErr(Api): def handle_http_exception(self, error): @@ -31,3 +32,4 @@ def init_apis(app: Flask): api.register_blueprint(acc_bp, url_prefix='/accounts') api.register_blueprint(transactions_bp, url_prefix='/transactions') api.register_blueprint(notifications_bp, url_prefix='/notifications') + api.register_blueprint(forex_bp, url_prefix='/forex') diff --git a/server/foxbank_server/apis/forex.py b/server/foxbank_server/apis/forex.py new file mode 100644 index 0000000..9dc6fbc --- /dev/null +++ b/server/foxbank_server/apis/forex.py @@ -0,0 +1,26 @@ +from flask.views import MethodView +from flask_smorest import Blueprint +from marshmallow import Schema, fields + +from ..db_utils import get_forex_rate +from .. import returns + +bp = Blueprint('forex', __name__, description='Foreign Exchange information') + +class GetExchangeResult(returns.SuccessSchema): + rate = fields.Float(optional=True) + +@bp.get('//') +@bp.response(422, returns.ErrorSchema, description='Invalid currency') +@bp.response(200, GetExchangeResult) +def get_exchange(from_currency: str, to_currency: str): + """Get exchange rate between two currencies""" + if from_currency == to_currency: + rate = 1 + else: + rate = get_forex_rate(from_currency, to_currency) + + if rate is None: + return returns.abort(returns.invalid_argument('currency')) + + return returns.success(rate=rate) diff --git a/server/foxbank_server/db_utils.py b/server/foxbank_server/db_utils.py index 7f02a4d..75d1e59 100644 --- a/server/foxbank_server/db_utils.py +++ b/server/foxbank_server/db_utils.py @@ -306,5 +306,32 @@ class Module(ModuleType): ) self.db.commit() + @get_db + def get_forex_rate(self, from_currency: str, to_currency: str) -> float | None: + cur = self.db.cursor() + + if from_currency == 'RON' or to_currency == 'RON': + currency_pairs = [(from_currency, to_currency)] + else: + currency_pairs = [(from_currency, 'RON'), ('RON', to_currency)] + + amount = 1.0 + for currency_pair in currency_pairs: + to_select = 'to_ron' + if currency_pair[0] == 'RON': + to_select = 'from_ron' + cur.execute( + f'select {to_select} from exchange where currency = ?', + (currency_pair[1] if currency_pair[0] == 'RON' else currency_pair[0],), + ) + rate = cur.fetchone() + if rate is None: + amount = None + break + rate = rate[0] + amount *= rate + + return amount + sys.modules[__name__] = Module(__name__) diff --git a/server/init.sql b/server/init.sql index 7643ad3..f2d1aee 100644 --- a/server/init.sql +++ b/server/init.sql @@ -60,6 +60,13 @@ create table users_notifications ( foreign key (notification_id) references notifications (id) ); +create table exchange ( + id integer primary key autoincrement, + currency text not null, + to_ron real not null, + from_ron real not null +); + create view V_account_balance as select accounts_transactions.account_id as "account_id",