diff --git a/backend_api_python/app/routes/strategy.py b/backend_api_python/app/routes/strategy.py
index a9b6834..17d7df5 100644
--- a/backend_api_python/app/routes/strategy.py
+++ b/backend_api_python/app/routes/strategy.py
@@ -816,9 +816,6 @@ def get_strategy_notifications():
user_strategy_ids = [r.get('id') for r in rows if r.get('id')]
cur.close()
- if not user_strategy_ids:
- return jsonify({'code': 1, 'msg': 'success', 'data': {'items': []}})
-
where = []
args = []
@@ -830,9 +827,15 @@ def get_strategy_notifications():
else:
return jsonify({'code': 1, 'msg': 'success', 'data': {'items': []}})
else:
- placeholders = ",".join(["?"] * len(user_strategy_ids))
- where.append(f"strategy_id IN ({placeholders})")
- args.extend(user_strategy_ids)
+ if user_strategy_ids:
+ placeholders = ",".join(["?"] * len(user_strategy_ids))
+ where.append(f"(strategy_id IN ({placeholders}) OR (strategy_id IS NULL AND user_id = ?))")
+ args.extend(user_strategy_ids)
+ args.append(user_id)
+ else:
+ # Only portfolio monitor notifications (strategy_id is NULL)
+ where.append("strategy_id IS NULL AND user_id = ?")
+ args.append(user_id)
if since_id:
where.append("id > ?")
@@ -889,15 +892,18 @@ def mark_notification_read():
if not notification_id:
return jsonify({'code': 0, 'msg': 'Missing id'}), 400
- # Only update notifications for user's strategies
+ # Update notifications for user's strategies OR portfolio monitor notifications
with get_db_connection() as db:
cur = db.cursor()
cur.execute(
"""
UPDATE qd_strategy_notifications SET is_read = 1
- WHERE id = ? AND strategy_id IN (SELECT id FROM qd_strategies_trading WHERE user_id = ?)
+ WHERE id = ? AND (
+ strategy_id IN (SELECT id FROM qd_strategies_trading WHERE user_id = ?)
+ OR (strategy_id IS NULL AND user_id = ?)
+ )
""",
- (int(notification_id), user_id)
+ (int(notification_id), user_id, user_id)
)
db.commit()
cur.close()
@@ -920,8 +926,9 @@ def mark_all_notifications_read():
"""
UPDATE qd_strategy_notifications SET is_read = 1
WHERE strategy_id IN (SELECT id FROM qd_strategies_trading WHERE user_id = ?)
+ OR (strategy_id IS NULL AND user_id = ?)
""",
- (user_id,)
+ (user_id, user_id)
)
db.commit()
cur.close()
@@ -944,8 +951,9 @@ def clear_notifications():
"""
DELETE FROM qd_strategy_notifications
WHERE strategy_id IN (SELECT id FROM qd_strategies_trading WHERE user_id = ?)
+ OR (strategy_id IS NULL AND user_id = ?)
""",
- (user_id,)
+ (user_id, user_id)
)
db.commit()
cur.close()
diff --git a/backend_api_python/app/services/portfolio_monitor.py b/backend_api_python/app/services/portfolio_monitor.py
index 0c35f03..9288153 100644
--- a/backend_api_python/app/services/portfolio_monitor.py
+++ b/backend_api_python/app/services/portfolio_monitor.py
@@ -768,8 +768,9 @@ def _send_monitor_notification(
cur.close()
elif ch == 'telegram':
chat_id = targets.get('telegram', '')
+ token_override = targets.get('telegram_bot_token', '')
if chat_id:
- notifier._notify_telegram(chat_id=chat_id, text=f"{error_title}\n\n{error_msg}", parse_mode="HTML")
+ notifier._notify_telegram(chat_id=chat_id, text=f"{error_title}\n\n{error_msg}", token_override=token_override, parse_mode="HTML")
elif ch == 'email':
to_email = targets.get('email', '')
if to_email:
@@ -815,11 +816,13 @@ def _send_monitor_notification(
elif ch == 'telegram':
chat_id = targets.get('telegram', '')
+ token_override = targets.get('telegram_bot_token', '')
if chat_id:
# Use Telegram-optimized format
notifier._notify_telegram(
chat_id=chat_id,
text=telegram_report,
+ token_override=token_override,
parse_mode="HTML"
)
@@ -1099,8 +1102,9 @@ def _check_position_alerts():
cur.close()
elif ch == 'telegram':
chat_id = targets.get('telegram', '')
+ token_override = targets.get('telegram_bot_token', '')
if chat_id:
- notifier._notify_telegram(chat_id=chat_id, text=alert_message, parse_mode="HTML")
+ notifier._notify_telegram(chat_id=chat_id, text=alert_message, token_override=token_override, parse_mode="HTML")
elif ch == 'email':
to_email = targets.get('email', '')
if to_email:
diff --git a/backend_api_python/app/services/trading_executor.py b/backend_api_python/app/services/trading_executor.py
index 1c49b80..a026f29 100644
--- a/backend_api_python/app/services/trading_executor.py
+++ b/backend_api_python/app/services/trading_executor.py
@@ -52,29 +52,48 @@ class TradingExecutor:
self._ensure_db_columns()
def _ensure_db_columns(self):
- """确保必要的数据库字段存在"""
+ """确保必要的数据库字段存在(支持 SQLite 和 PostgreSQL)"""
try:
+ db_type = os.getenv('DB_TYPE', 'sqlite').lower()
with get_db_connection() as db:
cursor = db.cursor()
+ col_names = set()
- # SQLite 兼容:使用 PRAGMA table_info 检查列是否存在
- try:
- cursor.execute("PRAGMA table_info(qd_strategy_positions)")
- cols = cursor.fetchall() or []
- col_names = {c.get('name') for c in cols if isinstance(c, dict)}
- except Exception:
- col_names = set()
+ if db_type == 'postgresql':
+ # PostgreSQL: 使用 information_schema 查询列
+ try:
+ cursor.execute("""
+ SELECT column_name FROM information_schema.columns
+ WHERE table_name = 'qd_strategy_positions'
+ """)
+ cols = cursor.fetchall() or []
+ col_names = {c.get('column_name') or c.get('COLUMN_NAME') for c in cols if isinstance(c, dict)}
+ except Exception:
+ col_names = set()
+ else:
+ # SQLite: 使用 PRAGMA table_info
+ try:
+ cursor.execute("PRAGMA table_info(qd_strategy_positions)")
+ cols = cursor.fetchall() or []
+ col_names = {c.get('name') for c in cols if isinstance(c, dict)}
+ except Exception:
+ col_names = set()
if 'highest_price' not in col_names:
- logger.info("Adding highest_price column to qd_strategy_positions (SQLite)...")
- # SQLite 不支持 AFTER 子句,类型用 REAL 即可
- cursor.execute("ALTER TABLE qd_strategy_positions ADD COLUMN highest_price REAL DEFAULT 0")
+ logger.info(f"Adding highest_price column to qd_strategy_positions ({db_type})...")
+ if db_type == 'postgresql':
+ cursor.execute("ALTER TABLE qd_strategy_positions ADD COLUMN IF NOT EXISTS highest_price DOUBLE PRECISION DEFAULT 0")
+ else:
+ cursor.execute("ALTER TABLE qd_strategy_positions ADD COLUMN highest_price REAL DEFAULT 0")
db.commit()
logger.info("highest_price column added")
if 'lowest_price' not in col_names:
- logger.info("Adding lowest_price column to qd_strategy_positions (SQLite)...")
- cursor.execute("ALTER TABLE qd_strategy_positions ADD COLUMN lowest_price REAL DEFAULT 0")
+ logger.info(f"Adding lowest_price column to qd_strategy_positions ({db_type})...")
+ if db_type == 'postgresql':
+ cursor.execute("ALTER TABLE qd_strategy_positions ADD COLUMN IF NOT EXISTS lowest_price DOUBLE PRECISION DEFAULT 0")
+ else:
+ cursor.execute("ALTER TABLE qd_strategy_positions ADD COLUMN lowest_price REAL DEFAULT 0")
db.commit()
logger.info("lowest_price column added")