fix: isolate ERP queues and force deletion by account

This commit is contained in:
inman committed 2026-09-03 09:45:44 +08:00
1 parent 69ea6d2517
commit d09b3032c0
9 files changed
+677 -97

No files matched your search

+20 -7
View File
@@ -1231,8 +1231,8 @@ test('operator page has a login gate and uses the durable task API', async () =>
const inpage = await readFile(new URL('../../chrome-extension/ltjt-order-assistant/inpage.js', import.meta.url), 'utf8');
assert.match(index, /id="loginPanel"/);
assert.match(index, /id="workbench"[^>]*hidden/);
assert.match(index, /styles\.css\?v=20260902-account-authorization-layout-1/);
assert.match(index, /app\.js\?v=20260902-account-authorization-layout-1/);
assert.match(index, /styles\.css\?v=20260902-account-routing-hard-delete-2/);
assert.match(index, /app\.js\?v=20260902-account-routing-hard-delete-2/);
assert.match(index, /id="statusDetailsPopover"/);
assert.match(index, /id="statusDetailsRefresh"/);
assert.match(app, /apiRequest\(`\/api\/tasks\?\$\{params\.toString\(\)\}`/);
@@ -1242,6 +1242,7 @@ test('operator page has a login gate and uses the durable task API', async () =>
assert.match(app, /historyPagination/);
assert.match(index, /id="historyBatchActions"/);
assert.match(index, /id="historySelectAll"/);
assert.match(index, /id="historyArchiveSelectedButton"/);
assert.match(index, /id="historyDeleteSelectedButton"/);
assert.match(app, /IS_HISTORY_PAGE = CURRENT_PAGE === '\/history'/);
assert.match(index, /href="\/history"/);
@@ -1392,28 +1393,39 @@ test('operator page has a login gate and uses the durable task API', async () =>
assert.match(app, /operation_contract_validation/);
assert.match(app, /api\/tasks\/\$\{encodeURIComponent\(taskId\)\}\/archive/);
assert.match(app, /api\/tasks\/\$\{encodeURIComponent\(taskId\)\}\/restore/);
assert.match(app, /const taskArchiveStates = new Map\(\)/);
assert.match(app, /const taskDeleteStates = new Map\(\)/);
assert.match(app, /taskDeleteStates\.get\(task\.task_id\)/);
assert.match(app, /taskDeleteStates\.set\(taskId, 'deleting'\)/);
assert.match(app, /deleteButton\.textContent = task\?\.archived_at \? '恢复中…' : '归档中…'/);
assert.doesNotMatch(app, /sendToExtension\('DELETE_TASK'/);
assert.match(app, /deleteButton\.textContent = '强制删除中…'/);
assert.match(app, /sendToExtension\('DELETE_TASK'/);
assert.match(app, /method: 'DELETE'/);
assert.match(app, /此操作不受“正在处理”或“等待 ERP 执行”状态限制/);
assert.match(taskService, /async archiveTask\(/);
assert.match(taskService, /async archiveTasks\(/);
assert.match(taskService, /async restoreTask\(/);
assert.match(taskService, /async hardDeleteTask\(/);
assert.match(taskService, /async hardDeleteTasks\(/);
assert.match(taskService, /archived_at = now\(\), archived_by = \$1/);
assert.match(taskService, /SET archived_at = NULL, archived_by = NULL, archive_reason = NULL/);
assert.match(taskService, /const missingTaskIds = normalizedTaskIds\.filter/);
assert.doesNotMatch(taskService, /async hardDeleteTask\(/);
assert.match(taskService, /task\.hard_deleted/);
assert.match(taskService, /this\.artifactStore\.cleanup\(outcome\.artifacts\)/);
assert.doesNotMatch(taskService, /DELETE FROM audit_events/);
assert.doesNotMatch(taskService, /DELETE FROM tasks/);
assert.match(taskService, /DELETE FROM tasks/);
assert.match(taskService, /erp-account-queue/);
assert.match(taskService, /t\.assigned_user_id = \$2/);
assert.match(taskService, /AND assigned_user_id = \$2\s+AND status = 'confirmed'/);
assert.match(server, /taskBulkDeleteSchema/);
assert.match(server, /taskBulkArchiveSchema/);
assert.match(server, /\.max\(100\)/);
assert.match(server, /app\.post\('\/api\/tasks\/bulk-delete'/);
assert.match(server, /app\.post\('\/api\/tasks\/bulk-archive'/);
assert.match(server, /app\.delete\('\/api\/tasks\/:taskId'/);
assert.match(server, /app\.post\('\/api\/tasks\/:taskId\/archive'/);
assert.match(server, /app\.post\('\/api\/tasks\/:taskId\/restore'/);
assert.doesNotMatch(server, /tasks\.hardDelete/);
assert.match(server, /tasks\.hardDeleteTasks/);
assert.match(server, /tasks\.hardDeleteTask/);
assert.match(bridge, /status: 'deleted'/);
assert.match(background, /LTJT_HARD_DELETE_TASK/);
assert.doesNotMatch(app, /task-json-output|taskResponseJson/);
@@ -1428,6 +1440,7 @@ test('operator page has a login gate and uses the durable task API', async () =>
assert.match(styles, /\.task-stage-card \{[\s\S]*display: flex;[\s\S]*justify-content: space-between;/);
assert.match(styles, /\.workbench-grid \{[\s\S]*min-width: 0;[\s\S]*overflow: hidden;/);
assert.match(styles, /overflow-x: hidden/);
assert.match(styles, /\.task-card-actions/);
assert.match(styles, /\.task-card-delete/);
assert.match(styles, /\.history-batch-actions/);
assert.match(app, /currentOption = stage\.options\.find/);