133 lines
3.6 KiB
Python
133 lines
3.6 KiB
Python
"""资产相关 Schema(请求/响应模型)
|
|
|
|
设计说明:
|
|
- *In 系列:详情表输入模型(不含 id/asset_id,由服务端填充)
|
|
- AssetCreate/AssetUpdate:主表字段 + 按类型嵌套的可选 detail
|
|
- AssetRead:完整输出,含计算字段 days_to_expiry(距到期天数)
|
|
"""
|
|
|
|
from datetime import date, datetime
|
|
from typing import Optional
|
|
|
|
from sqlmodel import SQLModel
|
|
|
|
from app.models.asset import AssetStatus, AssetType
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# 详情表输入模型
|
|
# --------------------------------------------------------------------------- #
|
|
class VPSDetailIn(SQLModel):
|
|
"""VPS 详情输入"""
|
|
|
|
ip_address: str
|
|
tailscale_ip: Optional[str] = None
|
|
region: Optional[str] = None
|
|
os: Optional[str] = None
|
|
cpu_cores: int = 1
|
|
memory_gb: float = 1
|
|
disk_gb: int = 20
|
|
bandwidth_gb: Optional[int] = None
|
|
ssh_port: int = 22
|
|
panel_url: Optional[str] = None
|
|
|
|
|
|
class DomainDetailIn(SQLModel):
|
|
"""域名详情输入"""
|
|
|
|
domain_name: str
|
|
registrar: Optional[str] = None
|
|
dns_provider: Optional[str] = None
|
|
cloudflare_account: Optional[str] = None
|
|
is_using: bool = True
|
|
redirect_target: Optional[str] = None
|
|
|
|
|
|
class AIAccountIn(SQLModel):
|
|
"""AI 账号详情输入"""
|
|
|
|
provider: str
|
|
api_key: Optional[str] = None
|
|
plan: Optional[str] = None
|
|
balance: Optional[float] = None
|
|
currency: str = "USD"
|
|
monthly_usage: Optional[float] = None
|
|
monthly_limit: Optional[float] = None
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# 资产主表模型
|
|
# --------------------------------------------------------------------------- #
|
|
class AssetBase(SQLModel):
|
|
"""资产主表公共字段"""
|
|
|
|
name: str
|
|
asset_type: AssetType
|
|
provider: str
|
|
account: Optional[str] = None
|
|
expiry_date: Optional[date] = None
|
|
auto_renew: bool = False
|
|
cost: float = 0
|
|
currency: str = "USD"
|
|
status: AssetStatus = AssetStatus.ACTIVE
|
|
is_archived: bool = False
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class AssetCreate(AssetBase):
|
|
"""创建资产:按 asset_type 携带对应 detail"""
|
|
|
|
vps_detail: Optional[VPSDetailIn] = None
|
|
domain_detail: Optional[DomainDetailIn] = None
|
|
ai_detail: Optional[AIAccountIn] = None
|
|
|
|
|
|
class AssetUpdate(SQLModel):
|
|
"""更新资产:所有字段可选,仅更新传入项"""
|
|
|
|
name: Optional[str] = None
|
|
asset_type: Optional[AssetType] = None
|
|
provider: Optional[str] = None
|
|
account: Optional[str] = None
|
|
expiry_date: Optional[date] = None
|
|
auto_renew: Optional[bool] = None
|
|
cost: Optional[float] = None
|
|
currency: Optional[str] = None
|
|
status: Optional[AssetStatus] = None
|
|
is_archived: Optional[bool] = None
|
|
remark: Optional[str] = None
|
|
vps_detail: Optional[VPSDetailIn] = None
|
|
domain_detail: Optional[DomainDetailIn] = None
|
|
ai_detail: Optional[AIAccountIn] = None
|
|
|
|
|
|
# --------------------------------------------------------------------------- #
|
|
# 输出模型
|
|
# --------------------------------------------------------------------------- #
|
|
class VPSDetailRead(VPSDetailIn):
|
|
id: int
|
|
asset_id: int
|
|
|
|
|
|
class DomainDetailRead(DomainDetailIn):
|
|
id: int
|
|
asset_id: int
|
|
|
|
|
|
class AIAccountRead(AIAccountIn):
|
|
id: int
|
|
asset_id: int
|
|
last_synced_at: Optional[datetime] = None
|
|
|
|
|
|
class AssetRead(AssetBase):
|
|
"""资产完整输出"""
|
|
|
|
id: int
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
days_to_expiry: Optional[int] = None
|
|
vps_detail: Optional[VPSDetailRead] = None
|
|
domain_detail: Optional[DomainDetailRead] = None
|
|
ai_detail: Optional[AIAccountRead] = None
|