From f6eba0418f328abb75c8081d9c05787e6b36e0dd Mon Sep 17 00:00:00 2001 From: WuYongJie Date: Thu, 28 May 2026 12:01:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(users):=20=E6=8E=92=E9=99=A4=E9=9D=9E?= =?UTF-8?q?=E5=86=85=E9=83=A8=E9=83=A8=E9=97=A8=E8=87=AA=E5=8A=A8=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=88=92=E5=BD=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/lib/business-role-inference.test.ts | 49 ++++++++++++ .../src/lib/business-role-inference.ts | 75 +++++-------------- .../__tests__/primary-department.test.ts | 27 +++++++ .../src/lib/hr-sync/primary-department.ts | 13 ++-- 4 files changed, 103 insertions(+), 61 deletions(-) create mode 100644 furniture-3d-system/src/lib/business-role-inference.test.ts diff --git a/furniture-3d-system/src/lib/business-role-inference.test.ts b/furniture-3d-system/src/lib/business-role-inference.test.ts new file mode 100644 index 00000000..5649c298 --- /dev/null +++ b/furniture-3d-system/src/lib/business-role-inference.test.ts @@ -0,0 +1,49 @@ +import { inferBusinessRolesFromDepartmentPath } from './business-role-inference' + +describe('business-role-inference', () => { + it('业务支持、快递、供应商、龙晨品牌中心不自动划归内部业务类型', () => { + const paths = [ + '江苏简尚品牌管理有限公司 > 业务支持 > 外协支持', + '江苏简尚品牌管理有限公司 > 快递 > 华东快递', + '江苏简尚品牌管理有限公司 > 快递公司 > 常州快递', + '江苏简尚品牌管理有限公司 > 供应商 > 常州区域 > 常州十四区', + '江苏简尚品牌管理有限公司 > 龙晨品牌中心 > 供应链中心(江苏简尚品牌管理有限公司 > 龙晨品牌中心)', + '江苏简尚品牌管理有限公司 > 龙晨品牌中心 > 营销策划中心', + ] + + paths.forEach((path) => { + expect(inferBusinessRolesFromDepartmentPath(path)).toMatchObject({ + businessRoles: [], + excluded: true, + shouldWarnWhenEmpty: false, + }) + expect(inferBusinessRolesFromDepartmentPath(path).reason).toContain('不属于内部人员') + }) + }) + + it('内部业务部门继续自动划归业务类型', () => { + expect( + inferBusinessRolesFromDepartmentPath( + '江苏简尚品牌管理有限公司 > 供应链中心 > 基本盘 采购部 > 采购二部', + ).businessRoles, + ).toEqual(['PURCHASING']) + + expect( + inferBusinessRolesFromDepartmentPath( + '江苏简尚品牌管理有限公司 > 产品研发部 > 基本盘 > 桌类组', + ).businessRoles, + ).toEqual(['DESIGN']) + + expect( + inferBusinessRolesFromDepartmentPath( + '江苏简尚品牌管理有限公司 > 品牌中心 > 空间视觉部', + ).businessRoles, + ).toEqual(['DESIGN']) + + expect( + inferBusinessRolesFromDepartmentPath( + '江苏简尚品牌管理有限公司 > 品牌中心 > 商品企划部', + ).businessRoles, + ).toEqual(['PLANNING']) + }) +}) diff --git a/furniture-3d-system/src/lib/business-role-inference.ts b/furniture-3d-system/src/lib/business-role-inference.ts index 1a99ebbb..d2be6911 100644 --- a/furniture-3d-system/src/lib/business-role-inference.ts +++ b/furniture-3d-system/src/lib/business-role-inference.ts @@ -15,25 +15,20 @@ const EXCLUDED_ROOTS = new Set([ '直播中心', '商务中心', '分销部', - '业务支持', '公共视觉部', '经营管理中心', '摄影中心', '广州项目组', '摄影需求', - '快递公司', '人力行政中心', '外部交流', ]) -const LONGCHEN_EXCLUDED_CHILDREN = [ - /^客服中心/, - /^财务中心/, - /^运营中心/, - /^总经理室/, - /^直播中心/, - /^商务中心/, -] +const NON_INTERNAL_ROOTS = new Set([ + '业务支持', + '供应商', + '龙晨品牌中心', +]) function splitDepartmentPath(fullPath: string | null | undefined): string[] { return String(fullPath ?? '') @@ -62,12 +57,16 @@ function uniqRoles(roles: BusinessAccountType[]): BusinessAccountType[] { return [...new Set(roles)] } +export function isNonInternalDepartmentRoot(root: string | null | undefined): boolean { + const normalizedRoot = String(root ?? '').trim() + return NON_INTERNAL_ROOTS.has(normalizedRoot) || /^快递/.test(normalizedRoot) +} + export function inferBusinessRolesFromDepartmentPath( fullPath: string | null | undefined, ): BusinessRoleInferenceResult { const parts = getBusinessParts(fullPath) const root = parts[0] ?? '' - const child = parts[1] ?? '' if (!root) { return { @@ -87,6 +86,15 @@ export function inferBusinessRolesFromDepartmentPath( } } + if (isNonInternalDepartmentRoot(root)) { + return { + businessRoles: [], + excluded: true, + shouldWarnWhenEmpty: false, + reason: `${root} 不属于内部人员,不参与业务类型`, + } + } + if (EXCLUDED_ROOTS.has(root) || /^运营中心/.test(root) || /^效率部/.test(root)) { return { businessRoles: [], @@ -96,51 +104,6 @@ export function inferBusinessRolesFromDepartmentPath( } } - if (root === '龙晨品牌中心') { - if (LONGCHEN_EXCLUDED_CHILDREN.some((pattern) => pattern.test(child))) { - return { - businessRoles: [], - excluded: true, - shouldWarnWhenEmpty: false, - reason: `龙晨品牌中心 > ${child} 不参与业务类型`, - } - } - - if (/^供应链中心/.test(child)) { - return { - businessRoles: ['PURCHASING'], - excluded: false, - shouldWarnWhenEmpty: true, - reason: '龙晨品牌中心供应链节点默认归采购', - } - } - - if (/^营销策划中心/.test(child)) { - return { - businessRoles: ['PLANNING'], - excluded: false, - shouldWarnWhenEmpty: true, - reason: '龙晨品牌中心营销策划节点默认归企划', - } - } - - return { - businessRoles: [], - excluded: false, - shouldWarnWhenEmpty: true, - reason: '龙晨品牌中心需要按内部节点确认业务类型', - } - } - - if (root === '供应商') { - return { - businessRoles: ['SUPPLIER'], - excluded: false, - shouldWarnWhenEmpty: true, - reason: '供应商节点默认归供应商', - } - } - if (root === '仓储中心') { return { businessRoles: ['WAREHOUSE'], diff --git a/furniture-3d-system/src/lib/hr-sync/__tests__/primary-department.test.ts b/furniture-3d-system/src/lib/hr-sync/__tests__/primary-department.test.ts index 66a43e06..170676cf 100644 --- a/furniture-3d-system/src/lib/hr-sync/__tests__/primary-department.test.ts +++ b/furniture-3d-system/src/lib/hr-sync/__tests__/primary-department.test.ts @@ -51,4 +51,31 @@ describe('primary-department', () => { ]), ).toBe('finance-1') }) + + it('业务支持、快递、供应商、龙晨品牌中心不会压过可确认的内部部门', () => { + expect( + choosePrimaryDepartmentExternalId(['supplier-1', 'longchen-1', 'express-1', 'business-1', 'unknown-1'], [ + { + externalId: 'supplier-1', + fullPath: '江苏简尚品牌管理有限公司 > 供应商 > 常州区域 > 常州十四区', + }, + { + externalId: 'longchen-1', + fullPath: '江苏简尚品牌管理有限公司 > 龙晨品牌中心 > 供应链中心', + }, + { + externalId: 'express-1', + fullPath: '江苏简尚品牌管理有限公司 > 快递 > 华东快递', + }, + { + externalId: 'business-1', + fullPath: '江苏简尚品牌管理有限公司 > 业务支持 > 外协支持', + }, + { + externalId: 'unknown-1', + fullPath: '江苏简尚品牌管理有限公司 > 未映射内部部门', + }, + ]), + ).toBe('unknown-1') + }) }) diff --git a/furniture-3d-system/src/lib/hr-sync/primary-department.ts b/furniture-3d-system/src/lib/hr-sync/primary-department.ts index 2ff82e57..4f3b4ef7 100644 --- a/furniture-3d-system/src/lib/hr-sync/primary-department.ts +++ b/furniture-3d-system/src/lib/hr-sync/primary-department.ts @@ -1,4 +1,7 @@ -import { inferBusinessRolesFromDepartmentPath } from '@/lib/business-role-inference' +import { + inferBusinessRolesFromDepartmentPath, + isNonInternalDepartmentRoot, +} from '@/lib/business-role-inference' export interface DepartmentPathCandidate { externalId: string @@ -49,12 +52,12 @@ function scoreDepartment(fullPath: string | null | undefined): number { const root = getBusinessRoot(fullPath) const inference = inferBusinessRolesFromDepartmentPath(fullPath) const hasInternalRole = inference.businessRoles.some((role) => role !== 'SUPPLIER') - const isSupplierRoot = root === '供应商' + const isNonInternalRoot = isNonInternalDepartmentRoot(root) if (hasInternalRole) return 500 - if (root && !isSupplierRoot && inference.excluded) return 300 - if (root && !isSupplierRoot && !inference.excluded) return 400 - if (inference.businessRoles.includes('SUPPLIER')) return 200 + if (root && !isNonInternalRoot && !inference.excluded) return 400 + if (root && !isNonInternalRoot && inference.excluded) return 300 + if (isNonInternalRoot) return 200 if (!inference.excluded) return 100 return 0 }