文件版本管理-初步优化

This commit is contained in:
Cheng Zhou
2026-01-14 11:35:37 +08:00
parent ef1e67218c
commit f9ef5c109f
46 changed files with 4603 additions and 30 deletions
+29
View File
@@ -0,0 +1,29 @@
import enum
import uuid
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict
class AcknowledgementType(str, enum.Enum):
RECEIVED = "RECEIVED"
class AcknowledgementCreate(BaseModel):
ack_type: AcknowledgementType
evidence: Optional[str] = None
class AcknowledgementRead(BaseModel):
id: uuid.UUID
distribution_id: uuid.UUID
user_id: uuid.UUID
site_id: Optional[uuid.UUID] = None
ack_type: AcknowledgementType
due_at: Optional[datetime] = None
acked_at: Optional[datetime] = None
note: Optional[str] = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
+50
View File
@@ -0,0 +1,50 @@
import enum
import uuid
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict, Field
class DistributionTargetType(str, enum.Enum):
SITE = "SITE"
ROLE = "ROLE"
USER = "USER"
class DistributionStatus(str, enum.Enum):
ACTIVE = "ACTIVE"
CLOSED = "CLOSED"
class DistributionTarget(BaseModel):
target_type: DistributionTargetType
target_id: str
class DistributionCreate(BaseModel):
targets: list[DistributionTarget]
due_at: Optional[datetime] = None
class DistributionStats(BaseModel):
total: int = 0
received: int = 0
read: int = 0
trained: int = 0
overdue: int = 0
class DistributionRead(BaseModel):
id: uuid.UUID
document_id: uuid.UUID
version_id: uuid.UUID
target_type: DistributionTargetType
target_id: str
status: DistributionStatus
due_at: Optional[datetime] = None
created_by: Optional[uuid.UUID] = None
created_at: datetime
stats: DistributionStats = Field(default_factory=DistributionStats)
model_config = ConfigDict(from_attributes=True)
+70
View File
@@ -0,0 +1,70 @@
import enum
import uuid
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict, Field
from app.schemas.document_version import DocumentVersionRead, DocumentVersionSummary
from app.schemas.distribution import DistributionStats
from app.schemas.user import UserDisplay
class DocumentScopeType(str, enum.Enum):
GLOBAL = "GLOBAL"
SITE = "SITE"
DERIVED = "DERIVED"
class DocumentStatus(str, enum.Enum):
DRAFT = "DRAFT"
ACTIVE = "ACTIVE"
ARCHIVED = "ARCHIVED"
class DocumentCreate(BaseModel):
trial_id: uuid.UUID
site_id: Optional[uuid.UUID] = None
doc_no: str
doc_type: str
title: str
scope_type: DocumentScopeType = DocumentScopeType.GLOBAL
owner_id: Optional[uuid.UUID] = None
description: Optional[str] = None
class DocumentUpdate(BaseModel):
title: Optional[str] = None
doc_type: Optional[str] = None
scope_type: Optional[DocumentScopeType] = None
owner_id: Optional[uuid.UUID] = None
site_id: Optional[uuid.UUID] = None
status: Optional[DocumentStatus] = None
description: Optional[str] = None
class DocumentSummary(BaseModel):
id: uuid.UUID
trial_id: uuid.UUID
site_id: Optional[uuid.UUID] = None
doc_no: str
doc_type: str
title: str
scope_type: DocumentScopeType
owner_id: Optional[uuid.UUID]
status: DocumentStatus
current_effective_version_id: Optional[uuid.UUID]
current_effective_version: Optional[DocumentVersionSummary] = None
created_at: datetime
updated_at: datetime
model_config = ConfigDict(from_attributes=True)
class DocumentDetail(DocumentSummary):
description: Optional[str] = None
owner: Optional[UserDisplay] = None
version_timeline: list[DocumentVersionRead] = Field(default_factory=list)
distribution_stats: DistributionStats = Field(default_factory=DistributionStats)
model_config = ConfigDict(from_attributes=True)
+57
View File
@@ -0,0 +1,57 @@
import enum
import uuid
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict
class DocumentVersionStatus(str, enum.Enum):
DRAFT = "DRAFT"
SUBMITTED = "SUBMITTED"
APPROVED = "APPROVED"
EFFECTIVE = "EFFECTIVE"
SUPERSEDED = "SUPERSEDED"
ARCHIVED = "ARCHIVED"
WITHDRAWN = "WITHDRAWN"
class DocumentVersionSummary(BaseModel):
id: uuid.UUID
version_no: str
status: DocumentVersionStatus
effective_at: Optional[datetime] = None
model_config = ConfigDict(from_attributes=True)
class DocumentVersionRead(BaseModel):
id: uuid.UUID
document_id: uuid.UUID
version_no: str
parent_version_id: Optional[uuid.UUID] = None
derived_from_version_id: Optional[uuid.UUID] = None
status: DocumentVersionStatus
effective_at: Optional[datetime] = None
superseded_at: Optional[datetime] = None
file_uri: str
file_hash: str
file_size: int
mime_type: Optional[str] = None
change_summary: Optional[str] = None
created_by: Optional[uuid.UUID] = None
submitted_at: Optional[datetime] = None
approved_at: Optional[datetime] = None
withdrawn_at: Optional[datetime] = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class VersionSubmitRequest(BaseModel):
template_id: uuid.UUID
comment: Optional[str] = None
class VersionActionRequest(BaseModel):
comment: Optional[str] = None
+1 -1
View File
@@ -5,7 +5,7 @@ from typing import Literal, Optional
from pydantic import BaseModel, ConfigDict, Field
from app.schemas.user import UserDisplay
StudyRole = Literal["PM", "CRA", "PV", "IMP", "ADMIN"]
StudyRole = Literal["PM", "CRA", "PV", "IMP", "QA", "ADMIN"]
class StudyMemberCreate(BaseModel):
+1 -1
View File
@@ -5,7 +5,7 @@ from typing import Literal, Optional
from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
UserRole = Literal["PM", "CRA", "PV", "IMP", "ADMIN"]
UserRole = Literal["PM", "CRA", "PV", "IMP", "QA", "ADMIN"]
RegisterRole = Literal["PM", "CRA", "PV", "IMP"]
UserStatus = Literal["PENDING", "ACTIVE", "REJECTED", "DISABLED"]
+29
View File
@@ -0,0 +1,29 @@
import uuid
from datetime import datetime
from pydantic import BaseModel, ConfigDict
class WorkflowNodeRead(BaseModel):
id: uuid.UUID
node_order: int
role: str
name: str | None = None
is_required: bool
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class WorkflowTemplateRead(BaseModel):
id: uuid.UUID
trial_id: uuid.UUID | None = None
name: str
description: str | None = None
is_active: bool
created_by: uuid.UUID | None = None
created_at: datetime
updated_at: datetime
nodes: list[WorkflowNodeRead] = []
model_config = ConfigDict(from_attributes=True)