立项配置数据入库、审计日志数据入库、编辑页UI界面美化、设备管理内容补充、审计日志显示优化
This commit is contained in:
@@ -14,3 +14,10 @@ class AuditLogRead(BaseModel):
|
||||
created_at: datetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class AuditEventCreate(BaseModel):
|
||||
action: str
|
||||
detail: Optional[str] = None
|
||||
entity_type: Optional[str] = None
|
||||
entity_id: Optional[uuid.UUID] = None
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, field_validator
|
||||
|
||||
|
||||
class MaterialEquipmentCreate(BaseModel):
|
||||
name: str
|
||||
spec_model: str
|
||||
unit: str | None = None
|
||||
brand: str
|
||||
origin: str | None = None
|
||||
production_permit_file_name: str | None = None
|
||||
tech_index_file_name: str | None = None
|
||||
need_calibration: bool
|
||||
calibration_cycle_days: int | None = None
|
||||
|
||||
@field_validator("name", "spec_model", "brand", mode="before")
|
||||
@classmethod
|
||||
def _strip_required(cls, value: str) -> str:
|
||||
text = (value or "").strip()
|
||||
if not text:
|
||||
raise ValueError("不能为空")
|
||||
return text
|
||||
|
||||
@field_validator("unit", "origin", "production_permit_file_name", "tech_index_file_name", mode="before")
|
||||
@classmethod
|
||||
def _strip_optional(cls, value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
text = value.strip()
|
||||
return text or None
|
||||
|
||||
|
||||
class MaterialEquipmentUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
spec_model: str | None = None
|
||||
unit: str | None = None
|
||||
brand: str | None = None
|
||||
origin: str | None = None
|
||||
production_permit_file_name: str | None = None
|
||||
tech_index_file_name: str | None = None
|
||||
need_calibration: bool | None = None
|
||||
calibration_cycle_days: int | None = None
|
||||
|
||||
@field_validator("name", "spec_model", "brand", mode="before")
|
||||
@classmethod
|
||||
def _strip_required(cls, value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
text = value.strip()
|
||||
if not text:
|
||||
raise ValueError("不能为空")
|
||||
return text
|
||||
|
||||
@field_validator("unit", "origin", "production_permit_file_name", "tech_index_file_name", mode="before")
|
||||
@classmethod
|
||||
def _strip_optional(cls, value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
text = value.strip()
|
||||
return text or None
|
||||
|
||||
|
||||
class MaterialEquipmentRead(BaseModel):
|
||||
id: uuid.UUID
|
||||
study_id: uuid.UUID
|
||||
name: str
|
||||
spec_model: str
|
||||
unit: str | None
|
||||
brand: str
|
||||
origin: str | None
|
||||
production_permit_file_name: str | None
|
||||
tech_index_file_name: str | None
|
||||
need_calibration: bool
|
||||
calibration_cycle_days: int | None
|
||||
created_by: uuid.UUID | None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -0,0 +1,29 @@
|
||||
import uuid
|
||||
from datetime import date, datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class ProjectMilestoneRead(BaseModel):
|
||||
id: uuid.UUID
|
||||
study_id: uuid.UUID
|
||||
name: str
|
||||
planned_date: date | None
|
||||
adjusted_start_date: date | None
|
||||
adjusted_end_date: date | None
|
||||
actual_start_date: date | None
|
||||
actual_end_date: date | None
|
||||
status: str
|
||||
notes: str | None
|
||||
owner_name: str | None
|
||||
updated_at: datetime
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class ProjectMilestoneUpdate(BaseModel):
|
||||
adjusted_start_date: date | None = None
|
||||
adjusted_end_date: date | None = None
|
||||
actual_start_date: date | None = None
|
||||
actual_end_date: date | None = None
|
||||
notes: str | None = None
|
||||
@@ -80,6 +80,7 @@ class StudySetupConfigData(BaseModel):
|
||||
class StudySetupConfigUpsert(BaseModel):
|
||||
expected_version: int | None = None
|
||||
data: StudySetupConfigData
|
||||
force_draft: bool = False
|
||||
|
||||
|
||||
class StudySetupConfigPublish(BaseModel):
|
||||
@@ -120,6 +121,34 @@ class SetupProjectionSummary(BaseModel):
|
||||
skipped_items: list[SetupProjectionSkippedItem] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ProjectPublishSnapshot(BaseModel):
|
||||
code: str = ""
|
||||
name: str = ""
|
||||
project_full_name: str = ""
|
||||
sponsor: str = ""
|
||||
protocol_no: str = ""
|
||||
lead_unit: str = ""
|
||||
principal_investigator: str = ""
|
||||
main_pm: str = ""
|
||||
research_analysis: str = ""
|
||||
research_product: str = ""
|
||||
control_product: str = ""
|
||||
indication: str = ""
|
||||
research_population: str = ""
|
||||
research_design: str = ""
|
||||
plan_start_date: str = ""
|
||||
plan_end_date: str = ""
|
||||
planned_site_count: int | None = None
|
||||
planned_enrollment_count: int | None = None
|
||||
summary_note: str = ""
|
||||
objective_note: str = ""
|
||||
status: str = ""
|
||||
visit_interval_days: int | None = None
|
||||
visit_total: int | None = None
|
||||
visit_window_start_offset: int | None = None
|
||||
visit_window_end_offset: int | None = None
|
||||
|
||||
|
||||
class StudySetupConfigRead(BaseModel):
|
||||
id: uuid.UUID
|
||||
study_id: uuid.UUID
|
||||
@@ -127,6 +156,7 @@ class StudySetupConfigRead(BaseModel):
|
||||
data: StudySetupConfigData
|
||||
publish_status: str
|
||||
published_data: StudySetupConfigData | None = None
|
||||
published_project_snapshot: ProjectPublishSnapshot | None = None
|
||||
published_by: uuid.UUID | None = None
|
||||
published_by_name: str | None = None
|
||||
published_at: datetime | None = None
|
||||
|
||||
Reference in New Issue
Block a user