Use ISIN numbers instead of share symbols and add comment field to database.

Fixes #65
This commit is contained in:
Administrator 2022-04-19 08:20:28 +02:00
parent 094b21a366
commit e9291d3a97
6 changed files with 90 additions and 53 deletions

View File

@ -2,7 +2,7 @@ __author__ = "Florian Kaiser"
__copyright__ = "Copyright 2022, Project Aktienbot" __copyright__ = "Copyright 2022, Project Aktienbot"
__credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"] __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"]
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.1"
import os import os
@ -27,22 +27,23 @@ def get_portfolio():
return_portfolio = [] return_portfolio = []
# Get all transactions of current user # Get all transactions of current user
transactions = db.session.execute("SELECT symbol, SUM(count), SUM(price), MAX(time) FROM `transactions` WHERE email = '" + email + "' GROUP BY symbol;").all() transactions = db.session.execute("SELECT isin, comment, SUM(count), SUM(price), MAX(time) FROM `transactions` WHERE email = '" + email + "' GROUP BY isin, comment;").all()
# If there are no transactions, return empty portfolio # If there are no transactions, return empty portfolio
# Otherwise calculate portfolio # Otherwise calculate portfolio
if transactions is not None: if transactions is not None:
for row in transactions: for row in transactions:
data = { data = {
"symbol": row[0], "isin": row[0],
"count": row[1], "comment": row[1],
# "calculated_price": row[2], "count": row[2],
"last_transaction": row[3], # "calculated_price": row[3],
"last_transaction": row[4],
'current_price': 0 'current_price': 0
} }
# Add current share value to portfolio # Add current share value to portfolio
query_share_price = db.session.query(SharePrice).filter_by(symbol=row[0]).order_by(SharePrice.date.desc()).first() query_share_price = db.session.query(SharePrice).filter_by(isin=row[0]).order_by(SharePrice.date.desc()).first()
if query_share_price is not None: if query_share_price is not None:
data['current_price'] = query_share_price.as_dict()['price'] data['current_price'] = query_share_price.as_dict()['price']

View File

@ -2,17 +2,16 @@ __author__ = "Florian Kaiser"
__copyright__ = "Copyright 2022, Project Aktienbot" __copyright__ = "Copyright 2022, Project Aktienbot"
__credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"] __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"]
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.1"
import datetime import datetime
import os import os
from apiflask import APIBlueprint, abort from apiflask import APIBlueprint, abort
from app.auth import auth
from app.models import SharePrice
from app.db import database as db from app.db import database as db
from app.helper_functions import make_response from app.helper_functions import make_response
from app.auth import auth from app.models import SharePrice
from app.schema import SymbolPriceSchema from app.schema import SymbolPriceSchema
share_price_blueprint = APIBlueprint('share_price', __name__, url_prefix='/api') share_price_blueprint = APIBlueprint('share_price', __name__, url_prefix='/api')
@ -25,7 +24,7 @@ __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file
@share_price_blueprint.doc(summary="Returns all transaction symbols", description="Returns all transaction symbols for all users") @share_price_blueprint.doc(summary="Returns all transaction symbols", description="Returns all transaction symbols for all users")
def get_transaction_symbols(): def get_transaction_symbols():
# Get all transaction symbols # Get all transaction symbols
symbols = db.session.execute("SELECT symbol FROM `transactions` GROUP BY symbol;").all() symbols = db.session.execute("SELECT isin FROM `transactions` GROUP BY isin;").all()
return_symbols = [] return_symbols = []
for s in symbols: for s in symbols:
@ -38,11 +37,11 @@ def get_transaction_symbols():
@share_price_blueprint.output({}, 200) @share_price_blueprint.output({}, 200)
@share_price_blueprint.input(schema=SymbolPriceSchema) @share_price_blueprint.input(schema=SymbolPriceSchema)
@share_price_blueprint.auth_required(auth) @share_price_blueprint.auth_required(auth)
@share_price_blueprint.doc(summary="Returns all transaction symbols", description="Returns all transaction symbols for all users") @share_price_blueprint.doc(summary="Adds new price for isin", description="Adds new price to database")
def add_symbol_price(data): def add_symbol_price(data):
# Check if required data is available # Check if required data is available
if not check_if_symbol_data_exists(data): if not check_if_isin_data_exists(data):
abort(400, message="Symbol missing") abort(400, message="ISIN missing")
if not check_if_price_data_exists(data): if not check_if_price_data_exists(data):
abort(400, message="Price missing") abort(400, message="Price missing")
@ -52,7 +51,7 @@ def add_symbol_price(data):
# Add share price # Add share price
share_price = SharePrice( share_price = SharePrice(
symbol=data['symbol'], isin=data['isin'],
price=data['price'], price=data['price'],
date=datetime.datetime.strptime(data['time'], '%Y-%m-%dT%H:%M:%S.%fZ'), date=datetime.datetime.strptime(data['time'], '%Y-%m-%dT%H:%M:%S.%fZ'),
) )
@ -63,11 +62,11 @@ def add_symbol_price(data):
return make_response(share_price.as_dict(), 200, "Successfully added price") return make_response(share_price.as_dict(), 200, "Successfully added price")
def check_if_symbol_data_exists(data): def check_if_isin_data_exists(data):
if 'symbol' not in data: if 'isin' not in data:
return False return False
if data['symbol'] == "" or data['symbol'] is None: if data['isin'] == "" or data['isin'] is None:
return False return False
return True return True

View File

@ -2,17 +2,16 @@ __author__ = "Florian Kaiser"
__copyright__ = "Copyright 2022, Project Aktienbot" __copyright__ = "Copyright 2022, Project Aktienbot"
__credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"] __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"]
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.1"
import os import os
from apiflask import APIBlueprint, abort from apiflask import APIBlueprint, abort
from app.auth import auth from app.auth import auth
from app.db import database as db from app.db import database as db
from app.helper_functions import make_response, get_email_or_abort_401 from app.helper_functions import make_response, get_email_or_abort_401
from app.models import Share from app.models import Share
from app.schema import SymbolSchema, SymbolResponseSchema, DeleteSuccessfulSchema from app.schema import SymbolSchema, SymbolResponseSchema, DeleteSuccessfulSchema, SymbolRemoveSchema
shares_blueprint = APIBlueprint('share', __name__, url_prefix='/api') shares_blueprint = APIBlueprint('share', __name__, url_prefix='/api')
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
@ -27,16 +26,20 @@ def add_symbol(data):
email = get_email_or_abort_401() email = get_email_or_abort_401()
# Check if required data is available # Check if required data is available
if not check_if_symbol_data_exists(data): if not check_if_isin_data_exists(data):
abort(400, message="Symbol missing") abort(400, message="ISIN missing")
if not check_if_comment_data_exists(data):
abort(400, message="Comment missing")
# Check if share already exists # Check if share already exists
check_share = db.session.query(Share).filter_by(symbol=data['symbol'], email=email).first() check_share = db.session.query(Share).filter_by(isin=data['isin'], email=email).first()
if check_share is None: if check_share is None:
# Keyword doesn't exist yet for this user -> add it # Keyword doesn't exist yet for this user -> add it
new_symbol = Share( new_symbol = Share(
email=email, email=email,
symbol=data['symbol'] isin=data['isin'],
comment=data['comment']
) )
db.session.add(new_symbol) db.session.add(new_symbol)
db.session.commit() db.session.commit()
@ -48,23 +51,23 @@ def add_symbol(data):
@shares_blueprint.route('/share', methods=['DELETE']) @shares_blueprint.route('/share', methods=['DELETE'])
@shares_blueprint.output(DeleteSuccessfulSchema, 200) @shares_blueprint.output(DeleteSuccessfulSchema, 200)
@shares_blueprint.input(schema=SymbolSchema) @shares_blueprint.input(schema=SymbolRemoveSchema)
@shares_blueprint.auth_required(auth) @shares_blueprint.auth_required(auth)
@shares_blueprint.doc(summary="Removes existing symbol", description="Removes existing symbol for current user") @shares_blueprint.doc(summary="Removes existing symbol", description="Removes existing symbol for current user")
def remove_symbol(data): def remove_symbol(data):
email = get_email_or_abort_401() email = get_email_or_abort_401()
# Check if required data is available # Check if required data is available
if not check_if_symbol_data_exists(data): if not check_if_isin_data_exists(data):
abort(400, message="Symbol missing") abort(400, message="ISIN missing")
# Check if share exists # Check if share exists
check_share = db.session.query(Share).filter_by(symbol=data['symbol'], email=email).first() check_share = db.session.query(Share).filter_by(isin=data['isin'], email=email).first()
if check_share is None: if check_share is None:
abort(500, "Symbol doesn't exist for this user") abort(500, "Symbol doesn't exist for this user")
else: else:
# Delete share # Delete share
db.session.query(Share).filter_by(symbol=data['symbol'], email=email).delete() db.session.query(Share).filter_by(isin=data['isin'], email=email).delete()
db.session.commit() db.session.commit()
return make_response({}, 200, "Successfully removed symbol") return make_response({}, 200, "Successfully removed symbol")
@ -89,11 +92,21 @@ def get_symbol():
return make_response(return_symbols, 200, "Successfully loaded symbols") return make_response(return_symbols, 200, "Successfully loaded symbols")
def check_if_symbol_data_exists(data): def check_if_isin_data_exists(data):
if "symbol" not in data: if "isin" not in data:
return False return False
if data['symbol'] == "" or data['symbol'] is None: if data['isin'] == "" or data['isin'] is None:
return False
return True
def check_if_comment_data_exists(data):
if "comment" not in data:
return False
if data['comment'] == "" or data['comment'] is None:
return False return False
return True return True

View File

@ -2,13 +2,12 @@ __author__ = "Florian Kaiser"
__copyright__ = "Copyright 2022, Project Aktienbot" __copyright__ = "Copyright 2022, Project Aktienbot"
__credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"] __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"]
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.1"
import datetime import datetime
import os import os
from apiflask import abort, APIBlueprint from apiflask import abort, APIBlueprint
from app.auth import auth from app.auth import auth
from app.db import database as db from app.db import database as db
from app.helper_functions import make_response, get_email_or_abort_401 from app.helper_functions import make_response, get_email_or_abort_401
@ -28,12 +27,15 @@ def add_transaction(data):
email = get_email_or_abort_401() email = get_email_or_abort_401()
# Check if required data is available # Check if required data is available
if not check_if_symbol_data_exists(data): if not check_if_isin_data_exists(data):
abort(400, "Symbol missing") abort(400, "ISIN missing")
if not check_if_time_data_exists(data): if not check_if_time_data_exists(data):
abort(400, "Time missing") abort(400, "Time missing")
if not check_if_comment_data_exists(data):
abort(400, "Comment missing")
if not check_if_count_data_exists(data): if not check_if_count_data_exists(data):
abort(400, "Count missing") abort(400, "Count missing")
@ -43,7 +45,8 @@ def add_transaction(data):
# Add transaction # Add transaction
new_transaction = Transaction( new_transaction = Transaction(
email=email, email=email,
symbol=data['symbol'], isin=data['isin'],
comment=data['comment'],
time=datetime.datetime.strptime(data['time'], '%Y-%m-%dT%H:%M:%S.%fZ'), time=datetime.datetime.strptime(data['time'], '%Y-%m-%dT%H:%M:%S.%fZ'),
count=data['count'], count=data['count'],
price=data['price'] price=data['price']
@ -74,11 +77,11 @@ def get_transaction():
return make_response(return_transactions, 200, "Successfully loaded transactions") return make_response(return_transactions, 200, "Successfully loaded transactions")
def check_if_symbol_data_exists(data): def check_if_isin_data_exists(data):
if "symbol" not in data: if "isin" not in data:
return False return False
if data['symbol'] == "" or data['symbol'] is None: if data['isin'] == "" or data['isin'] is None:
return False return False
return True return True
@ -94,6 +97,16 @@ def check_if_time_data_exists(data):
return True return True
def check_if_comment_data_exists(data):
if "comment" not in data:
return False
if data['comment'] == "" or data['comment'] is None:
return False
return True
def check_if_count_data_exists(data): def check_if_count_data_exists(data):
if "count" not in data: if "count" not in data:
return False return False

View File

@ -2,7 +2,7 @@ __author__ = "Florian Kaiser"
__copyright__ = "Copyright 2022, Project Aktienbot" __copyright__ = "Copyright 2022, Project Aktienbot"
__credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"] __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"]
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.1"
from app.db import database as db from app.db import database as db
@ -30,7 +30,8 @@ class Transaction(db.Model):
__tablename__ = 'transactions' __tablename__ = 'transactions'
t_id = db.Column('t_id', db.Integer(), nullable=False, unique=True, primary_key=True) t_id = db.Column('t_id', db.Integer(), nullable=False, unique=True, primary_key=True)
email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE')) email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE'))
symbol = db.Column('symbol', db.String(255)) isin = db.Column('isin', db.String(255))
comment = db.Column('comment', db.String(255))
time = db.Column('time', db.DateTime()) time = db.Column('time', db.DateTime())
count = db.Column('count', db.Integer()) count = db.Column('count', db.Integer())
price = db.Column('price', db.Float()) price = db.Column('price', db.Float())
@ -53,7 +54,8 @@ class Share(db.Model):
__tablename__ = 'shares' __tablename__ = 'shares'
a_id = db.Column('a_id', db.Integer(), nullable=False, unique=True, primary_key=True) a_id = db.Column('a_id', db.Integer(), nullable=False, unique=True, primary_key=True)
email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE')) email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE'))
symbol = db.Column('symbol', db.String(255)) isin = db.Column('isin', db.String(255))
comment = db.Column('comment', db.String(255))
def as_dict(self): def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns} return {c.name: getattr(self, c.name) for c in self.__table__.columns}
@ -62,7 +64,7 @@ class Share(db.Model):
class SharePrice(db.Model): class SharePrice(db.Model):
__tablename__ = 'share_price' __tablename__ = 'share_price'
id = db.Column('id', db.Integer(), nullable=False, unique=True, primary_key=True) id = db.Column('id', db.Integer(), nullable=False, unique=True, primary_key=True)
symbol = db.Column('symbol', db.String(255)) isin = db.Column('isin', db.String(255))
price = db.Column('price', db.Float()) price = db.Column('price', db.Float())
date = db.Column('date', db.DateTime()) date = db.Column('date', db.DateTime())

View File

@ -2,7 +2,7 @@ __author__ = "Florian Kaiser"
__copyright__ = "Copyright 2022, Project Aktienbot" __copyright__ = "Copyright 2022, Project Aktienbot"
__credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"] __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin Pauer"]
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.1"
from apiflask import Schema from apiflask import Schema
from apiflask.fields import Integer, String, Boolean, Field, Float from apiflask.fields import Integer, String, Boolean, Field, Float
@ -72,18 +72,24 @@ class KeywordSchema(Schema):
class SymbolSchema(Schema): class SymbolSchema(Schema):
symbol = String() isin = String()
comment = String()
class SymbolRemoveSchema(Schema):
isin = String()
class TransactionSchema(Schema): class TransactionSchema(Schema):
symbol = String() isin = String()
comment = String()
time = String(validate=validate.Regexp(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z")) time = String(validate=validate.Regexp(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z"))
count = Integer() count = Integer()
price = Float() price = Float()
class SymbolPriceSchema(Schema): class SymbolPriceSchema(Schema):
symbol = String() isin = String()
time = String(validate=validate.Regexp(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z")) time = String(validate=validate.Regexp(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z"))
price = Float() price = Float()
@ -103,7 +109,8 @@ class KeywordResponseSchema(Schema):
class SymbolResponseSchema(Schema): class SymbolResponseSchema(Schema):
symbol = String() isin = String()
comment = String()
s_id = Integer() s_id = Integer()
email = Email() email = Email()
@ -115,14 +122,16 @@ class PortfolioShareResponseSchema(Schema):
class TransactionResponseSchema(Schema): class TransactionResponseSchema(Schema):
email = Email() email = Email()
symbol = String() isin = String()
comment = String()
time = String() time = String()
count = Integer() count = Integer()
price = Float() price = Float()
class PortfolioResponseSchema(Schema): class PortfolioResponseSchema(Schema):
symbol = String() isin = String()
comment = String()
last_transaction = String() last_transaction = String()
count = Integer() count = Integer()
# price = Float() # price = Float()