OSMOKE1 修复 OA-only smoke 账号治理
这个提交包含在:
@@ -23,6 +23,8 @@ Options:
|
||||
--dry-run 只生成计划,不写数据库,默认。
|
||||
--apply 执行受控 OA 写入,需 WOUA_FIX_APPLY=1。
|
||||
--allow-employee-no=<no[,no]> 限定允许处理的员工号;可重复。
|
||||
--oa-only-smoke-employee-no=<no[,no]>
|
||||
明确标记 OA-only smoke 员工号;这些员工缺企微账号时不归档。
|
||||
--clear-inactive-bindings 显式清理 inactiveWithBinding 中的绑定;默认不清理。
|
||||
--repair-manager-effects 将归档测试主管的 active 下属和 pending 待办转给 fallback active manager。
|
||||
--manager-fallback-employee-no=<no>
|
||||
@@ -45,6 +47,7 @@ function parseArgs(argv) {
|
||||
reportDir: process.env.WOUA_FIX_REPORT_DIR
|
||||
|| path.join(DEFAULT_REPORT_ROOT, `wecom-oa-user-consistency-fix-${timestamp()}`),
|
||||
allowEmployeeNos: [],
|
||||
oaOnlySmokeEmployeeNos: splitList(process.env.OA_ONLY_SMOKE_EMPLOYEE_NOS || ""),
|
||||
clearInactiveBindings: false,
|
||||
repairManagerEffects: false,
|
||||
managerFallbackEmployeeNo: "",
|
||||
@@ -79,6 +82,11 @@ function parseArgs(argv) {
|
||||
index += 1;
|
||||
} else if (arg.startsWith("--allow-employee-no=")) {
|
||||
options.allowEmployeeNos.push(...splitList(arg.slice("--allow-employee-no=".length)));
|
||||
} else if (arg === "--oa-only-smoke-employee-no") {
|
||||
options.oaOnlySmokeEmployeeNos.push(...splitList(argv[index + 1] || ""));
|
||||
index += 1;
|
||||
} else if (arg.startsWith("--oa-only-smoke-employee-no=")) {
|
||||
options.oaOnlySmokeEmployeeNos.push(...splitList(arg.slice("--oa-only-smoke-employee-no=".length)));
|
||||
} else if (arg === "--clear-inactive-bindings") {
|
||||
options.clearInactiveBindings = true;
|
||||
} else if (arg === "--repair-manager-effects") {
|
||||
@@ -97,6 +105,7 @@ function parseArgs(argv) {
|
||||
throw new Error(`Unsupported --format: ${options.format}`);
|
||||
}
|
||||
options.allowEmployeeNos = normalizeEmployeeNoList(options.allowEmployeeNos);
|
||||
options.oaOnlySmokeEmployeeNos = normalizeEmployeeNoList(options.oaOnlySmokeEmployeeNos);
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -170,18 +179,40 @@ function buildAcceptedMissingRequiredFields(items) {
|
||||
function buildFixPlan(report, options = {}) {
|
||||
const findings = report?.findings ?? {};
|
||||
const allowSet = new Set(normalizeEmployeeNoList(options.allowEmployeeNos));
|
||||
const oaOnlySmokeSet = new Set(normalizeEmployeeNoList(options.oaOnlySmokeEmployeeNos));
|
||||
const shouldInclude = (item) => !allowSet.size || allowSet.has(item.employeeNo);
|
||||
const archiveCandidates = buildEmployeeNoActions(
|
||||
const archiveSource = buildEmployeeNoActions(
|
||||
findings.oaActiveMissingInWecom,
|
||||
"archive_oa_test_employee",
|
||||
"user_confirmed_oa_active_missing_in_wecom_are_test_data",
|
||||
).filter(shouldInclude);
|
||||
);
|
||||
const oaOnlySmokeExempted = [
|
||||
...buildEmployeeNoActions(
|
||||
findings.oaOnlySmokeExempted,
|
||||
"oa_only_smoke_exempted",
|
||||
"source_report_classified_oa_only_smoke",
|
||||
),
|
||||
...archiveSource
|
||||
.filter((item) => oaOnlySmokeSet.has(item.employeeNo))
|
||||
.map((item) => ({
|
||||
employeeNo: item.employeeNo,
|
||||
action: "oa_only_smoke_exempted",
|
||||
reason: "explicit_oa_only_smoke_employee_no",
|
||||
})),
|
||||
];
|
||||
const exemptSet = new Set(oaOnlySmokeExempted.map((item) => item.employeeNo));
|
||||
const archiveCandidates = archiveSource
|
||||
.filter((item) => !exemptSet.has(item.employeeNo))
|
||||
.filter(shouldInclude);
|
||||
const excludedByAllowlist = allowSet.size
|
||||
? buildEmployeeNoActions(
|
||||
findings.oaActiveMissingInWecom,
|
||||
"excluded_by_allowlist",
|
||||
"allowlist_did_not_include_employee_no",
|
||||
).filter((item) => !allowSet.has(item.employeeNo))
|
||||
? archiveSource
|
||||
.filter((item) => !exemptSet.has(item.employeeNo))
|
||||
.map((item) => ({
|
||||
employeeNo: item.employeeNo,
|
||||
action: "excluded_by_allowlist",
|
||||
reason: "allowlist_did_not_include_employee_no",
|
||||
}))
|
||||
.filter((item) => !allowSet.has(item.employeeNo))
|
||||
: [];
|
||||
|
||||
const inactiveBindingAction = options.clearInactiveBindings
|
||||
@@ -194,12 +225,14 @@ function buildFixPlan(report, options = {}) {
|
||||
sourceGeneratedAt: report?.generatedAt ?? null,
|
||||
decisions: {
|
||||
oaActiveMissingInWecom: "archive_oa_test_employees",
|
||||
oaOnlySmokeMissingInWecom: "exempt_no_archive",
|
||||
missingRequiredFields: "accepted_no_write",
|
||||
inactiveWithBinding: inactiveBindingAction,
|
||||
managerSideEffects: options.repairManagerEffects ? "repair_to_active_manager" : "report_only",
|
||||
wecomWriteBehavior: "no_wecom_writes",
|
||||
},
|
||||
archiveOaTestEmployees: archiveCandidates,
|
||||
oaOnlySmokeExempted,
|
||||
excludedByAllowlist,
|
||||
acceptedMissingRequiredFields: buildAcceptedMissingRequiredFields(findings.missingRequiredFields),
|
||||
inactiveWithBinding: buildEmployeeNoActions(
|
||||
@@ -234,6 +267,7 @@ function buildDryRunResult(plan, options = {}) {
|
||||
decisions: plan.decisions,
|
||||
totals: {
|
||||
archiveOaTestEmployees: plan.archiveOaTestEmployees.length,
|
||||
oaOnlySmokeExempted: plan.oaOnlySmokeExempted.length,
|
||||
excludedByAllowlist: plan.excludedByAllowlist.length,
|
||||
acceptedMissingRequiredFields: plan.acceptedMissingRequiredFields.length,
|
||||
inactiveWithBinding: plan.inactiveWithBinding.length,
|
||||
@@ -243,6 +277,7 @@ function buildDryRunResult(plan, options = {}) {
|
||||
},
|
||||
actions: {
|
||||
archiveOaTestEmployees: sample(plan.archiveOaTestEmployees),
|
||||
oaOnlySmokeExempted: sample(plan.oaOnlySmokeExempted),
|
||||
excludedByAllowlist: sample(plan.excludedByAllowlist),
|
||||
acceptedMissingRequiredFields: sample(plan.acceptedMissingRequiredFields),
|
||||
inactiveWithBinding: sample(plan.inactiveWithBinding),
|
||||
@@ -610,6 +645,7 @@ function buildDatabaseResult({ plan, archived, inactiveBindings, managerRepairs
|
||||
decisions: plan.decisions,
|
||||
totals: {
|
||||
archiveOaTestEmployees: archived.length,
|
||||
oaOnlySmokeExempted: plan.oaOnlySmokeExempted.length,
|
||||
archivedApplied: countByResult(archived, "applied"),
|
||||
archivedPlanned: countByResult(archived, "planned"),
|
||||
archivedNoop: countByResult(archived, "noop"),
|
||||
@@ -629,6 +665,7 @@ function buildDatabaseResult({ plan, archived, inactiveBindings, managerRepairs
|
||||
},
|
||||
actions: {
|
||||
archiveOaTestEmployees: sample(archived),
|
||||
oaOnlySmokeExempted: sample(plan.oaOnlySmokeExempted),
|
||||
excludedByAllowlist: sample(plan.excludedByAllowlist),
|
||||
acceptedMissingRequiredFields: sample(plan.acceptedMissingRequiredFields),
|
||||
inactiveWithBinding: sample(inactiveBindings),
|
||||
|
||||
在新工单中引用
屏蔽一个用户