from __future__ import annotations import json from datetime import date from http import HTTPStatus from backend.bootstrap.config import normalize_date, validate_stock_code, validate_text from backend.features.review.agent import ReviewAssistantError class ReviewHttpMixin: def save_trade_entry(self) -> None: try: body = self.read_json_body() self.send_json( {"ok": True, **self.application_service.save_trade_entry(body)}, HTTPStatus.CREATED, ) except (ValueError, json.JSONDecodeError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) def stream_assistant_chat(self) -> None: try: body = self.read_json_body() stream = self.application_service.assistant_stream(body) except (ValueError, json.JSONDecodeError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) return events = ({"type": "delta", "content": chunk} for chunk in stream) self.send_ndjson_stream(events, (ValueError, ReviewAssistantError)) def save_watchlist(self) -> None: try: body = self.read_json_body() code = validate_stock_code(str(body.get("code", ""))) name = validate_text(body.get("name"), "股票名称", 30, required=True) sector = validate_text(body.get("sector"), "所属板块", 50) color = str(body.get("color") or "red") if color not in {"red", "blue", "green", "amber"}: raise ValueError("标记颜色不支持。") remark = validate_text(body.get("remark"), "跟踪备注", 240) service = self.application_service service.database.save_watchlist( service.current_user_id, code, name, sector, color, remark ) self.send_json( { "ok": True, "items": service.database.list_watchlist(service.current_user_id), } ) except (ValueError, json.JSONDecodeError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) def save_note(self) -> None: try: body = self.read_json_body() code = str(body.get("code") or "").strip() if code: code = validate_stock_code(code) stock_name = validate_text(body.get("stock_name"), "股票名称", 30) trade_date = normalize_date(str(body.get("trade_date") or date.today().isoformat())) summary = validate_text(body.get("summary"), "盘面摘要", 500) content = validate_text(body.get("content"), "复盘内容", 5000) plan = validate_text(body.get("plan"), "明日计划", 2000) if not summary and not content and not plan: raise ValueError("每日复盘内容不能全部为空。") raw_id = body.get("id") note_id = int(raw_id) if raw_id else None service = self.application_service saved_id = service.database.save_note( service.current_user_id, code, stock_name, trade_date, content, plan, note_id, summary=summary, ) self.send_json({"ok": True, "id": saved_id}) except (ValueError, TypeError, json.JSONDecodeError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST)