diff --git a/app/utils/model_utils.py b/app/utils/model_utils.py index 15341eb..d015a2a 100644 --- a/app/utils/model_utils.py +++ b/app/utils/model_utils.py @@ -1,5 +1,6 @@ import uuid from datetime import datetime, timezone, timedelta, date +from decimal import Decimal, InvalidOperation from typing import List, Annotated, Any from fastapi import FastAPI, APIRouter, HTTPException @@ -92,6 +93,39 @@ FormattedDate = Annotated[ ] +# /*---------------------------------------decimal-------------------------------------------*/ + +# 辅助函数:将 Decimal 格式化为字符串 +def format_decimal_to_string(d: Decimal) -> str: + if isinstance(d, str): + return d + if d is None: + return None + return str(d) + + +# 辅助函数:将字符串解析为 decimal +def parse_decimal_from_string(d_str: Any) -> Decimal | None: + if d_str is None or d_str == "": + return None + if isinstance(d_str, Decimal): # 如果已经是 Decimal 对象,直接返回 + return d_str + try: + # 尝试解析 + return Decimal(str(d_str)) + except InvalidOperation: + # 如果解析失败,Pydantic 会处理验证错误 + raise ValueError(f"Invalid decimal format: {d_str}") + + +# 定义一个 Annotated 类型,用于在 Pydantic 字段中应用解析器 +# 当从输入数据(如 JSON 字符串)转换为 Decimal 对象时,会先经过这个解析器 +FormattedDecimal = Annotated[ + Decimal, + BeforeValidator(parse_decimal_from_string) +] + + # /*---------------------------------------other-------------------------------------------*/ def to_camel(snake_str: str) -> str: @@ -100,3 +134,7 @@ def to_camel(snake_str: str) -> str: # We capitalize the first letter of each component except the first one # and join them to form the camelCase string. return components[0] + ''.join(x.title() for x in components[1:]) + + +def to_dict(cls: BaseModel): + return cls.model_dump_json(by_alias=True)