Files
Airwallex/backend/app/models/db_models.py
zqq61 4f53889a8e feat: Airwallex 发卡管理后台完整实现
- 后端: FastAPI + SQLAlchemy + SQLite, JWT认证, 代理支持的AirwallexClient
- 前端: React 18 + Vite + Ant Design 5, 中文界面
- 功能: 卡片管理, 持卡人管理, 交易记录, API令牌, 系统设置, 审计日志
- 第三方API: X-API-Key认证, 权限控制
- Docker部署: docker-compose编排前后端
2026-03-15 23:05:08 +08:00

68 lines
3.0 KiB
Python

"""SQLAlchemy ORM models for the application database."""
from datetime import datetime
from sqlalchemy import Boolean, DateTime, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
from ..database import Base
class SystemSetting(Base):
"""Stores application-level configuration key-value pairs."""
__tablename__ = "system_settings"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
key: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True)
value: Mapped[str] = mapped_column(Text, nullable=False)
encrypted: Mapped[bool] = mapped_column(Boolean, default=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime, default=func.now(), onupdate=func.now()
)
class ApiToken(Base):
"""API tokens for programmatic access."""
__tablename__ = "api_tokens"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
token: Mapped[str] = mapped_column(String(512), unique=True, nullable=False, index=True)
permissions: Mapped[str] = mapped_column(Text, default="[]") # JSON string
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now())
expires_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
last_used_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
class CardLog(Base):
"""Logs for card-related operations."""
__tablename__ = "card_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
card_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
cardholder_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
action: Mapped[str] = mapped_column(String(100), nullable=False)
status: Mapped[str] = mapped_column(String(50), nullable=False)
operator: Mapped[str] = mapped_column(String(255), nullable=False)
request_data: Mapped[str | None] = mapped_column(Text, nullable=True)
response_data: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now())
class AuditLog(Base):
"""General audit trail for all administrative actions."""
__tablename__ = "audit_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
action: Mapped[str] = mapped_column(String(100), nullable=False)
resource_type: Mapped[str] = mapped_column(String(100), nullable=False)
resource_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
operator: Mapped[str] = mapped_column(String(255), nullable=False)
ip_address: Mapped[str | None] = mapped_column(String(45), nullable=True)
details: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=func.now())