refactor: 移除审批和回写功能模块

移除了整个审批(approvals)和官方回写(writebacks)功能模块,
包括相关模型、路由、服务和配置项。更新了数据库迁移文件,
删除了相关的审批请求表和官方回写运行表。同时从API路由器中
移除了相应的路由,并调整了安全常量和字段验证器以匹配变更。
```
This commit is contained in:
2026-07-08 17:08:59 +08:00
parent 19e59e83cc
commit 0a153b264a
48 changed files with 135 additions and 2225 deletions

View File

@@ -2,6 +2,7 @@ from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.operation_guard import require_operations_enabled
from app.core.security import ApiPrincipal, require_api_key
from app.core.task_queue import enqueue_risk_event_generation
from app.modules.risk.constants import RiskEventActionKey, RiskGenerationResultKey
@@ -94,6 +95,7 @@ def assign_risk_event(
db: Session = Depends(get_db),
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return RiskService(db).assign_event(
event_id,
assigned_to=payload.assigned_to,
@@ -109,6 +111,7 @@ def comment_risk_event(
db: Session = Depends(get_db),
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return RiskService(db).comment_event(
event_id,
comment=payload.comment,
@@ -124,6 +127,7 @@ def resolve_risk_event(
db: Session = Depends(get_db),
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return RiskService(db).resolve_event(
event_id,
comment=payload.comment,
@@ -139,12 +143,12 @@ def close_risk_event(
db: Session = Depends(get_db),
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return RiskService(db).close_event(
event_id,
closed_reason=payload.closed_reason,
review_summary=payload.review_summary,
actor=principal.actor,
approval_ticket_id=payload.approval_ticket_id,
)
@@ -155,11 +159,11 @@ def reopen_risk_event(
db: Session = Depends(get_db),
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return RiskService(db).reopen_event(
event_id,
comment=payload.comment,
actor=principal.actor,
approval_ticket_id=payload.approval_ticket_id,
)
@@ -168,6 +172,7 @@ def generate_risk_events(
db: Session = Depends(get_db),
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return RiskService(db).generate_events(actor=principal.actor)
@@ -175,4 +180,5 @@ def generate_risk_events(
def enqueue_risk_events(
principal: ApiPrincipal = Depends(require_api_key),
) -> dict:
require_operations_enabled()
return enqueue_risk_event_generation(actor=principal.actor)

View File

@@ -21,9 +21,7 @@ class RiskResolveRequest(BaseModel):
class RiskCloseRequest(BaseModel):
closed_reason: str = Field(..., min_length=1)
review_summary: str | None = None
approval_ticket_id: str | None = None
class RiskReopenRequest(BaseModel):
comment: str | None = None
approval_ticket_id: str | None = None

View File

@@ -2,7 +2,6 @@ from datetime import date
from decimal import Decimal
from typing import Any
from fastapi import HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session
@@ -17,15 +16,12 @@ from app.modules.audit.constants import (
)
from app.modules.audit.schemas import AuditLogCreate
from app.modules.audit.service import AuditService
from app.modules.approvals.constants import ApprovalActionValue, approval_action
from app.modules.approvals.service import ApprovalService
from app.modules.business.constants import (
CLOSED_RISK_STATUSES,
DONE_STATUSES,
GENERATED_RISK_EVENT_TYPES,
PROJECT_CLOSED_STATUSES,
SUPPLIER_RISK_LEVELS,
BusinessErrorDetail,
BusinessDomain,
RiskEventType,
RiskLevel,
@@ -203,20 +199,8 @@ class RiskService:
closed_reason: str,
review_summary: str | None = None,
actor: str = ActorValue.API,
approval_ticket_id: str | None = None,
) -> dict[str, Any]:
record = self._get_event(risk_event_id)
approval_payload = {
RiskEventPayloadKey.STATUS: StatusValue.CLOSED,
"closed_reason": closed_reason,
RiskEventActionKey.REVIEW_SUMMARY: review_summary,
}
self._consume_risk_approval(
approval_ticket_id,
risk_event_id,
approval_payload,
actor,
)
from_status = record.status
now = utc_now()
record.status = StatusValue.CLOSED
@@ -244,19 +228,8 @@ class RiskService:
risk_event_id: int,
comment: str | None = None,
actor: str = ActorValue.API,
approval_ticket_id: str | None = None,
) -> dict[str, Any]:
record = self._get_event(risk_event_id)
approval_payload = {
RiskEventPayloadKey.STATUS: StatusValue.OPEN,
RiskEventActionKey.COMMENT: comment,
}
self._consume_risk_approval(
approval_ticket_id,
risk_event_id,
approval_payload,
actor,
)
from_status = record.status
record.status = StatusValue.OPEN
record.resolved_at = None
@@ -384,27 +357,6 @@ class RiskService:
RiskEventActionKey.ACTION_RECORD: serialize_model(action),
}
def _consume_risk_approval(
self,
approval_ticket_id: str | None,
risk_event_id: int,
payload: dict[str, Any],
actor: str,
) -> None:
if not approval_ticket_id:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=BusinessErrorDetail.HIGH_RISK_APPROVAL_REQUIRED,
)
ApprovalService(self.db).consume_for(
approval_ticket_id,
BusinessDomain.RISK_EVENTS,
risk_event_id,
approval_action(ApprovalActionValue.UPDATE, BusinessDomain.RISK_EVENTS),
payload,
actor,
)
def generate_events(self, actor: str = ActorValue.API) -> dict[str, Any]:
"""Generate or refresh risk-event ledger entries from current signals."""