Compare commits

..

9 Commits

304 changed files with 17890 additions and 9820 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

2
.gitignore vendored
View File

@@ -84,8 +84,6 @@ logs/
ruoyi-ui/vue.config.js ruoyi-ui/vue.config.js
ruoyi-ui/dist.zip
*/src/test/ */src/test/
.pytest_cache/ .pytest_cache/

View File

@@ -51,7 +51,6 @@
"msg": "查询成功", "msg": "查询成功",
"rows": [ "rows": [
{ {
"id": 1002,
"recruitId": "REC20250205001", "recruitId": "REC20250205001",
"recruitName": "2025春季校园招聘", "recruitName": "2025春季校园招聘",
"posName": "Java开发工程师", "posName": "Java开发工程师",
@@ -81,19 +80,19 @@
### 1.2 查询招聘信息详情 ### 1.2 查询招聘信息详情
**接口描述:** 根据招聘信息主键ID查询详细信息 **接口描述:** 根据招聘项目编号查询详细信息
**请求方式:** `GET` **请求方式:** `GET`
**接口路径:** `/ccdi/staffRecruitment/{id}` **接口路径:** `/ccdi/staffRecruitment/{recruitId}`
**权限标识:** `ccdi:staffRecruitment:query` **权限标识:** `ccdi:staffRecruitment:query`
**路径参数:** **路径参数:**
| 参数名 | 类型 | 必填 | 说明 | 示例值 | | 参数名 | 类型 | 必填 | 说明 | 示例值 |
|------|------|----|--------------|-----| |-----------|--------|----|--------|----------------|
| id | Long | 是 | 招聘信息主键ID | 1002 | | recruitId | String | 是 | 招聘项目编号 | REC20250205001 |
**响应示例:** **响应示例:**
@@ -102,7 +101,6 @@
"code": 200, "code": 200,
"msg": "操作成功", "msg": "操作成功",
"data": { "data": {
"id": 1002,
"recruitId": "REC20250205001", "recruitId": "REC20250205001",
"recruitName": "2025春季校园招聘", "recruitName": "2025春季校园招聘",
"posName": "Java开发工程师", "posName": "Java开发工程师",
@@ -239,15 +237,15 @@
**请求方式:** `DELETE` **请求方式:** `DELETE`
**接口路径:** `/ccdi/staffRecruitment/{ids}` **接口路径:** `/ccdi/staffRecruitment/{recruitIds}`
**权限标识:** `ccdi:staffRecruitment:remove` **权限标识:** `ccdi:staffRecruitment:remove`
**路径参数:** **路径参数:**
| 参数名 | 类型 | 必填 | 说明 | 示例值 | | 参数名 | 类型 | 必填 | 说明 | 示例值 |
|------|------|----|-----------------------|----------| |------------|----------|----|------------------|-------------------------------|
| ids | Long[] | 是 | 招聘信息主键ID数组,多个用逗号分隔 | 1002,1003 | | recruitIds | String[] | 是 | 招聘项目编号数组,多个用逗号分隔 | REC20250205001,REC20250205002 |
**响应示例:** **响应示例:**
@@ -278,7 +276,7 @@
| 序号 | 字段名 | 说明 | 必填 | | 序号 | 字段名 | 说明 | 必填 |
|----|----------|-----------|----| |----|----------|-----------|----|
| 1 | 招聘项目编号 | 允许重复 | 是 | | 1 | 招聘项目编号 | 唯一标识 | 是 |
| 2 | 招聘项目名称 | - | 是 | | 2 | 招聘项目名称 | - | 是 |
| 3 | 职位名称 | - | 是 | | 3 | 职位名称 | - | 是 |
| 4 | 职位类别 | - | 是 | | 4 | 职位类别 | - | 是 |
@@ -328,7 +326,7 @@
```json ```json
{ {
"code": 500, "code": 500,
"msg": "很抱歉,导入完成!成功 8 条,失败 2 条,错误如下:<br/>1、招聘项目编号 REC001 导入失败:历史工作经历匹配到多条招聘主信息<br/>2、招聘项目编号 REC002 导入失败:证件号码格式不正确" "msg": "很抱歉,导入完成!成功 8 条,失败 2 条,错误如下:<br/>1、招聘项目编号 REC001 导入失败:该招聘项目编号已存在<br/>2、招聘项目编号 REC002 导入失败:证件号码格式不正确"
} }
``` ```
@@ -377,14 +375,14 @@ Excel导入导出对象,使用EasyExcel注解。
| 401 | 未授权,请先登录 | | 401 | 未授权,请先登录 |
| 403 | 无权限访问 | | 403 | 无权限访问 |
| 404 | 资源不存在 | | 404 | 资源不存在 |
| 409 | 数据冲突 | | 409 | 主键冲突 |
| 500 | 服务器内部错误 | | 500 | 服务器内部错误 |
### 常见业务错误 ### 常见业务错误
| 错误信息 | 说明 | | 错误信息 | 说明 |
|------------|--------------------| |------------|--------------------|
| 历史工作经历匹配到多条招聘主信息 | 招聘项目编号重复且候选人、项目名、职位名仍无法唯一匹配从表归属 | | 该招聘项目编号已存在 | 新增时recruitId重复 |
| 招聘项目编号不能为空 | recruitId字段为空 | | 招聘项目编号不能为空 | recruitId字段为空 |
| 证件号码格式不正确 | 身份证号格式验证失败 | | 证件号码格式不正确 | 身份证号格式验证失败 |
| 毕业年月格式不正确 | candGrad不是YYYYMM格式 | | 毕业年月格式不正确 | candGrad不是YYYYMM格式 |

View File

@@ -1,23 +1,22 @@
4.员工招聘信息表ccdi_staff_recruitment,,,,,, 4.员工招聘信息表ccdi_staff_recruitment,,,,,,
序号,字段名,类型,默认值,是否可为空,是否主键,注释 序号,字段名,类型,默认值,是否可为空,是否主键,注释
1,id,BIGINT,,,,主键ID 1,recruit_id,VARCHAR(32),,,,招聘项目编号
2,recruit_id,VARCHAR(32),,,,招聘项目编号(允许重复) 2,recruit_name,VARCHAR(100),,,,招聘项目名称
3,recruit_name,VARCHAR(100),,,,招聘项目名称 3,pos_name,VARCHAR(100),,,,职位名称
4,pos_name,VARCHAR(100),,,,职位名称 4,pos_category,VARCHAR(50),,,,职位类别
5,pos_category,VARCHAR(50),,,,职位类别 5,pos_desc,TEXT,,,,职位描述
6,pos_desc,TEXT,,,,职位描述 6,cand_name,VARCHAR(20),,,,应聘人员姓名
7,cand_name,VARCHAR(20),,,,应聘人员姓名 7,cand_edu,VARCHAR(20),,,,应聘人员学历
8,cand_edu,VARCHAR(20),,,,应聘人员学历 8,cand_id,VARCHAR(18),,,,应聘人员证件号码
9,cand_id,VARCHAR(18),,,,应聘人员证件号码 9,cand_school,VARCHAR(50),,,,应聘人员毕业院校
10,cand_school,VARCHAR(50),,,,应聘人员毕业院校 10,cand_major,VARCHAR(30),,,,应聘人员专业
11,cand_major,VARCHAR(30),,,,应聘人员专业 11,cand_grad,VARCHAR(6),,,,应聘人员毕业年月
12,cand_grad,VARCHAR(6),,,,应聘人员毕业年月 12,admit_status,VARCHAR(10),,,,记录录用情况:录用、未录用、放弃等
13,admit_status,VARCHAR(10),,,,记录录用情况:录用、未录用、放弃等 13,interviewer_name1,VARCHAR(20),,,,面试官1姓名
14,interviewer_name1,VARCHAR(20),,,,面试官1姓名 14,interviewer_id1,VARCHAR(10),,,,面试官1工号
15,interviewer_id1,VARCHAR(10),,,,面试官1工号 13,interviewer_name2,VARCHAR(20),,,,面试官2姓名
16,interviewer_name2,VARCHAR(20),,,,面试官2姓名 14,interviewer_id2,VARCHAR(10),,,,面试官2工号
17,interviewer_id2,VARCHAR(10),,,,面试官2工号 16,created_by,VARCHAR(20),-,,,记录创建人
18,created_by,VARCHAR(20),-,,,记录创建 17,updated_by,VARCHAR(20),-,,,记录更新
19,updated_by,VARCHAR(20),-,,,记录更新人 18,create_time,VARCHAR(10),0000-00-00,,,创建时间
20,create_time,VARCHAR(10),0000-00-00,,,创建时间 19,update_time,VARCHAR(10),0000-00-00,,,更新时间
21,update_time,VARCHAR(10),0000-00-00,,,更新时间
1 4.员工招聘信息表:ccdi_staff_recruitment
2 序号 字段名 类型 默认值 是否可为空 是否主键 注释
3 1 id recruit_id BIGINT VARCHAR(32) 主键ID 招聘项目编号
4 2 recruit_id recruit_name VARCHAR(32) VARCHAR(100) 招聘项目编号(允许重复) 招聘项目名称
5 3 recruit_name pos_name VARCHAR(100) 招聘项目名称 职位名称
6 4 pos_name pos_category VARCHAR(100) VARCHAR(50) 职位名称 职位类别
7 5 pos_category pos_desc VARCHAR(50) TEXT 职位类别 职位描述
8 6 pos_desc cand_name TEXT VARCHAR(20) 职位描述 应聘人员姓名
9 7 cand_name cand_edu VARCHAR(20) 应聘人员姓名 应聘人员学历
10 8 cand_edu cand_id VARCHAR(20) VARCHAR(18) 应聘人员学历 应聘人员证件号码
11 9 cand_id cand_school VARCHAR(18) VARCHAR(50) 应聘人员证件号码 应聘人员毕业院校
12 10 cand_school cand_major VARCHAR(50) VARCHAR(30) 应聘人员毕业院校 应聘人员专业
13 11 cand_major cand_grad VARCHAR(30) VARCHAR(6) 应聘人员专业 应聘人员毕业年月
14 12 cand_grad admit_status VARCHAR(6) VARCHAR(10) 应聘人员毕业年月 记录录用情况:录用、未录用、放弃等
15 13 admit_status interviewer_name1 VARCHAR(10) VARCHAR(20) 记录录用情况:录用、未录用、放弃等 面试官1姓名
16 14 interviewer_name1 interviewer_id1 VARCHAR(20) VARCHAR(10) 面试官1姓名 面试官1工号
17 15 13 interviewer_id1 interviewer_name2 VARCHAR(10) VARCHAR(20) 面试官1工号 面试官2姓名
18 16 14 interviewer_name2 interviewer_id2 VARCHAR(20) VARCHAR(10) 面试官2姓名 面试官2工号
19 17 16 interviewer_id2 created_by VARCHAR(10) VARCHAR(20) - 面试官2工号 记录创建人
20 18 17 created_by updated_by VARCHAR(20) - 记录创建人 记录更新人
21 19 18 updated_by create_time VARCHAR(20) VARCHAR(10) - 0000-00-00 记录更新人 创建时间
22 20 19 create_time update_time VARCHAR(10) 0000-00-00 创建时间 更新时间
21 update_time VARCHAR(10) 0000-00-00 更新时间

View File

@@ -1,3 +0,0 @@
关系图谱http://64.202.65.112:8082/atlas/refactor/#/home/graph/downloadService?id=lanxitest&mode=K_EXPAND&type=NORMAL&atlasToken=2C914E5E1FBFBC4AD15163E0AB03B800&params={"vId":"rel_node/15942f5b84bada01ccd25f5e5678ac22"}
资金流图谱http://64.202.65.112:8082/atlas/refactor/#/home/graph/downloadService?id=ccdi_lanxi_trans&mode=K_EXPAND&type=NORMAL&atlasToken=F4BBA291A285858BAF4526C6EC312388&params={"vId":"idno_node/f2f797081494c5c0555a3bbf0f57c5e7"}

View File

@@ -7,6 +7,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel; import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel; import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.vo.*; import com.ruoyi.info.collection.domain.vo.*;
import com.ruoyi.info.collection.service.ICcdiBaseStaffAssetImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService; import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffService; import com.ruoyi.info.collection.service.ICcdiBaseStaffService;
import com.ruoyi.info.collection.utils.EasyExcelUtil; import com.ruoyi.info.collection.utils.EasyExcelUtil;
@@ -46,6 +47,9 @@ public class CcdiBaseStaffController extends BaseController {
@Resource @Resource
private ICcdiBaseStaffImportService importAsyncService; private ICcdiBaseStaffImportService importAsyncService;
@Resource
private ICcdiBaseStaffAssetImportService baseStaffAssetImportService;
/** /**
* 查询员工列表 * 查询员工列表
*/ */
@@ -157,7 +161,14 @@ public class CcdiBaseStaffController extends BaseController {
return error("至少需要一条数据"); return error("至少需要一条数据");
} }
BaseStaffImportSubmitResultVO result = baseStaffService.importBaseStaffWithAssets(staffList, assetList); BaseStaffImportSubmitResultVO result = new BaseStaffImportSubmitResultVO();
if (hasStaffRows) {
result.setStaffTaskId(baseStaffService.importBaseStaff(staffList));
}
if (hasAssetRows) {
result.setAssetTaskId(baseStaffAssetImportService.importAssetInfo(assetList));
}
result.setMessage(buildImportSubmitMessage(hasStaffRows, hasAssetRows));
return AjaxResult.success("导入任务已提交,正在后台处理", result); return AjaxResult.success("导入任务已提交,正在后台处理", result);
} }
@@ -204,4 +215,13 @@ public class CcdiBaseStaffController extends BaseController {
return getDataTable(pageData, failures.size()); return getDataTable(pageData, failures.size());
} }
private String buildImportSubmitMessage(boolean hasStaffRows, boolean hasAssetRows) {
if (hasStaffRows && hasAssetRows) {
return "已提交员工信息和员工资产信息导入任务";
}
if (hasStaffRows) {
return "已提交员工信息导入任务";
}
return "已提交员工资产信息导入任务";
}
} }

View File

@@ -10,6 +10,7 @@ import com.ruoyi.info.collection.domain.vo.CcdiStaffFmyRelationVO;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportFailureVO; import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportFailureVO;
import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportSubmitResultVO; import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportSubmitResultVO;
import com.ruoyi.info.collection.service.ICcdiAssetInfoImportService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationImportService; import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationImportService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationService; import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationService;
import com.ruoyi.info.collection.utils.EasyExcelUtil; import com.ruoyi.info.collection.utils.EasyExcelUtil;
@@ -50,6 +51,9 @@ public class CcdiStaffFmyRelationController extends BaseController {
@Resource @Resource
private ICcdiStaffFmyRelationImportService relationImportService; private ICcdiStaffFmyRelationImportService relationImportService;
@Resource
private ICcdiAssetInfoImportService assetInfoImportService;
/** /**
* 查询员工亲属关系列表 * 查询员工亲属关系列表
*/ */
@@ -153,7 +157,15 @@ public class CcdiStaffFmyRelationController extends BaseController {
return error("至少需要一条数据"); return error("至少需要一条数据");
} }
StaffFmyRelationImportSubmitResultVO result = relationService.importRelationWithAssets(relationList, assetList); StaffFmyRelationImportSubmitResultVO result = new StaffFmyRelationImportSubmitResultVO();
if (hasRelationRows) {
result.setRelationTaskId(relationService.importRelation(relationList));
}
if (hasAssetRows) {
result.setAssetTaskId(assetInfoImportService.importAssetInfo(assetList));
}
result.setMessage(buildImportSubmitMessage(hasRelationRows, hasAssetRows));
return AjaxResult.success("导入任务已提交,正在后台处理", result); return AjaxResult.success("导入任务已提交,正在后台处理", result);
} }
@@ -199,4 +211,13 @@ public class CcdiStaffFmyRelationController extends BaseController {
return getDataTable(pageData, failures.size()); return getDataTable(pageData, failures.size());
} }
private String buildImportSubmitMessage(boolean hasRelationRows, boolean hasAssetRows) {
if (hasRelationRows && hasAssetRows) {
return "已提交员工亲属关系和亲属资产信息导入任务";
}
if (hasRelationRows) {
return "已提交员工亲属关系导入任务";
}
return "已提交亲属资产信息导入任务";
}
} }

View File

@@ -69,9 +69,9 @@ public class CcdiStaffRecruitmentController extends BaseController {
*/ */
@Operation(summary = "获取招聘信息详细信息") @Operation(summary = "获取招聘信息详细信息")
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:query')") @PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:query')")
@GetMapping(value = "/{id}") @GetMapping(value = "/{recruitId}")
public AjaxResult getInfo(@PathVariable Long id) { public AjaxResult getInfo(@PathVariable String recruitId) {
return success(recruitmentService.selectRecruitmentById(id)); return success(recruitmentService.selectRecruitmentById(recruitId));
} }
/** /**
@@ -102,9 +102,9 @@ public class CcdiStaffRecruitmentController extends BaseController {
@Operation(summary = "删除招聘信息") @Operation(summary = "删除招聘信息")
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:remove')") @PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:remove')")
@Log(title = "员工招聘信息", businessType = BusinessType.DELETE) @Log(title = "员工招聘信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}") @DeleteMapping("/{recruitIds}")
public AjaxResult remove(@PathVariable Long[] ids) { public AjaxResult remove(@PathVariable String[] recruitIds) {
return toAjax(recruitmentService.deleteRecruitmentByIds(ids)); return toAjax(recruitmentService.deleteRecruitmentByIds(recruitIds));
} }
/** /**

View File

@@ -94,6 +94,6 @@ public class CcdiEnterpriseBaseInfo implements Serializable {
/** 风险等级1-高风险, 2-中风险, 3-低风险 */ /** 风险等级1-高风险, 2-中风险, 3-低风险 */
private String riskLevel; private String riskLevel;
/** 企业来源GENERAL-一般企业, EMP_RELATION-员工关系人, CREDIT_CUSTOMER-信贷客户, SUPPLIER-供应商, INTERMEDIARY-中介, BOTH-兼有 */ /** 企业来源GENERAL-一般企业, EMP_RELATION-员工关系人, CREDIT_CUSTOMER-信贷客户, INTERMEDIARY-中介, BOTH-兼有 */
private String entSource; private String entSource;
} }

View File

@@ -22,11 +22,8 @@ public class CcdiStaffRecruitment implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 主键ID */
@TableId(type = IdType.AUTO)
private Long id;
/** 招聘记录编号 */ /** 招聘记录编号 */
@TableId(type = IdType.INPUT)
private String recruitId; private String recruitId;
/** 招聘项目名称 */ /** 招聘项目名称 */

View File

@@ -28,9 +28,6 @@ public class CcdiStaffRecruitmentWork implements Serializable {
@TableId(type = IdType.AUTO) @TableId(type = IdType.AUTO)
private Long id; private Long id;
/** 关联招聘信息主键ID */
private Long recruitmentId;
/** 关联招聘记录编号 */ /** 关联招聘记录编号 */
private String recruitId; private String recruitId;

View File

@@ -33,10 +33,6 @@ public class CcdiCustFmyRelationQueryDTO implements Serializable {
@Schema(description = "关系人姓名") @Schema(description = "关系人姓名")
private String relationName; private String relationName;
/** 关系人身份证号 */
@Schema(description = "关系人身份证号")
private String relationCertNo;
/** 状态 */ /** 状态 */
@Schema(description = "状态0-无效1-有效") @Schema(description = "状态0-无效1-有效")
private Integer status; private Integer status;

View File

@@ -37,10 +37,6 @@ public class CcdiStaffFmyRelationQueryDTO implements Serializable {
@Schema(description = "关系人姓名") @Schema(description = "关系人姓名")
private String relationName; private String relationName;
/** 关系人身份证号 */
@Schema(description = "关系人身份证号")
private String relationCertNo;
/** 状态 */ /** 状态 */
@Schema(description = "状态0-无效1-有效") @Schema(description = "状态0-无效1-有效")
private Integer status; private Integer status;

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.dto;
import com.ruoyi.info.collection.annotation.EnumValid; import com.ruoyi.info.collection.annotation.EnumValid;
import com.ruoyi.info.collection.enums.AdmitStatus; import com.ruoyi.info.collection.enums.AdmitStatus;
import com.ruoyi.info.collection.enums.RecruitType; import com.ruoyi.info.collection.enums.RecruitType;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
@@ -11,7 +10,6 @@ import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
* 员工招聘信息新增DTO * 员工招聘信息新增DTO
@@ -104,8 +102,4 @@ public class CcdiStaffRecruitmentAddDTO implements Serializable {
/** 面试官2工号 */ /** 面试官2工号 */
@Size(max = 10, message = "面试官2工号长度不能超过10个字符") @Size(max = 10, message = "面试官2工号长度不能超过10个字符")
private String interviewerId2; private String interviewerId2;
/** 历史工作经历列表 */
@Valid
private List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList;
} }

View File

@@ -26,13 +26,8 @@ public class CcdiStaffRecruitmentEditDTO implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 主键ID */
@NotNull(message = "招聘信息ID不能为空")
private Long id;
/** 招聘记录编号 */ /** 招聘记录编号 */
@NotBlank(message = "招聘记录编号不能为空") @NotNull(message = "招聘记录编号不能为空")
@Size(max = 32, message = "招聘记录编号长度不能超过32个字符")
private String recruitId; private String recruitId;
/** 招聘项目名称 */ /** 招聘项目名称 */

View File

@@ -2,7 +2,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -26,7 +25,6 @@ public class CcdiAccountInfoExcel implements Serializable {
@ExcelProperty(value = "证件号*", index = 1) @ExcelProperty(value = "证件号*", index = 1)
@ColumnWidth(24) @ColumnWidth(24)
@TextFormat
private String ownerId; private String ownerId;
@ExcelProperty(value = "账户姓名*", index = 2) @ExcelProperty(value = "账户姓名*", index = 2)
@@ -35,7 +33,6 @@ public class CcdiAccountInfoExcel implements Serializable {
@ExcelProperty(value = "账户号码*", index = 3) @ExcelProperty(value = "账户号码*", index = 3)
@ColumnWidth(28) @ColumnWidth(28)
@TextFormat
private String accountNo; private String accountNo;
@ExcelProperty(value = "账户类型*", index = 4) @ExcelProperty(value = "账户类型*", index = 4)
@@ -52,7 +49,6 @@ public class CcdiAccountInfoExcel implements Serializable {
@ExcelProperty(value = "银行代码", index = 7) @ExcelProperty(value = "银行代码", index = 7)
@ColumnWidth(16) @ColumnWidth(16)
@TextFormat
private String bankCode; private String bankCode;
@ExcelProperty(value = "币种", index = 8) @ExcelProperty(value = "币种", index = 8)

View File

@@ -26,14 +26,14 @@ public class CcdiBaseStaffAssetInfoExcel implements Serializable {
/** 员工身份证号 */ /** 员工身份证号 */
@ExcelProperty(value = "员工身份证号*", index = 0) @ExcelProperty(value = "员工身份证号*", index = 0)
@ColumnWidth(24) @ColumnWidth(22)
@Required @Required
@TextFormat @TextFormat
private String personId; private String personId;
/** 资产大类 */ /** 资产大类 */
@ExcelProperty(value = "资产大类*", index = 1) @ExcelProperty(value = "资产大类*", index = 1)
@ColumnWidth(18) @ColumnWidth(16)
@Required @Required
private String assetMainType; private String assetMainType;
@@ -51,39 +51,39 @@ public class CcdiBaseStaffAssetInfoExcel implements Serializable {
/** 产权占比 */ /** 产权占比 */
@ExcelProperty(value = "产权占比", index = 4) @ExcelProperty(value = "产权占比", index = 4)
@ColumnWidth(14) @ColumnWidth(12)
private BigDecimal ownershipRatio; private BigDecimal ownershipRatio;
/** 购买/评估日期 */ /** 购买/评估日期 */
@ExcelProperty(value = "购买/评估日期", index = 5) @ExcelProperty(value = "购买/评估日期", index = 5)
@ColumnWidth(20) @ColumnWidth(16)
private Date purchaseEvalDate; private Date purchaseEvalDate;
/** 资产原值 */ /** 资产原值 */
@ExcelProperty(value = "资产原值", index = 6) @ExcelProperty(value = "资产原值", index = 6)
@ColumnWidth(18) @ColumnWidth(16)
private BigDecimal originalValue; private BigDecimal originalValue;
/** 当前估值 */ /** 当前估值 */
@ExcelProperty(value = "当前估值*", index = 7) @ExcelProperty(value = "当前估值*", index = 7)
@ColumnWidth(18) @ColumnWidth(16)
@Required @Required
private BigDecimal currentValue; private BigDecimal currentValue;
/** 估值截止日期 */ /** 估值截止日期 */
@ExcelProperty(value = "估值截止日期", index = 8) @ExcelProperty(value = "估值截止日期", index = 8)
@ColumnWidth(20) @ColumnWidth(16)
private Date valuationDate; private Date valuationDate;
/** 资产状态 */ /** 资产状态 */
@ExcelProperty(value = "资产状态*", index = 9) @ExcelProperty(value = "资产状态*", index = 9)
@ColumnWidth(16) @ColumnWidth(14)
@DictDropdown(dictType = "ccdi_asset_status") @DictDropdown(dictType = "ccdi_asset_status")
@Required @Required
private String assetStatus; private String assetStatus;
/** 备注 */ /** 备注 */
@ExcelProperty(value = "备注", index = 10) @ExcelProperty(value = "备注", index = 10)
@ColumnWidth(32) @ColumnWidth(28)
private String remarks; private String remarks;
} }

View File

@@ -4,7 +4,6 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -26,56 +25,54 @@ public class CcdiBaseStaffExcel implements Serializable {
/** 姓名 */ /** 姓名 */
@ExcelProperty(value = "姓名", index = 0) @ExcelProperty(value = "姓名", index = 0)
@ColumnWidth(16) @ColumnWidth(15)
@Required @Required
private String name; private String name;
/** 员工ID */ /** 员工ID */
@ExcelProperty(value = "员工ID", index = 1) @ExcelProperty(value = "员工ID", index = 1)
@ColumnWidth(18) @ColumnWidth(15)
@Required @Required
private Long staffId; private Long staffId;
/** 所属部门ID */ /** 所属部门ID */
@ExcelProperty(value = "所属部门ID", index = 2) @ExcelProperty(value = "所属部门ID", index = 2)
@ColumnWidth(20) @ColumnWidth(15)
@Required @Required
private Long deptId; private Long deptId;
/** 身份证号 */ /** 身份证号 */
@ExcelProperty(value = "身份证号", index = 3) @ExcelProperty(value = "身份证号", index = 3)
@ColumnWidth(24) @ColumnWidth(20)
@Required @Required
@TextFormat
private String idCard; private String idCard;
/** 电话 */ /** 电话 */
@ExcelProperty(value = "电话", index = 4) @ExcelProperty(value = "电话", index = 4)
@ColumnWidth(18) @ColumnWidth(15)
@Required @Required
@TextFormat
private String phone; private String phone;
/** 年收入 */ /** 年收入 */
@ExcelProperty(value = "年收入(元/年)", index = 5) @ExcelProperty(value = "年收入(元/年)", index = 5)
@ColumnWidth(20) @ColumnWidth(18)
private BigDecimal annualIncome; private BigDecimal annualIncome;
/** 入职时间 */ /** 入职时间 */
@ExcelProperty(value = "入职时间", index = 6) @ExcelProperty(value = "入职时间", index = 6)
@ColumnWidth(18) @ColumnWidth(15)
private Date hireDate; private Date hireDate;
/** 是否党员 */ /** 是否党员 */
@ExcelProperty(value = "是否党员", index = 7) @ExcelProperty(value = "是否党员", index = 7)
@ColumnWidth(16) @ColumnWidth(12)
@DictDropdown(dictType = "ccdi_yes_no_flag") @DictDropdown(dictType = "ccdi_yes_no_flag")
@Required @Required
private Integer partyMember; private Integer partyMember;
/** 状态 */ /** 状态 */
@ExcelProperty(value = "状态", index = 8) @ExcelProperty(value = "状态", index = 8)
@ColumnWidth(14) @ColumnWidth(10)
@DictDropdown(dictType = "ccdi_employee_status") @DictDropdown(dictType = "ccdi_employee_status")
@Required @Required
private String status; private String status;

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -27,7 +26,6 @@ public class CcdiCustEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "身份证号", index = 0) @ExcelProperty(value = "身份证号", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
@Schema(description = "身份证号") @Schema(description = "身份证号")
private String personId; private String personId;
@@ -35,7 +33,6 @@ public class CcdiCustEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "统一社会信用代码", index = 1) @ExcelProperty(value = "统一社会信用代码", index = 1)
@ColumnWidth(25) @ColumnWidth(25)
@Required @Required
@TextFormat
@Schema(description = "统一社会信用代码") @Schema(description = "统一社会信用代码")
private String socialCreditCode; private String socialCreditCode;

View File

@@ -4,7 +4,6 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -27,7 +26,6 @@ public class CcdiCustFmyRelationExcel implements Serializable {
@ExcelProperty(value = "信贷客户身份证号*", index = 0) @ExcelProperty(value = "信贷客户身份证号*", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String personId; private String personId;
/** 关系类型 */ /** 关系类型 */
@@ -65,19 +63,16 @@ public class CcdiCustFmyRelationExcel implements Serializable {
@ExcelProperty(value = "关系人证件号码*", index = 6) @ExcelProperty(value = "关系人证件号码*", index = 6)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String relationCertNo; private String relationCertNo;
/** 手机号码1 */ /** 手机号码1 */
@ExcelProperty(value = "手机号码1", index = 7) @ExcelProperty(value = "手机号码1", index = 7)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String mobilePhone1; private String mobilePhone1;
/** 手机号码2 */ /** 手机号码2 */
@ExcelProperty(value = "手机号码2", index = 8) @ExcelProperty(value = "手机号码2", index = 8)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String mobilePhone2; private String mobilePhone2;
/** 微信名称1 */ /** 微信名称1 */

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -24,7 +23,6 @@ public class CcdiEnterpriseBaseInfoExcel implements Serializable {
@ExcelProperty(value = "统一社会信用代码*", index = 0) @ExcelProperty(value = "统一社会信用代码*", index = 0)
@ColumnWidth(24) @ColumnWidth(24)
@TextFormat
private String socialCreditCode; private String socialCreditCode;
@ExcelProperty(value = "企业名称*", index = 1) @ExcelProperty(value = "企业名称*", index = 1)
@@ -68,7 +66,6 @@ public class CcdiEnterpriseBaseInfoExcel implements Serializable {
@ExcelProperty(value = "法定代表人证件号码", index = 10) @ExcelProperty(value = "法定代表人证件号码", index = 10)
@ColumnWidth(24) @ColumnWidth(24)
@TextFormat
private String legalCertNo; private String legalCertNo;
@ExcelProperty(value = "股东1", index = 11) @ExcelProperty(value = "股东1", index = 11)

View File

@@ -2,8 +2,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -19,21 +17,17 @@ public class CcdiIntermediaryEnterpriseRelationExcel implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 中介本人证件号码 */ /** 中介本人证件号码 */
@ExcelProperty(value = "中介本人证件号码", index = 0) @ExcelProperty(value = "中介本人证件号码*", index = 0)
@ColumnWidth(24) @ColumnWidth(24)
@Required
@TextFormat
private String ownerPersonId; private String ownerPersonId;
/** 统一社会信用代码 */ /** 统一社会信用代码 */
@ExcelProperty(value = "统一社会信用代码", index = 1) @ExcelProperty(value = "统一社会信用代码*", index = 1)
@ColumnWidth(24) @ColumnWidth(24)
@Required
@TextFormat
private String socialCreditCode; private String socialCreditCode;
/** 关联职务 */ /** 关联职务 */
@ExcelProperty(value = "关联职务", index = 2) @ExcelProperty(value = "关联职务", index = 2)
@ColumnWidth(20) @ColumnWidth(20)
private String relationPersonPost; private String relationPersonPost;

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -30,7 +29,6 @@ public class CcdiIntermediaryEntityExcel implements Serializable {
/** 统一社会信用代码 */ /** 统一社会信用代码 */
@ExcelProperty(value = "统一社会信用代码*", index = 1) @ExcelProperty(value = "统一社会信用代码*", index = 1)
@ColumnWidth(20) @ColumnWidth(20)
@TextFormat
private String socialCreditCode; private String socialCreditCode;
/** 主体类型 */ /** 主体类型 */
@@ -79,7 +77,6 @@ public class CcdiIntermediaryEntityExcel implements Serializable {
/** 法定代表人证件号码 */ /** 法定代表人证件号码 */
@ExcelProperty(value = "法定代表人证件号码", index = 10) @ExcelProperty(value = "法定代表人证件号码", index = 10)
@ColumnWidth(20) @ColumnWidth(20)
@TextFormat
private String legalCertNo; private String legalCertNo;
/** 股东1 */ /** 股东1 */

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -53,13 +52,11 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
/** 证件号码 */ /** 证件号码 */
@ExcelProperty(value = "证件号码*", index = 5) @ExcelProperty(value = "证件号码*", index = 5)
@ColumnWidth(20) @ColumnWidth(20)
@TextFormat
private String personId; private String personId;
/** 手机号码 */ /** 手机号码 */
@ExcelProperty(value = "手机号码", index = 6) @ExcelProperty(value = "手机号码", index = 6)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String mobile; private String mobile;
/** 微信号 */ /** 微信号 */
@@ -80,7 +77,6 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
/** 企业统一信用码 */ /** 企业统一信用码 */
@ExcelProperty(value = "企业统一信用码", index = 10) @ExcelProperty(value = "企业统一信用码", index = 10)
@ColumnWidth(20) @ColumnWidth(20)
@TextFormat
private String socialCreditCode; private String socialCreditCode;
/** 职位 */ /** 职位 */
@@ -91,7 +87,6 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
/** 关联中介本人证件号码 */ /** 关联中介本人证件号码 */
@ExcelProperty(value = "关联中介本人证件号码", index = 12) @ExcelProperty(value = "关联中介本人证件号码", index = 12)
@ColumnWidth(24) @ColumnWidth(24)
@TextFormat
private String relatedNumId; private String relatedNumId;
/** 备注 */ /** 备注 */

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -27,7 +26,6 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
@ExcelProperty(value = "采购事项ID", index = 0) @ExcelProperty(value = "采购事项ID", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String purchaseId; private String purchaseId;
/** 采购类别 */ /** 采购类别 */
@@ -140,7 +138,6 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
@ExcelProperty(value = "申请人工号", index = 21) @ExcelProperty(value = "申请人工号", index = 21)
@ColumnWidth(15) @ColumnWidth(15)
@Required @Required
@TextFormat
private String applicantId; private String applicantId;
/** 申请人姓名 */ /** 申请人姓名 */
@@ -158,7 +155,6 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
/** 采购负责人工号 */ /** 采购负责人工号 */
@ExcelProperty(value = "采购负责人工号", index = 24) @ExcelProperty(value = "采购负责人工号", index = 24)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String purchaseLeaderId; private String purchaseLeaderId;
/** 采购负责人姓名 */ /** 采购负责人姓名 */

View File

@@ -4,7 +4,6 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -22,7 +21,6 @@ public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
@ExcelProperty(value = "采购事项ID", index = 0) @ExcelProperty(value = "采购事项ID", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String purchaseId; private String purchaseId;
@ExcelProperty(value = "供应商名称", index = 1) @ExcelProperty(value = "供应商名称", index = 1)
@@ -32,7 +30,6 @@ public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
@ExcelProperty(value = "供应商统一信用代码", index = 2) @ExcelProperty(value = "供应商统一信用代码", index = 2)
@ColumnWidth(25) @ColumnWidth(25)
@TextFormat
private String supplierUscc; private String supplierUscc;
@ExcelProperty(value = "供应商联系人", index = 3) @ExcelProperty(value = "供应商联系人", index = 3)
@@ -41,12 +38,10 @@ public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
@ExcelProperty(value = "供应商联系电话", index = 4) @ExcelProperty(value = "供应商联系电话", index = 4)
@ColumnWidth(18) @ColumnWidth(18)
@TextFormat
private String contactPhone; private String contactPhone;
@ExcelProperty(value = "供应商银行账户", index = 5) @ExcelProperty(value = "供应商银行账户", index = 5)
@ColumnWidth(20) @ColumnWidth(20)
@TextFormat
private String supplierBankAccount; private String supplierBankAccount;
@ExcelProperty(value = "是否中标", index = 6) @ExcelProperty(value = "是否中标", index = 6)

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -27,7 +26,6 @@ public class CcdiStaffEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "亲属身份证号", index = 0) @ExcelProperty(value = "亲属身份证号", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
@Schema(description = "亲属身份证号") @Schema(description = "亲属身份证号")
private String personId; private String personId;
@@ -35,7 +33,6 @@ public class CcdiStaffEnterpriseRelationExcel implements Serializable {
@ExcelProperty(value = "统一社会信用代码", index = 1) @ExcelProperty(value = "统一社会信用代码", index = 1)
@ColumnWidth(25) @ColumnWidth(25)
@Required @Required
@TextFormat
@Schema(description = "统一社会信用代码") @Schema(description = "统一社会信用代码")
private String socialCreditCode; private String socialCreditCode;

View File

@@ -28,7 +28,6 @@ public class CcdiStaffFmyRelationExcel implements Serializable {
@ExcelProperty(value = "员工身份证号*", index = 0) @ExcelProperty(value = "员工身份证号*", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String personId; private String personId;
/** 关系类型 */ /** 关系类型 */
@@ -72,13 +71,11 @@ public class CcdiStaffFmyRelationExcel implements Serializable {
/** 手机号码1 */ /** 手机号码1 */
@ExcelProperty(value = "手机号码1", index = 7) @ExcelProperty(value = "手机号码1", index = 7)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String mobilePhone1; private String mobilePhone1;
/** 手机号码2 */ /** 手机号码2 */
@ExcelProperty(value = "手机号码2", index = 8) @ExcelProperty(value = "手机号码2", index = 8)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String mobilePhone2; private String mobilePhone2;
/** 家庭成员年收入 */ /** 家庭成员年收入 */

View File

@@ -4,7 +4,6 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.DictDropdown; import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -22,11 +21,10 @@ public class CcdiStaffRecruitmentExcel implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 招聘记录编号 */ /** 招聘项目编号 */
@ExcelProperty(value = "招聘记录编号", index = 0) @ExcelProperty(value = "招聘项目编号", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String recruitId; private String recruitId;
/** 招聘项目名称 */ /** 招聘项目名称 */
@@ -53,76 +51,66 @@ public class CcdiStaffRecruitmentExcel implements Serializable {
@Required @Required
private String posDesc; private String posDesc;
/** 录用情况 */ /** 应聘人员姓名 */
@ExcelProperty(value = "录用情况", index = 5) @ExcelProperty(value = "应聘人员姓名", index = 5)
@ColumnWidth(10)
@DictDropdown(dictType = "ccdi_admit_status")
@Required
private String admitStatus;
/** 候选人姓名 */
@ExcelProperty(value = "候选人姓名", index = 6)
@ColumnWidth(15) @ColumnWidth(15)
@Required @Required
private String candName; private String candName;
/** 招聘类型 */
@ExcelProperty(value = "招聘类型", index = 7)
@ColumnWidth(12)
@DictDropdown(dictType = "ccdi_recruit_type")
@Required
private String recruitType;
/** 应聘人员学历 */ /** 应聘人员学历 */
@ExcelProperty(value = "学历", index = 8) @ExcelProperty(value = "应聘人员学历", index = 6)
@ColumnWidth(15) @ColumnWidth(15)
@Required @Required
private String candEdu; private String candEdu;
/** 应聘人员证件号码 */ /** 应聘人员证件号码 */
@ExcelProperty(value = "证件号码", index = 9) @ExcelProperty(value = "应聘人员证件号码", index = 7)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String candId; private String candId;
/** 应聘人员毕业年月 */
@ExcelProperty(value = "毕业年月", index = 10)
@ColumnWidth(15)
@Required
private String candGrad;
/** 应聘人员毕业院校 */ /** 应聘人员毕业院校 */
@ExcelProperty(value = "毕业院校", index = 11) @ExcelProperty(value = "应聘人员毕业院校", index = 8)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
private String candSchool; private String candSchool;
/** 应聘人员专业 */ /** 应聘人员专业 */
@ExcelProperty(value = "专业", index = 12) @ExcelProperty(value = "应聘人员专业", index = 9)
@ColumnWidth(15) @ColumnWidth(15)
@Required @Required
private String candMajor; private String candMajor;
/** 应聘人员毕业年月 */
@ExcelProperty(value = "应聘人员毕业年月", index = 10)
@ColumnWidth(15)
@Required
private String candGrad;
/** 录用情况 */
@ExcelProperty(value = "录用情况", index = 11)
@ColumnWidth(10)
@DictDropdown(dictType = "ccdi_admit_status")
@Required
private String admitStatus;
/** 面试官1姓名 */ /** 面试官1姓名 */
@ExcelProperty(value = "面试官1姓名", index = 13) @ExcelProperty(value = "面试官1姓名", index = 12)
@ColumnWidth(15) @ColumnWidth(15)
private String interviewerName1; private String interviewerName1;
/** 面试官1工号 */ /** 面试官1工号 */
@ExcelProperty(value = "面试官1工号", index = 14) @ExcelProperty(value = "面试官1工号", index = 13)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String interviewerId1; private String interviewerId1;
/** 面试官2姓名 */ /** 面试官2姓名 */
@ExcelProperty(value = "面试官2姓名", index = 15) @ExcelProperty(value = "面试官2姓名", index = 14)
@ColumnWidth(15) @ColumnWidth(15)
private String interviewerName2; private String interviewerName2;
/** 面试官2工号 */ /** 面试官2工号 */
@ExcelProperty(value = "面试官2工号", index = 16) @ExcelProperty(value = "面试官2工号", index = 15)
@ColumnWidth(15) @ColumnWidth(15)
@TextFormat
private String interviewerId2; private String interviewerId2;
} }

View File

@@ -3,7 +3,6 @@ package com.ruoyi.info.collection.domain.excel;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import com.ruoyi.common.annotation.TextFormat;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@@ -25,7 +24,6 @@ public class CcdiStaffRecruitmentWorkExcel implements Serializable {
@ExcelProperty(value = "招聘记录编号", index = 0) @ExcelProperty(value = "招聘记录编号", index = 0)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
@TextFormat
private String recruitId; private String recruitId;
/** 候选人姓名 */ /** 候选人姓名 */
@@ -63,20 +61,20 @@ public class CcdiStaffRecruitmentWorkExcel implements Serializable {
@ColumnWidth(18) @ColumnWidth(18)
private String departmentName; private String departmentName;
/** 岗位名称 */ /** 岗位 */
@ExcelProperty(value = "岗位名称", index = 7) @ExcelProperty(value = "岗位", index = 7)
@ColumnWidth(20) @ColumnWidth(20)
@Required @Required
private String positionName; private String positionName;
/** 入职年月 */ /** 入职年月 */
@ExcelProperty(value = "入职时间", index = 8) @ExcelProperty(value = "入职年月", index = 8)
@ColumnWidth(12) @ColumnWidth(12)
@Required @Required
private String jobStartMonth; private String jobStartMonth;
/** 离职年月 */ /** 离职年月 */
@ExcelProperty(value = "离职时间", index = 9) @ExcelProperty(value = "离职年月", index = 9)
@ColumnWidth(12) @ColumnWidth(12)
private String jobEndMonth; private String jobEndMonth;
@@ -85,8 +83,8 @@ public class CcdiStaffRecruitmentWorkExcel implements Serializable {
@ColumnWidth(30) @ColumnWidth(30)
private String departureReason; private String departureReason;
/** 主要工作内容 */ /** 工作内容 */
@ExcelProperty(value = "主要工作内容", index = 11) @ExcelProperty(value = "工作内容", index = 11)
@ColumnWidth(35) @ColumnWidth(35)
private String workContent; private String workContent;

View File

@@ -19,9 +19,6 @@ public class CcdiStaffRecruitmentVO implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 招聘记录编号 */ /** 招聘记录编号 */
private String recruitId; private String recruitId;

View File

@@ -22,7 +22,7 @@ public class IntermediaryEnterpriseRelationImportFailureVO implements Serializab
@Schema(description = "统一社会信用代码") @Schema(description = "统一社会信用代码")
private String socialCreditCode; private String socialCreditCode;
@Schema(description = "关联职务") @Schema(description = "关联职务")
private String relationPersonPost; private String relationPersonPost;
@Schema(description = "备注") @Schema(description = "备注")

View File

@@ -10,7 +10,6 @@ public enum EnterpriseSource {
GENERAL("GENERAL", "一般企业"), GENERAL("GENERAL", "一般企业"),
EMP_RELATION("EMP_RELATION", "员工关系人"), EMP_RELATION("EMP_RELATION", "员工关系人"),
CREDIT_CUSTOMER("CREDIT_CUSTOMER", "信贷客户"), CREDIT_CUSTOMER("CREDIT_CUSTOMER", "信贷客户"),
SUPPLIER("SUPPLIER", "供应商"),
INTERMEDIARY("INTERMEDIARY", "中介"), INTERMEDIARY("INTERMEDIARY", "中介"),
BOTH("BOTH", "兼有"); BOTH("BOTH", "兼有");

View File

@@ -1,28 +1,15 @@
package com.ruoyi.info.collection.handler; package com.ruoyi.info.collection.handler;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.ruoyi.common.annotation.Required; import com.ruoyi.common.annotation.Required;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** /**
* EasyExcel必填字段标注处理器 * EasyExcel必填字段标注处理器
@@ -31,18 +18,13 @@ import java.util.Set;
* @author ruoyi * @author ruoyi
*/ */
@Slf4j @Slf4j
public class RequiredFieldWriteHandler implements CellWriteHandler { public class RequiredFieldWriteHandler implements SheetWriteHandler {
/** /**
* 实体类Class对象 * 实体类Class对象
*/ */
private final Class<?> modelClass; private final Class<?> modelClass;
/**
* 必填字段列索引集合
*/
private final Set<Integer> requiredColumns;
/** /**
* 构造函数 * 构造函数
* *
@@ -50,30 +32,39 @@ public class RequiredFieldWriteHandler implements CellWriteHandler {
*/ */
public RequiredFieldWriteHandler(Class<?> modelClass) { public RequiredFieldWriteHandler(Class<?> modelClass) {
this.modelClass = modelClass; this.modelClass = modelClass;
this.requiredColumns = parseRequiredFields();
} }
@Override @Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
WriteTableHolder writeTableHolder, // 获取工作表
List<WriteCellData<?>> cellDataList, Sheet sheet = writeSheetHolder.getSheet();
Cell cell,
Head head, // 获取表头行第1行索引为0
Integer relativeRowIndex, Row headerRow = sheet.getRow(0);
Boolean isHead) { if (headerRow == null) {
if (!Boolean.TRUE.equals(isHead) || cell == null || !requiredColumns.contains(cell.getColumnIndex())) { log.warn("表头行不存在,跳过必填字段标注");
return; return;
} }
Workbook workbook = cell.getSheet().getWorkbook(); // 创建红色字体样式
Workbook workbook = writeWorkbookHolder.getWorkbook();
CellStyle redStyle = createRedFontStyle(workbook); CellStyle redStyle = createRedFontStyle(workbook);
// 解析实体类中的必填字段
Set<Integer> requiredColumns = parseRequiredFields();
// 为必填字段的表头添加红色星号
for (Integer columnIndex : requiredColumns) {
Cell cell = headerRow.getCell(columnIndex);
if (cell != null) {
String originalValue = cell.getStringCellValue(); String originalValue = cell.getStringCellValue();
if (originalValue != null && !originalValue.endsWith("*")) { // 添加红色星号
cell.setCellValue(originalValue + "*"); cell.setCellValue(originalValue + "*");
} // 应用红色样式到星号
cell.setCellStyle(redStyle); cell.setCellStyle(redStyle);
log.info("为列[{}]的表头添加必填标记(*)", cell.getColumnIndex()); log.info("为列[{}]的表头添加必填标记(*)", columnIndex);
}
}
} }
/** /**

View File

@@ -30,10 +30,10 @@ public interface CcdiStaffRecruitmentMapper extends BaseMapper<CcdiStaffRecruitm
/** /**
* 查询招聘信息详情 * 查询招聘信息详情
* *
* @param id 主键ID * @param recruitId 招聘项目编号
* @return 招聘信息VO * @return 招聘信息VO
*/ */
CcdiStaffRecruitmentVO selectRecruitmentById(@Param("id") Long id); CcdiStaffRecruitmentVO selectRecruitmentById(@Param("recruitId") String recruitId);
/** /**
* 批量插入招聘信息数据 * 批量插入招聘信息数据

View File

@@ -5,8 +5,6 @@ import com.ruoyi.info.collection.domain.vo.AssetImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 亲属资产信息异步导入 服务层 * 亲属资产信息异步导入 服务层
@@ -33,19 +31,6 @@ public interface ICcdiAssetInfoImportService {
*/ */
void importAssetInfoAsync(List<CcdiAssetInfoExcel> excelList, String taskId, String userName); void importAssetInfoAsync(List<CcdiAssetInfoExcel> excelList, String taskId, String userName);
/**
* 同步执行亲属资产导入可附加同一文件亲属关系Sheet成功导入的归属映射
*
* @param excelList Excel实体列表
* @param taskId 任务ID
* @param userName 用户名
* @param extraOwnerMappings 附加归属映射key为亲属证件号value为归属员工证件号集合
*/
void importAssetInfoSync(List<CcdiAssetInfoExcel> excelList,
String taskId,
String userName,
Map<String, Set<String>> extraOwnerMappings);
/** /**
* 查询导入状态 * 查询导入状态
* *

View File

@@ -5,8 +5,6 @@ import com.ruoyi.info.collection.domain.vo.BaseStaffAssetImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 员工资产信息异步导入 服务层 * 员工资产信息异步导入 服务层
@@ -33,19 +31,6 @@ public interface ICcdiBaseStaffAssetImportService {
*/ */
void importAssetInfoAsync(List<CcdiBaseStaffAssetInfoExcel> excelList, String taskId, String userName); void importAssetInfoAsync(List<CcdiBaseStaffAssetInfoExcel> excelList, String taskId, String userName);
/**
* 同步执行员工资产导入可附加同一文件员工Sheet成功导入的归属映射
*
* @param excelList Excel实体列表
* @param taskId 任务ID
* @param userName 用户名
* @param extraOwnerMappings 附加归属映射key为资产持有人证件号value为归属员工证件号集合
*/
void importAssetInfoSync(List<CcdiBaseStaffAssetInfoExcel> excelList,
String taskId,
String userName,
Map<String, Set<String>> extraOwnerMappings);
/** /**
* 查询导入状态 * 查询导入状态
* *

View File

@@ -5,7 +5,6 @@ import com.ruoyi.info.collection.domain.vo.ImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @Author: wkc * @Author: wkc
@@ -20,15 +19,6 @@ public interface ICcdiBaseStaffImportService {
*/ */
void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId); void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId);
/**
* 同步执行员工导入并返回本轮成功员工身份证号
*
* @param excelList Excel数据列表
* @param taskId 任务ID
* @return 成功导入的身份证号集合
*/
Set<String> importBaseStaffSync(List<CcdiBaseStaffExcel> excelList, String taskId);
/** /**
* 查询导入状态 * 查询导入状态
* *

View File

@@ -4,9 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffAddDTO; import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffEditDTO; import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffQueryDTO; import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel; import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.vo.BaseStaffImportSubmitResultVO;
import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffOptionVO; import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffOptionVO;
import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffVO; import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffVO;
@@ -85,16 +83,6 @@ public interface ICcdiBaseStaffService {
*/ */
String importBaseStaff(List<CcdiBaseStaffExcel> excelList); String importBaseStaff(List<CcdiBaseStaffExcel> excelList);
/**
* 导入员工信息和员工资产双Sheet数据
*
* @param staffList 员工信息Sheet
* @param assetList 员工资产Sheet
* @return 提交结果
*/
BaseStaffImportSubmitResultVO importBaseStaffWithAssets(List<CcdiBaseStaffExcel> staffList,
List<CcdiBaseStaffAssetInfoExcel> assetList);
/** /**
* 查询员工下拉列表 * 查询员工下拉列表
* 支持按员工ID或姓名模糊搜索只返回在职员工 * 支持按员工ID或姓名模糊搜索只返回在职员工

View File

@@ -5,7 +5,6 @@ import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportFailureVO; import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportFailureVO;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 员工亲属关系异步导入 服务层 * 员工亲属关系异步导入 服务层
@@ -24,16 +23,6 @@ public interface ICcdiStaffFmyRelationImportService {
*/ */
void importRelationAsync(List<CcdiStaffFmyRelationExcel> excelList, String taskId, String userName); void importRelationAsync(List<CcdiStaffFmyRelationExcel> excelList, String taskId, String userName);
/**
* 同步执行员工亲属关系导入并返回本轮成功关系映射
*
* @param excelList Excel实体列表
* @param taskId 任务ID
* @param userName 用户名
* @return key为亲属证件号value为归属员工证件号
*/
Map<String, String> importRelationSync(List<CcdiStaffFmyRelationExcel> excelList, String taskId, String userName);
/** /**
* 查询导入失败记录 * 查询导入失败记录
* *

View File

@@ -4,10 +4,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationAddDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationEditDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationQueryDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import com.ruoyi.info.collection.domain.vo.CcdiStaffFmyRelationVO; import com.ruoyi.info.collection.domain.vo.CcdiStaffFmyRelationVO;
import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportSubmitResultVO;
import java.util.List; import java.util.List;
@@ -83,14 +81,4 @@ public interface ICcdiStaffFmyRelationService {
* @return 任务ID * @return 任务ID
*/ */
String importRelation(List<CcdiStaffFmyRelationExcel> excelList); String importRelation(List<CcdiStaffFmyRelationExcel> excelList);
/**
* 导入员工亲属关系和亲属资产双Sheet数据
*
* @param relationList 员工亲属关系Sheet
* @param assetList 亲属资产Sheet
* @return 提交结果
*/
StaffFmyRelationImportSubmitResultVO importRelationWithAssets(List<CcdiStaffFmyRelationExcel> relationList,
List<CcdiAssetInfoExcel> assetList);
} }

View File

@@ -46,10 +46,10 @@ public interface ICcdiStaffRecruitmentService {
/** /**
* 查询招聘信息详情 * 查询招聘信息详情
* *
* @param id 主键ID * @param recruitId 招聘项目编号
* @return 招聘信息VO * @return 招聘信息VO
*/ */
CcdiStaffRecruitmentVO selectRecruitmentById(Long id); CcdiStaffRecruitmentVO selectRecruitmentById(String recruitId);
/** /**
* 新增招聘信息 * 新增招聘信息
@@ -70,10 +70,10 @@ public interface ICcdiStaffRecruitmentService {
/** /**
* 批量删除招聘信息 * 批量删除招聘信息
* *
* @param ids 需要删除的招聘信息ID * @param recruitIds 需要删除的招聘项目编号
* @return 结果 * @return 结果
*/ */
int deleteRecruitmentByIds(Long[] ids); int deleteRecruitmentByIds(String[] recruitIds);
/** /**
* 导入招聘信息数据 * 导入招聘信息数据

View File

@@ -82,15 +82,6 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
@Async @Async
@Transactional @Transactional
public void importAssetInfoAsync(List<CcdiAssetInfoExcel> excelList, String taskId, String userName) { public void importAssetInfoAsync(List<CcdiAssetInfoExcel> excelList, String taskId, String userName) {
importAssetInfoSync(excelList, taskId, userName, Map.of());
}
@Override
@Transactional
public void importAssetInfoSync(List<CcdiAssetInfoExcel> excelList,
String taskId,
String userName,
Map<String, Set<String>> extraOwnerMappings) {
List<CcdiAssetInfo> successList = new ArrayList<>(); List<CcdiAssetInfo> successList = new ArrayList<>();
List<AssetImportFailureVO> failures = new ArrayList<>(); List<AssetImportFailureVO> failures = new ArrayList<>();
@@ -101,7 +92,6 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
.toList(); .toList();
Map<String, Set<String>> ownerMap = buildOwnerMap(personIds); Map<String, Set<String>> ownerMap = buildOwnerMap(personIds);
mergeOwnerMappings(ownerMap, extraOwnerMappings);
for (int i = 0; i < excelList.size(); i++) { for (int i = 0; i < excelList.size(); i++) {
CcdiAssetInfoExcel excel = excelList.get(i); CcdiAssetInfoExcel excel = excelList.get(i);
@@ -199,18 +189,6 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
} }
} }
private void mergeOwnerMappings(Map<String, Set<String>> result, Map<String, Set<String>> mappings) {
if (mappings == null || mappings.isEmpty()) {
return;
}
for (Map.Entry<String, Set<String>> entry : mappings.entrySet()) {
if (StringUtils.isEmpty(entry.getKey()) || entry.getValue() == null || entry.getValue().isEmpty()) {
continue;
}
result.computeIfAbsent(entry.getKey(), key -> new java.util.LinkedHashSet<>()).addAll(entry.getValue());
}
}
private void validateExcel(CcdiAssetInfoExcel excel) { private void validateExcel(CcdiAssetInfoExcel excel) {
if (StringUtils.isEmpty(excel.getPersonId())) { if (StringUtils.isEmpty(excel.getPersonId())) {
throw new RuntimeException("亲属证件号不能为空"); throw new RuntimeException("亲属证件号不能为空");

View File

@@ -81,15 +81,6 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
@Async @Async
@Transactional @Transactional
public void importAssetInfoAsync(List<CcdiBaseStaffAssetInfoExcel> excelList, String taskId, String userName) { public void importAssetInfoAsync(List<CcdiBaseStaffAssetInfoExcel> excelList, String taskId, String userName) {
importAssetInfoSync(excelList, taskId, userName, Map.of());
}
@Override
@Transactional
public void importAssetInfoSync(List<CcdiBaseStaffAssetInfoExcel> excelList,
String taskId,
String userName,
Map<String, Set<String>> extraOwnerMappings) {
List<CcdiAssetInfo> successList = new ArrayList<>(); List<CcdiAssetInfo> successList = new ArrayList<>();
List<BaseStaffAssetImportFailureVO> failures = new ArrayList<>(); List<BaseStaffAssetImportFailureVO> failures = new ArrayList<>();
@@ -100,7 +91,6 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
.toList(); .toList();
Map<String, Set<String>> ownerMap = buildOwnerMap(personIds); Map<String, Set<String>> ownerMap = buildOwnerMap(personIds);
mergeOwnerMappings(ownerMap, extraOwnerMappings);
Set<String> existingAssetKeys = buildExistingAssetKeys(personIds); Set<String> existingAssetKeys = buildExistingAssetKeys(personIds);
Set<String> importedAssetKeys = new java.util.LinkedHashSet<>(); Set<String> importedAssetKeys = new java.util.LinkedHashSet<>();
@@ -217,18 +207,6 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
} }
} }
private void mergeOwnerMappings(Map<String, Set<String>> result, Map<String, Set<String>> mappings) {
if (mappings == null || mappings.isEmpty()) {
return;
}
for (Map.Entry<String, Set<String>> entry : mappings.entrySet()) {
if (StringUtils.isEmpty(entry.getKey()) || entry.getValue() == null || entry.getValue().isEmpty()) {
continue;
}
result.computeIfAbsent(entry.getKey(), key -> new java.util.LinkedHashSet<>()).addAll(entry.getValue());
}
}
private void validateExcel(CcdiBaseStaffAssetInfoExcel excel) { private void validateExcel(CcdiBaseStaffAssetInfoExcel excel) {
if (StringUtils.isEmpty(excel.getPersonId())) { if (StringUtils.isEmpty(excel.getPersonId())) {
throw new RuntimeException("员工身份证号不能为空"); throw new RuntimeException("员工身份证号不能为空");

View File

@@ -23,7 +23,6 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
@@ -52,12 +51,6 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
@Override @Override
@Async @Async
public void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId) { public void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId) {
importBaseStaffSync(excelList, taskId);
}
@Override
@Transactional
public Set<String> importBaseStaffSync(List<CcdiBaseStaffExcel> excelList, String taskId) {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 记录导入开始 // 记录导入开始
@@ -160,11 +153,6 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
long duration = System.currentTimeMillis() - startTime; long duration = System.currentTimeMillis() - startTime;
ImportLogUtils.logImportComplete(log, taskId, "员工基础信息", ImportLogUtils.logImportComplete(log, taskId, "员工基础信息",
excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration);
return newRecords.stream()
.map(CcdiBaseStaff::getIdCard)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toCollection(LinkedHashSet::new));
} }
/** /**

View File

@@ -6,19 +6,15 @@ import com.ruoyi.info.collection.domain.CcdiBaseStaff;
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffAddDTO; import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffEditDTO; import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffQueryDTO; import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel; import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.vo.BaseStaffImportSubmitResultVO;
import com.ruoyi.info.collection.domain.vo.CcdiAssetInfoVO; import com.ruoyi.info.collection.domain.vo.CcdiAssetInfoVO;
import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffOptionVO; import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffOptionVO;
import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffVO; import com.ruoyi.info.collection.domain.vo.CcdiBaseStaffVO;
import com.ruoyi.info.collection.enums.EmployeeStatus; import com.ruoyi.info.collection.enums.EmployeeStatus;
import com.ruoyi.info.collection.mapper.CcdiBaseStaffMapper; import com.ruoyi.info.collection.mapper.CcdiBaseStaffMapper;
import com.ruoyi.info.collection.service.ICcdiAssetInfoService; import com.ruoyi.info.collection.service.ICcdiAssetInfoService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffAssetImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService; import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffService; import com.ruoyi.info.collection.service.ICcdiBaseStaffService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
@@ -50,12 +46,6 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
@Resource @Resource
private ICcdiAssetInfoService assetInfoService; private ICcdiAssetInfoService assetInfoService;
@Resource
private ICcdiBaseStaffAssetImportService baseStaffAssetImportService;
@Resource
private CcdiDualSheetImportOrchestrationService dualSheetImportOrchestrationService;
/** /**
* 查询员工列表 * 查询员工列表
* *
@@ -228,52 +218,28 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
@Transactional @Transactional
public String importBaseStaff(List<CcdiBaseStaffExcel> excelList) { public String importBaseStaff(List<CcdiBaseStaffExcel> excelList) {
String taskId = UUID.randomUUID().toString(); String taskId = UUID.randomUUID().toString();
initializeImportStatus("import:baseStaff:", taskId, excelList.size()); long startTime = System.currentTimeMillis();
// 初始化Redis状态
String statusKey = "import:baseStaff:" + taskId;
Map<String, Object> statusData = new HashMap<>();
statusData.put("taskId", taskId);
statusData.put("status", "PROCESSING");
statusData.put("totalCount", excelList.size());
statusData.put("successCount", 0);
statusData.put("failureCount", 0);
statusData.put("progress", 0);
statusData.put("startTime", startTime);
statusData.put("message", "正在处理...");
redisTemplate.opsForHash().putAll(statusKey, statusData);
redisTemplate.expire(statusKey, 7, java.util.concurrent.TimeUnit.DAYS);
importAsyncService.importBaseStaffAsync(excelList, taskId); importAsyncService.importBaseStaffAsync(excelList, taskId);
return taskId; return taskId;
} }
@Override
@Transactional
public BaseStaffImportSubmitResultVO importBaseStaffWithAssets(List<CcdiBaseStaffExcel> staffList,
List<CcdiBaseStaffAssetInfoExcel> assetList) {
boolean hasStaffRows = staffList != null && !staffList.isEmpty();
boolean hasAssetRows = assetList != null && !assetList.isEmpty();
if (!hasStaffRows && !hasAssetRows) {
throw new RuntimeException("至少需要一条数据");
}
BaseStaffImportSubmitResultVO result = new BaseStaffImportSubmitResultVO();
result.setMessage(buildImportSubmitMessage(hasStaffRows, hasAssetRows));
if (hasStaffRows && !hasAssetRows) {
result.setStaffTaskId(importBaseStaff(staffList));
return result;
}
if (!hasStaffRows) {
result.setAssetTaskId(baseStaffAssetImportService.importAssetInfo(assetList));
return result;
}
String staffTaskId = UUID.randomUUID().toString();
String assetTaskId = UUID.randomUUID().toString();
initializeImportStatus("import:baseStaff:", staffTaskId, staffList.size());
initializeImportStatus("import:baseStaffAsset:", assetTaskId, assetList.size());
result.setStaffTaskId(staffTaskId);
result.setAssetTaskId(assetTaskId);
dualSheetImportOrchestrationService.importBaseStaffWithAssetsAsync(
staffList,
staffTaskId,
assetList,
assetTaskId,
currentUserName()
);
return result;
}
/** /**
* 查询员工下拉列表 * 查询员工下拉列表
* 支持按员工ID或姓名模糊搜索只返回在职员工 * 支持按员工ID或姓名模糊搜索只返回在职员工
@@ -286,40 +252,6 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
return baseStaffMapper.selectStaffOptions(query); return baseStaffMapper.selectStaffOptions(query);
} }
private void initializeImportStatus(String keyPrefix, String taskId, int totalCount) {
Map<String, Object> statusData = new HashMap<>();
statusData.put("taskId", taskId);
statusData.put("status", "PROCESSING");
statusData.put("totalCount", totalCount);
statusData.put("successCount", 0);
statusData.put("failureCount", 0);
statusData.put("progress", 0);
statusData.put("startTime", System.currentTimeMillis());
statusData.put("message", "正在处理...");
String statusKey = keyPrefix + taskId;
redisTemplate.opsForHash().putAll(statusKey, statusData);
redisTemplate.expire(statusKey, 7, java.util.concurrent.TimeUnit.DAYS);
}
private String buildImportSubmitMessage(boolean hasStaffRows, boolean hasAssetRows) {
if (hasStaffRows && hasAssetRows) {
return "已提交员工信息和员工资产信息导入任务";
}
if (hasStaffRows) {
return "已提交员工信息导入任务";
}
return "已提交员工资产信息导入任务";
}
private String currentUserName() {
try {
return SecurityUtils.getUsername();
} catch (Exception e) {
return "system";
}
}
/** /**
* 构建查询条件 * 构建查询条件
*/ */

View File

@@ -7,11 +7,8 @@ import com.ruoyi.info.collection.domain.excel.CcdiCustEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.CustEnterpriseRelationImportFailureVO; import com.ruoyi.info.collection.domain.vo.CustEnterpriseRelationImportFailureVO;
import com.ruoyi.info.collection.domain.vo.ImportResult; import com.ruoyi.info.collection.domain.vo.ImportResult;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationImportService; import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationImportService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.info.collection.utils.ImportLogUtils; import com.ruoyi.info.collection.utils.ImportLogUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -46,9 +43,6 @@ public class CcdiCustEnterpriseRelationImportServiceImpl implements ICcdiCustEnt
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
@Override @Override
@Async @Async
@Transactional @Transactional
@@ -133,15 +127,6 @@ public class CcdiCustEnterpriseRelationImportServiceImpl implements ICcdiCustEnt
// 批量插入新数据 // 批量插入新数据
if (!newRecords.isEmpty()) { if (!newRecords.isEmpty()) {
enterpriseAutoFillService.ensureExistsBatch(newRecords.stream()
.map(item -> new EnterpriseAutoFillService.EnterpriseFillItem(
item.getSocialCreditCode(),
item.getEnterpriseName(),
EnterpriseSource.CREDIT_CUSTOMER.getCode(),
DataSource.IMPORT.getCode(),
userName
))
.toList());
ImportLogUtils.logBatchOperationStart(log, taskId, "插入", ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
(newRecords.size() + 499) / 500, 500); (newRecords.size() + 499) / 500, 500);
saveBatch(newRecords, 500); saveBatch(newRecords, 500);

View File

@@ -8,12 +8,9 @@ import com.ruoyi.info.collection.domain.dto.CcdiCustEnterpriseRelationEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiCustEnterpriseRelationQueryDTO; import com.ruoyi.info.collection.domain.dto.CcdiCustEnterpriseRelationQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiCustEnterpriseRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiCustEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.CcdiCustEnterpriseRelationVO; import com.ruoyi.info.collection.domain.vo.CcdiCustEnterpriseRelationVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationImportService; import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationImportService;
import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationService; import com.ruoyi.info.collection.service.ICcdiCustEnterpriseRelationService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -46,9 +43,6 @@ public class CcdiCustEnterpriseRelationServiceImpl implements ICcdiCustEnterpris
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
/** /**
* 查询信贷客户实体关联列表 * 查询信贷客户实体关联列表
* *
@@ -141,14 +135,6 @@ public class CcdiCustEnterpriseRelationServiceImpl implements ICcdiCustEnterpris
relation.setDataSource("MANUAL"); relation.setDataSource("MANUAL");
} }
enterpriseAutoFillService.ensureExists(new EnterpriseAutoFillService.EnterpriseFillItem(
addDTO.getSocialCreditCode(),
addDTO.getEnterpriseName(),
EnterpriseSource.CREDIT_CUSTOMER.getCode(),
DataSource.MANUAL.getCode(),
SecurityUtils.getUsername()
));
int result = relationMapper.insert(relation); int result = relationMapper.insert(relation);
return result; return result;

View File

@@ -1,90 +0,0 @@
package com.ruoyi.info.collection.service.impl;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import com.ruoyi.info.collection.service.ICcdiAssetInfoImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffAssetImportService;
import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationImportService;
import jakarta.annotation.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 双Sheet导入后台顺序编排。
*/
@Service
public class CcdiDualSheetImportOrchestrationService {
@Resource
private ICcdiBaseStaffImportService baseStaffImportService;
@Resource
private ICcdiBaseStaffAssetImportService baseStaffAssetImportService;
@Resource
private ICcdiStaffFmyRelationImportService relationImportService;
@Resource
private ICcdiAssetInfoImportService assetInfoImportService;
@Async
public void importBaseStaffWithAssetsAsync(List<CcdiBaseStaffExcel> staffList,
String staffTaskId,
List<CcdiBaseStaffAssetInfoExcel> assetList,
String assetTaskId,
String userName) {
Set<String> successIdCards = baseStaffImportService.importBaseStaffSync(staffList, staffTaskId);
baseStaffAssetImportService.importAssetInfoSync(
assetList,
assetTaskId,
userName,
buildSelfOwnerMappings(successIdCards)
);
}
@Async
public void importRelationWithAssetsAsync(List<CcdiStaffFmyRelationExcel> relationList,
String relationTaskId,
List<CcdiAssetInfoExcel> assetList,
String assetTaskId,
String userName) {
Map<String, String> successRelationMappings = relationImportService.importRelationSync(relationList, relationTaskId, userName);
assetInfoImportService.importAssetInfoSync(
assetList,
assetTaskId,
userName,
buildRelationOwnerMappings(successRelationMappings)
);
}
private Map<String, Set<String>> buildSelfOwnerMappings(Set<String> idCards) {
Map<String, Set<String>> result = new LinkedHashMap<>();
if (idCards == null || idCards.isEmpty()) {
return result;
}
for (String idCard : idCards) {
result.computeIfAbsent(idCard, key -> new LinkedHashSet<>()).add(idCard);
}
return result;
}
private Map<String, Set<String>> buildRelationOwnerMappings(Map<String, String> relationMappings) {
Map<String, Set<String>> result = new LinkedHashMap<>();
if (relationMappings == null || relationMappings.isEmpty()) {
return result;
}
for (Map.Entry<String, String> entry : relationMappings.entrySet()) {
result.computeIfAbsent(entry.getKey(), key -> new LinkedHashSet<>()).add(entry.getValue());
}
return result;
}
}

View File

@@ -131,18 +131,14 @@ public class CcdiEnterpriseBaseInfoImportServiceImpl implements ICcdiEnterpriseB
if (!excel.getSocialCreditCode().matches("^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$")) { if (!excel.getSocialCreditCode().matches("^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$")) {
throw new RuntimeException("统一社会信用代码格式不正确"); throw new RuntimeException("统一社会信用代码格式不正确");
} }
String riskLevel = EnterpriseRiskLevel.resolveCode(StringUtils.trim(excel.getRiskLevel()));
if (riskLevel == null) {
throw new RuntimeException("风险等级不在允许范围内");
}
String entSource = EnterpriseSource.resolveCode(StringUtils.trim(excel.getEntSource())); String entSource = EnterpriseSource.resolveCode(StringUtils.trim(excel.getEntSource()));
if (entSource == null) { if (entSource == null) {
throw new RuntimeException("企业来源不在允许范围内"); throw new RuntimeException("企业来源不在允许范围内");
} }
String riskLevel = EnterpriseRiskLevel.resolveCode(StringUtils.trim(excel.getRiskLevel()));
if (riskLevel == null) {
if (EnterpriseSource.INTERMEDIARY.getCode().equals(entSource) && StringUtils.isEmpty(excel.getRiskLevel())) {
riskLevel = "1";
} else {
throw new RuntimeException("风险等级不在允许范围内");
}
}
if (existingCreditCodes.contains(excel.getSocialCreditCode())) { if (existingCreditCodes.contains(excel.getSocialCreditCode())) {
throw new RuntimeException(String.format("统一社会信用代码[%s]已存在,请勿重复导入", excel.getSocialCreditCode())); throw new RuntimeException(String.format("统一社会信用代码[%s]已存在,请勿重复导入", excel.getSocialCreditCode()));

View File

@@ -3,17 +3,16 @@ package com.ruoyi.info.collection.service.impl;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.info.collection.domain.CcdiBizIntermediary; import com.ruoyi.info.collection.domain.CcdiBizIntermediary;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation; import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.ImportResult; import com.ruoyi.info.collection.domain.vo.ImportResult;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO; import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper; import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiIntermediaryEnterpriseRelationImportService; import com.ruoyi.info.collection.service.ICcdiIntermediaryEnterpriseRelationImportService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.info.collection.utils.ImportLogUtils; import com.ruoyi.info.collection.utils.ImportLogUtils;
import com.ruoyi.common.utils.IdCardUtil; import com.ruoyi.common.utils.IdCardUtil;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
@@ -55,10 +54,10 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
private CcdiBizIntermediaryMapper intermediaryMapper; private CcdiBizIntermediaryMapper intermediaryMapper;
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
@Resource @Resource
private EnterpriseAutoFillService enterpriseAutoFillService; private RedisTemplate<String, Object> redisTemplate;
@Override @Override
@Async @Async
@@ -68,6 +67,7 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
ImportLogUtils.logImportStart(log, taskId, "中介实体关联关系", excelList.size(), userName); ImportLogUtils.logImportStart(log, taskId, "中介实体关联关系", excelList.size(), userName);
Map<String, String> ownerBizIdByPersonId = getOwnerBizIdByPersonId(excelList); Map<String, String> ownerBizIdByPersonId = getOwnerBizIdByPersonId(excelList);
Set<String> existingEnterpriseCodes = getExistingEnterpriseCodes(excelList);
Set<String> existingCombinations = getExistingRelationCombinations(ownerBizIdByPersonId, excelList); Set<String> existingCombinations = getExistingRelationCombinations(ownerBizIdByPersonId, excelList);
List<CcdiIntermediaryEnterpriseRelation> successRecords = new ArrayList<>(); List<CcdiIntermediaryEnterpriseRelation> successRecords = new ArrayList<>();
@@ -79,14 +79,15 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
try { try {
validateExcel(excel); validateExcel(excel);
String ownerPersonId = trim(excel.getOwnerPersonId()); String ownerBizId = ownerBizIdByPersonId.get(excel.getOwnerPersonId());
String socialCreditCode = trim(excel.getSocialCreditCode());
String ownerBizId = ownerBizIdByPersonId.get(ownerPersonId);
if (StringUtils.isEmpty(ownerBizId)) { if (StringUtils.isEmpty(ownerBizId)) {
throw new RuntimeException("中介本人不存在,请先导入或维护中介本人信息"); throw new RuntimeException("中介本人不存在,请先导入或维护中介本人信息");
} }
if (!existingEnterpriseCodes.contains(excel.getSocialCreditCode())) {
throw new RuntimeException("统一社会信用代码不存在于系统机构表");
}
String combination = ownerBizId + "|" + socialCreditCode; String combination = ownerBizId + "|" + excel.getSocialCreditCode();
if (existingCombinations.contains(combination)) { if (existingCombinations.contains(combination)) {
throw new RuntimeException("中介实体关联关系已存在,请勿重复导入"); throw new RuntimeException("中介实体关联关系已存在,请勿重复导入");
} }
@@ -97,9 +98,6 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation(); CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation();
BeanUtils.copyProperties(excel, relation); BeanUtils.copyProperties(excel, relation);
relation.setIntermediaryBizId(ownerBizId); relation.setIntermediaryBizId(ownerBizId);
relation.setSocialCreditCode(socialCreditCode);
relation.setRelationPersonPost(trim(excel.getRelationPersonPost()));
relation.setRemark(trim(excel.getRemark()));
relation.setCreatedBy(userName); relation.setCreatedBy(userName);
relation.setUpdatedBy(userName); relation.setUpdatedBy(userName);
successRecords.add(relation); successRecords.add(relation);
@@ -111,15 +109,6 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
} }
if (!successRecords.isEmpty()) { if (!successRecords.isEmpty()) {
enterpriseAutoFillService.ensureExistsBatch(successRecords.stream()
.map(item -> new EnterpriseAutoFillService.EnterpriseFillItem(
item.getSocialCreditCode(),
null,
EnterpriseSource.INTERMEDIARY.getCode(),
DataSource.IMPORT.getCode(),
userName
))
.toList());
saveBatch(successRecords, 500); saveBatch(successRecords, 500);
} }
if (!failures.isEmpty()) { if (!failures.isEmpty()) {
@@ -170,7 +159,6 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
private Map<String, String> getOwnerBizIdByPersonId(List<CcdiIntermediaryEnterpriseRelationExcel> excelList) { private Map<String, String> getOwnerBizIdByPersonId(List<CcdiIntermediaryEnterpriseRelationExcel> excelList) {
List<String> ownerPersonIds = excelList.stream() List<String> ownerPersonIds = excelList.stream()
.map(CcdiIntermediaryEnterpriseRelationExcel::getOwnerPersonId) .map(CcdiIntermediaryEnterpriseRelationExcel::getOwnerPersonId)
.map(this::trim)
.filter(StringUtils::isNotEmpty) .filter(StringUtils::isNotEmpty)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -185,16 +173,32 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
.collect(Collectors.toMap(CcdiBizIntermediary::getPersonId, CcdiBizIntermediary::getBizId, (left, right) -> left)); .collect(Collectors.toMap(CcdiBizIntermediary::getPersonId, CcdiBizIntermediary::getBizId, (left, right) -> left));
} }
private Set<String> getExistingEnterpriseCodes(List<CcdiIntermediaryEnterpriseRelationExcel> excelList) {
List<String> socialCreditCodes = excelList.stream()
.map(CcdiIntermediaryEnterpriseRelationExcel::getSocialCreditCode)
.filter(StringUtils::isNotEmpty)
.distinct()
.collect(Collectors.toList());
if (socialCreditCodes.isEmpty()) {
return Collections.emptySet();
}
LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
wrapper.in(CcdiEnterpriseBaseInfo::getSocialCreditCode, socialCreditCodes);
return enterpriseBaseInfoMapper.selectList(wrapper).stream()
.map(CcdiEnterpriseBaseInfo::getSocialCreditCode)
.collect(Collectors.toSet());
}
private Set<String> getExistingRelationCombinations(Map<String, String> ownerBizIdByPersonId, private Set<String> getExistingRelationCombinations(Map<String, String> ownerBizIdByPersonId,
List<CcdiIntermediaryEnterpriseRelationExcel> excelList) { List<CcdiIntermediaryEnterpriseRelationExcel> excelList) {
List<String> combinations = excelList.stream() List<String> combinations = excelList.stream()
.map(excel -> { .map(excel -> {
String ownerBizId = ownerBizIdByPersonId.get(trim(excel.getOwnerPersonId())); String ownerBizId = ownerBizIdByPersonId.get(excel.getOwnerPersonId());
String socialCreditCode = trim(excel.getSocialCreditCode()); if (StringUtils.isEmpty(ownerBizId) || StringUtils.isEmpty(excel.getSocialCreditCode())) {
if (StringUtils.isEmpty(ownerBizId) || StringUtils.isEmpty(socialCreditCode)) {
return null; return null;
} }
return ownerBizId + "|" + socialCreditCode; return ownerBizId + "|" + excel.getSocialCreditCode();
}) })
.filter(StringUtils::isNotEmpty) .filter(StringUtils::isNotEmpty)
.distinct() .distinct()
@@ -206,33 +210,24 @@ public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcd
} }
private void validateExcel(CcdiIntermediaryEnterpriseRelationExcel excel) { private void validateExcel(CcdiIntermediaryEnterpriseRelationExcel excel) {
String ownerPersonId = trim(excel.getOwnerPersonId()); if (StringUtils.isEmpty(excel.getOwnerPersonId())) {
String socialCreditCode = trim(excel.getSocialCreditCode());
String relationPersonPost = trim(excel.getRelationPersonPost());
String remark = trim(excel.getRemark());
if (StringUtils.isEmpty(ownerPersonId)) {
throw new RuntimeException("中介本人证件号码不能为空"); throw new RuntimeException("中介本人证件号码不能为空");
} }
if (StringUtils.isEmpty(socialCreditCode)) { if (StringUtils.isEmpty(excel.getSocialCreditCode())) {
throw new RuntimeException("统一社会信用代码不能为空"); throw new RuntimeException("统一社会信用代码不能为空");
} }
String ownerPersonIdError = IdCardUtil.getErrorMessage(ownerPersonId); String ownerPersonIdError = IdCardUtil.getErrorMessage(excel.getOwnerPersonId());
if (ownerPersonIdError != null) { if (ownerPersonIdError != null) {
throw new RuntimeException("中介本人证件号码" + ownerPersonIdError); throw new RuntimeException("中介本人证件号码" + ownerPersonIdError);
} }
if (StringUtils.isNotEmpty(relationPersonPost) && relationPersonPost.length() > 100) { if (StringUtils.isNotEmpty(excel.getRelationPersonPost()) && excel.getRelationPersonPost().length() > 100) {
throw new RuntimeException("关联职务长度不能超过100个字符"); throw new RuntimeException("关联职务长度不能超过100个字符");
} }
if (StringUtils.isNotEmpty(remark) && remark.length() > 500) { if (StringUtils.isNotEmpty(excel.getRemark()) && excel.getRemark().length() > 500) {
throw new RuntimeException("备注长度不能超过500个字符"); throw new RuntimeException("备注长度不能超过500个字符");
} }
} }
private String trim(String value) {
return value == null ? null : value.trim();
}
private IntermediaryEnterpriseRelationImportFailureVO createFailureVO(CcdiIntermediaryEnterpriseRelationExcel excel, private IntermediaryEnterpriseRelationImportFailureVO createFailureVO(CcdiIntermediaryEnterpriseRelationExcel excel,
String errorMessage) { String errorMessage) {
IntermediaryEnterpriseRelationImportFailureVO failure = new IntermediaryEnterpriseRelationImportFailureVO(); IntermediaryEnterpriseRelationImportFailureVO failure = new IntermediaryEnterpriseRelationImportFailureVO();

View File

@@ -14,8 +14,6 @@ import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEntityDetailVO;
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryPersonDetailVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryPersonDetailVO;
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryRelativeVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryRelativeVO;
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper; import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper; import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper;
@@ -24,7 +22,6 @@ import com.ruoyi.info.collection.service.ICcdiIntermediaryEnterpriseRelationImpo
import com.ruoyi.info.collection.service.ICcdiIntermediaryEntityImportService; import com.ruoyi.info.collection.service.ICcdiIntermediaryEntityImportService;
import com.ruoyi.info.collection.service.ICcdiIntermediaryPersonImportService; import com.ruoyi.info.collection.service.ICcdiIntermediaryPersonImportService;
import com.ruoyi.info.collection.service.ICcdiIntermediaryService; import com.ruoyi.info.collection.service.ICcdiIntermediaryService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -72,9 +69,6 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
/** /**
* 分页查询中介列表 * 分页查询中介列表
* 使用XML联合查询实现,支持个人中介和实体中介的灵活查询 * 使用XML联合查询实现,支持个人中介和实体中介的灵活查询
@@ -308,13 +302,6 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation(); CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation();
BeanUtils.copyProperties(addDTO, relation); BeanUtils.copyProperties(addDTO, relation);
relation.setIntermediaryBizId(owner.getBizId()); relation.setIntermediaryBizId(owner.getBizId());
enterpriseAutoFillService.ensureExists(new EnterpriseAutoFillService.EnterpriseFillItem(
addDTO.getSocialCreditCode(),
null,
EnterpriseSource.INTERMEDIARY.getCode(),
DataSource.MANUAL.getCode(),
SecurityUtils.getUsername()
));
return enterpriseRelationMapper.insert(relation); return enterpriseRelationMapper.insert(relation);
} }
@@ -330,13 +317,6 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation(); CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation();
BeanUtils.copyProperties(editDTO, relation); BeanUtils.copyProperties(editDTO, relation);
relation.setIntermediaryBizId(existing.getIntermediaryBizId()); relation.setIntermediaryBizId(existing.getIntermediaryBizId());
enterpriseAutoFillService.ensureExists(new EnterpriseAutoFillService.EnterpriseFillItem(
editDTO.getSocialCreditCode(),
null,
EnterpriseSource.INTERMEDIARY.getCode(),
DataSource.MANUAL.getCode(),
SecurityUtils.getUsername()
));
return enterpriseRelationMapper.updateById(relation); return enterpriseRelationMapper.updateById(relation);
} }
@@ -540,6 +520,9 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
private void validateEnterpriseRelation(String bizId, String socialCreditCode, Long excludeId) { private void validateEnterpriseRelation(String bizId, String socialCreditCode, Long excludeId) {
requireIntermediaryPerson(bizId); requireIntermediaryPerson(bizId);
if (enterpriseBaseInfoMapper.selectById(socialCreditCode) == null) {
throw new RuntimeException("关联机构不存在");
}
boolean exists = enterpriseRelationMapper.existsByIntermediaryBizIdAndSocialCreditCode(bizId, socialCreditCode); boolean exists = enterpriseRelationMapper.existsByIntermediaryBizIdAndSocialCreditCode(bizId, socialCreditCode);
if (exists) { if (exists) {
if (excludeId == null) { if (excludeId == null) {

View File

@@ -9,12 +9,9 @@ import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExc
import com.ruoyi.info.collection.domain.vo.ImportResult; import com.ruoyi.info.collection.domain.vo.ImportResult;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.domain.vo.PurchaseTransactionImportFailureVO; import com.ruoyi.info.collection.domain.vo.PurchaseTransactionImportFailureVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper; import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper;
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionSupplierMapper; import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionSupplierMapper;
import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionImportService; import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionImportService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.info.collection.utils.ImportLogUtils; import com.ruoyi.info.collection.utils.ImportLogUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -56,9 +53,6 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
@Override @Override
@Async @Async
@Transactional @Transactional
@@ -189,7 +183,6 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
// 批量插入新数据 // 批量插入新数据
if (!newTransactions.isEmpty()) { if (!newTransactions.isEmpty()) {
autoFillSupplierEnterprises(newSuppliers, userName);
ImportLogUtils.logBatchOperationStart(log, taskId, "插入", ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
(newTransactions.size() + 499) / 500, 500); (newTransactions.size() + 499) / 500, 500);
saveBatch(newTransactions, 500); saveBatch(newTransactions, 500);
@@ -335,19 +328,6 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
} }
} }
private void autoFillSupplierEnterprises(List<CcdiPurchaseTransactionSupplier> supplierList, String userName) {
enterpriseAutoFillService.ensureExistsBatch(supplierList.stream()
.filter(item -> StringUtils.isNotEmpty(item.getSupplierUscc()))
.map(item -> new EnterpriseAutoFillService.EnterpriseFillItem(
item.getSupplierUscc(),
item.getSupplierName(),
EnterpriseSource.SUPPLIER.getCode(),
DataSource.IMPORT.getCode(),
userName
))
.toList());
}
/** /**
* 验证采购交易数据 * 验证采购交易数据
* *

View File

@@ -11,13 +11,10 @@ import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel; import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionVO; import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionVO;
import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionSupplierVO; import com.ruoyi.info.collection.domain.vo.CcdiPurchaseTransactionSupplierVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper; import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper;
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionSupplierMapper; import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionSupplierMapper;
import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionImportService; import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionImportService;
import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionService; import com.ruoyi.info.collection.service.ICcdiPurchaseTransactionService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -58,9 +55,6 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
/** /**
* 查询采购交易列表 * 查询采购交易列表
* *
@@ -140,7 +134,6 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction(); CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
BeanUtils.copyProperties(addDTO, transaction); BeanUtils.copyProperties(addDTO, transaction);
fillWinnerSummary(transaction, supplierList); fillWinnerSummary(transaction, supplierList);
autoFillSupplierEnterprises(supplierList, DataSource.MANUAL.getCode(), SecurityUtils.getUsername());
int result = transactionMapper.insert(transaction); int result = transactionMapper.insert(transaction);
saveSuppliers(supplierList); saveSuppliers(supplierList);
@@ -338,21 +331,6 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
} }
} }
private void autoFillSupplierEnterprises(List<CcdiPurchaseTransactionSupplier> supplierList,
String dataSource,
String userName) {
enterpriseAutoFillService.ensureExistsBatch(supplierList.stream()
.filter(item -> StringUtils.isNotEmpty(item.getSupplierUscc()))
.map(item -> new EnterpriseAutoFillService.EnterpriseFillItem(
item.getSupplierUscc(),
item.getSupplierName(),
EnterpriseSource.SUPPLIER.getCode(),
dataSource,
userName
))
.toList());
}
private List<CcdiPurchaseTransactionSupplierVO> selectSupplierListByPurchaseId(String purchaseId) { private List<CcdiPurchaseTransactionSupplierVO> selectSupplierListByPurchaseId(String purchaseId) {
return supplierMapper.selectList( return supplierMapper.selectList(
new LambdaQueryWrapper<CcdiPurchaseTransactionSupplier>() new LambdaQueryWrapper<CcdiPurchaseTransactionSupplier>()

View File

@@ -9,12 +9,9 @@ import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.ImportResult; import com.ruoyi.info.collection.domain.vo.ImportResult;
import com.ruoyi.info.collection.domain.vo.ImportStatusVO; import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
import com.ruoyi.info.collection.domain.vo.StaffEnterpriseRelationImportFailureVO; import com.ruoyi.info.collection.domain.vo.StaffEnterpriseRelationImportFailureVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiStaffEnterpriseRelationImportService; import com.ruoyi.info.collection.service.ICcdiStaffEnterpriseRelationImportService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.info.collection.utils.ImportLogUtils; import com.ruoyi.info.collection.utils.ImportLogUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -52,9 +49,6 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
@Resource @Resource
private CcdiStaffFmyRelationMapper familyRelationMapper; private CcdiStaffFmyRelationMapper familyRelationMapper;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
@Override @Override
@Async @Async
@Transactional @Transactional
@@ -153,15 +147,6 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
// 批量插入新数据 // 批量插入新数据
if (!newRecords.isEmpty()) { if (!newRecords.isEmpty()) {
enterpriseAutoFillService.ensureExistsBatch(newRecords.stream()
.map(item -> new EnterpriseAutoFillService.EnterpriseFillItem(
item.getSocialCreditCode(),
item.getEnterpriseName(),
EnterpriseSource.EMP_RELATION.getCode(),
DataSource.IMPORT.getCode(),
userName
))
.toList());
ImportLogUtils.logBatchOperationStart(log, taskId, "插入", ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
(newRecords.size() + 499) / 500, 500); (newRecords.size() + 499) / 500, 500);
saveBatch(newRecords, 500); saveBatch(newRecords, 500);

View File

@@ -10,13 +10,10 @@ import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationOptionVO; import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationOptionVO;
import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO; import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO;
import com.ruoyi.info.collection.enums.DataSource;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.ICcdiStaffEnterpriseRelationImportService; import com.ruoyi.info.collection.service.ICcdiStaffEnterpriseRelationImportService;
import com.ruoyi.info.collection.service.ICcdiStaffEnterpriseRelationService; import com.ruoyi.info.collection.service.ICcdiStaffEnterpriseRelationService;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -52,9 +49,6 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource
private EnterpriseAutoFillService enterpriseAutoFillService;
/** /**
* 查询员工实体关系列表 * 查询员工实体关系列表
* *
@@ -150,14 +144,6 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
relation.setDataSource("MANUAL"); relation.setDataSource("MANUAL");
} }
enterpriseAutoFillService.ensureExists(new EnterpriseAutoFillService.EnterpriseFillItem(
addDTO.getSocialCreditCode(),
addDTO.getEnterpriseName(),
EnterpriseSource.EMP_RELATION.getCode(),
DataSource.MANUAL.getCode(),
SecurityUtils.getUsername()
));
int result = relationMapper.insert(relation); int result = relationMapper.insert(relation);
return result; return result;

View File

@@ -57,12 +57,6 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
@Async @Async
@Transactional @Transactional
public void importRelationAsync(List<CcdiStaffFmyRelationExcel> excelList, String taskId, String userName) { public void importRelationAsync(List<CcdiStaffFmyRelationExcel> excelList, String taskId, String userName) {
importRelationSync(excelList, taskId, userName);
}
@Override
@Transactional
public Map<String, String> importRelationSync(List<CcdiStaffFmyRelationExcel> excelList, String taskId, String userName) {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 记录导入开始 // 记录导入开始
@@ -219,15 +213,6 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
long duration = System.currentTimeMillis() - startTime; long duration = System.currentTimeMillis() - startTime;
ImportLogUtils.logImportComplete(log, taskId, "员工亲属关系", ImportLogUtils.logImportComplete(log, taskId, "员工亲属关系",
excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration); excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration);
return newRecords.stream()
.filter(item -> StringUtils.isNotEmpty(item.getRelationCertNo()) && StringUtils.isNotEmpty(item.getPersonId()))
.collect(Collectors.toMap(
CcdiStaffFmyRelation::getRelationCertNo,
CcdiStaffFmyRelation::getPersonId,
(left, right) -> left,
LinkedHashMap::new
));
} }
/** /**

View File

@@ -6,14 +6,11 @@ import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationAddDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationEditDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationQueryDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationQueryDTO;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import com.ruoyi.info.collection.domain.vo.CcdiAssetInfoVO; import com.ruoyi.info.collection.domain.vo.CcdiAssetInfoVO;
import com.ruoyi.info.collection.domain.vo.CcdiStaffFmyRelationVO; import com.ruoyi.info.collection.domain.vo.CcdiStaffFmyRelationVO;
import com.ruoyi.info.collection.domain.vo.StaffFmyRelationImportSubmitResultVO;
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
import com.ruoyi.info.collection.service.ICcdiAssetInfoImportService;
import com.ruoyi.info.collection.service.ICcdiAssetInfoService; import com.ruoyi.info.collection.service.ICcdiAssetInfoService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationImportService; import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationImportService;
import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationService; import com.ruoyi.info.collection.service.ICcdiStaffFmyRelationService;
@@ -54,15 +51,9 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
@Resource @Resource
private ICcdiAssetInfoService assetInfoService; private ICcdiAssetInfoService assetInfoService;
@Resource
private ICcdiAssetInfoImportService assetInfoImportService;
@Resource @Resource
private CcdiStaffEnterpriseRelationMapper staffEnterpriseRelationMapper; private CcdiStaffEnterpriseRelationMapper staffEnterpriseRelationMapper;
@Resource
private CcdiDualSheetImportOrchestrationService dualSheetImportOrchestrationService;
/** /**
* 查询员工亲属关系列表 * 查询员工亲属关系列表
* *
@@ -216,11 +207,25 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
// 生成任务ID // 生成任务ID
String taskId = UUID.randomUUID().toString(); String taskId = UUID.randomUUID().toString();
long startTime = System.currentTimeMillis();
// 获取当前用户名 // 获取当前用户名
String userName = SecurityUtils.getUsername(); String userName = SecurityUtils.getUsername();
initializeImportStatus("import:staffFmyRelation:", taskId, excelList.size()); // 初始化Redis状态
String statusKey = "import:staffFmyRelation:" + taskId;
Map<String, Object> statusData = new HashMap<>();
statusData.put("taskId", taskId);
statusData.put("status", "PROCESSING");
statusData.put("totalCount", excelList.size());
statusData.put("successCount", 0);
statusData.put("failureCount", 0);
statusData.put("progress", 0);
statusData.put("startTime", startTime);
statusData.put("message", "正在处理...");
redisTemplate.opsForHash().putAll(statusKey, statusData);
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
// 调用异步导入服务 // 调用异步导入服务
relationImportService.importRelationAsync(excelList, taskId, userName); relationImportService.importRelationAsync(excelList, taskId, userName);
@@ -228,79 +233,6 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
return taskId; return taskId;
} }
@Override
@Transactional
public StaffFmyRelationImportSubmitResultVO importRelationWithAssets(List<CcdiStaffFmyRelationExcel> relationList,
List<CcdiAssetInfoExcel> assetList) {
boolean hasRelationRows = relationList != null && !relationList.isEmpty();
boolean hasAssetRows = assetList != null && !assetList.isEmpty();
if (!hasRelationRows && !hasAssetRows) {
throw new RuntimeException("至少需要一条数据");
}
StaffFmyRelationImportSubmitResultVO result = new StaffFmyRelationImportSubmitResultVO();
result.setMessage(buildImportSubmitMessage(hasRelationRows, hasAssetRows));
if (hasRelationRows && !hasAssetRows) {
result.setRelationTaskId(importRelation(relationList));
return result;
}
if (!hasRelationRows) {
result.setAssetTaskId(assetInfoImportService.importAssetInfo(assetList));
return result;
}
String relationTaskId = UUID.randomUUID().toString();
String assetTaskId = UUID.randomUUID().toString();
initializeImportStatus("import:staffFmyRelation:", relationTaskId, relationList.size());
initializeImportStatus("import:assetInfo:", assetTaskId, assetList.size());
result.setRelationTaskId(relationTaskId);
result.setAssetTaskId(assetTaskId);
dualSheetImportOrchestrationService.importRelationWithAssetsAsync(
relationList,
relationTaskId,
assetList,
assetTaskId,
currentUserName()
);
return result;
}
private void initializeImportStatus(String keyPrefix, String taskId, int totalCount) {
Map<String, Object> statusData = new HashMap<>();
statusData.put("taskId", taskId);
statusData.put("status", "PROCESSING");
statusData.put("totalCount", totalCount);
statusData.put("successCount", 0);
statusData.put("failureCount", 0);
statusData.put("progress", 0);
statusData.put("startTime", System.currentTimeMillis());
statusData.put("message", "正在处理...");
String statusKey = keyPrefix + taskId;
redisTemplate.opsForHash().putAll(statusKey, statusData);
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
}
private String buildImportSubmitMessage(boolean hasRelationRows, boolean hasAssetRows) {
if (hasRelationRows && hasAssetRows) {
return "已提交员工亲属关系和亲属资产信息导入任务";
}
if (hasRelationRows) {
return "已提交员工亲属关系导入任务";
}
return "已提交亲属资产信息导入任务";
}
private String currentUserName() {
try {
return SecurityUtils.getUsername();
} catch (Exception e) {
return "system";
}
}
private CcdiAssetInfoVO toAssetInfoVO(CcdiAssetInfo assetInfo) { private CcdiAssetInfoVO toAssetInfoVO(CcdiAssetInfo assetInfo) {
CcdiAssetInfoVO assetInfoVO = new CcdiAssetInfoVO(); CcdiAssetInfoVO assetInfoVO = new CcdiAssetInfoVO();
BeanUtils.copyProperties(assetInfo, assetInfoVO); BeanUtils.copyProperties(assetInfo, assetInfoVO);

View File

@@ -165,8 +165,12 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
return new MainImportResult(Collections.emptyMap(), 0); return new MainImportResult(Collections.emptyMap(), 0);
} }
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> importedRecruitmentMap = new LinkedHashMap<>(); Set<String> existingRecruitIds = getExistingRecruitIds(
int successCount = 0; mainRows.stream().map(MainImportRow::data).toList()
);
Set<String> processedRecruitIds = new HashSet<>();
List<CcdiStaffRecruitment> newRecords = new ArrayList<>();
Map<String, CcdiStaffRecruitment> importedRecruitmentMap = new LinkedHashMap<>();
for (int index = 0; index < mainRows.size(); index++) { for (int index = 0; index < mainRows.size(); index++) {
MainImportRow mainRow = mainRows.get(index); MainImportRow mainRow = mainRows.get(index);
@@ -174,22 +178,36 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
try { try {
CcdiStaffRecruitmentAddDTO addDTO = new CcdiStaffRecruitmentAddDTO(); CcdiStaffRecruitmentAddDTO addDTO = new CcdiStaffRecruitmentAddDTO();
BeanUtils.copyProperties(excel, addDTO); BeanUtils.copyProperties(excel, addDTO);
addDTO.setRecruitType(normalizeRecruitType(excel.getRecruitType())); addDTO.setRecruitType(RecruitType.inferCode(addDTO.getRecruitName()));
validateRecruitmentData(addDTO, mainRow.sheetRowNum()); validateRecruitmentData(addDTO, mainRow.sheetRowNum());
String recruitId = trim(excel.getRecruitId()); String recruitId = trim(excel.getRecruitId());
if (existingRecruitIds.contains(recruitId)) {
throw buildValidationException(
MAIN_SHEET_NAME,
List.of(mainRow.sheetRowNum()),
String.format("招聘记录编号[%s]已存在,请勿重复导入", recruitId)
);
}
if (!processedRecruitIds.add(recruitId)) {
throw buildValidationException(
MAIN_SHEET_NAME,
List.of(mainRow.sheetRowNum()),
String.format("招聘记录编号[%s]在导入文件中重复,已跳过此条记录", recruitId)
);
}
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment(); CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
BeanUtils.copyProperties(excel, recruitment); BeanUtils.copyProperties(excel, recruitment);
recruitment.setRecruitId(recruitId); recruitment.setRecruitId(recruitId);
recruitment.setRecruitType(addDTO.getRecruitType()); recruitment.setRecruitType(addDTO.getRecruitType());
recruitment.setCreatedBy(userName); recruitment.setCreatedBy(userName);
recruitment.setUpdatedBy(userName); recruitment.setUpdatedBy(userName);
recruitmentMapper.insert(recruitment); newRecords.add(recruitment);
successCount++; importedRecruitmentMap.put(recruitId, recruitment);
addRecruitment(importedRecruitmentMap, recruitment);
ImportLogUtils.logProgress(log, taskId, index + 1, mainRows.size(), successCount, failures.size()); ImportLogUtils.logProgress(log, taskId, index + 1, mainRows.size(), newRecords.size(), failures.size());
} catch (Exception exception) { } catch (Exception exception) {
FailureMeta failureMeta = resolveFailureMeta(exception, List.of(mainRow.sheetRowNum()), MAIN_SHEET_NAME); FailureMeta failureMeta = resolveFailureMeta(exception, List.of(mainRow.sheetRowNum()), MAIN_SHEET_NAME);
failures.add(buildFailure(excel, failureMeta.sheetName(), failureMeta.sheetRowNum(), exception.getMessage())); failures.add(buildFailure(excel, failureMeta.sheetName(), failureMeta.sheetRowNum(), exception.getMessage()));
@@ -203,11 +221,16 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
} }
} }
return new MainImportResult(importedRecruitmentMap, successCount); if (!newRecords.isEmpty()) {
ImportLogUtils.logBatchOperationStart(log, taskId, "插入招聘信息", (newRecords.size() + 499) / 500, 500);
saveBatch(newRecords, 500);
}
return new MainImportResult(importedRecruitmentMap, newRecords.size());
} }
private int importWorkSheet(List<WorkImportRow> workRows, private int importWorkSheet(List<WorkImportRow> workRows,
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> importedRecruitmentMap, Map<String, CcdiStaffRecruitment> importedRecruitmentMap,
List<RecruitmentImportFailureVO> failures, List<RecruitmentImportFailureVO> failures,
String userName, String userName,
String taskId) { String taskId) {
@@ -215,7 +238,7 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
return 0; return 0;
} }
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> existingRecruitmentMap = Map<String, CcdiStaffRecruitment> existingRecruitmentMap =
getExistingRecruitmentMap(workRows, importedRecruitmentMap); getExistingRecruitmentMap(workRows, importedRecruitmentMap);
Map<String, List<WorkImportRow>> groupedRows = groupWorkRows(workRows); Map<String, List<WorkImportRow>> groupedRows = groupWorkRows(workRows);
int successCount = 0; int successCount = 0;
@@ -225,18 +248,15 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
processedGroups++; processedGroups++;
WorkImportRow firstRow = recruitWorkRows.get(0); WorkImportRow firstRow = recruitWorkRows.get(0);
String recruitId = trim(firstRow.data().getRecruitId()); String recruitId = trim(firstRow.data().getRecruitId());
CcdiStaffRecruitment recruitment = importedRecruitmentMap.get(recruitId);
if (recruitment == null) {
recruitment = existingRecruitmentMap.get(recruitId);
}
try { try {
RecruitmentMatchKey matchKey = buildMatchKey(firstRow.data());
CcdiStaffRecruitment recruitment = resolveMatchedRecruitment(
matchKey,
importedRecruitmentMap,
existingRecruitmentMap,
extractWorkRowNums(recruitWorkRows)
);
validateWorkGroup(recruitWorkRows, recruitment); validateWorkGroup(recruitWorkRows, recruitment);
if (recruitment != null && hasExistingWorkHistory(recruitment.getId())) { if (StringUtils.isNotEmpty(recruitId) && hasExistingWorkHistory(recruitId)) {
throw buildValidationException( throw buildValidationException(
WORK_SHEET_NAME, WORK_SHEET_NAME,
extractWorkRowNums(recruitWorkRows), extractWorkRowNums(recruitWorkRows),
@@ -244,7 +264,7 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
); );
} }
List<CcdiStaffRecruitmentWork> entities = buildWorkEntities(recruitWorkRows, recruitment, userName); List<CcdiStaffRecruitmentWork> entities = buildWorkEntities(recruitWorkRows, userName);
entities.forEach(entity -> recruitmentWorkMapper.insert(entity)); entities.forEach(entity -> recruitmentWorkMapper.insert(entity));
successCount += recruitWorkRows.size(); successCount += recruitWorkRows.size();
@@ -279,59 +299,33 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
} }
private String buildWorkGroupKey(WorkImportRow workRow) { private String buildWorkGroupKey(WorkImportRow workRow) {
RecruitmentMatchKey key = buildMatchKey(workRow.data()); String recruitId = trim(workRow.data().getRecruitId());
if (key.isComplete()) { if (StringUtils.isNotEmpty(recruitId)) {
return key.value(); return recruitId;
} }
return "__ROW__" + workRow.sheetRowNum(); return "__ROW__" + workRow.sheetRowNum();
} }
private Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> getExistingRecruitmentMap( private Map<String, CcdiStaffRecruitment> getExistingRecruitmentMap(List<WorkImportRow> workRows,
List<WorkImportRow> workRows, Map<String, CcdiStaffRecruitment> importedRecruitmentMap) {
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> importedRecruitmentMap
) {
LinkedHashSet<String> recruitIds = workRows.stream() LinkedHashSet<String> recruitIds = workRows.stream()
.filter(row -> !importedRecruitmentMap.containsKey(buildMatchKey(row.data())))
.map(row -> trim(row.data().getRecruitId())) .map(row -> trim(row.data().getRecruitId()))
.filter(StringUtils::isNotEmpty) .filter(StringUtils::isNotEmpty)
.filter(recruitId -> !importedRecruitmentMap.containsKey(recruitId))
.collect(Collectors.toCollection(LinkedHashSet::new)); .collect(Collectors.toCollection(LinkedHashSet::new));
if (recruitIds.isEmpty()) { if (recruitIds.isEmpty()) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
List<CcdiStaffRecruitment> recruitments = selectRecruitmentsByRecruitIds(recruitIds); List<CcdiStaffRecruitment> recruitments = recruitmentMapper.selectBatchIds(recruitIds);
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> result = new LinkedHashMap<>(); return recruitments.stream().collect(Collectors.toMap(CcdiStaffRecruitment::getRecruitId, item -> item));
recruitments.forEach(item -> addRecruitment(result, item));
return result;
} }
private CcdiStaffRecruitment resolveMatchedRecruitment( private List<CcdiStaffRecruitmentWork> buildWorkEntities(List<WorkImportRow> workRows, String userName) {
RecruitmentMatchKey matchKey,
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> importedRecruitmentMap,
Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> existingRecruitmentMap,
List<Integer> rowNums
) {
List<CcdiStaffRecruitment> matchedRecruitments = new ArrayList<>();
matchedRecruitments.addAll(importedRecruitmentMap.getOrDefault(matchKey, Collections.emptyList()));
matchedRecruitments.addAll(existingRecruitmentMap.getOrDefault(matchKey, Collections.emptyList()));
if (matchedRecruitments.size() > 1) {
throw buildValidationException(
WORK_SHEET_NAME,
rowNums,
String.format("招聘记录编号[%s]匹配到多条招聘主信息,无法确定历史工作经历归属", matchKey.recruitId())
);
}
return matchedRecruitments.isEmpty() ? null : matchedRecruitments.get(0);
}
private List<CcdiStaffRecruitmentWork> buildWorkEntities(List<WorkImportRow> workRows,
CcdiStaffRecruitment recruitment,
String userName) {
List<CcdiStaffRecruitmentWork> entities = new ArrayList<>(); List<CcdiStaffRecruitmentWork> entities = new ArrayList<>();
for (WorkImportRow workRow : workRows) { for (WorkImportRow workRow : workRows) {
CcdiStaffRecruitmentWork entity = new CcdiStaffRecruitmentWork(); CcdiStaffRecruitmentWork entity = new CcdiStaffRecruitmentWork();
BeanUtils.copyProperties(workRow.data(), entity); BeanUtils.copyProperties(workRow.data(), entity);
entity.setRecruitmentId(recruitment.getId()); entity.setRecruitId(trim(workRow.data().getRecruitId()));
entity.setRecruitId(recruitment.getRecruitId());
entity.setCreatedBy(userName); entity.setCreatedBy(userName);
entity.setUpdatedBy(userName); entity.setUpdatedBy(userName);
entities.add(entity); entities.add(entity);
@@ -339,9 +333,29 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
return entities; return entities;
} }
private boolean hasExistingWorkHistory(Long recruitmentId) { private Set<String> getExistingRecruitIds(List<CcdiStaffRecruitmentExcel> recruitmentList) {
List<String> recruitIds = recruitmentList.stream()
.map(CcdiStaffRecruitmentExcel::getRecruitId)
.map(this::trim)
.filter(StringUtils::isNotEmpty)
.toList();
if (recruitIds.isEmpty()) {
return Collections.emptySet();
}
LambdaQueryWrapper<CcdiStaffRecruitment> wrapper = new LambdaQueryWrapper<>();
wrapper.in(CcdiStaffRecruitment::getRecruitId, recruitIds);
List<CcdiStaffRecruitment> existingRecruitments = recruitmentMapper.selectList(wrapper);
return existingRecruitments.stream()
.map(CcdiStaffRecruitment::getRecruitId)
.collect(Collectors.toSet());
}
private boolean hasExistingWorkHistory(String recruitId) {
LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, recruitmentId); wrapper.eq(CcdiStaffRecruitmentWork::getRecruitId, recruitId);
return recruitmentWorkMapper.selectCount(wrapper) > 0; return recruitmentWorkMapper.selectCount(wrapper) > 0;
} }
@@ -362,22 +376,22 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "职位描述不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "职位描述不能为空");
} }
if (StringUtils.isEmpty(addDTO.getCandName())) { if (StringUtils.isEmpty(addDTO.getCandName())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "候选人姓名不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员姓名不能为空");
} }
if (StringUtils.isEmpty(addDTO.getCandEdu())) { if (StringUtils.isEmpty(addDTO.getCandEdu())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "学历不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员学历不能为空");
} }
if (StringUtils.isEmpty(addDTO.getCandId())) { if (StringUtils.isEmpty(addDTO.getCandId())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "证件号码不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "证件号码不能为空");
} }
if (StringUtils.isEmpty(addDTO.getCandSchool())) { if (StringUtils.isEmpty(addDTO.getCandSchool())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "毕业院校不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员毕业院校不能为空");
} }
if (StringUtils.isEmpty(addDTO.getCandMajor())) { if (StringUtils.isEmpty(addDTO.getCandMajor())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "专业不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员专业不能为空");
} }
if (StringUtils.isEmpty(addDTO.getCandGrad())) { if (StringUtils.isEmpty(addDTO.getCandGrad())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "毕业年月不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员毕业年月不能为空");
} }
if (StringUtils.isEmpty(addDTO.getAdmitStatus())) { if (StringUtils.isEmpty(addDTO.getAdmitStatus())) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "录用情况不能为空"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "录用情况不能为空");
@@ -400,23 +414,10 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
} }
if (RecruitType.getDescByCode(addDTO.getRecruitType()) == null) { if (RecruitType.getDescByCode(addDTO.getRecruitType()) == null) {
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘类型只能填写'SOCIAL/社招'或'CAMPUS/校招'"); throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘类型只能填写'SOCIAL'或'CAMPUS'");
} }
} }
private String normalizeRecruitType(String recruitType) {
String value = trim(recruitType);
if (StringUtils.isEmpty(value)) {
return value;
}
for (RecruitType type : RecruitType.values()) {
if (type.getCode().equals(value) || type.getDesc().equals(value)) {
return type.getCode();
}
}
return value;
}
private void validateWorkGroup(List<WorkImportRow> workRows, CcdiStaffRecruitment recruitment) { private void validateWorkGroup(List<WorkImportRow> workRows, CcdiStaffRecruitment recruitment) {
Set<Integer> processedSortOrders = new HashSet<>(); Set<Integer> processedSortOrders = new HashSet<>();
for (WorkImportRow workRow : workRows) { for (WorkImportRow workRow : workRows) {
@@ -450,14 +451,14 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "工作单位不能为空"); throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "工作单位不能为空");
} }
if (StringUtils.isEmpty(trim(excel.getPositionName()))) { if (StringUtils.isEmpty(trim(excel.getPositionName()))) {
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "岗位名称不能为空"); throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "岗位不能为空");
} }
if (StringUtils.isEmpty(trim(excel.getJobStartMonth()))) { if (StringUtils.isEmpty(trim(excel.getJobStartMonth()))) {
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "入职时间不能为空"); throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "入职年月不能为空");
} }
validateMonth(excel.getJobStartMonth(), "入职时间", sheetRowNum); validateMonth(excel.getJobStartMonth(), "入职年月", sheetRowNum);
if (StringUtils.isNotEmpty(trim(excel.getJobEndMonth()))) { if (StringUtils.isNotEmpty(trim(excel.getJobEndMonth()))) {
validateMonth(excel.getJobEndMonth(), "离职时间", sheetRowNum); validateMonth(excel.getJobEndMonth(), "离职年月", sheetRowNum);
} }
if (recruitment == null) { if (recruitment == null) {
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号不存在,请先维护招聘主信息"); throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号不存在,请先维护招聘主信息");
@@ -554,36 +555,30 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
redisTemplate.opsForHash().putAll(key, statusData); redisTemplate.opsForHash().putAll(key, statusData);
} }
private List<CcdiStaffRecruitment> selectRecruitmentsByRecruitIds(Set<String> recruitIds) { private void saveBatch(List<CcdiStaffRecruitment> list, int batchSize) {
if (recruitIds == null || recruitIds.isEmpty()) { for (int i = 0; i < list.size(); i += batchSize) {
return Collections.emptyList(); int end = Math.min(i + batchSize, list.size());
} List<CcdiStaffRecruitment> subList = list.subList(i, end);
LambdaQueryWrapper<CcdiStaffRecruitment> wrapper = new LambdaQueryWrapper<>();
wrapper.in(CcdiStaffRecruitment::getRecruitId, recruitIds); List<String> recruitIds = subList.stream()
return recruitmentMapper.selectList(wrapper); .map(CcdiStaffRecruitment::getRecruitId)
.toList();
if (recruitIds.isEmpty()) {
continue;
} }
private void addRecruitment(Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> map, List<CcdiStaffRecruitment> existingRecords = recruitmentMapper.selectBatchIds(recruitIds);
CcdiStaffRecruitment recruitment) { Set<String> existingIds = existingRecords.stream()
map.computeIfAbsent(buildMatchKey(recruitment), key -> new ArrayList<>()).add(recruitment); .map(CcdiStaffRecruitment::getRecruitId)
} .collect(Collectors.toSet());
private RecruitmentMatchKey buildMatchKey(CcdiStaffRecruitment recruitment) { List<CcdiStaffRecruitment> toInsert = subList.stream()
return new RecruitmentMatchKey( .filter(record -> !existingIds.contains(record.getRecruitId()))
trim(recruitment.getRecruitId()), .toList();
trim(recruitment.getCandName()), if (!toInsert.isEmpty()) {
trim(recruitment.getRecruitName()), recruitmentMapper.insertBatch(toInsert);
trim(recruitment.getPosName()) }
);
} }
private RecruitmentMatchKey buildMatchKey(CcdiStaffRecruitmentWorkExcel excel) {
return new RecruitmentMatchKey(
trim(excel.getRecruitId()),
trim(excel.getCandName()),
trim(excel.getRecruitName()),
trim(excel.getPosName())
);
} }
private List<MainImportRow> buildMainImportRows(List<CcdiStaffRecruitmentExcel> recruitmentList) { private List<MainImportRow> buildMainImportRows(List<CcdiStaffRecruitmentExcel> recruitmentList) {
@@ -633,25 +628,10 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
private record WorkImportRow(CcdiStaffRecruitmentWorkExcel data, int sheetRowNum) {} private record WorkImportRow(CcdiStaffRecruitmentWorkExcel data, int sheetRowNum) {}
private record MainImportResult(Map<RecruitmentMatchKey, List<CcdiStaffRecruitment>> importedRecruitmentMap, private record MainImportResult(Map<String, CcdiStaffRecruitment> importedRecruitmentMap, int successCount) {}
int successCount) {}
private record FailureMeta(String sheetName, String sheetRowNum) {} private record FailureMeta(String sheetName, String sheetRowNum) {}
private record RecruitmentMatchKey(String recruitId, String candName, String recruitName, String posName) {
private boolean isComplete() {
return StringUtils.isNotEmpty(recruitId)
&& StringUtils.isNotEmpty(candName)
&& StringUtils.isNotEmpty(recruitName)
&& StringUtils.isNotEmpty(posName);
}
private String value() {
return String.join("|", recruitId, candName, recruitName, posName);
}
}
private static class ImportValidationException extends RuntimeException { private static class ImportValidationException extends RuntimeException {
private final String sheetName; private final String sheetName;

View File

@@ -1,7 +1,6 @@
package com.ruoyi.info.collection.service.impl; package com.ruoyi.info.collection.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitment; import com.ruoyi.info.collection.domain.CcdiStaffRecruitment;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitmentWork; import com.ruoyi.info.collection.domain.CcdiStaffRecruitmentWork;
@@ -28,7 +27,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -110,15 +108,15 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
/** /**
* 查询招聘信息详情 * 查询招聘信息详情
* *
* @param id 主键ID * @param recruitId 招聘记录编号
* @return 招聘信息VO * @return 招聘信息VO
*/ */
@Override @Override
public CcdiStaffRecruitmentVO selectRecruitmentById(Long id) { public CcdiStaffRecruitmentVO selectRecruitmentById(String recruitId) {
CcdiStaffRecruitmentVO vo = recruitmentMapper.selectRecruitmentById(id); CcdiStaffRecruitmentVO vo = recruitmentMapper.selectRecruitmentById(recruitId);
if (vo != null) { if (vo != null) {
vo.setAdmitStatusDesc(AdmitStatus.getDescByCode(vo.getAdmitStatus())); vo.setAdmitStatusDesc(AdmitStatus.getDescByCode(vo.getAdmitStatus()));
vo.setWorkExperienceList(selectWorkExperienceList(vo.getId())); vo.setWorkExperienceList(selectWorkExperienceList(recruitId));
} }
return vo; return vo;
} }
@@ -132,14 +130,15 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
@Override @Override
@Transactional @Transactional
public int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO) { public int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO) {
String recruitId = trim(addDTO.getRecruitId()); // 检查招聘记录编号唯一性
if (recruitmentMapper.selectById(addDTO.getRecruitId()) != null) {
throw new RuntimeException("该招聘记录编号已存在");
}
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment(); CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
BeanUtils.copyProperties(addDTO, recruitment); BeanUtils.copyProperties(addDTO, recruitment);
recruitment.setRecruitId(recruitId);
int result = recruitmentMapper.insert(recruitment); int result = recruitmentMapper.insert(recruitment);
insertWorkExperienceList(recruitment.getId(), recruitId, addDTO.getRecruitType(), addDTO.getWorkExperienceList());
return result; return result;
} }
@@ -152,20 +151,9 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
@Override @Override
@Transactional @Transactional
public int updateRecruitment(CcdiStaffRecruitmentEditDTO editDTO) { public int updateRecruitment(CcdiStaffRecruitmentEditDTO editDTO) {
CcdiStaffRecruitment existing = recruitmentMapper.selectById(editDTO.getId());
if (existing == null) {
throw new RuntimeException("招聘信息不存在");
}
String recruitId = trim(editDTO.getRecruitId());
editDTO.setRecruitId(recruitId);
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment(); CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
BeanUtils.copyProperties(editDTO, recruitment); BeanUtils.copyProperties(editDTO, recruitment);
int result = recruitmentMapper.updateById(recruitment); int result = recruitmentMapper.updateById(recruitment);
if (!Objects.equals(existing.getRecruitId(), recruitId)) {
updateWorkRecruitId(editDTO.getId(), recruitId);
}
replaceWorkExperienceList(editDTO); replaceWorkExperienceList(editDTO);
return result; return result;
@@ -174,19 +162,16 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
/** /**
* 批量删除招聘信息 * 批量删除招聘信息
* *
* @param ids 需要删除的招聘信息ID * @param recruitIds 需要删除的招聘记录编号
* @return 结果 * @return 结果
*/ */
@Override @Override
@Transactional @Transactional
public int deleteRecruitmentByIds(Long[] ids) { public int deleteRecruitmentByIds(String[] recruitIds) {
List<Long> idList = Arrays.asList(ids);
if (!idList.isEmpty()) {
LambdaQueryWrapper<CcdiStaffRecruitmentWork> workWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CcdiStaffRecruitmentWork> workWrapper = new LambdaQueryWrapper<>();
workWrapper.in(CcdiStaffRecruitmentWork::getRecruitmentId, idList); workWrapper.in(CcdiStaffRecruitmentWork::getRecruitId, List.of(recruitIds));
recruitmentWorkMapper.delete(workWrapper); recruitmentWorkMapper.delete(workWrapper);
} return recruitmentMapper.deleteBatchIds(List.of(recruitIds));
return recruitmentMapper.deleteBatchIds(idList);
} }
/** /**
@@ -231,9 +216,9 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
return taskId; return taskId;
} }
private List<CcdiStaffRecruitmentWorkVO> selectWorkExperienceList(Long recruitmentId) { private List<CcdiStaffRecruitmentWorkVO> selectWorkExperienceList(String recruitId) {
LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, recruitmentId) wrapper.eq(CcdiStaffRecruitmentWork::getRecruitId, recruitId)
.orderByAsc(CcdiStaffRecruitmentWork::getSortOrder) .orderByAsc(CcdiStaffRecruitmentWork::getSortOrder)
.orderByDesc(CcdiStaffRecruitmentWork::getId); .orderByDesc(CcdiStaffRecruitmentWork::getId);
List<CcdiStaffRecruitmentWork> workList = recruitmentWorkMapper.selectList(wrapper); List<CcdiStaffRecruitmentWork> workList = recruitmentWorkMapper.selectList(wrapper);
@@ -247,20 +232,9 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
}).toList(); }).toList();
} }
private void updateWorkRecruitId(Long recruitmentId, String newRecruitId) {
LambdaUpdateWrapper<CcdiStaffRecruitmentWork> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, recruitmentId)
.set(CcdiStaffRecruitmentWork::getRecruitId, newRecruitId);
recruitmentWorkMapper.update(null, updateWrapper);
}
private String trim(String value) {
return value == null ? null : value.trim();
}
private void replaceWorkExperienceList(CcdiStaffRecruitmentEditDTO editDTO) { private void replaceWorkExperienceList(CcdiStaffRecruitmentEditDTO editDTO) {
LambdaQueryWrapper<CcdiStaffRecruitmentWork> deleteWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<CcdiStaffRecruitmentWork> deleteWrapper = new LambdaQueryWrapper<>();
deleteWrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, editDTO.getId()); deleteWrapper.eq(CcdiStaffRecruitmentWork::getRecruitId, editDTO.getRecruitId());
if (!Objects.equals(RecruitType.SOCIAL.getCode(), editDTO.getRecruitType())) { if (!Objects.equals(RecruitType.SOCIAL.getCode(), editDTO.getRecruitType())) {
recruitmentWorkMapper.delete(deleteWrapper); recruitmentWorkMapper.delete(deleteWrapper);
@@ -272,28 +246,12 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
} }
recruitmentWorkMapper.delete(deleteWrapper); recruitmentWorkMapper.delete(deleteWrapper);
List<CcdiStaffRecruitmentWork> workList = buildWorkExperienceEntities( List<CcdiStaffRecruitmentWork> workList = buildWorkExperienceEntities(editDTO);
editDTO.getId(),
editDTO.getRecruitId(),
editDTO.getWorkExperienceList()
);
workList.forEach(recruitmentWorkMapper::insert); workList.forEach(recruitmentWorkMapper::insert);
} }
private void insertWorkExperienceList(Long recruitmentId, private List<CcdiStaffRecruitmentWork> buildWorkExperienceEntities(CcdiStaffRecruitmentEditDTO editDTO) {
String recruitId, List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList = editDTO.getWorkExperienceList();
String recruitType,
List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList) {
if (!Objects.equals(RecruitType.SOCIAL.getCode(), recruitType)) {
return;
}
List<CcdiStaffRecruitmentWork> workList = buildWorkExperienceEntities(recruitmentId, recruitId, workExperienceList);
workList.forEach(recruitmentWorkMapper::insert);
}
private List<CcdiStaffRecruitmentWork> buildWorkExperienceEntities(Long recruitmentId,
String recruitId,
List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList) {
if (workExperienceList == null || workExperienceList.isEmpty()) { if (workExperienceList == null || workExperienceList.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
@@ -306,8 +264,7 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
} }
CcdiStaffRecruitmentWork work = new CcdiStaffRecruitmentWork(); CcdiStaffRecruitmentWork work = new CcdiStaffRecruitmentWork();
BeanUtils.copyProperties(item, work); BeanUtils.copyProperties(item, work);
work.setRecruitmentId(recruitmentId); work.setRecruitId(editDTO.getRecruitId());
work.setRecruitId(recruitId);
work.setSortOrder(i + 1); work.setSortOrder(i + 1);
entityList.add(work); entityList.add(work);
} }

View File

@@ -1,130 +0,0 @@
package com.ruoyi.info.collection.service.support;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.enums.EnterpriseSource;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import jakarta.annotation.Resource;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 关联业务实体库自动补全服务。
*/
@Service
public class EnterpriseAutoFillService {
private static final int BATCH_SIZE = 500;
@Resource
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
public record EnterpriseFillItem(
String socialCreditCode,
String enterpriseName,
String entSource,
String dataSource,
String userName
) {
}
@Transactional
public void ensureExists(EnterpriseFillItem item) {
ensureExistsBatch(List.of(item));
}
@Transactional
public void ensureExistsBatch(List<EnterpriseFillItem> items) {
if (StringUtils.isEmpty(items)) {
return;
}
Map<String, EnterpriseFillItem> normalizedItems = normalizeItems(items);
if (normalizedItems.isEmpty()) {
return;
}
Set<String> existingCodes = enterpriseBaseInfoMapper.selectBatchIds(new ArrayList<>(normalizedItems.keySet()))
.stream()
.map(CcdiEnterpriseBaseInfo::getSocialCreditCode)
.collect(Collectors.toSet());
List<CcdiEnterpriseBaseInfo> missingEntities = normalizedItems.entrySet().stream()
.filter(entry -> !existingCodes.contains(entry.getKey()))
.map(entry -> buildEntity(entry.getKey(), entry.getValue()))
.toList();
if (missingEntities.isEmpty()) {
return;
}
insertBatchIgnoreDuplicate(missingEntities);
}
private Map<String, EnterpriseFillItem> normalizeItems(List<EnterpriseFillItem> items) {
Map<String, EnterpriseFillItem> normalizedItems = new LinkedHashMap<>();
for (EnterpriseFillItem item : items) {
if (item == null || StringUtils.isEmpty(item.socialCreditCode())) {
continue;
}
String socialCreditCode = item.socialCreditCode().trim();
normalizedItems.putIfAbsent(socialCreditCode, new EnterpriseFillItem(
socialCreditCode,
trimToNull(item.enterpriseName()),
trimToNull(item.entSource()),
trimToNull(item.dataSource()),
trimToNull(item.userName())
));
}
return normalizedItems;
}
private CcdiEnterpriseBaseInfo buildEntity(String socialCreditCode, EnterpriseFillItem item) {
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
entity.setSocialCreditCode(socialCreditCode);
entity.setEnterpriseName(item.enterpriseName());
entity.setEntSource(item.entSource());
entity.setDataSource(item.dataSource());
entity.setRiskLevel(EnterpriseSource.INTERMEDIARY.getCode().equals(item.entSource()) ? "1" : null);
entity.setCreatedBy(item.userName());
entity.setUpdatedBy(item.userName());
return entity;
}
private void insertBatchIgnoreDuplicate(List<CcdiEnterpriseBaseInfo> entities) {
try {
for (int i = 0; i < entities.size(); i += BATCH_SIZE) {
int end = Math.min(i + BATCH_SIZE, entities.size());
enterpriseBaseInfoMapper.insertBatch(entities.subList(i, end));
}
} catch (DuplicateKeyException ex) {
insertOneByOneIgnoreDuplicate(entities);
}
}
private void insertOneByOneIgnoreDuplicate(List<CcdiEnterpriseBaseInfo> entities) {
for (CcdiEnterpriseBaseInfo entity : entities) {
if (enterpriseBaseInfoMapper.selectById(entity.getSocialCreditCode()) != null) {
continue;
}
try {
enterpriseBaseInfoMapper.insert(entity);
} catch (DuplicateKeyException duplicate) {
if (enterpriseBaseInfoMapper.selectById(entity.getSocialCreditCode()) == null) {
throw duplicate;
}
}
}
}
private String trimToNull(String value) {
if (StringUtils.isEmpty(value)) {
return null;
}
return value.trim();
}
}

View File

@@ -2,36 +2,19 @@ package com.ruoyi.info.collection.utils;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.ruoyi.common.annotation.DictDropdown;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.info.collection.handler.DictDropdownWriteHandler; import com.ruoyi.info.collection.handler.DictDropdownWriteHandler;
import com.ruoyi.info.collection.handler.RequiredFieldWriteHandler; import com.ruoyi.info.collection.handler.RequiredFieldWriteHandler;
import com.ruoyi.info.collection.handler.TextFormatWriteHandler; import com.ruoyi.info.collection.handler.TextFormatWriteHandler;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
/** /**
@@ -94,10 +77,8 @@ public class EasyExcelUtil {
* @return 数据列表 * @return 数据列表
*/ */
public static <T> List<T> importExcel(String fileName, Class<T> clazz) { public static <T> List<T> importExcel(String fileName, Class<T> clazz) {
try (InputStream inputStream = java.nio.file.Files.newInputStream(java.nio.file.Path.of(fileName))) { try {
return importExcel(inputStream, clazz); return EasyExcel.read(fileName).head(clazz).sheet().doReadSync();
} catch (ServiceException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("导入Excel失败", e); throw new RuntimeException("导入Excel失败", e);
} }
@@ -113,11 +94,7 @@ public class EasyExcelUtil {
*/ */
public static <T> List<T> importExcel(java.io.InputStream inputStream, Class<T> clazz) { public static <T> List<T> importExcel(java.io.InputStream inputStream, Class<T> clazz) {
try { try {
byte[] bytes = inputStream.readAllBytes(); return EasyExcel.read(inputStream).head(clazz).sheet().doReadSync();
validateDictDropdownTemplate(bytes, clazz, null);
return EasyExcel.read(new ByteArrayInputStream(bytes)).head(clazz).sheet().doReadSync();
} catch (ServiceException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("导入Excel失败", e); throw new RuntimeException("导入Excel失败", e);
} }
@@ -134,11 +111,7 @@ public class EasyExcelUtil {
*/ */
public static <T> List<T> importExcel(java.io.InputStream inputStream, Class<T> clazz, String sheetName) { public static <T> List<T> importExcel(java.io.InputStream inputStream, Class<T> clazz, String sheetName) {
try { try {
byte[] bytes = inputStream.readAllBytes(); return EasyExcel.read(inputStream).head(clazz).sheet(sheetName).doReadSync();
validateDictDropdownTemplate(bytes, clazz, sheetName);
return EasyExcel.read(new ByteArrayInputStream(bytes)).head(clazz).sheet(sheetName).doReadSync();
} catch (ServiceException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("导入Excel失败", e); throw new RuntimeException("导入Excel失败", e);
} }
@@ -155,10 +128,9 @@ public class EasyExcelUtil {
public static <T> void importTemplateExcel(HttpServletResponse response, Class<T> clazz, String sheetName) { public static <T> void importTemplateExcel(HttpServletResponse response, Class<T> clazz, String sheetName) {
try { try {
setResponseHeader(response, sheetName + "模板"); setResponseHeader(response, sheetName + "模板");
templateWriter(response, clazz) EasyExcel.write(response.getOutputStream(), clazz)
.sheet(sheetName) .sheet(sheetName)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new TextFormatWriteHandler(clazz))
.doWrite(List.of()); .doWrite(List.of());
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("下载导入模板失败", e); throw new RuntimeException("下载导入模板失败", e);
@@ -179,10 +151,9 @@ public class EasyExcelUtil {
WriteHandler... handlers) { WriteHandler... handlers) {
try { try {
setResponseHeader(response, sheetName + "模板"); setResponseHeader(response, sheetName + "模板");
var writerBuilder = templateWriter(response, clazz) var writerBuilder = EasyExcel.write(response.getOutputStream(), clazz)
.sheet(sheetName) .sheet(sheetName)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
.registerWriteHandler(new TextFormatWriteHandler(clazz));
// 注册所有自定义处理器 // 注册所有自定义处理器
for (WriteHandler handler : handlers) { for (WriteHandler handler : handlers) {
writerBuilder.registerWriteHandler(handler); writerBuilder.registerWriteHandler(handler);
@@ -219,7 +190,7 @@ public class EasyExcelUtil {
public static <T> void importTemplateWithDictDropdown(HttpServletResponse response, Class<T> clazz, String sheetName) { public static <T> void importTemplateWithDictDropdown(HttpServletResponse response, Class<T> clazz, String sheetName) {
try { try {
setResponseHeader(response, sheetName + "模板"); setResponseHeader(response, sheetName + "模板");
templateWriter(response, clazz) EasyExcel.write(response.getOutputStream(), clazz)
.sheet(sheetName) .sheet(sheetName)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new DictDropdownWriteHandler(clazz)) .registerWriteHandler(new DictDropdownWriteHandler(clazz))
@@ -246,7 +217,7 @@ public class EasyExcelUtil {
String sheetName, String fileName) { String sheetName, String fileName) {
try { try {
setResponseHeader(response, fileName); setResponseHeader(response, fileName);
templateWriter(response, clazz) EasyExcel.write(response.getOutputStream(), clazz)
.sheet(sheetName) .sheet(sheetName)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new DictDropdownWriteHandler(clazz)) .registerWriteHandler(new DictDropdownWriteHandler(clazz))
@@ -279,7 +250,7 @@ public class EasyExcelUtil {
String fileName String fileName
) { ) {
setResponseHeader(response, fileName); setResponseHeader(response, fileName);
try (ExcelWriter writer = templateWriter(response).build()) { try (ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build()) {
writer.write(List.of(), buildTemplateSheet(0, firstClazz, firstSheetName)); writer.write(List.of(), buildTemplateSheet(0, firstClazz, firstSheetName));
writer.write(List.of(), buildTemplateSheet(1, secondClazz, secondSheetName)); writer.write(List.of(), buildTemplateSheet(1, secondClazz, secondSheetName));
} catch (IOException e) { } catch (IOException e) {
@@ -290,6 +261,7 @@ public class EasyExcelUtil {
private static <T> WriteSheet buildTemplateSheet(int sheetNo, Class<T> clazz, String sheetName) { private static <T> WriteSheet buildTemplateSheet(int sheetNo, Class<T> clazz, String sheetName) {
return EasyExcel.writerSheet(sheetNo, sheetName) return EasyExcel.writerSheet(sheetNo, sheetName)
.head(clazz) .head(clazz)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new DictDropdownWriteHandler(clazz)) .registerWriteHandler(new DictDropdownWriteHandler(clazz))
.registerWriteHandler(new TextFormatWriteHandler(clazz)) .registerWriteHandler(new TextFormatWriteHandler(clazz))
.registerWriteHandler(new RequiredFieldWriteHandler(clazz)) .registerWriteHandler(new RequiredFieldWriteHandler(clazz))
@@ -350,137 +322,4 @@ public class EasyExcelUtil {
throw new RuntimeException("导出带字典下拉框的Excel失败", e); throw new RuntimeException("导出带字典下拉框的Excel失败", e);
} }
} }
private static void validateDictDropdownTemplate(byte[] bytes, Class<?> clazz, String sheetName) {
List<DropdownColumn> dropdownColumns = resolveDropdownColumns(clazz);
if (dropdownColumns.isEmpty()) {
return;
}
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(bytes))) {
Sheet sheet = sheetName == null ? workbook.getSheetAt(0) : workbook.getSheet(sheetName);
if (sheet == null) {
return;
}
int lastDataRowIndex = findLastDataRowIndex(sheet);
if (lastDataRowIndex < 1) {
return;
}
List<String> missingColumnTitles = new ArrayList<>();
for (DropdownColumn column : dropdownColumns) {
if (!isListValidationCovered(sheet, column.index(), lastDataRowIndex)) {
missingColumnTitles.add(column.title());
}
}
if (!missingColumnTitles.isEmpty()) {
throw new ServiceException(sheet.getSheetName() + " Sheet 的 "
+ String.join("", missingColumnTitles)
+ " 列缺少下拉框,请下载最新导入模板填写后重新导入");
}
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入Excel失败", e);
}
}
private static List<DropdownColumn> resolveDropdownColumns(Class<?> clazz) {
List<DropdownColumn> columns = new ArrayList<>();
Class<?> current = clazz;
while (current != null && current != Object.class) {
for (Field field : current.getDeclaredFields()) {
if (field.getAnnotation(DictDropdown.class) == null) {
continue;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty == null || excelProperty.index() < 0) {
continue;
}
columns.add(new DropdownColumn(excelProperty.index(), resolveColumnTitle(field, excelProperty)));
}
current = current.getSuperclass();
}
columns.sort(Comparator.comparingInt(DropdownColumn::index));
return columns;
}
private static String resolveColumnTitle(Field field, ExcelProperty excelProperty) {
if (excelProperty.value().length > 0 && excelProperty.value()[0] != null
&& !excelProperty.value()[0].isBlank()) {
return excelProperty.value()[0].replace("*", "");
}
return field.getName();
}
private static int findLastDataRowIndex(Sheet sheet) {
int lastDataRowIndex = -1;
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (hasData(row)) {
lastDataRowIndex = rowIndex;
}
}
return lastDataRowIndex;
}
private static boolean hasData(Row row) {
if (row == null || row.getLastCellNum() < 0) {
return false;
}
for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
if (cellIndex < 0) {
continue;
}
Cell cell = row.getCell(cellIndex);
if (cell != null && cell.toString() != null && !cell.toString().isBlank()) {
return true;
}
}
return false;
}
private static boolean isListValidationCovered(Sheet sheet, int columnIndex, int lastDataRowIndex) {
boolean[] coveredRows = new boolean[lastDataRowIndex + 1];
for (DataValidation validation : sheet.getDataValidations()) {
DataValidationConstraint constraint = validation.getValidationConstraint();
if (constraint == null || constraint.getValidationType() != DataValidationConstraint.ValidationType.LIST) {
continue;
}
for (CellRangeAddress address : validation.getRegions().getCellRangeAddresses()) {
if (address.getFirstColumn() > columnIndex || address.getLastColumn() < columnIndex) {
continue;
}
int firstRow = Math.max(1, address.getFirstRow());
int lastRow = Math.min(lastDataRowIndex, address.getLastRow());
for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
coveredRows[rowIndex] = true;
}
}
}
for (int rowIndex = 1; rowIndex <= lastDataRowIndex; rowIndex++) {
if (hasData(sheet.getRow(rowIndex)) && !coveredRows[rowIndex]) {
return false;
}
}
return true;
}
private record DropdownColumn(int index, String title) {}
private static <T> ExcelWriterBuilder templateWriter(HttpServletResponse response, Class<T> clazz)
throws IOException {
// 模板为空且体量小,使用内存工作簿避免 SXSSF 在无字体环境初始化 Fontconfig。
return EasyExcel.write(response.getOutputStream(), clazz).inMemory(Boolean.TRUE);
}
private static ExcelWriterBuilder templateWriter(HttpServletResponse response) throws IOException {
return EasyExcel.write(response.getOutputStream()).inMemory(Boolean.TRUE);
}
} }

View File

@@ -42,7 +42,7 @@
AND e.status = #{query.status} AND e.status = #{query.status}
</if> </if>
</where> </where>
ORDER BY e.create_time DESC, e.staff_id DESC ORDER BY e.create_time DESC
</select> </select>
<!-- 批量插入或更新员工信息只更新非null字段 --> <!-- 批量插入或更新员工信息只更新非null字段 -->

View File

@@ -53,9 +53,6 @@
<if test="query.relationName != null and query.relationName != ''"> <if test="query.relationName != null and query.relationName != ''">
AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%') AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%')
</if> </if>
<if test="query.relationCertNo != null and query.relationCertNo != ''">
AND r.relation_cert_no LIKE CONCAT('%', #{query.relationCertNo}, '%')
</if>
ORDER BY r.create_time DESC ORDER BY r.create_time DESC
</select> </select>

View File

@@ -61,9 +61,6 @@
<if test="query.relationName != null and query.relationName != ''"> <if test="query.relationName != null and query.relationName != ''">
AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%') AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%')
</if> </if>
<if test="query.relationCertNo != null and query.relationCertNo != ''">
AND r.relation_cert_no LIKE CONCAT('%', #{query.relationCertNo}, '%')
</if>
<if test="query.status != null"> <if test="query.status != null">
AND r.status = #{query.status} AND r.status = #{query.status}
</if> </if>
@@ -118,9 +115,6 @@
<if test="query.relationName != null and query.relationName != ''"> <if test="query.relationName != null and query.relationName != ''">
AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%') AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%')
</if> </if>
<if test="query.relationCertNo != null and query.relationCertNo != ''">
AND r.relation_cert_no LIKE CONCAT('%', #{query.relationCertNo}, '%')
</if>
<if test="query.status != null"> <if test="query.status != null">
AND r.status = #{query.status} AND r.status = #{query.status}
</if> </if>

View File

@@ -6,8 +6,7 @@
<!-- 招聘信息ResultMap --> <!-- 招聘信息ResultMap -->
<resultMap type="com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentVO" id="CcdiStaffRecruitmentVOResult"> <resultMap type="com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentVO" id="CcdiStaffRecruitmentVOResult">
<id property="id" column="id"/> <id property="recruitId" column="recruit_id"/>
<result property="recruitId" column="recruit_id"/>
<result property="recruitName" column="recruit_name"/> <result property="recruitName" column="recruit_name"/>
<result property="posName" column="pos_name"/> <result property="posName" column="pos_name"/>
<result property="posCategory" column="pos_category"/> <result property="posCategory" column="pos_category"/>
@@ -34,17 +33,17 @@
<!-- 分页查询招聘信息列表 --> <!-- 分页查询招聘信息列表 -->
<select id="selectRecruitmentPage" resultMap="CcdiStaffRecruitmentVOResult"> <select id="selectRecruitmentPage" resultMap="CcdiStaffRecruitmentVOResult">
SELECT SELECT
r.id, r.recruit_id, r.recruit_name, r.pos_name, r.pos_category, r.pos_desc, r.recruit_id, r.recruit_name, r.pos_name, r.pos_category, r.pos_desc,
r.cand_name, r.recruit_type, r.cand_edu, r.cand_id, r.cand_school, r.cand_major, r.cand_grad, r.cand_name, r.recruit_type, r.cand_edu, r.cand_id, r.cand_school, r.cand_major, r.cand_grad,
r.admit_status, COALESCE(w.work_experience_count, 0) AS work_experience_count, r.admit_status, COALESCE(w.work_experience_count, 0) AS work_experience_count,
r.interviewer_name1, r.interviewer_id1, r.interviewer_name2, r.interviewer_id2, r.interviewer_name1, r.interviewer_id1, r.interviewer_name2, r.interviewer_id2,
r.created_by, r.create_time, r.updated_by, r.update_time r.created_by, r.create_time, r.updated_by, r.update_time
FROM ccdi_staff_recruitment r FROM ccdi_staff_recruitment r
LEFT JOIN ( LEFT JOIN (
SELECT recruitment_id, COUNT(1) AS work_experience_count SELECT recruit_id COLLATE utf8mb4_general_ci AS recruit_id, COUNT(1) AS work_experience_count
FROM ccdi_staff_recruitment_work FROM ccdi_staff_recruitment_work
GROUP BY recruitment_id GROUP BY recruit_id COLLATE utf8mb4_general_ci
) w ON w.recruitment_id = r.id ) w ON w.recruit_id COLLATE utf8mb4_general_ci = r.recruit_id COLLATE utf8mb4_general_ci
<where> <where>
<if test="query.recruitName != null and query.recruitName != ''"> <if test="query.recruitName != null and query.recruitName != ''">
AND r.recruit_name LIKE CONCAT('%', #{query.recruitName}, '%') AND r.recruit_name LIKE CONCAT('%', #{query.recruitName}, '%')
@@ -79,16 +78,16 @@
<!-- 查询招聘信息详情 --> <!-- 查询招聘信息详情 -->
<select id="selectRecruitmentById" resultMap="CcdiStaffRecruitmentVOResult"> <select id="selectRecruitmentById" resultMap="CcdiStaffRecruitmentVOResult">
SELECT SELECT
id, recruit_id, recruit_name, pos_name, pos_category, pos_desc, recruit_id, recruit_name, pos_name, pos_category, pos_desc,
cand_name, recruit_type, cand_edu, cand_id, cand_school, cand_major, cand_grad, cand_name, recruit_type, cand_edu, cand_id, cand_school, cand_major, cand_grad,
admit_status, interviewer_name1, interviewer_id1, interviewer_name2, interviewer_id2, admit_status, interviewer_name1, interviewer_id1, interviewer_name2, interviewer_id2,
created_by, create_time, updated_by, update_time created_by, create_time, updated_by, update_time
FROM ccdi_staff_recruitment FROM ccdi_staff_recruitment
WHERE id = #{id} WHERE recruit_id = #{recruitId}
</select> </select>
<!-- 批量插入招聘信息数据 --> <!-- 批量插入招聘信息数据 -->
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="id"> <insert id="insertBatch">
INSERT INTO ccdi_staff_recruitment INSERT INTO ccdi_staff_recruitment
(recruit_id, recruit_name, pos_name, pos_category, pos_desc, (recruit_id, recruit_name, pos_name, pos_category, pos_desc,
cand_name, recruit_type, cand_edu, cand_id, cand_school, cand_major, cand_grad, cand_name, recruit_type, cand_edu, cand_id, cand_school, cand_major, cand_grad,
@@ -125,7 +124,7 @@
interviewer_id2 = #{item.interviewerId2}, interviewer_id2 = #{item.interviewerId2},
updated_by = #{item.updatedBy}, updated_by = #{item.updatedBy},
update_time = NOW() update_time = NOW()
WHERE id = #{item.id} WHERE recruit_id = #{item.recruitId}
</foreach> </foreach>
</update> </update>

View File

@@ -21,15 +21,4 @@ class CcdiBaseStaffMapperTest {
assertTrue(xml.contains("#{item.partyMember}"), xml); assertTrue(xml.contains("#{item.partyMember}"), xml);
} }
} }
@Test
void mapperXml_shouldUseStableOrderForBaseStaffPagination() throws Exception {
try (InputStream inputStream = getClass().getClassLoader()
.getResourceAsStream("mapper/info/collection/CcdiBaseStaffMapper.xml")) {
String xml = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)
.replaceAll("\\s+", " ");
assertTrue(xml.contains("ORDER BY e.create_time DESC, e.staff_id DESC"), xml);
}
}
} }

View File

@@ -96,26 +96,6 @@ class CcdiAssetInfoImportServiceImplTest {
assertEquals("320101199001010011", captor.getValue().get(0).getPersonId()); assertEquals("320101199001010011", captor.getValue().get(0).getPersonId());
} }
@Test
void importAssetInfoSync_shouldResolveFamilyIdFromCurrentWorkbookRelation() {
CcdiAssetInfoExcel excel = buildExcel("320101199001010033", "股权");
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
when(assetInfoMapper.selectOwnerCandidatesByRelationCertNos(List.of("320101199001010033")))
.thenReturn(List.of());
service.importAssetInfoSync(
List.of(excel),
"task-current-workbook",
"tester",
Map.of("320101199001010033", Set.of("320101199009090099"))
);
ArgumentCaptor<List<CcdiAssetInfo>> captor = ArgumentCaptor.forClass(List.class);
verify(assetInfoMapper).insertBatch(captor.capture());
assertEquals("320101199009090099", captor.getValue().get(0).getFamilyId());
assertEquals("320101199001010033", captor.getValue().get(0).getPersonId());
}
@Test @Test
void importAssetInfoAsync_shouldFailWhenEmployeeIdCardIsUsedForFamilyAssetImport() { void importAssetInfoAsync_shouldFailWhenEmployeeIdCardIsUsedForFamilyAssetImport() {
CcdiAssetInfoExcel excel = buildExcel("320101199001010011", "房产"); CcdiAssetInfoExcel excel = buildExcel("320101199001010011", "房产");

View File

@@ -19,7 +19,6 @@ import org.springframework.data.redis.core.ValueOperations;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -80,26 +79,6 @@ class CcdiBaseStaffAssetImportServiceImplTest {
assertEquals("320101199001010011", captor.getValue().get(0).getPersonId()); assertEquals("320101199001010011", captor.getValue().get(0).getPersonId());
} }
@Test
void importAssetInfoSync_shouldImportWhenOwnerComesFromCurrentWorkbook() {
CcdiBaseStaffAssetInfoExcel excel = buildExcel("320101199001010033", "存款");
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
when(assetInfoMapper.selectOwnerCandidatesByBaseStaffIdCards(List.of("320101199001010033")))
.thenReturn(List.of());
service.importAssetInfoSync(
List.of(excel),
"task-current-workbook",
"tester",
Map.of("320101199001010033", Set.of("320101199001010033"))
);
ArgumentCaptor<List<CcdiAssetInfo>> captor = ArgumentCaptor.forClass(List.class);
verify(assetInfoMapper).insertBatch(captor.capture());
assertEquals("320101199001010033", captor.getValue().get(0).getFamilyId());
assertEquals("320101199001010033", captor.getValue().get(0).getPersonId());
}
@Test @Test
void importAssetInfoAsync_shouldFailWhenFamilyCertificateIsUsed() { void importAssetInfoAsync_shouldFailWhenFamilyCertificateIsUsed() {
CcdiBaseStaffAssetInfoExcel excel = buildExcel("320101199201010022", "车辆"); CcdiBaseStaffAssetInfoExcel excel = buildExcel("320101199201010022", "车辆");

View File

@@ -1,13 +1,14 @@
package com.ruoyi.info.collection.service; package com.ruoyi.info.collection.service;
import com.ruoyi.info.collection.domain.CcdiBizIntermediary; import com.ruoyi.info.collection.domain.CcdiBizIntermediary;
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation; import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO; import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO;
import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper; import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper;
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper;
import com.ruoyi.info.collection.service.impl.CcdiIntermediaryEnterpriseRelationImportServiceImpl; import com.ruoyi.info.collection.service.impl.CcdiIntermediaryEnterpriseRelationImportServiceImpl;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@@ -22,7 +23,6 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@@ -42,7 +42,7 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
private CcdiBizIntermediaryMapper intermediaryMapper; private CcdiBizIntermediaryMapper intermediaryMapper;
@Mock @Mock
private EnterpriseAutoFillService enterpriseAutoFillService; private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
@Mock @Mock
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@@ -58,11 +58,11 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345"); CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345");
prepareFailureRedisMocks(); prepareFailureRedisMocks();
when(intermediaryMapper.selectList(any())).thenReturn(List.of()); when(intermediaryMapper.selectList(any())).thenReturn(List.of());
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of(enterprise("91330100MA27X12345")));
service.importAsync(List.of(excel), "task-owner-miss", "tester"); service.importAsync(List.of(excel), "task-owner-miss", "tester");
verify(relationMapper, never()).insertBatch(any()); verify(relationMapper, never()).insertBatch(any());
verify(enterpriseAutoFillService, never()).ensureExistsBatch(any());
IntermediaryEnterpriseRelationImportFailureVO failure = IntermediaryEnterpriseRelationImportFailureVO failure =
firstFailure("import:intermediary-enterprise-relation:task-owner-miss:failures"); firstFailure("import:intermediary-enterprise-relation:task-owner-miss:failures");
assertEquals("320101199001010014", failure.getOwnerPersonId()); assertEquals("320101199001010014", failure.getOwnerPersonId());
@@ -70,20 +70,20 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
} }
@Test @Test
void importEnterpriseRelationAsync_shouldAutoFillWhenEnterpriseDoesNotExist() { void importEnterpriseRelationAsync_shouldFailWhenEnterpriseDoesNotExist() {
CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345"); CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345");
prepareStatusRedisMock(); prepareFailureRedisMocks();
when(intermediaryMapper.selectList(any())).thenReturn(List.of(owner("owner-biz", "320101199001010014"))); when(intermediaryMapper.selectList(any())).thenReturn(List.of(owner("owner-biz", "320101199001010014")));
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of());
when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of()); when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of());
service.importAsync(List.of(excel), "task-ent-miss", "tester"); service.importAsync(List.of(excel), "task-ent-miss", "tester");
ArgumentCaptor<List<CcdiIntermediaryEnterpriseRelation>> relationCaptor = ArgumentCaptor.forClass(List.class); verify(relationMapper, never()).insertBatch(any());
verify(relationMapper).insertBatch(relationCaptor.capture()); IntermediaryEnterpriseRelationImportFailureVO failure =
assertEquals(1, relationCaptor.getValue().size()); firstFailure("import:intermediary-enterprise-relation:task-ent-miss:failures");
assertEquals("owner-biz", relationCaptor.getValue().get(0).getIntermediaryBizId()); assertEquals("91330100MA27X12345", failure.getSocialCreditCode());
assertEquals("91330100MA27X12345", relationCaptor.getValue().get(0).getSocialCreditCode()); assertTrue(failure.getErrorMessage().contains("机构表"));
assertIntermediaryAutoFill("91330100MA27X12345");
} }
@Test @Test
@@ -96,6 +96,10 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
owner("owner-biz-1", "320101199001010014"), owner("owner-biz-1", "320101199001010014"),
owner("owner-biz-2", "320101199003030035") owner("owner-biz-2", "320101199003030035")
)); ));
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of(
enterprise("91330100MA27X12345"),
enterprise("91330100MA27X12346")
));
when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of("owner-biz-1|91330100MA27X12345")); when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of("owner-biz-1|91330100MA27X12345"));
service.importAsync(List.of(duplicateInDb, duplicateInFile1, duplicateInFile2), "task-duplicate", "tester"); service.importAsync(List.of(duplicateInDb, duplicateInFile1, duplicateInFile2), "task-duplicate", "tester");
@@ -104,7 +108,6 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
verify(relationMapper).insertBatch(captor.capture()); verify(relationMapper).insertBatch(captor.capture());
assertEquals(1, captor.getValue().size()); assertEquals(1, captor.getValue().size());
assertEquals("owner-biz-2", captor.getValue().get(0).getIntermediaryBizId()); assertEquals("owner-biz-2", captor.getValue().get(0).getIntermediaryBizId());
assertIntermediaryAutoFill("91330100MA27X12346");
IntermediaryEnterpriseRelationImportFailureVO failure = IntermediaryEnterpriseRelationImportFailureVO failure =
firstFailure("import:intermediary-enterprise-relation:task-duplicate:failures"); firstFailure("import:intermediary-enterprise-relation:task-duplicate:failures");
assertTrue(failure.getErrorMessage().contains("重复") || failure.getErrorMessage().contains("已存在")); assertTrue(failure.getErrorMessage().contains("重复") || failure.getErrorMessage().contains("已存在"));
@@ -115,6 +118,7 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345"); CcdiIntermediaryEnterpriseRelationExcel excel = buildExcel("320101199001010014", "91330100MA27X12345");
prepareStatusRedisMock(); prepareStatusRedisMock();
when(intermediaryMapper.selectList(any())).thenReturn(List.of(owner("owner-biz", "320101199001010014"))); when(intermediaryMapper.selectList(any())).thenReturn(List.of(owner("owner-biz", "320101199001010014")));
when(enterpriseBaseInfoMapper.selectList(any())).thenReturn(List.of(enterprise("91330100MA27X12345")));
when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of()); when(relationMapper.batchExistsByCombinations(any())).thenReturn(List.of());
service.importAsync(List.of(excel), "task-success", "tester"); service.importAsync(List.of(excel), "task-success", "tester");
@@ -123,7 +127,6 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
verify(relationMapper).insertBatch(captor.capture()); verify(relationMapper).insertBatch(captor.capture());
assertEquals(1, captor.getValue().size()); assertEquals(1, captor.getValue().size());
assertEquals("owner-biz", captor.getValue().get(0).getIntermediaryBizId()); assertEquals("owner-biz", captor.getValue().get(0).getIntermediaryBizId());
assertIntermediaryAutoFill("91330100MA27X12345");
verify(valueOperations, never()).set(any(), any(), any(Long.class), any(TimeUnit.class)); verify(valueOperations, never()).set(any(), any(), any(Long.class), any(TimeUnit.class));
} }
@@ -160,15 +163,10 @@ class CcdiIntermediaryEnterpriseRelationImportServiceImplTest {
return owner; return owner;
} }
private void assertIntermediaryAutoFill(String socialCreditCode) { private CcdiEnterpriseBaseInfo enterprise(String socialCreditCode) {
ArgumentCaptor<List<EnterpriseAutoFillService.EnterpriseFillItem>> captor = ArgumentCaptor.forClass(List.class); CcdiEnterpriseBaseInfo enterprise = new CcdiEnterpriseBaseInfo();
verify(enterpriseAutoFillService).ensureExistsBatch(captor.capture()); enterprise.setSocialCreditCode(socialCreditCode);
assertEquals(1, captor.getValue().size()); enterprise.setEnterpriseName("机构" + socialCreditCode.substring(socialCreditCode.length() - 2));
EnterpriseAutoFillService.EnterpriseFillItem item = captor.getValue().get(0); return enterprise;
assertEquals(socialCreditCode, item.socialCreditCode());
assertNull(item.enterpriseName());
assertEquals("INTERMEDIARY", item.entSource());
assertEquals("IMPORT", item.dataSource());
assertEquals("tester", item.userName());
} }
} }

View File

@@ -2,8 +2,6 @@ package com.ruoyi.info.collection.service;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation; import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation; import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO; import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
@@ -12,10 +10,8 @@ import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationOptionVO;
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper; import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
import com.ruoyi.info.collection.service.impl.CcdiStaffEnterpriseRelationServiceImpl; import com.ruoyi.info.collection.service.impl.CcdiStaffEnterpriseRelationServiceImpl;
import com.ruoyi.info.collection.service.support.EnterpriseAutoFillService;
import org.apache.ibatis.builder.MapperBuilderAssistant; import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.Configuration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -24,17 +20,13 @@ import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.List; import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -63,17 +55,8 @@ class CcdiStaffEnterpriseRelationServiceImplTest {
@Mock @Mock
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Mock
private EnterpriseAutoFillService enterpriseAutoFillService;
@AfterEach
void clearSecurityContext() {
SecurityContextHolder.clearContext();
}
@Test @Test
void insertRelation_shouldAllowValidFamily() { void insertRelation_shouldAllowValidFamily() {
mockLoginUser("tester");
CcdiStaffEnterpriseRelationAddDTO addDTO = buildAddDto(); CcdiStaffEnterpriseRelationAddDTO addDTO = buildAddDto();
CcdiStaffFmyRelation familyRelation = new CcdiStaffFmyRelation(); CcdiStaffFmyRelation familyRelation = new CcdiStaffFmyRelation();
familyRelation.setRelationCertNo(addDTO.getPersonId()); familyRelation.setRelationCertNo(addDTO.getPersonId());
@@ -92,13 +75,6 @@ class CcdiStaffEnterpriseRelationServiceImplTest {
assertEquals(1, captor.getValue().getStatus()); assertEquals(1, captor.getValue().getStatus());
assertEquals("MANUAL", captor.getValue().getDataSource()); assertEquals("MANUAL", captor.getValue().getDataSource());
assertEquals(1, captor.getValue().getIsEmpFamily()); assertEquals(1, captor.getValue().getIsEmpFamily());
verify(enterpriseAutoFillService).ensureExists(argThat(item ->
"91310000123456789A".equals(item.socialCreditCode())
&& "测试企业".equals(item.enterpriseName())
&& "EMP_RELATION".equals(item.entSource())
&& "MANUAL".equals(item.dataSource())
&& "tester".equals(item.userName())
));
} }
@Test @Test
@@ -177,13 +153,4 @@ class CcdiStaffEnterpriseRelationServiceImplTest {
assistant.setCurrentNamespace(namespace); assistant.setCurrentNamespace(namespace);
TableInfoHelper.initTableInfo(assistant, entityClass); TableInfoHelper.initTableInfo(assistant, entityClass);
} }
private void mockLoginUser(String userName) {
SysUser user = new SysUser();
user.setUserName(userName);
LoginUser loginUser = new LoginUser(1L, 1L, user, Set.of());
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(loginUser, null, List.of());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} }

View File

@@ -1,8 +1,6 @@
package com.ruoyi.info.collection.service; package com.ruoyi.info.collection.service;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitment; import com.ruoyi.info.collection.domain.CcdiStaffRecruitment;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitmentWork;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel; import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel;
import com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO; import com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO;
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper; import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper;
@@ -29,7 +27,6 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -58,7 +55,7 @@ class CcdiStaffRecruitmentImportServiceImplTest {
void shouldFailWholeWorkGroupWhenExistingHistoryExists() { void shouldFailWholeWorkGroupWhenExistingHistoryExists() {
when(redisTemplate.opsForValue()).thenReturn(valueOperations); when(redisTemplate.opsForValue()).thenReturn(valueOperations);
when(redisTemplate.opsForHash()).thenReturn(hashOperations); when(redisTemplate.opsForHash()).thenReturn(hashOperations);
when(recruitmentMapper.selectList(any())).thenReturn(List.of(buildRecruitment("RC001"))); when(recruitmentMapper.selectBatchIds(any())).thenReturn(List.of(buildRecruitment("RC001")));
when(recruitmentWorkMapper.selectCount(any())).thenReturn(1L); when(recruitmentWorkMapper.selectCount(any())).thenReturn(1L);
CcdiStaffRecruitmentWorkExcel workRow = new CcdiStaffRecruitmentWorkExcel(); CcdiStaffRecruitmentWorkExcel workRow = new CcdiStaffRecruitmentWorkExcel();
@@ -89,81 +86,13 @@ class CcdiStaffRecruitmentImportServiceImplTest {
assertEquals("招聘记录编号[RC001]已存在历史工作经历,不允许重复导入", failure.getErrorMessage()); assertEquals("招聘记录编号[RC001]已存在历史工作经历,不允许重复导入", failure.getErrorMessage());
} }
@Test
void shouldAllowDuplicateRecruitIdsWhenImportingMainSheet() {
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
when(recruitmentMapper.insert(any(CcdiStaffRecruitment.class))).thenReturn(1);
CcdiStaffRecruitmentExcel first = buildRecruitmentExcel("RC001", "张三");
CcdiStaffRecruitmentExcel second = buildRecruitmentExcel("RC001", "李四");
service.importRecruitmentAsync(List.of(first, second), Collections.emptyList(), "task-2", "admin");
verify(recruitmentMapper, times(2)).insert(any(CcdiStaffRecruitment.class));
verify(valueOperations, never()).set(eq("import:recruitment:task-2:failures"), any(), anyLong(), any());
}
@Test
void shouldAttachWorkToMatchedRecruitmentWhenRecruitIdIsDuplicated() {
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
CcdiStaffRecruitment matched = buildRecruitment(10L, "RC001", "张三");
CcdiStaffRecruitment other = buildRecruitment(11L, "RC001", "李四");
when(recruitmentMapper.selectList(any())).thenReturn(List.of(matched, other));
when(recruitmentWorkMapper.selectCount(any())).thenReturn(0L);
CcdiStaffRecruitmentWorkExcel workRow = buildWorkExcel("RC001", "张三");
service.importRecruitmentAsync(Collections.emptyList(), List.of(workRow), "task-3", "admin");
ArgumentCaptor<CcdiStaffRecruitmentWork> workCaptor = ArgumentCaptor.forClass(CcdiStaffRecruitmentWork.class);
verify(recruitmentWorkMapper).insert(workCaptor.capture());
assertEquals(10L, workCaptor.getValue().getRecruitmentId());
assertEquals("RC001", workCaptor.getValue().getRecruitId());
}
private CcdiStaffRecruitment buildRecruitment(String recruitId) { private CcdiStaffRecruitment buildRecruitment(String recruitId) {
return buildRecruitment(1L, recruitId, "张三");
}
private CcdiStaffRecruitment buildRecruitment(Long id, String recruitId, String candName) {
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment(); CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
recruitment.setId(id);
recruitment.setRecruitId(recruitId); recruitment.setRecruitId(recruitId);
recruitment.setRecruitType("SOCIAL"); recruitment.setRecruitType("SOCIAL");
recruitment.setCandName(candName); recruitment.setCandName("张三");
recruitment.setRecruitName("社会招聘项目"); recruitment.setRecruitName("社会招聘项目");
recruitment.setPosName("Java工程师"); recruitment.setPosName("Java工程师");
return recruitment; return recruitment;
} }
private CcdiStaffRecruitmentExcel buildRecruitmentExcel(String recruitId, String candName) {
CcdiStaffRecruitmentExcel excel = new CcdiStaffRecruitmentExcel();
excel.setRecruitId(recruitId);
excel.setRecruitName("社会招聘项目");
excel.setPosName("Java工程师");
excel.setPosCategory("技术类");
excel.setPosDesc("负责系统开发");
excel.setAdmitStatus("录用");
excel.setCandName(candName);
excel.setRecruitType("SOCIAL");
excel.setCandEdu("本科");
excel.setCandId(candName.equals("张三") ? "110105199001010010" : "110105199002020026");
excel.setCandGrad("202110");
excel.setCandSchool("四川大学");
excel.setCandMajor("法学");
return excel;
}
private CcdiStaffRecruitmentWorkExcel buildWorkExcel(String recruitId, String candName) {
CcdiStaffRecruitmentWorkExcel workRow = new CcdiStaffRecruitmentWorkExcel();
workRow.setRecruitId(recruitId);
workRow.setCandName(candName);
workRow.setRecruitName("社会招聘项目");
workRow.setPosName("Java工程师");
workRow.setSortOrder(1);
workRow.setCompanyName("测试科技");
workRow.setPositionName("开发工程师");
workRow.setJobStartMonth("2022-01");
return workRow;
}
} }

View File

@@ -2,22 +2,12 @@ package com.ruoyi.info.collection.utils;
import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.info.collection.domain.excel.CcdiAccountInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel; import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
import com.ruoyi.info.collection.domain.excel.CcdiCustEnterpriseRelationExcel; import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiCustFmyRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel; import com.ruoyi.info.collection.domain.excel.CcdiEnterpriseBaseInfoExcel;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentExcel; import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel; import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
@@ -109,63 +99,6 @@ class EasyExcelUtilTemplateTest {
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) { try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
Sheet sheet = workbook.getSheetAt(0); Sheet sheet = workbook.getSheetAt(0);
assertTrue(hasValidationOnColumn(sheet, 7), "是否党员列应包含下拉校验"); assertTrue(hasValidationOnColumn(sheet, 7), "是否党员列应包含下拉校验");
assertHeaderValue(sheet, 0, "姓名*");
assertHeaderValue(sheet, 1, "员工ID*");
assertHeaderValue(sheet, 2, "所属部门ID*");
assertHeaderValue(sheet, 3, "身份证号*");
assertHeaderValue(sheet, 4, "电话*");
assertHeaderValue(sheet, 7, "是否党员*");
assertHeaderValue(sheet, 8, "状态*");
assertTextColumn(sheet, 3);
assertTextColumn(sheet, 4);
}
}
@Test
void importTemplateWithDictDropdown_shouldKeepBaseStaffDualSheetColumnWidths() throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
try (MockedStatic<DictUtils> mocked = mockStatic(DictUtils.class)) {
mocked.when(() -> DictUtils.getDictCache("ccdi_employee_status"))
.thenReturn(List.of(
buildDictData("在职", "0"),
buildDictData("离职", "1")
));
mocked.when(() -> DictUtils.getDictCache("ccdi_yes_no_flag"))
.thenReturn(List.of(
buildDictData("", "1"),
buildDictData("", "0")
));
mocked.when(() -> DictUtils.getDictCache("ccdi_asset_status"))
.thenReturn(List.of(
buildDictData("正常"),
buildDictData("冻结"),
buildDictData("处置中")
));
EasyExcelUtil.importTemplateWithDictDropdown(
response,
CcdiBaseStaffExcel.class,
"员工信息",
CcdiBaseStaffAssetInfoExcel.class,
"员工资产信息",
"员工信息维护导入模板"
);
}
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
Sheet staffSheet = workbook.getSheet("员工信息");
Sheet assetSheet = workbook.getSheet("员工资产信息");
assertNotNull(staffSheet);
assertNotNull(assetSheet);
assertColumnWidthsAtLeast(staffSheet, new int[] {16, 18, 20, 24, 18, 20, 18, 16, 14});
assertColumnWidthsAtLeast(assetSheet, new int[] {24, 18, 18, 24, 14, 20, 18, 18, 20, 16, 32});
assertHeaderValue(staffSheet, 0, "姓名*");
assertHeaderValue(staffSheet, 8, "状态*");
assertHeaderValue(assetSheet, 0, "员工身份证号*");
assertHeaderValue(assetSheet, 1, "资产大类*");
assertHeaderValue(assetSheet, 10, "备注");
} }
} }
@@ -180,11 +113,6 @@ class EasyExcelUtilTemplateTest {
buildDictData("未录用"), buildDictData("未录用"),
buildDictData("放弃") buildDictData("放弃")
)); ));
mocked.when(() -> DictUtils.getDictCache("ccdi_recruit_type"))
.thenReturn(List.of(
buildDictData("社招", "SOCIAL"),
buildDictData("校招", "CAMPUS")
));
EasyExcelUtil.importTemplateWithDictDropdown( EasyExcelUtil.importTemplateWithDictDropdown(
response, response,
@@ -200,8 +128,6 @@ class EasyExcelUtilTemplateTest {
assertEquals(2, workbook.getNumberOfSheets(), "招聘导入模板应输出双Sheet"); assertEquals(2, workbook.getNumberOfSheets(), "招聘导入模板应输出双Sheet");
assertEquals("招聘信息", workbook.getSheetAt(0).getSheetName()); assertEquals("招聘信息", workbook.getSheetAt(0).getSheetName());
assertEquals("历史工作经历", workbook.getSheetAt(1).getSheetName()); assertEquals("历史工作经历", workbook.getSheetAt(1).getSheetName());
assertTrue(hasValidationOnColumn(workbook.getSheetAt(0), 5), "录用情况列应包含下拉校验");
assertTrue(hasValidationOnColumn(workbook.getSheetAt(0), 7), "招聘类型列应包含下拉校验");
} }
} }
@@ -229,119 +155,12 @@ class EasyExcelUtilTemplateTest {
} }
} }
@Test
void infoImportTemplates_shouldFormatIdentifierAndContactColumnsAsText() throws Exception {
try (MockedStatic<DictUtils> mocked = mockStatic(DictUtils.class)) {
mockCommonDicts(mocked);
assertPlainTemplateTextColumns(CcdiAccountInfoExcel.class, "账户库管理", 1, 3, 7);
assertSingleTemplateTextColumns(CcdiAssetInfoExcel.class, "亲属资产信息", 0);
assertSingleTemplateTextColumns(CcdiBaseStaffAssetInfoExcel.class, "员工资产信息", 0);
assertDualTemplateTextColumns(
CcdiBaseStaffExcel.class,
"员工信息",
new int[] {3, 4},
CcdiBaseStaffAssetInfoExcel.class,
"员工资产信息",
new int[] {0},
"员工信息维护导入模板"
);
assertSingleTemplateTextColumns(CcdiCustEnterpriseRelationExcel.class, "信贷客户实体关联信息", 0, 1);
assertSingleTemplateTextColumns(CcdiCustFmyRelationExcel.class, "信贷客户家庭关系", 0, 6, 7, 8);
assertSingleTemplateTextColumns(CcdiEnterpriseBaseInfoExcel.class, "实体库管理", 0, 10);
assertSingleTemplateTextColumns(CcdiIntermediaryPersonExcel.class, "个人中介信息", 5, 6, 10, 12);
assertSingleTemplateTextColumns(CcdiIntermediaryEntityExcel.class, "实体中介信息", 1, 10);
assertSingleTemplateTextColumns(CcdiIntermediaryEnterpriseRelationExcel.class, "中介实体关联关系信息", 0, 1);
assertDualTemplateTextColumns(
CcdiPurchaseTransactionExcel.class,
"招投标主信息",
new int[] {0, 21, 24},
CcdiPurchaseTransactionSupplierExcel.class,
"供应商信息",
new int[] {0, 2, 4, 5},
"招投标信息维护导入模板"
);
assertSingleTemplateTextColumns(CcdiStaffEnterpriseRelationExcel.class, "员工亲属实体关联", 0, 1);
assertSingleTemplateTextColumns(CcdiStaffFmyRelationExcel.class, "员工亲属关系信息", 0, 6, 7, 8);
assertDualTemplateTextColumns(
CcdiStaffRecruitmentExcel.class,
"招聘信息",
new int[] {0, 9, 14, 16},
CcdiStaffRecruitmentWorkExcel.class,
"历史工作经历",
new int[] {0},
"招聘信息管理导入模板"
);
}
}
private void assertTextColumn(Sheet sheet, int columnIndex) { private void assertTextColumn(Sheet sheet, int columnIndex) {
CellStyle style = sheet.getColumnStyle(columnIndex); CellStyle style = sheet.getColumnStyle(columnIndex);
assertNotNull(style, "文本列应设置默认样式"); assertNotNull(style, "文本列应设置默认样式");
assertEquals("@", style.getDataFormatString(), "证件号列应使用文本格式"); assertEquals("@", style.getDataFormatString(), "证件号列应使用文本格式");
} }
private void assertHeaderValue(Sheet sheet, int columnIndex, String expectedValue) {
assertEquals(expectedValue, sheet.getRow(0).getCell(columnIndex).getStringCellValue());
}
private void assertTextColumns(Sheet sheet, int... columnIndexes) {
for (int columnIndex : columnIndexes) {
assertTextColumn(sheet, columnIndex);
}
}
private void assertPlainTemplateTextColumns(Class<?> clazz, String sheetName, int... columnIndexes) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
EasyExcelUtil.importTemplateExcel(response, clazz, sheetName);
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertTextColumns(workbook.getSheetAt(0), columnIndexes);
}
}
private void assertSingleTemplateTextColumns(Class<?> clazz, String sheetName, int... columnIndexes) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
EasyExcelUtil.importTemplateWithDictDropdown(response, clazz, sheetName);
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertTextColumns(workbook.getSheetAt(0), columnIndexes);
}
}
private <T1, T2> void assertDualTemplateTextColumns(Class<T1> firstClazz,
String firstSheetName,
int[] firstColumnIndexes,
Class<T2> secondClazz,
String secondSheetName,
int[] secondColumnIndexes,
String fileName) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
EasyExcelUtil.importTemplateWithDictDropdown(
response,
firstClazz,
firstSheetName,
secondClazz,
secondSheetName,
fileName
);
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
assertTextColumns(workbook.getSheet(firstSheetName), firstColumnIndexes);
assertTextColumns(workbook.getSheet(secondSheetName), secondColumnIndexes);
}
}
private void assertColumnWidthsAtLeast(Sheet sheet, int[] expectedWidths) {
for (int columnIndex = 0; columnIndex < expectedWidths.length; columnIndex++) {
int currentColumnIndex = columnIndex;
int expectedWidth = expectedWidths[currentColumnIndex];
int expected = expectedWidth * 256;
assertTrue(sheet.getColumnWidth(currentColumnIndex) >= expected,
() -> sheet.getSheetName() + "" + (currentColumnIndex + 1) + "列宽度应不小于" + expectedWidth);
}
}
private boolean hasValidationOnColumn(Sheet sheet, int columnIndex) { private boolean hasValidationOnColumn(Sheet sheet, int columnIndex) {
for (DataValidation validation : sheet.getDataValidations()) { for (DataValidation validation : sheet.getDataValidations()) {
for (CellRangeAddress address : validation.getRegions().getCellRangeAddresses()) { for (CellRangeAddress address : validation.getRegions().getCellRangeAddresses()) {
@@ -353,33 +172,6 @@ class EasyExcelUtilTemplateTest {
return false; return false;
} }
private void mockCommonDicts(MockedStatic<DictUtils> mocked) {
mocked.when(() -> DictUtils.getDictCache("ccdi_asset_status"))
.thenReturn(List.of(buildDictData("正常")));
mocked.when(() -> DictUtils.getDictCache("ccdi_employee_status"))
.thenReturn(List.of(buildDictData("在职", "1")));
mocked.when(() -> DictUtils.getDictCache("ccdi_yes_no_flag"))
.thenReturn(List.of(buildDictData("", "1")));
mocked.when(() -> DictUtils.getDictCache("ccdi_relation_type"))
.thenReturn(List.of(buildDictData("配偶")));
mocked.when(() -> DictUtils.getDictCache("ccdi_indiv_gender"))
.thenReturn(List.of(buildDictData("")));
mocked.when(() -> DictUtils.getDictCache("ccdi_certificate_type"))
.thenReturn(List.of(buildDictData("居民身份证")));
mocked.when(() -> DictUtils.getDictCache("ccdi_entity_type"))
.thenReturn(List.of(buildDictData("有限责任公司")));
mocked.when(() -> DictUtils.getDictCache("ccdi_enterprise_nature"))
.thenReturn(List.of(buildDictData("民营企业")));
mocked.when(() -> DictUtils.getDictCache("ccdi_person_type"))
.thenReturn(List.of(buildDictData("中介")));
mocked.when(() -> DictUtils.getDictCache("ccdi_person_sub_type"))
.thenReturn(List.of(buildDictData("本人")));
mocked.when(() -> DictUtils.getDictCache("ccdi_admit_status"))
.thenReturn(List.of(buildDictData("录用")));
mocked.when(() -> DictUtils.getDictCache("ccdi_recruit_type"))
.thenReturn(List.of(buildDictData("社招", "SOCIAL")));
}
private SysDictData buildDictData(String label) { private SysDictData buildDictData(String label) {
return buildDictData(label, label); return buildDictData(label, label);
} }

View File

@@ -15,7 +15,6 @@ import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
@@ -111,15 +110,7 @@ public class LsfxAnalysisClient {
* 上传文件 * 上传文件
*/ */
public UploadFileResponse uploadFile(Integer groupId, File file) { public UploadFileResponse uploadFile(Integer groupId, File file) {
return uploadFile(groupId, file, file.getName()); log.info("【流水分析】上传文件请求: groupId={}, fileName={}", groupId, file.getName());
}
/**
* 上传文件
*/
public UploadFileResponse uploadFile(Integer groupId, File file, String uploadFileName) {
String multipartFileName = StringUtils.hasText(uploadFileName) ? uploadFileName : file.getName();
log.info("【流水分析】上传文件请求: groupId={}, fileName={}", groupId, multipartFileName);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
try { try {
@@ -127,7 +118,7 @@ public class LsfxAnalysisClient {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put("groupId", groupId); params.put("groupId", groupId);
params.put("files", HttpUtil.namedFileResource(file, multipartFileName)); params.put("files", file);
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();
headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId); headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

View File

@@ -10,7 +10,6 @@ import org.springframework.http.*;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
@@ -32,24 +31,6 @@ public class HttpUtil {
@Resource @Resource
private ObjectMapper objectMapper; private ObjectMapper objectMapper;
public static org.springframework.core.io.Resource namedFileResource(File file, String filename) {
return new NamedFileSystemResource(file, filename);
}
private static class NamedFileSystemResource extends FileSystemResource {
private final String filename;
NamedFileSystemResource(File file, String filename) {
super(file);
this.filename = StringUtils.hasText(filename) ? filename : file.getName();
}
@Override
public String getFilename() {
return filename;
}
}
/** /**
* 发送GET请求带查询参数和请求头 * 发送GET请求带查询参数和请求头
* @param url 请求URL * @param url 请求URL
@@ -226,8 +207,6 @@ public class HttpUtil {
if (value instanceof File) { if (value instanceof File) {
File file = (File) value; File file = (File) value;
body.add(key, new FileSystemResource(file)); body.add(key, new FileSystemResource(file));
} else if (value instanceof org.springframework.core.io.Resource) {
body.add(key, value);
} else { } else {
body.add(key, value); body.add(key, value);
} }

View File

@@ -0,0 +1,78 @@
package com.ruoyi.ccdi.project.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.domain.dto.CcdiFundGraphEdgeDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiFundGraphManualEdgeSaveDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiFundGraphQueryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiFundGraphEdgeVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiFundGraphNodeVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiFundGraphStatementVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiFundGraphVO;
import com.ruoyi.ccdi.project.service.ICcdiFundGraphService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.utils.SecurityUtils;
import java.util.List;
/**
* 资金流图谱Controller
*/
@RestController
@RequestMapping("/ccdi/project/fund-graph")
@Tag(name = "资金流图谱")
public class CcdiFundGraphController extends BaseController {
@Resource
private ICcdiFundGraphService fundGraphService;
@GetMapping("/search")
@Operation(summary = "查询资金流图谱主体")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult searchSubjects(CcdiFundGraphQueryDTO queryDTO) {
List<CcdiFundGraphNodeVO> subjects = fundGraphService.searchSubjects(queryDTO);
return AjaxResult.success(subjects);
}
@GetMapping("/graph")
@Operation(summary = "查询一层资金流图谱")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getGraph(CcdiFundGraphQueryDTO queryDTO) {
CcdiFundGraphVO graph = fundGraphService.getFundGraph(queryDTO);
return AjaxResult.success(graph);
}
@GetMapping("/edge-detail")
@Operation(summary = "查询资金边流水明细")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public TableDataInfo getEdgeDetail(CcdiFundGraphEdgeDetailQueryDTO queryDTO) {
PageDomain pageDomain = TableSupport.buildPageRequest();
Page<CcdiFundGraphStatementVO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
Page<CcdiFundGraphStatementVO> result = fundGraphService.getEdgeDetails(page, queryDTO);
return getDataTable(result.getRecords(), result.getTotal());
}
@PostMapping("/manual-edge")
@Operation(summary = "新增手工资金流向")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult saveManualEdge(@RequestBody CcdiFundGraphManualEdgeSaveDTO saveDTO) {
try {
CcdiFundGraphEdgeVO edge = fundGraphService.saveManualEdge(saveDTO, SecurityUtils.getUsername());
return AjaxResult.success(edge);
} catch (IllegalArgumentException e) {
return AjaxResult.error(e.getMessage());
}
}
}

View File

@@ -2,14 +2,20 @@ package com.ruoyi.ccdi.project.controller;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectAbnormalAccountQueryDTO; import com.ruoyi.ccdi.project.domain.dto.CcdiProjectAbnormalAccountQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO; import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExternalPersonQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExternalRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO; import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO; import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO; import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSuspiciousTransactionQueryDTO; import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSuspiciousTransactionQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectExternalPersonWarningExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectRiskModelPeopleExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectRiskPeopleOverviewExcel; import com.ruoyi.ccdi.project.domain.excel.CcdiProjectRiskPeopleOverviewExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectSuspiciousTransactionExcel; import com.ruoyi.ccdi.project.domain.excel.CcdiProjectSuspiciousTransactionExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectAbnormalAccountPageVO; import com.ruoyi.ccdi.project.domain.vo.CcdiProjectAbnormalAccountPageVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativePageVO; import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativePageVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExternalRiskSummaryVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExternalPersonWarningVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisDetailVO; import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewDashboardVO; import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewDashboardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelCardsVO; import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelCardsVO;
@@ -67,6 +73,28 @@ public class CcdiProjectOverviewController extends BaseController {
return AjaxResult.success(overview); return AjaxResult.success(overview);
} }
/**
* 查询外部人员预警
*/
@GetMapping("/external-persons")
@Operation(summary = "查询外部人员预警")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getExternalPersons(CcdiProjectExternalPersonQueryDTO queryDTO) {
CcdiProjectExternalPersonWarningVO warnings = overviewService.getExternalPersonWarnings(queryDTO);
return AjaxResult.success(warnings);
}
/**
* 查询外部人员风险汇总
*/
@GetMapping("/external-persons/summary")
@Operation(summary = "查询外部人员风险汇总")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getExternalRiskSummary(Long projectId) {
CcdiProjectExternalRiskSummaryVO summary = overviewService.getExternalRiskSummary(projectId);
return AjaxResult.success(summary);
}
/** /**
* 查询中高风险人员TOP10 * 查询中高风险人员TOP10
*/ */
@@ -100,6 +128,28 @@ public class CcdiProjectOverviewController extends BaseController {
return AjaxResult.success(people); return AjaxResult.success(people);
} }
/**
* 查询外部人员风险模型卡片
*/
@GetMapping("/external-risk-models/cards")
@Operation(summary = "查询外部人员风险模型卡片")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getExternalRiskModelCards(Long projectId) {
CcdiProjectRiskModelCardsVO cards = overviewService.getExternalRiskModelCards(projectId);
return AjaxResult.success(cards);
}
/**
* 查询外部人员风险模型命中人员
*/
@GetMapping("/external-risk-models/people")
@Operation(summary = "查询外部人员风险模型命中人员")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getExternalRiskModelPeople(CcdiProjectExternalRiskModelPeopleQueryDTO queryDTO) {
CcdiProjectRiskModelPeopleVO people = overviewService.getExternalRiskModelPeople(queryDTO);
return AjaxResult.success(people);
}
/** /**
* 查询项目分析详情 * 查询项目分析详情
*/ */
@@ -173,6 +223,48 @@ public class CcdiProjectOverviewController extends BaseController {
util.exportExcel(response, rows, "风险人员总览"); util.exportExcel(response, rows, "风险人员总览");
} }
/**
* 导出外部人员预警
*/
@PostMapping("/external-persons/export")
@Operation(summary = "导出外部人员预警")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public void exportExternalPersons(HttpServletResponse response, Long projectId) {
List<CcdiProjectExternalPersonWarningExcel> rows = overviewService.exportExternalPersonWarnings(projectId);
ExcelUtil<CcdiProjectExternalPersonWarningExcel> util =
new ExcelUtil<>(CcdiProjectExternalPersonWarningExcel.class);
util.exportExcel(response, rows, "外部人员预警");
}
/**
* 导出风险模型命中人员
*/
@PostMapping("/risk-models/people/export")
@Operation(summary = "导出风险模型命中人员")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public void exportRiskModelPeople(HttpServletResponse response, CcdiProjectRiskModelPeopleQueryDTO queryDTO) {
List<CcdiProjectRiskModelPeopleExcel> rows = overviewService.exportRiskModelPeople(queryDTO);
ExcelUtil<CcdiProjectRiskModelPeopleExcel> util =
new ExcelUtil<>(CcdiProjectRiskModelPeopleExcel.class);
util.exportExcel(response, rows, "风险模型命中人员");
}
/**
* 导出外部人员风险模型命中人员
*/
@PostMapping("/external-risk-models/people/export")
@Operation(summary = "导出外部人员风险模型命中人员")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public void exportExternalRiskModelPeople(
HttpServletResponse response,
CcdiProjectExternalRiskModelPeopleQueryDTO queryDTO
) {
List<CcdiProjectRiskModelPeopleExcel> rows = overviewService.exportExternalRiskModelPeople(queryDTO);
ExcelUtil<CcdiProjectRiskModelPeopleExcel> util =
new ExcelUtil<>(CcdiProjectRiskModelPeopleExcel.class);
util.exportExcel(response, rows, "外部人员风险模型命中人员");
}
/** /**
* 导出风险明细 * 导出风险明细
*/ */
@@ -184,10 +276,10 @@ public class CcdiProjectOverviewController extends BaseController {
} }
/** /**
* 一键导出结果总览报告 * 导出结果总览报告
*/ */
@RequestMapping(value = "/report/export", method = { RequestMethod.GET, RequestMethod.POST }) @RequestMapping(value = "/report/export", method = { RequestMethod.GET, RequestMethod.POST })
@Operation(summary = "一键导出结果总览报告") @Operation(summary = "导出结果总览报告")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')") @PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public void exportOverviewReport(HttpServletResponse response, Long projectId) { public void exportOverviewReport(HttpServletResponse response, Long projectId) {
overviewService.exportOverviewReport(response, projectId); overviewService.exportOverviewReport(response, projectId);

View File

@@ -0,0 +1,55 @@
package com.ruoyi.ccdi.project.controller;
import com.ruoyi.ccdi.project.domain.dto.CcdiRelationGraphQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiRelationGraphSuspectedEnterpriseQueryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiRelationGraphNodeVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiRelationGraphSuspectedEnterpriseVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiRelationGraphVO;
import com.ruoyi.ccdi.project.service.ICcdiRelationGraphService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 关系图谱Controller
*/
@RestController
@RequestMapping("/ccdi/project/relation-graph")
@Tag(name = "关系图谱")
public class CcdiRelationGraphController extends BaseController {
@Resource
private ICcdiRelationGraphService relationGraphService;
@GetMapping("/search")
@Operation(summary = "查询关系图谱主体")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult searchSubjects(CcdiRelationGraphQueryDTO queryDTO) {
List<CcdiRelationGraphNodeVO> subjects = relationGraphService.searchSubjects(queryDTO);
return AjaxResult.success(subjects);
}
@GetMapping("/graph")
@Operation(summary = "查询一层关系图谱")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getGraph(CcdiRelationGraphQueryDTO queryDTO) {
CcdiRelationGraphVO graph = relationGraphService.getRelationGraph(queryDTO);
return AjaxResult.success(graph);
}
@GetMapping("/suspected-enterprises")
@Operation(summary = "查询关系图谱疑似同名企业")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getSuspectedEnterprises(CcdiRelationGraphSuspectedEnterpriseQueryDTO queryDTO) {
CcdiRelationGraphSuspectedEnterpriseVO result = relationGraphService.getSuspectedEnterprises(queryDTO);
return AjaxResult.success(result);
}
}

View File

@@ -40,6 +40,9 @@ public class CcdiBankStatementQueryDTO {
/** 本方主体 */ /** 本方主体 */
private List<String> ourSubjects; private List<String> ourSubjects;
/** 本方证件号 */
private List<String> ourCertNos;
/** 本方银行 */ /** 本方银行 */
private List<String> ourBanks; private List<String> ourBanks;

View File

@@ -0,0 +1,42 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* 资金流图谱边明细查询条件
*/
@Data
public class CcdiFundGraphEdgeDetailQueryDTO {
/** 项目ID历史字段资金流图谱不按项目过滤 */
private Long projectId;
/** 身份证号、员工姓名或本方户名 */
private String keyword;
/** 主体节点object_key复用图谱公共SQL片段时兼容条件判断 */
private String objectKey;
/** 边起点 */
private String fromKey;
/** 边终点 */
private String toKey;
/** 方向1支出2收入 */
private String direction;
/** 交易开始时间 */
private String transactionStartTime;
/** 交易结束时间 */
private String transactionEndTime;
/** 最小金额 */
private BigDecimal amountMin;
/** 最大金额 */
private BigDecimal amountMax;
}

View File

@@ -0,0 +1,45 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* 手工资金流向保存参数。
*/
@Data
public class CcdiFundGraphManualEdgeSaveDTO {
/** 起点主体object_key为空时默认使用当前查询中心 */
private String fromObjectKey;
/** 起点主体名称 */
private String fromName;
/** 终点主体object_key已有节点时传入 */
private String toObjectKey;
/** 终点主体名称;新建主体时必填 */
private String toName;
/** 终点主体身份证号/证件号有值时按md5(trim(idNo))复用主体 */
private String toIdNo;
/** 手工录入汇总金额 */
private BigDecimal amount;
/** 手工录入笔数 */
private Integer transactionCount;
/** 方向1支出2收入 */
private String direction;
/** 资金流向关系说明 */
private String relationDesc;
/** 来源说明 */
private String sourceDesc;
/** 分析备注 */
private String remark;
}

View File

@@ -0,0 +1,45 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* 资金流图谱查询条件
*/
@Data
public class CcdiFundGraphQueryDTO {
/** 项目ID历史字段资金流图谱不按项目过滤 */
private Long projectId;
/** 身份证号、员工姓名或本方户名 */
private String keyword;
/** 主体节点object_key节点穿透时直接使用 */
private String objectKey;
/** 交易开始时间 */
private String transactionStartTime;
/** 交易结束时间 */
private String transactionEndTime;
/** 最小金额 */
private BigDecimal amountMin;
/** 最大金额 */
private BigDecimal amountMax;
/** 最小汇总金额默认1000 */
private BigDecimal minTotalAmount;
/** 方向1支出2收入 */
private String direction;
/** 返回边数量上限 */
private Integer limit;
/** 预留追溯层级,一期固定按一层处理 */
private Integer depth;
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
/**
* 外部人员预警查询DTO
*/
@Data
public class CcdiProjectExternalPersonQueryDTO {
/** 项目ID */
private Long projectId;
/** 页码 */
private Integer pageNum;
/** 每页数量 */
private Integer pageSize;
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.ccdi.project.domain.dto;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Data;
/**
* 外部人员模型命中人员查询DTO
*/
@Data
public class CcdiProjectExternalRiskModelPeopleQueryDTO {
/** 项目ID */
private Long projectId;
/** 模型编码 */
private List<String> modelCodes;
/** 匹配方式 */
private String matchMode;
/** 关键字 */
private String keyword;
/** 页码 */
private Integer pageNum;
/** 每页数量 */
private Integer pageSize;
public String getModelCodesCsv() {
if (modelCodes == null || modelCodes.isEmpty()) {
return null;
}
return modelCodes.stream()
.filter(item -> item != null && !item.isBlank())
.map(String::trim)
.distinct()
.collect(Collectors.joining(","));
}
}

View File

@@ -0,0 +1,25 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
/**
* 关系图谱查询条件
*/
@Data
public class CcdiRelationGraphQueryDTO {
/** 项目ID历史字段关系图谱不按项目过滤 */
private Long projectId;
/** 身份证号、姓名、统一社会信用代码或节点object_key */
private String keyword;
/** 节点object_key节点穿透时直接使用 */
private String objectKey;
/** 返回边数量上限 */
private Integer limit;
/** 预留追溯层级,一期固定按一层处理 */
private Integer depth;
}

View File

@@ -0,0 +1,22 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
/**
* 关系图谱疑似企业查询条件
*/
@Data
public class CcdiRelationGraphSuspectedEnterpriseQueryDTO {
/** 姓名 */
private String personName;
/** 证件号 */
private String certNo;
/** 出生日期yyyy-MM-dd */
private String birthDate;
/** 返回数量上限 */
private Integer limit;
}

View File

@@ -207,6 +207,7 @@ public class CcdiBankStatement implements Serializable {
entity.setBatchSequence(item.getUploadSequnceNumber()); entity.setBatchSequence(item.getUploadSequnceNumber());
entity.setCustomerCertNo(item.getCustomerCertNo()); entity.setCustomerCertNo(item.getCustomerCertNo());
entity.setCustomerSocialCreditCode(item.getCustomerSocialCreditCode()); entity.setCustomerSocialCreditCode(item.getCustomerSocialCreditCode());
entity.setCretNo(normalizeCertNo(item.getCretNo()));
// 5. 特殊字段处理 // 5. 特殊字段处理
entity.setMetaJson(null); // 根据文档要求强制设为 null entity.setMetaJson(null); // 根据文档要求强制设为 null
@@ -219,4 +220,19 @@ public class CcdiBankStatement implements Serializable {
throw new RuntimeException("流水数据转换失败", e); throw new RuntimeException("流水数据转换失败", e);
} }
} }
private static String normalizeCertNo(String value) {
if (value == null || value.isBlank()) {
return null;
}
String normalized = value.trim()
.replace('', '-')
.replace('—', '-')
.replace('', '-');
int separatorIndex = normalized.indexOf('-');
if (separatorIndex >= 0) {
normalized = normalized.substring(0, separatorIndex).trim();
}
return normalized.isEmpty() ? null : normalized;
}
} }

View File

@@ -0,0 +1,35 @@
package com.ruoyi.ccdi.project.domain.excel;
import com.ruoyi.common.annotation.Excel;
import lombok.Data;
/**
* 外部人员预警导出对象
*/
@Data
public class CcdiProjectExternalPersonWarningExcel {
@Excel(name = "姓名")
private String name;
@Excel(name = "证件号")
private String idNo;
@Excel(name = "主体类型")
private String subjectType;
@Excel(name = "风险等级")
private String riskLevel;
@Excel(name = "命中模型数")
private Integer modelCount;
@Excel(name = "核心异常点")
private String riskPoint;
@Excel(name = "涉及对象")
private String relatedObject;
@Excel(name = "最近交易时间")
private String latestTradeTime;
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.ccdi.project.domain.excel;
import com.ruoyi.common.annotation.Excel;
import lombok.Data;
/**
* 风险模型命中人员导出对象
*/
@Data
public class CcdiProjectRiskModelPeopleExcel {
@Excel(name = "风险主体")
private String personName;
@Excel(name = "主体类型")
private String subjectType;
@Excel(name = "证件号")
private String idNo;
@Excel(name = "部门/涉及对象")
private String scopeName;
@Excel(name = "命中模型")
private String modelNames;
@Excel(name = "异常标签")
private String hitTags;
}

View File

@@ -14,20 +14,29 @@ public class CcdiProjectSuspiciousTransactionExcel {
@Excel(name = "交易时间") @Excel(name = "交易时间")
private String trxDate; private String trxDate;
@Excel(name = "可疑人员") @Excel(name = "本方账户")
private String suspiciousPersonName; private String leAccountNo;
@Excel(name = "关联人") @Excel(name = "本方主体")
private String relatedPersonName; private String leAccountName;
@Excel(name = "对方名称")
private String customerAccountName;
@Excel(name = "对方账户")
private String customerAccountNo;
@Excel(name = "关联员工") @Excel(name = "关联员工")
private String relatedStaffDisplay; private String relatedStaffDisplay;
@Excel(name = "关系") @Excel(name = "摘要")
private String relationType; private String userMemo;
@Excel(name = "摘要/交易类型") @Excel(name = "交易类型")
private String summaryAndCashType; private String cashType;
@Excel(name = "异常标签")
private String hitTags;
@Excel(name = "交易金额") @Excel(name = "交易金额")
private BigDecimal displayAmount; private BigDecimal displayAmount;

View File

@@ -0,0 +1,50 @@
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 资金流图谱汇总边
*/
@Data
public class CcdiFundGraphEdgeVO {
private String edgeKey;
private String fromKey;
private String toKey;
private String fromObjectKey;
private String toObjectKey;
private String fromName;
private String toName;
private BigDecimal totalAmount;
private Long transactionCount;
private String firstTrxDate;
private String lastTrxDate;
private String direction;
private String familyRelationType;
private String sourceType;
private String relationDesc;
private String sourceDesc;
private String remark;
private Integer depth;
private Boolean canTrace;
}

View File

@@ -0,0 +1,48 @@
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 资金流图谱节点
*/
@Data
public class CcdiFundGraphNodeVO {
private String nodeKey;
private String objectKey;
private String nodeName;
private String idNo;
private String cinocsno;
private String idnoType;
private String staffId;
private String sourceType;
private String nodeType;
private String identityType;
private String relationType;
private Long accountCount;
private String createdTime;
private String updatedTime;
private Boolean canExpand;
private Integer depth;
private BigDecimal totalAmount;
private Long transactionCount;
}

View File

@@ -0,0 +1,34 @@
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 资金流图谱边对应流水明细
*/
@Data
public class CcdiFundGraphStatementVO {
private Long bankStatementId;
private String trxDate;
private String leAccountNo;
private String leAccountName;
private String customerAccountName;
private String customerAccountNo;
private String cashType;
private String userMemo;
private BigDecimal amount;
private String direction;
private String familyRelationType;
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* 资金流图谱结果
*/
@Data
public class CcdiFundGraphVO {
private CcdiFundGraphNodeVO centerNode;
private List<CcdiFundGraphNodeVO> nodes = new ArrayList<>();
private List<CcdiFundGraphEdgeVO> edges = new ArrayList<>();
private BigDecimal totalAmount = BigDecimal.ZERO;
private Long transactionCount = 0L;
private Integer maxDepth = 1;
private Boolean traceReserved = true;
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.ccdi.project.domain.vo;
import java.util.List;
import lombok.Data;
/**
* 外部人员预警项
*/
@Data
public class CcdiProjectExternalPersonWarningItemVO {
private String name;
private String idNo;
private String subjectType;
private String riskLevel;
private String riskLevelType;
private Integer riskCount;
private Integer modelCount;
private String riskPoint;
private String relatedObject;
private String latestTradeTime;
private List<CcdiProjectRiskHitTagVO> riskPointTagList;
private String actionLabel;
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.ccdi.project.domain.vo;
import java.util.List;
import lombok.Data;
/**
* 外部人员预警分页
*/
@Data
public class CcdiProjectExternalPersonWarningVO {
private List<CcdiProjectExternalPersonWarningItemVO> rows;
private Long total;
private Long pageNum;
private Long pageSize;
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
/**
* 外部人员风险等级汇总
*/
@Data
public class CcdiProjectExternalRiskSummaryVO {
private Integer total;
private Integer high;
private Integer medium;
private Integer low;
private Integer noRisk;
}

View File

@@ -3,6 +3,7 @@ package com.ruoyi.ccdi.project.domain.vo;
import com.ruoyi.ccdi.project.domain.CcdiProject; import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectAbnormalAccountExcel; import com.ruoyi.ccdi.project.domain.excel.CcdiProjectAbnormalAccountExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectEmployeeCreditNegativeExcel; import com.ruoyi.ccdi.project.domain.excel.CcdiProjectEmployeeCreditNegativeExcel;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectExternalPersonWarningExcel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import lombok.Data; import lombok.Data;
@@ -21,10 +22,16 @@ public class CcdiProjectOverviewReportVO {
private CcdiProjectOverviewDashboardVO dashboard = new CcdiProjectOverviewDashboardVO(); private CcdiProjectOverviewDashboardVO dashboard = new CcdiProjectOverviewDashboardVO();
private CcdiProjectExternalRiskSummaryVO externalRiskSummary = new CcdiProjectExternalRiskSummaryVO();
private List<CcdiProjectOverviewReportModelSummaryVO> modelSummaries = new ArrayList<>(); private List<CcdiProjectOverviewReportModelSummaryVO> modelSummaries = new ArrayList<>();
private List<CcdiProjectOverviewReportModelSummaryVO> externalModelSummaries = new ArrayList<>();
private List<CcdiProjectRiskModelPeopleItemVO> riskPeople = new ArrayList<>(); private List<CcdiProjectRiskModelPeopleItemVO> riskPeople = new ArrayList<>();
private List<CcdiProjectExternalPersonWarningExcel> externalPersonWarnings = new ArrayList<>();
private List<CcdiProjectOverviewReportSuspiciousTransactionVO> suspiciousTransactions = new ArrayList<>(); private List<CcdiProjectOverviewReportSuspiciousTransactionVO> suspiciousTransactions = new ArrayList<>();
private List<CcdiProjectEmployeeCreditNegativeExcel> illegalPeople = new ArrayList<>(); private List<CcdiProjectEmployeeCreditNegativeExcel> illegalPeople = new ArrayList<>();

View File

@@ -13,4 +13,8 @@ public class CcdiProjectOverviewStatVO {
private String label; private String label;
private Integer value; private Integer value;
private Integer employeeValue;
private Integer externalValue;
} }

View File

@@ -33,4 +33,6 @@ public class CcdiProjectSuspiciousTransactionItemVO {
private Boolean hasModelRuleHit; private Boolean hasModelRuleHit;
private Boolean hasNameListHit; private Boolean hasNameListHit;
private String nameListHitType;
} }

Some files were not shown because too many files have changed in this diff Show More