✨ 组织与人员支持OA增量同步,并完善用户启停与性别空值
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+8
@@ -216,4 +216,12 @@ public class Dept extends TenantEntity {
|
|||||||
@TableField(updateStrategy = FieldStrategy.NOT_NULL)
|
@TableField(updateStrategy = FieldStrategy.NOT_NULL)
|
||||||
private String oaSupSubComId;
|
private String oaSupSubComId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OA上次更新时间(OA 的 modified 字段),仅同步比对使用
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(description = "OA上次更新时间", hidden = true)
|
||||||
|
@TableField(updateStrategy = FieldStrategy.NOT_NULL)
|
||||||
|
private String oaModified;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -35,8 +35,12 @@ public enum UserSex {
|
|||||||
if (name == null || name.isEmpty()) {
|
if (name == null || name.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String sexName = name.trim();
|
||||||
|
if ("-1".equals(sexName) || "0".equals(sexName) || "未知".equals(sexName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return Stream.of(values())
|
return Stream.of(values())
|
||||||
.filter(e -> e.getName().equals(name))
|
.filter(e -> e.getName().equals(sexName) || String.valueOf(e.getCode()).equals(sexName))
|
||||||
.map(UserSex::getCode)
|
.map(UserSex::getCode)
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -66,4 +66,7 @@ public class OaOrgSyncPageVO implements Serializable {
|
|||||||
|
|
||||||
@Schema(description = "是否已到最后一页")
|
@Schema(description = "是否已到最后一页")
|
||||||
private Boolean finished;
|
private Boolean finished;
|
||||||
|
|
||||||
|
@Schema(description = "增量同步使用的 OA modified 起始时间,后续分页需原样回传")
|
||||||
|
private String modifiedSince;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -63,4 +63,7 @@ public class OaPersonSyncPageVO implements Serializable {
|
|||||||
|
|
||||||
@Schema(description = "是否已到最后一页")
|
@Schema(description = "是否已到最后一页")
|
||||||
private Boolean finished;
|
private Boolean finished;
|
||||||
|
|
||||||
|
@Schema(description = "增量同步使用的 OA modified 起始时间,后续分页需原样回传")
|
||||||
|
private String modifiedSince;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.system.pojo.entity;
|
package org.springblade.system.pojo.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -131,6 +132,11 @@ public class User extends TenantEntity implements IPhone {
|
|||||||
* 是否是oa的账号
|
* 是否是oa的账号
|
||||||
*/
|
*/
|
||||||
private Integer isOa;
|
private Integer isOa;
|
||||||
|
/**
|
||||||
|
* OA上次更新时间(OA 的 modified 字段),仅同步比对使用
|
||||||
|
*/
|
||||||
|
@TableField(updateStrategy = FieldStrategy.NOT_NULL)
|
||||||
|
private String oaModified;
|
||||||
/**
|
/**
|
||||||
* 是否推送mk
|
* 是否推送mk
|
||||||
*/
|
*/
|
||||||
|
|||||||
+12
-6
@@ -93,7 +93,8 @@ public class DeptController extends BladeController {
|
|||||||
@PreAuth(menu = "dept")
|
@PreAuth(menu = "dept")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = "deptName", description = "部门名称", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
@Parameter(name = "deptName", description = "组织名称", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
||||||
|
@Parameter(name = "shortName", description = "组织简称", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
||||||
@Parameter(name = "fullName", description = "部门全称", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
|
@Parameter(name = "fullName", description = "部门全称", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
|
||||||
})
|
})
|
||||||
@ApiOperationSupport(order = 2)
|
@ApiOperationSupport(order = 2)
|
||||||
@@ -108,7 +109,8 @@ public class DeptController extends BladeController {
|
|||||||
@PreAuth(menu = "dept")
|
@PreAuth(menu = "dept")
|
||||||
@GetMapping("/lazy-list")
|
@GetMapping("/lazy-list")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@Parameter(name = "deptName", description = "部门名称", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
@Parameter(name = "deptName", description = "组织名称", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
||||||
|
@Parameter(name = "shortName", description = "组织简称", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
|
||||||
@Parameter(name = "fullName", description = "部门全称", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
|
@Parameter(name = "fullName", description = "部门全称", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
|
||||||
})
|
})
|
||||||
@ApiOperationSupport(order = 3)
|
@ApiOperationSupport(order = 3)
|
||||||
@@ -195,8 +197,10 @@ public class DeptController extends BladeController {
|
|||||||
@Operation(summary = "同步OA公司")
|
@Operation(summary = "同步OA公司")
|
||||||
public R<OaOrgSyncPageVO> syncOaCompany(
|
public R<OaOrgSyncPageVO> syncOaCompany(
|
||||||
@RequestParam(defaultValue = "1") Integer current,
|
@RequestParam(defaultValue = "1") Integer current,
|
||||||
@RequestParam(defaultValue = "20") Integer size) {
|
@RequestParam(defaultValue = "20") Integer size,
|
||||||
return R.data(oaSyncService.syncCompanyPage(current, size));
|
@RequestParam(defaultValue = "false") Boolean incremental,
|
||||||
|
@RequestParam(required = false) String modifiedSince) {
|
||||||
|
return R.data(oaSyncService.syncCompanyPage(current, size, Boolean.TRUE.equals(incremental), modifiedSince));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,8 +212,10 @@ public class DeptController extends BladeController {
|
|||||||
@Operation(summary = "同步OA部门")
|
@Operation(summary = "同步OA部门")
|
||||||
public R<OaOrgSyncPageVO> syncOaDepartment(
|
public R<OaOrgSyncPageVO> syncOaDepartment(
|
||||||
@RequestParam(defaultValue = "1") Integer current,
|
@RequestParam(defaultValue = "1") Integer current,
|
||||||
@RequestParam(defaultValue = "20") Integer size) {
|
@RequestParam(defaultValue = "20") Integer size,
|
||||||
return R.data(oaSyncService.syncDepartmentPage(current, size));
|
@RequestParam(defaultValue = "false") Boolean incremental,
|
||||||
|
@RequestParam(required = false) String modifiedSince) {
|
||||||
|
return R.data(oaSyncService.syncDepartmentPage(current, size, Boolean.TRUE.equals(incremental), modifiedSince));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+16
-2
@@ -171,8 +171,10 @@ public class UserController {
|
|||||||
@Operation(summary = "同步OA人员")
|
@Operation(summary = "同步OA人员")
|
||||||
public R<OaPersonSyncPageVO> syncIamAccounts(
|
public R<OaPersonSyncPageVO> syncIamAccounts(
|
||||||
@RequestParam(defaultValue = "1") Integer current,
|
@RequestParam(defaultValue = "1") Integer current,
|
||||||
@RequestParam(defaultValue = "20") Integer size) {
|
@RequestParam(defaultValue = "20") Integer size,
|
||||||
return R.data(oaSyncService.syncPersonFromUserList(current, size));
|
@RequestParam(defaultValue = "false") Boolean incremental,
|
||||||
|
@RequestParam(required = false) String modifiedSince) {
|
||||||
|
return R.data(oaSyncService.syncPersonFromUserList(current, size, Boolean.TRUE.equals(incremental), modifiedSince));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -186,6 +188,18 @@ public class UserController {
|
|||||||
return R.status(userService.updateUser(user));
|
return R.status(userService.updateUser(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用或停用
|
||||||
|
*/
|
||||||
|
@IsAdmin
|
||||||
|
@PostMapping("/change-status")
|
||||||
|
@ApiOperationSupport(order = 6)
|
||||||
|
@Operation(summary = "启用停用", description = "传入id和status")
|
||||||
|
public R changeStatus(@Parameter(description = "用户主键", required = true) @RequestParam Long id,
|
||||||
|
@Parameter(description = "状态:1启用,0停用", required = true) @RequestParam Integer status) {
|
||||||
|
return R.status(userService.changeUserStatus(id, status));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除
|
* 删除
|
||||||
*/
|
*/
|
||||||
|
|||||||
+4
-2
@@ -47,7 +47,8 @@ public interface DeptConvert {
|
|||||||
// 父公司id转为父部门编码,要拼接前缀
|
// 父公司id转为父部门编码,要拼接前缀
|
||||||
@Mapping(source = "supsubcomid", target = "parentCode")
|
@Mapping(source = "supsubcomid", target = "parentCode")
|
||||||
@Mapping(source = "created", target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
@Mapping(source = "created", target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Mapping(source = "modified", target = "updateTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
// OA modified 单独落库,用于增量比对,避免覆盖本系统 updateTime
|
||||||
|
@Mapping(source = "modified", target = "oaModified")
|
||||||
Dept baseConvert(OACompanyResponse company);
|
Dept baseConvert(OACompanyResponse company);
|
||||||
|
|
||||||
@Mapping(source = "departmentname", target = "deptName")
|
@Mapping(source = "departmentname", target = "deptName")
|
||||||
@@ -57,7 +58,8 @@ public interface DeptConvert {
|
|||||||
// 所属子公司id转为所属公司编码,要拼接前缀
|
// 所属子公司id转为所属公司编码,要拼接前缀
|
||||||
@Mapping(source = "subcompanyid1", target = "belongCompanyCode")
|
@Mapping(source = "subcompanyid1", target = "belongCompanyCode")
|
||||||
@Mapping(source = "created", target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
@Mapping(source = "created", target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Mapping(source = "modified", target = "updateTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
// OA modified 单独落库,用于增量比对,避免覆盖本系统 updateTime
|
||||||
|
@Mapping(source = "modified", target = "oaModified")
|
||||||
Dept baseConvert(OADepartmentResponse department);
|
Dept baseConvert(OADepartmentResponse department);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
@@ -70,6 +70,7 @@ public interface UserConvert {
|
|||||||
@Mapping(source = "lastname", target = "realName")
|
@Mapping(source = "lastname", target = "realName")
|
||||||
@Mapping(source = "mobile", target = "phone")
|
@Mapping(source = "mobile", target = "phone")
|
||||||
@Mapping(source = "email", target = "email")
|
@Mapping(source = "email", target = "email")
|
||||||
|
@Mapping(source = "modified", target = "oaModified")
|
||||||
User baseConvert(OAPersonResponse person);
|
User baseConvert(OAPersonResponse person);
|
||||||
|
|
||||||
@Mapping(source = "subcompanyname", target = "companyName")
|
@Mapping(source = "subcompanyname", target = "companyName")
|
||||||
|
|||||||
@@ -80,6 +80,9 @@
|
|||||||
<if test="param3.deptName!=null and param3.deptName!=''">
|
<if test="param3.deptName!=null and param3.deptName!=''">
|
||||||
and dept.dept_name like concat(concat('%', #{param3.deptName}),'%')
|
and dept.dept_name like concat(concat('%', #{param3.deptName}),'%')
|
||||||
</if>
|
</if>
|
||||||
|
<if test="param3.shortName!=null and param3.shortName!=''">
|
||||||
|
and dept.short_name like concat(concat('%', #{param3.shortName}),'%')
|
||||||
|
</if>
|
||||||
<if test="param3.fullName!=null and param3.fullName!=''">
|
<if test="param3.fullName!=null and param3.fullName!=''">
|
||||||
and dept.full_name like concat(concat('%', #{param3.fullName}),'%')
|
and dept.full_name like concat(concat('%', #{param3.fullName}),'%')
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
+15
-9
@@ -32,27 +32,33 @@ public interface IOASyncService {
|
|||||||
/**
|
/**
|
||||||
* 按页从 OA 人员接口同步组织与人员
|
* 按页从 OA 人员接口同步组织与人员
|
||||||
*
|
*
|
||||||
* @param current 当前页,从 1 开始
|
* @param current 当前页,从 1 开始
|
||||||
* @param size 每页条数
|
* @param size 每页条数
|
||||||
|
* @param incremental 是否增量同步(按本地最大 oaModified 过滤 OA)
|
||||||
|
* @param modifiedSince 增量起始时间;首屏可空,后续分页回传首屏返回值
|
||||||
* @return 本页同步结果
|
* @return 本页同步结果
|
||||||
*/
|
*/
|
||||||
OaPersonSyncPageVO syncPersonFromUserList(int current, int size);
|
OaPersonSyncPageVO syncPersonFromUserList(int current, int size, boolean incremental, String modifiedSince);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按页从 OA 公司接口同步公司
|
* 按页从 OA 公司接口同步公司
|
||||||
*
|
*
|
||||||
* @param current 当前页,从 1 开始
|
* @param current 当前页,从 1 开始
|
||||||
* @param size 每页条数
|
* @param size 每页条数
|
||||||
|
* @param incremental 是否增量同步(按本地最大 oaModified 过滤 OA)
|
||||||
|
* @param modifiedSince 增量起始时间;首屏可空,后续分页回传首屏返回值
|
||||||
* @return 本页同步结果
|
* @return 本页同步结果
|
||||||
*/
|
*/
|
||||||
OaOrgSyncPageVO syncCompanyPage(int current, int size);
|
OaOrgSyncPageVO syncCompanyPage(int current, int size, boolean incremental, String modifiedSince);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按页从 OA 部门接口同步部门;最后一页完成后更新祖级列表
|
* 按页从 OA 部门接口同步部门;最后一页完成后更新祖级列表
|
||||||
*
|
*
|
||||||
* @param current 当前页,从 1 开始
|
* @param current 当前页,从 1 开始
|
||||||
* @param size 每页条数
|
* @param size 每页条数
|
||||||
|
* @param incremental 是否增量同步(按本地最大 oaModified 过滤 OA)
|
||||||
|
* @param modifiedSince 增量起始时间;首屏可空,后续分页回传首屏返回值
|
||||||
* @return 本页同步结果
|
* @return 本页同步结果
|
||||||
*/
|
*/
|
||||||
OaOrgSyncPageVO syncDepartmentPage(int current, int size);
|
OaOrgSyncPageVO syncDepartmentPage(int current, int size, boolean incremental, String modifiedSince);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -93,6 +93,15 @@ public interface IUserService extends BaseService<User> {
|
|||||||
*/
|
*/
|
||||||
boolean updateUser(User user);
|
boolean updateUser(User user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用或停用用户(租户守卫校验用户归属,仅更新状态)
|
||||||
|
*
|
||||||
|
* @param userId 用户主键
|
||||||
|
* @param status 状态:1 启用,0 停用
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
boolean changeUserStatus(Long userId, Integer status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改用户基本信息(仅限当前登录用户自身,忽略角色 / 部门 / 岗位 / 账号等敏感字段)
|
* 修改用户基本信息(仅限当前登录用户自身,忽略角色 / 部门 / 岗位 / 账号等敏感字段)
|
||||||
*
|
*
|
||||||
|
|||||||
+4
@@ -434,6 +434,10 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
|
|||||||
if (dept.getIsPlatformCompany() == null) {
|
if (dept.getIsPlatformCompany() == null) {
|
||||||
dept.setIsPlatformCompany(0);
|
dept.setIsPlatformCompany(0);
|
||||||
}
|
}
|
||||||
|
// 排序未填时默认 1
|
||||||
|
if (dept.getSort() == null) {
|
||||||
|
dept.setSort(1);
|
||||||
|
}
|
||||||
if (Func.isEmpty(dept.getTenantId())) {
|
if (Func.isEmpty(dept.getTenantId())) {
|
||||||
throw new ServiceException("租户ID不能为空");
|
throw new ServiceException("租户ID不能为空");
|
||||||
}
|
}
|
||||||
|
|||||||
+222
-63
@@ -60,6 +60,7 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
private final IOAClient oaClient;
|
private final IOAClient oaClient;
|
||||||
private final DeptConvert deptConvert;
|
private final DeptConvert deptConvert;
|
||||||
private final IDeptService deptService;
|
private final IDeptService deptService;
|
||||||
|
private final IUserService userService;
|
||||||
private final IRoleService roleService;
|
private final IRoleService roleService;
|
||||||
private final IMKPushService mkPushService;
|
private final IMKPushService mkPushService;
|
||||||
private final IDataSyncRecordService dataSyncRecordService;
|
private final IDataSyncRecordService dataSyncRecordService;
|
||||||
@@ -124,10 +125,10 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public OaPersonSyncPageVO syncPersonFromUserList(int current, int size) {
|
public OaPersonSyncPageVO syncPersonFromUserList(int current, int size, boolean incremental, String modifiedSince) {
|
||||||
try {
|
try {
|
||||||
ComposeLogUtil.addLog(log);
|
ComposeLogUtil.addLog(log);
|
||||||
return this.syncPersonFromOaPage(current, size);
|
return this.syncPersonFromOaPage(current, size, incremental, modifiedSince);
|
||||||
} finally {
|
} finally {
|
||||||
ComposeLogUtil.removeLastLog();
|
ComposeLogUtil.removeLastLog();
|
||||||
}
|
}
|
||||||
@@ -135,10 +136,10 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public OaOrgSyncPageVO syncCompanyPage(int current, int size) {
|
public OaOrgSyncPageVO syncCompanyPage(int current, int size, boolean incremental, String modifiedSince) {
|
||||||
try {
|
try {
|
||||||
ComposeLogUtil.addLog(log);
|
ComposeLogUtil.addLog(log);
|
||||||
return this.syncCompanyFromOaPage(current, size);
|
return this.syncCompanyFromOaPage(current, size, incremental, modifiedSince);
|
||||||
} finally {
|
} finally {
|
||||||
ComposeLogUtil.removeLastLog();
|
ComposeLogUtil.removeLastLog();
|
||||||
}
|
}
|
||||||
@@ -146,10 +147,10 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public OaOrgSyncPageVO syncDepartmentPage(int current, int size) {
|
public OaOrgSyncPageVO syncDepartmentPage(int current, int size, boolean incremental, String modifiedSince) {
|
||||||
try {
|
try {
|
||||||
ComposeLogUtil.addLog(log);
|
ComposeLogUtil.addLog(log);
|
||||||
return this.syncDepartmentFromOaPage(current, size);
|
return this.syncDepartmentFromOaPage(current, size, incremental, modifiedSince);
|
||||||
} finally {
|
} finally {
|
||||||
ComposeLogUtil.removeLastLog();
|
ComposeLogUtil.removeLastLog();
|
||||||
}
|
}
|
||||||
@@ -280,14 +281,17 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
/**
|
/**
|
||||||
* 按页从 OA 人员列表同步组织与人员
|
* 按页从 OA 人员列表同步组织与人员
|
||||||
*
|
*
|
||||||
* @param current 当前页
|
* @param current 当前页
|
||||||
* @param size 每页条数
|
* @param size 每页条数
|
||||||
|
* @param incremental 是否增量同步
|
||||||
|
* @param modifiedSince 增量起始时间(后续分页回传)
|
||||||
* @return 本页同步结果
|
* @return 本页同步结果
|
||||||
*/
|
*/
|
||||||
private OaPersonSyncPageVO syncPersonFromOaPage(int current, int size) {
|
private OaPersonSyncPageVO syncPersonFromOaPage(int current, int size, boolean incremental, String modifiedSince) {
|
||||||
int pageNo = current < 1 ? 1 : current;
|
int pageNo = current < 1 ? 1 : current;
|
||||||
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
||||||
OAPersonSearch personSearch = buildPersonSearch(null);
|
IncrementalStart incrementalStart = resolvePersonIncrementalStart(incremental, modifiedSince);
|
||||||
|
OAPersonSearch personSearch = buildPersonSearch(incrementalStart.getStartTime());
|
||||||
personSearch.setCurPage(pageNo);
|
personSearch.setCurPage(pageNo);
|
||||||
personSearch.setPageSize(pageSize);
|
personSearch.setPageSize(pageSize);
|
||||||
OAResponse<OAPersonResponse> oaResponse = oaClient.queryPersonPage(new OASearch<>(personSearch));
|
OAResponse<OAPersonResponse> oaResponse = oaClient.queryPersonPage(new OASearch<>(personSearch));
|
||||||
@@ -311,26 +315,31 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
pageVO.setFetchedCount(oaPersons.size());
|
pageVO.setFetchedCount(oaPersons.size());
|
||||||
pageVO.setSyncedCount(personSyncCount.getSyncedCount());
|
pageVO.setSyncedCount(personSyncCount.getSyncedCount());
|
||||||
pageVO.setSkippedCount(personSyncCount.getSkippedCount());
|
pageVO.setSkippedCount(personSyncCount.getSkippedCount());
|
||||||
|
pageVO.setModifiedSince(incrementalStart.getModifiedSince());
|
||||||
boolean finished = oaPersons.isEmpty()
|
boolean finished = oaPersons.isEmpty()
|
||||||
|| oaPersons.size() < pageSize
|
|| oaPersons.size() < pageSize
|
||||||
|| (long) pageNo * pageSize >= totalSize;
|
|| (long) pageNo * pageSize >= totalSize;
|
||||||
pageVO.setFinished(finished);
|
pageVO.setFinished(finished);
|
||||||
ComposeLogUtil.getLastLog().info("OA人员分页同步完成 {}/{},成功{},跳过{}",
|
ComposeLogUtil.getLastLog().info("OA人员分页同步完成 mode={} {}/{},成功{},跳过{}",
|
||||||
pageNo, totalSize, personSyncCount.getSyncedCount(), personSyncCount.getSkippedCount());
|
incremental ? "incremental" : "full", pageNo, totalSize,
|
||||||
|
personSyncCount.getSyncedCount(), personSyncCount.getSkippedCount());
|
||||||
return pageVO;
|
return pageVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按页从 OA 公司接口同步公司
|
* 按页从 OA 公司接口同步公司
|
||||||
*
|
*
|
||||||
* @param current 当前页
|
* @param current 当前页
|
||||||
* @param size 每页条数
|
* @param size 每页条数
|
||||||
|
* @param incremental 是否增量同步
|
||||||
|
* @param modifiedSince 增量起始时间(后续分页回传)
|
||||||
* @return 本页同步结果
|
* @return 本页同步结果
|
||||||
*/
|
*/
|
||||||
private OaOrgSyncPageVO syncCompanyFromOaPage(int current, int size) {
|
private OaOrgSyncPageVO syncCompanyFromOaPage(int current, int size, boolean incremental, String modifiedSince) {
|
||||||
int pageNo = current < 1 ? 1 : current;
|
int pageNo = current < 1 ? 1 : current;
|
||||||
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
||||||
OACompanySearch companySearch = buildCompanySearch(null);
|
IncrementalStart incrementalStart = resolveIncrementalStart(incremental, modifiedSince, DeptCategory.COMPANY);
|
||||||
|
OACompanySearch companySearch = buildCompanySearch(incrementalStart.getStartTime());
|
||||||
companySearch.setCurPage(pageNo);
|
companySearch.setCurPage(pageNo);
|
||||||
companySearch.setPageSize(pageSize);
|
companySearch.setPageSize(pageSize);
|
||||||
OAResponse<OACompanyResponse> oaResponse = oaClient.queryCompanyPage(new OASearch<>(companySearch));
|
OAResponse<OACompanyResponse> oaResponse = oaClient.queryCompanyPage(new OASearch<>(companySearch));
|
||||||
@@ -347,6 +356,7 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
ComposeLogUtil.getLastLog().warn("同步公司,本页未处理数据:{}", JSON.toJSONString(syncCount.getNotHandledList()));
|
ComposeLogUtil.getLastLog().warn("同步公司,本页未处理数据:{}", JSON.toJSONString(syncCount.getNotHandledList()));
|
||||||
}
|
}
|
||||||
OaOrgSyncPageVO pageVO = buildOrgSyncPageVO("company", pageNo, pageSize, totalSize, oaCompanies.size(), syncCount);
|
OaOrgSyncPageVO pageVO = buildOrgSyncPageVO("company", pageNo, pageSize, totalSize, oaCompanies.size(), syncCount);
|
||||||
|
pageVO.setModifiedSince(incrementalStart.getModifiedSince());
|
||||||
if (Boolean.TRUE.equals(pageVO.getFinished())) {
|
if (Boolean.TRUE.equals(pageVO.getFinished())) {
|
||||||
// 公司全部分批入库后:重建层级,并删除上级不存在的数据
|
// 公司全部分批入库后:重建层级,并删除上级不存在的数据
|
||||||
deptService.rebuildOaHierarchy();
|
deptService.rebuildOaHierarchy();
|
||||||
@@ -354,19 +364,22 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
}
|
}
|
||||||
CacheUtil.clear(SYS_CACHE);
|
CacheUtil.clear(SYS_CACHE);
|
||||||
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
||||||
ComposeLogUtil.getLastLog().info("OA公司分页同步完成 {}/{},成功{},跳过{}",
|
ComposeLogUtil.getLastLog().info("OA公司分页同步完成 mode={} {}/{},成功{},跳过{}",
|
||||||
pageNo, totalSize, syncCount.getSyncedCount(), syncCount.getSkippedCount());
|
incremental ? "incremental" : "full", pageNo, totalSize,
|
||||||
|
syncCount.getSyncedCount(), syncCount.getSkippedCount());
|
||||||
return pageVO;
|
return pageVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按页从 OA 部门接口同步部门
|
* 按页从 OA 部门接口同步部门
|
||||||
*
|
*
|
||||||
* @param current 当前页
|
* @param current 当前页
|
||||||
* @param size 每页条数
|
* @param size 每页条数
|
||||||
|
* @param incremental 是否增量同步
|
||||||
|
* @param modifiedSince 增量起始时间(后续分页回传)
|
||||||
* @return 本页同步结果
|
* @return 本页同步结果
|
||||||
*/
|
*/
|
||||||
private OaOrgSyncPageVO syncDepartmentFromOaPage(int current, int size) {
|
private OaOrgSyncPageVO syncDepartmentFromOaPage(int current, int size, boolean incremental, String modifiedSince) {
|
||||||
int pageNo = current < 1 ? 1 : current;
|
int pageNo = current < 1 ? 1 : current;
|
||||||
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
int pageSize = size < 1 ? 20 : Math.min(size, 200);
|
||||||
String subCompanyIds = getOaSubCompanyIds(true);
|
String subCompanyIds = getOaSubCompanyIds(true);
|
||||||
@@ -376,7 +389,8 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
emptyPageVO.setFinished(true);
|
emptyPageVO.setFinished(true);
|
||||||
return emptyPageVO;
|
return emptyPageVO;
|
||||||
}
|
}
|
||||||
OADepartmentSearch departmentSearch = buildDepartmentSearch(null, subCompanyIds);
|
IncrementalStart incrementalStart = resolveIncrementalStart(incremental, modifiedSince, DeptCategory.DEPT);
|
||||||
|
OADepartmentSearch departmentSearch = buildDepartmentSearch(incrementalStart.getStartTime(), subCompanyIds);
|
||||||
departmentSearch.setCurPage(pageNo);
|
departmentSearch.setCurPage(pageNo);
|
||||||
departmentSearch.setPageSize(pageSize);
|
departmentSearch.setPageSize(pageSize);
|
||||||
OAResponse<OADepartmentResponse> oaResponse = oaClient.queryDepartmentPage(new OASearch<>(departmentSearch));
|
OAResponse<OADepartmentResponse> oaResponse = oaClient.queryDepartmentPage(new OASearch<>(departmentSearch));
|
||||||
@@ -393,6 +407,7 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
ComposeLogUtil.getLastLog().warn("同步部门,本页未处理数据:{}", JSON.toJSONString(syncCount.getNotHandledList()));
|
ComposeLogUtil.getLastLog().warn("同步部门,本页未处理数据:{}", JSON.toJSONString(syncCount.getNotHandledList()));
|
||||||
}
|
}
|
||||||
OaOrgSyncPageVO pageVO = buildOrgSyncPageVO("department", pageNo, pageSize, totalSize, oaDepartments.size(), syncCount);
|
OaOrgSyncPageVO pageVO = buildOrgSyncPageVO("department", pageNo, pageSize, totalSize, oaDepartments.size(), syncCount);
|
||||||
|
pageVO.setModifiedSince(incrementalStart.getModifiedSince());
|
||||||
if (Boolean.TRUE.equals(pageVO.getFinished())) {
|
if (Boolean.TRUE.equals(pageVO.getFinished())) {
|
||||||
// 部门分批同步完成后,重建层级、清理无法挂载数据并刷新祖级列表
|
// 部门分批同步完成后,重建层级、清理无法挂载数据并刷新祖级列表
|
||||||
deptService.rebuildOaHierarchy();
|
deptService.rebuildOaHierarchy();
|
||||||
@@ -401,11 +416,112 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
}
|
}
|
||||||
CacheUtil.clear(SYS_CACHE);
|
CacheUtil.clear(SYS_CACHE);
|
||||||
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
||||||
ComposeLogUtil.getLastLog().info("OA部门分页同步完成 {}/{},成功{},跳过{}",
|
ComposeLogUtil.getLastLog().info("OA部门分页同步完成 mode={} {}/{},成功{},跳过{}",
|
||||||
pageNo, totalSize, syncCount.getSyncedCount(), syncCount.getSkippedCount());
|
incremental ? "incremental" : "full", pageNo, totalSize,
|
||||||
|
syncCount.getSyncedCount(), syncCount.getSkippedCount());
|
||||||
return pageVO;
|
return pageVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析增量同步起始时间:优先使用前端回传值,保证同阶段分页起点不变
|
||||||
|
*/
|
||||||
|
private IncrementalStart resolveIncrementalStart(boolean incremental, String modifiedSince, DeptCategory deptCategory) {
|
||||||
|
if (!incremental) {
|
||||||
|
return IncrementalStart.empty();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(modifiedSince)) {
|
||||||
|
try {
|
||||||
|
Date startTime = DateUtil.parse(modifiedSince.trim(), DateUtil.PATTERN_DATETIME);
|
||||||
|
return new IncrementalStart(startTime, modifiedSince.trim());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
ComposeLogUtil.getLastLog().warn("解析回传 modifiedSince 失败:{},重新计算", modifiedSince);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dept latest = deptService.getOne(Wrappers.<Dept>lambdaQuery()
|
||||||
|
.select(Dept::getOaModified)
|
||||||
|
.eq(Dept::getIsOa, YES)
|
||||||
|
.eq(Dept::getDeptCategory, deptCategory.getCode())
|
||||||
|
.isNotNull(Dept::getOaModified)
|
||||||
|
.ne(Dept::getOaModified, "")
|
||||||
|
.orderByDesc(Dept::getOaModified)
|
||||||
|
.last("limit 1"), false);
|
||||||
|
if (latest == null || StringUtils.isBlank(latest.getOaModified())) {
|
||||||
|
ComposeLogUtil.getLastLog().info("本地无 {} oaModified 记录,增量同步按全量拉取后按字段比对跳过",
|
||||||
|
deptCategory.getName());
|
||||||
|
return IncrementalStart.empty();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Date startTime = DateUtil.parse(latest.getOaModified(), DateUtil.PATTERN_DATETIME);
|
||||||
|
ComposeLogUtil.getLastLog().info("增量同步{} OA modified 起始时间:{}",
|
||||||
|
deptCategory.getName(), latest.getOaModified());
|
||||||
|
return new IncrementalStart(startTime, latest.getOaModified());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
ComposeLogUtil.getLastLog().warn("解析本地最大 oaModified 失败:{},回退为全量拉取", latest.getOaModified());
|
||||||
|
return IncrementalStart.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人员增量同步起始时间:优先回传值,否则取本地 OA 用户最大 oaModified
|
||||||
|
*/
|
||||||
|
private IncrementalStart resolvePersonIncrementalStart(boolean incremental, String modifiedSince) {
|
||||||
|
if (!incremental) {
|
||||||
|
return IncrementalStart.empty();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(modifiedSince)) {
|
||||||
|
try {
|
||||||
|
Date startTime = DateUtil.parse(modifiedSince.trim(), DateUtil.PATTERN_DATETIME);
|
||||||
|
return new IncrementalStart(startTime, modifiedSince.trim());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
ComposeLogUtil.getLastLog().warn("解析人员回传 modifiedSince 失败:{},重新计算", modifiedSince);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
User latest = userService.getOne(Wrappers.<User>lambdaQuery()
|
||||||
|
.select(User::getOaModified)
|
||||||
|
.eq(User::getIsOa, YES)
|
||||||
|
.isNotNull(User::getOaModified)
|
||||||
|
.ne(User::getOaModified, "")
|
||||||
|
.orderByDesc(User::getOaModified)
|
||||||
|
.last("limit 1"), false);
|
||||||
|
if (latest == null || StringUtils.isBlank(latest.getOaModified())) {
|
||||||
|
ComposeLogUtil.getLastLog().info("本地无人员 oaModified 记录,增量同步按全量拉取后按字段比对跳过");
|
||||||
|
return IncrementalStart.empty();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Date startTime = DateUtil.parse(latest.getOaModified(), DateUtil.PATTERN_DATETIME);
|
||||||
|
ComposeLogUtil.getLastLog().info("增量同步人员 OA modified 起始时间:{}", latest.getOaModified());
|
||||||
|
return new IncrementalStart(startTime, latest.getOaModified());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
ComposeLogUtil.getLastLog().warn("解析本地人员最大 oaModified 失败:{},回退为全量拉取", latest.getOaModified());
|
||||||
|
return IncrementalStart.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增量同步起点
|
||||||
|
*/
|
||||||
|
private static class IncrementalStart {
|
||||||
|
private final Date startTime;
|
||||||
|
private final String modifiedSince;
|
||||||
|
|
||||||
|
private IncrementalStart(Date startTime, String modifiedSince) {
|
||||||
|
this.startTime = startTime;
|
||||||
|
this.modifiedSince = modifiedSince;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IncrementalStart empty() {
|
||||||
|
return new IncrementalStart(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getModifiedSince() {
|
||||||
|
return modifiedSince;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组装组织分页同步结果
|
* 组装组织分页同步结果
|
||||||
*/
|
*/
|
||||||
@@ -507,14 +623,10 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
return new OrgSyncCount(0, filteredSkipCount, Collections.emptyList());
|
return new OrgSyncCount(0, filteredSkipCount, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询数据库的部门,转换成map
|
// 查询已存在公司(含 oaModified),按编码索引
|
||||||
Map<String, Long> deptMap = getAllCompanyDeptMap();
|
Map<String, Dept> existingDeptMap = loadExistingDeptMap(DeptCategory.COMPANY, null);
|
||||||
|
Map<String, Long> deptIdByCode = toDeptIdMap(existingDeptMap);
|
||||||
// 处理部门
|
return persistSyncedDepts(allParam, existingDeptMap, deptIdByCode, DeptCategory.COMPANY, filteredSkipCount);
|
||||||
List<Dept> notHandledList = handleDept(allParam, deptMap, DeptCategory.COMPANY);
|
|
||||||
int syncedCount = allParam.size() - notHandledList.size();
|
|
||||||
int skippedCount = filteredSkipCount + notHandledList.size();
|
|
||||||
return new OrgSyncCount(syncedCount, skippedCount, notHandledList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -558,39 +670,62 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
deptCodes.add(dept.getParentCode());
|
deptCodes.add(dept.getParentCode());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 查询数据库的部门,转换成map。包含本页及上级编码,便于命中已入库的上级
|
// 查询数据库已有部门(含 oaModified)
|
||||||
Map<String, Long> deptMap = deptCodes.isEmpty() ? new HashMap<>() : deptService.list(Wrappers.<Dept>lambdaQuery()
|
Map<String, Dept> existingDeptMap = loadExistingDeptMap(DeptCategory.DEPT, deptCodes);
|
||||||
.eq(Dept::getDeptCategory, DeptCategory.DEPT.getCode())
|
Map<String, Long> deptIdByCode = toDeptIdMap(existingDeptMap);
|
||||||
.in(Dept::getDeptCode, deptCodes)
|
|
||||||
).stream()
|
|
||||||
.filter(dept -> StringUtils.isNotEmpty(dept.getDeptCode()))
|
|
||||||
.collect(Collectors.toMap(Dept::getDeptCode, Dept::getId, (a, b) -> b));
|
|
||||||
// 公司编码也放入 map,根部门挂到公司时才能解析父级
|
// 公司编码也放入 map,根部门挂到公司时才能解析父级
|
||||||
companyDeptMap.forEach(deptMap::putIfAbsent);
|
companyDeptMap.forEach(deptIdByCode::putIfAbsent);
|
||||||
// 处理部门
|
return persistSyncedDepts(allParam, existingDeptMap, deptIdByCode, DeptCategory.DEPT, filteredSkipCount);
|
||||||
List<Dept> notHandledList = this.handleDept(allParam, deptMap, DeptCategory.DEPT);
|
|
||||||
int syncedCount = allParam.size() - notHandledList.size();
|
|
||||||
int skippedCount = filteredSkipCount + notHandledList.size();
|
|
||||||
return new OrgSyncCount(syncedCount, skippedCount, notHandledList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理部门
|
* 加载已存在组织,按部门编码索引
|
||||||
* @param allParam 待处理的部门
|
*
|
||||||
* @param deptMap 数据库所有部门编码和id map
|
* @param deptCategory 组织类型
|
||||||
* @return 未处理的数据
|
* @param deptCodes 限定编码;为空则按类型全量加载
|
||||||
*/
|
*/
|
||||||
private List<Dept> handleDept(List<Dept> allParam, Map<String, Long> deptMap, DeptCategory deptCategory) {
|
private Map<String, Dept> loadExistingDeptMap(DeptCategory deptCategory, Set<String> deptCodes) {
|
||||||
// 数据库存在的所有部门id
|
if (deptCodes != null && deptCodes.isEmpty()) {
|
||||||
Set<Long> existsDeptIds = new HashSet<>(deptMap.values());
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
List<Dept> deptList = deptService.list(Wrappers.<Dept>lambdaQuery()
|
||||||
|
.eq(Dept::getDeptCategory, deptCategory.getCode())
|
||||||
|
.in(deptCodes != null, Dept::getDeptCode, deptCodes)
|
||||||
|
.select(Dept::getId, Dept::getDeptCode, Dept::getOaModified, Dept::getParentId));
|
||||||
|
return deptList.stream()
|
||||||
|
.filter(dept -> StringUtils.isNotEmpty(dept.getDeptCode()))
|
||||||
|
.collect(Collectors.toMap(Dept::getDeptCode, dept -> dept, (a, b) -> b));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Long> toDeptIdMap(Map<String, Dept> existingDeptMap) {
|
||||||
|
Map<String, Long> deptIdByCode = new HashMap<>();
|
||||||
|
existingDeptMap.forEach((code, dept) -> deptIdByCode.put(code, dept.getId()));
|
||||||
|
return deptIdByCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 持久化同步数据:不存在则新增;存在且 oaModified 不一致才修改
|
||||||
|
*
|
||||||
|
* @param allParam 待处理数据
|
||||||
|
* @param existingDeptMap 已存在组织(同类型)
|
||||||
|
* @param deptIdByCode 编码→id(含上级公司等)
|
||||||
|
* @param deptCategory 组织类型
|
||||||
|
* @param filteredSkipCount 上游过滤跳过数
|
||||||
|
* @return 同步统计
|
||||||
|
*/
|
||||||
|
private OrgSyncCount persistSyncedDepts(List<Dept> allParam, Map<String, Dept> existingDeptMap,
|
||||||
|
Map<String, Long> deptIdByCode, DeptCategory deptCategory,
|
||||||
|
int filteredSkipCount) {
|
||||||
|
Set<Long> existsDeptIds = existingDeptMap.values().stream()
|
||||||
|
.map(Dept::getId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
allParam.forEach(dept -> {
|
allParam.forEach(dept -> {
|
||||||
if (deptMap.containsKey(dept.getDeptCode())) {
|
if (deptIdByCode.containsKey(dept.getDeptCode())) {
|
||||||
// 根据部门编码获取对应的部门id
|
dept.setId(deptIdByCode.get(dept.getDeptCode()));
|
||||||
dept.setId(deptMap.get(dept.getDeptCode()));
|
|
||||||
} else {
|
} else {
|
||||||
// 没有就生成一个id
|
|
||||||
dept.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
|
dept.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
|
||||||
deptMap.put(dept.getDeptCode(), dept.getId());
|
deptIdByCode.put(dept.getDeptCode(), dept.getId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -600,7 +735,7 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
if (dept.getParentId() != null) {
|
if (dept.getParentId() != null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Long parentId = deptMap.get(dept.getParentCode());
|
Long parentId = deptIdByCode.get(dept.getParentCode());
|
||||||
if (parentId != null) {
|
if (parentId != null) {
|
||||||
dept.setParentId(parentId);
|
dept.setParentId(parentId);
|
||||||
continue;
|
continue;
|
||||||
@@ -615,11 +750,10 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
deptCategory.getName(), unresolvedParentCount);
|
deptCategory.getName(), unresolvedParentCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 父id不为空才新增;已存在的记录即使父id未解析也更新(空父id不会覆盖原值)
|
// 父id不为空才新增;已存在的记录即使父id未解析也允许更新(空父id不会覆盖原值)
|
||||||
List<Dept> list = allParam.stream()
|
List<Dept> list = allParam.stream()
|
||||||
.filter(dept -> dept.getParentId() != null || existsDeptIds.contains(dept.getId()))
|
.filter(dept -> dept.getParentId() != null || existsDeptIds.contains(dept.getId()))
|
||||||
.toList();
|
.toList();
|
||||||
// 不存在的新增
|
|
||||||
List<Dept> addList = list.stream()
|
List<Dept> addList = list.stream()
|
||||||
.filter(dept -> !existsDeptIds.contains(dept.getId()))
|
.filter(dept -> !existsDeptIds.contains(dept.getId()))
|
||||||
.toList();
|
.toList();
|
||||||
@@ -627,18 +761,43 @@ public class OASyncServiceImpl implements IOASyncService {
|
|||||||
ComposeLogUtil.getLastLog().info("批量新增{}:{}", deptCategory.getName(), addList.size());
|
ComposeLogUtil.getLastLog().info("批量新增{}:{}", deptCategory.getName(), addList.size());
|
||||||
deptService.saveBatch(addList);
|
deptService.saveBatch(addList);
|
||||||
}
|
}
|
||||||
// 存在的修改
|
// 已存在且 oaModified 不一致(或不存在可比对值)才修改
|
||||||
List<Dept> updateList = list.stream()
|
List<Dept> updateList = list.stream()
|
||||||
.filter(dept -> existsDeptIds.contains(dept.getId()))
|
.filter(dept -> existsDeptIds.contains(dept.getId()))
|
||||||
|
.filter(dept -> !shouldSkipOaUpdate(existingDeptMap.get(dept.getDeptCode()), dept))
|
||||||
.toList();
|
.toList();
|
||||||
if (CollectionUtil.isNotEmpty(updateList)) {
|
if (CollectionUtil.isNotEmpty(updateList)) {
|
||||||
ComposeLogUtil.getLastLog().info("批量修改{}:{}", deptCategory.getName(), updateList.size());
|
ComposeLogUtil.getLastLog().info("批量修改{}:{}", deptCategory.getName(), updateList.size());
|
||||||
deptService.updateBatchById(updateList);
|
deptService.updateBatchById(updateList);
|
||||||
}
|
}
|
||||||
// 返回仍未保存的数据
|
int unchangedCount = (int) list.stream()
|
||||||
return allParam.stream()
|
.filter(dept -> existsDeptIds.contains(dept.getId()))
|
||||||
|
.filter(dept -> shouldSkipOaUpdate(existingDeptMap.get(dept.getDeptCode()), dept))
|
||||||
|
.count();
|
||||||
|
List<Dept> notHandledList = allParam.stream()
|
||||||
.filter(dept -> dept.getParentId() == null && !existsDeptIds.contains(dept.getId()))
|
.filter(dept -> dept.getParentId() == null && !existsDeptIds.contains(dept.getId()))
|
||||||
.toList();
|
.toList();
|
||||||
|
int syncedCount = addList.size() + updateList.size();
|
||||||
|
int skippedCount = filteredSkipCount + unchangedCount + notHandledList.size();
|
||||||
|
if (unchangedCount > 0) {
|
||||||
|
ComposeLogUtil.getLastLog().info("跳过未变更{}:{}", deptCategory.getName(), unchangedCount);
|
||||||
|
}
|
||||||
|
return new OrgSyncCount(syncedCount, skippedCount, notHandledList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oaModified 一致则跳过更新;任一侧为空无法确认一致,执行更新以补齐字段
|
||||||
|
*/
|
||||||
|
private boolean shouldSkipOaUpdate(Dept existing, Dept incoming) {
|
||||||
|
if (existing == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String localModified = StringUtils.trimToEmpty(existing.getOaModified());
|
||||||
|
String remoteModified = StringUtils.trimToEmpty(incoming == null ? null : incoming.getOaModified());
|
||||||
|
if (localModified.isEmpty() || remoteModified.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return localModified.equals(remoteModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+34
-2
@@ -249,6 +249,7 @@ public class OaUserListSyncHelper {
|
|||||||
});
|
});
|
||||||
Map<String, Long> userMap = new HashMap<>();
|
Map<String, Long> userMap = new HashMap<>();
|
||||||
Set<Long> existsUserIds = new HashSet<>();
|
Set<Long> existsUserIds = new HashSet<>();
|
||||||
|
Set<Long> unchangedUserIds = new HashSet<>();
|
||||||
users.forEach(user -> {
|
users.forEach(user -> {
|
||||||
User existingUser = existingByAccount.get(user.getAccount());
|
User existingUser = existingByAccount.get(user.getAccount());
|
||||||
if (existingUser == null && StringUtils.isNotBlank(user.getPhone())) {
|
if (existingUser == null && StringUtils.isNotBlank(user.getPhone())) {
|
||||||
@@ -258,6 +259,9 @@ public class OaUserListSyncHelper {
|
|||||||
user.setId(existingUser.getId());
|
user.setId(existingUser.getId());
|
||||||
user.setPassword(null);
|
user.setPassword(null);
|
||||||
existsUserIds.add(existingUser.getId());
|
existsUserIds.add(existingUser.getId());
|
||||||
|
if (shouldSkipOaUpdate(existingUser, user)) {
|
||||||
|
unchangedUserIds.add(existingUser.getId());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
user.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
|
user.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
|
||||||
user.setPostId("-1");
|
user.setPostId("-1");
|
||||||
@@ -279,12 +283,18 @@ public class OaUserListSyncHelper {
|
|||||||
}
|
}
|
||||||
List<User> updateUsers = users.stream()
|
List<User> updateUsers = users.stream()
|
||||||
.filter(user -> existsUserIds.contains(user.getId()))
|
.filter(user -> existsUserIds.contains(user.getId()))
|
||||||
|
.filter(user -> !unchangedUserIds.contains(user.getId()))
|
||||||
.toList();
|
.toList();
|
||||||
if (CollectionUtil.isNotEmpty(updateUsers)) {
|
if (CollectionUtil.isNotEmpty(updateUsers)) {
|
||||||
ComposeLogUtil.getLastLog().info("批量修改用户:{}", updateUsers.size());
|
ComposeLogUtil.getLastLog().info("批量修改用户:{}", updateUsers.size());
|
||||||
userService.updateBatchById(updateUsers);
|
userService.updateBatchById(updateUsers);
|
||||||
}
|
}
|
||||||
|
if (!unchangedUserIds.isEmpty()) {
|
||||||
|
ComposeLogUtil.getLastLog().info("跳过未变更用户:{}", unchangedUserIds.size());
|
||||||
|
}
|
||||||
ComposeLogUtil.getLastLog().info("缺少账号已跳过的人员:{}", skippedCount);
|
ComposeLogUtil.getLastLog().info("缺少账号已跳过的人员:{}", skippedCount);
|
||||||
|
int syncedCount = addUsers.size() + updateUsers.size();
|
||||||
|
skippedCount += unchangedUserIds.size();
|
||||||
if (userMap.isEmpty()) {
|
if (userMap.isEmpty()) {
|
||||||
return new PersonSyncCount(0, skippedCount);
|
return new PersonSyncCount(0, skippedCount);
|
||||||
}
|
}
|
||||||
@@ -295,7 +305,13 @@ public class OaUserListSyncHelper {
|
|||||||
.collect(Collectors.toMap(this::getUserDeptKey, UserDept::getId, (first, second) -> second));
|
.collect(Collectors.toMap(this::getUserDeptKey, UserDept::getId, (first, second) -> second));
|
||||||
Set<Long> existsUserDeptIds = new HashSet<>(userDeptMap.values());
|
Set<Long> existsUserDeptIds = new HashSet<>(userDeptMap.values());
|
||||||
List<UserDept> userDeptList = oaPersons.stream()
|
List<UserDept> userDeptList = oaPersons.stream()
|
||||||
.filter(oaPerson -> userMap.containsKey(userConvert.resolveAccount(oaPerson)))
|
.filter(oaPerson -> {
|
||||||
|
String account = userConvert.resolveAccount(oaPerson);
|
||||||
|
if (!userMap.containsKey(account)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !unchangedUserIds.contains(userMap.get(account));
|
||||||
|
})
|
||||||
.map(oaPerson -> this.buildUserDept(oaPerson, userMap, orgIndex))
|
.map(oaPerson -> this.buildUserDept(oaPerson, userMap, orgIndex))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -333,6 +349,7 @@ public class OaUserListSyncHelper {
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
String defaultRoleId = getDefaultRoleId();
|
String defaultRoleId = getDefaultRoleId();
|
||||||
List<User> updateUserParams = list.stream()
|
List<User> updateUserParams = list.stream()
|
||||||
|
.filter(userDeptIds -> !unchangedUserIds.contains(userDeptIds.getUserId()))
|
||||||
.filter(userDeptIds -> StringUtils.isNotBlank(userDeptIds.getDeptIds()) && userDeptIds.getDeptIds().length() <= MAX_DEPT_ID_LENGTH)
|
.filter(userDeptIds -> StringUtils.isNotBlank(userDeptIds.getDeptIds()) && userDeptIds.getDeptIds().length() <= MAX_DEPT_ID_LENGTH)
|
||||||
.map(userDeptIds -> {
|
.map(userDeptIds -> {
|
||||||
User user = new User();
|
User user = new User();
|
||||||
@@ -347,7 +364,22 @@ public class OaUserListSyncHelper {
|
|||||||
if (CollectionUtil.isNotEmpty(updateUserParams)) {
|
if (CollectionUtil.isNotEmpty(updateUserParams)) {
|
||||||
userService.updateBatchById(updateUserParams);
|
userService.updateBatchById(updateUserParams);
|
||||||
}
|
}
|
||||||
return new PersonSyncCount(users.size(), skippedCount);
|
return new PersonSyncCount(syncedCount, skippedCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oaModified 一致则跳过更新;任一侧为空无法确认一致,执行更新以补齐字段
|
||||||
|
*/
|
||||||
|
private boolean shouldSkipOaUpdate(User existing, User incoming) {
|
||||||
|
if (existing == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String localModified = StringUtils.trimToEmpty(existing.getOaModified());
|
||||||
|
String remoteModified = StringUtils.trimToEmpty(incoming == null ? null : incoming.getOaModified());
|
||||||
|
if (localModified.isEmpty() || remoteModified.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return localModified.equals(remoteModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dept getOrCreateRootCompany() {
|
private Dept getOrCreateRootCompany() {
|
||||||
|
|||||||
+36
-1
@@ -339,6 +339,23 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
return submitUserInfo(user) && submitUserDept(user) && submitUserScopes(user);
|
return submitUserInfo(user) && submitUserDept(user) && submitUserScopes(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public boolean changeUserStatus(Long userId, Integer status) {
|
||||||
|
if (Func.isEmpty(userId)) {
|
||||||
|
throw new ServiceException("用户主键不能为空");
|
||||||
|
}
|
||||||
|
if (!Objects.equals(status, DataStatusEnum.ENABLE.getCode()) && !Objects.equals(status, 0)
|
||||||
|
&& !Objects.equals(status, DataStatusEnum.DISABLE.getCode())) {
|
||||||
|
throw new ServiceException("启停状态不正确");
|
||||||
|
}
|
||||||
|
TenantGuard.verify(this, userId, USER);
|
||||||
|
Integer targetStatus = Objects.equals(status, DataStatusEnum.ENABLE.getCode())
|
||||||
|
? DataStatusEnum.ENABLE.getCode() : 0;
|
||||||
|
CacheUtil.clear(USER_CACHE);
|
||||||
|
return changeStatus(Collections.singletonList(userId), targetStatus);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateUserInfo(User user) {
|
public boolean updateUserInfo(User user) {
|
||||||
// 用户修改自身信息强制指定当前请求账号的ID
|
// 用户修改自身信息强制指定当前请求账号的ID
|
||||||
@@ -364,7 +381,14 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
throw new ServiceException(StringUtil.format("当前手机 [{}] 已存在!", user.getPhone()));
|
throw new ServiceException(StringUtil.format("当前手机 [{}] 已存在!", user.getPhone()));
|
||||||
}
|
}
|
||||||
user.setPassword(null);
|
user.setPassword(null);
|
||||||
return updateById(user);
|
Integer originalSex = user.getSex();
|
||||||
|
Integer normalizedSex = normalizeUserSex(originalSex);
|
||||||
|
user.setSex(normalizedSex);
|
||||||
|
boolean updated = updateById(user);
|
||||||
|
if (user.getId() != null && originalSex != null && normalizedSex == null) {
|
||||||
|
this.update(Wrappers.<User>lambdaUpdate().set(User::getSex, null).eq(User::getId, user.getId()));
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean submitUserDept(User user) {
|
private boolean submitUserDept(User user) {
|
||||||
@@ -1086,6 +1110,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
throw new ServiceException(StringUtil.format("当前手机 [{}] 已存在!", user.getPhone()));
|
throw new ServiceException(StringUtil.format("当前手机 [{}] 已存在!", user.getPhone()));
|
||||||
}
|
}
|
||||||
CacheUtil.clear(USER_CACHE);
|
CacheUtil.clear(USER_CACHE);
|
||||||
|
user.setSex(normalizeUserSex(user.getSex()));
|
||||||
return save(user) && submitUserDept(user) && submitUserScopes(user);
|
return save(user) && submitUserDept(user) && submitUserScopes(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1096,6 +1121,16 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
if (user.getIncludeNewCustomer() == null) user.setIncludeNewCustomer(0);
|
if (user.getIncludeNewCustomer() == null) user.setIncludeNewCustomer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 性别仅保留男 / 女 / 未知;空值或历史占位 -1 不回填,按空处理。
|
||||||
|
*/
|
||||||
|
private Integer normalizeUserSex(Integer sex) {
|
||||||
|
if (Objects.equals(sex, 1) || Objects.equals(sex, 2) || Objects.equals(sex, 3)) {
|
||||||
|
return sex;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean submitUserScopes(User user) {
|
private boolean submitUserScopes(User user) {
|
||||||
userDataScopeMapper.delete(Wrappers.<UserDataScope>lambdaQuery().eq(UserDataScope::getUserId, user.getId()));
|
userDataScopeMapper.delete(Wrappers.<UserDataScope>lambdaQuery().eq(UserDataScope::getUserId, user.getId()));
|
||||||
userCustomerScopeMapper.delete(Wrappers.<UserCustomerScope>lambdaQuery().eq(UserCustomerScope::getUserId, user.getId()));
|
userCustomerScopeMapper.delete(Wrappers.<UserCustomerScope>lambdaQuery().eq(UserCustomerScope::getUserId, user.getId()));
|
||||||
|
|||||||
+6
-1
@@ -38,6 +38,7 @@ import org.springblade.system.pojo.enums.DictEnum;
|
|||||||
import org.springblade.system.pojo.vo.UserVO;
|
import org.springblade.system.pojo.vo.UserVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 包装类,返回视图层所需的字段
|
* 包装类,返回视图层所需的字段
|
||||||
@@ -81,7 +82,11 @@ public class UserWrapper extends BaseEntityWrapper<User, UserVO> {
|
|||||||
userVO.setPostId(StringPool.EMPTY);
|
userVO.setPostId(StringPool.EMPTY);
|
||||||
userVO.setPostName("暂未分配");
|
userVO.setPostName("暂未分配");
|
||||||
}
|
}
|
||||||
userVO.setSexName(DictCache.getValue(DictEnum.SEX, user.getSex()));
|
if (user.getSex() == null || Objects.equals(user.getSex(), -1)) {
|
||||||
|
userVO.setSexName("");
|
||||||
|
} else {
|
||||||
|
userVO.setSexName(DictCache.getValue(DictEnum.SEX, user.getSex()));
|
||||||
|
}
|
||||||
userVO.setUserTypeName(DictCache.getValue(DictEnum.USER_TYPE, user.getUserType()));
|
userVO.setUserTypeName(DictCache.getValue(DictEnum.USER_TYPE, user.getUserType()));
|
||||||
return userVO;
|
return userVO;
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-9
@@ -38,6 +38,7 @@ import org.springblade.core.tenant.annotation.TenantIgnore;
|
|||||||
import org.springblade.core.tool.jackson.JsonUtil;
|
import org.springblade.core.tool.jackson.JsonUtil;
|
||||||
import org.springblade.core.tool.utils.BeanUtil;
|
import org.springblade.core.tool.utils.BeanUtil;
|
||||||
import org.springblade.core.tool.utils.Func;
|
import org.springblade.core.tool.utils.Func;
|
||||||
|
import org.springblade.system.cache.SysCache;
|
||||||
import org.springblade.system.cache.UserCache;
|
import org.springblade.system.cache.UserCache;
|
||||||
import org.springblade.transport.excel.CustomerArchiveExcel;
|
import org.springblade.transport.excel.CustomerArchiveExcel;
|
||||||
import org.springblade.transport.mapper.CreditRatingStandardMapper;
|
import org.springblade.transport.mapper.CreditRatingStandardMapper;
|
||||||
@@ -118,6 +119,8 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
|||||||
private static final String APPROVAL_REVIEWING = "reviewing";
|
private static final String APPROVAL_REVIEWING = "reviewing";
|
||||||
private static final String APPROVAL_APPROVED = "approved";
|
private static final String APPROVAL_APPROVED = "approved";
|
||||||
private static final String APPROVAL_REJECTED = "rejected";
|
private static final String APPROVAL_REJECTED = "rejected";
|
||||||
|
/** 客商所属组织固定为顶层组织 */
|
||||||
|
private static final String FIXED_OWNER_DEPT_NAME = "桂物物流集团";
|
||||||
private static final String CUSTOMER_CODE_PREFIX = "KS";
|
private static final String CUSTOMER_CODE_PREFIX = "KS";
|
||||||
/**
|
/**
|
||||||
* 变更快照忽略字段:明细每次保存会重建主键/审计字段,不能作为“是否有修改”的依据
|
* 变更快照忽略字段:明细每次保存会重建主键/审计字段,不能作为“是否有修改”的依据
|
||||||
@@ -479,15 +482,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
|||||||
customer.setRegisteredAddress(buildRegisteredAddress(customer));
|
customer.setRegisteredAddress(buildRegisteredAddress(customer));
|
||||||
customer.setLegalPerson(trimToEmpty(customer.getLegalPerson()));
|
customer.setLegalPerson(trimToEmpty(customer.getLegalPerson()));
|
||||||
customer.setContactPhone(trimToEmpty(customer.getContactPhone()));
|
customer.setContactPhone(trimToEmpty(customer.getContactPhone()));
|
||||||
customer.setDeptIds(trimToNull(customer.getDeptIds()));
|
applyFixedOwnerDept(customer);
|
||||||
if (Func.isNotEmpty(customer.getDeptIds())) {
|
|
||||||
List<Long> deptIdList = Func.toLongList(customer.getDeptIds());
|
|
||||||
if (Func.isEmpty(deptIdList)) {
|
|
||||||
throw new ServiceException("所属组织不正确");
|
|
||||||
}
|
|
||||||
customer.setDeptId(deptIdList.get(0));
|
|
||||||
}
|
|
||||||
customer.setDeptName(trimToEmpty(customer.getDeptName()));
|
|
||||||
customer.setAccessType(Func.isEmpty(customer.getAccessType()) ? ACCESS_TEMPORARY : customer.getAccessType());
|
customer.setAccessType(Func.isEmpty(customer.getAccessType()) ? ACCESS_TEMPORARY : customer.getAccessType());
|
||||||
customer.setApprovalStatus(Func.isEmpty(customer.getApprovalStatus()) ? APPROVAL_DRAFT : customer.getApprovalStatus());
|
customer.setApprovalStatus(Func.isEmpty(customer.getApprovalStatus()) ? APPROVAL_DRAFT : customer.getApprovalStatus());
|
||||||
if (Func.isEmpty(customer.getStatus())) {
|
if (Func.isEmpty(customer.getStatus())) {
|
||||||
@@ -1628,6 +1623,25 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
|||||||
return trimToNull(fallbackAddress);
|
return trimToNull(fallbackAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客商所属组织固定为顶层「桂物物流集团」,忽略前端传入的其他组织。
|
||||||
|
*/
|
||||||
|
private void applyFixedOwnerDept(CustomerArchiveVO customer) {
|
||||||
|
customer.setDeptName(FIXED_OWNER_DEPT_NAME);
|
||||||
|
String tenantId = AuthUtil.getTenantId();
|
||||||
|
String deptIds = SysCache.getDeptIds(tenantId, FIXED_OWNER_DEPT_NAME);
|
||||||
|
if (Func.isEmpty(deptIds)) {
|
||||||
|
throw new ServiceException("未找到所属组织「" + FIXED_OWNER_DEPT_NAME + "」,请先维护组织数据");
|
||||||
|
}
|
||||||
|
List<Long> deptIdList = Func.toLongList(deptIds);
|
||||||
|
if (Func.isEmpty(deptIdList) || deptIdList.get(0) == null) {
|
||||||
|
throw new ServiceException("所属组织「" + FIXED_OWNER_DEPT_NAME + "」不正确");
|
||||||
|
}
|
||||||
|
Long deptId = deptIdList.get(0);
|
||||||
|
customer.setDeptId(deptId);
|
||||||
|
customer.setDeptIds(String.valueOf(deptId));
|
||||||
|
}
|
||||||
|
|
||||||
private String trimToEmpty(String value) {
|
private String trimToEmpty(String value) {
|
||||||
return value == null ? "" : value.trim();
|
return value == null ? "" : value.trim();
|
||||||
}
|
}
|
||||||
|
|||||||
-3
@@ -739,9 +739,6 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
|
|||||||
TransportBusinessSupport.validateRequired(projectApply.getCarrierNames(), "请选择下游承运商");
|
TransportBusinessSupport.validateRequired(projectApply.getCarrierNames(), "请选择下游承运商");
|
||||||
validateAmount(projectApply.getFundLimit(), "项目资金使用额度", false);
|
validateAmount(projectApply.getFundLimit(), "项目资金使用额度", false);
|
||||||
validateAmount(projectApply.getReceivableLimit(), "项目应收账款额度", false);
|
validateAmount(projectApply.getReceivableLimit(), "项目应收账款额度", false);
|
||||||
if (projectApply.getReceivableLimit() != null && projectApply.getFundLimit() != null && projectApply.getReceivableLimit().compareTo(projectApply.getFundLimit()) > 0) {
|
|
||||||
throw new ServiceException("项目应收账款额度不能超过项目资金使用额度");
|
|
||||||
}
|
|
||||||
validateDays(projectApply.getReceivableDays(), "应收账款回款期限");
|
validateDays(projectApply.getReceivableDays(), "应收账款回款期限");
|
||||||
validateDays(projectApply.getPaymentDays(), "回款账期");
|
validateDays(projectApply.getPaymentDays(), "回款账期");
|
||||||
validateAmount(projectApply.getProjectScale(), "项目规模", true);
|
validateAmount(projectApply.getProjectScale(), "项目规模", true);
|
||||||
|
|||||||
+5
-1
@@ -1926,7 +1926,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
|||||||
if (isRoadTransport(waybill.getTransportType())) {
|
if (isRoadTransport(waybill.getTransportType())) {
|
||||||
if ("承运商".equals(waybill.getCarrierType())) {
|
if ("承运商".equals(waybill.getCarrierType())) {
|
||||||
TransportBusinessSupport.validateRequired(waybill.getCarrierName(), "承运商不能为空");
|
TransportBusinessSupport.validateRequired(waybill.getCarrierName(), "承运商不能为空");
|
||||||
} else {
|
} else if (!isBatchImport(waybill)) {
|
||||||
TransportBusinessSupport.validateRequired(waybill.getDriverName(), "司机不能为空");
|
TransportBusinessSupport.validateRequired(waybill.getDriverName(), "司机不能为空");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2079,6 +2079,10 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
|||||||
return value.contains("公路") || value.contains("道路") || value.contains("road") || "gl".equals(value);
|
return value.contains("公路") || value.contains("道路") || value.contains("road") || "gl".equals(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isBatchImport(Waybill waybill) {
|
||||||
|
return waybill != null && TransportBusinessSupport.DATA_SOURCE_BATCH_IMPORT.equals(waybill.getDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
private void fillJsonFromFlatFields(Waybill waybill) {
|
private void fillJsonFromFlatFields(Waybill waybill) {
|
||||||
if (Func.isEmpty(waybill.getTaskEntryMode())) {
|
if (Func.isEmpty(waybill.getTaskEntryMode())) {
|
||||||
waybill.setTaskEntryMode("simple");
|
waybill.setTaskEntryMode("simple");
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- 机构表:记录 OA 的 modified(上次更新时间),用于增量同步比对
|
||||||
|
|
||||||
|
ALTER TABLE `blade_dept`
|
||||||
|
ADD COLUMN `oa_modified` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'OA上次更新时间(modified)' AFTER `oa_sup_sub_com_id`;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- 用户表:记录 OA 的 modified(上次更新时间),用于增量同步比对
|
||||||
|
|
||||||
|
ALTER TABLE `blade_user`
|
||||||
|
ADD COLUMN `oa_modified` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'OA上次更新时间(modified)' AFTER `is_oa`;
|
||||||
Reference in New Issue
Block a user