吸收数字员工管理端审计归档账单预览

This commit is contained in:
baiyanyun
2026-06-14 13:21:51 +08:00
parent dd6c10f44b
commit 8b651e4ae1
7 changed files with 111 additions and 23 deletions

View File

@@ -141,6 +141,17 @@ public class DigitalEmployeeAdminWorkbenchRowDto {
private String toolName;
@JsonProperty("server_id")
private String serverId;
@JsonProperty("audit_archive_id")
private String auditArchiveId;
@JsonProperty("archive_status")
private String archiveStatus;
@JsonProperty("archive_location")
private String archiveLocation;
@JsonProperty("billing_estimate_id")
private String billingEstimateId;
@JsonProperty("billing_source")
private String billingSource;
private Boolean estimated;
@JsonProperty("policy_kind")
private String policyKind;
@JsonProperty("policy_key")

View File

@@ -1113,6 +1113,12 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
.policyStatus(firstString(businessView.get("policy_status"), businessView.get("policyStatus"), payload.get("policy_status"), payload.get("policyStatus")))
.toolName(firstString(businessView.get("tool_name"), businessView.get("toolName"), payload.get("tool_name"), payload.get("toolName")))
.serverId(firstString(businessView.get("server_id"), businessView.get("serverId"), payload.get("server_id"), payload.get("serverId")))
.auditArchiveId(firstString(businessView.get("audit_archive_id"), businessView.get("auditArchiveId"), payload.get("audit_archive_id"), payload.get("auditArchiveId")))
.archiveStatus(firstString(businessView.get("archive_status"), businessView.get("archiveStatus"), payload.get("archive_status"), payload.get("archiveStatus")))
.archiveLocation(firstString(businessView.get("archive_location"), businessView.get("archiveLocation"), payload.get("archive_location"), payload.get("archiveLocation")))
.billingEstimateId(firstString(businessView.get("billing_estimate_id"), businessView.get("billingEstimateId"), payload.get("billing_estimate_id"), payload.get("billingEstimateId")))
.billingSource(firstString(businessView.get("billing_source"), businessView.get("billingSource"), payload.get("billing_source"), payload.get("billingSource")))
.estimated(nullableBooleanValue(firstPresent(businessView.get("estimated"), payload.get("estimated"))))
.policyKind(firstString(businessView.get("policy_kind"), businessView.get("policyKind"), payload.get("policy_kind"), payload.get("policyKind")))
.policyKey(firstString(businessView.get("policy_key"), businessView.get("policyKey"), payload.get("policy_key"), payload.get("policyKey")))
.scheduleId(firstString(businessView.get("schedule_id"), businessView.get("scheduleId"), payload.get("schedule_id"), payload.get("scheduleId")))
@@ -1216,9 +1222,12 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
}
private boolean isAuditRow(DigitalEmployeeAdminWorkbenchRowDto row) {
return Set.of("sandbox_audit", "token_cost", "tool_call_audit", "governance", "sync_failure").contains(row.getCategory())
return Set.of("sandbox_audit", "token_cost", "tool_call_audit", "governance", "sync_failure", "audit_archive", "billing_estimate").contains(row.getCategory())
|| contains(row.getKind(), "audit")
|| contains(row.getKind(), "cost");
|| contains(row.getKind(), "cost")
|| contains(row.getKind(), "billing")
|| StringUtils.isNotBlank(row.getAuditArchiveId())
|| StringUtils.isNotBlank(row.getBillingEstimateId());
}
private boolean isDailyReportRow(DigitalEmployeeAdminWorkbenchRowDto row) {

View File

@@ -1268,29 +1268,35 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
when(repository.queryBusinessRecords(eq(101L), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(1L), eq(20L)))
.thenReturn(page(List.of(
record("outbox-sandbox-audit", "event", "event-audit-1", 101L, new Date(10_000),
Map.of(
"entity_type", "event",
"category", "sandbox_audit",
"kind", "sandbox_command_observed",
"status", "warn",
"level", "warn",
"title", "Sandbox 命令观察",
"operation", "shell_exec",
"summary", "命令参数已脱敏"
Map.ofEntries(
Map.entry("entity_type", "event"),
Map.entry("category", "sandbox_audit"),
Map.entry("kind", "sandbox_command_observed"),
Map.entry("status", "warn"),
Map.entry("level", "warn"),
Map.entry("title", "Sandbox 命令观察"),
Map.entry("operation", "shell_exec"),
Map.entry("summary", "命令参数已脱敏"),
Map.entry("audit_archive_id", "archive-1"),
Map.entry("archive_status", "archived"),
Map.entry("archive_location", "admin://audit-archive/archive-1")
),
Map.of("id", "event-audit-1", "kind", "sandbox_command_observed")),
record("outbox-token-cost", "event", "event-audit-2", 101L, new Date(11_000),
Map.of(
"entity_type", "event",
"category", "token_cost",
"kind", "token_cost_recorded",
"status", "recorded",
"title", "Token 成本估算",
"model", "gpt-4.1",
"input_tokens", 120,
"output_tokens", 60,
"total_tokens", 180,
"estimated_cost_usd", 0.012
Map.ofEntries(
Map.entry("entity_type", "event"),
Map.entry("category", "token_cost"),
Map.entry("kind", "token_cost_recorded"),
Map.entry("status", "recorded"),
Map.entry("title", "Token 成本估算"),
Map.entry("model", "gpt-4.1"),
Map.entry("input_tokens", 120),
Map.entry("output_tokens", 60),
Map.entry("total_tokens", 180),
Map.entry("estimated_cost_usd", 0.012),
Map.entry("billing_estimate_id", "billing-estimate-1"),
Map.entry("billing_source", "runtime_token_cost"),
Map.entry("estimated", true)
),
Map.of("id", "event-audit-2", "kind", "token_cost_recorded")),
record("outbox-tool-audit", "event", "event-audit-3", 101L, new Date(12_000),
@@ -1351,8 +1357,14 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
.containsExactly("sandbox_audit", "token_cost", "tool_call_audit", "sync_failure", "governance");
assertThat(result.getRecords().get(0).getLevel()).isEqualTo("warn");
assertThat(result.getRecords().get(0).getSummary()).isEqualTo("命令参数已脱敏");
assertThat(result.getRecords().get(0).getAuditArchiveId()).isEqualTo("archive-1");
assertThat(result.getRecords().get(0).getArchiveStatus()).isEqualTo("archived");
assertThat(result.getRecords().get(0).getArchiveLocation()).isEqualTo("admin://audit-archive/archive-1");
assertThat(result.getRecords().get(1).getBusinessView()).containsEntry("total_tokens", 180);
assertThat(result.getRecords().get(1).getBusinessView()).containsEntry("estimated_cost_usd", 0.012);
assertThat(result.getRecords().get(1).getBillingEstimateId()).isEqualTo("billing-estimate-1");
assertThat(result.getRecords().get(1).getBillingSource()).isEqualTo("runtime_token_cost");
assertThat(result.getRecords().get(1).getEstimated()).isTrue();
assertThat(result.getRecords().get(2).getBusinessView()).containsEntry("tool_name", "shell");
assertThat(result.getRecords().get(3).getSummary()).isEqualTo("remote_timeout");
assertThat(result.getRecords().get(4).getBusinessView()).containsEntry("command_id", "command-1");