108 lines
2.9 KiB
Python
108 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi import Query
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.models import (
|
|
Account,
|
|
ClsNewsDocument,
|
|
DailyInputDocument,
|
|
DailyInputUpsertPayload,
|
|
ReportDocument,
|
|
ReportListItem,
|
|
)
|
|
from app.services.domain import (
|
|
get_accounts,
|
|
get_cls_news,
|
|
list_reports,
|
|
load_daily_input,
|
|
load_report,
|
|
normalize_daily_input,
|
|
normalize_date,
|
|
refresh_cls_news,
|
|
save_daily_input,
|
|
save_report,
|
|
seed_demo_content,
|
|
generate_report,
|
|
)
|
|
from app.services.storage import init_database
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(_app: FastAPI):
|
|
init_database()
|
|
seed_demo_content()
|
|
yield
|
|
|
|
|
|
app = FastAPI(
|
|
title="WeChat Finance Daily",
|
|
version="0.1.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
@app.get("/api/health")
|
|
def health() -> dict[str, str]:
|
|
return {"status": "ok"}
|
|
|
|
|
|
@app.get("/api/accounts", response_model=list[Account])
|
|
def accounts() -> list[Account]:
|
|
return get_accounts()
|
|
|
|
|
|
@app.get("/api/daily-inputs/{date_str}", response_model=DailyInputDocument)
|
|
def get_daily_inputs(date_str: str) -> DailyInputDocument:
|
|
return load_daily_input(normalize_date(date_str))
|
|
|
|
|
|
@app.put("/api/daily-inputs/{date_str}", response_model=DailyInputDocument)
|
|
def put_daily_inputs(date_str: str, payload: DailyInputUpsertPayload) -> DailyInputDocument:
|
|
document = normalize_daily_input(normalize_date(date_str), payload)
|
|
return save_daily_input(document)
|
|
|
|
|
|
@app.post("/api/reports/{date_str}/generate", response_model=ReportDocument)
|
|
def generate_daily_report(date_str: str) -> ReportDocument:
|
|
normalized_date = normalize_date(date_str)
|
|
input_document = load_daily_input(normalized_date)
|
|
report = generate_report(normalized_date, input_document)
|
|
return save_report(report)
|
|
|
|
|
|
@app.get("/api/reports", response_model=list[ReportListItem])
|
|
def get_report_list() -> list[ReportListItem]:
|
|
return list_reports()
|
|
|
|
|
|
@app.get("/api/opinions/{date_str}", response_model=ReportDocument)
|
|
def get_opinion_report(date_str: str) -> ReportDocument:
|
|
normalized_date = normalize_date(date_str)
|
|
existing = load_report(normalized_date)
|
|
if existing is not None:
|
|
return existing
|
|
report = generate_report(normalized_date, load_daily_input(normalized_date))
|
|
return save_report(report)
|
|
|
|
|
|
@app.get("/api/cls-news", response_model=ClsNewsDocument)
|
|
def get_cls_news_payload(date: str | None = Query(default=None)) -> ClsNewsDocument:
|
|
return get_cls_news(date)
|
|
|
|
|
|
@app.post("/api/cls-news/refresh", response_model=ClsNewsDocument)
|
|
def refresh_cls_news_payload(date: str | None = Query(default=None)) -> ClsNewsDocument:
|
|
return refresh_cls_news(date)
|