refactor: split app structure
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import HTTPException, Request
|
||||
from pydantic import ValidationError
|
||||
|
||||
from .config import ACCOUNTS_PATH, CLASSNOTES_PATH
|
||||
from .data import Account, Payment, read_accounts, read_classnotes
|
||||
from .schemas import AccountPayload, RegisterLinesPayload
|
||||
|
||||
|
||||
async def read_register_payload(request: Request) -> RegisterLinesPayload:
|
||||
body = await request.body()
|
||||
if not body.strip():
|
||||
return RegisterLinesPayload()
|
||||
|
||||
content_type = request.headers.get("content-type", "").lower()
|
||||
if "application/json" in content_type:
|
||||
try:
|
||||
data = json.loads(body)
|
||||
if isinstance(data, str):
|
||||
return RegisterLinesPayload(line=data)
|
||||
if isinstance(data, list):
|
||||
return RegisterLinesPayload(lines=data)
|
||||
if isinstance(data, dict):
|
||||
return RegisterLinesPayload(**data)
|
||||
except (json.JSONDecodeError, ValidationError) as exc:
|
||||
raise ValueError("登记 JSON 格式错误") from exc
|
||||
raise ValueError("登记 JSON 必须是字符串、字符串数组,或包含 line/lines 的对象")
|
||||
|
||||
try:
|
||||
text = body.decode("utf-8")
|
||||
except UnicodeDecodeError as exc:
|
||||
raise ValueError("登记内容必须使用 UTF-8 编码") from exc
|
||||
return RegisterLinesPayload(lines=text.splitlines())
|
||||
|
||||
|
||||
def load_records():
|
||||
if not CLASSNOTES_PATH.exists():
|
||||
raise HTTPException(status_code=503, detail=f"课程记录文件不存在: {CLASSNOTES_PATH}")
|
||||
return read_classnotes(CLASSNOTES_PATH)
|
||||
|
||||
|
||||
def load_accounts():
|
||||
if not ACCOUNTS_PATH.exists():
|
||||
raise HTTPException(status_code=503, detail=f"课时账户文件不存在: {ACCOUNTS_PATH}")
|
||||
return read_accounts(ACCOUNTS_PATH)
|
||||
|
||||
|
||||
def file_meta(path: Path) -> dict:
|
||||
if not path.exists():
|
||||
return {"exists": False, "path": str(path)}
|
||||
stat = path.stat()
|
||||
return {
|
||||
"exists": True,
|
||||
"path": str(path),
|
||||
"size": stat.st_size,
|
||||
"mtime": stat.st_mtime,
|
||||
}
|
||||
|
||||
|
||||
def payload_to_account(payload: AccountPayload, student_id: str | None = None) -> Account:
|
||||
return Account(
|
||||
student_id=student_id if student_id is not None else payload.student_id,
|
||||
student=payload.student,
|
||||
payments=[Payment(date=item.date, hours=item.hours) for item in payload.payments],
|
||||
remaining=payload.remaining,
|
||||
account_status=payload.account_status,
|
||||
note=payload.note,
|
||||
)
|
||||
Reference in New Issue
Block a user