Files
ShiErFeng/shierfeng-fastapi-backend/module_business/dao/test_batch_adoption_dao.py
T

101 lines
3.6 KiB
Python

from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from exceptions.exception import ServiceWarning
from module_business.domain.test_batch_graph import BATCH_MODELS, ROOT_TABLES, BatchSelection
from module_business.entity.vo.test_batch_vo import AdoptionRootModel
class TestBatchAdoptionDao:
"""旧数据闭包锁定、展示与批量纳入。"""
@classmethod
async def lock_roots(
cls,
db: AsyncSession,
roots: list[AdoptionRootModel],
) -> None:
requested: dict[str, set[int]] = {}
for root in roots:
requested.setdefault(ROOT_TABLES[root.resource_type], set()).update(root.resource_ids)
for table_name in sorted(requested):
primary_key = BATCH_MODELS[table_name][1]
ids = sorted(requested[table_name])
result = await db.execute(
select(primary_key).where(primary_key.in_(ids)).order_by(primary_key).with_for_update()
)
if {row[0] for row in result.all()} != set(ids):
raise ServiceWarning('', '指定的旧数据不存在')
@classmethod
async def lock_selection(cls, db: AsyncSession, selection: BatchSelection) -> None:
for table_name in sorted(selection):
ids = sorted(selection[table_name])
if not ids:
continue
primary_key = BATCH_MODELS[table_name][1]
result = await db.execute(
select(primary_key).where(primary_key.in_(ids)).order_by(primary_key).with_for_update()
)
if len(result.all()) != len(ids):
raise ServiceWarning('', '预览范围已变化')
@classmethod
async def find_tagged_record(
cls,
db: AsyncSession,
selection: BatchSelection,
) -> tuple[str, int] | None:
for table_name in sorted(selection):
ids = sorted(selection[table_name])
if not ids:
continue
model, primary_key, _ = BATCH_MODELS[table_name]
result = await db.execute(
select(primary_key)
.where(
primary_key.in_(ids),
model.test_batch_id.is_not(None),
)
.order_by(primary_key)
.limit(1)
)
record_id = result.scalar_one_or_none()
if record_id is not None:
return table_name, record_id
return None
@classmethod
async def list_display_keys(
cls,
db: AsyncSession,
selection: BatchSelection,
) -> dict[str, list[str]]:
keys: dict[str, list[str]] = {}
for table_name in BATCH_MODELS:
ids = sorted(selection[table_name])
if not ids:
keys[table_name] = []
continue
_, primary_key, display_column = BATCH_MODELS[table_name]
result = await db.execute(select(display_column).where(primary_key.in_(ids)).order_by(display_column))
keys[table_name] = sorted(str(row[0]) for row in result.all())
return keys
@classmethod
async def set_test_batch_id(
cls,
db: AsyncSession,
table_name: str,
ids: list[int],
batch_id: int,
) -> None:
if not ids:
return
model, primary_key, _ = BATCH_MODELS[table_name]
result = await db.execute(
update(model).where(primary_key.in_(ids), model.test_batch_id.is_(None)).values(test_batch_id=batch_id)
)
if result.rowcount != len(ids):
raise ServiceWarning('', '存在记录已属于其他测试批次')