新增完整的 channels 限界上下文模块,包含契约层、领域核心层、应用服务、管道编排、插件体系、基础设施组合根等全层级代码,新增飞书与微信 iLink 渠道插件基础结构,补充各类 DTO、端口协议与领域服务实现。
144 lines
4.7 KiB
Python
144 lines
4.7 KiB
Python
"""报告 DTO 定义。
|
||
|
||
包含报告聚合根 DTO、查询条件 DTO 与报告类型/状态枚举常量,以及 Report ↔ dict
|
||
互转的工具函数(供应用层响应序列化使用,避免反向依赖 adapters/mappers)。
|
||
对齐《19-聚合视图域-reports-router-设计方案.md》§5.3。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass, field
|
||
from datetime import datetime
|
||
from typing import Any
|
||
|
||
#: 报告类型枚举
|
||
REPORT_TYPES = frozenset(
|
||
{
|
||
"message_stats",
|
||
"session_stats",
|
||
"account_stats",
|
||
"delivery_stats",
|
||
"dashboard_overview",
|
||
}
|
||
)
|
||
|
||
#: 报告状态枚举(单向流转:pending → generating → ready / failed)
|
||
REPORT_STATUSES = frozenset(
|
||
{
|
||
"pending",
|
||
"generating",
|
||
"ready",
|
||
"failed",
|
||
}
|
||
)
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class Report:
|
||
"""报告聚合根 DTO。
|
||
|
||
字段:
|
||
report_id: 报告唯一标识(UUID,``rpt_`` 前缀)。
|
||
task_id: 关联的 scheduler 任务 ID(UUID)。
|
||
report_type: 报告类型(取值 ``REPORT_TYPES``)。
|
||
status: 报告状态(取值 ``REPORT_STATUSES``)。
|
||
params: 报告生成参数(JSON,如时间范围、过滤条件)。
|
||
content: 报告内容(JSON,仅 status=ready 时非空)。
|
||
error_message: 失败原因(仅 status=failed 时非空)。
|
||
created_at: 创建时间。
|
||
ready_at: 就绪时间(status=ready 时非空)。
|
||
created_by: 创建人(operator.user_id)。
|
||
retried_from: 重试来源报告的 task_id(仅重试生成的新报告非空)。
|
||
retried_at: 原报告被重试的时间(原报告标记字段,新报告为 None)。
|
||
"""
|
||
|
||
report_id: str
|
||
task_id: str
|
||
report_type: str
|
||
status: str
|
||
params: dict[str, Any] = field(default_factory=dict)
|
||
content: dict[str, Any] | None = None
|
||
error_message: str | None = None
|
||
created_at: datetime | None = None
|
||
ready_at: datetime | None = None
|
||
created_by: str = "system"
|
||
retried_from: str | None = None
|
||
retried_at: datetime | None = None
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class ReportQuery:
|
||
"""报告查询条件。
|
||
|
||
字段:
|
||
status: 按状态过滤(可选)。
|
||
report_type: 按报告类型过滤(可选)。
|
||
start_time: 起始时间(按 created_at 过滤,可选)。
|
||
end_time: 截止时间(按 created_at 过滤,可选)。
|
||
limit: 分页大小(默认 100,上限 200)。
|
||
offset: 分页偏移(默认 0)。
|
||
"""
|
||
|
||
status: str | None = None
|
||
report_type: str | None = None
|
||
start_time: datetime | None = None
|
||
end_time: datetime | None = None
|
||
limit: int = 100
|
||
offset: int = 0
|
||
|
||
|
||
def reportToDict(report: Report) -> dict[str, Any]:
|
||
"""Report DTO → dict(dispatch handler 返回值序列化)。
|
||
|
||
纯 DTO 序列化函数,不依赖 ORM,供应用层控制面分派与 router 响应使用。
|
||
包含 error_message(失败原因)与 retried_at(重试时间),供前端详情页展示。
|
||
"""
|
||
return {
|
||
"report_id": report.report_id,
|
||
"task_id": report.task_id,
|
||
"report_type": report.report_type,
|
||
"status": report.status,
|
||
"params": report.params,
|
||
"content": report.content,
|
||
"error_message": report.error_message,
|
||
"created_at": report.created_at.isoformat() if report.created_at else None,
|
||
"ready_at": report.ready_at.isoformat() if report.ready_at else None,
|
||
"created_by": report.created_by,
|
||
"retried_at": report.retried_at.isoformat() if report.retried_at else None,
|
||
"download_url": f"/api/channels/reports/oneoff/{report.task_id}/download",
|
||
}
|
||
|
||
|
||
def reportSummaryToDict(report: Report) -> dict[str, Any]:
|
||
"""Report DTO → 摘要 dict(列表项序列化)。
|
||
|
||
纯 DTO 序列化函数,不依赖 ORM,供应用层列表响应使用。
|
||
"""
|
||
return {
|
||
"report_id": report.report_id,
|
||
"task_id": report.task_id,
|
||
"report_type": report.report_type,
|
||
"status": report.status,
|
||
"created_at": report.created_at.isoformat() if report.created_at else None,
|
||
"ready_at": report.ready_at.isoformat() if report.ready_at else None,
|
||
"created_by": report.created_by,
|
||
}
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class RetryReportResult:
|
||
"""重试失败报告结果(RPT-ONEOFF-RETRY)。
|
||
|
||
描述重试操作的返回结果,包括原任务 ID 与新生成任务 ID,由
|
||
``ReportManagementPort.retryReport`` 引用。
|
||
|
||
字段:
|
||
task_id: 原失败报告任务 ID。
|
||
new_task_id: 重试生成的新报告任务 ID。
|
||
retried_at: 重试时间戳。
|
||
"""
|
||
|
||
task_id: str
|
||
new_task_id: str
|
||
retried_at: datetime
|