77 lines
2.8 KiB
Python
77 lines
2.8 KiB
Python
from datetime import datetime
|
|
|
|
from app.core.logger import make_log
|
|
from app.core.models import Memory, User, UserBalance, Asset, InternalTransaction
|
|
from app.core.storage import db_session
|
|
|
|
|
|
def get_user_balance(session, user: User, asset: Asset) -> UserBalance:
|
|
assert user, "No user"
|
|
assert asset, "No asset"
|
|
result = session.query(UserBalance).filter(
|
|
UserBalance.user_id == user.id,
|
|
UserBalance.asset_id == asset.id
|
|
)
|
|
results_count = result.count()
|
|
if results_count == 0:
|
|
user_balance = UserBalance(
|
|
user_id=user.id,
|
|
asset_id=asset.id,
|
|
balance=0,
|
|
created=datetime.now(),
|
|
)
|
|
session.add(user_balance)
|
|
session.commit()
|
|
return get_user_balance(session, user, asset)
|
|
elif results_count == 1:
|
|
return result.first()
|
|
else:
|
|
raise Exception(f"Multiple user balances found: {results_count}")
|
|
|
|
|
|
async def make_internal_transaction(
|
|
memory: Memory, user_id: int, asset_id: int, amount: float,
|
|
is_spent: bool, type: str = "NOT_SPECIFIED", spent_transaction_id: int = None
|
|
) -> InternalTransaction:
|
|
amount = float(amount)
|
|
is_spent = bool(is_spent)
|
|
type = str(type)[:256]
|
|
if amount < 0:
|
|
if not is_spent:
|
|
raise Exception(f"Invalid is_spent: {is_spent}, amount: {amount}")
|
|
elif amount > 0:
|
|
if is_spent:
|
|
raise Exception(f"Invalid is_spent: {is_spent}, amount: {amount}")
|
|
else:
|
|
raise Exception(f"Invalid amount: {amount}")
|
|
|
|
abs_amount = abs(amount)
|
|
with db_session(auto_commit=False) as session:
|
|
async with memory.transaction():
|
|
user = session.query(User).filter_by(id=user_id).first()
|
|
assert user, "No user"
|
|
asset = session.query(Asset).filter_by(id=asset_id).first()
|
|
assert asset, "No asset"
|
|
user_balance = get_user_balance(session, user, asset)
|
|
assert user_balance, "No user balance"
|
|
if is_spent is True:
|
|
if abs_amount > user_balance.balance:
|
|
raise Exception(f"Insufficient balance: {user_balance.balance} < {abs_amount}")
|
|
|
|
user_balance.balance = float(user_balance.balance) + amount
|
|
user_balance.updated = datetime.now()
|
|
|
|
internal_transaction = InternalTransaction(
|
|
user_id=user.id,
|
|
asset_id=asset.id,
|
|
amount=abs_amount,
|
|
is_spent=is_spent,
|
|
type=type,
|
|
spent_transaction_id=spent_transaction_id,
|
|
created=datetime.now(),
|
|
)
|
|
session.add(internal_transaction)
|
|
session.commit()
|
|
|
|
make_log(user, f"Made internal transaction: {'-' if is_spent else ''}{abs_amount} {asset.symbol}, type: {type}")
|