change
This commit is contained in:
@@ -51,11 +51,6 @@ public class Sys_user_history extends Sys_user {
|
||||
@Comment("变更原因")
|
||||
private String changeReason;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "text")
|
||||
@Comment("备注")
|
||||
private String remark;
|
||||
|
||||
@Column
|
||||
@Comment("会员变更表记录id")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
|
||||
+58
-12
@@ -22,11 +22,12 @@ import com.budwk.app.sys.services.SysUserService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingUserHistoryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -51,6 +52,10 @@ import java.util.stream.Collectors;
|
||||
@IocBean
|
||||
public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService {
|
||||
private static final int BATCH_SIZE = 500;
|
||||
/** 不需要人工确认。 */
|
||||
private static final int PENDING_CONFIRM_STATUS_NONE = 0;
|
||||
/** 数据源缺失,等待人工确认。 */
|
||||
private static final int PENDING_CONFIRM_STATUS_PENDING = 1;
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@@ -62,8 +67,6 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
private SysUserService sysUserService;
|
||||
@Inject
|
||||
private ThreadPoolTaskExecutor executorService;
|
||||
@Inject
|
||||
private PendingUserHistoryService pendingUserHistoryService;
|
||||
|
||||
|
||||
private static Map<String, String> unitIdNameMap;
|
||||
@@ -177,7 +180,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
* 全量更新已有用户时置空,避免 updateIgnoreNull 把已迁移的基金会员标识覆盖为非会员。
|
||||
*/
|
||||
u.setAidFundMember(null);
|
||||
|
||||
u.setPersonType(null);
|
||||
needDoUpdateList.add(u);
|
||||
}
|
||||
|
||||
@@ -292,12 +295,6 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
return "更新失败: " + e.getMessage();
|
||||
}
|
||||
|
||||
/*
|
||||
* 用户及普通变更记录完成后,再以本次完整源数据校正待确认人员。
|
||||
* 该步骤仅存在于 ALL 实现中,增量更新不会误判未包含在增量数据中的系统用户。
|
||||
*/
|
||||
int pendingConfirmCount = pendingUserHistoryService.reconcile(sysUsers, sources);
|
||||
|
||||
/* // 4. 异步添加会员角色 - 不等待完成
|
||||
if (Lang.isNotEmpty(addMemberUserIds)) {
|
||||
executorService.execute(() -> {
|
||||
@@ -355,14 +352,63 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
RoleEventPublisher.broadcast(new RoleEventMsg(unitId, RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name(), RoleEventMsg.RENEW_ROLE));
|
||||
}
|
||||
|
||||
/*
|
||||
* 所有异步用户更新完成后再校正待确认状态,避免主事务提前锁定 sys_user,
|
||||
* 导致异步更新线程等待主事务释放行锁而形成相互等待。
|
||||
*/
|
||||
reconcilePendingConfirmStatus(updateParam.getPullTime());
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("全量更新用户数据完成,耗时: {} 毫秒", (endTime - startTime));
|
||||
|
||||
if (needInitUserList.isEmpty() && histories.isEmpty() && pendingConfirmCount == 0) {
|
||||
if (needInitUserList.isEmpty() && histories.isEmpty()) {
|
||||
return "本次没有可更新的数据。";
|
||||
}
|
||||
return "更新完成: 新增用户 " + needInitUserList.size() + " 个, 有效变更 " + histories.size()
|
||||
+ " 条, 新增待确认人员 " + pendingConfirmCount + " 人";
|
||||
+ " 条";
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定批次的完整数据源校正系统用户待确认状态。
|
||||
* 已人工确认且仍未重新出现的人员保持已确认状态,避免每次全量更新重复转为待确认。
|
||||
*
|
||||
* @param pullTime 本次全量数据的拉取时间
|
||||
*/
|
||||
private void reconcilePendingConfirmStatus(String pullTime) {
|
||||
Sql resetStatusSql = Sqls.create("""
|
||||
UPDATE sys_user userInfo
|
||||
SET userInfo.pendingConfirmStatus = @noneStatus
|
||||
WHERE userInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
AND userInfo.pendingConfirmStatus <> @noneStatus
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_source sourceInfo
|
||||
WHERE sourceInfo.pullTime = @pullTime
|
||||
AND sourceInfo.loginname = userInfo.loginname
|
||||
AND sourceInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
)
|
||||
""");
|
||||
resetStatusSql.setParam("noneStatus", PENDING_CONFIRM_STATUS_NONE);
|
||||
resetStatusSql.setParam("pullTime", pullTime);
|
||||
dao.execute(resetStatusSql);
|
||||
|
||||
Sql pendingStatusSql = Sqls.create("""
|
||||
UPDATE sys_user userInfo
|
||||
SET userInfo.pendingConfirmStatus = @pendingStatus
|
||||
WHERE userInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
AND IFNULL(userInfo.pendingConfirmStatus, @noneStatus) = @noneStatus
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_source sourceInfo
|
||||
WHERE sourceInfo.pullTime = @pullTime
|
||||
AND sourceInfo.loginname = userInfo.loginname
|
||||
AND sourceInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
)
|
||||
""");
|
||||
pendingStatusSql.setParam("pendingStatus", PENDING_CONFIRM_STATUS_PENDING);
|
||||
pendingStatusSql.setParam("noneStatus", PENDING_CONFIRM_STATUS_NONE);
|
||||
pendingStatusSql.setParam("pullTime", pullTime);
|
||||
dao.execute(pendingStatusSql);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,6 @@ import lombok.Getter;
|
||||
public enum MemberChangeType {
|
||||
|
||||
//变更类型
|
||||
PENDING_CONFIRM("PENDING_CONFIRM", "待确认"),
|
||||
NEW("NEW", "新入职"),
|
||||
RESTORE("RESTORE", "入会"),
|
||||
WITHDRAWAL("WITHDRAWAL", "退会"),
|
||||
|
||||
+6
-1
@@ -156,7 +156,12 @@ public class MemberChangeApplyController {
|
||||
* @return
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission(value = {"member.change.branchUnion.audit","member.change.schoolUnion.audit", "member.change.unionGroup.audit"}, mode = SaMode.OR)
|
||||
@SaCheckPermission(value = {
|
||||
"member.change.branchUnion.audit",
|
||||
"member.change.schoolUnion.audit",
|
||||
"member.change.unionGroup.audit",
|
||||
"staff.sourcechange.pending"
|
||||
}, mode = SaMode.OR)
|
||||
public Result getUserByIdForMemberChange(String userId){
|
||||
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", userId));
|
||||
NutMap nutMap = Lang.obj2nutmap(user);
|
||||
|
||||
+11
-3
@@ -36,6 +36,7 @@ import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||
import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord;
|
||||
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberManagePageForm;
|
||||
import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingConfirmUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -79,6 +80,8 @@ public class MemberChangeManageController {
|
||||
private CommonService commonService;
|
||||
@Inject
|
||||
private MemberCommonService memberCommonService;
|
||||
@Inject
|
||||
private PendingConfirmUserService pendingConfirmUserService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/staffmanage/member/change/manage/index.html")
|
||||
@@ -101,7 +104,11 @@ public class MemberChangeManageController {
|
||||
@RepeatSubmit
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SLog(tag = "会员高级管理-会员变更", msg = "分工会/校工会会员管理员提交变更")
|
||||
@SaCheckPermission(value = {"member.change.mange", "staff.member.change.mange"}, mode = SaMode.OR)
|
||||
@SaCheckPermission(value = {
|
||||
"member.change.mange",
|
||||
"staff.member.change.mange",
|
||||
"staff.sourcechange.pending"
|
||||
}, mode = SaMode.OR)
|
||||
public Result doSubmitChange(MemberChangeRecord record){
|
||||
// 检验是否有变更
|
||||
if (Lang.isEmpty(record)) {
|
||||
@@ -162,6 +169,8 @@ public class MemberChangeManageController {
|
||||
if (schoolRoleBool) {
|
||||
memberCommonService.compareChangeInfoAndUpdateMember(record);
|
||||
}
|
||||
// 待确认人员完成变更提交后转为已确认;普通人员调用时不会产生状态变化。
|
||||
pendingConfirmUserService.markConfirmed(record.getUserId());
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -171,8 +180,7 @@ public class MemberChangeManageController {
|
||||
@SaCheckPermission(value = {
|
||||
"member.change.mange",
|
||||
"staff.member.change.mange",
|
||||
"staff.sourcechange.manage",
|
||||
"staff.sourcechange.pending"
|
||||
"staff.sourcechange.manage"
|
||||
}, mode = SaMode.OR)
|
||||
public Result getAllChangeMemberInfo(String userId){
|
||||
List<NutMap> mapList = memberCommonService.getAllChangeInfo(userId);
|
||||
|
||||
+3
-21
@@ -441,12 +441,8 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
||||
|
||||
MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", userId).desc("applyDateTime"));
|
||||
|
||||
/*
|
||||
* 待确认人员来自全量数据差异校正,没有常规的字段前后值 changeInfos。
|
||||
* 此处保留该人员的全部历史,再在组装时间线时仅接纳普通变更或待确认记录。
|
||||
*/
|
||||
List<Sys_user_history> historyList = dao().query(Sys_user_history.class,
|
||||
Cnd.where("loginname", "=", loginName).desc("changeTime"));
|
||||
List<Sys_user_history> historyList = dao().query(Sys_user_history.class, Cnd.where("loginname", "=", loginName)
|
||||
.and("changeInfos", "is not", null).desc("changeTime"));
|
||||
|
||||
List<String> recordList = historyList.stream().map(Sys_user_history::getRecordId).toList();
|
||||
|
||||
@@ -459,25 +455,11 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
||||
resultMapList.add(map);
|
||||
}
|
||||
for (Sys_user_history history : historyList) {
|
||||
boolean pendingConfirm = Lang.isNotEmpty(history.getChangeTypes())
|
||||
&& history.getChangeTypes().contains(MemberChangeType.PENDING_CONFIRM.name());
|
||||
if (Lang.isEmpty(history.getChangeInfos()) && !pendingConfirm) {
|
||||
continue;
|
||||
}
|
||||
NutMap map = NutMap.NEW();
|
||||
List<NutMap> changeInfos = history.getChangeInfos();
|
||||
if (pendingConfirm) {
|
||||
// 待确认记录没有人工异动表,使用差异校正原因构造可阅读的变更说明。
|
||||
changeInfos = List.of(NutMap.NEW()
|
||||
.setv("field", "pendingConfirm")
|
||||
.setv("fieldName", "人员状态")
|
||||
.setv("sourceValue", "系统用户中存在")
|
||||
.setv("newValue", StrUtil.blankToDefault(history.getChangeReason(), "本次全量人员数据中不存在")));
|
||||
}
|
||||
map.put("changeInfos", changeInfos);
|
||||
map.put("timestamp", DateUtil.format(history.getChangeTime(), "yyyy-MM-dd HH:mm:ss"));
|
||||
String changeOriginName = MemberChangeOrigin.valueOf(MemberChangeOrigin.class, history.getChangeOrigin()).changeOriginName;
|
||||
map.put("changeOriginName", pendingConfirm ? changeOriginName + "(待确认)" : changeOriginName);
|
||||
map.put("changeOriginName", MemberChangeOrigin.valueOf(MemberChangeOrigin.class, history.getChangeOrigin()).changeOriginName);
|
||||
resultMapList.add(map);
|
||||
}
|
||||
return resultMapList;
|
||||
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
package com.budwk.app.zhgh.staffmanage.sourcechange.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.param.PendingUserConfirmParam;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingUserHistoryService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 待确认人员记录页面及接口。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/sourcechange/pending")
|
||||
@Ok("json")
|
||||
@Api(tags = "待确认人员记录")
|
||||
public class PendingSourceChangeController {
|
||||
|
||||
@Inject
|
||||
private PendingUserHistoryService pendingUserHistoryService;
|
||||
|
||||
/**
|
||||
* 打开待确认人员记录页面。
|
||||
*/
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/staffmanage/sourcechange/pending/index.html")
|
||||
@SaCheckPermission("staff.sourcechange.pending")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询当前仍需人工确认的人员记录。
|
||||
*
|
||||
* @param pageForm 变更记录通用查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("分页查询待确认人员")
|
||||
@SaCheckPermission("staff.sourcechange.pending")
|
||||
public Result pageData(SourceChangePageForm pageForm) {
|
||||
return Result.success(pendingUserHistoryService.listPage(pageForm));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将待确认人员记录确认成最终异动类型。
|
||||
*
|
||||
* @param confirmParam 异动类型及备注
|
||||
* @return 处理结果
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("确认待确认人员")
|
||||
@SLog(tag = "待确认人员记录", msg = "确认人员")
|
||||
@SaCheckPermission("staff.sourcechange.pending")
|
||||
public Result confirm(@Valid @Param("data") PendingUserConfirmParam confirmParam) {
|
||||
try {
|
||||
pendingUserHistoryService.confirm(confirmParam);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.budwk.app.zhgh.staffmanage.sourcechange.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 待确认人员确认参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("待确认人员确认参数")
|
||||
public class PendingUserConfirmParam {
|
||||
|
||||
@NotBlank(message = "待确认记录不能为空")
|
||||
@ApiModelProperty("sys_user_history 记录ID")
|
||||
private String id;
|
||||
|
||||
@NotBlank(message = "请选择异动类型")
|
||||
@ApiModelProperty("最终异动类型")
|
||||
private String changeType;
|
||||
|
||||
@Size(max = 1000, message = "备注不能超过1000个字符")
|
||||
@ApiModelProperty("确认备注")
|
||||
private String remark;
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
package com.budwk.app.zhgh.staffmanage.sourcechange.service;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.models.Sys_user_source;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.param.PendingUserConfirmParam;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 待确认人员历史记录业务服务。
|
||||
*/
|
||||
public interface PendingUserHistoryService {
|
||||
|
||||
/**
|
||||
* 根据变更记录页面的查询条件分页查询待确认人员。
|
||||
*
|
||||
* @param pageForm 查询及分页参数
|
||||
* @return 待确认人员分页数据
|
||||
*/
|
||||
Pagination listPage(SourceChangePageForm pageForm);
|
||||
|
||||
/**
|
||||
* 将待确认记录更新为人工选择的最终异动类型并保存备注。
|
||||
*
|
||||
* @param confirmParam 确认参数
|
||||
*/
|
||||
void confirm(PendingUserConfirmParam confirmParam);
|
||||
|
||||
/**
|
||||
* 依据本次全量源数据校正待确认记录:缺失人员补充记录,重新出现人员删除待确认记录。
|
||||
*
|
||||
* @param systemUsers 更新开始时系统中已有的用户
|
||||
* @param sourceUsers 本次全量拉取的用户
|
||||
* @return 本次新增的待确认记录数量
|
||||
*/
|
||||
int reconcile(List<Sys_user> systemUsers, List<Sys_user_source> sourceUsers);
|
||||
}
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
package com.budwk.app.zhgh.staffmanage.sourcechange.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.models.Sys_user_history;
|
||||
import com.budwk.app.sys.models.Sys_user_source;
|
||||
import com.budwk.app.sys.services.SysUserService;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.param.PendingUserConfirmParam;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm;
|
||||
import com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingUserHistoryService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.dao.util.cri.Static;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.random.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 待确认人员历史记录业务实现。
|
||||
*/
|
||||
@IocBean
|
||||
public class PendingUserHistoryServiceImpl implements PendingUserHistoryService {
|
||||
|
||||
private static final int BATCH_SIZE = 500;
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@Inject
|
||||
private SysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* 查询待确认人员,查询字段与人员变更记录页面保持一致,但未选择日期时查询全部待确认数据。
|
||||
*/
|
||||
@Override
|
||||
public Pagination listPage(SourceChangePageForm pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
his.id,
|
||||
his.loginname,
|
||||
his.username,
|
||||
COALESCE(u.sex, his.sex) AS sex,
|
||||
COALESCE(u.unitName, his.unitName) AS unitName,
|
||||
COALESCE(u.unionName, his.unionName) AS unionName,
|
||||
his.userState,
|
||||
his.personType,
|
||||
his.preparedBy,
|
||||
his.changeTime,
|
||||
his.changeTypes,
|
||||
his.changeOrigin,
|
||||
his.remark,
|
||||
u.id AS userId
|
||||
FROM sys_user_history his
|
||||
LEFT JOIN vw_user u ON his.loginname = u.loginname
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
// 待确认页面固定限定待确认类型,避免已处理记录继续出现在列表中。
|
||||
cnd.and(new Static("JSON_CONTAINS(his.changeTypes, JSON_QUOTE('" + MemberChangeType.PENDING_CONFIRM.name() + "'), '$')"));
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup keywordGroup = new SqlExpressionGroup();
|
||||
keywordGroup.orLike("his.username", pageForm.getSearchKeyword());
|
||||
keywordGroup.orLike("his.loginname", pageForm.getSearchKeyword());
|
||||
cnd.and(keywordGroup);
|
||||
}
|
||||
cnd.andEX("u.unionId", "=", pageForm.getUnionId());
|
||||
cnd.andEX("u.unitId", "=", pageForm.getUnitId());
|
||||
cnd.andEX("u.sex", "=", pageForm.getSex());
|
||||
cnd.andEX("his.personType", "=", pageForm.getPersonType());
|
||||
cnd.andEX("his.preparedBy", "=", pageForm.getPreparedBy());
|
||||
cnd.andEX("his.userState", "=", pageForm.getUserState());
|
||||
cnd.andEX("his.changeOrigin", "=", pageForm.getChangeOrigin());
|
||||
|
||||
// 日期范围使用参数化条件,结束日期按次日零点前处理,包含所选结束日期的全部数据。
|
||||
if (StrUtil.isAllNotBlank(pageForm.getChangeDateBefore(), pageForm.getChangeDateEnd())) {
|
||||
Date startDate = DateUtil.parseDate(pageForm.getChangeDateBefore());
|
||||
Date endDateExclusive = DateUtil.offsetDay(DateUtil.parseDate(pageForm.getChangeDateEnd()), 1);
|
||||
cnd.and("his.changeTime", ">=", startDate);
|
||||
cnd.and("his.changeTime", "<", endDateExclusive);
|
||||
}
|
||||
if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||
} else {
|
||||
cnd.desc("his.changeTime");
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
return sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认待确认人员记录,异动类型只允许选择已定义且非待确认的最终类型。
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void confirm(PendingUserConfirmParam confirmParam) {
|
||||
MemberChangeType selectedType;
|
||||
try {
|
||||
selectedType = MemberChangeType.valueOf(confirmParam.getChangeType());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("异动类型不存在");
|
||||
}
|
||||
if (MemberChangeType.PENDING_CONFIRM == selectedType) {
|
||||
throw new IllegalArgumentException("请选择最终异动类型");
|
||||
}
|
||||
|
||||
// 更新条件同时校验记录仍处于待确认状态,防止重复确认覆盖已经处理的数据。
|
||||
Cnd cnd = Cnd.where("id", "=", confirmParam.getId())
|
||||
.and(new Static("JSON_CONTAINS(changeTypes, JSON_QUOTE('" + MemberChangeType.PENDING_CONFIRM.name() + "'), '$')"));
|
||||
Chain chain = Chain.make("changeTypes", Json.toJson(List.of(selectedType.name())))
|
||||
.add("remark", StrUtil.trim(confirmParam.getRemark()));
|
||||
int updated = dao.update(Sys_user_history.class, chain, cnd);
|
||||
if (updated == 0) {
|
||||
throw new IllegalStateException("待确认记录不存在或已被处理");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据本次全量源数据双向校正待确认历史:源数据重新出现则删除,源数据缺失则幂等新增。
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public int reconcile(List<Sys_user> systemUsers, List<Sys_user_source> sourceUsers) {
|
||||
Set<String> sourceLoginNames = sourceUsers.stream()
|
||||
.map(Sys_user_source::getLoginname)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
List<Sys_user_history> pendingHistories = dao.query(Sys_user_history.class, pendingCondition());
|
||||
|
||||
// 已重新出现在完整源数据中的人员不再需要人工确认,仅删除尚未处理的待确认记录。
|
||||
List<String> recoveredPendingIds = pendingHistories.stream()
|
||||
.filter(history -> sourceLoginNames.contains(history.getLoginname()))
|
||||
.map(Sys_user_history::getId)
|
||||
.toList();
|
||||
for (List<String> idBatch : ListUtil.split(recoveredPendingIds, BATCH_SIZE)) {
|
||||
dao.clear(Sys_user_history.class, Cnd.where("id", "in", idBatch));
|
||||
}
|
||||
|
||||
Set<String> existingPendingLoginNames = pendingHistories.stream()
|
||||
.filter(history -> !sourceLoginNames.contains(history.getLoginname()))
|
||||
.map(Sys_user_history::getLoginname)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
List<Sys_user_history> historiesToInsert = new ArrayList<>();
|
||||
|
||||
// 同一工号最多保留一条待确认记录,重复执行全部更新不会重复生成数据。
|
||||
for (Sys_user user : systemUsers) {
|
||||
String loginname = user.getLoginname();
|
||||
if (StrUtil.isBlank(loginname)
|
||||
|| sourceLoginNames.contains(loginname)
|
||||
|| !existingPendingLoginNames.add(loginname)) {
|
||||
continue;
|
||||
}
|
||||
Sys_user_history history = new Sys_user_history();
|
||||
BeanUtil.copyProperties(user, history);
|
||||
history.setId(R.UU32());
|
||||
history.setChangeTime(DateUtil.date());
|
||||
history.setChangeTypes(List.of(MemberChangeType.PENDING_CONFIRM.name()));
|
||||
history.setChangeOrigin(MemberChangeOrigin.SYSTEM.name());
|
||||
history.setChangeReason("全量人员数据中不存在");
|
||||
historiesToInsert.add(history);
|
||||
}
|
||||
|
||||
for (List<Sys_user_history> historyBatch : ListUtil.split(historiesToInsert, BATCH_SIZE)) {
|
||||
dao.fastInsert(historyBatch);
|
||||
}
|
||||
return historiesToInsert.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造待确认 JSON 类型条件,供查询及差异校正统一使用。
|
||||
*/
|
||||
private Cnd pendingCondition() {
|
||||
return Cnd.where(new Static("JSON_CONTAINS(changeTypes, JSON_QUOTE('" + MemberChangeType.PENDING_CONFIRM.name() + "'), '$')"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user