make case catalog read-only
This commit is contained in:
@@ -1,20 +1,10 @@
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.context import UserContext
|
||||
from app.core.exceptions import AppError
|
||||
from app.models.source_case import CaseBase
|
||||
from app.repositories.case_repository import CaseRepository
|
||||
from app.repositories.source_case_repository import SourceCaseRepository
|
||||
from app.schemas.case import (
|
||||
CaseDeletePreviewResponse,
|
||||
CaseDeleteRequest,
|
||||
CaseDeleteResponse,
|
||||
CaseDetailResponse,
|
||||
CaseListItem,
|
||||
CaseListResponse,
|
||||
CasePatientInfo,
|
||||
)
|
||||
from app.services.audit_service import AuditService
|
||||
from app.schemas.case import CaseDetailResponse, CaseListItem, CaseListResponse, CasePatientInfo
|
||||
|
||||
|
||||
class CaseService:
|
||||
@@ -62,51 +52,6 @@ class CaseService:
|
||||
order_item_types=sorted({item.item_type for item in order_items}),
|
||||
)
|
||||
|
||||
def get_delete_preview(self, case_id: int) -> CaseDeletePreviewResponse:
|
||||
"""病例删除预览:返回删除病例前端需要展示的影响范围。"""
|
||||
case = self.repo.get_case_by_id(case_id)
|
||||
if not case:
|
||||
raise AppError("CASE_NOT_FOUND", "case not found", 404)
|
||||
return CaseDeletePreviewResponse(
|
||||
case_id=case.id,
|
||||
case_title=case.title,
|
||||
can_delete=True,
|
||||
affected=self.repo.get_delete_preview_counts(case.id),
|
||||
)
|
||||
|
||||
def delete_case(self, case_id: int, payload: CaseDeleteRequest, ctx: UserContext) -> CaseDeleteResponse:
|
||||
"""病例删除:级联删除病例业务数据,并保留审计日志用于追踪操作。"""
|
||||
case = self.repo.get_case_by_id(case_id)
|
||||
if not case:
|
||||
raise AppError("CASE_NOT_FOUND", "case not found", 404)
|
||||
if not payload.confirm:
|
||||
raise AppError("CASE_DELETE_CONFIRM_REQUIRED", "case delete confirmation is required", 400)
|
||||
|
||||
preview = self.repo.get_delete_preview_counts(case_id)
|
||||
training_rows = (
|
||||
preview.get("training_session", 0)
|
||||
+ preview.get("training_order", 0)
|
||||
+ preview.get("training_submission", 0)
|
||||
+ preview.get("training_record", 0)
|
||||
)
|
||||
if training_rows and not payload.delete_training_data:
|
||||
raise AppError("CASE_DELETE_TRAINING_DATA_EXISTS", "case has training data; delete_training_data must be true", 400)
|
||||
|
||||
try:
|
||||
deleted_counts = self.repo.delete_case_cascade(case_id)
|
||||
AuditService(self.db).log(
|
||||
ctx,
|
||||
action="case.delete",
|
||||
resource_type="case",
|
||||
resource_id=str(case_id),
|
||||
metadata={"case_title": case.title, "deleted_counts": deleted_counts},
|
||||
)
|
||||
self.db.commit()
|
||||
except Exception:
|
||||
self.db.rollback()
|
||||
raise
|
||||
return CaseDeleteResponse(deleted=True, case_id=case_id, deleted_counts=deleted_counts)
|
||||
|
||||
def _to_list_item(self, case: CaseBase) -> CaseListItem:
|
||||
"""病例卡片转换:把 case_base 映射为当前前端病例列表结构。"""
|
||||
return CaseListItem(
|
||||
|
||||
Reference in New Issue
Block a user