feat: 支持研究素材删除并统一 Semi 表格
This commit is contained in:
@@ -76,11 +76,12 @@ class Assets:
|
||||
ResearchAsset.id == asset_id,
|
||||
ResearchAsset.version == body.version,
|
||||
ResearchAsset.kind == body.kind,
|
||||
ResearchAsset.archived.is_(False),
|
||||
)
|
||||
.values(version=body.version + 1, name=content["name"], updated_at=now())
|
||||
)
|
||||
if changed.rowcount != 1:
|
||||
raise HTTPException(409, "素材已变化,保留草稿并读取最新版本")
|
||||
raise HTTPException(409, "素材已变化或已删除,保留草稿并读取最新版本")
|
||||
version = body.version + 1
|
||||
else:
|
||||
asset_id, version = uid(), 1
|
||||
@@ -100,11 +101,15 @@ class Assets:
|
||||
async def archive(self, asset_id, version):
|
||||
result = await self.db.execute(
|
||||
update(ResearchAsset)
|
||||
.where(ResearchAsset.id == asset_id, ResearchAsset.version == version)
|
||||
.where(
|
||||
ResearchAsset.id == asset_id,
|
||||
ResearchAsset.version == version,
|
||||
ResearchAsset.archived.is_(False),
|
||||
)
|
||||
.values(archived=True, version=ResearchAsset.version + 1, updated_at=now())
|
||||
)
|
||||
if result.rowcount != 1:
|
||||
raise HTTPException(409, "素材已变化或不存在")
|
||||
raise HTTPException(409, "素材已变化、已删除或不存在,请刷新后重试")
|
||||
# Archiving is itself a revision; old references remain resolvable.
|
||||
previous = await self.db.get(ResearchRevision, (asset_id, version))
|
||||
self.db.add(
|
||||
|
||||
@@ -5,7 +5,7 @@ import json
|
||||
from collections import defaultdict
|
||||
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy import func, select, update
|
||||
|
||||
from ..backtests.contracts import Candidate, DraftInput, PreviewInput, SimulationSettings, Source
|
||||
from ..backtests.service import Backtests, uid
|
||||
@@ -243,6 +243,7 @@ class Experiments:
|
||||
"id",
|
||||
"name",
|
||||
"kind",
|
||||
"archived",
|
||||
"hypothesis",
|
||||
"inputs",
|
||||
"parents",
|
||||
@@ -256,7 +257,7 @@ class Experiments:
|
||||
)
|
||||
|
||||
async def list(self, kind=None, limit=25, offset=0):
|
||||
query = select(ResearchExperiment)
|
||||
query = select(ResearchExperiment).where(ResearchExperiment.archived.is_(False))
|
||||
if kind:
|
||||
query = query.where(ResearchExperiment.kind == kind)
|
||||
total = await self.db.scalar(select(func.count()).select_from(query.subquery()))
|
||||
@@ -281,6 +282,19 @@ class Experiments:
|
||||
}
|
||||
)
|
||||
|
||||
async def archive(self, experiment_id):
|
||||
"""Hide an immutable experiment; backtests and lineage must still resolve it.
|
||||
|
||||
Returns an acknowledgement, or raises HTTP 404 for an unknown ID. Repeated
|
||||
deletion is idempotent because candidate contents cannot change.
|
||||
"""
|
||||
result = await self.db.execute(
|
||||
update(ResearchExperiment).where(ResearchExperiment.id == experiment_id).values(archived=True)
|
||||
)
|
||||
if result.rowcount != 1:
|
||||
raise HTTPException(404, "研究实验不存在")
|
||||
return {"ok": True}
|
||||
|
||||
async def preview(self, experiment_id, candidate_ids=None, source_kind=None, reference=None):
|
||||
experiment = await self.get(experiment_id)
|
||||
candidates = experiment["candidates"]
|
||||
|
||||
@@ -143,6 +143,12 @@ async def experiment(experiment_id: str, request: Request):
|
||||
return await Experiments(db).get(experiment_id)
|
||||
|
||||
|
||||
@router.delete("/experiments/{experiment_id}")
|
||||
async def archive_experiment(experiment_id: str, request: Request):
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
return await Experiments(db).archive(experiment_id)
|
||||
|
||||
|
||||
@router.post("/experiments/{experiment_id}/preview", status_code=201)
|
||||
async def preview(experiment_id: str, body: ExperimentPreview, request: Request):
|
||||
async with request.app.state.sessions.begin() as db:
|
||||
|
||||
Reference in New Issue
Block a user