功能(提醒):统一项目提醒中心与桌面通知链路
增加通用提醒状态、数据库迁移和定时同步,覆盖风险时效、文件回执、项目里程碑、访视窗口与协作申请。 新增网页端和桌面端提醒中心、真实投递诊断与固定隐私通知正文,并补齐登录来源聚合、测试和说明文档。
This commit is contained in:
@@ -11,7 +11,7 @@ from urllib.parse import quote
|
||||
import aiofiles
|
||||
from fastapi import HTTPException, UploadFile, status
|
||||
from fastapi.responses import FileResponse
|
||||
from sqlalchemy import and_, delete as sa_delete, or_, select, update as sa_update
|
||||
from sqlalchemy import String, and_, cast, delete as sa_delete, or_, select, update as sa_update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.deps import get_cra_site_scope
|
||||
@@ -32,6 +32,7 @@ from app.models.distribution import Distribution, DistributionStatus, Distributi
|
||||
from app.models.document import Document, DocumentScopeType, DocumentStatus
|
||||
from app.models.document_version import DocumentVersion, DocumentVersionStatus
|
||||
from app.models.desktop_notification import DesktopNotificationDelivery
|
||||
from app.models.notification import Notification
|
||||
from app.models.study import Study
|
||||
from app.schemas.acknowledgement import AcknowledgementCreate
|
||||
from app.schemas.distribution import DistributionCreate, DistributionRead, DistributionStats
|
||||
@@ -39,6 +40,7 @@ from app.schemas.document import DocumentCreate, DocumentDetail, DocumentSummary
|
||||
from app.schemas.document_version import DocumentVersionRead, DocumentVersionSummary
|
||||
from app.schemas.notification import NotificationItem
|
||||
from app.schemas.user import UserDisplay
|
||||
from app.services import notification_service
|
||||
|
||||
UPLOAD_ROOT = Path(__file__).resolve().parent.parent / "uploads" / "documents"
|
||||
|
||||
@@ -688,6 +690,10 @@ async def create_acknowledgement(
|
||||
if distribution.target_type == DistributionTargetType.ROLE:
|
||||
if distribution.target_id not in ("ADMIN" if is_system_admin(current_user) else "", getattr(membership, "role_in_study", "")):
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="不在分发范围内")
|
||||
if distribution.target_type == DistributionTargetType.SITE and not is_system_admin(current_user):
|
||||
site_ids = await site_crud.list_ids_by_contact_user(db, doc.trial_id, current_user.id)
|
||||
if distribution.target_id not in {str(site_id) for site_id in site_ids}:
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="不在分发中心范围内")
|
||||
|
||||
if payload.ack_type != AcknowledgementType.RECEIVED:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="仅支持已接收回执")
|
||||
@@ -722,6 +728,12 @@ async def create_acknowledgement(
|
||||
operator_role=await get_operator_role_label(db, doc.trial_id, current_user),
|
||||
)
|
||||
)
|
||||
await notification_service.resolve_source_notifications(
|
||||
db,
|
||||
source_type="DOCUMENT_DISTRIBUTION",
|
||||
source_id=str(distribution.id),
|
||||
recipient_id=current_user.id,
|
||||
)
|
||||
await db.commit()
|
||||
await db.refresh(ack)
|
||||
return ack
|
||||
@@ -812,10 +824,18 @@ async def list_distribution_notifications(
|
||||
.join(DocumentVersion, Distribution.version_id == DocumentVersion.id)
|
||||
.join(Document, Distribution.document_id == Document.id)
|
||||
.join(Study, Document.trial_id == Study.id)
|
||||
.outerjoin(
|
||||
Notification,
|
||||
and_(
|
||||
Notification.source_type == "DOCUMENT_DISTRIBUTION",
|
||||
Notification.source_id == cast(Distribution.id, String),
|
||||
Notification.recipient_id == current_user.id,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
DesktopNotificationDelivery,
|
||||
and_(
|
||||
DesktopNotificationDelivery.distribution_id == Distribution.id,
|
||||
DesktopNotificationDelivery.notification_id == Notification.id,
|
||||
DesktopNotificationDelivery.user_id == current_user.id,
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user