This commit is contained in:
fengchuanhn@gmail.com
2026-05-21 01:47:21 +08:00
parent 7f57dfa9ed
commit 5ee6a57dd1
29 changed files with 794 additions and 18 deletions

View File

@@ -4,11 +4,13 @@ import string
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.roles import ROLE_AGENT, ROLE_OEM
from app.models.card_key import CardKey
from app.models.user import User
from app.schemas.admin_card_key import CardKeyCreate, CardKeyUpdate
DEFAULT_PAGE_SIZE = 20
MAX_PAGE_SIZE = 100
MAX_PAGE_SIZE = 200
_SERIAL_ALPHABET = string.ascii_uppercase + string.digits
_SERIAL_LENGTH = 16
@@ -43,22 +45,65 @@ async def _unique_serial(db: AsyncSession, preferred: str | None = None) -> str:
raise AdminCardKeyError("生成序列号失败,请重试")
async def _validate_assign_ids(
db: AsyncSession,
*,
oem_id: int | None,
agent_id: int | None,
) -> None:
if oem_id is not None and agent_id is not None:
raise AdminCardKeyError("OEM 与代理只能指定其一")
if oem_id is not None:
oem = await db.get(User, oem_id)
if oem is None or oem.role_id != ROLE_OEM:
raise AdminCardKeyError("所选 OEM 不存在")
if agent_id is not None:
agent = await db.get(User, agent_id)
if agent is None or agent.role_id != ROLE_AGENT:
raise AdminCardKeyError("所选代理不存在")
def _list_card_keys_filters(
*,
status: str | None = None,
username: str | None = None,
oem_id: int | None = None,
agent_id: int | None = None,
) -> list:
filters = []
if status == "unused":
filters.append(CardKey.activated_at.is_(None))
elif status == "used":
filters.append(CardKey.activated_at.is_not(None))
if username and username.strip():
filters.append(CardKey.username.ilike(f"%{username.strip()}%"))
if oem_id is not None:
filters.append(CardKey.oem_id == oem_id)
if agent_id is not None:
filters.append(CardKey.agent_id == agent_id)
return filters
async def list_card_keys(
db: AsyncSession,
*,
page: int = 1,
page_size: int = DEFAULT_PAGE_SIZE,
status: str | None = None,
username: str | None = None,
oem_id: int | None = None,
agent_id: int | None = None,
) -> tuple[list[CardKey], int]:
page_size = min(max(page_size, 1), MAX_PAGE_SIZE)
page = max(page, 1)
offset = (page - 1) * page_size
filters = []
if status == "unused":
filters.append(CardKey.activated_at.is_(None))
elif status == "used":
filters.append(CardKey.activated_at.is_not(None))
filters = _list_card_keys_filters(
status=status,
username=username,
oem_id=oem_id,
agent_id=agent_id,
)
count_stmt = select(func.count()).select_from(CardKey)
list_stmt = select(CardKey)
@@ -74,6 +119,7 @@ async def list_card_keys(
async def create_card_keys(db: AsyncSession, body: CardKeyCreate) -> list[CardKey]:
await _validate_assign_ids(db, oem_id=body.oem_id, agent_id=body.agent_id)
created: list[CardKey] = []
for index in range(body.count):
@@ -85,6 +131,8 @@ async def create_card_keys(db: AsyncSession, body: CardKeyCreate) -> list[CardKe
serial_number=serial,
duration_days=body.duration_days,
remark=body.remark,
oem_id=body.oem_id,
agent_id=body.agent_id,
)
db.add(card)
created.append(card)