144 lines
5.0 KiB
Python

import logging
from sqlalchemy.orm import Session
from app import crud, schemas
from app.models.transaction import TransactionType
from app.models.wallet import WalletType
from app.core.email import send_bot_completion_notification
logger = logging.getLogger(__name__)
def process_completed_bot_purchases(db: Session) -> int:
"""
Process bot purchases that have reached their end time.
Returns the number of bot purchases processed.
"""
# Get bot purchases that are running but have passed their end time
completed_due = crud.bot_purchase.get_completed_due(db)
if not completed_due:
return 0
count = 0
for purchase in completed_due:
try:
# Get user and bot information
user = crud.user.get(db, id=purchase.user_id)
bot = crud.bot.get(db, id=purchase.bot_id)
if not user or not bot:
logger.error(
f"User or bot not found for bot purchase {purchase.id}. "
f"User ID: {purchase.user_id}, Bot ID: {purchase.bot_id}"
)
continue
# Get user's trading wallet
trading_wallet = crud.wallet.get_by_user_and_type(
db, user_id=user.id, wallet_type=WalletType.TRADING
)
if not trading_wallet:
logger.error(
f"Trading wallet not found for user {user.id} "
f"when processing bot purchase {purchase.id}"
)
continue
# Calculate the total amount to be credited (principal + ROI)
principal = purchase.amount
roi = purchase.expected_roi_amount
total = principal + roi
# Update trading wallet balance
crud.wallet.update_balance(db, wallet_id=trading_wallet.id, amount=total, add=True)
# Create transaction records
# 1. Return of principal
principal_transaction = crud.transaction.create(
db,
obj_in=schemas.TransactionCreate(
user_id=user.id,
wallet_id=trading_wallet.id,
amount=principal,
transaction_type=TransactionType.BOT_EARNING,
description=f"Bot {bot.name} - Return of principal",
bot_purchase_id=purchase.id,
),
)
# 2. ROI
roi_transaction = crud.transaction.create(
db,
obj_in=schemas.TransactionCreate(
user_id=user.id,
wallet_id=trading_wallet.id,
amount=roi,
transaction_type=TransactionType.BOT_EARNING,
description=f"Bot {bot.name} - ROI",
bot_purchase_id=purchase.id,
related_transaction_id=principal_transaction.id,
),
)
# Update the first transaction to reference the second
crud.transaction.update(
db,
db_obj=principal_transaction,
obj_in={"related_transaction_id": roi_transaction.id},
)
# Mark the bot purchase as completed
crud.bot_purchase.complete(db, db_obj=purchase)
# Send email notification
send_bot_completion_notification(
email_to=user.email,
bot_name=bot.name,
amount=principal,
roi=roi,
)
count += 1
except Exception as e:
logger.error(
f"Error processing bot purchase {purchase.id}: {str(e)}"
)
return count
def get_bot_simulation_stats(db: Session) -> dict:
"""
Get statistics about bot simulations.
"""
# Get counts by status
running_count = len(crud.bot_purchase.get_by_status(
db, status=schemas.BotPurchaseStatus.RUNNING
))
completed_count = len(crud.bot_purchase.get_by_status(
db, status=schemas.BotPurchaseStatus.COMPLETED
))
cancelled_count = len(crud.bot_purchase.get_by_status(
db, status=schemas.BotPurchaseStatus.CANCELLED
))
# Calculate total invested amount (running bots)
running_purchases = crud.bot_purchase.get_by_status(
db, status=schemas.BotPurchaseStatus.RUNNING
)
total_invested = sum(p.amount for p in running_purchases)
# Calculate total ROI generated (completed bots)
completed_purchases = crud.bot_purchase.get_by_status(
db, status=schemas.BotPurchaseStatus.COMPLETED
)
total_roi_generated = sum(p.expected_roi_amount for p in completed_purchases)
return {
"running_count": running_count,
"completed_count": completed_count,
"cancelled_count": cancelled_count,
"total_invested": total_invested,
"total_roi_generated": total_roi_generated,
}