feat(lotto): POST /api/lotto/purchase/bulk — 결정카드 원클릭 기록

This commit is contained in:
2026-05-11 08:42:27 +09:00
parent 4f85496fe5
commit b936233e7c
3 changed files with 115 additions and 0 deletions

View File

@@ -991,6 +991,51 @@ def update_purchase_results(purchase_id: int, results: list, total_prize: int) -
)
def bulk_insert_purchases_from_briefing(draw_no: int, tier_mode: str, amount: int) -> Dict[str, Any]:
"""tier_mode 에 해당하는 큐레이터 picks 를 purchase_history 에 일괄 INSERT.
tier_mode: "core" | "core_bonus" | "core_bonus_extended" | "full"
"""
briefing = get_briefing(draw_no)
if not briefing:
return {"ok": False, "reason": "briefing not found"}
picks = briefing.get("picks") or {}
if isinstance(picks, list):
# 마이그레이션 이전 형태
picks = {"core": picks, "bonus": [], "extended": [], "pool": []}
tier_chain = {
"core": ["core"],
"core_bonus": ["core", "bonus"],
"core_bonus_extended": ["core", "bonus", "extended"],
"full": ["core", "bonus", "extended", "pool"],
}.get(tier_mode)
if not tier_chain:
return {"ok": False, "reason": f"unknown tier_mode: {tier_mode}"}
inserted_ids = []
with _conn() as conn:
for tier in tier_chain:
for idx, pick in enumerate(picks.get(tier) or []):
source_strategy = f"curator_{tier}"
source_detail = json.dumps({
"tier": tier,
"role": pick.get("risk_tag"),
"set_index": idx,
"draw_no": draw_no,
}, ensure_ascii=False)
numbers_json = json.dumps([pick.get("numbers")], ensure_ascii=False)
cur = conn.execute(
"""INSERT INTO purchase_history
(draw_no, amount, sets, prize, note, numbers, is_real, source_strategy, source_detail)
VALUES (?, ?, 1, 0, '', ?, 1, ?, ?)""",
(draw_no, 1000, numbers_json, source_strategy, source_detail),
)
inserted_ids.append(cur.lastrowid)
return {"ok": True, "inserted_ids": inserted_ids, "sets": len(inserted_ids)}
# --- Lotto Briefings ---
def save_briefing(data: Dict[str, Any]) -> int:

View File

@@ -19,6 +19,7 @@ from .db import (
get_recommendation_performance,
# Phase 2: 구매 이력
add_purchase, get_purchases, update_purchase, delete_purchase, get_purchase_stats,
bulk_insert_purchases_from_briefing,
# Phase 2: 주간 리포트 캐시
save_weekly_report, get_weekly_report_list, get_weekly_report,
# Phase 2: 개인 패턴 분석
@@ -343,6 +344,22 @@ def api_purchase_delete(purchase_id: int):
return {"ok": True}
class BulkPurchaseRequest(BaseModel):
draw_no: int
tier_mode: str # core | core_bonus | core_bonus_extended | full
sets: int # 검증용 — 실제 INSERT는 briefing 기준
amount: int # 검증용
@app.post("/api/lotto/purchase/bulk", status_code=201)
def api_purchase_bulk(body: BulkPurchaseRequest):
"""결정카드 원클릭 기록 — 큐레이터 브리핑 picks 를 tier_mode 기준으로 일괄 기록."""
result = bulk_insert_purchases_from_briefing(body.draw_no, body.tier_mode, body.amount)
if not result["ok"]:
raise HTTPException(status_code=400, detail=result["reason"])
return result
# ── 전략 진화 API ──────────────────────────────────────────────────────────
@app.get("/api/lotto/strategy/weights")