Compare commits
32 Commits
2b321a8621
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| aa08ab4711 | |||
| b7db711906 | |||
| b7d020c0b2 | |||
| d444eafd5f | |||
| c9398881f3 | |||
| d79a60ab8c | |||
| e9403662e2 | |||
| fd79bfe62f | |||
| c7f4982451 | |||
| 0b2571b962 | |||
| 129e44c808 | |||
| 50c177da78 | |||
| c660025bcc | |||
| bd51991248 | |||
| a2ba044ebe | |||
| 110817abba | |||
| ff9627d0d9 | |||
| 2d1b02474c | |||
| 5a9b79d4ee | |||
| 0c5fa6b2c8 | |||
| 94507e3747 | |||
| fc6af5234d | |||
| 624b51292f | |||
| 6385778e4c | |||
| 60a7906eb3 | |||
| 49118a4418 | |||
| d2d36d75a7 | |||
| bc2a885abf | |||
| 018b085447 | |||
| 55f6eb9129 | |||
| addea20fa1 | |||
| d4ac165723 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -88,3 +88,9 @@ ruoyi-ui/vue.config.js
|
|||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
|
||||||
tests/
|
tests/
|
||||||
|
|
||||||
|
tongweb_62318.properties
|
||||||
|
|
||||||
|
.superpowers/
|
||||||
|
|
||||||
|
tmp/
|
||||||
87
AGENTS.md
87
AGENTS.md
@@ -15,21 +15,58 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 协作约定
|
## 高优先级规则
|
||||||
|
|
||||||
- 使用简体中文进行思考和对话
|
- 使用简体中文进行思考和对话
|
||||||
- Git 提交说明使用中文
|
- Git 提交说明必须使用中文
|
||||||
- Git 提交前必须检查暂存区,仅允许包含本次任务相关文件
|
- 忽略 `.DS_Store` 文件,不将其视为本次任务需要处理或提交的有效变更
|
||||||
- 若暂存区存在无关文件,必须先移出暂存或与用户确认,禁止顺带提交
|
- 仅当用户明确声明调用 `using-superpowers` 时才允许启用;未明确声明时按普通流程直接处理需求
|
||||||
- 根据设计文档产出实施计划时,默认输出两份文档:
|
- Git 提交前必须检查暂存区,仅允许包含本次任务相关文件;若存在无关文件,必须先移出暂存或与用户确认
|
||||||
- 后端实施计划放 `docs/plans/backend/`
|
- 每一次改动都需要留下实施文档,记录修改内容、影响范围与验证情况
|
||||||
- 前端实施计划放 `docs/plans/frontend/`
|
- 功能设计同时涉及前端和后端改动时,必须分别输出后端与前端两份实施计划;若仅涉及单侧,则只输出对应实施计划
|
||||||
|
- 新增或修改设计文档、实施计划、实施记录前,必须先确认保存路径是否正确
|
||||||
|
- 前端相关安装、构建、调试、测试命令执行前,必须先通过 `nvm` 切换并确认 Node 版本
|
||||||
|
- 测试结束后,自动关闭测试过程中启动的前后端进程
|
||||||
|
- 重启后端时,必须优先使用 `bin/restart_java_backend.sh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 协作约定
|
||||||
|
|
||||||
|
### 基础协作
|
||||||
|
|
||||||
- 前端开发直接在当前分支进行,不需要额外创建 git worktree
|
- 前端开发直接在当前分支进行,不需要额外创建 git worktree
|
||||||
|
- 给出方案时,必须保持最短路径实现,不允许提供兼容性、补丁性或过度设计的方案
|
||||||
|
- 不允许自行扩展出用户需求之外的兜底、降级或变体方案,避免业务逻辑偏移
|
||||||
|
- 输出方案前必须完成全链路逻辑校验,确保方案逻辑正确、链路闭环
|
||||||
|
|
||||||
|
### Git 与变更管理
|
||||||
|
|
||||||
|
- Git 提交前必须检查暂存区,仅保留本次任务相关文件
|
||||||
|
- 若暂存区存在无关文件,必须先移出暂存或与用户确认,禁止顺带提交
|
||||||
|
- `.DS_Store` 默认忽略,不纳入任务变更范围
|
||||||
|
|
||||||
|
### 文档产出
|
||||||
|
|
||||||
|
- 若需求来自设计文档,默认同时沉淀后端与前端两份实施计划
|
||||||
|
- 功能设计同时涉及前端和后端改动时,实施计划分别放在 `docs/plans/backend/` 与 `docs/plans/frontend/`
|
||||||
|
- 功能修改只涉及前端或只涉及后端时,只输出对应的实施计划
|
||||||
|
- 非前后端架构项目不强制拆分两份实施计划
|
||||||
|
- 每一次改动都需要留下实施文档,实施记录优先放在 `docs/reports/implementation/`
|
||||||
|
- 每次新增或修改设计文档、实施计划、实施记录前,都要先确认保存路径是否正确
|
||||||
|
|
||||||
|
### 测试与运行
|
||||||
|
|
||||||
- 测试结束后,自动关闭测试过程中启动的前后端进程
|
- 测试结束后,自动关闭测试过程中启动的前后端进程
|
||||||
- 重启后端时,必须优先使用 `bin/restart_java_backend.sh`,不要直接手工执行 `java -jar` 替代正式重启流程
|
- 重启后端时,必须优先使用 `bin/restart_java_backend.sh`,不要直接手工执行 `java -jar` 替代正式重启流程
|
||||||
|
- 前端相关安装、构建、调试、测试命令执行前,必须先通过 `nvm` 切换并确认 Node 版本
|
||||||
|
|
||||||
|
### 数据库与编码
|
||||||
|
|
||||||
- 遇到 MCP 数据库操作时,使用项目配置文件中的数据库连接信息
|
- 遇到 MCP 数据库操作时,使用项目配置文件中的数据库连接信息
|
||||||
- 执行包含中文内容的 MySQL SQL 脚本或数据库导入时,禁止直接手写 `mysql -e` 或普通重定向执行;必须优先使用 `bin/mysql_utf8_exec.sh <sql-file>`,确保会话字符集为 `utf8mb4`,避免导入或写入乱码
|
- 执行包含中文内容的 MySQL SQL 脚本或数据库导入时,禁止直接手写 `mysql -e` 或普通重定向执行;必须优先使用 `bin/mysql_utf8_exec.sh <sql-file>`,确保会话字符集为 `utf8mb4`
|
||||||
- 数据库字符集与排序规则统一要求:所有业务表、系统表新增或修改时,必须显式使用 `utf8mb4` 字符集与 `utf8mb4_general_ci` 排序规则;禁止引入 `utf8mb4_0900_ai_ci`、`utf8mb4_unicode_ci` 或其他混用排序规则
|
- 所有业务表、系统表新增或修改时,必须显式使用 `utf8mb4` 字符集与 `utf8mb4_general_ci` 排序规则
|
||||||
|
- 禁止引入 `utf8mb4_0900_ai_ci`、`utf8mb4_unicode_ci` 或其他混用排序规则
|
||||||
- 银行流水打标相关规则与参数编码需要统一使用全大写;新增或修改 `rule_code`、`indicator_code`、`param_code` 时,禁止混用大小写风格
|
- 银行流水打标相关规则与参数编码需要统一使用全大写;新增或修改 `rule_code`、`indicator_code`、`param_code` 时,禁止混用大小写风格
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -43,7 +80,7 @@
|
|||||||
mvn clean compile
|
mvn clean compile
|
||||||
|
|
||||||
# 启动主应用(Jar)
|
# 启动主应用(Jar)
|
||||||
cd ruoyi-admin/target && java -jar ruoyi-admin.jar
|
sh bin/restart_java_backend.sh
|
||||||
|
|
||||||
# 打包全部模块
|
# 打包全部模块
|
||||||
mvn clean package
|
mvn clean package
|
||||||
@@ -63,6 +100,9 @@ mvn clean package -DskipTests
|
|||||||
```bash
|
```bash
|
||||||
cd ruoyi-ui
|
cd ruoyi-ui
|
||||||
|
|
||||||
|
# 使用 nvm 切换到项目所需 Node 版本
|
||||||
|
nvm use
|
||||||
|
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
npm install --registry=https://registry.npmmirror.com
|
npm install --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
@@ -166,8 +206,10 @@ return AjaxResult.success(result);
|
|||||||
- 非业务字段如 `create_by`、`create_time` 由后端自动维护
|
- 非业务字段如 `create_by`、`create_time` 由后端自动维护
|
||||||
- 前端表单不要暴露通用审计字段
|
- 前端表单不要暴露通用审计字段
|
||||||
- 新增菜单、字典、初始化数据时,同步补充 SQL 脚本
|
- 新增菜单、字典、初始化数据时,同步补充 SQL 脚本
|
||||||
- 执行数据库脚本或导入数据库前,需确认客户端会话字符集为 `utf8mb4`;涉及中文插入、更新、导入时默认使用 `bin/mysql_utf8_exec.sh`
|
- 执行数据库脚本或导入数据库前,需确认客户端会话字符集为 `utf8mb4`
|
||||||
- 所有系统表和业务表的表级、字符字段级排序规则统一为 `utf8mb4_general_ci`;新增建表 SQL、字段追加 SQL、表结构修复 SQL 必须显式声明,避免因默认排序规则漂移导致联表或条件查询报错
|
- 涉及中文插入、更新、导入时默认使用 `bin/mysql_utf8_exec.sh`
|
||||||
|
- 所有系统表和业务表的表级、字符字段级排序规则统一为 `utf8mb4_general_ci`
|
||||||
|
- 新增建表 SQL、字段追加 SQL、表结构修复 SQL 必须显式声明字符集与排序规则,避免因默认排序规则漂移导致联表或条件查询报错
|
||||||
|
|
||||||
### 前端规范
|
### 前端规范
|
||||||
|
|
||||||
@@ -183,6 +225,18 @@ return AjaxResult.success(result);
|
|||||||
- 返回结果仅展示失败数据
|
- 返回结果仅展示失败数据
|
||||||
- 大数据量导入优先采用 EasyExcel + 异步处理
|
- 大数据量导入优先采用 EasyExcel + 异步处理
|
||||||
|
|
||||||
|
### 导入页面测试规范
|
||||||
|
|
||||||
|
- 导入功能测试必须进入真实业务页面执行,先在页面内下载当前导入模板,再基于该模板生成测试文件,禁止手工凭记忆新建表头或脱离页面直接构造上传文件
|
||||||
|
- 双 Sheet 模板的导入测试必须覆盖两个 Sheet 的联动关系;除“缺少 Sheet / 空 Sheet”专项场景外,默认两个 Sheet 都要准备测试数据
|
||||||
|
- 导入测试文件优先放在 `output/spreadsheet/` 或 `output/playwright/`,不提交到 git
|
||||||
|
- 需要按场景拆分测试文件,避免多个互斥校验互相覆盖;至少覆盖空模板、主信息必填、主信息格式与金额、主从关系异常、供应商校验、缺少/空 Sheet、成功导入、成功与失败混合、失败记录查看、导入后清理回滚
|
||||||
|
- 主从关系异常测试至少覆盖:已存在主键、供应商有数据但主信息缺失、主信息重复、供应商 Sheet 中采购事项 ID 为空
|
||||||
|
- 供应商校验测试至少覆盖:重复供应商、多条中标、供应商名称为空、名称超长、联系人超长、银行账户超长、联系电话非法、统一信用代码非法、是否中标枚举非法
|
||||||
|
- 页面上传后必须核对页面提示、导入状态、失败记录弹窗和列表总数变化;异步导入场景还要核对任务状态从 `PROCESSING` 到最终状态的变化
|
||||||
|
- 对“成功导入 + 异常数据混合”的样本,必须额外核对成功数据是否真正入库、异常数据是否被拦截,以及是否存在被静默忽略的行
|
||||||
|
- 导入测试结束后,必须删除本轮成功写入的测试数据,清理页面本地导入任务缓存,并关闭测试过程中启动的前后端进程
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 当前仓库结构
|
## 当前仓库结构
|
||||||
@@ -228,15 +282,10 @@ ccdi/
|
|||||||
### 主要业务代码分布
|
### 主要业务代码分布
|
||||||
|
|
||||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/`
|
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/`
|
||||||
- 含 `controller`、`domain`、`mapper`、`service`、`annotation`、`validation` 等目录
|
|
||||||
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/`
|
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/`
|
||||||
- 含 `config`、`controller`、`domain`、`mapper`、`service`
|
|
||||||
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/`
|
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/`
|
||||||
- 含 `client`、`config`、`constants`、`controller`、`domain/request`、`domain/response`
|
|
||||||
- `ruoyi-ui/src/views/`
|
- `ruoyi-ui/src/views/`
|
||||||
- 当前包含 `ccdi`、`ccdiBaseStaff`、`ccdiProject`、`ccdiPurchaseTransaction`、`ccdiIntermediary`、亲属关系、员工调动、招聘等业务页面
|
|
||||||
- `ruoyi-ui/src/api/ccdi/`
|
- `ruoyi-ui/src/api/ccdi/`
|
||||||
- 放置纪检初核业务 API 封装
|
|
||||||
|
|
||||||
### 添加新后端模块时
|
### 添加新后端模块时
|
||||||
|
|
||||||
@@ -297,6 +346,9 @@ ccdi/
|
|||||||
- 只有历史资料或外部原始材料才放入 `assets/`
|
- 只有历史资料或外部原始材料才放入 `assets/`
|
||||||
- 如果移动了文档,需同步修正文档内引用路径
|
- 如果移动了文档,需同步修正文档内引用路径
|
||||||
- 若需求来自设计文档,默认同时沉淀后端与前端两份实施计划
|
- 若需求来自设计文档,默认同时沉淀后端与前端两份实施计划
|
||||||
|
- 功能设计同时涉及前端和后端改动时,必须分别输出后端与前端两份实施计划;若仅涉及前端或仅涉及后端,则只输出对应实施计划;非前后端架构项目不强制拆分双文档
|
||||||
|
- 每一次改动都需要留下实施文档,记录本次修改内容、影响范围与验证情况,实施记录优先放在 `docs/reports/implementation/`
|
||||||
|
- 每次新增或修改设计文档、实施计划、实施记录前,都要先确认保存路径是否正确
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -307,3 +359,4 @@ ccdi/
|
|||||||
- `docker/backend`、`docker/frontend`、`docker/mock` 分别对应三类运行时镜像
|
- `docker/backend`、`docker/frontend`、`docker/mock` 分别对应三类运行时镜像
|
||||||
- `sql/migration/` 用于增量迁移脚本,新增修复脚本优先按日期或功能命名
|
- `sql/migration/` 用于增量迁移脚本,新增修复脚本优先按日期或功能命名
|
||||||
- 启动前后端或 Mock 服务做验证后,结束测试时要主动停止进程,避免残留占用端口
|
- 启动前后端或 Mock 服务做验证后,结束测试时要主动停止进程,避免残留占用端口
|
||||||
|
- 前端相关安装、构建、调试、测试命令执行前,必须先通过 `nvm` 切换并确认 Node 版本
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ follow_logs() {
|
|||||||
start_action() {
|
start_action() {
|
||||||
running_pids=$(collect_pids)
|
running_pids=$(collect_pids)
|
||||||
if [ -n "${running_pids:-}" ]; then
|
if [ -n "${running_pids:-}" ]; then
|
||||||
log_error "检测到已有后端进程在运行: $running_pids,请先执行 stop 或 restart"
|
log_error "检测到已有后端进程在运行: ${running_pids},请先执行 stop 或 restart"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -80,18 +80,6 @@ public class CcdiAccountInfoController extends BaseController {
|
|||||||
return success(accountInfoService.selectAccountInfoById(id));
|
return success(accountInfoService.selectAccountInfoById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出账户库列表
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出账户库列表")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:accountInfo:export')")
|
|
||||||
@Log(title = "账户库管理", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiAccountInfoQueryDTO queryDTO) {
|
|
||||||
List<CcdiAccountInfoExcel> list = accountInfoService.selectAccountInfoListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiAccountInfoExcel.class, "账户库管理");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增账户
|
* 新增账户
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ 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.*;
|
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;
|
||||||
@@ -45,6 +47,9 @@ public class CcdiBaseStaffController extends BaseController {
|
|||||||
@Resource
|
@Resource
|
||||||
private ICcdiBaseStaffImportService importAsyncService;
|
private ICcdiBaseStaffImportService importAsyncService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ICcdiBaseStaffAssetImportService baseStaffAssetImportService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工列表
|
* 查询员工列表
|
||||||
*/
|
*/
|
||||||
@@ -70,18 +75,6 @@ public class CcdiBaseStaffController extends BaseController {
|
|||||||
return success(list);
|
return success(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出员工列表
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出员工列表")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:baseStaff:export')")
|
|
||||||
@Log(title = "员工信息", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiBaseStaffQueryDTO queryDTO) {
|
|
||||||
List<CcdiBaseStaffExcel> list = baseStaffService.selectBaseStaffListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiBaseStaffExcel.class, "员工信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取员工详细信息
|
* 获取员工详细信息
|
||||||
*/
|
*/
|
||||||
@@ -132,7 +125,14 @@ public class CcdiBaseStaffController extends BaseController {
|
|||||||
@Operation(summary = "下载导入模板")
|
@Operation(summary = "下载导入模板")
|
||||||
@PostMapping("/importTemplate")
|
@PostMapping("/importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiBaseStaffExcel.class, "员工信息");
|
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||||
|
response,
|
||||||
|
CcdiBaseStaffExcel.class,
|
||||||
|
"员工信息",
|
||||||
|
CcdiBaseStaffAssetInfoExcel.class,
|
||||||
|
"员工资产信息",
|
||||||
|
"员工信息维护导入模板"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,21 +142,33 @@ public class CcdiBaseStaffController extends BaseController {
|
|||||||
@PreAuthorize("@ss.hasPermi('ccdi:baseStaff:import')")
|
@PreAuthorize("@ss.hasPermi('ccdi:baseStaff:import')")
|
||||||
@Log(title = "员工信息", businessType = BusinessType.IMPORT)
|
@Log(title = "员工信息", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importData")
|
@PostMapping("/importData")
|
||||||
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
|
public AjaxResult importData(MultipartFile file) throws Exception {
|
||||||
List<CcdiBaseStaffExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiBaseStaffExcel.class);
|
List<CcdiBaseStaffExcel> staffList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiBaseStaffExcel.class,
|
||||||
|
"员工信息"
|
||||||
|
);
|
||||||
|
List<CcdiBaseStaffAssetInfoExcel> assetList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiBaseStaffAssetInfoExcel.class,
|
||||||
|
"员工资产信息"
|
||||||
|
);
|
||||||
|
|
||||||
if (list == null || list.isEmpty()) {
|
boolean hasStaffRows = staffList != null && !staffList.isEmpty();
|
||||||
|
boolean hasAssetRows = assetList != null && !assetList.isEmpty();
|
||||||
|
|
||||||
|
if (!hasStaffRows && !hasAssetRows) {
|
||||||
return error("至少需要一条数据");
|
return error("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交异步任务
|
BaseStaffImportSubmitResultVO result = new BaseStaffImportSubmitResultVO();
|
||||||
String taskId = baseStaffService.importBaseStaff(list, updateSupport);
|
if (hasStaffRows) {
|
||||||
|
result.setStaffTaskId(baseStaffService.importBaseStaff(staffList));
|
||||||
// 立即返回,不等待后台任务完成
|
}
|
||||||
ImportResultVO result = new ImportResultVO();
|
if (hasAssetRows) {
|
||||||
result.setTaskId(taskId);
|
result.setAssetTaskId(baseStaffAssetImportService.importAssetInfo(assetList));
|
||||||
result.setStatus("PROCESSING");
|
}
|
||||||
result.setMessage("导入任务已提交,正在后台处理");
|
result.setMessage(buildImportSubmitMessage(hasStaffRows, hasAssetRows));
|
||||||
|
|
||||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
||||||
}
|
}
|
||||||
@@ -202,4 +214,14 @@ 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 "已提交员工资产信息导入任务";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,18 +63,6 @@ public class CcdiCustEnterpriseRelationController extends BaseController {
|
|||||||
return getDataTable(result.getRecords(), result.getTotal());
|
return getDataTable(result.getRecords(), result.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出信贷客户实体关联列表
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出信贷客户实体关联列表")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:custEnterpriseRelation:export')")
|
|
||||||
@Log(title = "信贷客户实体关联信息", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiCustEnterpriseRelationQueryDTO queryDTO) {
|
|
||||||
List<CcdiCustEnterpriseRelationExcel> list = relationService.selectRelationListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiCustEnterpriseRelationExcel.class, "信贷客户实体关联信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取信贷客户实体关联详细信息
|
* 获取信贷客户实体关联详细信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -103,17 +103,6 @@ public class CcdiCustFmyRelationController extends BaseController {
|
|||||||
return toAjax(relationService.deleteRelationByIds(ids));
|
return toAjax(relationService.deleteRelationByIds(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出信贷客户家庭关系
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出信贷客户家庭关系")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:custFmyRelation:export')")
|
|
||||||
@Log(title = "信贷客户家庭关系", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiCustFmyRelationQueryDTO query) {
|
|
||||||
relationService.exportRelations(query, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载带字典下拉框的导入模板
|
* 下载带字典下拉框的导入模板
|
||||||
* 使用@DictDropdown注解自动添加下拉框
|
* 使用@DictDropdown注解自动添加下拉框
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package com.ruoyi.info.collection.controller;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.info.collection.domain.dto.*;
|
import com.ruoyi.info.collection.domain.dto.*;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
|
||||||
import com.ruoyi.info.collection.domain.vo.*;
|
import com.ruoyi.info.collection.domain.vo.*;
|
||||||
import com.ruoyi.info.collection.service.ICcdiIntermediaryEntityImportService;
|
import com.ruoyi.info.collection.service.ICcdiIntermediaryEnterpriseRelationImportService;
|
||||||
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.utils.EasyExcelUtil;
|
import com.ruoyi.info.collection.utils.EasyExcelUtil;
|
||||||
@@ -46,7 +46,7 @@ public class CcdiIntermediaryController extends BaseController {
|
|||||||
private ICcdiIntermediaryPersonImportService personImportService;
|
private ICcdiIntermediaryPersonImportService personImportService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ICcdiIntermediaryEntityImportService entityImportService;
|
private ICcdiIntermediaryEnterpriseRelationImportService enterpriseRelationImportService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询中介列表
|
* 查询中介列表
|
||||||
@@ -277,10 +277,10 @@ public class CcdiIntermediaryController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 下载实体中介导入模板
|
* 下载实体中介导入模板
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "下载实体中介导入模板")
|
@Operation(summary = "下载中介实体关联关系导入模板")
|
||||||
@PostMapping("/importEntityTemplate")
|
@PostMapping("/importEnterpriseRelationTemplate")
|
||||||
public void importEntityTemplate(HttpServletResponse response) {
|
public void importEnterpriseRelationTemplate(HttpServletResponse response) {
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiIntermediaryEntityExcel.class, "实体中介信息");
|
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiIntermediaryEnterpriseRelationExcel.class, "中介实体关联关系信息");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -313,20 +313,19 @@ public class CcdiIntermediaryController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 导入实体中介数据(异步)
|
* 导入实体中介数据(异步)
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "导入实体中介数据")
|
@Operation(summary = "导入中介实体关联关系数据")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||||
@Log(title = "实体中介", businessType = BusinessType.IMPORT)
|
@Log(title = "中介实体关联关系", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importEntityData")
|
@PostMapping("/importEnterpriseRelationData")
|
||||||
public AjaxResult importEntityData(MultipartFile file) throws Exception {
|
public AjaxResult importEnterpriseRelationData(MultipartFile file) throws Exception {
|
||||||
List<CcdiIntermediaryEntityExcel> list = EasyExcelUtil.importExcel(
|
List<CcdiIntermediaryEnterpriseRelationExcel> list = EasyExcelUtil.importExcel(
|
||||||
file.getInputStream(), CcdiIntermediaryEntityExcel.class);
|
file.getInputStream(), CcdiIntermediaryEnterpriseRelationExcel.class);
|
||||||
|
|
||||||
if (list == null || list.isEmpty()) {
|
if (list == null || list.isEmpty()) {
|
||||||
return error("至少需要一条数据");
|
return error("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交异步任务
|
String taskId = intermediaryService.importIntermediaryEnterpriseRelation(list);
|
||||||
String taskId = intermediaryService.importIntermediaryEntity(list);
|
|
||||||
|
|
||||||
// 立即返回,不等待后台任务完成
|
// 立即返回,不等待后台任务完成
|
||||||
ImportResultVO result = new ImportResultVO();
|
ImportResultVO result = new ImportResultVO();
|
||||||
@@ -383,12 +382,12 @@ public class CcdiIntermediaryController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 查询实体中介导入状态
|
* 查询实体中介导入状态
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "查询实体中介导入状态")
|
@Operation(summary = "查询中介实体关联关系导入状态")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||||
@GetMapping("/importEntityStatus/{taskId}")
|
@GetMapping("/importEnterpriseRelationStatus/{taskId}")
|
||||||
public AjaxResult getEntityImportStatus(@PathVariable String taskId) {
|
public AjaxResult getEnterpriseRelationImportStatus(@PathVariable String taskId) {
|
||||||
try {
|
try {
|
||||||
ImportStatusVO status = entityImportService.getImportStatus(taskId);
|
ImportStatusVO status = enterpriseRelationImportService.getImportStatus(taskId);
|
||||||
return success(status);
|
return success(status);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return error(e.getMessage());
|
return error(e.getMessage());
|
||||||
@@ -396,18 +395,18 @@ public class CcdiIntermediaryController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询实体中介导入失败记录
|
* 查询中介实体关联关系导入失败记录
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "查询实体中介导入失败记录")
|
@Operation(summary = "查询中介实体关联关系导入失败记录")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||||
@GetMapping("/importEntityFailures/{taskId}")
|
@GetMapping("/importEnterpriseRelationFailures/{taskId}")
|
||||||
public TableDataInfo getEntityImportFailures(
|
public TableDataInfo getEnterpriseRelationImportFailures(
|
||||||
@PathVariable String taskId,
|
@PathVariable String taskId,
|
||||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||||
|
|
||||||
List<IntermediaryEntityImportFailureVO> failures =
|
List<IntermediaryEnterpriseRelationImportFailureVO> failures =
|
||||||
entityImportService.getImportFailures(taskId);
|
enterpriseRelationImportService.getImportFailures(taskId);
|
||||||
|
|
||||||
// 手动分页
|
// 手动分页
|
||||||
int fromIndex = (pageNum - 1) * pageSize;
|
int fromIndex = (pageNum - 1) * pageSize;
|
||||||
@@ -418,7 +417,7 @@ public class CcdiIntermediaryController extends BaseController {
|
|||||||
return getDataTable(new ArrayList<>(), failures.size());
|
return getDataTable(new ArrayList<>(), failures.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IntermediaryEntityImportFailureVO> pageData = failures.subList(fromIndex, toIndex);
|
List<IntermediaryEnterpriseRelationImportFailureVO> pageData = failures.subList(fromIndex, toIndex);
|
||||||
|
|
||||||
return getDataTable(pageData, failures.size());
|
return getDataTable(pageData, failures.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
|||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||||
|
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.ImportResultVO;
|
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
@@ -33,12 +34,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息Controller
|
* 招投标信息维护Controller
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
*/
|
*/
|
||||||
@Tag(name = "采购交易信息管理")
|
@Tag(name = "招投标信息维护")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/ccdi/purchaseTransaction")
|
@RequestMapping("/ccdi/purchaseTransaction")
|
||||||
public class CcdiPurchaseTransactionController extends BaseController {
|
public class CcdiPurchaseTransactionController extends BaseController {
|
||||||
@@ -50,9 +51,9 @@ public class CcdiPurchaseTransactionController extends BaseController {
|
|||||||
private ICcdiPurchaseTransactionImportService transactionImportService;
|
private ICcdiPurchaseTransactionImportService transactionImportService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询采购交易列表
|
* 查询招投标信息列表
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "查询采购交易列表")
|
@Operation(summary = "查询招投标信息列表")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:list')")
|
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo list(CcdiPurchaseTransactionQueryDTO queryDTO) {
|
public TableDataInfo list(CcdiPurchaseTransactionQueryDTO queryDTO) {
|
||||||
@@ -64,21 +65,9 @@ public class CcdiPurchaseTransactionController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出采购交易列表
|
* 获取招投标信息详细信息
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "导出采购交易列表")
|
@Operation(summary = "获取招投标信息详细信息")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:export')")
|
|
||||||
@Log(title = "采购交易信息", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiPurchaseTransactionQueryDTO queryDTO) {
|
|
||||||
List<CcdiPurchaseTransactionExcel> list = transactionService.selectTransactionListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiPurchaseTransactionExcel.class, "采购交易信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取采购交易详细信息
|
|
||||||
*/
|
|
||||||
@Operation(summary = "获取采购交易详细信息")
|
|
||||||
@Parameter(name = "purchaseId", description = "采购事项ID", required = true)
|
@Parameter(name = "purchaseId", description = "采购事项ID", required = true)
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:query')")
|
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:query')")
|
||||||
@GetMapping(value = "/{purchaseId}")
|
@GetMapping(value = "/{purchaseId}")
|
||||||
@@ -87,66 +76,81 @@ public class CcdiPurchaseTransactionController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增采购交易
|
* 新增招投标信息
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "新增采购交易")
|
@Operation(summary = "新增招投标信息")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:add')")
|
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:add')")
|
||||||
@Log(title = "采购交易信息", businessType = BusinessType.INSERT)
|
@Log(title = "招投标信息维护", businessType = BusinessType.INSERT)
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody CcdiPurchaseTransactionAddDTO addDTO) {
|
public AjaxResult add(@Validated @RequestBody CcdiPurchaseTransactionAddDTO addDTO) {
|
||||||
return toAjax(transactionService.insertTransaction(addDTO));
|
return toAjax(transactionService.insertTransaction(addDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改采购交易
|
* 修改招投标信息
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "修改采购交易")
|
@Operation(summary = "修改招投标信息")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:edit')")
|
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:edit')")
|
||||||
@Log(title = "采购交易信息", businessType = BusinessType.UPDATE)
|
@Log(title = "招投标信息维护", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@Validated @RequestBody CcdiPurchaseTransactionEditDTO editDTO) {
|
public AjaxResult edit(@Validated @RequestBody CcdiPurchaseTransactionEditDTO editDTO) {
|
||||||
return toAjax(transactionService.updateTransaction(editDTO));
|
return toAjax(transactionService.updateTransaction(editDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除采购交易
|
* 删除招投标信息
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "删除采购交易")
|
@Operation(summary = "删除招投标信息")
|
||||||
@Parameter(name = "purchaseIds", description = "采购事项ID数组", required = true)
|
@Parameter(name = "purchaseIds", description = "采购事项ID数组", required = true)
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:remove')")
|
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:remove')")
|
||||||
@Log(title = "采购交易信息", businessType = BusinessType.DELETE)
|
@Log(title = "招投标信息维护", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{purchaseIds}")
|
@DeleteMapping("/{purchaseIds}")
|
||||||
public AjaxResult remove(@PathVariable String[] purchaseIds) {
|
public AjaxResult remove(@PathVariable String[] purchaseIds) {
|
||||||
return toAjax(transactionService.deleteTransactionByIds(purchaseIds));
|
return toAjax(transactionService.deleteTransactionByIds(purchaseIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载带字典下拉框的导入模板
|
* 下载双Sheet导入模板
|
||||||
* 使用@DictDropdown注解自动添加下拉框
|
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "下载导入模板")
|
@Operation(summary = "下载导入模板")
|
||||||
@PostMapping("/importTemplate")
|
@PostMapping("/importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiPurchaseTransactionExcel.class, "采购交易信息");
|
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||||
|
response,
|
||||||
|
CcdiPurchaseTransactionExcel.class,
|
||||||
|
"招投标主信息",
|
||||||
|
CcdiPurchaseTransactionSupplierExcel.class,
|
||||||
|
"供应商明细",
|
||||||
|
"招投标信息维护导入模板"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步导入采购交易
|
* 异步导入招投标信息
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "异步导入采购交易")
|
@Operation(summary = "异步导入招投标信息")
|
||||||
@Parameter(name = "file", description = "导入文件", required = true)
|
@Parameter(name = "file", description = "导入文件", required = true)
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:import')")
|
@PreAuthorize("@ss.hasPermi('ccdi:purchaseTransaction:import')")
|
||||||
@Log(title = "采购交易信息", businessType = BusinessType.IMPORT)
|
@Log(title = "招投标信息维护", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importData")
|
@PostMapping("/importData")
|
||||||
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
||||||
List<CcdiPurchaseTransactionExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiPurchaseTransactionExcel.class);
|
List<CcdiPurchaseTransactionExcel> mainList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiPurchaseTransactionExcel.class,
|
||||||
|
"招投标主信息"
|
||||||
|
);
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiPurchaseTransactionSupplierExcel.class,
|
||||||
|
"供应商明细"
|
||||||
|
);
|
||||||
|
|
||||||
if (list == null || list.isEmpty()) {
|
if ((mainList == null || mainList.isEmpty()) && (supplierList == null || supplierList.isEmpty())) {
|
||||||
return error("至少需要一条数据");
|
return error("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交异步任务
|
// 提交异步任务
|
||||||
String taskId = transactionService.importTransaction(list);
|
String taskId = transactionService.importTransaction(mainList, supplierList);
|
||||||
|
|
||||||
// 立即返回,不等待后台任务完成
|
// 立即返回,不等待后台任务完成
|
||||||
ImportResultVO result = new ImportResultVO();
|
ImportResultVO result = new ImportResultVO();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
|
|||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationQueryDTO;
|
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.CcdiStaffEnterpriseRelationVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
|
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
@@ -33,12 +34,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息Controller
|
* 员工亲属实体关联Controller
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Tag(name = "员工实体关系信息管理")
|
@Tag(name = "员工亲属实体关联管理")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/ccdi/staffEnterpriseRelation")
|
@RequestMapping("/ccdi/staffEnterpriseRelation")
|
||||||
public class CcdiStaffEnterpriseRelationController extends BaseController {
|
public class CcdiStaffEnterpriseRelationController extends BaseController {
|
||||||
@@ -50,9 +51,9 @@ public class CcdiStaffEnterpriseRelationController extends BaseController {
|
|||||||
private ICcdiStaffEnterpriseRelationImportService relationImportService;
|
private ICcdiStaffEnterpriseRelationImportService relationImportService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工实体关系列表
|
* 查询员工亲属实体关联列表
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "查询员工实体关系列表")
|
@Operation(summary = "查询员工亲属实体关联列表")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:list')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo list(CcdiStaffEnterpriseRelationQueryDTO queryDTO) {
|
public TableDataInfo list(CcdiStaffEnterpriseRelationQueryDTO queryDTO) {
|
||||||
@@ -64,21 +65,20 @@ public class CcdiStaffEnterpriseRelationController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出员工实体关系列表
|
* 查询有效员工亲属下拉列表
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "导出员工实体关系列表")
|
@Operation(summary = "查询有效员工亲属下拉列表")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:export')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:list')")
|
||||||
@Log(title = "员工实体关系信息", businessType = BusinessType.EXPORT)
|
@GetMapping("/familyOptions")
|
||||||
@PostMapping("/export")
|
public AjaxResult familyOptions(@RequestParam(required = false) String query) {
|
||||||
public void export(HttpServletResponse response, CcdiStaffEnterpriseRelationQueryDTO queryDTO) {
|
List<CcdiStaffEnterpriseRelationOptionVO> list = relationService.selectFamilyOptions(query);
|
||||||
List<CcdiStaffEnterpriseRelationExcel> list = relationService.selectRelationListForExport(queryDTO);
|
return success(list);
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiStaffEnterpriseRelationExcel.class, "员工实体关系信息");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取员工实体关系详细信息
|
* 获取员工亲属实体关联详细信息
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "获取员工实体关系详细信息")
|
@Operation(summary = "获取员工亲属实体关联详细信息")
|
||||||
@Parameter(name = "id", description = "主键ID", required = true)
|
@Parameter(name = "id", description = "主键ID", required = true)
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:query')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:query')")
|
||||||
@GetMapping(value = "/{id}")
|
@GetMapping(value = "/{id}")
|
||||||
@@ -87,34 +87,34 @@ public class CcdiStaffEnterpriseRelationController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增员工实体关系
|
* 新增员工亲属实体关联
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "新增员工实体关系")
|
@Operation(summary = "新增员工亲属实体关联")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:add')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:add')")
|
||||||
@Log(title = "员工实体关系信息", businessType = BusinessType.INSERT)
|
@Log(title = "员工亲属实体关联", businessType = BusinessType.INSERT)
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody CcdiStaffEnterpriseRelationAddDTO addDTO) {
|
public AjaxResult add(@Validated @RequestBody CcdiStaffEnterpriseRelationAddDTO addDTO) {
|
||||||
return toAjax(relationService.insertRelation(addDTO));
|
return toAjax(relationService.insertRelation(addDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改员工实体关系
|
* 修改员工亲属实体关联
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "修改员工实体关系")
|
@Operation(summary = "修改员工亲属实体关联")
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:edit')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:edit')")
|
||||||
@Log(title = "员工实体关系信息", businessType = BusinessType.UPDATE)
|
@Log(title = "员工亲属实体关联", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@Validated @RequestBody CcdiStaffEnterpriseRelationEditDTO editDTO) {
|
public AjaxResult edit(@Validated @RequestBody CcdiStaffEnterpriseRelationEditDTO editDTO) {
|
||||||
return toAjax(relationService.updateRelation(editDTO));
|
return toAjax(relationService.updateRelation(editDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除员工实体关系
|
* 删除员工亲属实体关联
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "删除员工实体关系")
|
@Operation(summary = "删除员工亲属实体关联")
|
||||||
@Parameter(name = "ids", description = "主键ID数组", required = true)
|
@Parameter(name = "ids", description = "主键ID数组", required = true)
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:remove')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:remove')")
|
||||||
@Log(title = "员工实体关系信息", businessType = BusinessType.DELETE)
|
@Log(title = "员工亲属实体关联", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{ids}")
|
@DeleteMapping("/{ids}")
|
||||||
public AjaxResult remove(@PathVariable Long[] ids) {
|
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||||
return toAjax(relationService.deleteRelationByIds(ids));
|
return toAjax(relationService.deleteRelationByIds(ids));
|
||||||
@@ -127,16 +127,16 @@ public class CcdiStaffEnterpriseRelationController extends BaseController {
|
|||||||
@Operation(summary = "下载导入模板")
|
@Operation(summary = "下载导入模板")
|
||||||
@PostMapping("/importTemplate")
|
@PostMapping("/importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiStaffEnterpriseRelationExcel.class, "员工实体关系信息");
|
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiStaffEnterpriseRelationExcel.class, "员工亲属实体关联");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步导入员工实体关系
|
* 异步导入员工亲属实体关联
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "异步导入员工实体关系")
|
@Operation(summary = "异步导入员工亲属实体关联")
|
||||||
@Parameter(name = "file", description = "导入文件", required = true)
|
@Parameter(name = "file", description = "导入文件", required = true)
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:import')")
|
@PreAuthorize("@ss.hasPermi('ccdi:staffEnterpriseRelation:import')")
|
||||||
@Log(title = "员工实体关系信息", businessType = BusinessType.IMPORT)
|
@Log(title = "员工亲属实体关联", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importData")
|
@PostMapping("/importData")
|
||||||
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
||||||
List<CcdiStaffEnterpriseRelationExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiStaffEnterpriseRelationExcel.class);
|
List<CcdiStaffEnterpriseRelationExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiStaffEnterpriseRelationExcel.class);
|
||||||
@@ -152,9 +152,9 @@ public class CcdiStaffEnterpriseRelationController extends BaseController {
|
|||||||
ImportResultVO result = new ImportResultVO();
|
ImportResultVO result = new ImportResultVO();
|
||||||
result.setTaskId(taskId);
|
result.setTaskId(taskId);
|
||||||
result.setStatus("PROCESSING");
|
result.setStatus("PROCESSING");
|
||||||
result.setMessage("导入任务已提交,正在后台处理");
|
result.setMessage("员工亲属实体关联导入任务已提交,正在后台处理");
|
||||||
|
|
||||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
return AjaxResult.success("员工亲属实体关联导入任务已提交,正在后台处理", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ 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.ImportResultVO;
|
|
||||||
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.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;
|
||||||
@@ -49,6 +51,9 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
|||||||
@Resource
|
@Resource
|
||||||
private ICcdiStaffFmyRelationImportService relationImportService;
|
private ICcdiStaffFmyRelationImportService relationImportService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ICcdiAssetInfoImportService assetInfoImportService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工亲属关系列表
|
* 查询员工亲属关系列表
|
||||||
*/
|
*/
|
||||||
@@ -63,18 +68,6 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
|||||||
return getDataTable(result.getRecords(), result.getTotal());
|
return getDataTable(result.getRecords(), result.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出员工亲属关系列表
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出员工亲属关系列表")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffFmyRelation:export')")
|
|
||||||
@Log(title = "员工亲属关系", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiStaffFmyRelationQueryDTO queryDTO) {
|
|
||||||
List<CcdiStaffFmyRelationExcel> list = relationService.selectRelationListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiStaffFmyRelationExcel.class, "员工亲属关系信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取员工亲属关系详细信息
|
* 获取员工亲属关系详细信息
|
||||||
*/
|
*/
|
||||||
@@ -127,7 +120,14 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
|||||||
@Operation(summary = "下载导入模板")
|
@Operation(summary = "下载导入模板")
|
||||||
@PostMapping("/importTemplate")
|
@PostMapping("/importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiStaffFmyRelationExcel.class, "员工亲属关系信息");
|
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||||
|
response,
|
||||||
|
CcdiStaffFmyRelationExcel.class,
|
||||||
|
"员工亲属关系信息",
|
||||||
|
CcdiAssetInfoExcel.class,
|
||||||
|
"亲属资产信息",
|
||||||
|
"员工亲属关系维护导入模板"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,20 +139,32 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
|||||||
@Log(title = "员工亲属关系", businessType = BusinessType.IMPORT)
|
@Log(title = "员工亲属关系", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importData")
|
@PostMapping("/importData")
|
||||||
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
||||||
List<CcdiStaffFmyRelationExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiStaffFmyRelationExcel.class);
|
List<CcdiStaffFmyRelationExcel> relationList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiStaffFmyRelationExcel.class,
|
||||||
|
"员工亲属关系信息"
|
||||||
|
);
|
||||||
|
List<CcdiAssetInfoExcel> assetList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiAssetInfoExcel.class,
|
||||||
|
"亲属资产信息"
|
||||||
|
);
|
||||||
|
|
||||||
if (list == null || list.isEmpty()) {
|
boolean hasRelationRows = relationList != null && !relationList.isEmpty();
|
||||||
|
boolean hasAssetRows = assetList != null && !assetList.isEmpty();
|
||||||
|
|
||||||
|
if (!hasRelationRows && !hasAssetRows) {
|
||||||
return error("至少需要一条数据");
|
return error("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交异步任务
|
StaffFmyRelationImportSubmitResultVO result = new StaffFmyRelationImportSubmitResultVO();
|
||||||
String taskId = relationService.importRelation(list);
|
if (hasRelationRows) {
|
||||||
|
result.setRelationTaskId(relationService.importRelation(relationList));
|
||||||
// 立即返回,不等待后台任务完成
|
}
|
||||||
ImportResultVO result = new ImportResultVO();
|
if (hasAssetRows) {
|
||||||
result.setTaskId(taskId);
|
result.setAssetTaskId(assetInfoImportService.importAssetInfo(assetList));
|
||||||
result.setStatus("PROCESSING");
|
}
|
||||||
result.setMessage("导入任务已提交,正在后台处理");
|
result.setMessage(buildImportSubmitMessage(hasRelationRows, hasAssetRows));
|
||||||
|
|
||||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
||||||
}
|
}
|
||||||
@@ -198,4 +210,14 @@ 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 "已提交亲属资产信息导入任务";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentAddDTO;
|
|||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||||
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.vo.CcdiStaffRecruitmentVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
|
import com.ruoyi.info.collection.domain.vo.ImportResultVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
@@ -63,18 +64,6 @@ public class CcdiStaffRecruitmentController extends BaseController {
|
|||||||
return getDataTable(result.getRecords(), result.getTotal());
|
return getDataTable(result.getRecords(), result.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出招聘信息列表
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出招聘信息列表")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffRecruitment:export')")
|
|
||||||
@Log(title = "员工招聘信息", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiStaffRecruitmentQueryDTO queryDTO) {
|
|
||||||
List<CcdiStaffRecruitmentExcel> list = recruitmentService.selectRecruitmentListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiStaffRecruitmentExcel.class, "员工招聘信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取招聘信息详细信息
|
* 获取招聘信息详细信息
|
||||||
*/
|
*/
|
||||||
@@ -125,7 +114,14 @@ public class CcdiStaffRecruitmentController extends BaseController {
|
|||||||
@Operation(summary = "下载导入模板")
|
@Operation(summary = "下载导入模板")
|
||||||
@PostMapping("/importTemplate")
|
@PostMapping("/importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiStaffRecruitmentExcel.class, "员工招聘信息");
|
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||||
|
response,
|
||||||
|
CcdiStaffRecruitmentExcel.class,
|
||||||
|
"招聘信息",
|
||||||
|
CcdiStaffRecruitmentWorkExcel.class,
|
||||||
|
"历史工作经历",
|
||||||
|
"招聘信息管理导入模板"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,16 +133,25 @@ public class CcdiStaffRecruitmentController extends BaseController {
|
|||||||
@Log(title = "员工招聘信息", businessType = BusinessType.IMPORT)
|
@Log(title = "员工招聘信息", businessType = BusinessType.IMPORT)
|
||||||
@PostMapping("/importData")
|
@PostMapping("/importData")
|
||||||
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
public AjaxResult importData(@Parameter(description = "导入文件") MultipartFile file) throws Exception {
|
||||||
List<CcdiStaffRecruitmentExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiStaffRecruitmentExcel.class);
|
List<CcdiStaffRecruitmentExcel> recruitmentList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiStaffRecruitmentExcel.class,
|
||||||
|
"招聘信息"
|
||||||
|
);
|
||||||
|
List<CcdiStaffRecruitmentWorkExcel> workList = EasyExcelUtil.importExcel(
|
||||||
|
file.getInputStream(),
|
||||||
|
CcdiStaffRecruitmentWorkExcel.class,
|
||||||
|
"历史工作经历"
|
||||||
|
);
|
||||||
|
|
||||||
if (list == null || list.isEmpty()) {
|
boolean hasRecruitmentRows = recruitmentList != null && !recruitmentList.isEmpty();
|
||||||
|
boolean hasWorkRows = workList != null && !workList.isEmpty();
|
||||||
|
if (!hasRecruitmentRows && !hasWorkRows) {
|
||||||
return error("至少需要一条数据");
|
return error("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交异步任务
|
String taskId = recruitmentService.importRecruitment(recruitmentList, workList);
|
||||||
String taskId = recruitmentService.importRecruitment(list);
|
|
||||||
|
|
||||||
// 立即返回,不等待后台任务完成
|
|
||||||
ImportResultVO result = new ImportResultVO();
|
ImportResultVO result = new ImportResultVO();
|
||||||
result.setTaskId(taskId);
|
result.setTaskId(taskId);
|
||||||
result.setStatus("PROCESSING");
|
result.setStatus("PROCESSING");
|
||||||
|
|||||||
@@ -63,18 +63,6 @@ public class CcdiStaffTransferController extends BaseController {
|
|||||||
return getDataTable(result.getRecords(), result.getTotal());
|
return getDataTable(result.getRecords(), result.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出员工调动记录列表
|
|
||||||
*/
|
|
||||||
@Operation(summary = "导出员工调动记录列表")
|
|
||||||
@PreAuthorize("@ss.hasPermi('ccdi:staffTransfer:export')")
|
|
||||||
@Log(title = "员工调动记录", businessType = BusinessType.EXPORT)
|
|
||||||
@PostMapping("/export")
|
|
||||||
public void export(HttpServletResponse response, CcdiStaffTransferQueryDTO queryDTO) {
|
|
||||||
List<CcdiStaffTransferExcel> list = transferService.selectTransferListForExport(queryDTO);
|
|
||||||
EasyExcelUtil.exportExcel(response, list, CcdiStaffTransferExcel.class, "员工调动记录信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取员工调动记录详细信息
|
* 获取员工调动记录详细信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class CcdiBizIntermediary implements Serializable {
|
|||||||
/** 职位 */
|
/** 职位 */
|
||||||
private String position;
|
private String position;
|
||||||
|
|
||||||
/** 关联人员ID */
|
/** 关联中介本人证件号码 */
|
||||||
private String relatedNumId;
|
private String relatedNumId;
|
||||||
|
|
||||||
/** 数据来源,MANUAL:手动录入, SYSTEM:系统同步, IMPORT:批量导入, API:接口获取 */
|
/** 数据来源,MANUAL:手动录入, SYSTEM:系统同步, IMPORT:批量导入, API:接口获取 */
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.ruoyi.info.collection.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招投标供应商明细对象 ccdi_purchase_transaction_supplier
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CcdiPurchaseTransactionSupplier implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 采购事项ID */
|
||||||
|
private String purchaseId;
|
||||||
|
|
||||||
|
/** 供应商名称 */
|
||||||
|
private String supplierName;
|
||||||
|
|
||||||
|
/** 供应商统一信用代码 */
|
||||||
|
private String supplierUscc;
|
||||||
|
|
||||||
|
/** 供应商联系人 */
|
||||||
|
private String contactPerson;
|
||||||
|
|
||||||
|
/** 供应商联系电话 */
|
||||||
|
private String contactPhone;
|
||||||
|
|
||||||
|
/** 供应商银行账户 */
|
||||||
|
private String supplierBankAccount;
|
||||||
|
|
||||||
|
/** 是否中标:1-是,0-否 */
|
||||||
|
private Integer isBidWinner;
|
||||||
|
|
||||||
|
/** 排序 */
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/** 创建人 */
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createdBy;
|
||||||
|
|
||||||
|
/** 更新人 */
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updatedBy;
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ public class CcdiStaffRecruitment implements Serializable {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 招聘项目编号 */
|
/** 招聘记录编号 */
|
||||||
@TableId(type = IdType.INPUT)
|
@TableId(type = IdType.INPUT)
|
||||||
private String recruitId;
|
private String recruitId;
|
||||||
|
|
||||||
@@ -41,6 +41,9 @@ public class CcdiStaffRecruitment implements Serializable {
|
|||||||
/** 应聘人员姓名 */
|
/** 应聘人员姓名 */
|
||||||
private String candName;
|
private String candName;
|
||||||
|
|
||||||
|
/** 招聘类型:SOCIAL-社招,CAMPUS-校招 */
|
||||||
|
private String recruitType;
|
||||||
|
|
||||||
/** 应聘人员学历 */
|
/** 应聘人员学历 */
|
||||||
private String candEdu;
|
private String candEdu;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.ruoyi.info.collection.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招聘记录历史工作经历对象 ccdi_staff_recruitment_work
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-15
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("ccdi_staff_recruitment_work")
|
||||||
|
public class CcdiStaffRecruitmentWork implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 主键 */
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 关联招聘记录编号 */
|
||||||
|
private String recruitId;
|
||||||
|
|
||||||
|
/** 排序号 */
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 工作单位 */
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/** 所属部门 */
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
/** 岗位名称 */
|
||||||
|
private String positionName;
|
||||||
|
|
||||||
|
/** 入职年月 */
|
||||||
|
private String jobStartMonth;
|
||||||
|
|
||||||
|
/** 离职年月 */
|
||||||
|
private String jobEndMonth;
|
||||||
|
|
||||||
|
/** 离职原因 */
|
||||||
|
private String departureReason;
|
||||||
|
|
||||||
|
/** 主要工作内容 */
|
||||||
|
private String workContent;
|
||||||
|
|
||||||
|
/** 备注 */
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/** 创建人 */
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createdBy;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/** 更新人 */
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updatedBy;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
||||||
@@ -89,7 +89,6 @@ public class CcdiEnterpriseBaseInfoAddDTO implements Serializable {
|
|||||||
private String shareholder5;
|
private String shareholder5;
|
||||||
|
|
||||||
@Schema(description = "经营状态")
|
@Schema(description = "经营状态")
|
||||||
@NotBlank(message = "经营状态不能为空")
|
|
||||||
@Size(max = 50, message = "经营状态长度不能超过50个字符")
|
@Size(max = 50, message = "经营状态长度不能超过50个字符")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
@@ -102,6 +101,5 @@ public class CcdiEnterpriseBaseInfoAddDTO implements Serializable {
|
|||||||
private String entSource;
|
private String entSource;
|
||||||
|
|
||||||
@Schema(description = "数据来源")
|
@Schema(description = "数据来源")
|
||||||
@NotBlank(message = "数据来源不能为空")
|
|
||||||
private String dataSource;
|
private String dataSource;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ public class CcdiEnterpriseBaseInfoEditDTO implements Serializable {
|
|||||||
private String shareholder5;
|
private String shareholder5;
|
||||||
|
|
||||||
@Schema(description = "经营状态")
|
@Schema(description = "经营状态")
|
||||||
@NotBlank(message = "经营状态不能为空")
|
|
||||||
@Size(max = 50, message = "经营状态长度不能超过50个字符")
|
@Size(max = 50, message = "经营状态长度不能超过50个字符")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ public class CcdiIntermediaryPersonAddDTO implements Serializable {
|
|||||||
@Size(max = 100, message = "职位长度不能超过100个字符")
|
@Size(max = 100, message = "职位长度不能超过100个字符")
|
||||||
private String position;
|
private String position;
|
||||||
|
|
||||||
@Schema(description = "关联人员ID")
|
@Schema(description = "关联中介本人证件号码")
|
||||||
@Size(max = 50, message = "关联人员ID长度不能超过50个字符")
|
@Size(max = 50, message = "关联中介本人证件号码长度不能超过50个字符")
|
||||||
private String relatedNumId;
|
private String relatedNumId;
|
||||||
|
|
||||||
@Schema(description = "关联关系")
|
@Schema(description = "关联关系")
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ public class CcdiIntermediaryPersonEditDTO implements Serializable {
|
|||||||
@Size(max = 100, message = "职位长度不能超过100个字符")
|
@Size(max = 100, message = "职位长度不能超过100个字符")
|
||||||
private String position;
|
private String position;
|
||||||
|
|
||||||
@Schema(description = "关联人员ID")
|
@Schema(description = "关联中介本人证件号码")
|
||||||
@Size(max = 50, message = "关联人员ID长度不能超过50个字符")
|
@Size(max = 50, message = "关联中介本人证件号码长度不能超过50个字符")
|
||||||
private String relatedNumId;
|
private String relatedNumId;
|
||||||
|
|
||||||
@Schema(description = "关联关系")
|
@Schema(description = "关联关系")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.domain.dto;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -9,15 +10,16 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息新增DTO
|
* 招投标信息新增DTO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "采购交易信息新增")
|
@Schema(description = "招投标信息新增")
|
||||||
public class CcdiPurchaseTransactionAddDTO implements Serializable {
|
public class CcdiPurchaseTransactionAddDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
@@ -88,30 +90,10 @@ public class CcdiPurchaseTransactionAddDTO implements Serializable {
|
|||||||
@Schema(description = "采购方式")
|
@Schema(description = "采购方式")
|
||||||
private String purchaseMethod;
|
private String purchaseMethod;
|
||||||
|
|
||||||
/** 中标供应商名称 */
|
/** 供应商明细 */
|
||||||
@Size(max = 200, message = "中标供应商名称长度不能超过200个字符")
|
@Valid
|
||||||
@Schema(description = "中标供应商名称")
|
@Schema(description = "供应商明细列表")
|
||||||
private String supplierName;
|
private List<CcdiPurchaseTransactionSupplierDTO> supplierList;
|
||||||
|
|
||||||
/** 供应商联系人 */
|
|
||||||
@Size(max = 50, message = "供应商联系人长度不能超过50个字符")
|
|
||||||
@Schema(description = "供应商联系人")
|
|
||||||
private String contactPerson;
|
|
||||||
|
|
||||||
/** 供应商联系电话 */
|
|
||||||
@Pattern(regexp = "^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$", message = "供应商联系电话格式不正确")
|
|
||||||
@Schema(description = "供应商联系电话")
|
|
||||||
private String contactPhone;
|
|
||||||
|
|
||||||
/** 供应商统一信用代码 */
|
|
||||||
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "供应商统一信用代码格式不正确")
|
|
||||||
@Schema(description = "供应商统一信用代码")
|
|
||||||
private String supplierUscc;
|
|
||||||
|
|
||||||
/** 供应商银行账户 */
|
|
||||||
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
|
|
||||||
@Schema(description = "供应商银行账户")
|
|
||||||
private String supplierBankAccount;
|
|
||||||
|
|
||||||
/** 采购申请日期(或立项日期) */
|
/** 采购申请日期(或立项日期) */
|
||||||
@NotNull(message = "采购申请日期不能为空")
|
@NotNull(message = "采购申请日期不能为空")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.domain.dto;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -9,15 +10,16 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息编辑DTO
|
* 招投标信息编辑DTO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "采购交易信息编辑")
|
@Schema(description = "招投标信息编辑")
|
||||||
public class CcdiPurchaseTransactionEditDTO implements Serializable {
|
public class CcdiPurchaseTransactionEditDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
@@ -88,30 +90,10 @@ public class CcdiPurchaseTransactionEditDTO implements Serializable {
|
|||||||
@Schema(description = "采购方式")
|
@Schema(description = "采购方式")
|
||||||
private String purchaseMethod;
|
private String purchaseMethod;
|
||||||
|
|
||||||
/** 中标供应商名称 */
|
/** 供应商明细 */
|
||||||
@Size(max = 200, message = "中标供应商名称长度不能超过200个字符")
|
@Valid
|
||||||
@Schema(description = "中标供应商名称")
|
@Schema(description = "供应商明细列表")
|
||||||
private String supplierName;
|
private List<CcdiPurchaseTransactionSupplierDTO> supplierList;
|
||||||
|
|
||||||
/** 供应商联系人 */
|
|
||||||
@Size(max = 50, message = "供应商联系人长度不能超过50个字符")
|
|
||||||
@Schema(description = "供应商联系人")
|
|
||||||
private String contactPerson;
|
|
||||||
|
|
||||||
/** 供应商联系电话 */
|
|
||||||
@Pattern(regexp = "^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$", message = "供应商联系电话格式不正确")
|
|
||||||
@Schema(description = "供应商联系电话")
|
|
||||||
private String contactPhone;
|
|
||||||
|
|
||||||
/** 供应商统一信用代码 */
|
|
||||||
@Pattern(regexp = "^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$", message = "供应商统一信用代码格式不正确")
|
|
||||||
@Schema(description = "供应商统一信用代码")
|
|
||||||
private String supplierUscc;
|
|
||||||
|
|
||||||
/** 供应商银行账户 */
|
|
||||||
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
|
|
||||||
@Schema(description = "供应商银行账户")
|
|
||||||
private String supplierBankAccount;
|
|
||||||
|
|
||||||
/** 采购申请日期(或立项日期) */
|
/** 采购申请日期(或立项日期) */
|
||||||
@NotNull(message = "采购申请日期不能为空")
|
@NotNull(message = "采购申请日期不能为空")
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息查询DTO
|
* 招投标信息查询DTO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "采购交易信息查询条件")
|
@Schema(description = "招投标信息查询条件")
|
||||||
public class CcdiPurchaseTransactionQueryDTO implements Serializable {
|
public class CcdiPurchaseTransactionQueryDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招投标供应商明细DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "招投标供应商明细")
|
||||||
|
public class CcdiPurchaseTransactionSupplierDTO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank(message = "供应商名称不能为空")
|
||||||
|
@Schema(description = "供应商名称")
|
||||||
|
private String supplierName;
|
||||||
|
|
||||||
|
@NotBlank(message = "供应商统一信用代码不能为空")
|
||||||
|
@Schema(description = "供应商统一信用代码")
|
||||||
|
private String supplierUscc;
|
||||||
|
|
||||||
|
@Schema(description = "供应商联系人")
|
||||||
|
private String contactPerson;
|
||||||
|
|
||||||
|
@Schema(description = "供应商联系电话")
|
||||||
|
private String contactPhone;
|
||||||
|
|
||||||
|
@Schema(description = "供应商银行账户")
|
||||||
|
private String supplierBankAccount;
|
||||||
|
|
||||||
|
@Schema(description = "是否中标:1-是,0-否")
|
||||||
|
private Integer isBidWinner;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sortOrder;
|
||||||
|
}
|
||||||
@@ -10,22 +10,22 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息新增DTO
|
* 员工亲属实体关联新增DTO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "员工实体关系信息新增")
|
@Schema(description = "员工亲属实体关联新增")
|
||||||
public class CcdiStaffEnterpriseRelationAddDTO implements Serializable {
|
public class CcdiStaffEnterpriseRelationAddDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 身份证号 */
|
/** 亲属身份证号 */
|
||||||
@NotBlank(message = "身份证号不能为空")
|
@NotBlank(message = "亲属身份证号不能为空")
|
||||||
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$", message = "身份证号格式不正确")
|
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$", message = "亲属身份证号格式不正确")
|
||||||
@Schema(description = "身份证号")
|
@Schema(description = "亲属身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|
||||||
/** 关联人在企业的职务 */
|
/** 关联人在企业的职务 */
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息编辑DTO
|
* 员工亲属实体关联编辑DTO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "员工实体关系信息编辑")
|
@Schema(description = "员工亲属实体关联编辑")
|
||||||
public class CcdiStaffEnterpriseRelationEditDTO implements Serializable {
|
public class CcdiStaffEnterpriseRelationEditDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
@@ -27,8 +27,8 @@ public class CcdiStaffEnterpriseRelationEditDTO implements Serializable {
|
|||||||
@Schema(description = "主键ID")
|
@Schema(description = "主键ID")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 身份证号 */
|
/** 亲属身份证号 */
|
||||||
@Schema(description = "身份证号(不可修改)")
|
@Schema(description = "亲属身份证号(不可修改)")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|
||||||
/** 关联人在企业的职务 */
|
/** 关联人在企业的职务 */
|
||||||
|
|||||||
@@ -7,22 +7,30 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息查询DTO
|
* 员工亲属实体关联查询DTO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "员工实体关系信息查询条件")
|
@Schema(description = "员工亲属实体关联查询条件")
|
||||||
public class CcdiStaffEnterpriseRelationQueryDTO implements Serializable {
|
public class CcdiStaffEnterpriseRelationQueryDTO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 身份证号 */
|
/** 亲属身份证号 */
|
||||||
@Schema(description = "身份证号")
|
@Schema(description = "亲属身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|
||||||
|
/** 亲属姓名 */
|
||||||
|
@Schema(description = "亲属姓名")
|
||||||
|
private String relationName;
|
||||||
|
|
||||||
|
/** 关联员工 */
|
||||||
|
@Schema(description = "关联员工")
|
||||||
|
private String staffPersonName;
|
||||||
|
|
||||||
/** 统一社会信用代码 */
|
/** 统一社会信用代码 */
|
||||||
@Schema(description = "统一社会信用代码")
|
@Schema(description = "统一社会信用代码")
|
||||||
private String socialCreditCode;
|
private String socialCreditCode;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ 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 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;
|
||||||
@@ -22,9 +23,9 @@ public class CcdiStaffRecruitmentAddDTO implements Serializable {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 招聘项目编号 */
|
/** 招聘记录编号 */
|
||||||
@NotBlank(message = "招聘项目编号不能为空")
|
@NotBlank(message = "招聘记录编号不能为空")
|
||||||
@Size(max = 32, message = "招聘项目编号长度不能超过32个字符")
|
@Size(max = 32, message = "招聘记录编号长度不能超过32个字符")
|
||||||
private String recruitId;
|
private String recruitId;
|
||||||
|
|
||||||
/** 招聘项目名称 */
|
/** 招聘项目名称 */
|
||||||
@@ -51,6 +52,11 @@ public class CcdiStaffRecruitmentAddDTO implements Serializable {
|
|||||||
@Size(max = 20, message = "应聘人员姓名长度不能超过20个字符")
|
@Size(max = 20, message = "应聘人员姓名长度不能超过20个字符")
|
||||||
private String candName;
|
private String candName;
|
||||||
|
|
||||||
|
/** 招聘类型 */
|
||||||
|
@NotBlank(message = "招聘类型不能为空")
|
||||||
|
@EnumValid(enumClass = RecruitType.class, message = "招聘类型状态值不合法")
|
||||||
|
private String recruitType;
|
||||||
|
|
||||||
/** 应聘人员学历 */
|
/** 应聘人员学历 */
|
||||||
@NotBlank(message = "应聘人员学历不能为空")
|
@NotBlank(message = "应聘人员学历不能为空")
|
||||||
@Size(max = 20, message = "应聘人员学历长度不能超过20个字符")
|
@Size(max = 20, message = "应聘人员学历长度不能超过20个字符")
|
||||||
|
|||||||
@@ -2,14 +2,17 @@ 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 jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.Data;
|
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
|
||||||
@@ -23,8 +26,8 @@ public class CcdiStaffRecruitmentEditDTO implements Serializable {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 招聘项目编号 */
|
/** 招聘记录编号 */
|
||||||
@NotNull(message = "招聘项目编号不能为空")
|
@NotNull(message = "招聘记录编号不能为空")
|
||||||
private String recruitId;
|
private String recruitId;
|
||||||
|
|
||||||
/** 招聘项目名称 */
|
/** 招聘项目名称 */
|
||||||
@@ -46,6 +49,10 @@ public class CcdiStaffRecruitmentEditDTO implements Serializable {
|
|||||||
@Size(max = 20, message = "应聘人员姓名长度不能超过20个字符")
|
@Size(max = 20, message = "应聘人员姓名长度不能超过20个字符")
|
||||||
private String candName;
|
private String candName;
|
||||||
|
|
||||||
|
/** 招聘类型 */
|
||||||
|
@EnumValid(enumClass = RecruitType.class, message = "招聘类型状态值不合法")
|
||||||
|
private String recruitType;
|
||||||
|
|
||||||
/** 应聘人员学历 */
|
/** 应聘人员学历 */
|
||||||
@Size(max = 20, message = "应聘人员学历长度不能超过20个字符")
|
@Size(max = 20, message = "应聘人员学历长度不能超过20个字符")
|
||||||
private String candEdu;
|
private String candEdu;
|
||||||
@@ -86,4 +93,8 @@ public class CcdiStaffRecruitmentEditDTO 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ public class CcdiStaffRecruitmentQueryDTO implements Serializable {
|
|||||||
/** 候选人姓名(模糊查询) */
|
/** 候选人姓名(模糊查询) */
|
||||||
private String candName;
|
private String candName;
|
||||||
|
|
||||||
|
/** 招聘类型(精确查询) */
|
||||||
|
private String recruitType;
|
||||||
|
|
||||||
/** 证件号码(精确查询) */
|
/** 证件号码(精确查询) */
|
||||||
private String candId;
|
private String candId;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招聘记录历史工作经历编辑DTO
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CcdiStaffRecruitmentWorkEditDTO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 排序号 */
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 工作单位 */
|
||||||
|
@Size(max = 200, message = "工作单位长度不能超过200个字符")
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/** 所属部门 */
|
||||||
|
@Size(max = 100, message = "所属部门长度不能超过100个字符")
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
/** 岗位名称 */
|
||||||
|
@Size(max = 100, message = "岗位名称长度不能超过100个字符")
|
||||||
|
private String positionName;
|
||||||
|
|
||||||
|
/** 入职年月 */
|
||||||
|
@Pattern(regexp = "^$|^((19|20)\\d{2})-(0[1-9]|1[0-2])$", message = "入职年月格式不正确,应为YYYY-MM")
|
||||||
|
private String jobStartMonth;
|
||||||
|
|
||||||
|
/** 离职年月 */
|
||||||
|
@Pattern(regexp = "^$|^((19|20)\\d{2})-(0[1-9]|1[0-2])$", message = "离职年月格式不正确,应为YYYY-MM")
|
||||||
|
private String jobEndMonth;
|
||||||
|
|
||||||
|
/** 离职原因 */
|
||||||
|
@Size(max = 500, message = "离职原因长度不能超过500个字符")
|
||||||
|
private String departureReason;
|
||||||
|
|
||||||
|
/** 主要工作内容 */
|
||||||
|
@Size(max = 1000, message = "主要工作内容长度不能超过1000个字符")
|
||||||
|
private String workContent;
|
||||||
|
|
||||||
|
/** 备注 */
|
||||||
|
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -88,7 +88,7 @@ public class CcdiEnterpriseBaseInfoExcel implements Serializable {
|
|||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private String shareholder5;
|
private String shareholder5;
|
||||||
|
|
||||||
@ExcelProperty(value = "经营状态*", index = 16)
|
@ExcelProperty(value = "经营状态", index = 16)
|
||||||
@ColumnWidth(16)
|
@ColumnWidth(16)
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
@@ -99,8 +99,4 @@ public class CcdiEnterpriseBaseInfoExcel implements Serializable {
|
|||||||
@ExcelProperty(value = "企业来源*", index = 18)
|
@ExcelProperty(value = "企业来源*", index = 18)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private String entSource;
|
private String entSource;
|
||||||
|
|
||||||
@ExcelProperty(value = "数据来源*", index = 19)
|
|
||||||
@ColumnWidth(18)
|
|
||||||
private String dataSource;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.excel;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中介实体关联关系导入对象
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CcdiIntermediaryEnterpriseRelationExcel implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 中介本人证件号码 */
|
||||||
|
@ExcelProperty(value = "中介本人证件号码*", index = 0)
|
||||||
|
@ColumnWidth(24)
|
||||||
|
private String ownerPersonId;
|
||||||
|
|
||||||
|
/** 统一社会信用代码 */
|
||||||
|
@ExcelProperty(value = "统一社会信用代码*", index = 1)
|
||||||
|
@ColumnWidth(24)
|
||||||
|
private String socialCreditCode;
|
||||||
|
|
||||||
|
/** 关联人职务 */
|
||||||
|
@ExcelProperty(value = "关联人职务", index = 2)
|
||||||
|
@ColumnWidth(20)
|
||||||
|
private String relationPersonPost;
|
||||||
|
|
||||||
|
/** 备注 */
|
||||||
|
@ExcelProperty(value = "备注", index = 3)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
|
|||||||
/** 人员子类型 */
|
/** 人员子类型 */
|
||||||
@ExcelProperty(value = "人员子类型", index = 2)
|
@ExcelProperty(value = "人员子类型", index = 2)
|
||||||
@ColumnWidth(15)
|
@ColumnWidth(15)
|
||||||
|
@DictDropdown(dictType = "ccdi_person_sub_type")
|
||||||
private String personSubType;
|
private String personSubType;
|
||||||
|
|
||||||
/** 性别 */
|
/** 性别 */
|
||||||
@@ -83,19 +84,13 @@ public class CcdiIntermediaryPersonExcel implements Serializable {
|
|||||||
@ColumnWidth(15)
|
@ColumnWidth(15)
|
||||||
private String position;
|
private String position;
|
||||||
|
|
||||||
/** 关联人员ID */
|
/** 关联中介本人证件号码 */
|
||||||
@ExcelProperty(value = "关联人员ID", index = 12)
|
@ExcelProperty(value = "关联中介本人证件号码", index = 12)
|
||||||
@ColumnWidth(15)
|
@ColumnWidth(24)
|
||||||
private String relatedNumId;
|
private String relatedNumId;
|
||||||
|
|
||||||
/** 关系类型 */
|
|
||||||
@ExcelProperty(value = "关系类型", index = 13)
|
|
||||||
@ColumnWidth(15)
|
|
||||||
@DictDropdown(dictType = "ccdi_relation_type")
|
|
||||||
private String relationType;
|
|
||||||
|
|
||||||
/** 备注 */
|
/** 备注 */
|
||||||
@ExcelProperty(value = "备注", index = 14)
|
@ExcelProperty(value = "备注", index = 13)
|
||||||
@ColumnWidth(30)
|
@ColumnWidth(30)
|
||||||
private String remark;
|
private String remark;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息Excel导入导出对象
|
* 招投标主信息Excel导入导出对象
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
@@ -88,107 +88,82 @@ public class CcdiPurchaseTransactionExcel implements Serializable {
|
|||||||
@Required
|
@Required
|
||||||
private String purchaseMethod;
|
private String purchaseMethod;
|
||||||
|
|
||||||
/** 中标供应商名称 */
|
|
||||||
@ExcelProperty(value = "中标供应商名称", index = 12)
|
|
||||||
@ColumnWidth(25)
|
|
||||||
private String supplierName;
|
|
||||||
|
|
||||||
/** 供应商联系人 */
|
|
||||||
@ExcelProperty(value = "供应商联系人", index = 13)
|
|
||||||
@ColumnWidth(15)
|
|
||||||
private String contactPerson;
|
|
||||||
|
|
||||||
/** 供应商联系电话 */
|
|
||||||
@ExcelProperty(value = "供应商联系电话", index = 14)
|
|
||||||
@ColumnWidth(18)
|
|
||||||
private String contactPhone;
|
|
||||||
|
|
||||||
/** 供应商统一信用代码 */
|
|
||||||
@ExcelProperty(value = "供应商统一信用代码", index = 15)
|
|
||||||
@ColumnWidth(25)
|
|
||||||
private String supplierUscc;
|
|
||||||
|
|
||||||
/** 供应商银行账户 */
|
|
||||||
@ExcelProperty(value = "供应商银行账户", index = 16)
|
|
||||||
@ColumnWidth(20)
|
|
||||||
private String supplierBankAccount;
|
|
||||||
|
|
||||||
/** 采购申请日期(或立项日期) */
|
/** 采购申请日期(或立项日期) */
|
||||||
@ExcelProperty(value = "采购申请日期", index = 17)
|
@ExcelProperty(value = "采购申请日期", index = 12)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
@Required
|
@Required
|
||||||
private Date applyDate;
|
private Date applyDate;
|
||||||
|
|
||||||
/** 采购计划批准日期 */
|
/** 采购计划批准日期 */
|
||||||
@ExcelProperty(value = "采购计划批准日期", index = 18)
|
@ExcelProperty(value = "采购计划批准日期", index = 13)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date planApproveDate;
|
private Date planApproveDate;
|
||||||
|
|
||||||
/** 采购公告发布日期 */
|
/** 采购公告发布日期 */
|
||||||
@ExcelProperty(value = "采购公告发布日期", index = 19)
|
@ExcelProperty(value = "采购公告发布日期", index = 14)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date announceDate;
|
private Date announceDate;
|
||||||
|
|
||||||
/** 开标日期 */
|
/** 开标日期 */
|
||||||
@ExcelProperty(value = "开标日期", index = 20)
|
@ExcelProperty(value = "开标日期", index = 15)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date bidOpenDate;
|
private Date bidOpenDate;
|
||||||
|
|
||||||
/** 合同签订日期 */
|
/** 合同签订日期 */
|
||||||
@ExcelProperty(value = "合同签订日期", index = 21)
|
@ExcelProperty(value = "合同签订日期", index = 16)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date contractSignDate;
|
private Date contractSignDate;
|
||||||
|
|
||||||
/** 预计交货日期 */
|
/** 预计交货日期 */
|
||||||
@ExcelProperty(value = "预计交货日期", index = 22)
|
@ExcelProperty(value = "预计交货日期", index = 17)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date expectedDeliveryDate;
|
private Date expectedDeliveryDate;
|
||||||
|
|
||||||
/** 实际交货日期 */
|
/** 实际交货日期 */
|
||||||
@ExcelProperty(value = "实际交货日期", index = 23)
|
@ExcelProperty(value = "实际交货日期", index = 18)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date actualDeliveryDate;
|
private Date actualDeliveryDate;
|
||||||
|
|
||||||
/** 验收日期 */
|
/** 验收日期 */
|
||||||
@ExcelProperty(value = "验收日期", index = 24)
|
@ExcelProperty(value = "验收日期", index = 19)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date acceptanceDate;
|
private Date acceptanceDate;
|
||||||
|
|
||||||
/** 结算日期 */
|
/** 结算日期 */
|
||||||
@ExcelProperty(value = "结算日期", index = 25)
|
@ExcelProperty(value = "结算日期", index = 20)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private Date settlementDate;
|
private Date settlementDate;
|
||||||
|
|
||||||
/** 申请人工号 */
|
/** 申请人工号 */
|
||||||
@ExcelProperty(value = "申请人工号", index = 26)
|
@ExcelProperty(value = "申请人工号", index = 21)
|
||||||
@ColumnWidth(15)
|
@ColumnWidth(15)
|
||||||
@Required
|
@Required
|
||||||
private String applicantId;
|
private String applicantId;
|
||||||
|
|
||||||
/** 申请人姓名 */
|
/** 申请人姓名 */
|
||||||
@ExcelProperty(value = "申请人姓名", index = 27)
|
@ExcelProperty(value = "申请人姓名", index = 22)
|
||||||
@ColumnWidth(15)
|
@ColumnWidth(15)
|
||||||
@Required
|
@Required
|
||||||
private String applicantName;
|
private String applicantName;
|
||||||
|
|
||||||
/** 申请部门 */
|
/** 申请部门 */
|
||||||
@ExcelProperty(value = "申请部门", index = 28)
|
@ExcelProperty(value = "申请部门", index = 23)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
@Required
|
@Required
|
||||||
private String applyDepartment;
|
private String applyDepartment;
|
||||||
|
|
||||||
/** 采购负责人工号 */
|
/** 采购负责人工号 */
|
||||||
@ExcelProperty(value = "采购负责人工号", index = 29)
|
@ExcelProperty(value = "采购负责人工号", index = 24)
|
||||||
@ColumnWidth(15)
|
@ColumnWidth(15)
|
||||||
private String purchaseLeaderId;
|
private String purchaseLeaderId;
|
||||||
|
|
||||||
/** 采购负责人姓名 */
|
/** 采购负责人姓名 */
|
||||||
@ExcelProperty(value = "采购负责人姓名", index = 30)
|
@ExcelProperty(value = "采购负责人姓名", index = 25)
|
||||||
@ColumnWidth(15)
|
@ColumnWidth(15)
|
||||||
private String purchaseLeaderName;
|
private String purchaseLeaderName;
|
||||||
|
|
||||||
/** 采购部门 */
|
/** 采购部门 */
|
||||||
@ExcelProperty(value = "采购部门", index = 31)
|
@ExcelProperty(value = "采购部门", index = 26)
|
||||||
@ColumnWidth(18)
|
@ColumnWidth(18)
|
||||||
private String purchaseDepartment;
|
private String purchaseDepartment;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.excel;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||||
|
import com.ruoyi.common.annotation.DictDropdown;
|
||||||
|
import com.ruoyi.common.annotation.Required;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招投标供应商明细Excel对象
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CcdiPurchaseTransactionSupplierExcel implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "采购事项ID", index = 0)
|
||||||
|
@ColumnWidth(20)
|
||||||
|
@Required
|
||||||
|
private String purchaseId;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "供应商名称", index = 1)
|
||||||
|
@ColumnWidth(25)
|
||||||
|
@Required
|
||||||
|
private String supplierName;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "供应商统一信用代码", index = 2)
|
||||||
|
@ColumnWidth(25)
|
||||||
|
private String supplierUscc;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "供应商联系人", index = 3)
|
||||||
|
@ColumnWidth(15)
|
||||||
|
private String contactPerson;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "供应商联系电话", index = 4)
|
||||||
|
@ColumnWidth(18)
|
||||||
|
private String contactPhone;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "供应商银行账户", index = 5)
|
||||||
|
@ColumnWidth(20)
|
||||||
|
private String supplierBankAccount;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "是否中标", index = 6)
|
||||||
|
@ColumnWidth(12)
|
||||||
|
@DictDropdown(dictType = "ccdi_yes_no_flag")
|
||||||
|
private String isBidWinner;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "排序", index = 7)
|
||||||
|
@ColumnWidth(10)
|
||||||
|
private Integer sortOrder;
|
||||||
|
}
|
||||||
@@ -10,23 +10,23 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息Excel导入导出对象
|
* 员工亲属实体关联Excel导入导出对象
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "员工实体关系信息Excel导入导出对象")
|
@Schema(description = "员工亲属实体关联Excel导入导出对象")
|
||||||
public class CcdiStaffEnterpriseRelationExcel implements Serializable {
|
public class CcdiStaffEnterpriseRelationExcel 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
|
||||||
@Schema(description = "身份证号")
|
@Schema(description = "亲属身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|
||||||
/** 统一社会信用代码 */
|
/** 统一社会信用代码 */
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.excel;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||||
|
import com.ruoyi.common.annotation.Required;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招聘记录历史工作经历Excel导入对象
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CcdiStaffRecruitmentWorkExcel implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 招聘记录编号 */
|
||||||
|
@ExcelProperty(value = "招聘记录编号", index = 0)
|
||||||
|
@ColumnWidth(20)
|
||||||
|
@Required
|
||||||
|
private String recruitId;
|
||||||
|
|
||||||
|
/** 候选人姓名 */
|
||||||
|
@ExcelProperty(value = "候选人姓名", index = 1)
|
||||||
|
@ColumnWidth(15)
|
||||||
|
@Required
|
||||||
|
private String candName;
|
||||||
|
|
||||||
|
/** 招聘项目名称 */
|
||||||
|
@ExcelProperty(value = "招聘项目名称", index = 2)
|
||||||
|
@ColumnWidth(25)
|
||||||
|
@Required
|
||||||
|
private String recruitName;
|
||||||
|
|
||||||
|
/** 职位名称 */
|
||||||
|
@ExcelProperty(value = "职位名称", index = 3)
|
||||||
|
@ColumnWidth(20)
|
||||||
|
@Required
|
||||||
|
private String posName;
|
||||||
|
|
||||||
|
/** 排序号 */
|
||||||
|
@ExcelProperty(value = "排序号", index = 4)
|
||||||
|
@ColumnWidth(10)
|
||||||
|
@Required
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 工作单位 */
|
||||||
|
@ExcelProperty(value = "工作单位", index = 5)
|
||||||
|
@ColumnWidth(25)
|
||||||
|
@Required
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/** 所属部门 */
|
||||||
|
@ExcelProperty(value = "所属部门", index = 6)
|
||||||
|
@ColumnWidth(18)
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
/** 岗位 */
|
||||||
|
@ExcelProperty(value = "岗位", index = 7)
|
||||||
|
@ColumnWidth(20)
|
||||||
|
@Required
|
||||||
|
private String positionName;
|
||||||
|
|
||||||
|
/** 入职年月 */
|
||||||
|
@ExcelProperty(value = "入职年月", index = 8)
|
||||||
|
@ColumnWidth(12)
|
||||||
|
@Required
|
||||||
|
private String jobStartMonth;
|
||||||
|
|
||||||
|
/** 离职年月 */
|
||||||
|
@ExcelProperty(value = "离职年月", index = 9)
|
||||||
|
@ColumnWidth(12)
|
||||||
|
private String jobEndMonth;
|
||||||
|
|
||||||
|
/** 离职原因 */
|
||||||
|
@ExcelProperty(value = "离职原因", index = 10)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
private String departureReason;
|
||||||
|
|
||||||
|
/** 工作内容 */
|
||||||
|
@ExcelProperty(value = "工作内容", index = 11)
|
||||||
|
@ColumnWidth(35)
|
||||||
|
private String workContent;
|
||||||
|
|
||||||
|
/** 备注 */
|
||||||
|
@ExcelProperty(value = "备注", index = 12)
|
||||||
|
@ColumnWidth(25)
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
|||||||
@Schema(description = "亲属资产信息导入失败记录")
|
@Schema(description = "亲属资产信息导入失败记录")
|
||||||
public class AssetImportFailureVO {
|
public class AssetImportFailureVO {
|
||||||
|
|
||||||
|
/** Sheet名称 */
|
||||||
|
@Schema(description = "Sheet名称")
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
/** Excel行号 */
|
||||||
|
@Schema(description = "Excel行号")
|
||||||
|
private Integer rowNum;
|
||||||
|
|
||||||
/** 亲属证件号 */
|
/** 亲属证件号 */
|
||||||
@Schema(description = "亲属证件号")
|
@Schema(description = "亲属证件号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
|||||||
@Schema(description = "员工资产信息导入失败记录")
|
@Schema(description = "员工资产信息导入失败记录")
|
||||||
public class BaseStaffAssetImportFailureVO {
|
public class BaseStaffAssetImportFailureVO {
|
||||||
|
|
||||||
|
/** Sheet名称 */
|
||||||
|
@Schema(description = "Sheet名称")
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
/** Excel行号 */
|
||||||
|
@Schema(description = "Excel行号")
|
||||||
|
private Integer rowNum;
|
||||||
|
|
||||||
/** 员工身份证号 */
|
/** 员工身份证号 */
|
||||||
@Schema(description = "员工身份证号")
|
@Schema(description = "员工身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工双Sheet导入提交结果
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "员工双Sheet导入提交结果")
|
||||||
|
public class BaseStaffImportSubmitResultVO {
|
||||||
|
|
||||||
|
@Schema(description = "员工信息导入任务ID")
|
||||||
|
private String staffTaskId;
|
||||||
|
|
||||||
|
@Schema(description = "员工资产信息导入任务ID")
|
||||||
|
private String assetTaskId;
|
||||||
|
|
||||||
|
@Schema(description = "提交说明")
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ public class CcdiIntermediaryPersonDetailVO implements Serializable {
|
|||||||
@Schema(description = "职位")
|
@Schema(description = "职位")
|
||||||
private String position;
|
private String position;
|
||||||
|
|
||||||
@Schema(description = "关联人员ID")
|
@Schema(description = "关联中介本人证件号码")
|
||||||
private String relatedNumId;
|
private String relatedNumId;
|
||||||
|
|
||||||
@Schema(description = "关联关系")
|
@Schema(description = "关联关系")
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class CcdiIntermediaryRelativeVO implements Serializable {
|
|||||||
@Schema(description = "人员ID")
|
@Schema(description = "人员ID")
|
||||||
private String bizId;
|
private String bizId;
|
||||||
|
|
||||||
@Schema(description = "所属中介ID")
|
@Schema(description = "关联中介本人证件号码")
|
||||||
private String relatedNumId;
|
private String relatedNumId;
|
||||||
|
|
||||||
@Schema(description = "姓名")
|
@Schema(description = "姓名")
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招投标供应商明细VO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "招投标供应商明细")
|
||||||
|
public class CcdiPurchaseTransactionSupplierVO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "采购事项ID")
|
||||||
|
private String purchaseId;
|
||||||
|
|
||||||
|
@Schema(description = "供应商名称")
|
||||||
|
private String supplierName;
|
||||||
|
|
||||||
|
@Schema(description = "供应商统一信用代码")
|
||||||
|
private String supplierUscc;
|
||||||
|
|
||||||
|
@Schema(description = "供应商联系人")
|
||||||
|
private String contactPerson;
|
||||||
|
|
||||||
|
@Schema(description = "供应商联系电话")
|
||||||
|
private String contactPhone;
|
||||||
|
|
||||||
|
@Schema(description = "供应商银行账户")
|
||||||
|
private String supplierBankAccount;
|
||||||
|
|
||||||
|
@Schema(description = "是否中标:1-是,0-否")
|
||||||
|
private Integer isBidWinner;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sortOrder;
|
||||||
|
}
|
||||||
@@ -8,15 +8,16 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息VO
|
* 招投标信息VO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "采购交易信息")
|
@Schema(description = "招投标信息")
|
||||||
public class CcdiPurchaseTransactionVO implements Serializable {
|
public class CcdiPurchaseTransactionVO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
@@ -90,6 +91,14 @@ public class CcdiPurchaseTransactionVO implements Serializable {
|
|||||||
@Schema(description = "供应商银行账户")
|
@Schema(description = "供应商银行账户")
|
||||||
private String supplierBankAccount;
|
private String supplierBankAccount;
|
||||||
|
|
||||||
|
/** 参与供应商数 */
|
||||||
|
@Schema(description = "参与供应商数")
|
||||||
|
private Integer supplierCount;
|
||||||
|
|
||||||
|
/** 供应商明细 */
|
||||||
|
@Schema(description = "供应商明细列表")
|
||||||
|
private List<CcdiPurchaseTransactionSupplierVO> supplierList;
|
||||||
|
|
||||||
/** 采购申请日期(或立项日期) */
|
/** 采购申请日期(或立项日期) */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
@Schema(description = "采购申请日期")
|
@Schema(description = "采购申请日期")
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工亲属实体关联下拉选项VO
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "员工亲属实体关联下拉选项")
|
||||||
|
public class CcdiStaffEnterpriseRelationOptionVO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 亲属身份证号 */
|
||||||
|
@Schema(description = "亲属身份证号")
|
||||||
|
private String relationCertNo;
|
||||||
|
|
||||||
|
/** 亲属姓名 */
|
||||||
|
@Schema(description = "亲属姓名")
|
||||||
|
private String relationName;
|
||||||
|
|
||||||
|
/** 关联员工身份证号 */
|
||||||
|
@Schema(description = "关联员工身份证号")
|
||||||
|
private String staffPersonId;
|
||||||
|
|
||||||
|
/** 关联员工姓名 */
|
||||||
|
@Schema(description = "关联员工姓名")
|
||||||
|
private String staffPersonName;
|
||||||
|
}
|
||||||
@@ -9,13 +9,13 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息VO
|
* 员工亲属实体关联VO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "员工实体关系信息")
|
@Schema(description = "员工亲属实体关联")
|
||||||
public class CcdiStaffEnterpriseRelationVO implements Serializable {
|
public class CcdiStaffEnterpriseRelationVO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
@@ -25,13 +25,21 @@ public class CcdiStaffEnterpriseRelationVO implements Serializable {
|
|||||||
@Schema(description = "主键ID")
|
@Schema(description = "主键ID")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 身份证号 */
|
/** 亲属身份证号 */
|
||||||
@Schema(description = "身份证号")
|
@Schema(description = "亲属身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|
||||||
/** 员工姓名 */
|
/** 亲属姓名 */
|
||||||
@Schema(description = "员工姓名")
|
@Schema(description = "亲属姓名")
|
||||||
private String personName;
|
private String relationName;
|
||||||
|
|
||||||
|
/** 关联员工身份证号 */
|
||||||
|
@Schema(description = "关联员工身份证号")
|
||||||
|
private String staffPersonId;
|
||||||
|
|
||||||
|
/** 关联员工姓名 */
|
||||||
|
@Schema(description = "关联员工姓名")
|
||||||
|
private String staffPersonName;
|
||||||
|
|
||||||
/** 关联人在企业的职务 */
|
/** 关联人在企业的职务 */
|
||||||
@Schema(description = "关联人在企业的职务")
|
@Schema(description = "关联人在企业的职务")
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import lombok.Data;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工招聘信息VO
|
* 员工招聘信息VO
|
||||||
@@ -18,7 +19,7 @@ public class CcdiStaffRecruitmentVO implements Serializable {
|
|||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 招聘项目编号 */
|
/** 招聘记录编号 */
|
||||||
private String recruitId;
|
private String recruitId;
|
||||||
|
|
||||||
/** 招聘项目名称 */
|
/** 招聘项目名称 */
|
||||||
@@ -36,6 +37,9 @@ public class CcdiStaffRecruitmentVO implements Serializable {
|
|||||||
/** 应聘人员姓名 */
|
/** 应聘人员姓名 */
|
||||||
private String candName;
|
private String candName;
|
||||||
|
|
||||||
|
/** 招聘类型 */
|
||||||
|
private String recruitType;
|
||||||
|
|
||||||
/** 应聘人员学历 */
|
/** 应聘人员学历 */
|
||||||
private String candEdu;
|
private String candEdu;
|
||||||
|
|
||||||
@@ -57,6 +61,12 @@ public class CcdiStaffRecruitmentVO implements Serializable {
|
|||||||
/** 录用情况描述 */
|
/** 录用情况描述 */
|
||||||
private String admitStatusDesc;
|
private String admitStatusDesc;
|
||||||
|
|
||||||
|
/** 历史工作经历条数 */
|
||||||
|
private Long workExperienceCount;
|
||||||
|
|
||||||
|
/** 历史工作经历列表 */
|
||||||
|
private List<CcdiStaffRecruitmentWorkVO> workExperienceList;
|
||||||
|
|
||||||
/** 面试官1姓名 */
|
/** 面试官1姓名 */
|
||||||
private String interviewerName1;
|
private String interviewerName1;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招聘记录历史工作经历VO
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-15
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CcdiStaffRecruitmentWorkVO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 排序号 */
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 工作单位 */
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
/** 所属部门 */
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
/** 岗位名称 */
|
||||||
|
private String positionName;
|
||||||
|
|
||||||
|
/** 入职年月 */
|
||||||
|
private String jobStartMonth;
|
||||||
|
|
||||||
|
/** 离职年月 */
|
||||||
|
private String jobEndMonth;
|
||||||
|
|
||||||
|
/** 离职原因 */
|
||||||
|
private String departureReason;
|
||||||
|
|
||||||
|
/** 主要工作内容 */
|
||||||
|
private String workContent;
|
||||||
|
|
||||||
|
/** 备注 */
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -14,8 +14,14 @@ import java.math.BigDecimal;
|
|||||||
@Schema(description = "导入失败记录")
|
@Schema(description = "导入失败记录")
|
||||||
public class ImportFailureVO {
|
public class ImportFailureVO {
|
||||||
|
|
||||||
|
@Schema(description = "Sheet名称")
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
@Schema(description = "Excel行号")
|
||||||
|
private Integer rowNum;
|
||||||
|
|
||||||
@Schema(description = "柜员号")
|
@Schema(description = "柜员号")
|
||||||
private Long employeeId;
|
private Long staffId;
|
||||||
|
|
||||||
@Schema(description = "姓名")
|
@Schema(description = "姓名")
|
||||||
private String name;
|
private String name;
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中介实体关联关系导入失败记录
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "中介实体关联关系导入失败记录")
|
||||||
|
public class IntermediaryEnterpriseRelationImportFailureVO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "中介本人证件号码")
|
||||||
|
private String ownerPersonId;
|
||||||
|
|
||||||
|
@Schema(description = "统一社会信用代码")
|
||||||
|
private String socialCreditCode;
|
||||||
|
|
||||||
|
@Schema(description = "关联人职务")
|
||||||
|
private String relationPersonPost;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "错误信息")
|
||||||
|
private String errorMessage;
|
||||||
|
}
|
||||||
@@ -22,21 +22,45 @@ public class IntermediaryPersonImportFailureVO implements Serializable {
|
|||||||
@Schema(description = "姓名")
|
@Schema(description = "姓名")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Schema(description = "证件号码")
|
|
||||||
private String personId;
|
|
||||||
|
|
||||||
@Schema(description = "人员类型")
|
@Schema(description = "人员类型")
|
||||||
private String personType;
|
private String personType;
|
||||||
|
|
||||||
|
@Schema(description = "人员子类型")
|
||||||
|
private String personSubType;
|
||||||
|
|
||||||
@Schema(description = "性别")
|
@Schema(description = "性别")
|
||||||
private String gender;
|
private String gender;
|
||||||
|
|
||||||
|
@Schema(description = "证件类型")
|
||||||
|
private String idType;
|
||||||
|
|
||||||
|
@Schema(description = "证件号码")
|
||||||
|
private String personId;
|
||||||
|
|
||||||
@Schema(description = "手机号码")
|
@Schema(description = "手机号码")
|
||||||
private String mobile;
|
private String mobile;
|
||||||
|
|
||||||
|
@Schema(description = "微信号")
|
||||||
|
private String wechatNo;
|
||||||
|
|
||||||
|
@Schema(description = "联系地址")
|
||||||
|
private String contactAddress;
|
||||||
|
|
||||||
@Schema(description = "所在公司")
|
@Schema(description = "所在公司")
|
||||||
private String company;
|
private String company;
|
||||||
|
|
||||||
|
@Schema(description = "企业统一信用码")
|
||||||
|
private String socialCreditCode;
|
||||||
|
|
||||||
|
@Schema(description = "职位")
|
||||||
|
private String position;
|
||||||
|
|
||||||
|
@Schema(description = "关联中介本人证件号码")
|
||||||
|
private String relatedNumId;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
@Schema(description = "错误信息")
|
@Schema(description = "错误信息")
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,23 @@ import lombok.Data;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购交易信息导入失败记录VO
|
* 招投标信息导入失败记录VO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "采购交易信息导入失败记录")
|
@Schema(description = "招投标信息导入失败记录")
|
||||||
public class PurchaseTransactionImportFailureVO {
|
public class PurchaseTransactionImportFailureVO {
|
||||||
|
|
||||||
|
/** 失败来源Sheet */
|
||||||
|
@Schema(description = "失败来源Sheet")
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
/** 失败行号 */
|
||||||
|
@Schema(description = "失败行号")
|
||||||
|
private String sheetRowNum;
|
||||||
|
|
||||||
/** 采购事项ID */
|
/** 采购事项ID */
|
||||||
@Schema(description = "采购事项ID")
|
@Schema(description = "采购事项ID")
|
||||||
private String purchaseId;
|
private String purchaseId;
|
||||||
|
|||||||
@@ -13,12 +13,21 @@ import lombok.Data;
|
|||||||
@Schema(description = "招聘信息导入失败记录")
|
@Schema(description = "招聘信息导入失败记录")
|
||||||
public class RecruitmentImportFailureVO {
|
public class RecruitmentImportFailureVO {
|
||||||
|
|
||||||
|
@Schema(description = "失败Sheet")
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
@Schema(description = "失败行号")
|
||||||
|
private String sheetRowNum;
|
||||||
|
|
||||||
@Schema(description = "招聘项目编号")
|
@Schema(description = "招聘项目编号")
|
||||||
private String recruitId;
|
private String recruitId;
|
||||||
|
|
||||||
@Schema(description = "招聘项目名称")
|
@Schema(description = "招聘项目名称")
|
||||||
private String recruitName;
|
private String recruitName;
|
||||||
|
|
||||||
|
@Schema(description = "职位名称")
|
||||||
|
private String posName;
|
||||||
|
|
||||||
@Schema(description = "应聘人员姓名")
|
@Schema(description = "应聘人员姓名")
|
||||||
private String candName;
|
private String candName;
|
||||||
|
|
||||||
@@ -28,6 +37,12 @@ public class RecruitmentImportFailureVO {
|
|||||||
@Schema(description = "录用情况")
|
@Schema(description = "录用情况")
|
||||||
private String admitStatus;
|
private String admitStatus;
|
||||||
|
|
||||||
|
@Schema(description = "工作单位")
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
@Schema(description = "岗位")
|
||||||
|
private String positionName;
|
||||||
|
|
||||||
@Schema(description = "错误信息")
|
@Schema(description = "错误信息")
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,22 +7,26 @@ import java.io.Serial;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息导入失败记录VO
|
* 员工亲属实体关联导入失败记录VO
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Schema(description = "员工实体关系信息导入失败记录")
|
@Schema(description = "员工亲属实体关联导入失败记录")
|
||||||
public class StaffEnterpriseRelationImportFailureVO implements Serializable {
|
public class StaffEnterpriseRelationImportFailureVO implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 身份证号 */
|
/** 亲属身份证号 */
|
||||||
@Schema(description = "身份证号")
|
@Schema(description = "亲属身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|
||||||
|
/** 亲属姓名 */
|
||||||
|
@Schema(description = "亲属姓名")
|
||||||
|
private String relationName;
|
||||||
|
|
||||||
/** 统一社会信用代码 */
|
/** 统一社会信用代码 */
|
||||||
@Schema(description = "统一社会信用代码")
|
@Schema(description = "统一社会信用代码")
|
||||||
private String socialCreditCode;
|
private String socialCreditCode;
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
|||||||
@Schema(description = "员工亲属关系信息导入失败记录")
|
@Schema(description = "员工亲属关系信息导入失败记录")
|
||||||
public class StaffFmyRelationImportFailureVO {
|
public class StaffFmyRelationImportFailureVO {
|
||||||
|
|
||||||
|
/** Sheet名称 */
|
||||||
|
@Schema(description = "Sheet名称")
|
||||||
|
private String sheetName;
|
||||||
|
|
||||||
|
/** Excel行号 */
|
||||||
|
@Schema(description = "Excel行号")
|
||||||
|
private Integer rowNum;
|
||||||
|
|
||||||
/** 员工身份证号 */
|
/** 员工身份证号 */
|
||||||
@Schema(description = "员工身份证号")
|
@Schema(description = "员工身份证号")
|
||||||
private String personId;
|
private String personId;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.ruoyi.info.collection.domain.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 员工亲属关系双Sheet导入提交结果
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "员工亲属关系双Sheet导入提交结果")
|
||||||
|
public class StaffFmyRelationImportSubmitResultVO {
|
||||||
|
|
||||||
|
@Schema(description = "员工亲属关系导入任务ID")
|
||||||
|
private String relationTaskId;
|
||||||
|
|
||||||
|
@Schema(description = "亲属资产信息导入任务ID")
|
||||||
|
private String assetTaskId;
|
||||||
|
|
||||||
|
@Schema(description = "提交结果提示")
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.ruoyi.info.collection.enums;
|
||||||
|
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招聘类型枚举
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public enum RecruitType {
|
||||||
|
|
||||||
|
/** 社招 */
|
||||||
|
SOCIAL("SOCIAL", "社招"),
|
||||||
|
|
||||||
|
/** 校招 */
|
||||||
|
CAMPUS("CAMPUS", "校招");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
RecruitType(String code, String desc) {
|
||||||
|
this.code = code;
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDescByCode(String code) {
|
||||||
|
for (RecruitType type : values()) {
|
||||||
|
if (type.code.equals(code)) {
|
||||||
|
return type.desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String inferCode(String recruitName) {
|
||||||
|
if (StringUtils.isNotEmpty(recruitName) && recruitName.contains("校园")) {
|
||||||
|
return CAMPUS.code;
|
||||||
|
}
|
||||||
|
return SOCIAL.code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,10 +14,14 @@ import java.util.List;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface CcdiIntermediaryEnterpriseRelationMapper extends BaseMapper<CcdiIntermediaryEnterpriseRelation> {
|
public interface CcdiIntermediaryEnterpriseRelationMapper extends BaseMapper<CcdiIntermediaryEnterpriseRelation> {
|
||||||
|
|
||||||
|
int insertBatch(@Param("list") List<CcdiIntermediaryEnterpriseRelation> list);
|
||||||
|
|
||||||
List<CcdiIntermediaryEnterpriseRelationVO> selectByIntermediaryBizId(@Param("bizId") String bizId);
|
List<CcdiIntermediaryEnterpriseRelationVO> selectByIntermediaryBizId(@Param("bizId") String bizId);
|
||||||
|
|
||||||
CcdiIntermediaryEnterpriseRelationVO selectDetailById(@Param("id") Long id);
|
CcdiIntermediaryEnterpriseRelationVO selectDetailById(@Param("id") Long id);
|
||||||
|
|
||||||
boolean existsByIntermediaryBizIdAndSocialCreditCode(@Param("bizId") String bizId,
|
boolean existsByIntermediaryBizIdAndSocialCreditCode(@Param("bizId") String bizId,
|
||||||
@Param("socialCreditCode") String socialCreditCode);
|
@Param("socialCreditCode") String socialCreditCode);
|
||||||
|
|
||||||
|
List<String> batchExistsByCombinations(@Param("combinations") List<String> combinations);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ public interface CcdiPurchaseTransactionMapper extends BaseMapper<CcdiPurchaseTr
|
|||||||
*/
|
*/
|
||||||
CcdiPurchaseTransactionVO selectTransactionById(@Param("purchaseId") String purchaseId);
|
CcdiPurchaseTransactionVO selectTransactionById(@Param("purchaseId") String purchaseId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定采购事项ID对应的供应商明细
|
||||||
|
*
|
||||||
|
* @param purchaseIds 采购事项ID列表
|
||||||
|
* @return 删除行数
|
||||||
|
*/
|
||||||
|
int deleteSuppliersByPurchaseIds(@Param("purchaseIds") List<String> purchaseIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量插入采购交易数据
|
* 批量插入采购交易数据
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.ruoyi.info.collection.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiPurchaseTransactionSupplier;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招投标供应商明细Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface CcdiPurchaseTransactionSupplierMapper extends BaseMapper<CcdiPurchaseTransactionSupplier> {
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
|
import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationQueryDTO;
|
||||||
|
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 org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
@@ -38,6 +39,14 @@ public interface CcdiStaffEnterpriseRelationMapper extends BaseMapper<CcdiStaffE
|
|||||||
*/
|
*/
|
||||||
CcdiStaffEnterpriseRelationVO selectRelationById(@Param("id") Long id);
|
CcdiStaffEnterpriseRelationVO selectRelationById(@Param("id") Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询有效员工亲属下拉选项
|
||||||
|
*
|
||||||
|
* @param query 搜索关键词
|
||||||
|
* @return 下拉选项
|
||||||
|
*/
|
||||||
|
List<CcdiStaffEnterpriseRelationOptionVO> selectFamilyOptions(@Param("query") String query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断身份证号和统一社会信用代码的组合是否已存在
|
* 判断身份证号和统一社会信用代码的组合是否已存在
|
||||||
*
|
*
|
||||||
@@ -57,6 +66,14 @@ public interface CcdiStaffEnterpriseRelationMapper extends BaseMapper<CcdiStaffE
|
|||||||
*/
|
*/
|
||||||
Set<String> batchExistsByCombinations(@Param("combinations") List<String> combinations);
|
Set<String> batchExistsByCombinations(@Param("combinations") List<String> combinations);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据亲属身份证号批量置无效
|
||||||
|
*
|
||||||
|
* @param personId 亲属身份证号
|
||||||
|
* @return 影响行数
|
||||||
|
*/
|
||||||
|
int invalidateByFamilyCertNo(@Param("personId") String personId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量插入员工实体关系数据
|
* 批量插入员工实体关系数据
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.ruoyi.info.collection.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiStaffRecruitmentWork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 招聘记录历史工作经历 数据层
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-04-15
|
||||||
|
*/
|
||||||
|
public interface CcdiStaffRecruitmentWorkMapper extends BaseMapper<CcdiStaffRecruitmentWork> {
|
||||||
|
}
|
||||||
@@ -16,9 +16,8 @@ public interface ICcdiBaseStaffImportService {
|
|||||||
* 异步导入员工数据
|
* 异步导入员工数据
|
||||||
*
|
*
|
||||||
* @param excelList Excel数据列表
|
* @param excelList Excel数据列表
|
||||||
* @param isUpdateSupport 是否更新已存在的数据
|
|
||||||
*/
|
*/
|
||||||
void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport, String taskId);
|
void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询导入状态
|
* 查询导入状态
|
||||||
|
|||||||
@@ -79,10 +79,9 @@ public interface ICcdiBaseStaffService {
|
|||||||
* 导入员工数据
|
* 导入员工数据
|
||||||
*
|
*
|
||||||
* @param excelList Excel实体列表
|
* @param excelList Excel实体列表
|
||||||
* @param isUpdateSupport 是否更新支持
|
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
String importBaseStaff(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport);
|
String importBaseStaff(List<CcdiBaseStaffExcel> excelList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工下拉列表
|
* 查询员工下拉列表
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.ruoyi.info.collection.service;
|
||||||
|
|
||||||
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
|
||||||
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
|
import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中介实体关联关系异步导入服务接口
|
||||||
|
*/
|
||||||
|
public interface ICcdiIntermediaryEnterpriseRelationImportService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步导入中介实体关联关系
|
||||||
|
*
|
||||||
|
* @param excelList Excel数据
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @param userName 当前用户名
|
||||||
|
*/
|
||||||
|
void importAsync(List<CcdiIntermediaryEnterpriseRelationExcel> excelList, String taskId, String userName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询导入状态
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return 导入状态
|
||||||
|
*/
|
||||||
|
ImportStatusVO getImportStatus(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询导入失败记录
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return 失败记录
|
||||||
|
*/
|
||||||
|
List<IntermediaryEnterpriseRelationImportFailureVO> getImportFailures(String taskId);
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import com.ruoyi.info.collection.domain.vo.IntermediaryPersonImportFailureVO;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 个人中介异步导入Service接口
|
* 中介信息异步导入Service接口
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-06
|
* @date 2026-02-06
|
||||||
@@ -15,7 +15,7 @@ import java.util.List;
|
|||||||
public interface ICcdiIntermediaryPersonImportService {
|
public interface ICcdiIntermediaryPersonImportService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步导入个人中介数据
|
* 异步导入中介信息
|
||||||
*
|
*
|
||||||
* @param excelList Excel数据列表
|
* @param excelList Excel数据列表
|
||||||
* @param taskId 任务ID
|
* @param taskId 任务ID
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.info.collection.domain.dto.*;
|
import com.ruoyi.info.collection.domain.dto.*;
|
||||||
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
|
||||||
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO;
|
||||||
@@ -168,7 +169,7 @@ public interface ICcdiIntermediaryService {
|
|||||||
int deleteIntermediaryByIds(String[] ids);
|
int deleteIntermediaryByIds(String[] ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验人员ID唯一性
|
* 校验中介本人证件号码唯一性
|
||||||
*
|
*
|
||||||
* @param personId 人员ID
|
* @param personId 人员ID
|
||||||
* @param bizId 排除的人员ID
|
* @param bizId 排除的人员ID
|
||||||
@@ -193,6 +194,14 @@ public interface ICcdiIntermediaryService {
|
|||||||
*/
|
*/
|
||||||
String importIntermediaryPerson(List<CcdiIntermediaryPersonExcel> list);
|
String importIntermediaryPerson(List<CcdiIntermediaryPersonExcel> list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入中介实体关联关系
|
||||||
|
*
|
||||||
|
* @param list Excel实体列表
|
||||||
|
* @return 任务ID
|
||||||
|
*/
|
||||||
|
String importIntermediaryEnterpriseRelation(List<CcdiIntermediaryEnterpriseRelationExcel> list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入实体中介数据
|
* 导入实体中介数据
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.info.collection.service;
|
package com.ruoyi.info.collection.service;
|
||||||
|
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||||
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||||
import com.ruoyi.info.collection.domain.vo.PurchaseTransactionImportFailureVO;
|
import com.ruoyi.info.collection.domain.vo.PurchaseTransactionImportFailureVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
|
|
||||||
@@ -17,11 +18,17 @@ public interface ICcdiPurchaseTransactionImportService {
|
|||||||
/**
|
/**
|
||||||
* 异步导入采购交易数据
|
* 异步导入采购交易数据
|
||||||
*
|
*
|
||||||
* @param excelList Excel数据列表
|
* @param mainExcelList 主信息Excel数据列表
|
||||||
|
* @param supplierExcelList 供应商明细Excel数据列表
|
||||||
* @param taskId 任务ID
|
* @param taskId 任务ID
|
||||||
* @param userName 当前用户名
|
* @param userName 当前用户名
|
||||||
*/
|
*/
|
||||||
void importTransactionAsync(List<CcdiPurchaseTransactionExcel> excelList, String taskId, String userName);
|
void importTransactionAsync(
|
||||||
|
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList,
|
||||||
|
String taskId,
|
||||||
|
String userName
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询导入状态
|
* 查询导入状态
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
|||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||||
|
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 java.util.List;
|
import java.util.List;
|
||||||
@@ -77,8 +78,12 @@ public interface ICcdiPurchaseTransactionService {
|
|||||||
/**
|
/**
|
||||||
* 导入采购交易数据(异步)
|
* 导入采购交易数据(异步)
|
||||||
*
|
*
|
||||||
* @param excelList Excel实体列表
|
* @param mainExcelList 主信息Excel实体列表
|
||||||
|
* @param supplierExcelList 供应商明细Excel实体列表
|
||||||
* @return 任务ID
|
* @return 任务ID
|
||||||
*/
|
*/
|
||||||
String importTransaction(List<CcdiPurchaseTransactionExcel> excelList);
|
String importTransaction(
|
||||||
|
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import com.ruoyi.info.collection.domain.vo.StaffEnterpriseRelationImportFailureV
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息异步导入服务层
|
* 员工亲属实体关联异步导入服务层
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
|
|||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationQueryDTO;
|
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.CcdiStaffEnterpriseRelationVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -42,6 +43,14 @@ public interface ICcdiStaffEnterpriseRelationService {
|
|||||||
*/
|
*/
|
||||||
List<CcdiStaffEnterpriseRelationExcel> selectRelationListForExport(CcdiStaffEnterpriseRelationQueryDTO queryDTO);
|
List<CcdiStaffEnterpriseRelationExcel> selectRelationListForExport(CcdiStaffEnterpriseRelationQueryDTO queryDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询有效员工亲属下拉选项
|
||||||
|
*
|
||||||
|
* @param query 搜索关键词
|
||||||
|
* @return 下拉选项
|
||||||
|
*/
|
||||||
|
List<CcdiStaffEnterpriseRelationOptionVO> selectFamilyOptions(String query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工实体关系详情
|
* 查询员工实体关系详情
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.info.collection.service;
|
package com.ruoyi.info.collection.service;
|
||||||
|
|
||||||
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.vo.ImportStatusVO;
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
import com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO;
|
import com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO;
|
||||||
|
|
||||||
@@ -21,7 +22,8 @@ public interface ICcdiStaffRecruitmentImportService {
|
|||||||
* @param taskId 任务ID
|
* @param taskId 任务ID
|
||||||
* @param userName 用户名
|
* @param userName 用户名
|
||||||
*/
|
*/
|
||||||
void importRecruitmentAsync(List<CcdiStaffRecruitmentExcel> excelList,
|
void importRecruitmentAsync(List<CcdiStaffRecruitmentExcel> recruitmentList,
|
||||||
|
List<CcdiStaffRecruitmentWorkExcel> workList,
|
||||||
String taskId,
|
String taskId,
|
||||||
String userName);
|
String userName);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentAddDTO;
|
|||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||||
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.vo.CcdiStaffRecruitmentVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -80,5 +81,6 @@ public interface ICcdiStaffRecruitmentService {
|
|||||||
* @param excelList Excel实体列表
|
* @param excelList Excel实体列表
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
String importRecruitment(List<CcdiStaffRecruitmentExcel> excelList);
|
String importRecruitment(List<CcdiStaffRecruitmentExcel> recruitmentList,
|
||||||
|
List<CcdiStaffRecruitmentWorkExcel> workList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportService {
|
public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportService {
|
||||||
|
|
||||||
private static final String STATUS_KEY_PREFIX = "import:assetInfo:";
|
private static final String STATUS_KEY_PREFIX = "import:assetInfo:";
|
||||||
|
private static final String SHEET_NAME = "亲属资产信息";
|
||||||
|
private static final int EXCEL_DATA_START_ROW = 2;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CcdiAssetInfoMapper assetInfoMapper;
|
private CcdiAssetInfoMapper assetInfoMapper;
|
||||||
@@ -91,7 +93,8 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
|
|||||||
|
|
||||||
Map<String, Set<String>> ownerMap = buildOwnerMap(personIds);
|
Map<String, Set<String>> ownerMap = buildOwnerMap(personIds);
|
||||||
|
|
||||||
for (CcdiAssetInfoExcel excel : excelList) {
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
|
CcdiAssetInfoExcel excel = excelList.get(i);
|
||||||
try {
|
try {
|
||||||
validateExcel(excel);
|
validateExcel(excel);
|
||||||
Set<String> familyIds = ownerMap.get(excel.getPersonId());
|
Set<String> familyIds = ownerMap.get(excel.getPersonId());
|
||||||
@@ -111,6 +114,8 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
AssetImportFailureVO failureVO = new AssetImportFailureVO();
|
AssetImportFailureVO failureVO = new AssetImportFailureVO();
|
||||||
BeanUtils.copyProperties(excel, failureVO);
|
BeanUtils.copyProperties(excel, failureVO);
|
||||||
|
failureVO.setSheetName(SHEET_NAME);
|
||||||
|
failureVO.setRowNum(i + EXCEL_DATA_START_ROW);
|
||||||
failureVO.setErrorMessage(e.getMessage());
|
failureVO.setErrorMessage(e.getMessage());
|
||||||
failures.add(failureVO);
|
failures.add(failureVO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.info.collection.service.impl;
|
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.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.info.collection.domain.CcdiAssetInfo;
|
import com.ruoyi.info.collection.domain.CcdiAssetInfo;
|
||||||
@@ -90,14 +91,24 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
Map<String, Set<String>> ownerMap = buildOwnerMap(personIds);
|
Map<String, Set<String>> ownerMap = buildOwnerMap(personIds);
|
||||||
|
Set<String> existingAssetKeys = buildExistingAssetKeys(personIds);
|
||||||
|
Set<String> importedAssetKeys = new java.util.LinkedHashSet<>();
|
||||||
|
|
||||||
for (CcdiBaseStaffAssetInfoExcel excel : excelList) {
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
|
CcdiBaseStaffAssetInfoExcel excel = excelList.get(i);
|
||||||
try {
|
try {
|
||||||
validateExcel(excel);
|
validateExcel(excel);
|
||||||
Set<String> familyIds = ownerMap.get(excel.getPersonId());
|
Set<String> familyIds = ownerMap.get(excel.getPersonId());
|
||||||
if (familyIds == null || familyIds.isEmpty()) {
|
if (familyIds == null || familyIds.isEmpty()) {
|
||||||
throw new RuntimeException("员工资产导入仅支持员工本人证件号");
|
throw new RuntimeException("员工资产导入仅支持员工本人证件号");
|
||||||
}
|
}
|
||||||
|
String assetKey = buildAssetKey(excel.getPersonId(), excel.getAssetMainType(), excel.getAssetSubType(), excel.getAssetName());
|
||||||
|
if (existingAssetKeys.contains(assetKey)) {
|
||||||
|
throw new RuntimeException("资产记录已存在");
|
||||||
|
}
|
||||||
|
if (!importedAssetKeys.add(assetKey)) {
|
||||||
|
throw new RuntimeException("资产记录在导入文件中重复");
|
||||||
|
}
|
||||||
|
|
||||||
CcdiAssetInfo assetInfo = new CcdiAssetInfo();
|
CcdiAssetInfo assetInfo = new CcdiAssetInfo();
|
||||||
BeanUtils.copyProperties(excel, assetInfo);
|
BeanUtils.copyProperties(excel, assetInfo);
|
||||||
@@ -109,6 +120,8 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
BaseStaffAssetImportFailureVO failureVO = new BaseStaffAssetImportFailureVO();
|
BaseStaffAssetImportFailureVO failureVO = new BaseStaffAssetImportFailureVO();
|
||||||
BeanUtils.copyProperties(excel, failureVO);
|
BeanUtils.copyProperties(excel, failureVO);
|
||||||
|
failureVO.setSheetName("员工资产信息");
|
||||||
|
failureVO.setRowNum(i + 2);
|
||||||
failureVO.setErrorMessage(e.getMessage());
|
failureVO.setErrorMessage(e.getMessage());
|
||||||
failures.add(failureVO);
|
failures.add(failureVO);
|
||||||
}
|
}
|
||||||
@@ -168,6 +181,18 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<String> buildExistingAssetKeys(List<String> personIds) {
|
||||||
|
if (personIds == null || personIds.isEmpty()) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
LambdaQueryWrapper<CcdiAssetInfo> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.in(CcdiAssetInfo::getPersonId, personIds);
|
||||||
|
return assetInfoMapper.selectList(wrapper).stream()
|
||||||
|
.filter(asset -> StringUtils.equals(asset.getFamilyId(), asset.getPersonId()))
|
||||||
|
.map(asset -> buildAssetKey(asset.getPersonId(), asset.getAssetMainType(), asset.getAssetSubType(), asset.getAssetName()))
|
||||||
|
.collect(java.util.stream.Collectors.toCollection(java.util.LinkedHashSet::new));
|
||||||
|
}
|
||||||
|
|
||||||
private void mergeOwnerMappings(Map<String, Set<String>> result, List<Map<String, String>> mappings) {
|
private void mergeOwnerMappings(Map<String, Set<String>> result, List<Map<String, String>> mappings) {
|
||||||
if (mappings == null) {
|
if (mappings == null) {
|
||||||
return;
|
return;
|
||||||
@@ -203,6 +228,14 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String buildAssetKey(String personId, String assetMainType, String assetSubType, String assetName) {
|
||||||
|
return String.join("|",
|
||||||
|
StringUtils.nvl(personId, ""),
|
||||||
|
StringUtils.nvl(assetMainType, ""),
|
||||||
|
StringUtils.nvl(assetSubType, ""),
|
||||||
|
StringUtils.nvl(assetName, ""));
|
||||||
|
}
|
||||||
|
|
||||||
private void updateImportStatus(String taskId, String status, ImportResult result) {
|
private void updateImportStatus(String taskId, String status, ImportResult result) {
|
||||||
Map<String, Object> statusData = new HashMap<>();
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
statusData.put("status", status);
|
statusData.put("status", status);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ 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.common.core.domain.entity.SysDept;
|
||||||
import com.ruoyi.info.collection.domain.CcdiBaseStaff;
|
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.excel.CcdiBaseStaffExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
|
||||||
@@ -13,6 +14,7 @@ import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService;
|
|||||||
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;
|
||||||
|
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -43,16 +45,18 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
@Resource
|
@Resource
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysDeptMapper deptMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Async
|
@Async
|
||||||
public void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport, String taskId) {
|
public void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId) {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// 记录导入开始
|
// 记录导入开始
|
||||||
ImportLogUtils.logImportStart(log, taskId, "员工基础信息", excelList.size(), "系统");
|
ImportLogUtils.logImportStart(log, taskId, "员工基础信息", excelList.size(), "系统");
|
||||||
|
|
||||||
List<CcdiBaseStaff> newRecords = new ArrayList<>();
|
List<CcdiBaseStaff> newRecords = new ArrayList<>();
|
||||||
List<CcdiBaseStaff> updateRecords = new ArrayList<>();
|
|
||||||
List<ImportFailureVO> failures = new ArrayList<>();
|
List<ImportFailureVO> failures = new ArrayList<>();
|
||||||
|
|
||||||
// 批量查询已存在的员工ID和身份证号
|
// 批量查询已存在的员工ID和身份证号
|
||||||
@@ -75,13 +79,12 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
CcdiBaseStaffAddDTO addDTO = new CcdiBaseStaffAddDTO();
|
CcdiBaseStaffAddDTO addDTO = new CcdiBaseStaffAddDTO();
|
||||||
BeanUtils.copyProperties(excel, addDTO);
|
BeanUtils.copyProperties(excel, addDTO);
|
||||||
|
|
||||||
// 验证数据(支持更新模式)
|
validateStaffData(addDTO, existingIds, existingIdCards);
|
||||||
validateStaffData(addDTO, isUpdateSupport, existingIds, existingIdCards);
|
|
||||||
|
|
||||||
CcdiBaseStaff staff = new CcdiBaseStaff();
|
CcdiBaseStaff staff = new CcdiBaseStaff();
|
||||||
BeanUtils.copyProperties(excel, staff);
|
BeanUtils.copyProperties(excel, staff);
|
||||||
|
|
||||||
// 统一检查Excel内重复(更新和新增两个分支都需要检查)
|
// 统一检查Excel内重复
|
||||||
if (processedStaffIds.contains(excel.getStaffId())) {
|
if (processedStaffIds.contains(excel.getStaffId())) {
|
||||||
throw new RuntimeException(String.format("员工ID[%d]在导入文件中重复,已跳过此条记录", excel.getStaffId()));
|
throw new RuntimeException(String.format("员工ID[%d]在导入文件中重复,已跳过此条记录", excel.getStaffId()));
|
||||||
}
|
}
|
||||||
@@ -90,20 +93,7 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
throw new RuntimeException(String.format("身份证号[%s]在导入文件中重复,已跳过此条记录", excel.getIdCard()));
|
throw new RuntimeException(String.format("身份证号[%s]在导入文件中重复,已跳过此条记录", excel.getIdCard()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查员工ID是否在数据库中已存在
|
|
||||||
if (existingIds.contains(excel.getStaffId())) {
|
|
||||||
// 员工ID已存在于数据库
|
|
||||||
if (!isUpdateSupport) {
|
|
||||||
throw new RuntimeException("员工ID已存在且未启用更新支持");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过检查,添加到更新列表
|
|
||||||
updateRecords.add(staff);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 员工ID不存在,添加到新增列表
|
|
||||||
newRecords.add(staff);
|
newRecords.add(staff);
|
||||||
}
|
|
||||||
|
|
||||||
// 统一标记为已处理(只有成功添加到列表后才会执行到这里)
|
// 统一标记为已处理(只有成功添加到列表后才会执行到这里)
|
||||||
if (excel.getStaffId() != null) {
|
if (excel.getStaffId() != null) {
|
||||||
@@ -115,11 +105,13 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
|
|
||||||
// 记录进度
|
// 记录进度
|
||||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
||||||
newRecords.size() + updateRecords.size(), failures.size());
|
newRecords.size(), failures.size());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ImportFailureVO failure = new ImportFailureVO();
|
ImportFailureVO failure = new ImportFailureVO();
|
||||||
BeanUtils.copyProperties(excel, failure);
|
BeanUtils.copyProperties(excel, failure);
|
||||||
|
failure.setSheetName("员工信息");
|
||||||
|
failure.setRowNum(i + 2);
|
||||||
failure.setErrorMessage(e.getMessage());
|
failure.setErrorMessage(e.getMessage());
|
||||||
failures.add(failure);
|
failures.add(failure);
|
||||||
|
|
||||||
@@ -137,13 +129,6 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
saveBatch(newRecords, 500);
|
saveBatch(newRecords, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量更新已有数据(先删除再插入)
|
|
||||||
if (!updateRecords.isEmpty() && isUpdateSupport) {
|
|
||||||
ImportLogUtils.logBatchOperationStart(log, taskId, "更新",
|
|
||||||
(updateRecords.size() + 499) / 500, 500);
|
|
||||||
baseStaffMapper.insertOrUpdateBatch(updateRecords);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存失败记录到Redis
|
// 保存失败记录到Redis
|
||||||
if (!failures.isEmpty()) {
|
if (!failures.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
@@ -157,7 +142,7 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
|
|
||||||
ImportResult result = new ImportResult();
|
ImportResult result = new ImportResult();
|
||||||
result.setTotalCount(excelList.size());
|
result.setTotalCount(excelList.size());
|
||||||
result.setSuccessCount(newRecords.size() + updateRecords.size());
|
result.setSuccessCount(newRecords.size());
|
||||||
result.setFailureCount(failures.size());
|
result.setFailureCount(failures.size());
|
||||||
|
|
||||||
// 更新最终状态
|
// 更新最终状态
|
||||||
@@ -299,11 +284,10 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
* 验证员工数据
|
* 验证员工数据
|
||||||
*
|
*
|
||||||
* @param addDTO 新增DTO
|
* @param addDTO 新增DTO
|
||||||
* @param isUpdateSupport 是否支持更新
|
|
||||||
* @param existingIds 已存在的员工ID集合(导入场景使用,传null表示单条新增)
|
* @param existingIds 已存在的员工ID集合(导入场景使用,传null表示单条新增)
|
||||||
* @param existingIdCards 已存在的身份证号集合(导入场景使用,传null表示单条新增)
|
* @param existingIdCards 已存在的身份证号集合(导入场景使用,传null表示单条新增)
|
||||||
*/
|
*/
|
||||||
public void validateStaffData(CcdiBaseStaffAddDTO addDTO, Boolean isUpdateSupport, Set<Long> existingIds, Set<String> existingIdCards) {
|
public void validateStaffData(CcdiBaseStaffAddDTO addDTO, Set<Long> existingIds, Set<String> existingIdCards) {
|
||||||
// 验证必填字段
|
// 验证必填字段
|
||||||
if (StringUtils.isEmpty(addDTO.getName())) {
|
if (StringUtils.isEmpty(addDTO.getName())) {
|
||||||
throw new RuntimeException("姓名不能为空");
|
throw new RuntimeException("姓名不能为空");
|
||||||
@@ -326,6 +310,7 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
if (StringUtils.isEmpty(addDTO.getStatus())) {
|
if (StringUtils.isEmpty(addDTO.getStatus())) {
|
||||||
throw new RuntimeException("状态不能为空");
|
throw new RuntimeException("状态不能为空");
|
||||||
}
|
}
|
||||||
|
validateDeptId(addDTO.getDeptId());
|
||||||
|
|
||||||
// 验证身份证号格式
|
// 验证身份证号格式
|
||||||
String idCardError = IdCardUtil.getErrorMessage(addDTO.getIdCard());
|
String idCardError = IdCardUtil.getErrorMessage(addDTO.getIdCard());
|
||||||
@@ -347,14 +332,13 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
throw new RuntimeException("该身份证号已存在");
|
throw new RuntimeException("该身份证号已存在");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 导入场景:如果员工ID不存在,才检查身份证号唯一性
|
if (existingIds.contains(addDTO.getStaffId())) {
|
||||||
if (!existingIds.contains(addDTO.getStaffId())) {
|
throw new RuntimeException("该员工ID已存在");
|
||||||
// 使用批量查询的结果检查身份证号唯一性
|
}
|
||||||
if (existingIdCards != null && existingIdCards.contains(addDTO.getIdCard())) {
|
if (existingIdCards != null && existingIdCards.contains(addDTO.getIdCard())) {
|
||||||
throw new RuntimeException("该身份证号已存在");
|
throw new RuntimeException("该身份证号已存在");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 验证状态
|
// 验证状态
|
||||||
if (!"0".equals(addDTO.getStatus()) && !"1".equals(addDTO.getStatus())) {
|
if (!"0".equals(addDTO.getStatus()) && !"1".equals(addDTO.getStatus())) {
|
||||||
@@ -378,4 +362,11 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
|||||||
throw new RuntimeException(fieldLabel + "最多保留2位小数");
|
throw new RuntimeException(fieldLabel + "最多保留2位小数");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateDeptId(Long deptId) {
|
||||||
|
SysDept dept = deptMapper.selectDeptById(deptId);
|
||||||
|
if (dept == null || !"0".equals(dept.getStatus()) || !"0".equals(dept.getDelFlag())) {
|
||||||
|
throw new RuntimeException(String.format("所属部门ID[%d]不存在或已停用/删除,请检查机构号", deptId));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,12 +212,11 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
|||||||
* 导入员工数据
|
* 导入员工数据
|
||||||
*
|
*
|
||||||
* @param excelList Excel实体列表
|
* @param excelList Excel实体列表
|
||||||
* @param isUpdateSupport 是否更新支持
|
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public String importBaseStaff(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport) {
|
public String importBaseStaff(List<CcdiBaseStaffExcel> excelList) {
|
||||||
String taskId = UUID.randomUUID().toString();
|
String taskId = UUID.randomUUID().toString();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
@@ -236,7 +235,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
|||||||
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
||||||
redisTemplate.expire(statusKey, 7, java.util.concurrent.TimeUnit.DAYS);
|
redisTemplate.expire(statusKey, 7, java.util.concurrent.TimeUnit.DAYS);
|
||||||
|
|
||||||
importAsyncService.importBaseStaffAsync(excelList, isUpdateSupport, taskId);
|
importAsyncService.importBaseStaffAsync(excelList, taskId);
|
||||||
|
|
||||||
return taskId;
|
return taskId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,10 +131,6 @@ 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("统一社会信用代码格式不正确");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(excel.getStatus())) {
|
|
||||||
throw new RuntimeException("经营状态不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
String riskLevel = EnterpriseRiskLevel.resolveCode(StringUtils.trim(excel.getRiskLevel()));
|
String riskLevel = EnterpriseRiskLevel.resolveCode(StringUtils.trim(excel.getRiskLevel()));
|
||||||
if (riskLevel == null) {
|
if (riskLevel == null) {
|
||||||
throw new RuntimeException("风险等级不在允许范围内");
|
throw new RuntimeException("风险等级不在允许范围内");
|
||||||
@@ -143,10 +139,6 @@ public class CcdiEnterpriseBaseInfoImportServiceImpl implements ICcdiEnterpriseB
|
|||||||
if (entSource == null) {
|
if (entSource == null) {
|
||||||
throw new RuntimeException("企业来源不在允许范围内");
|
throw new RuntimeException("企业来源不在允许范围内");
|
||||||
}
|
}
|
||||||
String dataSource = resolveDataSourceCode(StringUtils.trim(excel.getDataSource()));
|
|
||||||
if (dataSource == null) {
|
|
||||||
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()));
|
||||||
@@ -159,8 +151,8 @@ public class CcdiEnterpriseBaseInfoImportServiceImpl implements ICcdiEnterpriseB
|
|||||||
BeanUtils.copyProperties(excel, entity);
|
BeanUtils.copyProperties(excel, entity);
|
||||||
entity.setRiskLevel(riskLevel);
|
entity.setRiskLevel(riskLevel);
|
||||||
entity.setEntSource(entSource);
|
entity.setEntSource(entSource);
|
||||||
entity.setDataSource(dataSource);
|
entity.setDataSource(DataSource.IMPORT.getCode());
|
||||||
entity.setStatus(StringUtils.trim(excel.getStatus()));
|
entity.setStatus(trimToNull(excel.getStatus()));
|
||||||
entity.setCreatedBy(userName);
|
entity.setCreatedBy(userName);
|
||||||
entity.setUpdatedBy(userName);
|
entity.setUpdatedBy(userName);
|
||||||
return entity;
|
return entity;
|
||||||
@@ -206,15 +198,6 @@ public class CcdiEnterpriseBaseInfoImportServiceImpl implements ICcdiEnterpriseB
|
|||||||
redisTemplate.opsForHash().putAll(buildStatusKey(taskId), statusData);
|
redisTemplate.opsForHash().putAll(buildStatusKey(taskId), statusData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolveDataSourceCode(String value) {
|
|
||||||
for (DataSource source : DataSource.values()) {
|
|
||||||
if (source.getCode().equals(value) || source.getDesc().equals(value)) {
|
|
||||||
return source.getCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildStatusKey(String taskId) {
|
private String buildStatusKey(String taskId) {
|
||||||
return "import:enterpriseBaseInfo:" + taskId;
|
return "import:enterpriseBaseInfo:" + taskId;
|
||||||
}
|
}
|
||||||
@@ -222,4 +205,11 @@ public class CcdiEnterpriseBaseInfoImportServiceImpl implements ICcdiEnterpriseB
|
|||||||
private String buildFailuresKey(String taskId) {
|
private String buildFailuresKey(String taskId) {
|
||||||
return "import:enterpriseBaseInfo:" + taskId + ":failures";
|
return "import:enterpriseBaseInfo:" + taskId + ":failures";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
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 com.ruoyi.info.collection.domain.CcdiCustEnterpriseRelation;
|
||||||
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
|
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoAddDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiEnterpriseBaseInfoQueryDTO;
|
||||||
@@ -14,6 +17,9 @@ import com.ruoyi.info.collection.enums.DataSource;
|
|||||||
import com.ruoyi.info.collection.enums.EnterpriseRiskLevel;
|
import com.ruoyi.info.collection.enums.EnterpriseRiskLevel;
|
||||||
import com.ruoyi.info.collection.enums.EnterpriseSource;
|
import com.ruoyi.info.collection.enums.EnterpriseSource;
|
||||||
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
|
import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper;
|
||||||
|
import com.ruoyi.info.collection.mapper.CcdiCustEnterpriseRelationMapper;
|
||||||
|
import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper;
|
||||||
|
import com.ruoyi.info.collection.mapper.CcdiStaffEnterpriseRelationMapper;
|
||||||
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoImportService;
|
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoImportService;
|
||||||
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoService;
|
import com.ruoyi.info.collection.service.ICcdiEnterpriseBaseInfoService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -25,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.StringJoiner;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -40,6 +47,15 @@ public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInf
|
|||||||
@Resource
|
@Resource
|
||||||
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
|
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiStaffEnterpriseRelationMapper staffEnterpriseRelationMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiCustEnterpriseRelationMapper custEnterpriseRelationMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiIntermediaryEnterpriseRelationMapper intermediaryEnterpriseRelationMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ICcdiEnterpriseBaseInfoImportService enterpriseBaseInfoImportService;
|
private ICcdiEnterpriseBaseInfoImportService enterpriseBaseInfoImportService;
|
||||||
|
|
||||||
@@ -69,10 +85,12 @@ public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInf
|
|||||||
if (enterpriseBaseInfoMapper.selectById(addDTO.getSocialCreditCode()) != null) {
|
if (enterpriseBaseInfoMapper.selectById(addDTO.getSocialCreditCode()) != null) {
|
||||||
throw new RuntimeException("该统一社会信用代码已存在");
|
throw new RuntimeException("该统一社会信用代码已存在");
|
||||||
}
|
}
|
||||||
validateEnumFields(addDTO.getStatus(), addDTO.getRiskLevel(), addDTO.getEntSource(), addDTO.getDataSource());
|
validateRiskLevelAndEnterpriseSource(addDTO.getRiskLevel(), addDTO.getEntSource());
|
||||||
|
|
||||||
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
|
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
|
||||||
BeanUtils.copyProperties(addDTO, entity);
|
BeanUtils.copyProperties(addDTO, entity);
|
||||||
|
entity.setStatus(trimToNull(addDTO.getStatus()));
|
||||||
|
entity.setDataSource(DataSource.MANUAL.getCode());
|
||||||
return enterpriseBaseInfoMapper.insert(entity);
|
return enterpriseBaseInfoMapper.insert(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +105,8 @@ public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInf
|
|||||||
|
|
||||||
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
|
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
|
||||||
BeanUtils.copyProperties(editDTO, entity);
|
BeanUtils.copyProperties(editDTO, entity);
|
||||||
|
entity.setStatus(trimToNull(editDTO.getStatus()));
|
||||||
|
entity.setDataSource(existing.getDataSource());
|
||||||
return enterpriseBaseInfoMapper.updateById(entity);
|
return enterpriseBaseInfoMapper.updateById(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +116,9 @@ public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInf
|
|||||||
if (socialCreditCodes == null || socialCreditCodes.length == 0) {
|
if (socialCreditCodes == null || socialCreditCodes.length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
for (String socialCreditCode : socialCreditCodes) {
|
||||||
|
validateDeleteRelations(socialCreditCode);
|
||||||
|
}
|
||||||
return enterpriseBaseInfoMapper.deleteBatchIds(List.of(socialCreditCodes));
|
return enterpriseBaseInfoMapper.deleteBatchIds(List.of(socialCreditCodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,18 +180,22 @@ public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInf
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateEnumFields(String status, String riskLevel, String entSource, String dataSource) {
|
private void validateEnumFields(String status, String riskLevel, String entSource, String dataSource) {
|
||||||
if (StringUtils.isEmpty(status)) {
|
validateRiskLevelAndEnterpriseSource(riskLevel, entSource);
|
||||||
throw new RuntimeException("经营状态不能为空");
|
if (StringUtils.isNotEmpty(status) && StringUtils.trim(status).length() > 50) {
|
||||||
|
throw new RuntimeException("经营状态长度不能超过50个字符");
|
||||||
}
|
}
|
||||||
|
if (!containsDataSource(dataSource)) {
|
||||||
|
throw new RuntimeException("数据来源不在允许范围内");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateRiskLevelAndEnterpriseSource(String riskLevel, String entSource) {
|
||||||
if (!EnterpriseRiskLevel.contains(riskLevel)) {
|
if (!EnterpriseRiskLevel.contains(riskLevel)) {
|
||||||
throw new RuntimeException("风险等级不在允许范围内");
|
throw new RuntimeException("风险等级不在允许范围内");
|
||||||
}
|
}
|
||||||
if (!EnterpriseSource.contains(entSource)) {
|
if (!EnterpriseSource.contains(entSource)) {
|
||||||
throw new RuntimeException("企业来源不在允许范围内");
|
throw new RuntimeException("企业来源不在允许范围内");
|
||||||
}
|
}
|
||||||
if (!containsDataSource(dataSource)) {
|
|
||||||
throw new RuntimeException("数据来源不在允许范围内");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean containsDataSource(String code) {
|
private boolean containsDataSource(String code) {
|
||||||
@@ -179,4 +206,30 @@ public class CcdiEnterpriseBaseInfoServiceImpl implements ICcdiEnterpriseBaseInf
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateDeleteRelations(String socialCreditCode) {
|
||||||
|
StringJoiner relationTypes = new StringJoiner("、");
|
||||||
|
if (staffEnterpriseRelationMapper.selectCount(new LambdaQueryWrapper<CcdiStaffEnterpriseRelation>()
|
||||||
|
.eq(CcdiStaffEnterpriseRelation::getSocialCreditCode, socialCreditCode)) > 0) {
|
||||||
|
relationTypes.add("员工");
|
||||||
|
}
|
||||||
|
if (custEnterpriseRelationMapper.selectCount(new LambdaQueryWrapper<CcdiCustEnterpriseRelation>()
|
||||||
|
.eq(CcdiCustEnterpriseRelation::getSocialCreditCode, socialCreditCode)) > 0) {
|
||||||
|
relationTypes.add("信贷客户");
|
||||||
|
}
|
||||||
|
if (intermediaryEnterpriseRelationMapper.selectCount(new LambdaQueryWrapper<CcdiIntermediaryEnterpriseRelation>()
|
||||||
|
.eq(CcdiIntermediaryEnterpriseRelation::getSocialCreditCode, socialCreditCode)) > 0) {
|
||||||
|
relationTypes.add("中介");
|
||||||
|
}
|
||||||
|
if (relationTypes.length() > 0) {
|
||||||
|
throw new RuntimeException("统一社会信用代码[" + socialCreditCode + "]已关联" + relationTypes + ",删除失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
package com.ruoyi.info.collection.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
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.excel.CcdiIntermediaryEnterpriseRelationExcel;
|
||||||
|
import com.ruoyi.info.collection.domain.vo.ImportResult;
|
||||||
|
import com.ruoyi.info.collection.domain.vo.ImportStatusVO;
|
||||||
|
import com.ruoyi.info.collection.domain.vo.IntermediaryEnterpriseRelationImportFailureVO;
|
||||||
|
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.service.ICcdiIntermediaryEnterpriseRelationImportService;
|
||||||
|
import com.ruoyi.info.collection.utils.ImportLogUtils;
|
||||||
|
import com.ruoyi.common.utils.IdCardUtil;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中介实体关联关系异步导入实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@EnableAsync
|
||||||
|
public class CcdiIntermediaryEnterpriseRelationImportServiceImpl implements ICcdiIntermediaryEnterpriseRelationImportService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CcdiIntermediaryEnterpriseRelationImportServiceImpl.class);
|
||||||
|
|
||||||
|
private static final String STATUS_KEY_PREFIX = "import:intermediary-enterprise-relation:";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiIntermediaryEnterpriseRelationMapper relationMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiBizIntermediaryMapper intermediaryMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiEnterpriseBaseInfoMapper enterpriseBaseInfoMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Async
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void importAsync(List<CcdiIntermediaryEnterpriseRelationExcel> excelList, String taskId, String userName) {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
ImportLogUtils.logImportStart(log, taskId, "中介实体关联关系", excelList.size(), userName);
|
||||||
|
|
||||||
|
Map<String, String> ownerBizIdByPersonId = getOwnerBizIdByPersonId(excelList);
|
||||||
|
Set<String> existingEnterpriseCodes = getExistingEnterpriseCodes(excelList);
|
||||||
|
Set<String> existingCombinations = getExistingRelationCombinations(ownerBizIdByPersonId, excelList);
|
||||||
|
|
||||||
|
List<CcdiIntermediaryEnterpriseRelation> successRecords = new ArrayList<>();
|
||||||
|
List<IntermediaryEnterpriseRelationImportFailureVO> failures = new ArrayList<>();
|
||||||
|
Set<String> processedCombinations = new HashSet<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
|
CcdiIntermediaryEnterpriseRelationExcel excel = excelList.get(i);
|
||||||
|
try {
|
||||||
|
validateExcel(excel);
|
||||||
|
|
||||||
|
String ownerBizId = ownerBizIdByPersonId.get(excel.getOwnerPersonId());
|
||||||
|
if (StringUtils.isEmpty(ownerBizId)) {
|
||||||
|
throw new RuntimeException("中介本人不存在,请先导入或维护中介本人信息");
|
||||||
|
}
|
||||||
|
if (!existingEnterpriseCodes.contains(excel.getSocialCreditCode())) {
|
||||||
|
throw new RuntimeException("统一社会信用代码不存在于系统机构表");
|
||||||
|
}
|
||||||
|
|
||||||
|
String combination = ownerBizId + "|" + excel.getSocialCreditCode();
|
||||||
|
if (existingCombinations.contains(combination)) {
|
||||||
|
throw new RuntimeException("中介实体关联关系已存在,请勿重复导入");
|
||||||
|
}
|
||||||
|
if (!processedCombinations.add(combination)) {
|
||||||
|
throw new RuntimeException("同一中介本人与统一社会信用代码组合在导入文件中重复");
|
||||||
|
}
|
||||||
|
|
||||||
|
CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation();
|
||||||
|
BeanUtils.copyProperties(excel, relation);
|
||||||
|
relation.setIntermediaryBizId(ownerBizId);
|
||||||
|
relation.setCreatedBy(userName);
|
||||||
|
relation.setUpdatedBy(userName);
|
||||||
|
successRecords.add(relation);
|
||||||
|
} catch (Exception e) {
|
||||||
|
failures.add(createFailureVO(excel, e.getMessage()));
|
||||||
|
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(),
|
||||||
|
String.format("中介本人证件号码=%s, 统一社会信用代码=%s", excel.getOwnerPersonId(), excel.getSocialCreditCode()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!successRecords.isEmpty()) {
|
||||||
|
saveBatch(successRecords, 500);
|
||||||
|
}
|
||||||
|
if (!failures.isEmpty()) {
|
||||||
|
redisTemplate.opsForValue().set(failureKey(taskId), failures, 7, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportResult result = new ImportResult();
|
||||||
|
result.setTotalCount(excelList.size());
|
||||||
|
result.setSuccessCount(successRecords.size());
|
||||||
|
result.setFailureCount(failures.size());
|
||||||
|
updateImportStatus(taskId, result);
|
||||||
|
|
||||||
|
long duration = System.currentTimeMillis() - startTime;
|
||||||
|
ImportLogUtils.logImportComplete(log, taskId, "中介实体关联关系",
|
||||||
|
excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImportStatusVO getImportStatus(String taskId) {
|
||||||
|
String key = statusKey(taskId);
|
||||||
|
if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
|
||||||
|
throw new RuntimeException("任务不存在或已过期");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Object, Object> statusMap = redisTemplate.opsForHash().entries(key);
|
||||||
|
ImportStatusVO statusVO = new ImportStatusVO();
|
||||||
|
statusVO.setTaskId((String) statusMap.get("taskId"));
|
||||||
|
statusVO.setStatus((String) statusMap.get("status"));
|
||||||
|
statusVO.setTotalCount((Integer) statusMap.get("totalCount"));
|
||||||
|
statusVO.setSuccessCount((Integer) statusMap.get("successCount"));
|
||||||
|
statusVO.setFailureCount((Integer) statusMap.get("failureCount"));
|
||||||
|
statusVO.setProgress((Integer) statusMap.get("progress"));
|
||||||
|
statusVO.setStartTime((Long) statusMap.get("startTime"));
|
||||||
|
statusVO.setEndTime((Long) statusMap.get("endTime"));
|
||||||
|
statusVO.setMessage((String) statusMap.get("message"));
|
||||||
|
return statusVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IntermediaryEnterpriseRelationImportFailureVO> getImportFailures(String taskId) {
|
||||||
|
Object failuresObj = redisTemplate.opsForValue().get(failureKey(taskId));
|
||||||
|
if (failuresObj == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return JSON.parseArray(JSON.toJSONString(failuresObj), IntermediaryEnterpriseRelationImportFailureVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getOwnerBizIdByPersonId(List<CcdiIntermediaryEnterpriseRelationExcel> excelList) {
|
||||||
|
List<String> ownerPersonIds = excelList.stream()
|
||||||
|
.map(CcdiIntermediaryEnterpriseRelationExcel::getOwnerPersonId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (ownerPersonIds.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(CcdiBizIntermediary::getPersonSubType, "本人")
|
||||||
|
.in(CcdiBizIntermediary::getPersonId, ownerPersonIds);
|
||||||
|
return intermediaryMapper.selectList(wrapper).stream()
|
||||||
|
.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,
|
||||||
|
List<CcdiIntermediaryEnterpriseRelationExcel> excelList) {
|
||||||
|
List<String> combinations = excelList.stream()
|
||||||
|
.map(excel -> {
|
||||||
|
String ownerBizId = ownerBizIdByPersonId.get(excel.getOwnerPersonId());
|
||||||
|
if (StringUtils.isEmpty(ownerBizId) || StringUtils.isEmpty(excel.getSocialCreditCode())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ownerBizId + "|" + excel.getSocialCreditCode();
|
||||||
|
})
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (combinations.isEmpty()) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
return new HashSet<>(relationMapper.batchExistsByCombinations(combinations));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateExcel(CcdiIntermediaryEnterpriseRelationExcel excel) {
|
||||||
|
if (StringUtils.isEmpty(excel.getOwnerPersonId())) {
|
||||||
|
throw new RuntimeException("中介本人证件号码不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(excel.getSocialCreditCode())) {
|
||||||
|
throw new RuntimeException("统一社会信用代码不能为空");
|
||||||
|
}
|
||||||
|
String ownerPersonIdError = IdCardUtil.getErrorMessage(excel.getOwnerPersonId());
|
||||||
|
if (ownerPersonIdError != null) {
|
||||||
|
throw new RuntimeException("中介本人证件号码" + ownerPersonIdError);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(excel.getRelationPersonPost()) && excel.getRelationPersonPost().length() > 100) {
|
||||||
|
throw new RuntimeException("关联人职务长度不能超过100个字符");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(excel.getRemark()) && excel.getRemark().length() > 500) {
|
||||||
|
throw new RuntimeException("备注长度不能超过500个字符");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntermediaryEnterpriseRelationImportFailureVO createFailureVO(CcdiIntermediaryEnterpriseRelationExcel excel,
|
||||||
|
String errorMessage) {
|
||||||
|
IntermediaryEnterpriseRelationImportFailureVO failure = new IntermediaryEnterpriseRelationImportFailureVO();
|
||||||
|
BeanUtils.copyProperties(excel, failure);
|
||||||
|
failure.setErrorMessage(errorMessage);
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveBatch(List<CcdiIntermediaryEnterpriseRelation> list, int batchSize) {
|
||||||
|
for (int i = 0; i < list.size(); i += batchSize) {
|
||||||
|
int end = Math.min(i + batchSize, list.size());
|
||||||
|
relationMapper.insertBatch(list.subList(i, end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateImportStatus(String taskId, ImportResult result) {
|
||||||
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
|
statusData.put("status", result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS");
|
||||||
|
statusData.put("successCount", result.getSuccessCount());
|
||||||
|
statusData.put("failureCount", result.getFailureCount());
|
||||||
|
statusData.put("progress", 100);
|
||||||
|
statusData.put("endTime", System.currentTimeMillis());
|
||||||
|
statusData.put("message", result.getFailureCount() == 0
|
||||||
|
? "全部成功!共导入" + result.getTotalCount() + "条数据"
|
||||||
|
: "成功" + result.getSuccessCount() + "条,失败" + result.getFailureCount() + "条");
|
||||||
|
redisTemplate.opsForHash().putAll(statusKey(taskId), statusData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String statusKey(String taskId) {
|
||||||
|
return STATUS_KEY_PREFIX + taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String failureKey(String taskId) {
|
||||||
|
return statusKey(taskId) + ":failures";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,15 +22,18 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 个人中介异步导入Service实现
|
* 中介信息异步导入实现
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-02-06
|
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
@@ -38,6 +41,8 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CcdiIntermediaryPersonImportServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(CcdiIntermediaryPersonImportServiceImpl.class);
|
||||||
|
|
||||||
|
private static final String STATUS_KEY_PREFIX = "import:intermediary:";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CcdiBizIntermediaryMapper intermediaryMapper;
|
private CcdiBizIntermediaryMapper intermediaryMapper;
|
||||||
|
|
||||||
@@ -47,110 +52,104 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
|||||||
@Override
|
@Override
|
||||||
@Async
|
@Async
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void importPersonAsync(List<CcdiIntermediaryPersonExcel> excelList,
|
public void importPersonAsync(List<CcdiIntermediaryPersonExcel> excelList, String taskId, String userName) {
|
||||||
String taskId,
|
|
||||||
String userName) {
|
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
ImportLogUtils.logImportStart(log, taskId, "中介信息", excelList.size(), userName);
|
||||||
|
|
||||||
// 记录导入开始
|
List<CcdiIntermediaryPersonExcel> ownerRows = new ArrayList<>();
|
||||||
ImportLogUtils.logImportStart(log, taskId, "个人中介", excelList.size(), userName);
|
List<CcdiIntermediaryPersonExcel> relativeRows = new ArrayList<>();
|
||||||
|
|
||||||
List<CcdiBizIntermediary> newRecords = new ArrayList<>();
|
|
||||||
List<IntermediaryPersonImportFailureVO> failures = new ArrayList<>();
|
List<IntermediaryPersonImportFailureVO> failures = new ArrayList<>();
|
||||||
|
|
||||||
// 批量查询已存在的证件号
|
|
||||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的证件号", excelList.size());
|
|
||||||
Set<String> existingPersonIds = getExistingPersonIds(excelList);
|
|
||||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "证件号", existingPersonIds.size());
|
|
||||||
|
|
||||||
// 用于检测Excel内部的重复ID
|
|
||||||
Set<String> excelProcessedIds = new HashSet<>();
|
|
||||||
|
|
||||||
// 分类数据
|
|
||||||
for (int i = 0; i < excelList.size(); i++) {
|
for (int i = 0; i < excelList.size(); i++) {
|
||||||
CcdiIntermediaryPersonExcel excel = excelList.get(i);
|
CcdiIntermediaryPersonExcel excel = excelList.get(i);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 验证数据
|
validateCommonRow(excel);
|
||||||
validatePersonData(excel, existingPersonIds);
|
if (isOwnerRow(excel)) {
|
||||||
|
validateOwnerRow(excel);
|
||||||
CcdiBizIntermediary intermediary = new CcdiBizIntermediary();
|
ownerRows.add(excel);
|
||||||
BeanUtils.copyProperties(excel, intermediary);
|
|
||||||
|
|
||||||
// 设置数据来源和审计字段
|
|
||||||
intermediary.setDataSource("IMPORT");
|
|
||||||
intermediary.setCreatedBy(userName);
|
|
||||||
intermediary.setUpdatedBy(userName);
|
|
||||||
|
|
||||||
if (existingPersonIds.contains(excel.getPersonId())) {
|
|
||||||
// 证件号码在数据库中已存在,直接报错
|
|
||||||
throw new RuntimeException(String.format("证件号码[%s]已存在,请勿重复导入", excel.getPersonId()));
|
|
||||||
} else if (excelProcessedIds.contains(excel.getPersonId())) {
|
|
||||||
// 证件号码在Excel文件内部重复
|
|
||||||
throw new RuntimeException(String.format("证件号码[%s]在导入文件中重复,已跳过此条记录", excel.getPersonId()));
|
|
||||||
} else {
|
} else {
|
||||||
newRecords.add(intermediary);
|
validateRelativeRow(excel);
|
||||||
excelProcessedIds.add(excel.getPersonId()); // 标记为已处理
|
relativeRows.add(excel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录进度
|
|
||||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
|
||||||
newRecords.size(), failures.size());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
failures.add(createFailureVO(excel, e.getMessage()));
|
failures.add(createFailureVO(excel, e.getMessage()));
|
||||||
|
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(),
|
||||||
// 记录验证失败日志
|
String.format("姓名=%s, 证件号码=%s", excel.getName(), excel.getPersonId()));
|
||||||
String keyData = String.format("姓名=%s, 证件号码=%s",
|
|
||||||
excel.getName(), excel.getPersonId());
|
|
||||||
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量插入新数据
|
Set<String> existingOwnerPersonIds = getExistingOwnerPersonIds(ownerRows);
|
||||||
if (!newRecords.isEmpty()) {
|
Set<String> existingOwnerRefs = getExistingOwnerRefs(relativeRows);
|
||||||
ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
|
Set<String> existingRelativeCombinations = getExistingRelativeCombinations(relativeRows);
|
||||||
(newRecords.size() + 499) / 500, 500);
|
|
||||||
saveBatch(newRecords, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存失败记录到Redis
|
List<CcdiBizIntermediary> successRecords = new ArrayList<>();
|
||||||
if (!failures.isEmpty()) {
|
Set<String> importedOwnerPersonIds = new HashSet<>();
|
||||||
|
|
||||||
|
for (CcdiIntermediaryPersonExcel ownerExcel : ownerRows) {
|
||||||
try {
|
try {
|
||||||
String failuresKey = "import:intermediary:" + taskId + ":failures";
|
String ownerPersonId = ownerExcel.getPersonId();
|
||||||
redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS);
|
if (existingOwnerPersonIds.contains(ownerPersonId)) {
|
||||||
ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size());
|
throw new RuntimeException(String.format("中介本人证件号码[%s]已存在,请勿重复导入", ownerPersonId));
|
||||||
} catch (Exception e) {
|
|
||||||
ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e);
|
|
||||||
}
|
}
|
||||||
|
if (!importedOwnerPersonIds.add(ownerPersonId)) {
|
||||||
|
throw new RuntimeException(String.format("中介本人证件号码[%s]在导入文件中重复", ownerPersonId));
|
||||||
|
}
|
||||||
|
successRecords.add(buildRecord(ownerExcel, userName, null));
|
||||||
|
} catch (Exception e) {
|
||||||
|
failures.add(createFailureVO(ownerExcel, e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> validOwnerRefs = new HashSet<>(existingOwnerRefs);
|
||||||
|
validOwnerRefs.addAll(importedOwnerPersonIds);
|
||||||
|
Set<String> processedRelativeCombinations = new HashSet<>();
|
||||||
|
|
||||||
|
for (CcdiIntermediaryPersonExcel relativeExcel : relativeRows) {
|
||||||
|
try {
|
||||||
|
String ownerPersonId = relativeExcel.getRelatedNumId();
|
||||||
|
String combination = ownerPersonId + "|" + relativeExcel.getPersonId();
|
||||||
|
if (!validOwnerRefs.contains(ownerPersonId)) {
|
||||||
|
throw new RuntimeException(String.format("关联中介本人证件号码[%s]不存在", ownerPersonId));
|
||||||
|
}
|
||||||
|
if (existingRelativeCombinations.contains(combination)) {
|
||||||
|
throw new RuntimeException(String.format("同一中介本人名下证件号码[%s]的亲属已存在,请勿重复导入", relativeExcel.getPersonId()));
|
||||||
|
}
|
||||||
|
if (!processedRelativeCombinations.add(combination)) {
|
||||||
|
throw new RuntimeException(String.format("同一中介本人名下证件号码[%s]的亲属在导入文件中重复", relativeExcel.getPersonId()));
|
||||||
|
}
|
||||||
|
successRecords.add(buildRecord(relativeExcel, userName, ownerPersonId));
|
||||||
|
} catch (Exception e) {
|
||||||
|
failures.add(createFailureVO(relativeExcel, e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!successRecords.isEmpty()) {
|
||||||
|
saveBatch(successRecords, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!failures.isEmpty()) {
|
||||||
|
redisTemplate.opsForValue().set(failureKey(taskId), failures, 7, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportResult result = new ImportResult();
|
ImportResult result = new ImportResult();
|
||||||
result.setTotalCount(excelList.size());
|
result.setTotalCount(excelList.size());
|
||||||
result.setSuccessCount(newRecords.size());
|
result.setSuccessCount(successRecords.size());
|
||||||
result.setFailureCount(failures.size());
|
result.setFailureCount(failures.size());
|
||||||
|
updateImportStatus(taskId, result);
|
||||||
|
|
||||||
// 更新最终状态
|
|
||||||
String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS";
|
|
||||||
updateImportStatus(taskId, finalStatus, result);
|
|
||||||
|
|
||||||
// 记录导入完成
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImportStatusVO getImportStatus(String taskId) {
|
public ImportStatusVO getImportStatus(String taskId) {
|
||||||
String key = "import:intermediary:" + taskId;
|
String key = statusKey(taskId);
|
||||||
Boolean hasKey = redisTemplate.hasKey(key);
|
if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
|
||||||
|
|
||||||
if (Boolean.FALSE.equals(hasKey)) {
|
|
||||||
throw new RuntimeException("任务不存在或已过期");
|
throw new RuntimeException("任务不存在或已过期");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Object, Object> statusMap = redisTemplate.opsForHash().entries(key);
|
Map<Object, Object> statusMap = redisTemplate.opsForHash().entries(key);
|
||||||
|
|
||||||
ImportStatusVO statusVO = new ImportStatusVO();
|
ImportStatusVO statusVO = new ImportStatusVO();
|
||||||
statusVO.setTaskId((String) statusMap.get("taskId"));
|
statusVO.setTaskId((String) statusMap.get("taskId"));
|
||||||
statusVO.setStatus((String) statusMap.get("status"));
|
statusVO.setStatus((String) statusMap.get("status"));
|
||||||
@@ -161,83 +160,120 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
|||||||
statusVO.setStartTime((Long) statusMap.get("startTime"));
|
statusVO.setStartTime((Long) statusMap.get("startTime"));
|
||||||
statusVO.setEndTime((Long) statusMap.get("endTime"));
|
statusVO.setEndTime((Long) statusMap.get("endTime"));
|
||||||
statusVO.setMessage((String) statusMap.get("message"));
|
statusVO.setMessage((String) statusMap.get("message"));
|
||||||
|
|
||||||
return statusVO;
|
return statusVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IntermediaryPersonImportFailureVO> getImportFailures(String taskId) {
|
public List<IntermediaryPersonImportFailureVO> getImportFailures(String taskId) {
|
||||||
String key = "import:intermediary:" + taskId + ":failures";
|
Object failuresObj = redisTemplate.opsForValue().get(failureKey(taskId));
|
||||||
Object failuresObj = redisTemplate.opsForValue().get(key);
|
|
||||||
|
|
||||||
if (failuresObj == null) {
|
if (failuresObj == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.parseArray(JSON.toJSONString(failuresObj), IntermediaryPersonImportFailureVO.class);
|
return JSON.parseArray(JSON.toJSONString(failuresObj), IntermediaryPersonImportFailureVO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean isOwnerRow(CcdiIntermediaryPersonExcel excel) {
|
||||||
* 批量查询已存在的证件号
|
return "本人".equals(excel.getPersonSubType());
|
||||||
*/
|
}
|
||||||
private Set<String> getExistingPersonIds(List<CcdiIntermediaryPersonExcel> excelList) {
|
|
||||||
List<String> personIds = excelList.stream()
|
private void validateCommonRow(CcdiIntermediaryPersonExcel excel) {
|
||||||
|
if (StringUtils.isEmpty(excel.getName())) {
|
||||||
|
throw new RuntimeException("姓名不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(excel.getPersonSubType())) {
|
||||||
|
throw new RuntimeException("人员子类型不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(excel.getPersonId())) {
|
||||||
|
throw new RuntimeException("证件号码不能为空");
|
||||||
|
}
|
||||||
|
String idCardError = IdCardUtil.getErrorMessage(excel.getPersonId());
|
||||||
|
if (idCardError != null) {
|
||||||
|
throw new RuntimeException("证件号码" + idCardError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateOwnerRow(CcdiIntermediaryPersonExcel excel) {
|
||||||
|
if (StringUtils.isNotEmpty(excel.getRelatedNumId())) {
|
||||||
|
throw new RuntimeException("本人行关联中介本人证件号码必须为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateRelativeRow(CcdiIntermediaryPersonExcel excel) {
|
||||||
|
if (StringUtils.isEmpty(excel.getRelatedNumId())) {
|
||||||
|
throw new RuntimeException("亲属行必须填写关联中介本人证件号码");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getExistingOwnerPersonIds(List<CcdiIntermediaryPersonExcel> ownerRows) {
|
||||||
|
List<String> ownerPersonIds = ownerRows.stream()
|
||||||
.map(CcdiIntermediaryPersonExcel::getPersonId)
|
.map(CcdiIntermediaryPersonExcel::getPersonId)
|
||||||
.filter(StringUtils::isNotEmpty)
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
if (ownerPersonIds.isEmpty()) {
|
||||||
if (personIds.isEmpty()) {
|
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.in(CcdiBizIntermediary::getPersonId, personIds);
|
wrapper.eq(CcdiBizIntermediary::getPersonSubType, "本人")
|
||||||
List<CcdiBizIntermediary> existingIntermediaries = intermediaryMapper.selectList(wrapper);
|
.in(CcdiBizIntermediary::getPersonId, ownerPersonIds);
|
||||||
|
return intermediaryMapper.selectList(wrapper).stream()
|
||||||
return existingIntermediaries.stream()
|
|
||||||
.map(CcdiBizIntermediary::getPersonId)
|
.map(CcdiBizIntermediary::getPersonId)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Set<String> getExistingOwnerRefs(List<CcdiIntermediaryPersonExcel> relativeRows) {
|
||||||
* 批量保存(使用ON DUPLICATE KEY UPDATE)
|
List<String> ownerRefs = relativeRows.stream()
|
||||||
*/
|
.map(CcdiIntermediaryPersonExcel::getRelatedNumId)
|
||||||
private int saveBatchWithUpsert(List<CcdiBizIntermediary> list, int batchSize) {
|
|
||||||
int totalCount = 0;
|
|
||||||
for (int i = 0; i < list.size(); i += batchSize) {
|
|
||||||
int end = Math.min(i + batchSize, list.size());
|
|
||||||
List<CcdiBizIntermediary> subList = list.subList(i, end);
|
|
||||||
int count = intermediaryMapper.importPersonBatch(subList);
|
|
||||||
totalCount += count;
|
|
||||||
}
|
|
||||||
return totalCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从数据库获取已存在的证件号
|
|
||||||
*/
|
|
||||||
private Set<String> getExistingPersonIdsFromDb(List<CcdiBizIntermediary> records) {
|
|
||||||
List<String> personIds = records.stream()
|
|
||||||
.map(CcdiBizIntermediary::getPersonId)
|
|
||||||
.filter(StringUtils::isNotEmpty)
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
if (ownerRefs.isEmpty()) {
|
||||||
if (personIds.isEmpty()) {
|
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.in(CcdiBizIntermediary::getPersonId, personIds);
|
wrapper.eq(CcdiBizIntermediary::getPersonSubType, "本人")
|
||||||
List<CcdiBizIntermediary> existing = intermediaryMapper.selectList(wrapper);
|
.in(CcdiBizIntermediary::getPersonId, ownerRefs);
|
||||||
|
return intermediaryMapper.selectList(wrapper).stream()
|
||||||
return existing.stream()
|
|
||||||
.map(CcdiBizIntermediary::getPersonId)
|
.map(CcdiBizIntermediary::getPersonId)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Set<String> getExistingRelativeCombinations(List<CcdiIntermediaryPersonExcel> relativeRows) {
|
||||||
* 创建失败记录VO
|
List<String> ownerRefs = relativeRows.stream()
|
||||||
*/
|
.map(CcdiIntermediaryPersonExcel::getRelatedNumId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<String> relativePersonIds = relativeRows.stream()
|
||||||
|
.map(CcdiIntermediaryPersonExcel::getPersonId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (ownerRefs.isEmpty() || relativePersonIds.isEmpty()) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.ne(CcdiBizIntermediary::getPersonSubType, "本人")
|
||||||
|
.in(CcdiBizIntermediary::getRelatedNumId, ownerRefs)
|
||||||
|
.in(CcdiBizIntermediary::getPersonId, relativePersonIds);
|
||||||
|
return intermediaryMapper.selectList(wrapper).stream()
|
||||||
|
.map(item -> item.getRelatedNumId() + "|" + item.getPersonId())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CcdiBizIntermediary buildRecord(CcdiIntermediaryPersonExcel excel, String userName, String ownerPersonId) {
|
||||||
|
CcdiBizIntermediary intermediary = new CcdiBizIntermediary();
|
||||||
|
BeanUtils.copyProperties(excel, intermediary);
|
||||||
|
intermediary.setRelatedNumId(ownerPersonId);
|
||||||
|
intermediary.setDataSource("IMPORT");
|
||||||
|
intermediary.setCreatedBy(userName);
|
||||||
|
intermediary.setUpdatedBy(userName);
|
||||||
|
return intermediary;
|
||||||
|
}
|
||||||
|
|
||||||
private IntermediaryPersonImportFailureVO createFailureVO(CcdiIntermediaryPersonExcel excel, String errorMsg) {
|
private IntermediaryPersonImportFailureVO createFailureVO(CcdiIntermediaryPersonExcel excel, String errorMsg) {
|
||||||
IntermediaryPersonImportFailureVO failure = new IntermediaryPersonImportFailureVO();
|
IntermediaryPersonImportFailureVO failure = new IntermediaryPersonImportFailureVO();
|
||||||
BeanUtils.copyProperties(excel, failure);
|
BeanUtils.copyProperties(excel, failure);
|
||||||
@@ -245,73 +281,31 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
|||||||
return failure;
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void saveBatch(List<CcdiBizIntermediary> list, int batchSize) {
|
||||||
* 创建失败记录VO(重载方法)
|
|
||||||
*/
|
|
||||||
private IntermediaryPersonImportFailureVO createFailureVO(CcdiBizIntermediary record, String errorMsg) {
|
|
||||||
CcdiIntermediaryPersonExcel excel = new CcdiIntermediaryPersonExcel();
|
|
||||||
BeanUtils.copyProperties(record, excel);
|
|
||||||
return createFailureVO(excel, errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量保存
|
|
||||||
*/
|
|
||||||
private int saveBatch(List<CcdiBizIntermediary> list, int batchSize) {
|
|
||||||
// 使用真正的批量插入,分批次执行以提高性能
|
|
||||||
int totalCount = 0;
|
|
||||||
for (int i = 0; i < list.size(); i += batchSize) {
|
for (int i = 0; i < list.size(); i += batchSize) {
|
||||||
int end = Math.min(i + batchSize, list.size());
|
int end = Math.min(i + batchSize, list.size());
|
||||||
List<CcdiBizIntermediary> subList = list.subList(i, end);
|
intermediaryMapper.insertBatch(list.subList(i, end));
|
||||||
int count = intermediaryMapper.insertBatch(subList);
|
|
||||||
totalCount += count;
|
|
||||||
}
|
}
|
||||||
return totalCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void updateImportStatus(String taskId, ImportResult result) {
|
||||||
* 更新导入状态
|
|
||||||
*/
|
|
||||||
private void updateImportStatus(String taskId, String status, ImportResult result) {
|
|
||||||
String key = "import:intermediary:" + taskId;
|
|
||||||
Map<String, Object> statusData = new HashMap<>();
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
statusData.put("status", status);
|
statusData.put("status", result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS");
|
||||||
statusData.put("successCount", result.getSuccessCount());
|
statusData.put("successCount", result.getSuccessCount());
|
||||||
statusData.put("failureCount", result.getFailureCount());
|
statusData.put("failureCount", result.getFailureCount());
|
||||||
statusData.put("progress", 100);
|
statusData.put("progress", 100);
|
||||||
statusData.put("endTime", System.currentTimeMillis());
|
statusData.put("endTime", System.currentTimeMillis());
|
||||||
|
statusData.put("message", result.getFailureCount() == 0
|
||||||
if ("SUCCESS".equals(status)) {
|
? "全部成功!共导入" + result.getTotalCount() + "条数据"
|
||||||
statusData.put("message", "全部成功!共导入" + result.getTotalCount() + "条数据");
|
: "成功" + result.getSuccessCount() + "条,失败" + result.getFailureCount() + "条");
|
||||||
} else {
|
redisTemplate.opsForHash().putAll(statusKey(taskId), statusData);
|
||||||
statusData.put("message", "成功" + result.getSuccessCount() + "条,失败" + result.getFailureCount() + "条");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
redisTemplate.opsForHash().putAll(key, statusData);
|
private String statusKey(String taskId) {
|
||||||
|
return STATUS_KEY_PREFIX + taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private String failureKey(String taskId) {
|
||||||
* 验证个人中介数据
|
return statusKey(taskId) + ":failures";
|
||||||
*
|
|
||||||
* @param excel Excel数据
|
|
||||||
* @param existingPersonIds 已存在的证件号集合
|
|
||||||
*/
|
|
||||||
private void validatePersonData(CcdiIntermediaryPersonExcel excel,
|
|
||||||
Set<String> existingPersonIds) {
|
|
||||||
// 验证必填字段:姓名
|
|
||||||
if (StringUtils.isEmpty(excel.getName())) {
|
|
||||||
throw new RuntimeException("姓名不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证必填字段:证件号码
|
|
||||||
if (StringUtils.isEmpty(excel.getPersonId())) {
|
|
||||||
throw new RuntimeException("证件号码不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证证件号码格式
|
|
||||||
String idCardError = IdCardUtil.getErrorMessage(excel.getPersonId());
|
|
||||||
if (idCardError != null) {
|
|
||||||
throw new RuntimeException("证件号码" + idCardError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.ruoyi.info.collection.domain.CcdiBizIntermediary;
|
|||||||
import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo;
|
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.dto.*;
|
import com.ruoyi.info.collection.domain.dto.*;
|
||||||
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEnterpriseRelationExcel;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel;
|
||||||
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO;
|
||||||
@@ -17,6 +18,7 @@ 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;
|
||||||
import com.ruoyi.info.collection.mapper.CcdiIntermediaryMapper;
|
import com.ruoyi.info.collection.mapper.CcdiIntermediaryMapper;
|
||||||
|
import com.ruoyi.info.collection.service.ICcdiIntermediaryEnterpriseRelationImportService;
|
||||||
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;
|
||||||
@@ -61,6 +63,9 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
@Resource
|
@Resource
|
||||||
private ICcdiIntermediaryEntityImportService entityImportService;
|
private ICcdiIntermediaryEntityImportService entityImportService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ICcdiIntermediaryEnterpriseRelationImportService enterpriseRelationImportService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@@ -101,8 +106,9 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CcdiIntermediaryRelativeVO> selectIntermediaryRelativeList(String bizId) {
|
public List<CcdiIntermediaryRelativeVO> selectIntermediaryRelativeList(String bizId) {
|
||||||
|
CcdiBizIntermediary owner = requireIntermediaryPerson(bizId);
|
||||||
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.eq(CcdiBizIntermediary::getRelatedNumId, bizId)
|
wrapper.eq(CcdiBizIntermediary::getRelatedNumId, owner.getPersonId())
|
||||||
.ne(CcdiBizIntermediary::getPersonSubType, "本人")
|
.ne(CcdiBizIntermediary::getPersonSubType, "本人")
|
||||||
.orderByDesc(CcdiBizIntermediary::getCreateTime);
|
.orderByDesc(CcdiBizIntermediary::getCreateTime);
|
||||||
return bizIntermediaryMapper.selectList(wrapper).stream().map(this::buildRelativeVo).toList();
|
return bizIntermediaryMapper.selectList(wrapper).stream().map(this::buildRelativeVo).toList();
|
||||||
@@ -187,8 +193,9 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
BeanUtils.copyProperties(editDTO, person);
|
BeanUtils.copyProperties(editDTO, person);
|
||||||
person.setPersonSubType("本人");
|
person.setPersonSubType("本人");
|
||||||
person.setRelatedNumId(null);
|
person.setRelatedNumId(null);
|
||||||
|
int updated = bizIntermediaryMapper.updateById(person);
|
||||||
return bizIntermediaryMapper.updateById(person);
|
syncRelativeOwnerPersonId(existing.getPersonId(), editDTO.getPersonId());
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -196,13 +203,13 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
public int insertIntermediaryRelative(String bizId, CcdiIntermediaryRelativeAddDTO addDTO) {
|
public int insertIntermediaryRelative(String bizId, CcdiIntermediaryRelativeAddDTO addDTO) {
|
||||||
CcdiBizIntermediary owner = requireIntermediaryPerson(bizId);
|
CcdiBizIntermediary owner = requireIntermediaryPerson(bizId);
|
||||||
validateRelativePersonSubType(addDTO.getPersonSubType());
|
validateRelativePersonSubType(addDTO.getPersonSubType());
|
||||||
if (!checkPersonIdUnique(addDTO.getPersonId(), null)) {
|
if (!checkRelativePersonUnique(owner.getPersonId(), addDTO.getPersonId(), null)) {
|
||||||
throw new RuntimeException("该证件号已存在");
|
throw new RuntimeException("该中介本人下已存在相同证件号亲属");
|
||||||
}
|
}
|
||||||
|
|
||||||
CcdiBizIntermediary relative = new CcdiBizIntermediary();
|
CcdiBizIntermediary relative = new CcdiBizIntermediary();
|
||||||
BeanUtils.copyProperties(addDTO, relative);
|
BeanUtils.copyProperties(addDTO, relative);
|
||||||
relative.setRelatedNumId(owner.getBizId());
|
relative.setRelatedNumId(owner.getPersonId());
|
||||||
relative.setDataSource("MANUAL");
|
relative.setDataSource("MANUAL");
|
||||||
return bizIntermediaryMapper.insert(relative);
|
return bizIntermediaryMapper.insert(relative);
|
||||||
}
|
}
|
||||||
@@ -216,8 +223,8 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
}
|
}
|
||||||
validateRelativePersonSubType(editDTO.getPersonSubType());
|
validateRelativePersonSubType(editDTO.getPersonSubType());
|
||||||
if (StringUtils.isNotEmpty(editDTO.getPersonId())
|
if (StringUtils.isNotEmpty(editDTO.getPersonId())
|
||||||
&& !checkPersonIdUnique(editDTO.getPersonId(), editDTO.getBizId())) {
|
&& !checkRelativePersonUnique(existing.getRelatedNumId(), editDTO.getPersonId(), editDTO.getBizId())) {
|
||||||
throw new RuntimeException("该证件号已存在");
|
throw new RuntimeException("该中介本人下已存在相同证件号亲属");
|
||||||
}
|
}
|
||||||
|
|
||||||
CcdiBizIntermediary relative = new CcdiBizIntermediary();
|
CcdiBizIntermediary relative = new CcdiBizIntermediary();
|
||||||
@@ -334,7 +341,8 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
if (intermediary != null) {
|
if (intermediary != null) {
|
||||||
if (isIntermediaryPerson(intermediary)) {
|
if (isIntermediaryPerson(intermediary)) {
|
||||||
bizIntermediaryMapper.delete(new LambdaQueryWrapper<CcdiBizIntermediary>()
|
bizIntermediaryMapper.delete(new LambdaQueryWrapper<CcdiBizIntermediary>()
|
||||||
.eq(CcdiBizIntermediary::getRelatedNumId, id));
|
.eq(CcdiBizIntermediary::getRelatedNumId, intermediary.getPersonId())
|
||||||
|
.ne(CcdiBizIntermediary::getPersonSubType, "本人"));
|
||||||
enterpriseRelationMapper.delete(new LambdaQueryWrapper<CcdiIntermediaryEnterpriseRelation>()
|
enterpriseRelationMapper.delete(new LambdaQueryWrapper<CcdiIntermediaryEnterpriseRelation>()
|
||||||
.eq(CcdiIntermediaryEnterpriseRelation::getIntermediaryBizId, id));
|
.eq(CcdiIntermediaryEnterpriseRelation::getIntermediaryBizId, id));
|
||||||
}
|
}
|
||||||
@@ -359,7 +367,8 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
@Override
|
@Override
|
||||||
public boolean checkPersonIdUnique(String personId, String bizId) {
|
public boolean checkPersonIdUnique(String personId, String bizId) {
|
||||||
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.eq(CcdiBizIntermediary::getPersonId, personId);
|
wrapper.eq(CcdiBizIntermediary::getPersonId, personId)
|
||||||
|
.eq(CcdiBizIntermediary::getPersonSubType, "本人");
|
||||||
if (StringUtils.isNotEmpty(bizId)) {
|
if (StringUtils.isNotEmpty(bizId)) {
|
||||||
wrapper.ne(CcdiBizIntermediary::getBizId, bizId);
|
wrapper.ne(CcdiBizIntermediary::getBizId, bizId);
|
||||||
}
|
}
|
||||||
@@ -419,6 +428,31 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
return taskId;
|
return taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public String importIntermediaryEnterpriseRelation(List<CcdiIntermediaryEnterpriseRelationExcel> list) {
|
||||||
|
String taskId = UUID.randomUUID().toString();
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
String statusKey = "import:intermediary-enterprise-relation:" + taskId;
|
||||||
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
|
statusData.put("taskId", taskId);
|
||||||
|
statusData.put("status", "PROCESSING");
|
||||||
|
statusData.put("totalCount", list.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);
|
||||||
|
|
||||||
|
String userName = SecurityUtils.getUsername();
|
||||||
|
enterpriseRelationImportService.importAsync(list, taskId, userName);
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入实体中介数据(异步)
|
* 导入实体中介数据(异步)
|
||||||
*
|
*
|
||||||
@@ -473,6 +507,17 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkRelativePersonUnique(String ownerPersonId, String personId, String excludeBizId) {
|
||||||
|
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(CcdiBizIntermediary::getRelatedNumId, ownerPersonId)
|
||||||
|
.eq(CcdiBizIntermediary::getPersonId, personId)
|
||||||
|
.ne(CcdiBizIntermediary::getPersonSubType, "本人");
|
||||||
|
if (StringUtils.isNotEmpty(excludeBizId)) {
|
||||||
|
wrapper.ne(CcdiBizIntermediary::getBizId, excludeBizId);
|
||||||
|
}
|
||||||
|
return bizIntermediaryMapper.selectCount(wrapper) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
if (enterpriseBaseInfoMapper.selectById(socialCreditCode) == null) {
|
||||||
@@ -490,6 +535,20 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncRelativeOwnerPersonId(String oldOwnerPersonId, String newOwnerPersonId) {
|
||||||
|
if (StringUtils.isEmpty(oldOwnerPersonId)
|
||||||
|
|| StringUtils.isEmpty(newOwnerPersonId)
|
||||||
|
|| oldOwnerPersonId.equals(newOwnerPersonId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcdiBizIntermediary relative = new CcdiBizIntermediary();
|
||||||
|
relative.setRelatedNumId(newOwnerPersonId);
|
||||||
|
bizIntermediaryMapper.update(relative, new LambdaQueryWrapper<CcdiBizIntermediary>()
|
||||||
|
.eq(CcdiBizIntermediary::getRelatedNumId, oldOwnerPersonId)
|
||||||
|
.ne(CcdiBizIntermediary::getPersonSubType, "本人"));
|
||||||
|
}
|
||||||
|
|
||||||
private CcdiIntermediaryRelativeVO buildRelativeVo(CcdiBizIntermediary relative) {
|
private CcdiIntermediaryRelativeVO buildRelativeVo(CcdiBizIntermediary relative) {
|
||||||
CcdiIntermediaryRelativeVO vo = new CcdiIntermediaryRelativeVO();
|
CcdiIntermediaryRelativeVO vo = new CcdiIntermediaryRelativeVO();
|
||||||
BeanUtils.copyProperties(relative, vo);
|
BeanUtils.copyProperties(relative, vo);
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ package com.ruoyi.info.collection.service.impl;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransaction;
|
import com.ruoyi.info.collection.domain.CcdiPurchaseTransaction;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiPurchaseTransactionSupplier;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||||
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionSupplierExcel;
|
||||||
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.mapper.CcdiPurchaseTransactionMapper;
|
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper;
|
||||||
|
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.utils.ImportLogUtils;
|
import com.ruoyi.info.collection.utils.ImportLogUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
@@ -37,83 +40,155 @@ import java.util.stream.Collectors;
|
|||||||
public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTransactionImportService {
|
public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTransactionImportService {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CcdiPurchaseTransactionImportServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(CcdiPurchaseTransactionImportServiceImpl.class);
|
||||||
|
private static final String MAIN_SHEET_NAME = "招投标主信息";
|
||||||
|
private static final String SUPPLIER_SHEET_NAME = "供应商明细";
|
||||||
|
private static final int EXCEL_DATA_START_ROW = 2;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CcdiPurchaseTransactionMapper transactionMapper;
|
private CcdiPurchaseTransactionMapper transactionMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiPurchaseTransactionSupplierMapper supplierMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Async
|
@Async
|
||||||
@Transactional
|
@Transactional
|
||||||
public void importTransactionAsync(List<CcdiPurchaseTransactionExcel> excelList, String taskId, String userName) {
|
public void importTransactionAsync(
|
||||||
|
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList,
|
||||||
|
String taskId,
|
||||||
|
String userName
|
||||||
|
) {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
List<CcdiPurchaseTransactionExcel> safeMainList = mainExcelList == null ? List.of() : mainExcelList;
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> safeSupplierList = supplierExcelList == null ? List.of() : supplierExcelList;
|
||||||
|
List<MainImportRow> indexedMainRows = buildMainImportRows(safeMainList);
|
||||||
|
List<SupplierImportRow> indexedSupplierRows = buildSupplierImportRows(safeSupplierList);
|
||||||
|
int totalCount = countImportUnits(safeMainList, safeSupplierList);
|
||||||
|
|
||||||
// 记录导入开始
|
// 记录导入开始
|
||||||
ImportLogUtils.logImportStart(log, taskId, "采购交易信息", excelList.size(), userName);
|
ImportLogUtils.logImportStart(log, taskId, "招投标信息维护", totalCount, userName);
|
||||||
|
|
||||||
List<CcdiPurchaseTransaction> newRecords = new ArrayList<>();
|
List<CcdiPurchaseTransaction> newTransactions = new ArrayList<>();
|
||||||
|
List<CcdiPurchaseTransactionSupplier> newSuppliers = new ArrayList<>();
|
||||||
List<PurchaseTransactionImportFailureVO> failures = new ArrayList<>();
|
List<PurchaseTransactionImportFailureVO> failures = new ArrayList<>();
|
||||||
|
|
||||||
// 批量查询已存在的采购事项ID
|
// 批量查询已存在的采购事项ID
|
||||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的采购事项ID", excelList.size());
|
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的采购事项ID", safeMainList.size());
|
||||||
Set<String> existingIds = getExistingPurchaseIds(excelList);
|
Set<String> existingIds = getExistingPurchaseIds(safeMainList);
|
||||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "采购事项ID", existingIds.size());
|
ImportLogUtils.logBatchQueryComplete(log, taskId, "采购事项ID", existingIds.size());
|
||||||
|
|
||||||
// 用于跟踪Excel文件内已处理的采购事项ID
|
Map<String, List<MainImportRow>> mainGroupMap = indexedMainRows.stream()
|
||||||
Set<String> processedIds = new HashSet<>();
|
.filter(item -> StringUtils.isNotEmpty(item.data().getPurchaseId()))
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
item -> item.data().getPurchaseId(),
|
||||||
|
LinkedHashMap::new,
|
||||||
|
Collectors.toList()
|
||||||
|
));
|
||||||
|
Map<String, List<SupplierImportRow>> supplierGroupMap = indexedSupplierRows.stream()
|
||||||
|
.filter(item -> StringUtils.isNotEmpty(item.data().getPurchaseId()))
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
item -> item.data().getPurchaseId(),
|
||||||
|
LinkedHashMap::new,
|
||||||
|
Collectors.toList()
|
||||||
|
));
|
||||||
|
LinkedHashSet<String> purchaseIds = new LinkedHashSet<>();
|
||||||
|
purchaseIds.addAll(mainGroupMap.keySet());
|
||||||
|
purchaseIds.addAll(supplierGroupMap.keySet());
|
||||||
|
|
||||||
// 分类数据
|
for (SupplierImportRow supplierExcel : indexedSupplierRows) {
|
||||||
for (int i = 0; i < excelList.size(); i++) {
|
if (StringUtils.isEmpty(supplierExcel.data().getPurchaseId())) {
|
||||||
CcdiPurchaseTransactionExcel excel = excelList.get(i);
|
failures.add(buildFailure(
|
||||||
|
null,
|
||||||
try {
|
null,
|
||||||
// 转换为AddDTO进行验证
|
SUPPLIER_SHEET_NAME,
|
||||||
CcdiPurchaseTransactionAddDTO addDTO = new CcdiPurchaseTransactionAddDTO();
|
String.valueOf(supplierExcel.sheetRowNum()),
|
||||||
BeanUtils.copyProperties(excel, addDTO);
|
"供应商明细Sheet中的采购事项ID不能为空"
|
||||||
|
));
|
||||||
// 验证数据
|
}
|
||||||
validateTransactionData(addDTO, existingIds);
|
|
||||||
|
|
||||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
|
||||||
BeanUtils.copyProperties(excel, transaction);
|
|
||||||
|
|
||||||
if (existingIds.contains(excel.getPurchaseId())) {
|
|
||||||
// 采购事项ID已存在,直接报错
|
|
||||||
throw new RuntimeException(String.format("采购事项ID[%s]已存在,请勿重复导入", excel.getPurchaseId()));
|
|
||||||
} else if (processedIds.contains(excel.getPurchaseId())) {
|
|
||||||
// Excel文件内部重复
|
|
||||||
throw new RuntimeException(String.format("采购事项ID[%s]在导入文件中重复,已跳过此条记录", excel.getPurchaseId()));
|
|
||||||
} else {
|
|
||||||
transaction.setCreatedBy(userName);
|
|
||||||
transaction.setUpdatedBy(userName);
|
|
||||||
newRecords.add(transaction);
|
|
||||||
processedIds.add(excel.getPurchaseId()); // 标记为已处理
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (String purchaseId : purchaseIds) {
|
||||||
|
index++;
|
||||||
|
List<MainImportRow> mainRows = mainGroupMap.getOrDefault(purchaseId, List.of());
|
||||||
|
List<SupplierImportRow> supplierRows = supplierGroupMap.getOrDefault(purchaseId, List.of());
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (existingIds.contains(purchaseId)) {
|
||||||
|
throw buildValidationException(
|
||||||
|
MAIN_SHEET_NAME,
|
||||||
|
extractMainRowNums(mainRows),
|
||||||
|
String.format("采购事项ID[%s]已存在,请勿重复导入", purchaseId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (mainRows.isEmpty()) {
|
||||||
|
throw buildValidationException(
|
||||||
|
SUPPLIER_SHEET_NAME,
|
||||||
|
extractSupplierRowNums(supplierRows),
|
||||||
|
String.format("采购事项ID[%s]缺少招投标主信息", purchaseId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (mainRows.size() > 1) {
|
||||||
|
throw buildValidationException(
|
||||||
|
MAIN_SHEET_NAME,
|
||||||
|
extractMainRowNums(mainRows),
|
||||||
|
String.format("采购事项ID[%s]在招投标主信息Sheet中重复", purchaseId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainImportRow mainRow = mainRows.getFirst();
|
||||||
|
CcdiPurchaseTransactionExcel mainExcel = mainRow.data();
|
||||||
|
CcdiPurchaseTransactionAddDTO addDTO = new CcdiPurchaseTransactionAddDTO();
|
||||||
|
BeanUtils.copyProperties(mainExcel, addDTO);
|
||||||
|
|
||||||
|
validateTransactionData(addDTO, mainRow.sheetRowNum());
|
||||||
|
List<CcdiPurchaseTransactionSupplier> suppliers = buildSupplierEntities(purchaseId, supplierRows, userName);
|
||||||
|
|
||||||
|
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||||
|
BeanUtils.copyProperties(mainExcel, transaction);
|
||||||
|
fillWinnerSummary(transaction, suppliers);
|
||||||
|
transaction.setCreatedBy(userName);
|
||||||
|
transaction.setUpdatedBy(userName);
|
||||||
|
newTransactions.add(transaction);
|
||||||
|
newSuppliers.addAll(suppliers);
|
||||||
|
|
||||||
// 记录进度
|
// 记录进度
|
||||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
ImportLogUtils.logProgress(log, taskId, index, Math.max(totalCount, purchaseIds.size()),
|
||||||
newRecords.size(), failures.size());
|
newTransactions.size(), failures.size());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
PurchaseTransactionImportFailureVO failure = new PurchaseTransactionImportFailureVO();
|
MainImportRow mainRow = mainRows.isEmpty() ? null : mainRows.getFirst();
|
||||||
BeanUtils.copyProperties(excel, failure);
|
CcdiPurchaseTransactionExcel mainExcel = mainRow == null ? null : mainRow.data();
|
||||||
failure.setErrorMessage(e.getMessage());
|
FailureMeta failureMeta = resolveFailureMeta(e, mainRows, supplierRows);
|
||||||
failures.add(failure);
|
failures.add(buildFailure(
|
||||||
|
mainExcel,
|
||||||
|
purchaseId,
|
||||||
|
failureMeta.sheetName(),
|
||||||
|
failureMeta.sheetRowNum(),
|
||||||
|
e.getMessage()
|
||||||
|
));
|
||||||
|
|
||||||
// 记录验证失败日志
|
// 记录验证失败日志
|
||||||
String keyData = String.format("采购事项ID=%s, 采购类别=%s, 标的物=%s",
|
String keyData = String.format("采购事项ID=%s, 采购类别=%s, 标的物=%s",
|
||||||
excel.getPurchaseId(), excel.getPurchaseCategory(), excel.getSubjectName());
|
purchaseId,
|
||||||
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData);
|
mainExcel == null ? "" : mainExcel.getPurchaseCategory(),
|
||||||
|
mainExcel == null ? "" : mainExcel.getSubjectName());
|
||||||
|
ImportLogUtils.logValidationError(log, taskId, index, e.getMessage(), keyData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量插入新数据
|
// 批量插入新数据
|
||||||
if (!newRecords.isEmpty()) {
|
if (!newTransactions.isEmpty()) {
|
||||||
ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
|
ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
|
||||||
(newRecords.size() + 499) / 500, 500);
|
(newTransactions.size() + 499) / 500, 500);
|
||||||
saveBatch(newRecords, 500);
|
saveBatch(newTransactions, 500);
|
||||||
|
}
|
||||||
|
if (!newSuppliers.isEmpty()) {
|
||||||
|
saveSupplierBatch(newSuppliers, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存失败记录到Redis
|
// 保存失败记录到Redis
|
||||||
@@ -128,8 +203,8 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImportResult result = new ImportResult();
|
ImportResult result = new ImportResult();
|
||||||
result.setTotalCount(excelList.size());
|
result.setTotalCount(totalCount);
|
||||||
result.setSuccessCount(newRecords.size());
|
result.setSuccessCount(newTransactions.size());
|
||||||
result.setFailureCount(failures.size());
|
result.setFailureCount(failures.size());
|
||||||
|
|
||||||
// 更新最终状态
|
// 更新最终状态
|
||||||
@@ -138,8 +213,8 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
|||||||
|
|
||||||
// 记录导入完成
|
// 记录导入完成
|
||||||
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);
|
totalCount, result.getSuccessCount(), result.getFailureCount(), duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,71 +318,338 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveSupplierBatch(List<CcdiPurchaseTransactionSupplier> list, int batchSize) {
|
||||||
|
for (int i = 0; i < list.size(); i += batchSize) {
|
||||||
|
int end = Math.min(i + batchSize, list.size());
|
||||||
|
List<CcdiPurchaseTransactionSupplier> subList = list.subList(i, end);
|
||||||
|
for (CcdiPurchaseTransactionSupplier supplier : subList) {
|
||||||
|
supplierMapper.insert(supplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证采购交易数据
|
* 验证采购交易数据
|
||||||
*
|
*
|
||||||
* @param addDTO 新增DTO
|
* @param addDTO 新增DTO
|
||||||
* @param existingIds 已存在的采购事项ID集合
|
|
||||||
*/
|
*/
|
||||||
private void validateTransactionData(CcdiPurchaseTransactionAddDTO addDTO, Set<String> existingIds) {
|
private void validateTransactionData(CcdiPurchaseTransactionAddDTO addDTO, int sheetRowNum) {
|
||||||
// 验证必填字段
|
// 验证必填字段
|
||||||
if (StringUtils.isEmpty(addDTO.getPurchaseId())) {
|
if (StringUtils.isEmpty(addDTO.getPurchaseId())) {
|
||||||
throw new RuntimeException("采购事项ID不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购事项ID不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getPurchaseCategory())) {
|
if (StringUtils.isEmpty(addDTO.getPurchaseCategory())) {
|
||||||
throw new RuntimeException("采购类别不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购类别不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getSubjectName())) {
|
if (StringUtils.isEmpty(addDTO.getSubjectName())) {
|
||||||
throw new RuntimeException("标的物名称不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "标的物名称不能为空");
|
||||||
}
|
}
|
||||||
if (addDTO.getPurchaseQty() == null) {
|
if (addDTO.getPurchaseQty() == null) {
|
||||||
throw new RuntimeException("采购数量不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购数量不能为空");
|
||||||
}
|
}
|
||||||
if (addDTO.getBudgetAmount() == null) {
|
if (addDTO.getBudgetAmount() == null) {
|
||||||
throw new RuntimeException("预算金额不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "预算金额不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getPurchaseMethod())) {
|
if (StringUtils.isEmpty(addDTO.getPurchaseMethod())) {
|
||||||
throw new RuntimeException("采购方式不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购方式不能为空");
|
||||||
}
|
}
|
||||||
if (addDTO.getApplyDate() == null) {
|
if (addDTO.getApplyDate() == null) {
|
||||||
throw new RuntimeException("采购申请日期不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购申请日期不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getApplicantId())) {
|
if (StringUtils.isEmpty(addDTO.getApplicantId())) {
|
||||||
throw new RuntimeException("申请人工号不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请人工号不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getApplicantName())) {
|
if (StringUtils.isEmpty(addDTO.getApplicantName())) {
|
||||||
throw new RuntimeException("申请人姓名不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请人姓名不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getApplyDepartment())) {
|
if (StringUtils.isEmpty(addDTO.getApplyDepartment())) {
|
||||||
throw new RuntimeException("申请部门不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请部门不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证工号格式(7位数字)
|
// 验证工号格式(7位数字)
|
||||||
if (!addDTO.getApplicantId().matches("^\\d{7}$")) {
|
if (!addDTO.getApplicantId().matches("^\\d{7}$")) {
|
||||||
throw new RuntimeException("申请人工号必须为7位数字");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请人工号必须为7位数字");
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(addDTO.getPurchaseLeaderId()) && !addDTO.getPurchaseLeaderId().matches("^\\d{7}$")) {
|
if (StringUtils.isNotEmpty(addDTO.getPurchaseLeaderId()) && !addDTO.getPurchaseLeaderId().matches("^\\d{7}$")) {
|
||||||
throw new RuntimeException("采购负责人工号必须为7位数字");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购负责人工号必须为7位数字");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证金额非负
|
// 验证金额非负
|
||||||
if (addDTO.getPurchaseQty().compareTo(BigDecimal.ZERO) <= 0) {
|
if (addDTO.getPurchaseQty().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new RuntimeException("采购数量必须大于0");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购数量必须大于0");
|
||||||
}
|
}
|
||||||
if (addDTO.getBudgetAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
if (addDTO.getBudgetAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new RuntimeException("预算金额必须大于0");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "预算金额必须大于0");
|
||||||
}
|
}
|
||||||
if (addDTO.getBidAmount() != null && addDTO.getBidAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
if (addDTO.getBidAmount() != null && addDTO.getBidAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new RuntimeException("中标金额必须大于0");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "中标金额必须大于0");
|
||||||
}
|
}
|
||||||
if (addDTO.getActualAmount() != null && addDTO.getActualAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
if (addDTO.getActualAmount() != null && addDTO.getActualAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new RuntimeException("实际采购金额必须大于0");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "实际采购金额必须大于0");
|
||||||
}
|
}
|
||||||
if (addDTO.getContractAmount() != null && addDTO.getContractAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
if (addDTO.getContractAmount() != null && addDTO.getContractAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new RuntimeException("合同金额必须大于0");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "合同金额必须大于0");
|
||||||
}
|
}
|
||||||
if (addDTO.getSettlementAmount() != null && addDTO.getSettlementAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
if (addDTO.getSettlementAmount() != null && addDTO.getSettlementAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new RuntimeException("结算金额必须大于0");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "结算金额必须大于0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CcdiPurchaseTransactionSupplier> buildSupplierEntities(
|
||||||
|
String purchaseId,
|
||||||
|
List<SupplierImportRow> supplierRows,
|
||||||
|
String userName
|
||||||
|
) {
|
||||||
|
List<SupplierImportRow> normalizedRows = supplierRows == null
|
||||||
|
? List.of()
|
||||||
|
: supplierRows.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(item -> hasAnySupplierValue(item.data()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
List<Integer> winnerRowNums = new ArrayList<>();
|
||||||
|
Map<String, Integer> supplierKeyRowMap = new LinkedHashMap<>();
|
||||||
|
List<CcdiPurchaseTransactionSupplier> result = new ArrayList<>();
|
||||||
|
for (SupplierImportRow supplierImportRow : normalizedRows) {
|
||||||
|
CcdiPurchaseTransactionSupplierExcel supplierRow = supplierImportRow.data();
|
||||||
|
int isBidWinner = validateSupplierRow(supplierImportRow);
|
||||||
|
if (isBidWinner == 1) {
|
||||||
|
winnerRowNums.add(supplierImportRow.sheetRowNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
String duplicateKey = StringUtils.trimToEmpty(supplierRow.getSupplierName()) + "|"
|
||||||
|
+ StringUtils.trimToEmpty(supplierRow.getSupplierUscc());
|
||||||
|
Integer firstRowNum = supplierKeyRowMap.putIfAbsent(duplicateKey, supplierImportRow.sheetRowNum());
|
||||||
|
if (firstRowNum != null) {
|
||||||
|
throw buildValidationException(
|
||||||
|
SUPPLIER_SHEET_NAME,
|
||||||
|
List.of(firstRowNum, supplierImportRow.sheetRowNum()),
|
||||||
|
String.format("采购事项ID[%s]存在重复供应商", purchaseId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CcdiPurchaseTransactionSupplier supplier = new CcdiPurchaseTransactionSupplier();
|
||||||
|
supplier.setPurchaseId(purchaseId);
|
||||||
|
supplier.setSupplierName(StringUtils.trim(supplierRow.getSupplierName()));
|
||||||
|
supplier.setSupplierUscc(StringUtils.trimToNull(supplierRow.getSupplierUscc()));
|
||||||
|
supplier.setContactPerson(StringUtils.trimToNull(supplierRow.getContactPerson()));
|
||||||
|
supplier.setContactPhone(StringUtils.trimToNull(supplierRow.getContactPhone()));
|
||||||
|
supplier.setSupplierBankAccount(StringUtils.trimToNull(supplierRow.getSupplierBankAccount()));
|
||||||
|
supplier.setIsBidWinner(isBidWinner);
|
||||||
|
supplier.setSortOrder(supplierRow.getSortOrder() == null ? result.size() + 1 : supplierRow.getSortOrder());
|
||||||
|
supplier.setCreatedBy(userName);
|
||||||
|
supplier.setUpdatedBy(userName);
|
||||||
|
result.add(supplier);
|
||||||
|
}
|
||||||
|
if (winnerRowNums.size() > 1) {
|
||||||
|
throw buildValidationException(
|
||||||
|
SUPPLIER_SHEET_NAME,
|
||||||
|
winnerRowNums,
|
||||||
|
String.format("采购事项ID[%s]存在多条中标供应商", purchaseId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int validateSupplierRow(SupplierImportRow supplierImportRow) {
|
||||||
|
CcdiPurchaseTransactionSupplierExcel supplierRow = supplierImportRow.data();
|
||||||
|
if (StringUtils.isEmpty(supplierRow.getSupplierName())) {
|
||||||
|
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商名称不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.length(supplierRow.getSupplierName()) > 200) {
|
||||||
|
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商名称长度不能超过200个字符");
|
||||||
|
}
|
||||||
|
if (StringUtils.length(supplierRow.getContactPerson()) > 50) {
|
||||||
|
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商联系人长度不能超过50个字符");
|
||||||
|
}
|
||||||
|
if (StringUtils.length(supplierRow.getSupplierBankAccount()) > 50) {
|
||||||
|
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商银行账户长度不能超过50个字符");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(supplierRow.getContactPhone())
|
||||||
|
&& !supplierRow.getContactPhone().matches("^1[3-9]\\d{9}$|^0\\d{2,3}-?\\d{7,8}$")) {
|
||||||
|
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商联系电话格式不正确");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(supplierRow.getSupplierUscc())
|
||||||
|
&& !supplierRow.getSupplierUscc().matches("^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$")) {
|
||||||
|
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商统一信用代码格式不正确");
|
||||||
|
}
|
||||||
|
return parseIsBidWinner(supplierRow.getIsBidWinner(), supplierImportRow.sheetRowNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAnySupplierValue(CcdiPurchaseTransactionSupplierExcel supplierRow) {
|
||||||
|
return StringUtils.isNotEmpty(supplierRow.getPurchaseId())
|
||||||
|
|| StringUtils.isNotEmpty(supplierRow.getSupplierName())
|
||||||
|
|| StringUtils.isNotEmpty(supplierRow.getSupplierUscc())
|
||||||
|
|| StringUtils.isNotEmpty(supplierRow.getContactPerson())
|
||||||
|
|| StringUtils.isNotEmpty(supplierRow.getContactPhone())
|
||||||
|
|| StringUtils.isNotEmpty(supplierRow.getSupplierBankAccount())
|
||||||
|
|| StringUtils.isNotEmpty(supplierRow.getIsBidWinner())
|
||||||
|
|| supplierRow.getSortOrder() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseIsBidWinner(String rawValue, Integer sheetRowNum) {
|
||||||
|
if (StringUtils.isEmpty(rawValue)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
String normalized = StringUtils.trim(rawValue);
|
||||||
|
if ("1".equals(normalized) || "是".equals(normalized) || "Y".equalsIgnoreCase(normalized)
|
||||||
|
|| "TRUE".equalsIgnoreCase(normalized)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ("0".equals(normalized) || "否".equals(normalized) || "N".equalsIgnoreCase(normalized)
|
||||||
|
|| "FALSE".equalsIgnoreCase(normalized)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
throw buildValidationException(
|
||||||
|
SUPPLIER_SHEET_NAME,
|
||||||
|
sheetRowNum == null ? List.of() : List.of(sheetRowNum),
|
||||||
|
"是否中标仅支持填写“是/否”或“1/0”"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillWinnerSummary(
|
||||||
|
CcdiPurchaseTransaction transaction,
|
||||||
|
List<CcdiPurchaseTransactionSupplier> supplierList
|
||||||
|
) {
|
||||||
|
CcdiPurchaseTransactionSupplier winner = supplierList.stream()
|
||||||
|
.filter(item -> Objects.equals(item.getIsBidWinner(), 1))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (winner == null) {
|
||||||
|
transaction.setSupplierName(null);
|
||||||
|
transaction.setSupplierUscc(null);
|
||||||
|
transaction.setContactPerson(null);
|
||||||
|
transaction.setContactPhone(null);
|
||||||
|
transaction.setSupplierBankAccount(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
transaction.setSupplierName(winner.getSupplierName());
|
||||||
|
transaction.setSupplierUscc(winner.getSupplierUscc());
|
||||||
|
transaction.setContactPerson(winner.getContactPerson());
|
||||||
|
transaction.setContactPhone(winner.getContactPhone());
|
||||||
|
transaction.setSupplierBankAccount(winner.getSupplierBankAccount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PurchaseTransactionImportFailureVO buildFailure(
|
||||||
|
CcdiPurchaseTransactionExcel mainExcel,
|
||||||
|
String purchaseId,
|
||||||
|
String sheetName,
|
||||||
|
String sheetRowNum,
|
||||||
|
String errorMessage
|
||||||
|
) {
|
||||||
|
PurchaseTransactionImportFailureVO failure = new PurchaseTransactionImportFailureVO();
|
||||||
|
if (mainExcel != null) {
|
||||||
|
BeanUtils.copyProperties(mainExcel, failure);
|
||||||
|
}
|
||||||
|
failure.setSheetName(sheetName);
|
||||||
|
failure.setSheetRowNum(sheetRowNum);
|
||||||
|
if (StringUtils.isNotEmpty(purchaseId)) {
|
||||||
|
failure.setPurchaseId(purchaseId);
|
||||||
|
}
|
||||||
|
failure.setErrorMessage(errorMessage);
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countImportUnits(
|
||||||
|
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||||
|
) {
|
||||||
|
LinkedHashSet<String> purchaseIds = new LinkedHashSet<>();
|
||||||
|
purchaseIds.addAll(
|
||||||
|
mainExcelList.stream()
|
||||||
|
.map(CcdiPurchaseTransactionExcel::getPurchaseId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||||
|
);
|
||||||
|
purchaseIds.addAll(
|
||||||
|
supplierExcelList.stream()
|
||||||
|
.map(CcdiPurchaseTransactionSupplierExcel::getPurchaseId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||||
|
);
|
||||||
|
return purchaseIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MainImportRow> buildMainImportRows(List<CcdiPurchaseTransactionExcel> mainExcelList) {
|
||||||
|
List<MainImportRow> rows = new ArrayList<>();
|
||||||
|
for (int i = 0; i < mainExcelList.size(); i++) {
|
||||||
|
rows.add(new MainImportRow(mainExcelList.get(i), i + EXCEL_DATA_START_ROW));
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SupplierImportRow> buildSupplierImportRows(List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList) {
|
||||||
|
List<SupplierImportRow> rows = new ArrayList<>();
|
||||||
|
for (int i = 0; i < supplierExcelList.size(); i++) {
|
||||||
|
rows.add(new SupplierImportRow(supplierExcelList.get(i), i + EXCEL_DATA_START_ROW));
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> extractMainRowNums(List<MainImportRow> rows) {
|
||||||
|
return rows.stream().map(MainImportRow::sheetRowNum).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> extractSupplierRowNums(List<SupplierImportRow> rows) {
|
||||||
|
return rows.stream().map(SupplierImportRow::sheetRowNum).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImportValidationException buildValidationException(String sheetName, List<Integer> rowNums, String message) {
|
||||||
|
return new ImportValidationException(sheetName, formatSheetRowNum(rowNums), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FailureMeta resolveFailureMeta(
|
||||||
|
Exception exception,
|
||||||
|
List<MainImportRow> mainRows,
|
||||||
|
List<SupplierImportRow> supplierRows
|
||||||
|
) {
|
||||||
|
if (exception instanceof ImportValidationException validationException) {
|
||||||
|
return new FailureMeta(validationException.getSheetName(), validationException.getSheetRowNum());
|
||||||
|
}
|
||||||
|
if (!mainRows.isEmpty()) {
|
||||||
|
return new FailureMeta(MAIN_SHEET_NAME, formatSheetRowNum(extractMainRowNums(mainRows)));
|
||||||
|
}
|
||||||
|
if (!supplierRows.isEmpty()) {
|
||||||
|
return new FailureMeta(SUPPLIER_SHEET_NAME, formatSheetRowNum(extractSupplierRowNums(supplierRows)));
|
||||||
|
}
|
||||||
|
return new FailureMeta("", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatSheetRowNum(List<Integer> rowNums) {
|
||||||
|
if (rowNums == null || rowNums.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return rowNums.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.sorted()
|
||||||
|
.map(String::valueOf)
|
||||||
|
.collect(Collectors.joining("、"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private record MainImportRow(CcdiPurchaseTransactionExcel data, int sheetRowNum) {}
|
||||||
|
|
||||||
|
private record SupplierImportRow(CcdiPurchaseTransactionSupplierExcel data, int sheetRowNum) {}
|
||||||
|
|
||||||
|
private record FailureMeta(String sheetName, String sheetRowNum) {}
|
||||||
|
|
||||||
|
private static class ImportValidationException extends RuntimeException {
|
||||||
|
|
||||||
|
private final String sheetName;
|
||||||
|
private final String sheetRowNum;
|
||||||
|
|
||||||
|
private ImportValidationException(String sheetName, String sheetRowNum, String message) {
|
||||||
|
super(message);
|
||||||
|
this.sheetName = sheetName;
|
||||||
|
this.sheetRowNum = sheetRowNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSheetName() {
|
||||||
|
return sheetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSheetRowNum() {
|
||||||
|
return sheetRowNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,34 @@ package com.ruoyi.info.collection.service.impl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.info.collection.domain.CcdiPurchaseTransaction;
|
import com.ruoyi.info.collection.domain.CcdiPurchaseTransaction;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiPurchaseTransactionSupplier;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionAddDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionQueryDTO;
|
||||||
|
import com.ruoyi.info.collection.domain.dto.CcdiPurchaseTransactionSupplierDTO;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiPurchaseTransactionExcel;
|
||||||
|
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.mapper.CcdiPurchaseTransactionMapper;
|
import com.ruoyi.info.collection.mapper.CcdiPurchaseTransactionMapper;
|
||||||
|
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.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;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -39,6 +49,9 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
@Resource
|
@Resource
|
||||||
private ICcdiPurchaseTransactionImportService transactionImportService;
|
private ICcdiPurchaseTransactionImportService transactionImportService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiPurchaseTransactionSupplierMapper supplierMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@@ -93,7 +106,14 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public CcdiPurchaseTransactionVO selectTransactionById(String purchaseId) {
|
public CcdiPurchaseTransactionVO selectTransactionById(String purchaseId) {
|
||||||
return transactionMapper.selectTransactionById(purchaseId);
|
CcdiPurchaseTransactionVO detail = transactionMapper.selectTransactionById(purchaseId);
|
||||||
|
if (detail == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<CcdiPurchaseTransactionSupplierVO> supplierList = selectSupplierListByPurchaseId(purchaseId);
|
||||||
|
detail.setSupplierList(supplierList);
|
||||||
|
detail.setSupplierCount(supplierList.size());
|
||||||
|
return detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,9 +130,12 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
throw new RuntimeException("该采购事项ID已存在");
|
throw new RuntimeException("该采购事项ID已存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<CcdiPurchaseTransactionSupplier> supplierList = buildSupplierEntities(addDTO.getPurchaseId(), addDTO.getSupplierList());
|
||||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||||
BeanUtils.copyProperties(addDTO, transaction);
|
BeanUtils.copyProperties(addDTO, transaction);
|
||||||
|
fillWinnerSummary(transaction, supplierList);
|
||||||
int result = transactionMapper.insert(transaction);
|
int result = transactionMapper.insert(transaction);
|
||||||
|
saveSuppliers(supplierList);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -126,9 +149,13 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int updateTransaction(CcdiPurchaseTransactionEditDTO editDTO) {
|
public int updateTransaction(CcdiPurchaseTransactionEditDTO editDTO) {
|
||||||
|
List<CcdiPurchaseTransactionSupplier> supplierList = buildSupplierEntities(editDTO.getPurchaseId(), editDTO.getSupplierList());
|
||||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||||
BeanUtils.copyProperties(editDTO, transaction);
|
BeanUtils.copyProperties(editDTO, transaction);
|
||||||
|
fillWinnerSummary(transaction, supplierList);
|
||||||
int result = transactionMapper.updateById(transaction);
|
int result = transactionMapper.updateById(transaction);
|
||||||
|
transactionMapper.deleteSuppliersByPurchaseIds(List.of(editDTO.getPurchaseId()));
|
||||||
|
saveSuppliers(supplierList);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -142,19 +169,24 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int deleteTransactionByIds(String[] purchaseIds) {
|
public int deleteTransactionByIds(String[] purchaseIds) {
|
||||||
|
transactionMapper.deleteSuppliersByPurchaseIds(List.of(purchaseIds));
|
||||||
return transactionMapper.deleteBatchIds(java.util.List.of(purchaseIds));
|
return transactionMapper.deleteBatchIds(java.util.List.of(purchaseIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入采购交易数据(异步)
|
* 导入采购交易数据(异步)
|
||||||
*
|
*
|
||||||
* @param excelList Excel实体列表
|
* @param mainExcelList 主信息Excel实体列表
|
||||||
|
* @param supplierExcelList 供应商明细Excel实体列表
|
||||||
* @return 任务ID
|
* @return 任务ID
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public String importTransaction(java.util.List<CcdiPurchaseTransactionExcel> excelList) {
|
public String importTransaction(
|
||||||
if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
|
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||||
|
) {
|
||||||
|
if ((mainExcelList == null || mainExcelList.isEmpty()) && (supplierExcelList == null || supplierExcelList.isEmpty())) {
|
||||||
throw new RuntimeException("至少需要一条数据");
|
throw new RuntimeException("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +202,7 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
Map<String, Object> statusData = new HashMap<>();
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
statusData.put("taskId", taskId);
|
statusData.put("taskId", taskId);
|
||||||
statusData.put("status", "PROCESSING");
|
statusData.put("status", "PROCESSING");
|
||||||
statusData.put("totalCount", excelList.size());
|
statusData.put("totalCount", countImportUnits(mainExcelList, supplierExcelList));
|
||||||
statusData.put("successCount", 0);
|
statusData.put("successCount", 0);
|
||||||
statusData.put("failureCount", 0);
|
statusData.put("failureCount", 0);
|
||||||
statusData.put("progress", 0);
|
statusData.put("progress", 0);
|
||||||
@@ -181,8 +213,134 @@ public class CcdiPurchaseTransactionServiceImpl implements ICcdiPurchaseTransact
|
|||||||
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
||||||
|
|
||||||
// 调用异步导入服务
|
// 调用异步导入服务
|
||||||
transactionImportService.importTransactionAsync(excelList, taskId, userName);
|
transactionImportService.importTransactionAsync(mainExcelList, supplierExcelList, taskId, userName);
|
||||||
|
|
||||||
return taskId;
|
return taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int countImportUnits(
|
||||||
|
List<CcdiPurchaseTransactionExcel> mainExcelList,
|
||||||
|
List<CcdiPurchaseTransactionSupplierExcel> supplierExcelList
|
||||||
|
) {
|
||||||
|
LinkedHashSet<String> purchaseIds = new LinkedHashSet<>();
|
||||||
|
if (mainExcelList != null) {
|
||||||
|
purchaseIds.addAll(
|
||||||
|
mainExcelList.stream()
|
||||||
|
.map(CcdiPurchaseTransactionExcel::getPurchaseId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (supplierExcelList != null) {
|
||||||
|
purchaseIds.addAll(
|
||||||
|
supplierExcelList.stream()
|
||||||
|
.map(CcdiPurchaseTransactionSupplierExcel::getPurchaseId)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return purchaseIds.isEmpty() ? 0 : purchaseIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CcdiPurchaseTransactionSupplier> buildSupplierEntities(
|
||||||
|
String purchaseId,
|
||||||
|
List<CcdiPurchaseTransactionSupplierDTO> supplierDTOList
|
||||||
|
) {
|
||||||
|
List<CcdiPurchaseTransactionSupplierDTO> normalizedList = normalizeSupplierList(supplierDTOList);
|
||||||
|
validateSupplierList(normalizedList);
|
||||||
|
|
||||||
|
List<CcdiPurchaseTransactionSupplier> supplierList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < normalizedList.size(); i++) {
|
||||||
|
CcdiPurchaseTransactionSupplierDTO dto = normalizedList.get(i);
|
||||||
|
CcdiPurchaseTransactionSupplier supplier = new CcdiPurchaseTransactionSupplier();
|
||||||
|
BeanUtils.copyProperties(dto, supplier);
|
||||||
|
supplier.setPurchaseId(purchaseId);
|
||||||
|
supplier.setIsBidWinner(Objects.equals(dto.getIsBidWinner(), 1) ? 1 : 0);
|
||||||
|
supplier.setSortOrder(dto.getSortOrder() == null ? i + 1 : dto.getSortOrder());
|
||||||
|
supplierList.add(supplier);
|
||||||
|
}
|
||||||
|
return supplierList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CcdiPurchaseTransactionSupplierDTO> normalizeSupplierList(
|
||||||
|
List<CcdiPurchaseTransactionSupplierDTO> supplierDTOList
|
||||||
|
) {
|
||||||
|
if (supplierDTOList == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return supplierDTOList.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(this::hasAnySupplierValue)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAnySupplierValue(CcdiPurchaseTransactionSupplierDTO supplierDTO) {
|
||||||
|
return StringUtils.isNotEmpty(supplierDTO.getSupplierName())
|
||||||
|
|| StringUtils.isNotEmpty(supplierDTO.getSupplierUscc())
|
||||||
|
|| StringUtils.isNotEmpty(supplierDTO.getContactPerson())
|
||||||
|
|| StringUtils.isNotEmpty(supplierDTO.getContactPhone())
|
||||||
|
|| StringUtils.isNotEmpty(supplierDTO.getSupplierBankAccount())
|
||||||
|
|| supplierDTO.getIsBidWinner() != null
|
||||||
|
|| supplierDTO.getSortOrder() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateSupplierList(List<CcdiPurchaseTransactionSupplierDTO> supplierList) {
|
||||||
|
long winnerCount = supplierList.stream()
|
||||||
|
.filter(item -> Objects.equals(item.getIsBidWinner(), 1))
|
||||||
|
.count();
|
||||||
|
if (winnerCount > 1) {
|
||||||
|
throw new RuntimeException("同一招投标事项仅允许维护一条中标供应商");
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedHashSet<String> duplicateKeys = new LinkedHashSet<>();
|
||||||
|
for (CcdiPurchaseTransactionSupplierDTO supplier : supplierList) {
|
||||||
|
String duplicateKey = StringUtils.trimToEmpty(supplier.getSupplierName()) + "|"
|
||||||
|
+ StringUtils.trimToEmpty(supplier.getSupplierUscc());
|
||||||
|
if (!duplicateKeys.add(duplicateKey)) {
|
||||||
|
throw new RuntimeException("同一招投标事项存在重复供应商,请检查供应商名称和统一信用代码");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillWinnerSummary(
|
||||||
|
CcdiPurchaseTransaction transaction,
|
||||||
|
List<CcdiPurchaseTransactionSupplier> supplierList
|
||||||
|
) {
|
||||||
|
CcdiPurchaseTransactionSupplier winnerSupplier = supplierList.stream()
|
||||||
|
.filter(item -> Objects.equals(item.getIsBidWinner(), 1))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (winnerSupplier == null) {
|
||||||
|
transaction.setSupplierName(null);
|
||||||
|
transaction.setSupplierUscc(null);
|
||||||
|
transaction.setContactPerson(null);
|
||||||
|
transaction.setContactPhone(null);
|
||||||
|
transaction.setSupplierBankAccount(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
transaction.setSupplierName(winnerSupplier.getSupplierName());
|
||||||
|
transaction.setSupplierUscc(winnerSupplier.getSupplierUscc());
|
||||||
|
transaction.setContactPerson(winnerSupplier.getContactPerson());
|
||||||
|
transaction.setContactPhone(winnerSupplier.getContactPhone());
|
||||||
|
transaction.setSupplierBankAccount(winnerSupplier.getSupplierBankAccount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveSuppliers(List<CcdiPurchaseTransactionSupplier> supplierList) {
|
||||||
|
for (CcdiPurchaseTransactionSupplier supplier : supplierList) {
|
||||||
|
supplierMapper.insert(supplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CcdiPurchaseTransactionSupplierVO> selectSupplierListByPurchaseId(String purchaseId) {
|
||||||
|
return supplierMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<CcdiPurchaseTransactionSupplier>()
|
||||||
|
.eq(CcdiPurchaseTransactionSupplier::getPurchaseId, purchaseId)
|
||||||
|
.orderByAsc(CcdiPurchaseTransactionSupplier::getSortOrder)
|
||||||
|
.orderByAsc(CcdiPurchaseTransactionSupplier::getId)
|
||||||
|
).stream().map(entity -> {
|
||||||
|
CcdiPurchaseTransactionSupplierVO vo = new CcdiPurchaseTransactionSupplierVO();
|
||||||
|
BeanUtils.copyProperties(entity, vo);
|
||||||
|
return vo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ 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.CcdiBaseStaff;
|
|
||||||
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.dto.CcdiStaffEnterpriseRelationAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
|
||||||
import com.ruoyi.info.collection.domain.excel.CcdiStaffEnterpriseRelationExcel;
|
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.mapper.CcdiBaseStaffMapper;
|
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.utils.ImportLogUtils;
|
import com.ruoyi.info.collection.utils.ImportLogUtils;
|
||||||
@@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工实体关系信息异步导入服务层处理
|
* 员工亲属实体关联异步导入服务层处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2026-02-09
|
* @date 2026-02-09
|
||||||
@@ -47,7 +47,7 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CcdiBaseStaffMapper baseStaffMapper;
|
private CcdiStaffFmyRelationMapper familyRelationMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Async
|
@Async
|
||||||
@@ -56,37 +56,48 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// 记录导入开始
|
// 记录导入开始
|
||||||
ImportLogUtils.logImportStart(log, taskId, "员工实体关系", excelList.size(), userName);
|
ImportLogUtils.logImportStart(log, taskId, "员工亲属实体关联", excelList.size(), userName);
|
||||||
|
|
||||||
List<CcdiStaffEnterpriseRelation> newRecords = new ArrayList<>();
|
List<CcdiStaffEnterpriseRelation> newRecords = new ArrayList<>();
|
||||||
List<StaffEnterpriseRelationImportFailureVO> failures = new ArrayList<>();
|
List<StaffEnterpriseRelationImportFailureVO> failures = new ArrayList<>();
|
||||||
|
|
||||||
// 批量验证员工身份证号是否存在
|
|
||||||
Set<String> excelPersonIds = excelList.stream()
|
Set<String> excelPersonIds = excelList.stream()
|
||||||
.map(CcdiStaffEnterpriseRelationExcel::getPersonId)
|
.map(CcdiStaffEnterpriseRelationExcel::getPersonId)
|
||||||
.filter(StringUtils::isNotEmpty)
|
.filter(StringUtils::isNotEmpty)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
Set<String> existingPersonIds = new HashSet<>();
|
Map<String, CcdiStaffFmyRelation> validFamilies = new HashMap<>();
|
||||||
|
Set<String> knownFamilyCertNos = new HashSet<>();
|
||||||
|
Map<String, String> familyNameMap = new HashMap<>();
|
||||||
if (!excelPersonIds.isEmpty()) {
|
if (!excelPersonIds.isEmpty()) {
|
||||||
ImportLogUtils.logBatchQueryStart(log, taskId, "员工身份证号", excelPersonIds.size());
|
ImportLogUtils.logBatchQueryStart(log, taskId, "员工亲属关系", excelPersonIds.size());
|
||||||
|
|
||||||
LambdaQueryWrapper<CcdiBaseStaff> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<CcdiStaffFmyRelation> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.select(CcdiBaseStaff::getIdCard)
|
wrapper.select(
|
||||||
.in(CcdiBaseStaff::getIdCard, excelPersonIds);
|
CcdiStaffFmyRelation::getRelationCertNo,
|
||||||
|
CcdiStaffFmyRelation::getRelationName,
|
||||||
|
CcdiStaffFmyRelation::getPersonId,
|
||||||
|
CcdiStaffFmyRelation::getStatus,
|
||||||
|
CcdiStaffFmyRelation::getIsEmpFamily
|
||||||
|
)
|
||||||
|
.in(CcdiStaffFmyRelation::getRelationCertNo, excelPersonIds);
|
||||||
|
|
||||||
List<CcdiBaseStaff> existingStaff = baseStaffMapper.selectList(wrapper);
|
List<CcdiStaffFmyRelation> familyRelations = familyRelationMapper.selectList(wrapper);
|
||||||
existingPersonIds = existingStaff.stream()
|
for (CcdiStaffFmyRelation familyRelation : familyRelations) {
|
||||||
.map(CcdiBaseStaff::getIdCard)
|
knownFamilyCertNos.add(familyRelation.getRelationCertNo());
|
||||||
.collect(Collectors.toSet());
|
familyNameMap.putIfAbsent(familyRelation.getRelationCertNo(), familyRelation.getRelationName());
|
||||||
|
if (Boolean.TRUE.equals(familyRelation.getIsEmpFamily()) && Integer.valueOf(1).equals(familyRelation.getStatus())) {
|
||||||
|
validFamilies.putIfAbsent(familyRelation.getRelationCertNo(), familyRelation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工身份证号", existingPersonIds.size());
|
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工亲属关系", familyRelations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量查询已存在的person_id + social_credit_code组合
|
// 批量查询已存在的person_id + social_credit_code组合
|
||||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的员工企业关系组合", excelList.size());
|
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的员工亲属实体关联组合", excelList.size());
|
||||||
Set<String> existingCombinations = getExistingCombinations(excelList);
|
Set<String> existingCombinations = getExistingCombinations(excelList);
|
||||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工企业关系组合", existingCombinations.size());
|
ImportLogUtils.logBatchQueryComplete(log, taskId, "员工亲属实体关联组合", existingCombinations.size());
|
||||||
|
|
||||||
// 用于跟踪Excel文件内已处理的组合
|
// 用于跟踪Excel文件内已处理的组合
|
||||||
Set<String> processedCombinations = new HashSet<>();
|
Set<String> processedCombinations = new HashSet<>();
|
||||||
@@ -103,41 +114,18 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
// 验证数据
|
// 验证数据
|
||||||
validateRelationData(addDTO);
|
validateRelationData(addDTO);
|
||||||
|
|
||||||
// 身份证号存在性检查(在基本验证之后)
|
CcdiStaffFmyRelation familyRelation = validFamilies.get(excel.getPersonId());
|
||||||
if (!existingPersonIds.contains(excel.getPersonId())) {
|
CcdiStaffEnterpriseRelation relation = validateAndBuildEntity(
|
||||||
throw new RuntimeException(String.format(
|
excel,
|
||||||
"第%d行: 身份证号[%s]不存在于员工信息表中,请先添加员工信息",
|
familyRelation,
|
||||||
i + 1, excel.getPersonId()));
|
knownFamilyCertNos,
|
||||||
}
|
existingCombinations,
|
||||||
|
processedCombinations,
|
||||||
String combination = excel.getPersonId() + "|" + excel.getSocialCreditCode();
|
userName
|
||||||
|
);
|
||||||
CcdiStaffEnterpriseRelation relation = new CcdiStaffEnterpriseRelation();
|
|
||||||
BeanUtils.copyProperties(excel, relation);
|
|
||||||
|
|
||||||
if (existingCombinations.contains(combination)) {
|
|
||||||
// 组合已存在,直接报错
|
|
||||||
throw new RuntimeException(String.format("身份证号[%s]和统一社会信用代码[%s]的组合已存在,请勿重复导入",
|
|
||||||
excel.getPersonId(), excel.getSocialCreditCode()));
|
|
||||||
} else if (processedCombinations.contains(combination)) {
|
|
||||||
// Excel文件内部重复
|
|
||||||
throw new RuntimeException(String.format("身份证号[%s]和统一社会信用代码[%s]的组合在导入文件中重复,已跳过此条记录",
|
|
||||||
excel.getPersonId(), excel.getSocialCreditCode()));
|
|
||||||
} else {
|
|
||||||
relation.setCreatedBy(userName);
|
|
||||||
relation.setUpdatedBy(userName);
|
|
||||||
|
|
||||||
// 设置默认值
|
|
||||||
relation.setStatus(1);
|
|
||||||
relation.setIsEmployee(0);
|
|
||||||
relation.setIsEmpFamily(1);
|
|
||||||
relation.setIsCustomer(0);
|
|
||||||
relation.setIsCustFamily(0);
|
|
||||||
relation.setDataSource("IMPORT");
|
|
||||||
|
|
||||||
newRecords.add(relation);
|
newRecords.add(relation);
|
||||||
processedCombinations.add(combination); // 标记为已处理
|
processedCombinations.add(excel.getPersonId() + "|" + excel.getSocialCreditCode());
|
||||||
}
|
|
||||||
|
|
||||||
// 记录进度
|
// 记录进度
|
||||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
||||||
@@ -146,11 +134,12 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
StaffEnterpriseRelationImportFailureVO failure = new StaffEnterpriseRelationImportFailureVO();
|
StaffEnterpriseRelationImportFailureVO failure = new StaffEnterpriseRelationImportFailureVO();
|
||||||
BeanUtils.copyProperties(excel, failure);
|
BeanUtils.copyProperties(excel, failure);
|
||||||
|
failure.setRelationName(familyNameMap.get(excel.getPersonId()));
|
||||||
failure.setErrorMessage(e.getMessage());
|
failure.setErrorMessage(e.getMessage());
|
||||||
failures.add(failure);
|
failures.add(failure);
|
||||||
|
|
||||||
// 记录验证失败日志
|
// 记录验证失败日志
|
||||||
String keyData = String.format("身份证号=%s, 统一社会信用代码=%s, 企业名称=%s",
|
String keyData = String.format("亲属身份证号=%s, 统一社会信用代码=%s, 企业名称=%s",
|
||||||
excel.getPersonId(), excel.getSocialCreditCode(), excel.getEnterpriseName());
|
excel.getPersonId(), excel.getSocialCreditCode(), excel.getEnterpriseName());
|
||||||
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData);
|
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData);
|
||||||
}
|
}
|
||||||
@@ -185,7 +174,7 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
|
|
||||||
// 记录导入完成
|
// 记录导入完成
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,9 +240,9 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
statusData.put("endTime", System.currentTimeMillis());
|
statusData.put("endTime", System.currentTimeMillis());
|
||||||
|
|
||||||
if ("SUCCESS".equals(status)) {
|
if ("SUCCESS".equals(status)) {
|
||||||
statusData.put("message", "全部成功!共导入" + result.getTotalCount() + "条数据");
|
statusData.put("message", "员工亲属实体关联导入全部成功!共导入" + result.getTotalCount() + "条数据");
|
||||||
} else {
|
} else {
|
||||||
statusData.put("message", "成功" + result.getSuccessCount() + "条,失败" + result.getFailureCount() + "条");
|
statusData.put("message", "员工亲属实体关联导入成功" + result.getSuccessCount() + "条,失败" + result.getFailureCount() + "条");
|
||||||
}
|
}
|
||||||
|
|
||||||
redisTemplate.opsForHash().putAll(key, statusData);
|
redisTemplate.opsForHash().putAll(key, statusData);
|
||||||
@@ -297,14 +286,14 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证员工实体关系数据
|
* 验证员工亲属实体关联基础数据
|
||||||
*
|
*
|
||||||
* @param addDTO 新增DTO
|
* @param addDTO 新增DTO
|
||||||
*/
|
*/
|
||||||
private void validateRelationData(CcdiStaffEnterpriseRelationAddDTO addDTO) {
|
private void validateRelationData(CcdiStaffEnterpriseRelationAddDTO addDTO) {
|
||||||
// 验证必填字段
|
// 验证必填字段
|
||||||
if (StringUtils.isEmpty(addDTO.getPersonId())) {
|
if (StringUtils.isEmpty(addDTO.getPersonId())) {
|
||||||
throw new RuntimeException("身份证号不能为空");
|
throw new RuntimeException("亲属身份证号不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getSocialCreditCode())) {
|
if (StringUtils.isEmpty(addDTO.getSocialCreditCode())) {
|
||||||
throw new RuntimeException("统一社会信用代码不能为空");
|
throw new RuntimeException("统一社会信用代码不能为空");
|
||||||
@@ -313,9 +302,9 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
throw new RuntimeException("企业名称不能为空");
|
throw new RuntimeException("企业名称不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证身份证号格式(18位)
|
// 验证亲属身份证号格式(18位)
|
||||||
if (!addDTO.getPersonId().matches("^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$")) {
|
if (!addDTO.getPersonId().matches("^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$")) {
|
||||||
throw new RuntimeException("身份证号格式不正确,必须为18位有效身份证号");
|
throw new RuntimeException("亲属身份证号格式不正确,必须为18位有效身份证号");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证统一社会信用代码格式(18位)
|
// 验证统一社会信用代码格式(18位)
|
||||||
@@ -331,4 +320,38 @@ public class CcdiStaffEnterpriseRelationImportServiceImpl implements ICcdiStaffE
|
|||||||
throw new RuntimeException("企业名称长度不能超过200个字符");
|
throw new RuntimeException("企业名称长度不能超过200个字符");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CcdiStaffEnterpriseRelation validateAndBuildEntity(CcdiStaffEnterpriseRelationExcel excel,
|
||||||
|
CcdiStaffFmyRelation familyRelation,
|
||||||
|
Set<String> knownFamilyCertNos,
|
||||||
|
Set<String> existingCombinations,
|
||||||
|
Set<String> processedCombinations,
|
||||||
|
String userName) {
|
||||||
|
String combination = excel.getPersonId() + "|" + excel.getSocialCreditCode();
|
||||||
|
|
||||||
|
if (familyRelation == null) {
|
||||||
|
if (knownFamilyCertNos.contains(excel.getPersonId())) {
|
||||||
|
throw new RuntimeException("亲属身份证号[" + excel.getPersonId() + "]不是有效员工亲属,请先维护有效的员工亲属关系");
|
||||||
|
}
|
||||||
|
throw new RuntimeException("亲属身份证号[" + excel.getPersonId() + "]不存在,请先维护员工亲属关系");
|
||||||
|
}
|
||||||
|
if (existingCombinations.contains(combination)) {
|
||||||
|
throw new RuntimeException("亲属身份证号[" + excel.getPersonId() + "]和统一社会信用代码[" + excel.getSocialCreditCode() + "]的组合已存在,请勿重复导入");
|
||||||
|
}
|
||||||
|
if (processedCombinations.contains(combination)) {
|
||||||
|
throw new RuntimeException("亲属身份证号[" + excel.getPersonId() + "]和统一社会信用代码[" + excel.getSocialCreditCode() + "]的组合在导入文件中重复,已跳过此条记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
CcdiStaffEnterpriseRelation relation = new CcdiStaffEnterpriseRelation();
|
||||||
|
BeanUtils.copyProperties(excel, relation);
|
||||||
|
relation.setCreatedBy(userName);
|
||||||
|
relation.setUpdatedBy(userName);
|
||||||
|
relation.setStatus(1);
|
||||||
|
relation.setIsEmployee(0);
|
||||||
|
relation.setIsEmpFamily(1);
|
||||||
|
relation.setIsCustomer(0);
|
||||||
|
relation.setIsCustFamily(0);
|
||||||
|
relation.setDataSource("IMPORT");
|
||||||
|
return relation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ package com.ruoyi.info.collection.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
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.CcdiStaffEnterpriseRelation;
|
import com.ruoyi.info.collection.domain.CcdiStaffEnterpriseRelation;
|
||||||
|
import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationAddDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffEnterpriseRelationQueryDTO;
|
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.CcdiStaffEnterpriseRelationVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO;
|
||||||
|
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;
|
||||||
@@ -37,6 +40,9 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
|
|||||||
@Resource
|
@Resource
|
||||||
private CcdiStaffEnterpriseRelationMapper relationMapper;
|
private CcdiStaffEnterpriseRelationMapper relationMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiStaffFmyRelationMapper familyRelationMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ICcdiStaffEnterpriseRelationImportService relationImportService;
|
private ICcdiStaffEnterpriseRelationImportService relationImportService;
|
||||||
|
|
||||||
@@ -86,6 +92,11 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
|
|||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.util.List<CcdiStaffEnterpriseRelationOptionVO> selectFamilyOptions(String query) {
|
||||||
|
return relationMapper.selectFamilyOptions(query);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工实体关系详情
|
* 查询员工实体关系详情
|
||||||
*
|
*
|
||||||
@@ -106,16 +117,15 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int insertRelation(CcdiStaffEnterpriseRelationAddDTO addDTO) {
|
public int insertRelation(CcdiStaffEnterpriseRelationAddDTO addDTO) {
|
||||||
// 检查身份证号+统一社会信用代码唯一性
|
validateEffectiveFamily(addDTO.getPersonId());
|
||||||
|
|
||||||
if (relationMapper.existsByPersonIdAndSocialCreditCode(addDTO.getPersonId(), addDTO.getSocialCreditCode())) {
|
if (relationMapper.existsByPersonIdAndSocialCreditCode(addDTO.getPersonId(), addDTO.getSocialCreditCode())) {
|
||||||
throw new RuntimeException("该身份证号和统一社会信用代码组合已存在");
|
throw new RuntimeException("该亲属身份证号和统一社会信用代码组合已存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
CcdiStaffEnterpriseRelation relation = new CcdiStaffEnterpriseRelation();
|
CcdiStaffEnterpriseRelation relation = new CcdiStaffEnterpriseRelation();
|
||||||
BeanUtils.copyProperties(addDTO, relation);
|
BeanUtils.copyProperties(addDTO, relation);
|
||||||
|
|
||||||
// 设置默认值
|
|
||||||
// 新增时强制设置状态为有效
|
|
||||||
relation.setStatus(1);
|
relation.setStatus(1);
|
||||||
|
|
||||||
if (relation.getIsEmployee() == null) {
|
if (relation.getIsEmployee() == null) {
|
||||||
@@ -159,7 +169,7 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
|
|||||||
updateWrapper.set(editDTO.getRemark() != null, CcdiStaffEnterpriseRelation::getRemark, editDTO.getRemark());
|
updateWrapper.set(editDTO.getRemark() != null, CcdiStaffEnterpriseRelation::getRemark, editDTO.getRemark());
|
||||||
|
|
||||||
// 注意:以下字段不可修改
|
// 注意:以下字段不可修改
|
||||||
// - personId(身份证号,业务主键)
|
// - personId(亲属身份证号,业务主键)
|
||||||
// - socialCreditCode(统一社会信用代码,业务主键)
|
// - socialCreditCode(统一社会信用代码,业务主键)
|
||||||
// - dataSource(数据来源,系统字段)
|
// - dataSource(数据来源,系统字段)
|
||||||
// - isEmployee(是否为员工,系统字段)
|
// - isEmployee(是否为员工,系统字段)
|
||||||
@@ -224,4 +234,28 @@ public class CcdiStaffEnterpriseRelationServiceImpl implements ICcdiStaffEnterpr
|
|||||||
|
|
||||||
return taskId;
|
return taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CcdiStaffFmyRelation validateEffectiveFamily(String familyCertNo) {
|
||||||
|
CcdiStaffFmyRelation validFamily = familyRelationMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<CcdiStaffFmyRelation>()
|
||||||
|
.eq(CcdiStaffFmyRelation::getRelationCertNo, familyCertNo)
|
||||||
|
.eq(CcdiStaffFmyRelation::getIsEmpFamily, Boolean.TRUE)
|
||||||
|
.eq(CcdiStaffFmyRelation::getStatus, 1)
|
||||||
|
.last("LIMIT 1")
|
||||||
|
);
|
||||||
|
if (validFamily != null) {
|
||||||
|
return validFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcdiStaffFmyRelation existingFamily = familyRelationMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<CcdiStaffFmyRelation>()
|
||||||
|
.select(CcdiStaffFmyRelation::getId)
|
||||||
|
.eq(CcdiStaffFmyRelation::getRelationCertNo, familyCertNo)
|
||||||
|
.last("LIMIT 1")
|
||||||
|
);
|
||||||
|
if (existingFamily == null) {
|
||||||
|
throw new RuntimeException("亲属身份证号[" + familyCertNo + "]不存在,请先维护员工亲属关系");
|
||||||
|
}
|
||||||
|
throw new RuntimeException("亲属身份证号[" + familyCertNo + "]不是有效员工亲属,请先维护有效的员工亲属关系");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ import java.util.stream.Collectors;
|
|||||||
public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelationImportService {
|
public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelationImportService {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CcdiStaffFmyRelationImportServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(CcdiStaffFmyRelationImportServiceImpl.class);
|
||||||
|
private static final String SHEET_NAME = "员工亲属关系信息";
|
||||||
|
private static final int EXCEL_DATA_START_ROW = 2;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CcdiStaffFmyRelationMapper relationMapper;
|
private CcdiStaffFmyRelationMapper relationMapper;
|
||||||
@@ -168,6 +170,8 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
StaffFmyRelationImportFailureVO failure = new StaffFmyRelationImportFailureVO();
|
StaffFmyRelationImportFailureVO failure = new StaffFmyRelationImportFailureVO();
|
||||||
BeanUtils.copyProperties(excel, failure);
|
BeanUtils.copyProperties(excel, failure);
|
||||||
|
failure.setSheetName(SHEET_NAME);
|
||||||
|
failure.setRowNum(i + EXCEL_DATA_START_ROW);
|
||||||
failure.setErrorMessage(e.getMessage());
|
failure.setErrorMessage(e.getMessage());
|
||||||
failures.add(failure);
|
failures.add(failure);
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ package com.ruoyi.info.collection.service.impl;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.info.collection.domain.CcdiAssetInfo;
|
import com.ruoyi.info.collection.domain.CcdiAssetInfo;
|
||||||
import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
|
import com.ruoyi.info.collection.domain.CcdiStaffFmyRelation;
|
||||||
import com.ruoyi.info.collection.domain.vo.CcdiAssetInfoVO;
|
|
||||||
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.CcdiStaffFmyRelationExcel;
|
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
|
||||||
|
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.mapper.CcdiStaffEnterpriseRelationMapper;
|
||||||
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
|
import com.ruoyi.info.collection.mapper.CcdiStaffFmyRelationMapper;
|
||||||
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;
|
||||||
@@ -50,6 +51,9 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
|
|||||||
@Resource
|
@Resource
|
||||||
private ICcdiAssetInfoService assetInfoService;
|
private ICcdiAssetInfoService assetInfoService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiStaffEnterpriseRelationMapper staffEnterpriseRelationMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询员工亲属关系列表
|
* 查询员工亲属关系列表
|
||||||
*
|
*
|
||||||
@@ -161,6 +165,9 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
|
|||||||
CcdiStaffFmyRelation relation = new CcdiStaffFmyRelation();
|
CcdiStaffFmyRelation relation = new CcdiStaffFmyRelation();
|
||||||
BeanUtils.copyProperties(editDTO, relation);
|
BeanUtils.copyProperties(editDTO, relation);
|
||||||
int result = relationMapper.updateById(relation);
|
int result = relationMapper.updateById(relation);
|
||||||
|
if (Integer.valueOf(1).equals(existing.getStatus()) && Integer.valueOf(0).equals(editDTO.getStatus())) {
|
||||||
|
staffEnterpriseRelationMapper.invalidateByFamilyCertNo(existing.getRelationCertNo());
|
||||||
|
}
|
||||||
assetInfoService.replaceByFamilyIdAndPersonId(editDTO.getPersonId(), editDTO.getRelationCertNo(), editDTO.getAssetInfoList());
|
assetInfoService.replaceByFamilyIdAndPersonId(editDTO.getPersonId(), editDTO.getRelationCertNo(), editDTO.getAssetInfoList());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,35 @@ 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.common.utils.IdCardUtil;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
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.dto.CcdiStaffRecruitmentAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentAddDTO;
|
||||||
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.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.RecruitmentImportFailureVO;
|
import com.ruoyi.info.collection.domain.vo.RecruitmentImportFailureVO;
|
||||||
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.mapper.CcdiStaffRecruitmentMapper;
|
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper;
|
||||||
|
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentWorkMapper;
|
||||||
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentImportService;
|
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentImportService;
|
||||||
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.StringUtils;
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
@@ -24,10 +40,6 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 招聘信息异步导入Service实现
|
* 招聘信息异步导入Service实现
|
||||||
*
|
*
|
||||||
@@ -40,110 +52,72 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CcdiStaffRecruitmentImportServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(CcdiStaffRecruitmentImportServiceImpl.class);
|
||||||
|
|
||||||
|
private static final String MAIN_SHEET_NAME = "招聘信息";
|
||||||
|
private static final String WORK_SHEET_NAME = "历史工作经历";
|
||||||
|
private static final int EXCEL_DATA_START_ROW = 2;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CcdiStaffRecruitmentMapper recruitmentMapper;
|
private CcdiStaffRecruitmentMapper recruitmentMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiStaffRecruitmentWorkMapper recruitmentWorkMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Async
|
@Async
|
||||||
@Transactional
|
@Transactional
|
||||||
public void importRecruitmentAsync(List<CcdiStaffRecruitmentExcel> excelList,
|
public void importRecruitmentAsync(List<CcdiStaffRecruitmentExcel> recruitmentList,
|
||||||
|
List<CcdiStaffRecruitmentWorkExcel> workList,
|
||||||
String taskId,
|
String taskId,
|
||||||
String userName) {
|
String userName) {
|
||||||
|
List<CcdiStaffRecruitmentExcel> safeRecruitmentList = recruitmentList == null
|
||||||
|
? Collections.emptyList()
|
||||||
|
: recruitmentList;
|
||||||
|
List<CcdiStaffRecruitmentWorkExcel> safeWorkList = workList == null
|
||||||
|
? Collections.emptyList()
|
||||||
|
: workList;
|
||||||
|
int totalCount = safeRecruitmentList.size() + safeWorkList.size();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// 记录导入开始
|
ImportLogUtils.logImportStart(log, taskId, "招聘信息双Sheet", totalCount, userName);
|
||||||
ImportLogUtils.logImportStart(log, taskId, "招聘信息", excelList.size(), userName);
|
|
||||||
|
|
||||||
List<CcdiStaffRecruitment> newRecords = new ArrayList<>();
|
|
||||||
List<RecruitmentImportFailureVO> failures = new ArrayList<>();
|
List<RecruitmentImportFailureVO> failures = new ArrayList<>();
|
||||||
|
List<MainImportRow> indexedMainRows = buildMainImportRows(safeRecruitmentList);
|
||||||
|
List<WorkImportRow> indexedWorkRows = buildWorkImportRows(safeWorkList);
|
||||||
|
|
||||||
// 批量查询已存在的招聘项目编号
|
MainImportResult mainImportResult = importMainSheet(indexedMainRows, failures, userName, taskId);
|
||||||
ImportLogUtils.logBatchQueryStart(log, taskId, "已存在的招聘项目编号", excelList.size());
|
int workSuccessCount = importWorkSheet(
|
||||||
Set<String> existingRecruitIds = getExistingRecruitIds(excelList);
|
indexedWorkRows,
|
||||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "招聘项目编号", existingRecruitIds.size());
|
mainImportResult.importedRecruitmentMap(),
|
||||||
|
failures,
|
||||||
|
userName,
|
||||||
|
taskId
|
||||||
|
);
|
||||||
|
|
||||||
// 用于检测Excel内部的重复ID
|
|
||||||
Set<String> excelProcessedIds = new HashSet<>();
|
|
||||||
|
|
||||||
// 分类数据
|
|
||||||
for (int i = 0; i < excelList.size(); i++) {
|
|
||||||
CcdiStaffRecruitmentExcel excel = excelList.get(i);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 转换为AddDTO进行验证
|
|
||||||
CcdiStaffRecruitmentAddDTO addDTO = new CcdiStaffRecruitmentAddDTO();
|
|
||||||
BeanUtils.copyProperties(excel, addDTO);
|
|
||||||
|
|
||||||
// 验证数据
|
|
||||||
validateRecruitmentData(addDTO, existingRecruitIds);
|
|
||||||
|
|
||||||
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
|
|
||||||
BeanUtils.copyProperties(excel, recruitment);
|
|
||||||
|
|
||||||
if (existingRecruitIds.contains(excel.getRecruitId())) {
|
|
||||||
// 招聘项目编号在数据库中已存在,直接报错
|
|
||||||
throw new RuntimeException(String.format("招聘项目编号[%s]已存在,请勿重复导入", excel.getRecruitId()));
|
|
||||||
} else if (excelProcessedIds.contains(excel.getRecruitId())) {
|
|
||||||
// 招聘项目编号在Excel文件内部重复
|
|
||||||
throw new RuntimeException(String.format("招聘项目编号[%s]在导入文件中重复,已跳过此条记录", excel.getRecruitId()));
|
|
||||||
} else {
|
|
||||||
recruitment.setCreatedBy(userName);
|
|
||||||
recruitment.setUpdatedBy(userName);
|
|
||||||
newRecords.add(recruitment);
|
|
||||||
excelProcessedIds.add(excel.getRecruitId()); // 标记为已处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录进度
|
|
||||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
|
||||||
newRecords.size(), failures.size());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
RecruitmentImportFailureVO failure = new RecruitmentImportFailureVO();
|
|
||||||
BeanUtils.copyProperties(excel, failure);
|
|
||||||
failure.setErrorMessage(e.getMessage());
|
|
||||||
failures.add(failure);
|
|
||||||
|
|
||||||
// 记录验证失败日志
|
|
||||||
String keyData = String.format("招聘项目编号=%s, 项目名称=%s, 应聘人员=%s",
|
|
||||||
excel.getRecruitId(), excel.getRecruitName(), excel.getCandName());
|
|
||||||
ImportLogUtils.logValidationError(log, taskId, i + 1, e.getMessage(), keyData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量插入新数据
|
|
||||||
if (!newRecords.isEmpty()) {
|
|
||||||
ImportLogUtils.logBatchOperationStart(log, taskId, "插入",
|
|
||||||
(newRecords.size() + 499) / 500, 500);
|
|
||||||
saveBatch(newRecords, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存失败记录到Redis
|
|
||||||
if (!failures.isEmpty()) {
|
if (!failures.isEmpty()) {
|
||||||
try {
|
saveFailures(taskId, failures);
|
||||||
String failuresKey = "import:recruitment:" + taskId + ":failures";
|
|
||||||
redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS);
|
|
||||||
ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size());
|
|
||||||
} catch (Exception e) {
|
|
||||||
ImportLogUtils.logRedisError(log, taskId, "保存失败记录", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportResult result = new ImportResult();
|
ImportResult result = new ImportResult();
|
||||||
result.setTotalCount(excelList.size());
|
result.setTotalCount(totalCount);
|
||||||
result.setSuccessCount(newRecords.size());
|
result.setSuccessCount(mainImportResult.successCount() + workSuccessCount);
|
||||||
result.setFailureCount(failures.size());
|
result.setFailureCount(Math.max(totalCount - result.getSuccessCount(), 0));
|
||||||
|
|
||||||
// 更新最终状态
|
String finalStatus = resolveFinalStatus(result);
|
||||||
String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS";
|
|
||||||
updateImportStatus(taskId, finalStatus, result);
|
updateImportStatus(taskId, finalStatus, result);
|
||||||
|
|
||||||
// 记录导入完成
|
|
||||||
long duration = System.currentTimeMillis() - startTime;
|
long duration = System.currentTimeMillis() - startTime;
|
||||||
ImportLogUtils.logImportComplete(log, taskId, "招聘信息",
|
ImportLogUtils.logImportComplete(
|
||||||
excelList.size(), result.getSuccessCount(), result.getFailureCount(), duration);
|
log,
|
||||||
|
taskId,
|
||||||
|
"招聘信息双Sheet",
|
||||||
|
totalCount,
|
||||||
|
result.getSuccessCount(),
|
||||||
|
result.getFailureCount(),
|
||||||
|
duration
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -183,14 +157,188 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
|
|||||||
return JSON.parseArray(JSON.toJSONString(failuresObj), RecruitmentImportFailureVO.class);
|
return JSON.parseArray(JSON.toJSONString(failuresObj), RecruitmentImportFailureVO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private MainImportResult importMainSheet(List<MainImportRow> mainRows,
|
||||||
* 批量查询已存在的招聘项目编号
|
List<RecruitmentImportFailureVO> failures,
|
||||||
*/
|
String userName,
|
||||||
private Set<String> getExistingRecruitIds(List<CcdiStaffRecruitmentExcel> excelList) {
|
String taskId) {
|
||||||
List<String> recruitIds = excelList.stream()
|
if (mainRows.isEmpty()) {
|
||||||
.map(CcdiStaffRecruitmentExcel::getRecruitId)
|
return new MainImportResult(Collections.emptyMap(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> existingRecruitIds = getExistingRecruitIds(
|
||||||
|
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++) {
|
||||||
|
MainImportRow mainRow = mainRows.get(index);
|
||||||
|
CcdiStaffRecruitmentExcel excel = mainRow.data();
|
||||||
|
try {
|
||||||
|
CcdiStaffRecruitmentAddDTO addDTO = new CcdiStaffRecruitmentAddDTO();
|
||||||
|
BeanUtils.copyProperties(excel, addDTO);
|
||||||
|
addDTO.setRecruitType(RecruitType.inferCode(addDTO.getRecruitName()));
|
||||||
|
|
||||||
|
validateRecruitmentData(addDTO, mainRow.sheetRowNum());
|
||||||
|
|
||||||
|
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();
|
||||||
|
BeanUtils.copyProperties(excel, recruitment);
|
||||||
|
recruitment.setRecruitId(recruitId);
|
||||||
|
recruitment.setRecruitType(addDTO.getRecruitType());
|
||||||
|
recruitment.setCreatedBy(userName);
|
||||||
|
recruitment.setUpdatedBy(userName);
|
||||||
|
newRecords.add(recruitment);
|
||||||
|
importedRecruitmentMap.put(recruitId, recruitment);
|
||||||
|
|
||||||
|
ImportLogUtils.logProgress(log, taskId, index + 1, mainRows.size(), newRecords.size(), failures.size());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
FailureMeta failureMeta = resolveFailureMeta(exception, List.of(mainRow.sheetRowNum()), MAIN_SHEET_NAME);
|
||||||
|
failures.add(buildFailure(excel, failureMeta.sheetName(), failureMeta.sheetRowNum(), exception.getMessage()));
|
||||||
|
ImportLogUtils.logValidationError(
|
||||||
|
log,
|
||||||
|
taskId,
|
||||||
|
index + 1,
|
||||||
|
exception.getMessage(),
|
||||||
|
String.format("招聘记录编号=%s, 项目名称=%s, 应聘人员=%s", excel.getRecruitId(), excel.getRecruitName(), excel.getCandName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
Map<String, CcdiStaffRecruitment> importedRecruitmentMap,
|
||||||
|
List<RecruitmentImportFailureVO> failures,
|
||||||
|
String userName,
|
||||||
|
String taskId) {
|
||||||
|
if (workRows.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, CcdiStaffRecruitment> existingRecruitmentMap =
|
||||||
|
getExistingRecruitmentMap(workRows, importedRecruitmentMap);
|
||||||
|
Map<String, List<WorkImportRow>> groupedRows = groupWorkRows(workRows);
|
||||||
|
int successCount = 0;
|
||||||
|
int processedGroups = 0;
|
||||||
|
|
||||||
|
for (List<WorkImportRow> recruitWorkRows : groupedRows.values()) {
|
||||||
|
processedGroups++;
|
||||||
|
WorkImportRow firstRow = recruitWorkRows.get(0);
|
||||||
|
String recruitId = trim(firstRow.data().getRecruitId());
|
||||||
|
CcdiStaffRecruitment recruitment = importedRecruitmentMap.get(recruitId);
|
||||||
|
if (recruitment == null) {
|
||||||
|
recruitment = existingRecruitmentMap.get(recruitId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
validateWorkGroup(recruitWorkRows, recruitment);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(recruitId) && hasExistingWorkHistory(recruitId)) {
|
||||||
|
throw buildValidationException(
|
||||||
|
WORK_SHEET_NAME,
|
||||||
|
extractWorkRowNums(recruitWorkRows),
|
||||||
|
String.format("招聘记录编号[%s]已存在历史工作经历,不允许重复导入", recruitId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CcdiStaffRecruitmentWork> entities = buildWorkEntities(recruitWorkRows, userName);
|
||||||
|
entities.forEach(entity -> recruitmentWorkMapper.insert(entity));
|
||||||
|
successCount += recruitWorkRows.size();
|
||||||
|
|
||||||
|
ImportLogUtils.logProgress(log, taskId, processedGroups, groupedRows.size(), successCount, failures.size());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
FailureMeta failureMeta = resolveFailureMeta(exception, extractWorkRowNums(recruitWorkRows), WORK_SHEET_NAME);
|
||||||
|
failures.add(buildFailure(firstRow.data(), failureMeta.sheetName(), failureMeta.sheetRowNum(), exception.getMessage()));
|
||||||
|
ImportLogUtils.logValidationError(
|
||||||
|
log,
|
||||||
|
taskId,
|
||||||
|
processedGroups,
|
||||||
|
exception.getMessage(),
|
||||||
|
String.format(
|
||||||
|
"招聘记录编号=%s, 候选人=%s, 工作单位=%s",
|
||||||
|
firstRow.data().getRecruitId(),
|
||||||
|
firstRow.data().getCandName(),
|
||||||
|
firstRow.data().getCompanyName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return successCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<WorkImportRow>> groupWorkRows(List<WorkImportRow> workRows) {
|
||||||
|
Map<String, List<WorkImportRow>> groupedRows = new LinkedHashMap<>();
|
||||||
|
for (WorkImportRow workRow : workRows) {
|
||||||
|
groupedRows.computeIfAbsent(buildWorkGroupKey(workRow), key -> new ArrayList<>()).add(workRow);
|
||||||
|
}
|
||||||
|
return groupedRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildWorkGroupKey(WorkImportRow workRow) {
|
||||||
|
String recruitId = trim(workRow.data().getRecruitId());
|
||||||
|
if (StringUtils.isNotEmpty(recruitId)) {
|
||||||
|
return recruitId;
|
||||||
|
}
|
||||||
|
return "__ROW__" + workRow.sheetRowNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, CcdiStaffRecruitment> getExistingRecruitmentMap(List<WorkImportRow> workRows,
|
||||||
|
Map<String, CcdiStaffRecruitment> importedRecruitmentMap) {
|
||||||
|
LinkedHashSet<String> recruitIds = workRows.stream()
|
||||||
|
.map(row -> trim(row.data().getRecruitId()))
|
||||||
.filter(StringUtils::isNotEmpty)
|
.filter(StringUtils::isNotEmpty)
|
||||||
.collect(Collectors.toList());
|
.filter(recruitId -> !importedRecruitmentMap.containsKey(recruitId))
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
if (recruitIds.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
List<CcdiStaffRecruitment> recruitments = recruitmentMapper.selectBatchIds(recruitIds);
|
||||||
|
return recruitments.stream().collect(Collectors.toMap(CcdiStaffRecruitment::getRecruitId, item -> item));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CcdiStaffRecruitmentWork> buildWorkEntities(List<WorkImportRow> workRows, String userName) {
|
||||||
|
List<CcdiStaffRecruitmentWork> entities = new ArrayList<>();
|
||||||
|
for (WorkImportRow workRow : workRows) {
|
||||||
|
CcdiStaffRecruitmentWork entity = new CcdiStaffRecruitmentWork();
|
||||||
|
BeanUtils.copyProperties(workRow.data(), entity);
|
||||||
|
entity.setRecruitId(trim(workRow.data().getRecruitId()));
|
||||||
|
entity.setCreatedBy(userName);
|
||||||
|
entity.setUpdatedBy(userName);
|
||||||
|
entities.add(entity);
|
||||||
|
}
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
if (recruitIds.isEmpty()) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
@@ -205,69 +353,189 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean hasExistingWorkHistory(String recruitId) {
|
||||||
* 验证招聘信息数据
|
LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>();
|
||||||
*/
|
wrapper.eq(CcdiStaffRecruitmentWork::getRecruitId, recruitId);
|
||||||
private void validateRecruitmentData(CcdiStaffRecruitmentAddDTO addDTO,
|
return recruitmentWorkMapper.selectCount(wrapper) > 0;
|
||||||
Set<String> existingRecruitIds) {
|
}
|
||||||
// 验证必填字段
|
|
||||||
|
private void validateRecruitmentData(CcdiStaffRecruitmentAddDTO addDTO, int sheetRowNum) {
|
||||||
if (StringUtils.isEmpty(addDTO.getRecruitId())) {
|
if (StringUtils.isEmpty(addDTO.getRecruitId())) {
|
||||||
throw new RuntimeException("招聘项目编号不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getRecruitName())) {
|
if (StringUtils.isEmpty(addDTO.getRecruitName())) {
|
||||||
throw new RuntimeException("招聘项目名称不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘项目名称不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getPosName())) {
|
if (StringUtils.isEmpty(addDTO.getPosName())) {
|
||||||
throw new RuntimeException("职位名称不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "职位名称不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getPosCategory())) {
|
if (StringUtils.isEmpty(addDTO.getPosCategory())) {
|
||||||
throw new RuntimeException("职位类别不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "职位类别不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getPosDesc())) {
|
if (StringUtils.isEmpty(addDTO.getPosDesc())) {
|
||||||
throw new RuntimeException("职位描述不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "职位描述不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getCandName())) {
|
if (StringUtils.isEmpty(addDTO.getCandName())) {
|
||||||
throw new RuntimeException("应聘人员姓名不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员姓名不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getCandEdu())) {
|
if (StringUtils.isEmpty(addDTO.getCandEdu())) {
|
||||||
throw new RuntimeException("应聘人员学历不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员学历不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getCandId())) {
|
if (StringUtils.isEmpty(addDTO.getCandId())) {
|
||||||
throw new RuntimeException("证件号码不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "证件号码不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getCandSchool())) {
|
if (StringUtils.isEmpty(addDTO.getCandSchool())) {
|
||||||
throw new RuntimeException("应聘人员毕业院校不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员毕业院校不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getCandMajor())) {
|
if (StringUtils.isEmpty(addDTO.getCandMajor())) {
|
||||||
throw new RuntimeException("应聘人员专业不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员专业不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getCandGrad())) {
|
if (StringUtils.isEmpty(addDTO.getCandGrad())) {
|
||||||
throw new RuntimeException("应聘人员毕业年月不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "应聘人员毕业年月不能为空");
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(addDTO.getAdmitStatus())) {
|
if (StringUtils.isEmpty(addDTO.getAdmitStatus())) {
|
||||||
throw new RuntimeException("录用情况不能为空");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "录用情况不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(addDTO.getRecruitType())) {
|
||||||
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘类型不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证证件号码格式
|
|
||||||
String idCardError = IdCardUtil.getErrorMessage(addDTO.getCandId());
|
String idCardError = IdCardUtil.getErrorMessage(addDTO.getCandId());
|
||||||
if (idCardError != null) {
|
if (idCardError != null) {
|
||||||
throw new RuntimeException("证件号码" + idCardError);
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "证件号码" + idCardError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证毕业年月格式(YYYYMM)
|
|
||||||
if (!addDTO.getCandGrad().matches("^((19|20)\\d{2})(0[1-9]|1[0-2])$")) {
|
if (!addDTO.getCandGrad().matches("^((19|20)\\d{2})(0[1-9]|1[0-2])$")) {
|
||||||
throw new RuntimeException("毕业年月格式不正确,应为YYYYMM");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "毕业年月格式不正确,应为YYYYMM");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证录用状态
|
|
||||||
if (AdmitStatus.getDescByCode(addDTO.getAdmitStatus()) == null) {
|
if (AdmitStatus.getDescByCode(addDTO.getAdmitStatus()) == null) {
|
||||||
throw new RuntimeException("录用情况只能填写'录用'、'未录用'或'放弃'");
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "录用情况只能填写'录用'、'未录用'或'放弃'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RecruitType.getDescByCode(addDTO.getRecruitType()) == null) {
|
||||||
|
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "招聘类型只能填写'SOCIAL'或'CAMPUS'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void validateWorkGroup(List<WorkImportRow> workRows, CcdiStaffRecruitment recruitment) {
|
||||||
* 更新导入状态
|
Set<Integer> processedSortOrders = new HashSet<>();
|
||||||
*/
|
for (WorkImportRow workRow : workRows) {
|
||||||
|
validateRecruitmentWorkData(workRow.data(), recruitment, processedSortOrders, workRow.sheetRowNum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateRecruitmentWorkData(CcdiStaffRecruitmentWorkExcel excel,
|
||||||
|
CcdiStaffRecruitment recruitment,
|
||||||
|
Set<Integer> processedSortOrders,
|
||||||
|
int sheetRowNum) {
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getRecruitId()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getCandName()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "候选人姓名不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getRecruitName()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘项目名称不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getPosName()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "职位名称不能为空");
|
||||||
|
}
|
||||||
|
if (excel.getSortOrder() == null || excel.getSortOrder() <= 0) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "排序号不能为空且必须大于0");
|
||||||
|
}
|
||||||
|
if (!processedSortOrders.add(excel.getSortOrder())) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "同一招聘记录编号下排序号重复");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getCompanyName()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "工作单位不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getPositionName()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "岗位不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(trim(excel.getJobStartMonth()))) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "入职年月不能为空");
|
||||||
|
}
|
||||||
|
validateMonth(excel.getJobStartMonth(), "入职年月", sheetRowNum);
|
||||||
|
if (StringUtils.isNotEmpty(trim(excel.getJobEndMonth()))) {
|
||||||
|
validateMonth(excel.getJobEndMonth(), "离职年月", sheetRowNum);
|
||||||
|
}
|
||||||
|
if (recruitment == null) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号不存在,请先维护招聘主信息");
|
||||||
|
}
|
||||||
|
if (!"SOCIAL".equals(recruitment.getRecruitType())) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "该招聘记录不是社招,不允许导入历史工作经历");
|
||||||
|
}
|
||||||
|
if (!sameText(excel.getCandName(), recruitment.getCandName())) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号与候选人姓名不匹配");
|
||||||
|
}
|
||||||
|
if (!sameText(excel.getRecruitName(), recruitment.getRecruitName())) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号与招聘项目名称不匹配");
|
||||||
|
}
|
||||||
|
if (!sameText(excel.getPosName(), recruitment.getPosName())) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), "招聘记录编号与职位名称不匹配");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateMonth(String value, String fieldName, int sheetRowNum) {
|
||||||
|
String month = trim(value);
|
||||||
|
if (!month.matches("^((19|20)\\d{2})-(0[1-9]|1[0-2])$")) {
|
||||||
|
throw buildValidationException(WORK_SHEET_NAME, List.of(sheetRowNum), fieldName + "格式不正确,应为YYYY-MM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sameText(String first, String second) {
|
||||||
|
return Objects.equals(trim(first), trim(second));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trim(String value) {
|
||||||
|
return value == null ? null : value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveFailures(String taskId, List<RecruitmentImportFailureVO> failures) {
|
||||||
|
try {
|
||||||
|
String failuresKey = "import:recruitment:" + taskId + ":failures";
|
||||||
|
redisTemplate.opsForValue().set(failuresKey, failures, 7, TimeUnit.DAYS);
|
||||||
|
ImportLogUtils.logRedisOperation(log, taskId, "保存失败记录", failures.size());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
ImportLogUtils.logRedisError(log, taskId, "保存失败记录", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecruitmentImportFailureVO buildFailure(CcdiStaffRecruitmentExcel excel,
|
||||||
|
String sheetName,
|
||||||
|
String sheetRowNum,
|
||||||
|
String errorMessage) {
|
||||||
|
RecruitmentImportFailureVO failure = new RecruitmentImportFailureVO();
|
||||||
|
BeanUtils.copyProperties(excel, failure);
|
||||||
|
failure.setSheetName(sheetName);
|
||||||
|
failure.setSheetRowNum(sheetRowNum);
|
||||||
|
failure.setErrorMessage(errorMessage);
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecruitmentImportFailureVO buildFailure(CcdiStaffRecruitmentWorkExcel excel,
|
||||||
|
String sheetName,
|
||||||
|
String sheetRowNum,
|
||||||
|
String errorMessage) {
|
||||||
|
RecruitmentImportFailureVO failure = new RecruitmentImportFailureVO();
|
||||||
|
BeanUtils.copyProperties(excel, failure);
|
||||||
|
failure.setSheetName(sheetName);
|
||||||
|
failure.setSheetRowNum(sheetRowNum);
|
||||||
|
failure.setErrorMessage(errorMessage);
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveFinalStatus(ImportResult result) {
|
||||||
|
if (result.getFailureCount() == 0) {
|
||||||
|
return "SUCCESS";
|
||||||
|
}
|
||||||
|
if (result.getSuccessCount() == 0) {
|
||||||
|
return "FAILED";
|
||||||
|
}
|
||||||
|
return "PARTIAL_SUCCESS";
|
||||||
|
}
|
||||||
|
|
||||||
private void updateImportStatus(String taskId, String status, ImportResult result) {
|
private void updateImportStatus(String taskId, String status, ImportResult result) {
|
||||||
String key = "import:recruitment:" + taskId;
|
String key = "import:recruitment:" + taskId;
|
||||||
Map<String, Object> statusData = new HashMap<>();
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
@@ -287,35 +555,100 @@ public class CcdiStaffRecruitmentImportServiceImpl implements ICcdiStaffRecruitm
|
|||||||
redisTemplate.opsForHash().putAll(key, statusData);
|
redisTemplate.opsForHash().putAll(key, statusData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量保存
|
|
||||||
*/
|
|
||||||
private void saveBatch(List<CcdiStaffRecruitment> list, int batchSize) {
|
private void saveBatch(List<CcdiStaffRecruitment> list, int batchSize) {
|
||||||
// 使用真正的批量插入,分批次执行以提高性能
|
|
||||||
for (int i = 0; i < list.size(); i += batchSize) {
|
for (int i = 0; i < list.size(); i += batchSize) {
|
||||||
int end = Math.min(i + batchSize, list.size());
|
int end = Math.min(i + batchSize, list.size());
|
||||||
List<CcdiStaffRecruitment> subList = list.subList(i, end);
|
List<CcdiStaffRecruitment> subList = list.subList(i, end);
|
||||||
|
|
||||||
// 过滤掉已存在的记录,防止主键冲突
|
|
||||||
List<String> recruitIds = subList.stream()
|
List<String> recruitIds = subList.stream()
|
||||||
.map(CcdiStaffRecruitment::getRecruitId)
|
.map(CcdiStaffRecruitment::getRecruitId)
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
|
if (recruitIds.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!recruitIds.isEmpty()) {
|
|
||||||
List<CcdiStaffRecruitment> existingRecords = recruitmentMapper.selectBatchIds(recruitIds);
|
List<CcdiStaffRecruitment> existingRecords = recruitmentMapper.selectBatchIds(recruitIds);
|
||||||
Set<String> existingIds = existingRecords.stream()
|
Set<String> existingIds = existingRecords.stream()
|
||||||
.map(CcdiStaffRecruitment::getRecruitId)
|
.map(CcdiStaffRecruitment::getRecruitId)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
// 只插入不存在的记录
|
|
||||||
List<CcdiStaffRecruitment> toInsert = subList.stream()
|
List<CcdiStaffRecruitment> toInsert = subList.stream()
|
||||||
.filter(r -> !existingIds.contains(r.getRecruitId()))
|
.filter(record -> !existingIds.contains(record.getRecruitId()))
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
|
|
||||||
if (!toInsert.isEmpty()) {
|
if (!toInsert.isEmpty()) {
|
||||||
recruitmentMapper.insertBatch(toInsert);
|
recruitmentMapper.insertBatch(toInsert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<MainImportRow> buildMainImportRows(List<CcdiStaffRecruitmentExcel> recruitmentList) {
|
||||||
|
List<MainImportRow> rows = new ArrayList<>();
|
||||||
|
for (int i = 0; i < recruitmentList.size(); i++) {
|
||||||
|
rows.add(new MainImportRow(recruitmentList.get(i), i + EXCEL_DATA_START_ROW));
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<WorkImportRow> buildWorkImportRows(List<CcdiStaffRecruitmentWorkExcel> workList) {
|
||||||
|
List<WorkImportRow> rows = new ArrayList<>();
|
||||||
|
for (int i = 0; i < workList.size(); i++) {
|
||||||
|
rows.add(new WorkImportRow(workList.get(i), i + EXCEL_DATA_START_ROW));
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> extractWorkRowNums(List<WorkImportRow> rows) {
|
||||||
|
return rows.stream().map(WorkImportRow::sheetRowNum).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FailureMeta resolveFailureMeta(Exception exception, List<Integer> rowNums, String defaultSheetName) {
|
||||||
|
if (exception instanceof ImportValidationException validationException) {
|
||||||
|
return new FailureMeta(validationException.getSheetName(), validationException.getSheetRowNum());
|
||||||
|
}
|
||||||
|
return new FailureMeta(defaultSheetName, formatSheetRowNum(rowNums));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImportValidationException buildValidationException(String sheetName, List<Integer> rowNums, String message) {
|
||||||
|
return new ImportValidationException(sheetName, formatSheetRowNum(rowNums), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatSheetRowNum(List<Integer> rowNums) {
|
||||||
|
if (rowNums == null || rowNums.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return rowNums.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.sorted()
|
||||||
|
.map(String::valueOf)
|
||||||
|
.collect(Collectors.joining("、"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private record MainImportRow(CcdiStaffRecruitmentExcel data, int sheetRowNum) {}
|
||||||
|
|
||||||
|
private record WorkImportRow(CcdiStaffRecruitmentWorkExcel data, int sheetRowNum) {}
|
||||||
|
|
||||||
|
private record MainImportResult(Map<String, CcdiStaffRecruitment> importedRecruitmentMap, int successCount) {}
|
||||||
|
|
||||||
|
private record FailureMeta(String sheetName, String sheetRowNum) {}
|
||||||
|
|
||||||
|
private static class ImportValidationException extends RuntimeException {
|
||||||
|
|
||||||
|
private final String sheetName;
|
||||||
|
private final String sheetRowNum;
|
||||||
|
|
||||||
|
private ImportValidationException(String sheetName, String sheetRowNum, String message) {
|
||||||
|
super(message);
|
||||||
|
this.sheetName = sheetName;
|
||||||
|
this.sheetRowNum = sheetRowNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSheetName() {
|
||||||
|
return sheetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSheetRowNum() {
|
||||||
|
return sheetRowNum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
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.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.dto.CcdiStaffRecruitmentAddDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentAddDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
|
||||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
|
||||||
|
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentWorkEditDTO;
|
||||||
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.vo.CcdiStaffRecruitmentVO;
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentVO;
|
||||||
|
import com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentWorkVO;
|
||||||
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.mapper.CcdiStaffRecruitmentWorkMapper;
|
||||||
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper;
|
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper;
|
||||||
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentImportService;
|
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentImportService;
|
||||||
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentService;
|
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentService;
|
||||||
@@ -19,9 +26,11 @@ import org.springframework.data.redis.core.RedisTemplate;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -37,6 +46,9 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
@Resource
|
@Resource
|
||||||
private CcdiStaffRecruitmentMapper recruitmentMapper;
|
private CcdiStaffRecruitmentMapper recruitmentMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CcdiStaffRecruitmentWorkMapper recruitmentWorkMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ICcdiStaffRecruitmentImportService recruitmentImportService;
|
private ICcdiStaffRecruitmentImportService recruitmentImportService;
|
||||||
|
|
||||||
@@ -96,7 +108,7 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
/**
|
/**
|
||||||
* 查询招聘信息详情
|
* 查询招聘信息详情
|
||||||
*
|
*
|
||||||
* @param recruitId 招聘项目编号
|
* @param recruitId 招聘记录编号
|
||||||
* @return 招聘信息VO
|
* @return 招聘信息VO
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -104,6 +116,7 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
CcdiStaffRecruitmentVO vo = recruitmentMapper.selectRecruitmentById(recruitId);
|
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(recruitId));
|
||||||
}
|
}
|
||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
@@ -117,9 +130,9 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO) {
|
public int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO) {
|
||||||
// 检查招聘项目编号唯一性
|
// 检查招聘记录编号唯一性
|
||||||
if (recruitmentMapper.selectById(addDTO.getRecruitId()) != null) {
|
if (recruitmentMapper.selectById(addDTO.getRecruitId()) != null) {
|
||||||
throw new RuntimeException("该招聘项目编号已存在");
|
throw new RuntimeException("该招聘记录编号已存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
|
CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
|
||||||
@@ -141,6 +154,7 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
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);
|
||||||
|
replaceWorkExperienceList(editDTO);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -148,12 +162,15 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
/**
|
/**
|
||||||
* 批量删除招聘信息
|
* 批量删除招聘信息
|
||||||
*
|
*
|
||||||
* @param recruitIds 需要删除的招聘项目编号
|
* @param recruitIds 需要删除的招聘记录编号
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public int deleteRecruitmentByIds(String[] recruitIds) {
|
public int deleteRecruitmentByIds(String[] recruitIds) {
|
||||||
|
LambdaQueryWrapper<CcdiStaffRecruitmentWork> workWrapper = new LambdaQueryWrapper<>();
|
||||||
|
workWrapper.in(CcdiStaffRecruitmentWork::getRecruitId, List.of(recruitIds));
|
||||||
|
recruitmentWorkMapper.delete(workWrapper);
|
||||||
return recruitmentMapper.deleteBatchIds(List.of(recruitIds));
|
return recruitmentMapper.deleteBatchIds(List.of(recruitIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,24 +182,26 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public String importRecruitment(java.util.List<CcdiStaffRecruitmentExcel> excelList) {
|
public String importRecruitment(List<CcdiStaffRecruitmentExcel> recruitmentList,
|
||||||
if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
|
List<CcdiStaffRecruitmentWorkExcel> workList) {
|
||||||
|
recruitmentList = recruitmentList == null ? List.of() : recruitmentList;
|
||||||
|
workList = workList == null ? List.of() : workList;
|
||||||
|
boolean noRecruitmentRows = StringUtils.isNull(recruitmentList) || recruitmentList.isEmpty();
|
||||||
|
boolean noWorkRows = StringUtils.isNull(workList) || workList.isEmpty();
|
||||||
|
if (noRecruitmentRows && noWorkRows) {
|
||||||
throw new RuntimeException("至少需要一条数据");
|
throw new RuntimeException("至少需要一条数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成任务ID
|
|
||||||
String taskId = UUID.randomUUID().toString();
|
String taskId = UUID.randomUUID().toString();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// 获取当前用户名
|
|
||||||
String userName = SecurityUtils.getUsername();
|
String userName = SecurityUtils.getUsername();
|
||||||
|
int totalCount = recruitmentList.size() + workList.size();
|
||||||
|
|
||||||
// 初始化Redis状态
|
|
||||||
String statusKey = "import:recruitment:" + taskId;
|
String statusKey = "import:recruitment:" + taskId;
|
||||||
Map<String, Object> statusData = new HashMap<>();
|
Map<String, Object> statusData = new HashMap<>();
|
||||||
statusData.put("taskId", taskId);
|
statusData.put("taskId", taskId);
|
||||||
statusData.put("status", "PROCESSING");
|
statusData.put("status", "PROCESSING");
|
||||||
statusData.put("totalCount", excelList.size());
|
statusData.put("totalCount", totalCount);
|
||||||
statusData.put("successCount", 0);
|
statusData.put("successCount", 0);
|
||||||
statusData.put("failureCount", 0);
|
statusData.put("failureCount", 0);
|
||||||
statusData.put("progress", 0);
|
statusData.put("progress", 0);
|
||||||
@@ -192,9 +211,63 @@ public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentSer
|
|||||||
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
||||||
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
||||||
|
|
||||||
// 调用异步导入服务
|
recruitmentImportService.importRecruitmentAsync(recruitmentList, workList, taskId, userName);
|
||||||
recruitmentImportService.importRecruitmentAsync(excelList, taskId, userName);
|
|
||||||
|
|
||||||
return taskId;
|
return taskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<CcdiStaffRecruitmentWorkVO> selectWorkExperienceList(String recruitId) {
|
||||||
|
LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(CcdiStaffRecruitmentWork::getRecruitId, recruitId)
|
||||||
|
.orderByAsc(CcdiStaffRecruitmentWork::getSortOrder)
|
||||||
|
.orderByDesc(CcdiStaffRecruitmentWork::getId);
|
||||||
|
List<CcdiStaffRecruitmentWork> workList = recruitmentWorkMapper.selectList(wrapper);
|
||||||
|
if (workList == null || workList.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return workList.stream().map(work -> {
|
||||||
|
CcdiStaffRecruitmentWorkVO vo = new CcdiStaffRecruitmentWorkVO();
|
||||||
|
BeanUtils.copyProperties(work, vo);
|
||||||
|
return vo;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replaceWorkExperienceList(CcdiStaffRecruitmentEditDTO editDTO) {
|
||||||
|
LambdaQueryWrapper<CcdiStaffRecruitmentWork> deleteWrapper = new LambdaQueryWrapper<>();
|
||||||
|
deleteWrapper.eq(CcdiStaffRecruitmentWork::getRecruitId, editDTO.getRecruitId());
|
||||||
|
|
||||||
|
if (!Objects.equals(RecruitType.SOCIAL.getCode(), editDTO.getRecruitType())) {
|
||||||
|
recruitmentWorkMapper.delete(deleteWrapper);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editDTO.getWorkExperienceList() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
recruitmentWorkMapper.delete(deleteWrapper);
|
||||||
|
List<CcdiStaffRecruitmentWork> workList = buildWorkExperienceEntities(editDTO);
|
||||||
|
workList.forEach(recruitmentWorkMapper::insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CcdiStaffRecruitmentWork> buildWorkExperienceEntities(CcdiStaffRecruitmentEditDTO editDTO) {
|
||||||
|
List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList = editDTO.getWorkExperienceList();
|
||||||
|
if (workExperienceList == null || workExperienceList.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CcdiStaffRecruitmentWork> entityList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < workExperienceList.size(); i++) {
|
||||||
|
CcdiStaffRecruitmentWorkEditDTO item = workExperienceList.get(i);
|
||||||
|
if (item == null || StringUtils.isBlank(item.getCompanyName()) || StringUtils.isBlank(item.getJobStartMonth())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CcdiStaffRecruitmentWork work = new CcdiStaffRecruitmentWork();
|
||||||
|
BeanUtils.copyProperties(item, work);
|
||||||
|
work.setRecruitId(editDTO.getRecruitId());
|
||||||
|
work.setSortOrder(i + 1);
|
||||||
|
entityList.add(work);
|
||||||
|
}
|
||||||
|
return entityList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.ruoyi.info.collection.utils;
|
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.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.info.collection.handler.DictDropdownWriteHandler;
|
import com.ruoyi.info.collection.handler.DictDropdownWriteHandler;
|
||||||
@@ -98,6 +100,23 @@ public class EasyExcelUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入Excel(按指定Sheet名称)
|
||||||
|
*
|
||||||
|
* @param inputStream 输入流
|
||||||
|
* @param clazz 实体类
|
||||||
|
* @param sheetName 工作表名称
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @return 数据列表
|
||||||
|
*/
|
||||||
|
public static <T> List<T> importExcel(java.io.InputStream inputStream, Class<T> clazz, String sheetName) {
|
||||||
|
try {
|
||||||
|
return EasyExcel.read(inputStream).head(clazz).sheet(sheetName).doReadSync();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("导入Excel失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载导入模板
|
* 下载导入模板
|
||||||
*
|
*
|
||||||
@@ -210,6 +229,45 @@ public class EasyExcelUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载双Sheet导入模板(带字典下拉框)
|
||||||
|
*
|
||||||
|
* @param response 响应对象
|
||||||
|
* @param firstClazz 第一张Sheet实体类
|
||||||
|
* @param firstSheetName 第一张Sheet名称
|
||||||
|
* @param secondClazz 第二张Sheet实体类
|
||||||
|
* @param secondSheetName 第二张Sheet名称
|
||||||
|
* @param fileName 文件名称
|
||||||
|
* @param <T1> 第一张Sheet泛型
|
||||||
|
* @param <T2> 第二张Sheet泛型
|
||||||
|
*/
|
||||||
|
public static <T1, T2> void importTemplateWithDictDropdown(
|
||||||
|
HttpServletResponse response,
|
||||||
|
Class<T1> firstClazz,
|
||||||
|
String firstSheetName,
|
||||||
|
Class<T2> secondClazz,
|
||||||
|
String secondSheetName,
|
||||||
|
String fileName
|
||||||
|
) {
|
||||||
|
setResponseHeader(response, fileName);
|
||||||
|
try (ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build()) {
|
||||||
|
writer.write(List.of(), buildTemplateSheet(0, firstClazz, firstSheetName));
|
||||||
|
writer.write(List.of(), buildTemplateSheet(1, secondClazz, secondSheetName));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("下载双Sheet导入模板失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> WriteSheet buildTemplateSheet(int sheetNo, Class<T> clazz, String sheetName) {
|
||||||
|
return EasyExcel.writerSheet(sheetNo, sheetName)
|
||||||
|
.head(clazz)
|
||||||
|
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
|
||||||
|
.registerWriteHandler(new DictDropdownWriteHandler(clazz))
|
||||||
|
.registerWriteHandler(new TextFormatWriteHandler(clazz))
|
||||||
|
.registerWriteHandler(new RequiredFieldWriteHandler(clazz))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出Excel(带字典下拉框)
|
* 导出Excel(带字典下拉框)
|
||||||
* 导出的数据包含实际值,但模板中有下拉框供后续编辑使用
|
* 导出的数据包含实际值,但模板中有下拉框供后续编辑使用
|
||||||
|
|||||||
@@ -4,6 +4,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper">
|
<mapper namespace="com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper">
|
||||||
|
|
||||||
|
<insert id="insertBatch" parameterType="java.util.List">
|
||||||
|
INSERT INTO ccdi_intermediary_enterprise_relation (
|
||||||
|
intermediary_biz_id, social_credit_code, relation_person_post, remark,
|
||||||
|
created_by, updated_by, create_time, update_time
|
||||||
|
) VALUES
|
||||||
|
<foreach collection="list" item="item" separator=",">
|
||||||
|
(
|
||||||
|
#{item.intermediaryBizId}, #{item.socialCreditCode}, #{item.relationPersonPost}, #{item.remark},
|
||||||
|
#{item.createdBy}, #{item.updatedBy}, NOW(), NOW()
|
||||||
|
)
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
<resultMap id="CcdiIntermediaryEnterpriseRelationVOResult"
|
<resultMap id="CcdiIntermediaryEnterpriseRelationVOResult"
|
||||||
type="com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO">
|
type="com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO">
|
||||||
<id property="id" column="id"/>
|
<id property="id" column="id"/>
|
||||||
@@ -63,4 +76,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
AND social_credit_code = #{socialCreditCode}
|
AND social_credit_code = #{socialCreditCode}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="batchExistsByCombinations" resultType="string">
|
||||||
|
SELECT CONCAT(intermediary_biz_id, '|', social_credit_code)
|
||||||
|
FROM ccdi_intermediary_enterprise_relation
|
||||||
|
WHERE CONCAT(intermediary_biz_id, '|', social_credit_code) IN
|
||||||
|
<foreach collection="combinations" item="item" open="(" separator="," close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
child.create_time
|
child.create_time
|
||||||
FROM ccdi_biz_intermediary child
|
FROM ccdi_biz_intermediary child
|
||||||
INNER JOIN ccdi_biz_intermediary parent
|
INNER JOIN ccdi_biz_intermediary parent
|
||||||
ON child.related_num_id COLLATE utf8mb4_general_ci = parent.biz_id COLLATE utf8mb4_general_ci
|
ON child.related_num_id COLLATE utf8mb4_general_ci = parent.person_id COLLATE utf8mb4_general_ci
|
||||||
AND parent.person_sub_type COLLATE utf8mb4_general_ci = '本人' COLLATE utf8mb4_general_ci
|
AND parent.person_sub_type COLLATE utf8mb4_general_ci = '本人' COLLATE utf8mb4_general_ci
|
||||||
WHERE child.person_sub_type IS NOT NULL
|
WHERE child.person_sub_type IS NOT NULL
|
||||||
AND child.person_sub_type COLLATE utf8mb4_general_ci != '本人' COLLATE utf8mb4_general_ci
|
AND child.person_sub_type COLLATE utf8mb4_general_ci != '本人' COLLATE utf8mb4_general_ci
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
<result property="contactPhone" column="contact_phone"/>
|
<result property="contactPhone" column="contact_phone"/>
|
||||||
<result property="supplierUscc" column="supplier_uscc"/>
|
<result property="supplierUscc" column="supplier_uscc"/>
|
||||||
<result property="supplierBankAccount" column="supplier_bank_account"/>
|
<result property="supplierBankAccount" column="supplier_bank_account"/>
|
||||||
|
<result property="supplierCount" column="supplier_count"/>
|
||||||
<result property="applyDate" column="apply_date"/>
|
<result property="applyDate" column="apply_date"/>
|
||||||
<result property="planApproveDate" column="plan_approve_date"/>
|
<result property="planApproveDate" column="plan_approve_date"/>
|
||||||
<result property="announceDate" column="announce_date"/>
|
<result property="announceDate" column="announce_date"/>
|
||||||
@@ -47,49 +48,61 @@
|
|||||||
<!-- 分页查询采购交易列表 -->
|
<!-- 分页查询采购交易列表 -->
|
||||||
<select id="selectTransactionPage" resultMap="CcdiPurchaseTransactionVOResult">
|
<select id="selectTransactionPage" resultMap="CcdiPurchaseTransactionVOResult">
|
||||||
SELECT
|
SELECT
|
||||||
purchase_id, purchase_category, project_name, subject_name, subject_desc,
|
t.purchase_id, t.purchase_category, t.project_name, t.subject_name, t.subject_desc,
|
||||||
purchase_qty, budget_amount, bid_amount, actual_amount, contract_amount, settlement_amount,
|
t.purchase_qty, t.budget_amount, t.bid_amount, t.actual_amount, t.contract_amount, t.settlement_amount,
|
||||||
purchase_method, supplier_name, contact_person, contact_phone, supplier_uscc, supplier_bank_account,
|
t.purchase_method, t.supplier_name, t.contact_person, t.contact_phone, t.supplier_uscc, t.supplier_bank_account,
|
||||||
apply_date, plan_approve_date, announce_date, bid_open_date, contract_sign_date,
|
IFNULL(supplier_stats.supplier_count, 0) AS supplier_count,
|
||||||
expected_delivery_date, actual_delivery_date, acceptance_date, settlement_date,
|
t.apply_date, t.plan_approve_date, t.announce_date, t.bid_open_date, t.contract_sign_date,
|
||||||
applicant_id, applicant_name, apply_department, purchase_leader_id, purchase_leader_name, purchase_department,
|
t.expected_delivery_date, t.actual_delivery_date, t.acceptance_date, t.settlement_date,
|
||||||
created_by, create_time, updated_by, update_time
|
t.applicant_id, t.applicant_name, t.apply_department, t.purchase_leader_id, t.purchase_leader_name, t.purchase_department,
|
||||||
FROM ccdi_purchase_transaction
|
t.created_by, t.create_time, t.updated_by, t.update_time
|
||||||
|
FROM ccdi_purchase_transaction t
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT purchase_id, COUNT(*) AS supplier_count
|
||||||
|
FROM ccdi_purchase_transaction_supplier
|
||||||
|
GROUP BY purchase_id
|
||||||
|
) supplier_stats ON supplier_stats.purchase_id = t.purchase_id
|
||||||
<where>
|
<where>
|
||||||
<if test="query.projectName != null and query.projectName != ''">
|
<if test="query.projectName != null and query.projectName != ''">
|
||||||
AND project_name LIKE CONCAT('%', #{query.projectName}, '%')
|
AND t.project_name LIKE CONCAT('%', #{query.projectName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="query.subjectName != null and query.subjectName != ''">
|
<if test="query.subjectName != null and query.subjectName != ''">
|
||||||
AND subject_name LIKE CONCAT('%', #{query.subjectName}, '%')
|
AND t.subject_name LIKE CONCAT('%', #{query.subjectName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="query.applicantName != null and query.applicantName != ''">
|
<if test="query.applicantName != null and query.applicantName != ''">
|
||||||
AND applicant_name LIKE CONCAT('%', #{query.applicantName}, '%')
|
AND t.applicant_name LIKE CONCAT('%', #{query.applicantName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="query.applicantId != null and query.applicantId != ''">
|
<if test="query.applicantId != null and query.applicantId != ''">
|
||||||
AND applicant_id = #{query.applicantId}
|
AND t.applicant_id = #{query.applicantId}
|
||||||
</if>
|
</if>
|
||||||
<if test="query.applyDateStart != null">
|
<if test="query.applyDateStart != null">
|
||||||
AND apply_date >= #{query.applyDateStart}
|
AND t.apply_date >= #{query.applyDateStart}
|
||||||
</if>
|
</if>
|
||||||
<if test="query.applyDateEnd != null">
|
<if test="query.applyDateEnd != null">
|
||||||
AND apply_date <= #{query.applyDateEnd}
|
AND t.apply_date <= #{query.applyDateEnd}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
ORDER BY create_time DESC
|
ORDER BY t.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 查询采购交易详情 -->
|
<!-- 查询采购交易详情 -->
|
||||||
<select id="selectTransactionById" resultMap="CcdiPurchaseTransactionVOResult">
|
<select id="selectTransactionById" resultMap="CcdiPurchaseTransactionVOResult">
|
||||||
SELECT
|
SELECT
|
||||||
purchase_id, purchase_category, project_name, subject_name, subject_desc,
|
t.purchase_id, t.purchase_category, t.project_name, t.subject_name, t.subject_desc,
|
||||||
purchase_qty, budget_amount, bid_amount, actual_amount, contract_amount, settlement_amount,
|
t.purchase_qty, t.budget_amount, t.bid_amount, t.actual_amount, t.contract_amount, t.settlement_amount,
|
||||||
purchase_method, supplier_name, contact_person, contact_phone, supplier_uscc, supplier_bank_account,
|
t.purchase_method, t.supplier_name, t.contact_person, t.contact_phone, t.supplier_uscc, t.supplier_bank_account,
|
||||||
apply_date, plan_approve_date, announce_date, bid_open_date, contract_sign_date,
|
IFNULL(supplier_stats.supplier_count, 0) AS supplier_count,
|
||||||
expected_delivery_date, actual_delivery_date, acceptance_date, settlement_date,
|
t.apply_date, t.plan_approve_date, t.announce_date, t.bid_open_date, t.contract_sign_date,
|
||||||
applicant_id, applicant_name, apply_department, purchase_leader_id, purchase_leader_name, purchase_department,
|
t.expected_delivery_date, t.actual_delivery_date, t.acceptance_date, t.settlement_date,
|
||||||
created_by, create_time, updated_by, update_time
|
t.applicant_id, t.applicant_name, t.apply_department, t.purchase_leader_id, t.purchase_leader_name, t.purchase_department,
|
||||||
FROM ccdi_purchase_transaction
|
t.created_by, t.create_time, t.updated_by, t.update_time
|
||||||
WHERE purchase_id = #{purchaseId}
|
FROM ccdi_purchase_transaction t
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT purchase_id, COUNT(*) AS supplier_count
|
||||||
|
FROM ccdi_purchase_transaction_supplier
|
||||||
|
GROUP BY purchase_id
|
||||||
|
) supplier_stats ON supplier_stats.purchase_id = t.purchase_id
|
||||||
|
WHERE t.purchase_id = #{purchaseId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 批量插入采购交易数据 -->
|
<!-- 批量插入采购交易数据 -->
|
||||||
@@ -137,4 +150,12 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteSuppliersByPurchaseIds">
|
||||||
|
DELETE FROM ccdi_purchase_transaction_supplier
|
||||||
|
WHERE purchase_id IN
|
||||||
|
<foreach collection="purchaseIds" item="purchaseId" open="(" separator="," close=")">
|
||||||
|
#{purchaseId}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
<resultMap type="com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO" id="CcdiStaffEnterpriseRelationVOResult">
|
<resultMap type="com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationVO" id="CcdiStaffEnterpriseRelationVOResult">
|
||||||
<id property="id" column="id"/>
|
<id property="id" column="id"/>
|
||||||
<result property="personId" column="person_id"/>
|
<result property="personId" column="person_id"/>
|
||||||
<result property="personName" column="person_name"/>
|
<result property="relationName" column="relation_name"/>
|
||||||
|
<result property="staffPersonId" column="staff_person_id"/>
|
||||||
|
<result property="staffPersonName" column="staff_person_name"/>
|
||||||
<result property="relationPersonPost" column="relation_person_post"/>
|
<result property="relationPersonPost" column="relation_person_post"/>
|
||||||
<result property="socialCreditCode" column="social_credit_code"/>
|
<result property="socialCreditCode" column="social_credit_code"/>
|
||||||
<result property="enterpriseName" column="enterprise_name"/>
|
<result property="enterpriseName" column="enterprise_name"/>
|
||||||
@@ -28,17 +30,28 @@
|
|||||||
<!-- 分页查询员工实体关系列表 -->
|
<!-- 分页查询员工实体关系列表 -->
|
||||||
<select id="selectRelationPage" resultMap="CcdiStaffEnterpriseRelationVOResult">
|
<select id="selectRelationPage" resultMap="CcdiStaffEnterpriseRelationVOResult">
|
||||||
SELECT
|
SELECT
|
||||||
ser.id, ser.person_id, bs.name as person_name, ser.relation_person_post,
|
ser.id, ser.person_id, sfr.relation_name, sfr.person_id AS staff_person_id, bs.name AS staff_person_name,
|
||||||
|
ser.relation_person_post,
|
||||||
ser.social_credit_code, ser.enterprise_name, ser.status, ser.remark,
|
ser.social_credit_code, ser.enterprise_name, ser.status, ser.remark,
|
||||||
ser.data_source, ser.is_employee, ser.is_emp_family, ser.is_customer,
|
ser.data_source, ser.is_employee, ser.is_emp_family, ser.is_customer,
|
||||||
ser.is_cust_family, ser.created_by, ser.create_time, ser.updated_by,
|
ser.is_cust_family, ser.created_by, ser.create_time, ser.updated_by,
|
||||||
ser.update_time
|
ser.update_time
|
||||||
FROM ccdi_staff_enterprise_relation ser
|
FROM ccdi_staff_enterprise_relation ser
|
||||||
LEFT JOIN ccdi_base_staff bs ON ser.person_id = bs.id_card
|
LEFT JOIN ccdi_staff_fmy_relation sfr
|
||||||
|
ON ser.person_id = sfr.relation_cert_no
|
||||||
|
AND sfr.is_emp_family = 1
|
||||||
|
LEFT JOIN ccdi_base_staff bs ON sfr.person_id = bs.id_card
|
||||||
<where>
|
<where>
|
||||||
<if test="query.personId != null and query.personId != ''">
|
<if test="query.personId != null and query.personId != ''">
|
||||||
AND ser.person_id LIKE CONCAT('%', #{query.personId}, '%')
|
AND ser.person_id LIKE CONCAT('%', #{query.personId}, '%')
|
||||||
</if>
|
</if>
|
||||||
|
<if test="query.relationName != null and query.relationName != ''">
|
||||||
|
AND sfr.relation_name LIKE CONCAT('%', #{query.relationName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="query.staffPersonName != null and query.staffPersonName != ''">
|
||||||
|
AND (sfr.person_id LIKE CONCAT('%', #{query.staffPersonName}, '%')
|
||||||
|
OR bs.name LIKE CONCAT('%', #{query.staffPersonName}, '%'))
|
||||||
|
</if>
|
||||||
<if test="query.socialCreditCode != null and query.socialCreditCode != ''">
|
<if test="query.socialCreditCode != null and query.socialCreditCode != ''">
|
||||||
AND ser.social_credit_code LIKE CONCAT('%', #{query.socialCreditCode}, '%')
|
AND ser.social_credit_code LIKE CONCAT('%', #{query.socialCreditCode}, '%')
|
||||||
</if>
|
</if>
|
||||||
@@ -55,16 +68,40 @@
|
|||||||
<!-- 查询员工实体关系详情 -->
|
<!-- 查询员工实体关系详情 -->
|
||||||
<select id="selectRelationById" resultMap="CcdiStaffEnterpriseRelationVOResult">
|
<select id="selectRelationById" resultMap="CcdiStaffEnterpriseRelationVOResult">
|
||||||
SELECT
|
SELECT
|
||||||
ser.id, ser.person_id, bs.name as person_name, ser.relation_person_post,
|
ser.id, ser.person_id, sfr.relation_name, sfr.person_id AS staff_person_id, bs.name AS staff_person_name,
|
||||||
|
ser.relation_person_post,
|
||||||
ser.social_credit_code, ser.enterprise_name, ser.status, ser.remark,
|
ser.social_credit_code, ser.enterprise_name, ser.status, ser.remark,
|
||||||
ser.data_source, ser.is_employee, ser.is_emp_family, ser.is_customer,
|
ser.data_source, ser.is_employee, ser.is_emp_family, ser.is_customer,
|
||||||
ser.is_cust_family, ser.created_by, ser.create_time, ser.updated_by,
|
ser.is_cust_family, ser.created_by, ser.create_time, ser.updated_by,
|
||||||
ser.update_time
|
ser.update_time
|
||||||
FROM ccdi_staff_enterprise_relation ser
|
FROM ccdi_staff_enterprise_relation ser
|
||||||
LEFT JOIN ccdi_base_staff bs ON ser.person_id = bs.id_card
|
LEFT JOIN ccdi_staff_fmy_relation sfr
|
||||||
|
ON ser.person_id = sfr.relation_cert_no
|
||||||
|
AND sfr.is_emp_family = 1
|
||||||
|
LEFT JOIN ccdi_base_staff bs ON sfr.person_id = bs.id_card
|
||||||
WHERE ser.id = #{id}
|
WHERE ser.id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询有效员工亲属下拉选项 -->
|
||||||
|
<select id="selectFamilyOptions" resultType="com.ruoyi.info.collection.domain.vo.CcdiStaffEnterpriseRelationOptionVO">
|
||||||
|
SELECT
|
||||||
|
sfr.relation_cert_no AS relationCertNo,
|
||||||
|
sfr.relation_name AS relationName,
|
||||||
|
sfr.person_id AS staffPersonId,
|
||||||
|
bs.name AS staffPersonName
|
||||||
|
FROM ccdi_staff_fmy_relation sfr
|
||||||
|
LEFT JOIN ccdi_base_staff bs ON sfr.person_id = bs.id_card
|
||||||
|
<where>
|
||||||
|
sfr.is_emp_family = 1
|
||||||
|
AND sfr.status = 1
|
||||||
|
<if test="query != null and query != ''">
|
||||||
|
AND sfr.relation_cert_no LIKE CONCAT('%', #{query}, '%')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY sfr.create_time DESC
|
||||||
|
LIMIT 100
|
||||||
|
</select>
|
||||||
|
|
||||||
<!-- 判断身份证号和统一社会信用代码的组合是否已存在 -->
|
<!-- 判断身份证号和统一社会信用代码的组合是否已存在 -->
|
||||||
<select id="existsByPersonIdAndSocialCreditCode" resultType="boolean">
|
<select id="existsByPersonIdAndSocialCreditCode" resultType="boolean">
|
||||||
SELECT COUNT(1) > 0
|
SELECT COUNT(1) > 0
|
||||||
@@ -84,6 +121,14 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<update id="invalidateByFamilyCertNo">
|
||||||
|
UPDATE ccdi_staff_enterprise_relation
|
||||||
|
SET status = 0,
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE person_id = #{personId}
|
||||||
|
AND status != 0
|
||||||
|
</update>
|
||||||
|
|
||||||
<!-- 批量插入员工实体关系数据 -->
|
<!-- 批量插入员工实体关系数据 -->
|
||||||
<insert id="insertBatch">
|
<insert id="insertBatch">
|
||||||
INSERT INTO ccdi_staff_enterprise_relation
|
INSERT INTO ccdi_staff_enterprise_relation
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
<result property="posCategory" column="pos_category"/>
|
<result property="posCategory" column="pos_category"/>
|
||||||
<result property="posDesc" column="pos_desc"/>
|
<result property="posDesc" column="pos_desc"/>
|
||||||
<result property="candName" column="cand_name"/>
|
<result property="candName" column="cand_name"/>
|
||||||
|
<result property="recruitType" column="recruit_type"/>
|
||||||
<result property="candEdu" column="cand_edu"/>
|
<result property="candEdu" column="cand_edu"/>
|
||||||
<result property="candId" column="cand_id"/>
|
<result property="candId" column="cand_id"/>
|
||||||
<result property="candSchool" column="cand_school"/>
|
<result property="candSchool" column="cand_school"/>
|
||||||
<result property="candMajor" column="cand_major"/>
|
<result property="candMajor" column="cand_major"/>
|
||||||
<result property="candGrad" column="cand_grad"/>
|
<result property="candGrad" column="cand_grad"/>
|
||||||
<result property="admitStatus" column="admit_status"/>
|
<result property="admitStatus" column="admit_status"/>
|
||||||
|
<result property="workExperienceCount" column="work_experience_count"/>
|
||||||
<result property="interviewerName1" column="interviewer_name1"/>
|
<result property="interviewerName1" column="interviewer_name1"/>
|
||||||
<result property="interviewerId1" column="interviewer_id1"/>
|
<result property="interviewerId1" column="interviewer_id1"/>
|
||||||
<result property="interviewerName2" column="interviewer_name2"/>
|
<result property="interviewerName2" column="interviewer_name2"/>
|
||||||
@@ -31,44 +33,53 @@
|
|||||||
<!-- 分页查询招聘信息列表 -->
|
<!-- 分页查询招聘信息列表 -->
|
||||||
<select id="selectRecruitmentPage" resultMap="CcdiStaffRecruitmentVOResult">
|
<select id="selectRecruitmentPage" resultMap="CcdiStaffRecruitmentVOResult">
|
||||||
SELECT
|
SELECT
|
||||||
recruit_id, recruit_name, pos_name, pos_category, pos_desc,
|
r.recruit_id, r.recruit_name, r.pos_name, r.pos_category, r.pos_desc,
|
||||||
cand_name, cand_edu, cand_id, cand_school, cand_major, cand_grad,
|
r.cand_name, r.recruit_type, r.cand_edu, r.cand_id, r.cand_school, r.cand_major, r.cand_grad,
|
||||||
admit_status, interviewer_name1, interviewer_id1, interviewer_name2, interviewer_id2,
|
r.admit_status, COALESCE(w.work_experience_count, 0) AS work_experience_count,
|
||||||
created_by, create_time, updated_by, update_time
|
r.interviewer_name1, r.interviewer_id1, r.interviewer_name2, r.interviewer_id2,
|
||||||
FROM ccdi_staff_recruitment
|
r.created_by, r.create_time, r.updated_by, r.update_time
|
||||||
|
FROM ccdi_staff_recruitment r
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT recruit_id COLLATE utf8mb4_general_ci AS recruit_id, COUNT(1) AS work_experience_count
|
||||||
|
FROM ccdi_staff_recruitment_work
|
||||||
|
GROUP BY recruit_id COLLATE utf8mb4_general_ci
|
||||||
|
) 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 recruit_name LIKE CONCAT('%', #{query.recruitName}, '%')
|
AND r.recruit_name LIKE CONCAT('%', #{query.recruitName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="query.posName != null and query.posName != ''">
|
<if test="query.posName != null and query.posName != ''">
|
||||||
AND pos_name LIKE CONCAT('%', #{query.posName}, '%')
|
AND r.pos_name LIKE CONCAT('%', #{query.posName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="query.candName != null and query.candName != ''">
|
<if test="query.candName != null and query.candName != ''">
|
||||||
AND cand_name LIKE CONCAT('%', #{query.candName}, '%')
|
AND r.cand_name LIKE CONCAT('%', #{query.candName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="query.recruitType != null and query.recruitType != ''">
|
||||||
|
AND r.recruit_type = #{query.recruitType}
|
||||||
</if>
|
</if>
|
||||||
<if test="query.candId != null and query.candId != ''">
|
<if test="query.candId != null and query.candId != ''">
|
||||||
AND cand_id = #{query.candId}
|
AND r.cand_id = #{query.candId}
|
||||||
</if>
|
</if>
|
||||||
<if test="query.admitStatus != null and query.admitStatus != ''">
|
<if test="query.admitStatus != null and query.admitStatus != ''">
|
||||||
AND admit_status = #{query.admitStatus}
|
AND r.admit_status = #{query.admitStatus}
|
||||||
</if>
|
</if>
|
||||||
<if test="query.interviewerName != null and query.interviewerName != ''">
|
<if test="query.interviewerName != null and query.interviewerName != ''">
|
||||||
AND (interviewer_name1 LIKE CONCAT('%', #{query.interviewerName}, '%')
|
AND (r.interviewer_name1 LIKE CONCAT('%', #{query.interviewerName}, '%')
|
||||||
OR interviewer_name2 LIKE CONCAT('%', #{query.interviewerName}, '%'))
|
OR r.interviewer_name2 LIKE CONCAT('%', #{query.interviewerName}, '%'))
|
||||||
</if>
|
</if>
|
||||||
<if test="query.interviewerId != null and query.interviewerId != ''">
|
<if test="query.interviewerId != null and query.interviewerId != ''">
|
||||||
AND (interviewer_id1 = #{query.interviewerId}
|
AND (r.interviewer_id1 = #{query.interviewerId}
|
||||||
OR interviewer_id2 = #{query.interviewerId})
|
OR r.interviewer_id2 = #{query.interviewerId})
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
ORDER BY create_time DESC
|
ORDER BY r.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 查询招聘信息详情 -->
|
<!-- 查询招聘信息详情 -->
|
||||||
<select id="selectRecruitmentById" resultMap="CcdiStaffRecruitmentVOResult">
|
<select id="selectRecruitmentById" resultMap="CcdiStaffRecruitmentVOResult">
|
||||||
SELECT
|
SELECT
|
||||||
recruit_id, recruit_name, pos_name, pos_category, pos_desc,
|
recruit_id, recruit_name, pos_name, pos_category, pos_desc,
|
||||||
cand_name, 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
|
||||||
@@ -79,13 +90,13 @@
|
|||||||
<insert id="insertBatch">
|
<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, 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)
|
||||||
VALUES
|
VALUES
|
||||||
<foreach collection="list" item="item" separator=",">
|
<foreach collection="list" item="item" separator=",">
|
||||||
(#{item.recruitId}, #{item.recruitName}, #{item.posName}, #{item.posCategory}, #{item.posDesc},
|
(#{item.recruitId}, #{item.recruitName}, #{item.posName}, #{item.posCategory}, #{item.posDesc},
|
||||||
#{item.candName}, #{item.candEdu}, #{item.candId}, #{item.candSchool}, #{item.candMajor}, #{item.candGrad},
|
#{item.candName}, #{item.recruitType}, #{item.candEdu}, #{item.candId}, #{item.candSchool}, #{item.candMajor}, #{item.candGrad},
|
||||||
#{item.admitStatus}, #{item.interviewerName1}, #{item.interviewerId1}, #{item.interviewerName2}, #{item.interviewerId2},
|
#{item.admitStatus}, #{item.interviewerName1}, #{item.interviewerId1}, #{item.interviewerName2}, #{item.interviewerId2},
|
||||||
#{item.createdBy}, NOW(), #{item.updatedBy}, NOW())
|
#{item.createdBy}, NOW(), #{item.updatedBy}, NOW())
|
||||||
</foreach>
|
</foreach>
|
||||||
@@ -100,6 +111,7 @@
|
|||||||
pos_category = #{item.posCategory},
|
pos_category = #{item.posCategory},
|
||||||
pos_desc = #{item.posDesc},
|
pos_desc = #{item.posDesc},
|
||||||
cand_name = #{item.candName},
|
cand_name = #{item.candName},
|
||||||
|
recruit_type = #{item.recruitType},
|
||||||
cand_edu = #{item.candEdu},
|
cand_edu = #{item.candEdu},
|
||||||
cand_id = #{item.candId},
|
cand_id = #{item.candId},
|
||||||
cand_school = #{item.candSchool},
|
cand_school = #{item.candSchool},
|
||||||
|
|||||||
@@ -96,8 +96,12 @@ class CcdiAssetInfoControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void getImportFailures_shouldReturnPagedRows() {
|
void getImportFailures_shouldReturnPagedRows() {
|
||||||
AssetImportFailureVO failure1 = new AssetImportFailureVO();
|
AssetImportFailureVO failure1 = new AssetImportFailureVO();
|
||||||
|
failure1.setSheetName("亲属资产信息");
|
||||||
|
failure1.setRowNum(2);
|
||||||
failure1.setPersonId("A1");
|
failure1.setPersonId("A1");
|
||||||
AssetImportFailureVO failure2 = new AssetImportFailureVO();
|
AssetImportFailureVO failure2 = new AssetImportFailureVO();
|
||||||
|
failure2.setSheetName("亲属资产信息");
|
||||||
|
failure2.setRowNum(3);
|
||||||
failure2.setPersonId("A2");
|
failure2.setPersonId("A2");
|
||||||
when(assetInfoImportService.getImportFailures("task-3")).thenReturn(List.of(failure1, failure2));
|
when(assetInfoImportService.getImportFailures("task-3")).thenReturn(List.of(failure1, failure2));
|
||||||
|
|
||||||
@@ -105,7 +109,10 @@ class CcdiAssetInfoControllerTest {
|
|||||||
|
|
||||||
assertEquals(2, result.getTotal());
|
assertEquals(2, result.getTotal());
|
||||||
assertEquals(1, result.getRows().size());
|
assertEquals(1, result.getRows().size());
|
||||||
assertEquals("A2", ((AssetImportFailureVO) result.getRows().get(0)).getPersonId());
|
AssetImportFailureVO row = (AssetImportFailureVO) result.getRows().get(0);
|
||||||
|
assertEquals("亲属资产信息", row.getSheetName());
|
||||||
|
assertEquals(3, row.getRowNum());
|
||||||
|
assertEquals("A2", row.getPersonId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user