fix(client): sync digital approval decisions

This commit is contained in:
baiyanyun
2026-06-07 17:52:20 +08:00
parent b07f133ed6
commit aee8af0877
3 changed files with 126 additions and 4 deletions

View File

@@ -75,6 +75,66 @@ describe("digital employee state service", () => {
status: "pending",
});
});
it("updates formal approval records when UI approval decisions are saved", async () => {
const { saveDigitalEmployeeUiState } = await import("./stateService");
mockState.db?.approvals.set("approval-1", {
id: "approval-1",
plan_id: "plan-1",
task_id: "task-1",
run_id: "run-1",
title: "确认发送日报给管理端",
status: "pending",
payload: JSON.stringify({ source: "test" }),
sync_status: "synced",
created_at: "2026-06-07T07:00:00.000Z",
updated_at: "2026-06-07T07:00:00.000Z",
});
saveDigitalEmployeeUiState({
action: "decide_approval",
date: "2026-06-07",
metadata: {
decision_id: "approval-1",
decision: "approved",
},
state: {
selectedDutyIdsByDate: {},
confirmedDates: {},
reportScheduleTime: "18:00",
reportGeneratedAtByDate: {},
decisionResultsByDate: {
"2026-06-07": {
"approval-1": "approved",
},
},
profile: {
name: "飞天数字员工",
company: "qimingclaw 客户端",
position: "客户端任务执行员",
currentStatus: "working",
},
},
});
expect(mockState.db?.approvals.get("approval-1")).toMatchObject({
id: "approval-1",
status: "approved",
sync_status: "pending",
updated_at: "2026-06-07T08:00:00.000Z",
});
expect(JSON.parse(mockState.db?.approvals.get("approval-1")?.payload ?? "{}")).toMatchObject({
source: "test",
decision: "approved",
decidedAt: "2026-06-07T08:00:00.000Z",
previousStatus: "pending",
});
expect(mockState.db?.outbox.get("approval:upsert:approval-1")).toMatchObject({
entity_type: "approval",
entity_id: "approval-1",
status: "pending",
});
});
});
interface TestArtifactRow {
@@ -133,11 +193,18 @@ class TestDb {
const normalized = sql.replace(/\s+/g, " ").trim();
return {
all: () => [],
get: () => ({ count: 0 }),
get: (...args: unknown[]) => this.get(normalized, args),
run: (...args: unknown[]) => this.run(normalized, args),
};
}
private get(sql: string, args: unknown[]): unknown {
if (sql.startsWith("SELECT id, plan_id, task_id, run_id, title, status, payload, created_at FROM digital_approvals")) {
return this.approvals.get(args[0] as string);
}
return { count: 0 };
}
private run(sql: string, args: unknown[]): unknown {
if (sql.startsWith("INSERT INTO digital_plans")) return { changes: 1 };
if (sql.startsWith("INSERT INTO digital_tasks")) return { changes: 1 };
@@ -184,6 +251,7 @@ class TestDb {
string,
string,
];
const previous = this.approvals.get(id);
this.approvals.set(id, {
id,
plan_id: planId,
@@ -192,8 +260,8 @@ class TestDb {
title,
status,
payload,
sync_status: "pending",
created_at: createdAt,
sync_status: previous?.sync_status === "synced" ? "pending" : previous?.sync_status ?? "pending",
created_at: previous?.created_at ?? createdAt,
updated_at: updatedAt,
});
return { changes: 1 };