```
refactor: 移除审批和回写功能模块 移除了整个审批(approvals)和官方回写(writebacks)功能模块, 包括相关模型、路由、服务和配置项。更新了数据库迁移文件, 删除了相关的审批请求表和官方回写运行表。同时从API路由器中 移除了相应的路由,并调整了安全常量和字段验证器以匹配变更。 ```
This commit is contained in:
@@ -10,21 +10,14 @@ from sqlalchemy import Select, func, select
|
||||
from sqlalchemy.sql.schema import Column
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.constants import ActorValue
|
||||
from app.core.pagination import bounded_limit, bounded_offset
|
||||
from app.modules.audit.constants import AuditRiskLevel, AuditSource
|
||||
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.registry import get_domain_model, get_writable_fields, is_high_risk_domain
|
||||
from app.modules.business.registry import get_domain_model, get_writable_fields
|
||||
from app.modules.business.constants import (
|
||||
INVALID_FIELD_VALUE_TEMPLATE,
|
||||
READ_ONLY_FIELD_TEMPLATE,
|
||||
UNKNOWN_FIELD_TEMPLATE,
|
||||
BusinessErrorDetail,
|
||||
BusinessField,
|
||||
BusinessPayloadKey,
|
||||
)
|
||||
|
||||
|
||||
@@ -90,11 +83,10 @@ def _model_payload(domain: str, model: Any, data: dict[str, Any]) -> dict[str, A
|
||||
|
||||
|
||||
class BusinessService:
|
||||
"""Manage generic CRUD operations across registered business domains."""
|
||||
"""Read business records across registered domains."""
|
||||
|
||||
def __init__(self, db: Session):
|
||||
self.db = db
|
||||
self.audit = AuditService(db)
|
||||
|
||||
def list_records(
|
||||
self,
|
||||
@@ -124,116 +116,3 @@ class BusinessService:
|
||||
detail=BusinessErrorDetail.RECORD_NOT_FOUND,
|
||||
)
|
||||
return serialize_model(record)
|
||||
|
||||
def create_record(
|
||||
self,
|
||||
domain: str,
|
||||
data: dict[str, Any],
|
||||
actor: str = ActorValue.API,
|
||||
approval_ticket_id: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
model = get_domain_model(domain)
|
||||
high_risk = is_high_risk_domain(domain)
|
||||
payload = _model_payload(domain, model, data)
|
||||
record = model(**payload)
|
||||
self.db.add(record)
|
||||
if high_risk:
|
||||
self.db.flush()
|
||||
self._consume_approval(
|
||||
approval_ticket_id,
|
||||
domain,
|
||||
record.id,
|
||||
approval_action(ApprovalActionValue.CREATE, domain),
|
||||
data,
|
||||
actor,
|
||||
)
|
||||
self.db.commit()
|
||||
self.db.refresh(record)
|
||||
result = serialize_model(record)
|
||||
self.audit.log(
|
||||
AuditLogCreate(
|
||||
actor=actor,
|
||||
source=AuditSource.API,
|
||||
action=approval_action(ApprovalActionValue.CREATE, domain),
|
||||
target_type=domain,
|
||||
target_id=str(record.id),
|
||||
risk_level=AuditRiskLevel.HIGH if high_risk else AuditRiskLevel.LOW,
|
||||
request_payload={
|
||||
BusinessPayloadKey.DATA: data,
|
||||
BusinessPayloadKey.APPROVAL_TICKET_ID: approval_ticket_id,
|
||||
},
|
||||
response_payload=result,
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
def update_record(
|
||||
self,
|
||||
domain: str,
|
||||
record_id: int,
|
||||
data: dict[str, Any],
|
||||
actor: str = ActorValue.API,
|
||||
approval_ticket_id: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
model = get_domain_model(domain)
|
||||
high_risk = is_high_risk_domain(domain)
|
||||
record = self.db.get(model, record_id)
|
||||
if record is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=BusinessErrorDetail.RECORD_NOT_FOUND,
|
||||
)
|
||||
payload = _model_payload(domain, model, data)
|
||||
if high_risk:
|
||||
self._consume_approval(
|
||||
approval_ticket_id,
|
||||
domain,
|
||||
record_id,
|
||||
approval_action(ApprovalActionValue.UPDATE, domain),
|
||||
data,
|
||||
actor,
|
||||
)
|
||||
for key, value in payload.items():
|
||||
setattr(record, key, value)
|
||||
self.db.commit()
|
||||
self.db.refresh(record)
|
||||
result = serialize_model(record)
|
||||
self.audit.log(
|
||||
AuditLogCreate(
|
||||
actor=actor,
|
||||
source=AuditSource.API,
|
||||
action=approval_action(ApprovalActionValue.UPDATE, domain),
|
||||
target_type=domain,
|
||||
target_id=str(record.id),
|
||||
risk_level=AuditRiskLevel.HIGH if high_risk else AuditRiskLevel.LOW,
|
||||
request_payload={
|
||||
BusinessPayloadKey.DATA: data,
|
||||
BusinessPayloadKey.APPROVAL_TICKET_ID: approval_ticket_id,
|
||||
},
|
||||
response_payload=result,
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
def _consume_approval(
|
||||
self,
|
||||
approval_ticket_id: str | None,
|
||||
domain: str,
|
||||
record_id: str | int | None,
|
||||
action: str,
|
||||
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,
|
||||
domain,
|
||||
record_id,
|
||||
action,
|
||||
payload,
|
||||
actor,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user