吸收数字员工日报物理事实发送记录预览

This commit is contained in:
baiyanyun
2026-06-15 17:20:42 +08:00
parent fd06f3bce3
commit 3a41eb40d0
9 changed files with 164 additions and 4 deletions

View File

@@ -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")

View File

@@ -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;

View File

@@ -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())

View File

@@ -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");