WHMSLIVE 部署验证企微HR主数据镜像

这个提交包含在:
2026-05-18 20:10:00 +08:00
父节点 27968fba49
当前提交 e10b1cd091
共修改 14 个文件,包含 258 行新增和 67 行删除
@@ -300,6 +300,10 @@ function hrTokenCandidates(config) {
];
}
function canFallbackToAgentSecret(error) {
return error instanceof WecomHrMasterSyncError && error.code === "wecom_errcode_48009";
}
function normalizeDepartmentMap(payload) {
const map = new Map();
const departments = Array.isArray(payload?.department) ? payload.department : [];
@@ -419,6 +423,78 @@ function normalizeWecomHrProfile({ contact = {}, staff = {}, departmentMap = new
return profile;
}
async function fetchContactProfilesInput({ config, token, userids, limit, fetchImpl, timeoutMs }) {
const departmentMap = await fetchDepartmentMap({
accessToken: token.accessToken,
fetchImpl,
timeoutMs,
});
const departmentId = toSafeString(config.wecomContactDefaultDepartmentId, 32) || "1";
const contacts = userids.length
? await Promise.all(userids.map((userid) => fetchContactMember({
accessToken: token.accessToken,
userid,
fetchImpl,
timeoutMs,
})))
: await listContactMembers({
accessToken: token.accessToken,
departmentId,
limit,
fetchImpl,
timeoutMs,
});
return { departmentMap, contacts, tokenSource: token.source };
}
async function fetchContactProfilesInputWithFallback({ config, contactToken, userids, limit, fetchImpl, timeoutMs }) {
try {
return await fetchContactProfilesInput({
config,
token: contactToken,
userids,
limit,
fetchImpl,
timeoutMs,
});
} catch (error) {
if (!canFallbackToAgentSecret(error) || contactToken.source === "WECOM_AGENT_SECRET_FALLBACK") {
throw error;
}
const fallback = await getTokenFromCandidates({
config,
candidates: [{ source: "WECOM_AGENT_SECRET_FALLBACK", secret: config?.wecomAgentSecret }],
timeoutMs,
fetchImpl,
});
if (!fallback.ok) {
throw error;
}
try {
return await fetchContactProfilesInput({
config,
token: fallback,
userids,
limit,
fetchImpl,
timeoutMs,
});
} catch (fallbackError) {
if (canFallbackToAgentSecret(fallbackError)) {
fallbackError.details = {
...(fallbackError.details ?? {}),
firstTokenSource: contactToken.source,
fallbackTokenSource: fallback.source,
};
}
throw fallbackError;
}
}
}
async function fetchWecomHrProfiles({ config, userids, limit, fetchImpl = fetch }) {
const timeoutMs = config.wecomRequestTimeoutMs ?? 10000;
const contactToken = await getTokenFromCandidates({
@@ -441,29 +517,17 @@ async function fetchWecomHrProfiles({ config, userids, limit, fetchImpl = fetch
throw new WecomHrMasterSyncError(hrToken.code, hrToken.message, { missing: hrToken.missing });
}
const departmentMap = await fetchDepartmentMap({
accessToken: contactToken.accessToken,
const contactInput = await fetchContactProfilesInputWithFallback({
config,
contactToken,
userids,
limit,
fetchImpl,
timeoutMs,
});
const departmentId = toSafeString(config.wecomContactDefaultDepartmentId, 32) || "1";
const contacts = userids.length
? await Promise.all(userids.map((userid) => fetchContactMember({
accessToken: contactToken.accessToken,
userid,
fetchImpl,
timeoutMs,
})))
: await listContactMembers({
accessToken: contactToken.accessToken,
departmentId,
limit,
fetchImpl,
timeoutMs,
});
const profiles = [];
for (const contact of contacts) {
for (const contact of contactInput.contacts) {
const userid = toSafeString(contact.userid, 128);
if (!userid) continue;
const staff = await fetchHrStaffInfo({
@@ -472,13 +536,13 @@ async function fetchWecomHrProfiles({ config, userids, limit, fetchImpl = fetch
fetchImpl,
timeoutMs,
});
profiles.push(normalizeWecomHrProfile({ contact, staff, departmentMap }));
profiles.push(normalizeWecomHrProfile({ contact, staff, departmentMap: contactInput.departmentMap }));
}
return {
profiles,
tokenSource: {
contact: contactToken.source,
contact: contactInput.tokenSource,
hr: hrToken.source,
},
};