feat: refine subject visits and project workflows

Add early termination visit workflow with ordering, non-applicable visit handling, visit window display, and medication adherence support.

Extend monitoring visit issue template fields, site scoping, setup draft project info handling, login security UI, attachment behavior, and related tests/migrations.
This commit is contained in:
Cheng Zhou
2026-05-09 17:10:34 +08:00
parent 74feca4467
commit 917ab7ccf1
41 changed files with 3463 additions and 701 deletions
@@ -6,7 +6,11 @@ from pydantic import BaseModel, ConfigDict, field_validator
class MonitoringVisitIssueCreate(BaseModel):
issue_no: str | None = None
site_id: uuid.UUID | None = None
category: str
severity: str | None = None
mark: str | None = None
visit_cycle: str | None = None
subject_code: str | None = None
monitor_item: str | None = None
monitor_type: str | None = None
@@ -18,6 +22,9 @@ class MonitoringVisitIssueCreate(BaseModel):
description: str | None = None
action_taken: str | None = None
follow_up_progress: str | None = None
center_query: str | None = None
center_latest_reply: str | None = None
rectification_completed: bool = False
found_date: date | None = None
due_at: datetime | None = None
actual_resolve_date: date | None = None
@@ -42,6 +49,9 @@ class MonitoringVisitIssueCreate(BaseModel):
@field_validator(
"subject_code",
"severity",
"mark",
"visit_cycle",
"monitor_item",
"monitor_type",
"source",
@@ -51,6 +61,8 @@ class MonitoringVisitIssueCreate(BaseModel):
"description",
"action_taken",
"follow_up_progress",
"center_query",
"center_latest_reply",
"responsible_name",
mode="before",
)
@@ -80,9 +92,13 @@ class MonitoringVisitIssueCreate(BaseModel):
class MonitoringVisitIssueRead(BaseModel):
id: uuid.UUID
study_id: uuid.UUID
site_id: uuid.UUID | None
issue_no: str
open_duration: str
category: str
severity: str | None
mark: str | None
visit_cycle: str | None
subject_code: str | None
monitor_item: str | None
monitor_type: str | None
@@ -96,6 +112,9 @@ class MonitoringVisitIssueRead(BaseModel):
description: str | None
action_taken: str | None
follow_up_progress: str | None
center_query: str | None
center_latest_reply: str | None
rectification_completed: bool
found_date: date | None
overdue: bool
due_at: datetime | None
@@ -115,7 +134,11 @@ class MonitoringVisitIssueImportSummary(BaseModel):
class MonitoringVisitIssueUpdate(BaseModel):
issue_no: str | None = None
site_id: uuid.UUID | None = None
category: str | None = None
severity: str | None = None
mark: str | None = None
visit_cycle: str | None = None
subject_code: str | None = None
monitor_item: str | None = None
monitor_type: str | None = None
@@ -127,6 +150,9 @@ class MonitoringVisitIssueUpdate(BaseModel):
description: str | None = None
action_taken: str | None = None
follow_up_progress: str | None = None
center_query: str | None = None
center_latest_reply: str | None = None
rectification_completed: bool | None = None
found_date: date | None = None
due_at: datetime | None = None
actual_resolve_date: date | None = None
@@ -145,6 +171,9 @@ class MonitoringVisitIssueUpdate(BaseModel):
@field_validator(
"subject_code",
"severity",
"mark",
"visit_cycle",
"monitor_item",
"monitor_type",
"source",
@@ -154,6 +183,8 @@ class MonitoringVisitIssueUpdate(BaseModel):
"description",
"action_taken",
"follow_up_progress",
"center_query",
"center_latest_reply",
"responsible_name",
mode="before",
)