feat(music-lab): market_trends·trend_reports DB + market.py + /api/music/market 5개 API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 12:26:37 +09:00
parent 3b9dcfe0dd
commit 26b9eea0dc
4 changed files with 303 additions and 0 deletions

View File

@@ -137,6 +137,38 @@ def init_db() -> None:
""")
conn.execute("CREATE INDEX IF NOT EXISTS idx_rr_month ON revenue_records(record_month DESC)")
# ── market_trends 테이블 ──────────────────────────────────────────
conn.execute("""
CREATE TABLE IF NOT EXISTS market_trends (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source TEXT NOT NULL DEFAULT '',
country TEXT NOT NULL DEFAULT '',
genre TEXT NOT NULL DEFAULT '',
keyword TEXT NOT NULL DEFAULT '',
score REAL NOT NULL DEFAULT 0.0,
rank INTEGER,
metadata TEXT NOT NULL DEFAULT '{}',
collected_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
)
""")
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_mt_country_source "
"ON market_trends(country, source, collected_at DESC)"
)
# ── trend_reports 테이블 ──────────────────────────────────────────
conn.execute("""
CREATE TABLE IF NOT EXISTS trend_reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
report_date TEXT UNIQUE NOT NULL DEFAULT '',
top_genres TEXT NOT NULL DEFAULT '[]',
top_keywords TEXT NOT NULL DEFAULT '[]',
recommended_styles TEXT NOT NULL DEFAULT '[]',
insights TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
)
""")
# ── music_tasks CRUD ──────────────────────────────────────────────────────────
@@ -583,3 +615,88 @@ def get_revenue_dashboard() -> dict:
"by_month": [dict(r) for r in by_month],
"by_country": [dict(r) for r in by_country],
}
# ── market_trends CRUD ────────────────────────────────────────────────────────
def insert_market_trends(trends: list) -> None:
with _conn() as conn:
conn.executemany(
"""INSERT INTO market_trends (source, country, genre, keyword, score, rank, metadata)
VALUES (?, ?, ?, ?, ?, ?, ?)""",
[(t.get("source",""), t.get("country",""), t.get("genre",""),
t.get("keyword",""), t.get("score", 0.0), t.get("rank"),
json.dumps(t.get("metadata", {})))
for t in trends],
)
def get_market_trends(
country: str = None, genre: str = None, source: str = None, days: int = 7
) -> list:
with _conn() as conn:
q = "SELECT * FROM market_trends WHERE collected_at >= datetime('now', ?)"
params: list = [f"-{days} days"]
if country:
q += " AND country=?"; params.append(country)
if genre:
q += " AND genre=?"; params.append(genre)
if source:
q += " AND source=?"; params.append(source)
q += " ORDER BY collected_at DESC LIMIT 500"
rows = conn.execute(q, params).fetchall()
return [
{"id": r["id"], "source": r["source"], "country": r["country"],
"genre": r["genre"], "keyword": r["keyword"], "score": r["score"],
"rank": r["rank"], "metadata": json.loads(r["metadata"]),
"collected_at": r["collected_at"]}
for r in rows
]
# ── trend_reports CRUD ────────────────────────────────────────────────────────
def upsert_trend_report(data: dict) -> None:
with _conn() as conn:
conn.execute(
"""INSERT INTO trend_reports
(report_date, top_genres, top_keywords, recommended_styles, insights)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(report_date) DO UPDATE SET
top_genres=excluded.top_genres,
top_keywords=excluded.top_keywords,
recommended_styles=excluded.recommended_styles,
insights=excluded.insights""",
(data["report_date"], json.dumps(data["top_genres"]),
json.dumps(data["top_keywords"]), json.dumps(data["recommended_styles"]),
data["insights"]),
)
def get_latest_trend_report() -> Optional[Dict[str, Any]]:
with _conn() as conn:
row = conn.execute(
"SELECT * FROM trend_reports ORDER BY report_date DESC LIMIT 1"
).fetchone()
if not row:
return None
return {
"id": row["id"],
"report_date": row["report_date"],
"top_genres": json.loads(row["top_genres"]),
"top_keywords": json.loads(row["top_keywords"]),
"recommended_styles": json.loads(row["recommended_styles"]),
"insights": row["insights"],
"created_at": row["created_at"],
}
def get_trend_reports(limit: int = 10) -> list:
with _conn() as conn:
rows = conn.execute(
"SELECT id, report_date, insights, created_at FROM trend_reports "
"ORDER BY report_date DESC LIMIT ?", (limit,)
).fetchall()
return [{"id": r["id"], "report_date": r["report_date"],
"insights": r["insights"][:100], "created_at": r["created_at"]}
for r in rows]