@@ -50,6 +50,7 @@ def _ensure_table(self):
5050 cur .execute ("""
5151 CREATE TABLE IF NOT EXISTS qd_analysis_memory (
5252 id SERIAL PRIMARY KEY,
53+ user_id INT,
5354 market VARCHAR(50) NOT NULL,
5455 symbol VARCHAR(50) NOT NULL,
5556 decision VARCHAR(10) NOT NULL,
@@ -77,18 +78,22 @@ def _ensure_table(self):
7778
7879 CREATE INDEX IF NOT EXISTS idx_analysis_memory_created
7980 ON qd_analysis_memory(created_at DESC);
81+
82+ CREATE INDEX IF NOT EXISTS idx_analysis_memory_user
83+ ON qd_analysis_memory(user_id);
8084 """ )
8185 db .commit ()
8286 cur .close ()
8387 except Exception as e :
8488 logger .warning (f"Memory table creation skipped: { e } " )
8589
86- def store (self , analysis_result : Dict [str , Any ]) -> Optional [int ]:
90+ def store (self , analysis_result : Dict [str , Any ], user_id : int = None ) -> Optional [int ]:
8791 """
8892 Store an analysis result for future reference.
8993
9094 Args:
9195 analysis_result: Result from FastAnalysisService.analyze()
96+ user_id: User ID who created this analysis
9297
9398 Returns:
9499 Memory ID or None if failed
@@ -115,20 +120,20 @@ def store(self, analysis_result: Dict[str, Any]) -> Optional[int]:
115120
116121 cur .execute ("""
117122 INSERT INTO qd_analysis_memory (
118- market, symbol, decision, confidence,
123+ user_id, market, symbol, decision, confidence,
119124 price_at_analysis, entry_price, stop_loss, take_profit,
120125 summary, reasons, risks, scores, indicators_snapshot, raw_result
121- ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
126+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )
122127 RETURNING id
123- """ , (market , symbol , decision , confidence , price , entry , stop , take ,
128+ """ , (user_id , market , symbol , decision , confidence , price , entry , stop , take ,
124129 summary , reasons , risks , scores , indicators , raw ))
125130
126131 # 使用 lastrowid 属性获取 ID(execute 内部已经处理了 RETURNING)
127132 memory_id = cur .lastrowid
128133 db .commit ()
129134 cur .close ()
130135
131- logger .info (f"Stored analysis memory #{ memory_id } for { symbol } " )
136+ logger .info (f"Stored analysis memory #{ memory_id } for { symbol } by user { user_id } " )
132137 return memory_id
133138
134139 except Exception as e :
@@ -192,7 +197,7 @@ def get_all_history(self, user_id: int = None, page: int = 1, page_size: int = 2
192197 Get all analysis history with pagination.
193198
194199 Args:
195- user_id: Optional user ID filter (not used currently, for future )
200+ user_id: User ID filter (required to show only user's own history )
196201 page: Page number (1-indexed)
197202 page_size: Items per page
198203
@@ -205,21 +210,27 @@ def get_all_history(self, user_id: int = None, page: int = 1, page_size: int = 2
205210 with get_db_connection () as db :
206211 cur = db .cursor ()
207212
213+ # Build WHERE clause based on user_id
214+ where_clause = "WHERE user_id = %s" if user_id else ""
215+ params_count = (user_id ,) if user_id else ()
216+
208217 # Get total count
209- cur .execute ("SELECT COUNT(*) as cnt FROM qd_analysis_memory" )
218+ cur .execute (f "SELECT COUNT(*) as cnt FROM qd_analysis_memory { where_clause } " , params_count )
210219 total_row = cur .fetchone ()
211220 total = total_row ['cnt' ] if total_row else 0
212221
213222 # Get paginated results
214- cur .execute ("""
223+ params = (user_id , page_size , offset ) if user_id else (page_size , offset )
224+ cur .execute (f"""
215225 SELECT
216226 id, market, symbol, decision, confidence, price_at_analysis,
217227 summary, reasons, scores, indicators_snapshot, raw_result,
218228 created_at, validated_at, was_correct, actual_return_pct
219229 FROM qd_analysis_memory
230+ { where_clause }
220231 ORDER BY created_at DESC
221232 LIMIT %s OFFSET %s
222- """ , ( page_size , offset ) )
233+ """ , params )
223234
224235 rows = cur .fetchall () or []
225236 cur .close ()
@@ -254,20 +265,25 @@ def get_all_history(self, user_id: int = None, page: int = 1, page_size: int = 2
254265 logger .error (f"Failed to get all history: { e } " )
255266 return {"items" : [], "total" : 0 , "page" : page , "page_size" : page_size }
256267
257- def delete_history (self , memory_id : int ) -> bool :
268+ def delete_history (self , memory_id : int , user_id : int = None ) -> bool :
258269 """
259270 Delete a history record by ID.
260271
261272 Args:
262273 memory_id: The ID of the analysis memory to delete
274+ user_id: User ID to ensure user can only delete their own records
263275
264276 Returns:
265277 True if deleted successfully, False otherwise
266278 """
267279 try :
268280 with get_db_connection () as db :
269281 cur = db .cursor ()
270- cur .execute ("DELETE FROM qd_analysis_memory WHERE id = %s" , (memory_id ,))
282+ if user_id :
283+ # Only delete if it belongs to the user
284+ cur .execute ("DELETE FROM qd_analysis_memory WHERE id = %s AND user_id = %s" , (memory_id , user_id ))
285+ else :
286+ cur .execute ("DELETE FROM qd_analysis_memory WHERE id = %s" , (memory_id ,))
271287 db .commit ()
272288 affected = cur .rowcount
273289 cur .close ()
0 commit comments