新增电子试验主文件目录与文件归档

This commit is contained in:
Cheng Zhou
2026-05-28 10:54:13 +08:00
parent 31fcb7e6f2
commit fa961f1391
20 changed files with 2226 additions and 10 deletions
+23 -3
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import hashlib
import json
import uuid
@@ -16,6 +18,7 @@ from app.core.project_permissions import role_has_api_permission
from app.crud import acknowledgement as acknowledgement_crud
from app.crud import distribution as distribution_crud
from app.crud import document as document_crud
from app.crud import etmf as etmf_crud
from app.crud import document_version as version_crud
from app.crud import member as member_crud
from app.crud import site as site_crud
@@ -58,6 +61,7 @@ def _doc_snapshot(doc: Document) -> dict:
"id": str(doc.id),
"trial_id": str(doc.trial_id),
"site_id": str(doc.site_id) if doc.site_id else None,
"etmf_node_id": str(doc.etmf_node_id) if doc.etmf_node_id else None,
"doc_no": doc.doc_no,
"status": str(doc.status),
"current_effective_version_id": str(doc.current_effective_version_id) if doc.current_effective_version_id else None,
@@ -108,9 +112,20 @@ async def create_document(
current_user,
) -> Document:
await _ensure_study_access(db, doc_in.trial_id, current_user, action="create_document")
if doc_in.scope_type == DocumentScopeType.SITE and not doc_in.site_id:
etmf_node = None
if doc_in.etmf_node_id:
etmf_node = await etmf_crud.get_node(db, doc_in.etmf_node_id)
if not etmf_node:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="eTMF目录不存在")
if etmf_node.study_id != doc_in.trial_id:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="eTMF目录不属于当前项目")
if etmf_node.scope_type == DocumentScopeType.SITE and not doc_in.site_id:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="中心级eTMF目录需指定中心")
scope_type = etmf_node.scope_type if etmf_node else doc_in.scope_type
if scope_type == DocumentScopeType.SITE and not doc_in.site_id:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="分中心文件需指定分中心")
site_id = doc_in.site_id if doc_in.scope_type == DocumentScopeType.SITE else None
site_id = doc_in.site_id if scope_type == DocumentScopeType.SITE else None
if site_id:
site = await site_crud.get_site(db, site_id)
if not site or not site.is_active:
@@ -122,10 +137,11 @@ async def create_document(
doc = Document(
trial_id=doc_in.trial_id,
site_id=site_id,
etmf_node_id=doc_in.etmf_node_id,
doc_no=doc_in.doc_no,
doc_type=doc_in.doc_type,
title=doc_in.title,
scope_type=doc_in.scope_type,
scope_type=scope_type,
owner_id=doc_in.owner_id,
description=doc_in.description,
)
@@ -154,6 +170,7 @@ async def list_documents(
doc_type: str | None,
status: str | None,
scope_type: str | None,
etmf_node_id: uuid.UUID | None = None,
skip: int,
limit: int,
current_user,
@@ -168,6 +185,7 @@ async def list_documents(
doc_type=doc_type,
status=status,
scope_type=scope_type,
etmf_node_id=etmf_node_id,
cra_site_ids=cra_site_ids,
skip=skip,
limit=limit,
@@ -185,6 +203,7 @@ async def list_documents(
id=doc.id,
trial_id=doc.trial_id,
site_id=doc.site_id,
etmf_node_id=doc.etmf_node_id,
doc_type=doc.doc_type,
title=doc.title,
scope_type=doc.scope_type,
@@ -228,6 +247,7 @@ async def get_document_detail(
id=doc.id,
trial_id=doc.trial_id,
site_id=doc.site_id,
etmf_node_id=doc.etmf_node_id,
doc_type=doc.doc_type,
title=doc.title,
scope_type=doc.scope_type,