108 lines
3.9 KiB
Python
108 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
from .shared import *
|
|
|
|
from ...services.sstc.entity_lookup import _ensure_charter, _ensure_project, _ensure_release
|
|
from ...services.sstc.governance import _assert_release_transition_allowed, _require_manager
|
|
from ...services.sstc.signal_core import _as_dict, _parse_node_id, _parse_project_id
|
|
|
|
router = APIRouter(tags=["sstc"])
|
|
|
|
@router.patch("/projects/{project_id}/releases/{release_node_id}/status")
|
|
async def patch_release_status(
|
|
project_id: str,
|
|
release_node_id: str,
|
|
body: ReleaseStatusPatchRequest,
|
|
permission_user: User = Depends(require_project_member_or_manager),
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
_ = permission_user
|
|
_require_manager(current_user)
|
|
pid = _parse_project_id(project_id)
|
|
rid = _parse_node_id(release_node_id, "release_node_id")
|
|
tenant_id = int(current_user.tenant_id)
|
|
await _ensure_project(SSTCService(db, tenant_id=tenant_id), pid)
|
|
release_node = await _ensure_release(
|
|
db, tenant_id=tenant_id, project_id=pid, release_node_id=rid
|
|
)
|
|
await _assert_release_transition_allowed(
|
|
db,
|
|
tenant_id=tenant_id,
|
|
project_id=pid,
|
|
release_node=release_node,
|
|
target_status=body.status,
|
|
)
|
|
before = {"status": release_node.status}
|
|
release_node.status = body.status
|
|
content = _as_dict(release_node.content)
|
|
content["status_note"] = body.note
|
|
content["last_status_changed_at"] = now_cn_aware().isoformat()
|
|
release_node.content = content
|
|
await log_operation(
|
|
db,
|
|
tenant_id=tenant_id,
|
|
user_id=int(current_user.id),
|
|
project_id=pid,
|
|
entity_type="release",
|
|
entity_id=str(rid),
|
|
action="status_change",
|
|
before_data=before,
|
|
after_data={"status": body.status, "note": body.note},
|
|
)
|
|
await db.commit()
|
|
return success_response({"id": str(release_node.id), "status": release_node.status})
|
|
|
|
@router.post("/projects/{project_id}/releases/{release_node_id}/verification/generate")
|
|
async def generate_release_verification(
|
|
project_id: str,
|
|
release_node_id: str,
|
|
permission_user: User = Depends(require_project_member_or_manager),
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
_ = permission_user
|
|
_require_manager(current_user)
|
|
pid = _parse_project_id(project_id)
|
|
rid = _parse_node_id(release_node_id, "release_node_id")
|
|
tenant_id = int(current_user.tenant_id)
|
|
await _ensure_project(SSTCService(db, tenant_id=tenant_id), pid)
|
|
release_node = await _ensure_release(
|
|
db, tenant_id=tenant_id, project_id=pid, release_node_id=rid
|
|
)
|
|
|
|
content = _as_dict(release_node.content)
|
|
charter_id = int(content.get("charter_id") or 0)
|
|
charter = await _ensure_charter(
|
|
db,
|
|
tenant_id=tenant_id,
|
|
project_id=pid,
|
|
charter_id=charter_id,
|
|
)
|
|
charter_content = _as_dict(charter.content)
|
|
success_metrics = charter_content.get("success_metrics") or charter_content.get("core_metrics") or []
|
|
if not success_metrics:
|
|
success_metrics = ["功能验收通过", "核心流程无阻塞", "关键性能指标达标"]
|
|
|
|
items = [
|
|
{
|
|
"id": f"check-{i+1}",
|
|
"title": str(metric),
|
|
"expected": "达到预期",
|
|
"status": "pending",
|
|
"required": True,
|
|
"source": "charter_success_metric",
|
|
"verified_by": None,
|
|
"verified_at": None,
|
|
"note": None,
|
|
}
|
|
for i, metric in enumerate(success_metrics)
|
|
]
|
|
content["verification_items"] = items
|
|
content["verification_progress"] = {"done": 0, "total": len(items)}
|
|
content["verification_done"] = False
|
|
release_node.content = content
|
|
await db.commit()
|
|
return success_response({"release_id": str(release_node.id), "verification_items": items})
|
|
|