feat(saju-lab): /interpret 응답에 fortune_scores + lucky + monthly_flow 포함
This commit is contained in:
@@ -34,6 +34,9 @@ class SajuInterpretResponse(BaseModel):
|
|||||||
cost_usd: float
|
cost_usd: float
|
||||||
latency_ms: int
|
latency_ms: int
|
||||||
reroll_count: int = 0
|
reroll_count: int = 0
|
||||||
|
fortune_scores: dict
|
||||||
|
lucky: dict
|
||||||
|
monthly_flow: List[dict]
|
||||||
|
|
||||||
|
|
||||||
class CompatInterpretResponse(BaseModel):
|
class CompatInterpretResponse(BaseModel):
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ router = APIRouter(prefix="/api/saju")
|
|||||||
@router.post("/interpret", response_model=SajuInterpretResponse)
|
@router.post("/interpret", response_model=SajuInterpretResponse)
|
||||||
async def interpret_saju_endpoint(req: SajuInterpretRequest):
|
async def interpret_saju_endpoint(req: SajuInterpretRequest):
|
||||||
"""사주 입력 → 계산 + AI 해석 + DB 저장."""
|
"""사주 입력 → 계산 + AI 해석 + DB 저장."""
|
||||||
# 음력 입력 시 양력 변환
|
from datetime import date
|
||||||
|
|
||||||
if req.calendar_type == "lunar":
|
if req.calendar_type == "lunar":
|
||||||
sy, sm, sd = lunar_to_solar(req.year, req.month, req.day, req.is_leap_month)
|
sy, sm, sd = lunar_to_solar(req.year, req.month, req.day, req.is_leap_month)
|
||||||
else:
|
else:
|
||||||
@@ -32,6 +33,13 @@ async def interpret_saju_endpoint(req: SajuInterpretRequest):
|
|||||||
saju = calculate_saju(sy, sm, sd, req.hour, req.gender)
|
saju = calculate_saju(sy, sm, sd, req.hour, req.gender)
|
||||||
analysis = perform_full_analysis(saju, 2026)
|
analysis = perform_full_analysis(saju, 2026)
|
||||||
daeun = calculate_daeun(sy, sm, sd, req.gender, saju["month"]["stem"], saju["month"]["branch"])
|
daeun = calculate_daeun(sy, sm, sd, req.gender, saju["month"]["stem"], saju["month"]["branch"])
|
||||||
|
# 신규
|
||||||
|
from ..calculator.fortune_scores import calculate_fortune_scores
|
||||||
|
from ..calculator.lucky import calculate_lucky
|
||||||
|
from ..calculator.monthly_flow import calculate_monthly_flow
|
||||||
|
fortune_scores = calculate_fortune_scores(saju, analysis, 2026)
|
||||||
|
lucky = calculate_lucky(saju, analysis, date.today())
|
||||||
|
monthly_flow = calculate_monthly_flow(saju, 2026)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"계산 실패: {e}")
|
raise HTTPException(status_code=400, detail=f"계산 실패: {e}")
|
||||||
|
|
||||||
@@ -40,7 +48,6 @@ async def interpret_saju_endpoint(req: SajuInterpretRequest):
|
|||||||
except pipeline.SajuError as e:
|
except pipeline.SajuError as e:
|
||||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||||
|
|
||||||
# DB 저장
|
|
||||||
rid = db_module.save_saju_record({
|
rid = db_module.save_saju_record({
|
||||||
"birth_year": req.year, "birth_month": req.month, "birth_day": req.day,
|
"birth_year": req.year, "birth_month": req.month, "birth_day": req.day,
|
||||||
"birth_hour": req.hour, "gender": req.gender,
|
"birth_hour": req.hour, "gender": req.gender,
|
||||||
@@ -55,6 +62,9 @@ async def interpret_saju_endpoint(req: SajuInterpretRequest):
|
|||||||
"cost_usd": interp_result["cost_usd"],
|
"cost_usd": interp_result["cost_usd"],
|
||||||
"latency_ms": interp_result["latency_ms"],
|
"latency_ms": interp_result["latency_ms"],
|
||||||
"reroll_count": interp_result["reroll_count"],
|
"reroll_count": interp_result["reroll_count"],
|
||||||
|
"fortune_scores_json": fortune_scores,
|
||||||
|
"lucky_json": lucky,
|
||||||
|
"monthly_flow_json": monthly_flow,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -69,6 +79,9 @@ async def interpret_saju_endpoint(req: SajuInterpretRequest):
|
|||||||
"cost_usd": interp_result["cost_usd"],
|
"cost_usd": interp_result["cost_usd"],
|
||||||
"latency_ms": interp_result["latency_ms"],
|
"latency_ms": interp_result["latency_ms"],
|
||||||
"reroll_count": interp_result["reroll_count"],
|
"reroll_count": interp_result["reroll_count"],
|
||||||
|
"fortune_scores": fortune_scores,
|
||||||
|
"lucky": lucky,
|
||||||
|
"monthly_flow": monthly_flow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,11 +38,10 @@ def test_health():
|
|||||||
|
|
||||||
|
|
||||||
def test_saju_interpret_endpoint(monkeypatch):
|
def test_saju_interpret_endpoint(monkeypatch):
|
||||||
"""saju interpret이 pipeline mock으로 동작."""
|
"""saju interpret이 pipeline mock으로 동작 + 신규 필드 검증."""
|
||||||
async def fake_interpret(*args, **kwargs):
|
async def fake_interpret(*args, **kwargs):
|
||||||
return _interpret_result()
|
return _interpret_result()
|
||||||
|
|
||||||
# interpret_saju를 mock
|
|
||||||
from app.routers import saju as saju_router
|
from app.routers import saju as saju_router
|
||||||
monkeypatch.setattr(saju_router.pipeline, "interpret_saju", fake_interpret)
|
monkeypatch.setattr(saju_router.pipeline, "interpret_saju", fake_interpret)
|
||||||
|
|
||||||
@@ -58,6 +57,16 @@ def test_saju_interpret_endpoint(monkeypatch):
|
|||||||
assert "daeun" in data
|
assert "daeun" in data
|
||||||
assert "reading_id" in data
|
assert "reading_id" in data
|
||||||
assert data["reading_id"] > 0
|
assert data["reading_id"] > 0
|
||||||
|
# 신규 필드
|
||||||
|
assert "fortune_scores" in data
|
||||||
|
for k in ("wealth", "romance", "social", "career", "overall"):
|
||||||
|
assert k in data["fortune_scores"]
|
||||||
|
assert 0 <= data["fortune_scores"][k] <= 100
|
||||||
|
assert "lucky" in data
|
||||||
|
for k in ("color", "number", "direction", "good_signs", "warnings"):
|
||||||
|
assert k in data["lucky"]
|
||||||
|
assert "monthly_flow" in data
|
||||||
|
assert len(data["monthly_flow"]) == 12
|
||||||
|
|
||||||
|
|
||||||
def test_saju_list_get_cycle(monkeypatch):
|
def test_saju_list_get_cycle(monkeypatch):
|
||||||
|
|||||||
Reference in New Issue
Block a user