员工亲属实体关联
This commit is contained in:
@@ -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.CcdiBaseStaffEditDTO;
|
||||
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.vo.*;
|
||||
import com.ruoyi.info.collection.service.ICcdiBaseStaffAssetImportService;
|
||||
import com.ruoyi.info.collection.service.ICcdiBaseStaffImportService;
|
||||
import com.ruoyi.info.collection.service.ICcdiBaseStaffService;
|
||||
import com.ruoyi.info.collection.utils.EasyExcelUtil;
|
||||
@@ -45,6 +47,9 @@ public class CcdiBaseStaffController extends BaseController {
|
||||
@Resource
|
||||
private ICcdiBaseStaffImportService importAsyncService;
|
||||
|
||||
@Resource
|
||||
private ICcdiBaseStaffAssetImportService baseStaffAssetImportService;
|
||||
|
||||
/**
|
||||
* 查询员工列表
|
||||
*/
|
||||
@@ -120,7 +125,14 @@ public class CcdiBaseStaffController extends BaseController {
|
||||
@Operation(summary = "下载导入模板")
|
||||
@PostMapping("/importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiBaseStaffExcel.class, "员工信息");
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||
response,
|
||||
CcdiBaseStaffExcel.class,
|
||||
"员工信息",
|
||||
CcdiBaseStaffAssetInfoExcel.class,
|
||||
"员工资产信息",
|
||||
"员工信息维护导入模板"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,21 +142,33 @@ public class CcdiBaseStaffController extends BaseController {
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:baseStaff:import')")
|
||||
@Log(title = "员工信息", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importData")
|
||||
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
|
||||
List<CcdiBaseStaffExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiBaseStaffExcel.class);
|
||||
public AjaxResult importData(MultipartFile file) throws Exception {
|
||||
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("至少需要一条数据");
|
||||
}
|
||||
|
||||
// 提交异步任务
|
||||
String taskId = baseStaffService.importBaseStaff(list, updateSupport);
|
||||
|
||||
// 立即返回,不等待后台任务完成
|
||||
ImportResultVO result = new ImportResultVO();
|
||||
result.setTaskId(taskId);
|
||||
result.setStatus("PROCESSING");
|
||||
result.setMessage("导入任务已提交,正在后台处理");
|
||||
BaseStaffImportSubmitResultVO result = new BaseStaffImportSubmitResultVO();
|
||||
if (hasStaffRows) {
|
||||
result.setStaffTaskId(baseStaffService.importBaseStaff(staffList));
|
||||
}
|
||||
if (hasAssetRows) {
|
||||
result.setAssetTaskId(baseStaffAssetImportService.importAssetInfo(assetList));
|
||||
}
|
||||
result.setMessage(buildImportSubmitMessage(hasStaffRows, hasAssetRows));
|
||||
|
||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
||||
}
|
||||
@@ -190,4 +214,14 @@ public class CcdiBaseStaffController extends BaseController {
|
||||
|
||||
return getDataTable(pageData, failures.size());
|
||||
}
|
||||
|
||||
private String buildImportSubmitMessage(boolean hasStaffRows, boolean hasAssetRows) {
|
||||
if (hasStaffRows && hasAssetRows) {
|
||||
return "已提交员工信息和员工资产信息导入任务";
|
||||
}
|
||||
if (hasStaffRows) {
|
||||
return "已提交员工信息导入任务";
|
||||
}
|
||||
return "已提交员工资产信息导入任务";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.CcdiStaffFmyRelationEditDTO;
|
||||
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.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.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.ICcdiStaffFmyRelationService;
|
||||
import com.ruoyi.info.collection.utils.EasyExcelUtil;
|
||||
@@ -49,6 +51,9 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
||||
@Resource
|
||||
private ICcdiStaffFmyRelationImportService relationImportService;
|
||||
|
||||
@Resource
|
||||
private ICcdiAssetInfoImportService assetInfoImportService;
|
||||
|
||||
/**
|
||||
* 查询员工亲属关系列表
|
||||
*/
|
||||
@@ -115,7 +120,14 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
||||
@Operation(summary = "下载导入模板")
|
||||
@PostMapping("/importTemplate")
|
||||
public void importTemplate(HttpServletResponse response) {
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiStaffFmyRelationExcel.class, "员工亲属关系信息");
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(
|
||||
response,
|
||||
CcdiStaffFmyRelationExcel.class,
|
||||
"员工亲属关系信息",
|
||||
CcdiAssetInfoExcel.class,
|
||||
"亲属资产信息",
|
||||
"员工亲属关系维护导入模板"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,20 +139,32 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
||||
@Log(title = "员工亲属关系", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importData")
|
||||
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("至少需要一条数据");
|
||||
}
|
||||
|
||||
// 提交异步任务
|
||||
String taskId = relationService.importRelation(list);
|
||||
|
||||
// 立即返回,不等待后台任务完成
|
||||
ImportResultVO result = new ImportResultVO();
|
||||
result.setTaskId(taskId);
|
||||
result.setStatus("PROCESSING");
|
||||
result.setMessage("导入任务已提交,正在后台处理");
|
||||
StaffFmyRelationImportSubmitResultVO result = new StaffFmyRelationImportSubmitResultVO();
|
||||
if (hasRelationRows) {
|
||||
result.setRelationTaskId(relationService.importRelation(relationList));
|
||||
}
|
||||
if (hasAssetRows) {
|
||||
result.setAssetTaskId(assetInfoImportService.importAssetInfo(assetList));
|
||||
}
|
||||
result.setMessage(buildImportSubmitMessage(hasRelationRows, hasAssetRows));
|
||||
|
||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
||||
}
|
||||
@@ -186,4 +210,14 @@ public class CcdiStaffFmyRelationController extends BaseController {
|
||||
|
||||
return getDataTable(pageData, failures.size());
|
||||
}
|
||||
|
||||
private String buildImportSubmitMessage(boolean hasRelationRows, boolean hasAssetRows) {
|
||||
if (hasRelationRows && hasAssetRows) {
|
||||
return "已提交员工亲属关系和亲属资产信息导入任务";
|
||||
}
|
||||
if (hasRelationRows) {
|
||||
return "已提交员工亲属关系导入任务";
|
||||
}
|
||||
return "已提交亲属资产信息导入任务";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package com.ruoyi.info.collection.domain.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
@@ -20,29 +18,19 @@ public class CcdiPurchaseTransactionSupplierDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotBlank(message = "供应商名称不能为空")
|
||||
@Size(max = 200, message = "供应商名称长度不能超过200个字符")
|
||||
@Schema(description = "供应商名称")
|
||||
private String supplierName;
|
||||
|
||||
@Pattern(
|
||||
regexp = "^$|^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$",
|
||||
message = "供应商统一信用代码格式不正确"
|
||||
)
|
||||
@NotBlank(message = "供应商统一信用代码不能为空")
|
||||
@Schema(description = "供应商统一信用代码")
|
||||
private String supplierUscc;
|
||||
|
||||
@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;
|
||||
|
||||
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
|
||||
@Schema(description = "供应商银行账户")
|
||||
private String supplierBankAccount;
|
||||
|
||||
|
||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
||||
@Schema(description = "亲属资产信息导入失败记录")
|
||||
public class AssetImportFailureVO {
|
||||
|
||||
/** Sheet名称 */
|
||||
@Schema(description = "Sheet名称")
|
||||
private String sheetName;
|
||||
|
||||
/** Excel行号 */
|
||||
@Schema(description = "Excel行号")
|
||||
private Integer rowNum;
|
||||
|
||||
/** 亲属证件号 */
|
||||
@Schema(description = "亲属证件号")
|
||||
private String personId;
|
||||
|
||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
||||
@Schema(description = "员工资产信息导入失败记录")
|
||||
public class BaseStaffAssetImportFailureVO {
|
||||
|
||||
/** Sheet名称 */
|
||||
@Schema(description = "Sheet名称")
|
||||
private String sheetName;
|
||||
|
||||
/** Excel行号 */
|
||||
@Schema(description = "Excel行号")
|
||||
private Integer rowNum;
|
||||
|
||||
/** 员工身份证号 */
|
||||
@Schema(description = "员工身份证号")
|
||||
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;
|
||||
}
|
||||
@@ -14,8 +14,14 @@ import java.math.BigDecimal;
|
||||
@Schema(description = "导入失败记录")
|
||||
public class ImportFailureVO {
|
||||
|
||||
@Schema(description = "Sheet名称")
|
||||
private String sheetName;
|
||||
|
||||
@Schema(description = "Excel行号")
|
||||
private Integer rowNum;
|
||||
|
||||
@Schema(description = "柜员号")
|
||||
private Long employeeId;
|
||||
private Long staffId;
|
||||
|
||||
@Schema(description = "姓名")
|
||||
private String name;
|
||||
|
||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
||||
@Schema(description = "招投标信息导入失败记录")
|
||||
public class PurchaseTransactionImportFailureVO {
|
||||
|
||||
/** 失败来源Sheet */
|
||||
@Schema(description = "失败来源Sheet")
|
||||
private String sheetName;
|
||||
|
||||
/** 失败行号 */
|
||||
@Schema(description = "失败行号")
|
||||
private String sheetRowNum;
|
||||
|
||||
/** 采购事项ID */
|
||||
@Schema(description = "采购事项ID")
|
||||
private String purchaseId;
|
||||
|
||||
@@ -15,6 +15,14 @@ import java.math.BigDecimal;
|
||||
@Schema(description = "员工亲属关系信息导入失败记录")
|
||||
public class StaffFmyRelationImportFailureVO {
|
||||
|
||||
/** Sheet名称 */
|
||||
@Schema(description = "Sheet名称")
|
||||
private String sheetName;
|
||||
|
||||
/** Excel行号 */
|
||||
@Schema(description = "Excel行号")
|
||||
private Integer rowNum;
|
||||
|
||||
/** 员工身份证号 */
|
||||
@Schema(description = "员工身份证号")
|
||||
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;
|
||||
}
|
||||
@@ -15,10 +15,9 @@ public interface ICcdiBaseStaffImportService {
|
||||
/**
|
||||
* 异步导入员工数据
|
||||
*
|
||||
* @param excelList Excel数据列表
|
||||
* @param isUpdateSupport 是否更新已存在的数据
|
||||
* @param excelList Excel数据列表
|
||||
*/
|
||||
void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport, String taskId);
|
||||
void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId);
|
||||
|
||||
/**
|
||||
* 查询导入状态
|
||||
|
||||
@@ -78,11 +78,10 @@ public interface ICcdiBaseStaffService {
|
||||
/**
|
||||
* 导入员工数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @param excelList Excel实体列表
|
||||
* @return 结果
|
||||
*/
|
||||
String importBaseStaff(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport);
|
||||
String importBaseStaff(List<CcdiBaseStaffExcel> excelList);
|
||||
|
||||
/**
|
||||
* 查询员工下拉列表
|
||||
|
||||
@@ -39,6 +39,8 @@ import java.util.concurrent.TimeUnit;
|
||||
public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportService {
|
||||
|
||||
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
|
||||
private CcdiAssetInfoMapper assetInfoMapper;
|
||||
@@ -91,7 +93,8 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
|
||||
|
||||
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 {
|
||||
validateExcel(excel);
|
||||
Set<String> familyIds = ownerMap.get(excel.getPersonId());
|
||||
@@ -111,6 +114,8 @@ public class CcdiAssetInfoImportServiceImpl implements ICcdiAssetInfoImportServi
|
||||
} catch (Exception e) {
|
||||
AssetImportFailureVO failureVO = new AssetImportFailureVO();
|
||||
BeanUtils.copyProperties(excel, failureVO);
|
||||
failureVO.setSheetName(SHEET_NAME);
|
||||
failureVO.setRowNum(i + EXCEL_DATA_START_ROW);
|
||||
failureVO.setErrorMessage(e.getMessage());
|
||||
failures.add(failureVO);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.info.collection.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.info.collection.domain.CcdiAssetInfo;
|
||||
@@ -90,14 +91,24 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
||||
.toList();
|
||||
|
||||
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 {
|
||||
validateExcel(excel);
|
||||
Set<String> familyIds = ownerMap.get(excel.getPersonId());
|
||||
if (familyIds == null || familyIds.isEmpty()) {
|
||||
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();
|
||||
BeanUtils.copyProperties(excel, assetInfo);
|
||||
@@ -109,6 +120,8 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
||||
} catch (Exception e) {
|
||||
BaseStaffAssetImportFailureVO failureVO = new BaseStaffAssetImportFailureVO();
|
||||
BeanUtils.copyProperties(excel, failureVO);
|
||||
failureVO.setSheetName("员工资产信息");
|
||||
failureVO.setRowNum(i + 2);
|
||||
failureVO.setErrorMessage(e.getMessage());
|
||||
failures.add(failureVO);
|
||||
}
|
||||
@@ -168,6 +181,18 @@ public class CcdiBaseStaffAssetImportServiceImpl implements ICcdiBaseStaffAssetI
|
||||
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) {
|
||||
if (mappings == null) {
|
||||
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) {
|
||||
Map<String, Object> statusData = new HashMap<>();
|
||||
statusData.put("status", status);
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
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.dto.CcdiBaseStaffAddDTO;
|
||||
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.common.utils.IdCardUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -43,16 +45,18 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource
|
||||
private SysDeptMapper deptMapper;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport, String taskId) {
|
||||
public void importBaseStaffAsync(List<CcdiBaseStaffExcel> excelList, String taskId) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 记录导入开始
|
||||
ImportLogUtils.logImportStart(log, taskId, "员工基础信息", excelList.size(), "系统");
|
||||
|
||||
List<CcdiBaseStaff> newRecords = new ArrayList<>();
|
||||
List<CcdiBaseStaff> updateRecords = new ArrayList<>();
|
||||
List<ImportFailureVO> failures = new ArrayList<>();
|
||||
|
||||
// 批量查询已存在的员工ID和身份证号
|
||||
@@ -75,13 +79,12 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
CcdiBaseStaffAddDTO addDTO = new CcdiBaseStaffAddDTO();
|
||||
BeanUtils.copyProperties(excel, addDTO);
|
||||
|
||||
// 验证数据(支持更新模式)
|
||||
validateStaffData(addDTO, isUpdateSupport, existingIds, existingIdCards);
|
||||
validateStaffData(addDTO, existingIds, existingIdCards);
|
||||
|
||||
CcdiBaseStaff staff = new CcdiBaseStaff();
|
||||
BeanUtils.copyProperties(excel, staff);
|
||||
|
||||
// 统一检查Excel内重复(更新和新增两个分支都需要检查)
|
||||
// 统一检查Excel内重复
|
||||
if (processedStaffIds.contains(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()));
|
||||
}
|
||||
|
||||
// 检查员工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) {
|
||||
@@ -115,11 +105,13 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
|
||||
// 记录进度
|
||||
ImportLogUtils.logProgress(log, taskId, i + 1, excelList.size(),
|
||||
newRecords.size() + updateRecords.size(), failures.size());
|
||||
newRecords.size(), failures.size());
|
||||
|
||||
} catch (Exception e) {
|
||||
ImportFailureVO failure = new ImportFailureVO();
|
||||
BeanUtils.copyProperties(excel, failure);
|
||||
failure.setSheetName("员工信息");
|
||||
failure.setRowNum(i + 2);
|
||||
failure.setErrorMessage(e.getMessage());
|
||||
failures.add(failure);
|
||||
|
||||
@@ -137,13 +129,6 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
saveBatch(newRecords, 500);
|
||||
}
|
||||
|
||||
// 批量更新已有数据(先删除再插入)
|
||||
if (!updateRecords.isEmpty() && isUpdateSupport) {
|
||||
ImportLogUtils.logBatchOperationStart(log, taskId, "更新",
|
||||
(updateRecords.size() + 499) / 500, 500);
|
||||
baseStaffMapper.insertOrUpdateBatch(updateRecords);
|
||||
}
|
||||
|
||||
// 保存失败记录到Redis
|
||||
if (!failures.isEmpty()) {
|
||||
try {
|
||||
@@ -157,7 +142,7 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
|
||||
ImportResult result = new ImportResult();
|
||||
result.setTotalCount(excelList.size());
|
||||
result.setSuccessCount(newRecords.size() + updateRecords.size());
|
||||
result.setSuccessCount(newRecords.size());
|
||||
result.setFailureCount(failures.size());
|
||||
|
||||
// 更新最终状态
|
||||
@@ -299,11 +284,10 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
* 验证员工数据
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
* @param isUpdateSupport 是否支持更新
|
||||
* @param existingIds 已存在的员工ID集合(导入场景使用,传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())) {
|
||||
throw new RuntimeException("姓名不能为空");
|
||||
@@ -326,6 +310,7 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
if (StringUtils.isEmpty(addDTO.getStatus())) {
|
||||
throw new RuntimeException("状态不能为空");
|
||||
}
|
||||
validateDeptId(addDTO.getDeptId());
|
||||
|
||||
// 验证身份证号格式
|
||||
String idCardError = IdCardUtil.getErrorMessage(addDTO.getIdCard());
|
||||
@@ -347,12 +332,11 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
throw new RuntimeException("该身份证号已存在");
|
||||
}
|
||||
} else {
|
||||
// 导入场景:如果员工ID不存在,才检查身份证号唯一性
|
||||
if (!existingIds.contains(addDTO.getStaffId())) {
|
||||
// 使用批量查询的结果检查身份证号唯一性
|
||||
if (existingIdCards != null && existingIdCards.contains(addDTO.getIdCard())) {
|
||||
throw new RuntimeException("该身份证号已存在");
|
||||
}
|
||||
if (existingIds.contains(addDTO.getStaffId())) {
|
||||
throw new RuntimeException("该员工ID已存在");
|
||||
}
|
||||
if (existingIdCards != null && existingIdCards.contains(addDTO.getIdCard())) {
|
||||
throw new RuntimeException("该身份证号已存在");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,4 +362,11 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,13 +211,12 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
/**
|
||||
* 导入员工数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @param excelList Excel实体列表
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public String importBaseStaff(List<CcdiBaseStaffExcel> excelList, Boolean isUpdateSupport) {
|
||||
public String importBaseStaff(List<CcdiBaseStaffExcel> excelList) {
|
||||
String taskId = UUID.randomUUID().toString();
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
@@ -236,7 +235,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
||||
redisTemplate.expire(statusKey, 7, java.util.concurrent.TimeUnit.DAYS);
|
||||
|
||||
importAsyncService.importBaseStaffAsync(excelList, isUpdateSupport, taskId);
|
||||
importAsyncService.importBaseStaffAsync(excelList, taskId);
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ import java.util.stream.Collectors;
|
||||
public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTransactionImportService {
|
||||
|
||||
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
|
||||
private CcdiPurchaseTransactionMapper transactionMapper;
|
||||
@@ -62,6 +65,8 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
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);
|
||||
|
||||
// 记录导入开始
|
||||
@@ -76,17 +81,17 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
Set<String> existingIds = getExistingPurchaseIds(safeMainList);
|
||||
ImportLogUtils.logBatchQueryComplete(log, taskId, "采购事项ID", existingIds.size());
|
||||
|
||||
Map<String, List<CcdiPurchaseTransactionExcel>> mainGroupMap = safeMainList.stream()
|
||||
.filter(item -> StringUtils.isNotEmpty(item.getPurchaseId()))
|
||||
Map<String, List<MainImportRow>> mainGroupMap = indexedMainRows.stream()
|
||||
.filter(item -> StringUtils.isNotEmpty(item.data().getPurchaseId()))
|
||||
.collect(Collectors.groupingBy(
|
||||
CcdiPurchaseTransactionExcel::getPurchaseId,
|
||||
item -> item.data().getPurchaseId(),
|
||||
LinkedHashMap::new,
|
||||
Collectors.toList()
|
||||
));
|
||||
Map<String, List<CcdiPurchaseTransactionSupplierExcel>> supplierGroupMap = safeSupplierList.stream()
|
||||
.filter(item -> StringUtils.isNotEmpty(item.getPurchaseId()))
|
||||
Map<String, List<SupplierImportRow>> supplierGroupMap = indexedSupplierRows.stream()
|
||||
.filter(item -> StringUtils.isNotEmpty(item.data().getPurchaseId()))
|
||||
.collect(Collectors.groupingBy(
|
||||
CcdiPurchaseTransactionSupplierExcel::getPurchaseId,
|
||||
item -> item.data().getPurchaseId(),
|
||||
LinkedHashMap::new,
|
||||
Collectors.toList()
|
||||
));
|
||||
@@ -94,34 +99,53 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
purchaseIds.addAll(mainGroupMap.keySet());
|
||||
purchaseIds.addAll(supplierGroupMap.keySet());
|
||||
|
||||
for (CcdiPurchaseTransactionSupplierExcel supplierExcel : safeSupplierList) {
|
||||
if (StringUtils.isEmpty(supplierExcel.getPurchaseId())) {
|
||||
failures.add(buildFailure(null, null, "供应商明细Sheet中的采购事项ID不能为空"));
|
||||
for (SupplierImportRow supplierExcel : indexedSupplierRows) {
|
||||
if (StringUtils.isEmpty(supplierExcel.data().getPurchaseId())) {
|
||||
failures.add(buildFailure(
|
||||
null,
|
||||
null,
|
||||
SUPPLIER_SHEET_NAME,
|
||||
String.valueOf(supplierExcel.sheetRowNum()),
|
||||
"供应商明细Sheet中的采购事项ID不能为空"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (String purchaseId : purchaseIds) {
|
||||
index++;
|
||||
List<CcdiPurchaseTransactionExcel> mainRows = mainGroupMap.getOrDefault(purchaseId, List.of());
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierRows = supplierGroupMap.getOrDefault(purchaseId, List.of());
|
||||
List<MainImportRow> mainRows = mainGroupMap.getOrDefault(purchaseId, List.of());
|
||||
List<SupplierImportRow> supplierRows = supplierGroupMap.getOrDefault(purchaseId, List.of());
|
||||
|
||||
try {
|
||||
if (existingIds.contains(purchaseId)) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]已存在,请勿重复导入", purchaseId));
|
||||
throw buildValidationException(
|
||||
MAIN_SHEET_NAME,
|
||||
extractMainRowNums(mainRows),
|
||||
String.format("采购事项ID[%s]已存在,请勿重复导入", purchaseId)
|
||||
);
|
||||
}
|
||||
if (mainRows.isEmpty()) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]缺少招投标主信息", purchaseId));
|
||||
throw buildValidationException(
|
||||
SUPPLIER_SHEET_NAME,
|
||||
extractSupplierRowNums(supplierRows),
|
||||
String.format("采购事项ID[%s]缺少招投标主信息", purchaseId)
|
||||
);
|
||||
}
|
||||
if (mainRows.size() > 1) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]在招投标主信息Sheet中重复", purchaseId));
|
||||
throw buildValidationException(
|
||||
MAIN_SHEET_NAME,
|
||||
extractMainRowNums(mainRows),
|
||||
String.format("采购事项ID[%s]在招投标主信息Sheet中重复", purchaseId)
|
||||
);
|
||||
}
|
||||
|
||||
CcdiPurchaseTransactionExcel mainExcel = mainRows.getFirst();
|
||||
MainImportRow mainRow = mainRows.getFirst();
|
||||
CcdiPurchaseTransactionExcel mainExcel = mainRow.data();
|
||||
CcdiPurchaseTransactionAddDTO addDTO = new CcdiPurchaseTransactionAddDTO();
|
||||
BeanUtils.copyProperties(mainExcel, addDTO);
|
||||
|
||||
validateTransactionData(addDTO);
|
||||
validateTransactionData(addDTO, mainRow.sheetRowNum());
|
||||
List<CcdiPurchaseTransactionSupplier> suppliers = buildSupplierEntities(purchaseId, supplierRows, userName);
|
||||
|
||||
CcdiPurchaseTransaction transaction = new CcdiPurchaseTransaction();
|
||||
@@ -137,8 +161,16 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
newTransactions.size(), failures.size());
|
||||
|
||||
} catch (Exception e) {
|
||||
CcdiPurchaseTransactionExcel mainExcel = mainRows.isEmpty() ? null : mainRows.getFirst();
|
||||
failures.add(buildFailure(mainExcel, purchaseId, e.getMessage()));
|
||||
MainImportRow mainRow = mainRows.isEmpty() ? null : mainRows.getFirst();
|
||||
CcdiPurchaseTransactionExcel mainExcel = mainRow == null ? null : mainRow.data();
|
||||
FailureMeta failureMeta = resolveFailureMeta(e, mainRows, supplierRows);
|
||||
failures.add(buildFailure(
|
||||
mainExcel,
|
||||
purchaseId,
|
||||
failureMeta.sheetName(),
|
||||
failureMeta.sheetRowNum(),
|
||||
e.getMessage()
|
||||
));
|
||||
|
||||
// 记录验证失败日志
|
||||
String keyData = String.format("采购事项ID=%s, 采购类别=%s, 标的物=%s",
|
||||
@@ -301,97 +333,99 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
*/
|
||||
private void validateTransactionData(CcdiPurchaseTransactionAddDTO addDTO) {
|
||||
private void validateTransactionData(CcdiPurchaseTransactionAddDTO addDTO, int sheetRowNum) {
|
||||
// 验证必填字段
|
||||
if (StringUtils.isEmpty(addDTO.getPurchaseId())) {
|
||||
throw new RuntimeException("采购事项ID不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购事项ID不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getPurchaseCategory())) {
|
||||
throw new RuntimeException("采购类别不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购类别不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getSubjectName())) {
|
||||
throw new RuntimeException("标的物名称不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "标的物名称不能为空");
|
||||
}
|
||||
if (addDTO.getPurchaseQty() == null) {
|
||||
throw new RuntimeException("采购数量不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购数量不能为空");
|
||||
}
|
||||
if (addDTO.getBudgetAmount() == null) {
|
||||
throw new RuntimeException("预算金额不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "预算金额不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getPurchaseMethod())) {
|
||||
throw new RuntimeException("采购方式不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购方式不能为空");
|
||||
}
|
||||
if (addDTO.getApplyDate() == null) {
|
||||
throw new RuntimeException("采购申请日期不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购申请日期不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getApplicantId())) {
|
||||
throw new RuntimeException("申请人工号不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请人工号不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getApplicantName())) {
|
||||
throw new RuntimeException("申请人姓名不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请人姓名不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getApplyDepartment())) {
|
||||
throw new RuntimeException("申请部门不能为空");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "申请部门不能为空");
|
||||
}
|
||||
|
||||
// 验证工号格式(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}$")) {
|
||||
throw new RuntimeException("采购负责人工号必须为7位数字");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "采购负责人工号必须为7位数字");
|
||||
}
|
||||
|
||||
// 验证金额非负
|
||||
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) {
|
||||
throw new RuntimeException("预算金额必须大于0");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "预算金额必须大于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) {
|
||||
throw new RuntimeException("实际采购金额必须大于0");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "实际采购金额必须大于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) {
|
||||
throw new RuntimeException("结算金额必须大于0");
|
||||
throw buildValidationException(MAIN_SHEET_NAME, List.of(sheetRowNum), "结算金额必须大于0");
|
||||
}
|
||||
}
|
||||
|
||||
private List<CcdiPurchaseTransactionSupplier> buildSupplierEntities(
|
||||
String purchaseId,
|
||||
List<CcdiPurchaseTransactionSupplierExcel> supplierRows,
|
||||
List<SupplierImportRow> supplierRows,
|
||||
String userName
|
||||
) {
|
||||
List<CcdiPurchaseTransactionSupplierExcel> normalizedRows = supplierRows == null
|
||||
List<SupplierImportRow> normalizedRows = supplierRows == null
|
||||
? List.of()
|
||||
: supplierRows.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(this::hasAnySupplierValue)
|
||||
.filter(item -> hasAnySupplierValue(item.data()))
|
||||
.toList();
|
||||
|
||||
long winnerCount = normalizedRows.stream()
|
||||
.filter(item -> parseIsBidWinner(item.getIsBidWinner()) == 1)
|
||||
.count();
|
||||
if (winnerCount > 1) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]存在多条中标供应商", purchaseId));
|
||||
}
|
||||
|
||||
Set<String> duplicateSupplierKeys = new LinkedHashSet<>();
|
||||
List<Integer> winnerRowNums = new ArrayList<>();
|
||||
Map<String, Integer> supplierKeyRowMap = new LinkedHashMap<>();
|
||||
List<CcdiPurchaseTransactionSupplier> result = new ArrayList<>();
|
||||
for (int i = 0; i < normalizedRows.size(); i++) {
|
||||
CcdiPurchaseTransactionSupplierExcel supplierRow = normalizedRows.get(i);
|
||||
validateSupplierRow(supplierRow);
|
||||
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());
|
||||
if (!duplicateSupplierKeys.add(duplicateKey)) {
|
||||
throw new RuntimeException(String.format("采购事项ID[%s]存在重复供应商", purchaseId));
|
||||
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();
|
||||
@@ -401,37 +435,45 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
supplier.setContactPerson(StringUtils.trimToNull(supplierRow.getContactPerson()));
|
||||
supplier.setContactPhone(StringUtils.trimToNull(supplierRow.getContactPhone()));
|
||||
supplier.setSupplierBankAccount(StringUtils.trimToNull(supplierRow.getSupplierBankAccount()));
|
||||
supplier.setIsBidWinner(parseIsBidWinner(supplierRow.getIsBidWinner()));
|
||||
supplier.setSortOrder(supplierRow.getSortOrder() == null ? i + 1 : supplierRow.getSortOrder());
|
||||
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 void validateSupplierRow(CcdiPurchaseTransactionSupplierExcel supplierRow) {
|
||||
private int validateSupplierRow(SupplierImportRow supplierImportRow) {
|
||||
CcdiPurchaseTransactionSupplierExcel supplierRow = supplierImportRow.data();
|
||||
if (StringUtils.isEmpty(supplierRow.getSupplierName())) {
|
||||
throw new RuntimeException("供应商名称不能为空");
|
||||
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商名称不能为空");
|
||||
}
|
||||
if (StringUtils.length(supplierRow.getSupplierName()) > 200) {
|
||||
throw new RuntimeException("供应商名称长度不能超过200个字符");
|
||||
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商名称长度不能超过200个字符");
|
||||
}
|
||||
if (StringUtils.length(supplierRow.getContactPerson()) > 50) {
|
||||
throw new RuntimeException("供应商联系人长度不能超过50个字符");
|
||||
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商联系人长度不能超过50个字符");
|
||||
}
|
||||
if (StringUtils.length(supplierRow.getSupplierBankAccount()) > 50) {
|
||||
throw new RuntimeException("供应商银行账户长度不能超过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 new RuntimeException("供应商联系电话格式不正确");
|
||||
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 new RuntimeException("供应商统一信用代码格式不正确");
|
||||
throw buildValidationException(SUPPLIER_SHEET_NAME, List.of(supplierImportRow.sheetRowNum()), "供应商统一信用代码格式不正确");
|
||||
}
|
||||
parseIsBidWinner(supplierRow.getIsBidWinner());
|
||||
return parseIsBidWinner(supplierRow.getIsBidWinner(), supplierImportRow.sheetRowNum());
|
||||
}
|
||||
|
||||
private boolean hasAnySupplierValue(CcdiPurchaseTransactionSupplierExcel supplierRow) {
|
||||
@@ -445,7 +487,7 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
|| supplierRow.getSortOrder() != null;
|
||||
}
|
||||
|
||||
private int parseIsBidWinner(String rawValue) {
|
||||
private int parseIsBidWinner(String rawValue, Integer sheetRowNum) {
|
||||
if (StringUtils.isEmpty(rawValue)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -458,7 +500,11 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
|| "FALSE".equalsIgnoreCase(normalized)) {
|
||||
return 0;
|
||||
}
|
||||
throw new RuntimeException("是否中标仅支持填写“是/否”或“1/0”");
|
||||
throw buildValidationException(
|
||||
SUPPLIER_SHEET_NAME,
|
||||
sheetRowNum == null ? List.of() : List.of(sheetRowNum),
|
||||
"是否中标仅支持填写“是/否”或“1/0”"
|
||||
);
|
||||
}
|
||||
|
||||
private void fillWinnerSummary(
|
||||
@@ -487,12 +533,16 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
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);
|
||||
}
|
||||
@@ -519,4 +569,87 @@ public class CcdiPurchaseTransactionImportServiceImpl implements ICcdiPurchaseTr
|
||||
);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ import java.util.stream.Collectors;
|
||||
public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelationImportService {
|
||||
|
||||
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
|
||||
private CcdiStaffFmyRelationMapper relationMapper;
|
||||
@@ -168,6 +170,8 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
|
||||
} catch (Exception e) {
|
||||
StaffFmyRelationImportFailureVO failure = new StaffFmyRelationImportFailureVO();
|
||||
BeanUtils.copyProperties(excel, failure);
|
||||
failure.setSheetName(SHEET_NAME);
|
||||
failure.setRowNum(i + EXCEL_DATA_START_ROW);
|
||||
failure.setErrorMessage(e.getMessage());
|
||||
failures.add(failure);
|
||||
|
||||
|
||||
@@ -96,8 +96,12 @@ class CcdiAssetInfoControllerTest {
|
||||
@Test
|
||||
void getImportFailures_shouldReturnPagedRows() {
|
||||
AssetImportFailureVO failure1 = new AssetImportFailureVO();
|
||||
failure1.setSheetName("亲属资产信息");
|
||||
failure1.setRowNum(2);
|
||||
failure1.setPersonId("A1");
|
||||
AssetImportFailureVO failure2 = new AssetImportFailureVO();
|
||||
failure2.setSheetName("亲属资产信息");
|
||||
failure2.setRowNum(3);
|
||||
failure2.setPersonId("A2");
|
||||
when(assetInfoImportService.getImportFailures("task-3")).thenReturn(List.of(failure1, failure2));
|
||||
|
||||
@@ -105,7 +109,10 @@ class CcdiAssetInfoControllerTest {
|
||||
|
||||
assertEquals(2, result.getTotal());
|
||||
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
|
||||
|
||||
@@ -93,10 +93,39 @@ class CcdiBaseStaffAssetImportServiceImplTest {
|
||||
ArgumentCaptor<Object> failureCaptor = ArgumentCaptor.forClass(Object.class);
|
||||
verify(valueOperations).set(eq("import:baseStaffAsset:task-2:failures"), failureCaptor.capture(), eq(7L), eq(TimeUnit.DAYS));
|
||||
BaseStaffAssetImportFailureVO failure = (BaseStaffAssetImportFailureVO) ((List<?>) failureCaptor.getValue()).get(0);
|
||||
assertEquals("员工资产信息", failure.getSheetName());
|
||||
assertEquals(2, failure.getRowNum());
|
||||
assertEquals("320101199201010022", failure.getPersonId());
|
||||
assertTrue(failure.getErrorMessage().contains("员工资产导入仅支持员工本人证件号"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void importAssetInfoAsync_shouldFailWhenAssetAlreadyExists() {
|
||||
CcdiBaseStaffAssetInfoExcel excel = buildExcel("320101199001010011", "房产");
|
||||
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
|
||||
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
||||
when(assetInfoMapper.selectOwnerCandidatesByBaseStaffIdCards(List.of("320101199001010011")))
|
||||
.thenReturn(List.of(owner("320101199001010011", "320101199001010011")));
|
||||
|
||||
CcdiAssetInfo existing = new CcdiAssetInfo();
|
||||
existing.setFamilyId("320101199001010011");
|
||||
existing.setPersonId("320101199001010011");
|
||||
existing.setAssetMainType("房产");
|
||||
existing.setAssetSubType("房产小类");
|
||||
existing.setAssetName("房产名称");
|
||||
when(assetInfoMapper.selectList(any())).thenReturn(List.of(existing));
|
||||
|
||||
service.importAssetInfoAsync(List.of(excel), "task-duplicate", "tester");
|
||||
|
||||
verify(assetInfoMapper, never()).insertBatch(any());
|
||||
ArgumentCaptor<Object> failureCaptor = ArgumentCaptor.forClass(Object.class);
|
||||
verify(valueOperations).set(eq("import:baseStaffAsset:task-duplicate:failures"), failureCaptor.capture(), eq(7L), eq(TimeUnit.DAYS));
|
||||
BaseStaffAssetImportFailureVO failure = (BaseStaffAssetImportFailureVO) ((List<?>) failureCaptor.getValue()).get(0);
|
||||
assertEquals("员工资产信息", failure.getSheetName());
|
||||
assertEquals(2, failure.getRowNum());
|
||||
assertTrue(failure.getErrorMessage().contains("资产记录已存在"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getImportStatusAndFailures_shouldUseBaseStaffAssetPrefixes() {
|
||||
when(redisTemplate.opsForHash()).thenReturn(hashOperations);
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package com.ruoyi.info.collection.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffAddDTO;
|
||||
import com.ruoyi.info.collection.service.impl.CcdiBaseStaffImportServiceImpl;
|
||||
import com.ruoyi.system.mapper.SysDeptMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
@@ -11,60 +17,109 @@ import java.util.Set;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CcdiBaseStaffImportServiceImplTest {
|
||||
|
||||
private final CcdiBaseStaffImportServiceImpl service = new CcdiBaseStaffImportServiceImpl();
|
||||
@InjectMocks
|
||||
private CcdiBaseStaffImportServiceImpl service;
|
||||
|
||||
@Mock
|
||||
private SysDeptMapper deptMapper;
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowEmptyAnnualIncome() {
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(null), false, Collections.emptySet(), Collections.emptySet()));
|
||||
mockNormalDept();
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(null), Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowZeroAndTwoDecimalAnnualIncome() {
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("0.00")), false, Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("12345.67")), false, Collections.emptySet(), Collections.emptySet()));
|
||||
mockNormalDept();
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("0.00")), Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("12345.67")), Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowPartyMemberValuesZeroAndOne() {
|
||||
mockNormalDept();
|
||||
CcdiBaseStaffAddDTO nonPartyMember = buildDto(null);
|
||||
nonPartyMember.setPartyMember(0);
|
||||
CcdiBaseStaffAddDTO partyMember = buildDto(null);
|
||||
partyMember.setPartyMember(1);
|
||||
|
||||
assertDoesNotThrow(() -> service.validateStaffData(nonPartyMember, false, Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(partyMember, false, Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(nonPartyMember, Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(partyMember, Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectInvalidPartyMemberValue() {
|
||||
mockNormalDept();
|
||||
CcdiBaseStaffAddDTO dto = buildDto(null);
|
||||
dto.setPartyMember(2);
|
||||
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(dto, false, Set.of(), Set.of()));
|
||||
() -> service.validateStaffData(dto, Set.of(), Set.of()));
|
||||
|
||||
assertEquals("是否党员只能填写'0'或'1'", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectNegativeAnnualIncome() {
|
||||
mockNormalDept();
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(new BigDecimal("-1.00")), false, Set.of(), Set.of()));
|
||||
() -> service.validateStaffData(buildDto(new BigDecimal("-1.00")), Set.of(), Set.of()));
|
||||
|
||||
assertEquals("年收入不能为负数", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectAnnualIncomeWithMoreThanTwoDecimals() {
|
||||
mockNormalDept();
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(new BigDecimal("12.345")), false, Set.of(), Set.of()));
|
||||
() -> service.validateStaffData(buildDto(new BigDecimal("12.345")), Set.of(), Set.of()));
|
||||
|
||||
assertEquals("年收入最多保留2位小数", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowWhenDeptIsNormalAndNotDeleted() {
|
||||
mockNormalDept();
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(null), Set.of(), Set.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectWhenDeptDoesNotExist() {
|
||||
when(deptMapper.selectDeptById(10L)).thenReturn(null);
|
||||
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(null), Set.of(), Set.of()));
|
||||
|
||||
assertEquals("所属部门ID[10]不存在或已停用/删除,请检查机构号", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectWhenDeptIsDisabled() {
|
||||
when(deptMapper.selectDeptById(10L)).thenReturn(buildDept("1", "0"));
|
||||
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(null), Set.of(), Set.of()));
|
||||
|
||||
assertEquals("所属部门ID[10]不存在或已停用/删除,请检查机构号", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectWhenDeptIsDeleted() {
|
||||
when(deptMapper.selectDeptById(10L)).thenReturn(buildDept("0", "2"));
|
||||
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(null), Set.of(), Set.of()));
|
||||
|
||||
assertEquals("所属部门ID[10]不存在或已停用/删除,请检查机构号", exception.getMessage());
|
||||
}
|
||||
|
||||
private CcdiBaseStaffAddDTO buildDto(BigDecimal annualIncome) {
|
||||
CcdiBaseStaffAddDTO dto = new CcdiBaseStaffAddDTO();
|
||||
dto.setName("张三");
|
||||
@@ -77,4 +132,17 @@ class CcdiBaseStaffImportServiceImplTest {
|
||||
dto.setAnnualIncome(annualIncome);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private SysDept buildDept(String status, String delFlag) {
|
||||
SysDept dept = new SysDept();
|
||||
dept.setDeptId(10L);
|
||||
dept.setDeptName("测试部门");
|
||||
dept.setStatus(status);
|
||||
dept.setDelFlag(delFlag);
|
||||
return dept;
|
||||
}
|
||||
|
||||
private void mockNormalDept() {
|
||||
lenient().when(deptMapper.selectDeptById(10L)).thenReturn(buildDept("0", "0"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user