离职联动去掉30天缓冲与日期暂缓,花名册标记离职即托管归档
This commit is contained in:
parent
97bcfcf5c9
commit
5ef8e77eeb
@ -154,8 +154,8 @@ scgi_temp_path <proxy_dir>/tmp/scgi;
|
||||
|
||||
上游标记离职后自动执行:归档素材库账号 + 把素材托管给所在部门。
|
||||
|
||||
- **默认只处理离职满 30 天者**(`RESIGNATION_MIN_DAYS`),避开交接期、返聘与上游数据延迟
|
||||
- 离职日期缺失者暂缓,交人工核实
|
||||
- 人事已确认花名册标记离职即为事实离职:**离职即托管+归档,无天数缓冲**(`RESIGNATION_MIN_DAYS` 已废弃)
|
||||
- 离职日期缺失者同样处理(日期仅作展示,不作门槛)
|
||||
- 超级管理员账号不由自动流程处理
|
||||
|
||||
### 素材归属与署名分离
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
* (employmentState 非 RESIGNED)时,账号应自动激活,无需管理员手动激活。
|
||||
* 2. 自动角色:花名册 M 级(levelType='M')或负责人(isLeadership)→ 管理层角色;
|
||||
* P 级 → 普通用户。角色由花名册数据派生,不靠人工设置。
|
||||
* 3. 离职自动归档:已在 organization-sync.applyResignationEffects 处理(离职满 30 天)。
|
||||
* 3. 离职自动归档:已在 organization-sync.applyResignationEffects 处理(离职即处理,无天数缓冲)。
|
||||
*
|
||||
* 供登录链路(凭证登录 / 钉钉登录)与同步链路复用。
|
||||
*/
|
||||
|
||||
@ -441,8 +441,6 @@ export interface ResignationEffectResult {
|
||||
candidates: number
|
||||
/** 满足处理条件、实际纳入本次联动的人数 */
|
||||
pending: number
|
||||
/** 因离职时间不足或日期缺失而暂缓的人数 */
|
||||
deferred: number
|
||||
archivedAccounts: number
|
||||
custodiedMaterials: number
|
||||
details: Array<{
|
||||
@ -452,7 +450,6 @@ export interface ResignationEffectResult {
|
||||
materials: number
|
||||
resignedAt: Date | null
|
||||
}>
|
||||
deferredDetails: Array<{ displayName: string; reason: string }>
|
||||
failures: Array<{ username: string; reason: string }>
|
||||
dryRun: boolean
|
||||
}
|
||||
@ -467,13 +464,13 @@ export interface ResignationEffectResult {
|
||||
*
|
||||
* 仅处理已通过钉钉唯一值建立正式绑定的账号,不按姓名猜测。
|
||||
*
|
||||
* `minDaysSinceResignation` 用于避开交接期、返聘与上游数据延迟:只处理离职已满
|
||||
* 指定天数的人;离职日期缺失者一并暂缓,交人工核实,不做推断。
|
||||
* 人事已确认:花名册标记离职即为事实离职,因此离职即托管+归档,
|
||||
* 不再设天数缓冲;离职日期缺失者同样处理(日期仅作展示,不作门槛)。
|
||||
*/
|
||||
export async function applyResignationEffects(
|
||||
options: { dryRun?: boolean; minDaysSinceResignation?: number } = {},
|
||||
options: { dryRun?: boolean } = {},
|
||||
): Promise<ResignationEffectResult> {
|
||||
const { dryRun = false, minDaysSinceResignation } = options
|
||||
const { dryRun = false } = options
|
||||
|
||||
// 通过正式绑定关系找出"人已离职、账号还活着"的情况
|
||||
const bindings = await prisma.userEmployeeBinding.findMany({
|
||||
@ -492,41 +489,18 @@ export async function applyResignationEffects(
|
||||
const result: ResignationEffectResult = {
|
||||
candidates: bindings.length,
|
||||
pending: 0,
|
||||
deferred: 0,
|
||||
archivedAccounts: 0,
|
||||
custodiedMaterials: 0,
|
||||
details: [],
|
||||
deferredDetails: [],
|
||||
failures: [],
|
||||
dryRun,
|
||||
}
|
||||
|
||||
const cutoff =
|
||||
typeof minDaysSinceResignation === 'number'
|
||||
? new Date(Date.now() - minDaysSinceResignation * 24 * 60 * 60 * 1000)
|
||||
: null
|
||||
|
||||
for (const binding of bindings) {
|
||||
const username = binding.user.username
|
||||
const displayName = binding.employeeProfile.displayName
|
||||
const resignedAt = binding.employeeProfile.resignedAt
|
||||
|
||||
if (cutoff) {
|
||||
if (!resignedAt) {
|
||||
result.deferred += 1
|
||||
result.deferredDetails.push({ displayName, reason: '离职日期缺失,需人工核实' })
|
||||
continue
|
||||
}
|
||||
if (resignedAt > cutoff) {
|
||||
result.deferred += 1
|
||||
result.deferredDetails.push({
|
||||
displayName,
|
||||
reason: '离职未满 ' + minDaysSinceResignation + ' 天(' + resignedAt.toLocaleDateString('zh-CN') + ')',
|
||||
})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const materialCount = await prisma.material.count({
|
||||
where: { userId: binding.userId, deletedAt: null },
|
||||
})
|
||||
@ -604,7 +578,6 @@ export function ensureDailyOrganizationSyncStarted() {
|
||||
}
|
||||
|
||||
const syncHour = Math.min(23, Math.max(0, Number(process.env.ORGANIZATION_SYNC_HOUR || 2)))
|
||||
const minDays = Math.max(0, Number(process.env.RESIGNATION_MIN_DAYS || 30))
|
||||
|
||||
const runOnce = async () => {
|
||||
try {
|
||||
@ -628,10 +601,10 @@ export function ensureDailyOrganizationSyncStarted() {
|
||||
}
|
||||
|
||||
try {
|
||||
const effect = await applyResignationEffects({ minDaysSinceResignation: minDays })
|
||||
const effect = await applyResignationEffects()
|
||||
if (effect.archivedAccounts > 0 || effect.custodiedMaterials > 0) {
|
||||
console.info(
|
||||
`[organization-sync] 离职联动:归档 ${effect.archivedAccounts} 个账号,托管 ${effect.custodiedMaterials} 条素材,暂缓 ${effect.deferred} 人`,
|
||||
`[organization-sync] 离职联动:归档 ${effect.archivedAccounts} 个账号,托管 ${effect.custodiedMaterials} 条素材`,
|
||||
)
|
||||
}
|
||||
if (effect.failures.length > 0) {
|
||||
|
||||
@ -63,13 +63,10 @@ async function main() {
|
||||
console.log(' └ 状态未知 ' + r.markedUnknown)
|
||||
|
||||
console.log('\n===== 三、离职联动 =====')
|
||||
// 只处理离职已满 30 天的人:避开交接期、返聘与上游数据延迟;
|
||||
// 离职日期缺失者一并暂缓,交人工核实
|
||||
const MIN_DAYS = Number(process.env.RESIGNATION_MIN_DAYS || 30)
|
||||
const e = await applyResignationEffects({ dryRun: !apply, minDaysSinceResignation: MIN_DAYS })
|
||||
// 人事确认:花名册标记离职即为事实离职,立即托管+归档,无天数缓冲
|
||||
const e = await applyResignationEffects({ dryRun: !apply })
|
||||
console.log(' 人已离职、账号仍活跃 ' + e.candidates + ' 人')
|
||||
console.log(' ├ 本次纳入处理 ' + e.pending + ' 人(离职已满 ' + MIN_DAYS + ' 天)')
|
||||
console.log(' └ 暂缓 ' + e.deferred + ' 人')
|
||||
console.log(' └ 本次纳入处理 ' + e.pending + ' 人')
|
||||
if (apply) {
|
||||
console.log('\n 已归档账号 ' + e.archivedAccounts)
|
||||
console.log(' 已托管素材 ' + e.custodiedMaterials + ' 条')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user