吸收数字员工日报物理事实发送记录预览
This commit is contained in:
@@ -133,6 +133,10 @@ public class DigitalEmployeeAdminWorkbenchRowDto {
|
||||
private String reportId;
|
||||
@JsonProperty("daily_report_fact_id")
|
||||
private String dailyReportFactId;
|
||||
@JsonProperty("daily_report_table")
|
||||
private String dailyReportTable;
|
||||
@JsonProperty("daily_report_materialized")
|
||||
private Boolean dailyReportMaterialized;
|
||||
@JsonProperty("daily_report_physical_fact_status")
|
||||
private String dailyReportPhysicalFactStatus;
|
||||
@JsonProperty("send_record_id")
|
||||
@@ -141,6 +145,10 @@ public class DigitalEmployeeAdminWorkbenchRowDto {
|
||||
private String sendChannel;
|
||||
@JsonProperty("send_request_status")
|
||||
private String sendRequestStatus;
|
||||
@JsonProperty("send_record_status")
|
||||
private String sendRecordStatus;
|
||||
@JsonProperty("formal_daily_report_page_disabled")
|
||||
private Boolean formalDailyReportPageDisabled;
|
||||
@JsonProperty("external_send_disabled")
|
||||
private Boolean externalSendDisabled;
|
||||
@JsonProperty("third_party_channel_disabled")
|
||||
|
||||
@@ -25,12 +25,20 @@ public class DigitalEmployeeDailyReportFact {
|
||||
private String clientKey;
|
||||
private String deviceId;
|
||||
private String reportId;
|
||||
private String dailyReportFactId;
|
||||
private String planId;
|
||||
private String status;
|
||||
private String physicalFactStatus;
|
||||
private String deliveryStatus;
|
||||
private String approvalStatus;
|
||||
private String approvalDecisionStatus;
|
||||
private String confirmedAt;
|
||||
private String reportDate;
|
||||
private String sendRecordId;
|
||||
private String sendChannel;
|
||||
private String sendRequestStatus;
|
||||
private String sendRecordStatus;
|
||||
private String materializedSource;
|
||||
private String businessView;
|
||||
private Date syncedAt;
|
||||
private Date modified;
|
||||
|
||||
@@ -300,12 +300,20 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
|
||||
.clientKey(record.getClientKey())
|
||||
.deviceId(record.getDeviceId())
|
||||
.reportId(reportId)
|
||||
.dailyReportFactId(firstString(view.get("daily_report_fact_id"), view.get("dailyReportFactId")))
|
||||
.planId(row.getPlanId())
|
||||
.status(row.getStatus())
|
||||
.physicalFactStatus(firstString(view.get("daily_report_physical_fact_status"), view.get("dailyReportPhysicalFactStatus"), view.get("physical_fact_status"), view.get("physicalFactStatus")))
|
||||
.deliveryStatus(firstString(view.get("delivery_status"), view.get("deliveryStatus")))
|
||||
.approvalStatus(firstString(view.get("approval_status"), view.get("approvalStatus")))
|
||||
.approvalDecisionStatus(firstString(view.get("approval_decision_status"), view.get("approvalDecisionStatus")))
|
||||
.confirmedAt(firstString(view.get("confirmed_at"), view.get("confirmedAt")))
|
||||
.reportDate(firstString(view.get("report_date"), view.get("reportDate")))
|
||||
.sendRecordId(firstString(view.get("send_record_id"), view.get("sendRecordId")))
|
||||
.sendChannel(firstString(view.get("send_channel"), view.get("sendChannel")))
|
||||
.sendRequestStatus(firstString(view.get("send_request_status"), view.get("sendRequestStatus")))
|
||||
.sendRecordStatus(firstString(view.get("send_record_status"), view.get("sendRecordStatus"), view.get("send_request_status"), view.get("sendRequestStatus")))
|
||||
.materializedSource(firstString(view.get("materialized_source"), view.get("materializedSource"), "digital_employee_daily_report_fact"))
|
||||
.businessView(record.getBusinessView())
|
||||
.syncedAt(record.getSyncedAt())
|
||||
.modified(now)
|
||||
@@ -1160,10 +1168,14 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
|
||||
.conflictStatus(firstString(businessView.get("conflict_status"), businessView.get("conflictStatus"), payload.get("conflict_status"), payload.get("conflictStatus")))
|
||||
.reportId(firstString(businessView.get("report_id"), payload.get("report_id")))
|
||||
.dailyReportFactId(firstString(businessView.get("daily_report_fact_id"), businessView.get("dailyReportFactId"), payload.get("daily_report_fact_id"), payload.get("dailyReportFactId")))
|
||||
.dailyReportTable(firstString(businessView.get("daily_report_table"), businessView.get("dailyReportTable"), payload.get("daily_report_table"), payload.get("dailyReportTable"), "digital_employee_daily_report_fact"))
|
||||
.dailyReportMaterialized(nullableBooleanValue(firstPresent(businessView.get("daily_report_materialized"), businessView.get("dailyReportMaterialized"), payload.get("daily_report_materialized"), payload.get("dailyReportMaterialized"))))
|
||||
.dailyReportPhysicalFactStatus(firstString(businessView.get("daily_report_physical_fact_status"), businessView.get("dailyReportPhysicalFactStatus"), payload.get("daily_report_physical_fact_status"), payload.get("dailyReportPhysicalFactStatus")))
|
||||
.sendRecordId(firstString(businessView.get("send_record_id"), businessView.get("sendRecordId"), payload.get("send_record_id"), payload.get("sendRecordId")))
|
||||
.sendChannel(firstString(businessView.get("send_channel"), businessView.get("sendChannel"), payload.get("send_channel"), payload.get("sendChannel")))
|
||||
.sendRequestStatus(firstString(businessView.get("send_request_status"), businessView.get("sendRequestStatus"), payload.get("send_request_status"), payload.get("sendRequestStatus")))
|
||||
.sendRecordStatus(firstString(businessView.get("send_record_status"), businessView.get("sendRecordStatus"), payload.get("send_record_status"), payload.get("sendRecordStatus"), businessView.get("send_request_status"), payload.get("send_request_status")))
|
||||
.formalDailyReportPageDisabled(nullableBooleanValue(firstPresent(businessView.get("formal_daily_report_page_disabled"), businessView.get("formalDailyReportPageDisabled"), payload.get("formal_daily_report_page_disabled"), payload.get("formalDailyReportPageDisabled"))))
|
||||
.externalSendDisabled(nullableBooleanValue(firstPresent(businessView.get("external_send_disabled"), businessView.get("externalSendDisabled"), payload.get("external_send_disabled"), payload.get("externalSendDisabled"))))
|
||||
.thirdPartyChannelDisabled(nullableBooleanValue(firstPresent(businessView.get("third_party_channel_disabled"), businessView.get("thirdPartyChannelDisabled"), payload.get("third_party_channel_disabled"), payload.get("thirdPartyChannelDisabled"))))
|
||||
.approvalDecisionStatus(firstString(businessView.get("approval_decision_status"), businessView.get("approvalDecisionStatus"), payload.get("approval_decision_status"), payload.get("approvalDecisionStatus")))
|
||||
@@ -1448,8 +1460,12 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
|
||||
|| startsWithAny(row.getKind(), "daily_report")
|
||||
|| StringUtils.isNotBlank(row.getReportId())
|
||||
|| StringUtils.isNotBlank(row.getDailyReportPhysicalFactStatus())
|
||||
|| StringUtils.isNotBlank(row.getDailyReportTable())
|
||||
|| row.getDailyReportMaterialized() != null
|
||||
|| StringUtils.isNotBlank(row.getSendChannel())
|
||||
|| StringUtils.isNotBlank(row.getSendRequestStatus())
|
||||
|| StringUtils.isNotBlank(row.getSendRecordStatus())
|
||||
|| row.getFormalDailyReportPageDisabled() != null
|
||||
|| row.getExternalSendDisabled() != null
|
||||
|| row.getThirdPartyChannelDisabled() != null
|
||||
|| StringUtils.isNotBlank(row.getDailyReportApprovalId())
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeDailyReportFac
|
||||
import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeSyncRecordRepository;
|
||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeAdminAction;
|
||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeBusinessFact;
|
||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeDailyReportFact;
|
||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeSyncRecord;
|
||||
import com.xspaceagi.system.spec.common.RequestContext;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -123,6 +124,59 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
|
||||
assertThat(factCaptor.getValue().getStatus()).isEqualTo("active");
|
||||
}
|
||||
|
||||
@Test
|
||||
void syncOutboxMaterializesDailyReportPhysicalFactAndSendRecord() {
|
||||
DigitalEmployeeSyncItemDto item = new DigitalEmployeeSyncItemDto();
|
||||
item.setOutboxId("outbox-daily-report-1");
|
||||
item.setEntityType("daily_report");
|
||||
item.setEntityId("report-1");
|
||||
item.setOperation("upsert");
|
||||
item.setBusinessView(Map.ofEntries(
|
||||
Map.entry("entity_type", "daily_report"),
|
||||
Map.entry("category", "daily_report"),
|
||||
Map.entry("kind", "daily_report_generated"),
|
||||
Map.entry("status", "generated"),
|
||||
Map.entry("title", "6 月 13 日日报"),
|
||||
Map.entry("report_id", "report-1"),
|
||||
Map.entry("daily_report_fact_id", "daily-report-fact-1"),
|
||||
Map.entry("daily_report_physical_fact_status", "materialized"),
|
||||
Map.entry("approval_decision_status", "approved"),
|
||||
Map.entry("send_record_id", "send-record-1"),
|
||||
Map.entry("send_channel", "email"),
|
||||
Map.entry("send_request_status", "recorded"),
|
||||
Map.entry("send_record_status", "materialized"),
|
||||
Map.entry("materialized_source", "digital_employee_daily_report_fact"),
|
||||
Map.entry("summary", "日报已物化")
|
||||
));
|
||||
item.setPayload(Map.of("id", "report-1", "kind", "daily_report_generated"));
|
||||
|
||||
DigitalEmployeeSyncRequestDto request = new DigitalEmployeeSyncRequestDto();
|
||||
request.setClientKey("client-key-001");
|
||||
request.setDeviceId("device-001");
|
||||
request.setItems(List.of(item));
|
||||
doAnswer(invocation -> {
|
||||
DigitalEmployeeSyncRecord saved = invocation.getArgument(0);
|
||||
saved.setId(1002L);
|
||||
return true;
|
||||
}).when(repository).save(any(DigitalEmployeeSyncRecord.class));
|
||||
|
||||
service.syncOutbox(request);
|
||||
|
||||
ArgumentCaptor<DigitalEmployeeDailyReportFact> factCaptor = ArgumentCaptor.forClass(DigitalEmployeeDailyReportFact.class);
|
||||
verify(dailyReportFactRepository).upsertBySyncRecord(factCaptor.capture());
|
||||
DigitalEmployeeDailyReportFact fact = factCaptor.getValue();
|
||||
assertThat(fact.getSyncRecordId()).isEqualTo(1002L);
|
||||
assertThat(fact.getReportId()).isEqualTo("report-1");
|
||||
assertThat(fact.getDailyReportFactId()).isEqualTo("daily-report-fact-1");
|
||||
assertThat(fact.getPhysicalFactStatus()).isEqualTo("materialized");
|
||||
assertThat(fact.getApprovalDecisionStatus()).isEqualTo("approved");
|
||||
assertThat(fact.getSendRecordId()).isEqualTo("send-record-1");
|
||||
assertThat(fact.getSendChannel()).isEqualTo("email");
|
||||
assertThat(fact.getSendRequestStatus()).isEqualTo("recorded");
|
||||
assertThat(fact.getSendRecordStatus()).isEqualTo("materialized");
|
||||
assertThat(fact.getMaterializedSource()).isEqualTo("digital_employee_daily_report_fact");
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryRecordsReturnsStoredBusinessMetadata() {
|
||||
DigitalEmployeeSyncRecord record = planRecord("plan-1", "客户回访", "active", 101L, new Date(1_000));
|
||||
@@ -2053,10 +2107,14 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
|
||||
Map.entry("title", "6 月 13 日日报"),
|
||||
Map.entry("report_id", "report-1"),
|
||||
Map.entry("daily_report_fact_id", "daily-report-fact-1"),
|
||||
Map.entry("daily_report_table", "digital_employee_daily_report_fact"),
|
||||
Map.entry("daily_report_materialized", true),
|
||||
Map.entry("daily_report_physical_fact_status", "pending_materialization"),
|
||||
Map.entry("send_record_id", "send-record-1"),
|
||||
Map.entry("send_channel", "email"),
|
||||
Map.entry("send_request_status", "recorded"),
|
||||
Map.entry("send_record_status", "materialized"),
|
||||
Map.entry("formal_daily_report_page_disabled", true),
|
||||
Map.entry("external_send_disabled", true),
|
||||
Map.entry("third_party_channel_disabled", true),
|
||||
Map.entry("approval_decision_status", "pending"),
|
||||
@@ -2128,10 +2186,14 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
|
||||
assertThat(result.getRecords().get(0).getStatus()).isEqualTo("generated");
|
||||
assertThat(result.getRecords().get(0).getSummary()).isEqualTo("日报已生成");
|
||||
assertThat(result.getRecords().get(0).getDailyReportFactId()).isEqualTo("daily-report-fact-1");
|
||||
assertThat(result.getRecords().get(0).getDailyReportTable()).isEqualTo("digital_employee_daily_report_fact");
|
||||
assertThat(result.getRecords().get(0).getDailyReportMaterialized()).isTrue();
|
||||
assertThat(result.getRecords().get(0).getDailyReportPhysicalFactStatus()).isEqualTo("pending_materialization");
|
||||
assertThat(result.getRecords().get(0).getSendRecordId()).isEqualTo("send-record-1");
|
||||
assertThat(result.getRecords().get(0).getSendChannel()).isEqualTo("email");
|
||||
assertThat(result.getRecords().get(0).getSendRequestStatus()).isEqualTo("recorded");
|
||||
assertThat(result.getRecords().get(0).getSendRecordStatus()).isEqualTo("materialized");
|
||||
assertThat(result.getRecords().get(0).getFormalDailyReportPageDisabled()).isTrue();
|
||||
assertThat(result.getRecords().get(0).getExternalSendDisabled()).isTrue();
|
||||
assertThat(result.getRecords().get(0).getThirdPartyChannelDisabled()).isTrue();
|
||||
assertThat(result.getRecords().get(0).getApprovalDecisionStatus()).isEqualTo("pending");
|
||||
|
||||
@@ -92,12 +92,20 @@ CREATE TABLE IF NOT EXISTS `digital_employee_daily_report_fact` (
|
||||
`client_key` VARCHAR(255) DEFAULT NULL COMMENT '客户端Key',
|
||||
`device_id` VARCHAR(255) DEFAULT NULL COMMENT '设备ID',
|
||||
`report_id` VARCHAR(255) NOT NULL COMMENT '日报ID',
|
||||
`daily_report_fact_id` VARCHAR(255) DEFAULT NULL COMMENT '日报事实ID',
|
||||
`plan_id` VARCHAR(255) DEFAULT NULL COMMENT '计划ID',
|
||||
`status` VARCHAR(128) DEFAULT NULL COMMENT '状态',
|
||||
`physical_fact_status` VARCHAR(128) DEFAULT NULL COMMENT '物理事实状态',
|
||||
`delivery_status` VARCHAR(128) DEFAULT NULL COMMENT '交付状态',
|
||||
`approval_status` VARCHAR(128) DEFAULT NULL COMMENT '审批状态',
|
||||
`approval_decision_status` VARCHAR(128) DEFAULT NULL COMMENT '审批裁决状态',
|
||||
`confirmed_at` VARCHAR(64) DEFAULT NULL COMMENT '确认时间',
|
||||
`report_date` VARCHAR(64) DEFAULT NULL COMMENT '日报日期',
|
||||
`send_record_id` VARCHAR(255) DEFAULT NULL COMMENT '发送记录ID',
|
||||
`send_channel` VARCHAR(128) DEFAULT NULL COMMENT '发送渠道',
|
||||
`send_request_status` VARCHAR(128) DEFAULT NULL COMMENT '发送请求状态',
|
||||
`send_record_status` VARCHAR(128) DEFAULT NULL COMMENT '发送记录状态',
|
||||
`materialized_source` VARCHAR(128) DEFAULT NULL COMMENT '物化来源',
|
||||
`business_view` JSON DEFAULT NULL COMMENT '业务视图快照',
|
||||
`synced_at` DATETIME DEFAULT NULL COMMENT '同步时间',
|
||||
`modified` DATETIME NOT NULL COMMENT '修改时间',
|
||||
|
||||
@@ -1223,6 +1223,10 @@ const DigitalEmployeeOps: React.FC = () => {
|
||||
{detailRecord.report_id || detailRecord.entity_id || '--'}
|
||||
{detailRecord.daily_report_fact_id &&
|
||||
` · 事实 ${detailRecord.daily_report_fact_id}`}
|
||||
{detailRecord.daily_report_table &&
|
||||
` · 正式日报物理表 ${detailRecord.daily_report_table}`}
|
||||
{detailRecord.daily_report_materialized != null &&
|
||||
` · 物化 ${detailRecord.daily_report_materialized ? '已写入' : '未写入'}`}
|
||||
{detailRecord.daily_report_physical_fact_status &&
|
||||
` · 物理事实 ${detailRecord.daily_report_physical_fact_status}`}
|
||||
{detailRecord.send_record_id &&
|
||||
@@ -1230,8 +1234,11 @@ const DigitalEmployeeOps: React.FC = () => {
|
||||
{detailRecord.send_channel && ` · 渠道 ${detailRecord.send_channel}`}
|
||||
{detailRecord.send_request_status &&
|
||||
` · 发送请求状态 ${detailRecord.send_request_status}`}
|
||||
{detailRecord.send_record_status &&
|
||||
` · 发送记录物化 ${detailRecord.send_record_status}`}
|
||||
{detailRecord.approval_decision_status &&
|
||||
` · 审批状态 ${detailRecord.approval_decision_status}`}
|
||||
{detailRecord.formal_daily_report_page_disabled && ' · 正式外部日报页面禁用'}
|
||||
{detailRecord.external_send_disabled && ' · 外部发送禁用'}
|
||||
{detailRecord.third_party_channel_disabled && ' · 第三方发送禁用'}
|
||||
{detailRecord.daily_report_approval_id &&
|
||||
@@ -1246,7 +1253,7 @@ const DigitalEmployeeOps: React.FC = () => {
|
||||
` · 裁决记录 ${detailRecord.daily_report_approval_recorded_at}`}
|
||||
<Typography.Text type="secondary">
|
||||
{' '}
|
||||
· 展示发送记录、审批状态、审批裁决、物理事实状态和事实来源,只记录发送请求/发送结果/审批/回执/裁决意图,不触发真实外部发送或第三方发送。
|
||||
· 展示正式日报物理表、发送记录物化、审批状态、审批裁决、物理事实状态和事实来源,只记录发送请求/发送结果/审批/回执/裁决意图,不触发真实外部发送或第三方发送,正式外部日报页面仍禁用。
|
||||
</Typography.Text>
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
|
||||
@@ -652,10 +652,14 @@ export interface DigitalEmployeeAdminWorkbenchRow {
|
||||
conflict_status?: string;
|
||||
report_id?: string;
|
||||
daily_report_fact_id?: string;
|
||||
daily_report_table?: string;
|
||||
daily_report_materialized?: boolean;
|
||||
daily_report_physical_fact_status?: string;
|
||||
send_record_id?: string;
|
||||
send_channel?: string;
|
||||
send_request_status?: string;
|
||||
send_record_status?: string;
|
||||
formal_daily_report_page_disabled?: boolean;
|
||||
external_send_disabled?: boolean;
|
||||
third_party_channel_disabled?: boolean;
|
||||
approval_decision_status?: string;
|
||||
|
||||
@@ -3129,20 +3129,66 @@ function checkDigitalAdminDailyReportWorkbench() {
|
||||
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
||||
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
||||
const docs = fs.readFileSync(docsPath, "utf8");
|
||||
const dailyReportFactEntity = fs.readFileSync(
|
||||
path.join(
|
||||
backendRoot,
|
||||
"app-platform-modules",
|
||||
"app-platform-agent",
|
||||
"app-platform-agent-core-adapter",
|
||||
"src",
|
||||
"main",
|
||||
"java",
|
||||
"com",
|
||||
"xspaceagi",
|
||||
"agent",
|
||||
"core",
|
||||
"adapter",
|
||||
"repository",
|
||||
"entity",
|
||||
"DigitalEmployeeDailyReportFact.java",
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
const sql = fs.readFileSync(path.join(backendRoot, "sql", "update-20260612.sql"), "utf8");
|
||||
const requiredSnippets = [
|
||||
[service, "daily_reports", "backend daily report view"],
|
||||
[service, "isDailyReportRow", "backend daily report matcher"],
|
||||
[service, "daily_report", "backend daily report category"],
|
||||
[service, "daily_report:record_approval_decision", "backend daily report approval decision action"],
|
||||
[service, "daily_report_table", "backend daily report table projection"],
|
||||
[service, "daily_report_materialized", "backend daily report materialized projection"],
|
||||
[service, "send_record_status", "backend send record status projection"],
|
||||
[service, "formal_daily_report_page_disabled", "backend formal daily report page guard projection"],
|
||||
[dto, "report_id", "backend report id row field"],
|
||||
[dto, "daily_report_table", "backend daily report table row field"],
|
||||
[dto, "daily_report_materialized", "backend daily report materialized row field"],
|
||||
[dto, "send_record_status", "backend send record status row field"],
|
||||
[dto, "formal_daily_report_page_disabled", "backend formal daily report page guard row field"],
|
||||
[dto, "daily_report_approval_id", "backend daily report approval id row field"],
|
||||
[dto, "daily_report_approval_action", "backend daily report approval action row field"],
|
||||
[dto, "daily_report_approval_recorded_at", "backend daily report approval recorded at row field"],
|
||||
[dailyReportFactEntity, "dailyReportFactId", "daily report fact entity fact id field"],
|
||||
[dailyReportFactEntity, "physicalFactStatus", "daily report fact entity physical status field"],
|
||||
[dailyReportFactEntity, "sendRecordStatus", "daily report fact entity send status field"],
|
||||
[dailyReportFactEntity, "materializedSource", "daily report fact entity materialized source field"],
|
||||
[sql, "daily_report_fact_id", "daily report fact sql fact id column"],
|
||||
[sql, "physical_fact_status", "daily report fact sql physical status column"],
|
||||
[sql, "send_record_status", "daily report fact sql send status column"],
|
||||
[sql, "materialized_source", "daily report fact sql materialized source column"],
|
||||
[test, "queryAdminWorkbenchDailyReportsReturnsDailyReportRowsOnly", "backend daily report workbench test"],
|
||||
[test, "syncOutboxMaterializesDailyReportPhysicalFactAndSendRecord", "backend daily report physical fact materialization test"],
|
||||
[test, "queryAdminWorkbenchDailyReportsReturnsPhysicalFactAndSendShellRows", "backend daily report physical send shell test"],
|
||||
[test, "getDailyReportApprovalId", "backend daily report approval assertion"],
|
||||
[qimingTypes, "daily_reports", "qiming daily report view type"],
|
||||
[qimingTypes, "daily_report_table", "qiming daily report table type field"],
|
||||
[qimingTypes, "daily_report_materialized", "qiming daily report materialized type field"],
|
||||
[qimingTypes, "send_record_status", "qiming send record status type field"],
|
||||
[qimingTypes, "formal_daily_report_page_disabled", "qiming formal daily report page guard type field"],
|
||||
[qimingTypes, "daily_report_approval_id", "qiming daily report approval id type field"],
|
||||
[qimingOps, "日报运营", "qiming daily report tab"],
|
||||
[qimingOps, "正式日报物理表", "qiming formal daily report physical table copy"],
|
||||
[qimingOps, "发送记录物化", "qiming send record materialized copy"],
|
||||
[qimingOps, "正式外部日报页面禁用", "qiming formal daily report page disabled copy"],
|
||||
[qimingOps, "记录已送达", "qiming daily report delivered action"],
|
||||
[qimingOps, "确认回执", "qiming daily report confirmed action"],
|
||||
[qimingOps, "请求审批", "qiming daily report approval action"],
|
||||
@@ -3150,6 +3196,7 @@ function checkDigitalAdminDailyReportWorkbench() {
|
||||
[qimingOps, "记录发送结果", "qiming daily report send record action"],
|
||||
[docs, "正式管理端日报运营预览", "docs daily report absorption"],
|
||||
[docs, "管理端日报审批裁决回写预览", "docs daily report approval decision absorption"],
|
||||
[docs, "正式日报物理事实与发送记录预览已开始吸收", "docs daily report physical fact send record absorption"],
|
||||
];
|
||||
const missing = requiredSnippets
|
||||
.filter(([content, snippet]) => !content.includes(snippet))
|
||||
|
||||
@@ -614,9 +614,9 @@ GET /api/digital-employee/approvals
|
||||
- 建议:先使用 sync record 派生业务查询模型和 embedded 业务视图预览承接联调,再按容量和查询压力决定是否拆 Plan / Task / Run / Event 物理业务表。
|
||||
|
||||
13. **日报实体与导出交付**
|
||||
- 已吸收:embedded 页面可基于当前 workday projection 导出本地文本日报;生成日报时会通过 qimingclaw bridge 写入 `daily_report` text / HTML / PDF Artifact 与 `daily_report_generated` Event,并可通过 `/api/digital-employee/daily-reports` 和详情接口读取只读日报投影。日报 HTML/PDF 导出、发送记录、管理端确认回执和日报发送审批已开始吸收,交付动作会写入 `daily_report_send_recorded` / `daily_report_confirmed` / `daily_report_approval_requested` 事件,sync `business_view.category = daily_report` 可被管理端筛选消费。管理端正式日报页面预览和正式管理端日报运营预览已开始吸收,embedded 新增“日报运营”入口,展示日报生成、交付、确认、审批和关联产物状态,并复用现有生成、记录发送、确认回执和请求审批动作;qiming-backend 的 `daily_reports` 运营台视图会聚合日报生成、发送记录、确认回执和审批请求,qiming“数字员工运营台”的“日报运营”tab 可记录已送达、确认回执、请求审批和发送结果。发送账单审计外壳已开始吸收,qiming-backend 新增 `/api/digital-employee/admin/daily-reports/send-records`,qiming 运营台可在日报详情中“记录发送结果”,但不接真实第三方发送通道。正式管理端协作运营收口已开始吸收,日报运营详情会展示 `daily_report_fact_id`、`send_record_id` 和 `approval_decision_status`,用于解释事实来源、发送记录和审批状态。管理端日报审批裁决回写预览已开始吸收,日报运营详情可展示 `daily_report_approval_id`、裁决动作、裁决人、原因和记录时间,并只记录审批裁决意图,不触发真实发送或自动审批。资产通知日报业务查询总收口已开始吸收,日报运营详情会补充 `daily_report_physical_fact_status`、发送渠道、发送请求状态、外部发送禁用和第三方发送禁用说明。
|
||||
- 缺口:没有正式 DailyReport 物理表、真实管理端发送通道和正式外部管理端日报页面。
|
||||
- 建议:先稳定 Artifact/Event 派生日报交付模型,再根据管理端联调需要决定是否物化 DailyReport 表与发送记录表。
|
||||
- 已吸收:embedded 页面可基于当前 workday projection 导出本地文本日报;生成日报时会通过 qimingclaw bridge 写入 `daily_report` text / HTML / PDF Artifact 与 `daily_report_generated` Event,并可通过 `/api/digital-employee/daily-reports` 和详情接口读取只读日报投影。日报 HTML/PDF 导出、发送记录、管理端确认回执和日报发送审批已开始吸收,交付动作会写入 `daily_report_send_recorded` / `daily_report_confirmed` / `daily_report_approval_requested` 事件,sync `business_view.category = daily_report` 可被管理端筛选消费。管理端正式日报页面预览和正式管理端日报运营预览已开始吸收,embedded 新增“日报运营”入口,展示日报生成、交付、确认、审批和关联产物状态,并复用现有生成、记录发送、确认回执和请求审批动作;qiming-backend 的 `daily_reports` 运营台视图会聚合日报生成、发送记录、确认回执和审批请求,qiming“数字员工运营台”的“日报运营”tab 可记录已送达、确认回执、请求审批和发送结果。发送账单审计外壳已开始吸收,qiming-backend 新增 `/api/digital-employee/admin/daily-reports/send-records`,qiming 运营台可在日报详情中“记录发送结果”,但不接真实第三方发送通道。正式管理端协作运营收口已开始吸收,日报运营详情会展示 `daily_report_fact_id`、`send_record_id` 和 `approval_decision_status`,用于解释事实来源、发送记录和审批状态。管理端日报审批裁决回写预览已开始吸收,日报运营详情可展示 `daily_report_approval_id`、裁决动作、裁决人、原因和记录时间,并只记录审批裁决意图,不触发真实发送或自动审批。资产通知日报业务查询总收口已开始吸收,日报运营详情会补充 `daily_report_physical_fact_status`、发送渠道、发送请求状态、外部发送禁用和第三方发送禁用说明。正式日报物理事实与发送记录预览已开始吸收,后端复用 `digital_employee_daily_report_fact` 增量物化日报事实、物理事实状态、审批裁决状态、发送记录状态和物化来源,qiming 日报运营详情展示正式日报物理表、发送记录物化和正式外部日报页面禁用状态。
|
||||
- 缺口:真实管理端发送通道、第三方发送通道、更完整 DailyReport 物理模型和正式外部管理端日报页面。
|
||||
- 建议:先稳定 `digital_employee_daily_report_fact` 增量物化与 Artifact/Event 派生交付模型,再根据管理端联调需要决定是否扩展正式 DailyReport 表、发送记录表和外部页面。
|
||||
|
||||
## 管理端联动原则
|
||||
|
||||
|
||||
Reference in New Issue
Block a user