From b5ca4fa6acd8c7ea8ed1400b133eb2eb6b5cb8ba Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 14 十月 2026 15:22:16 +0800
Subject: [PATCH] feat(hrm): 社保公积金方案支持按部门绑定,修比例输入精度
---
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSocialSecuritySchemeServiceImpl.java | 157 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 149 insertions(+), 8 deletions(-)
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSocialSecuritySchemeServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSocialSecuritySchemeServiceImpl.java
index 142653a..5be274f 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSocialSecuritySchemeServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSocialSecuritySchemeServiceImpl.java
@@ -1,18 +1,36 @@
package cn.iocoder.yudao.module.hrm.service.salary;
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.HrmSocialSecuritySchemeSaveReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSocialSecuritySchemeDO;
+import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSocialSecuritySchemeDeptDO;
+import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSocialSecuritySchemeDeptMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSocialSecuritySchemeMapper;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
+import java.time.LocalDate;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SOCIAL_SECURITY_SCHEME_DEPT_EXISTS;
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SOCIAL_SECURITY_SCHEME_NOT_EXISTS;
/**
* 绀句繚鍏Н閲戞柟妗� Service 瀹炵幇绫�
+ *
+ * 鏂规鐨勭即绾虫瘮渚嬫寜銆屾柟妗� - 閫傜敤閮ㄩ棬銆嶅叧鑱旇〃鐢熸晥锛涗竴涓儴闂ㄥ彧鑳界粦瀹氫竴涓柟妗堬紝鏈粦瀹氫换浣曢儴闂ㄧ殑鏂规浣滀负鍏ㄥ眬榛樿鏂规銆�
*
* @author 瓒呯骇绠$悊鍛�
*/
@@ -20,24 +38,42 @@
@Validated
public class HrmSocialSecuritySchemeServiceImpl implements HrmSocialSecuritySchemeService {
+ /**
+ * 鍚敤鐘舵��
+ */
+ private static final Integer STATUS_ENABLE = 0;
+
@Resource
private HrmSocialSecuritySchemeMapper schemeMapper;
+ @Resource
+ private HrmSocialSecuritySchemeDeptMapper schemeDeptMapper;
+
+ @Resource
+ private DeptApi deptApi;
+
@Override
- public Long createScheme(HrmSocialSecuritySchemeDO scheme) {
+ @Transactional(rollbackFor = Exception.class)
+ public Long createScheme(HrmSocialSecuritySchemeSaveReqVO createReqVO) {
+ HrmSocialSecuritySchemeDO scheme = BeanUtils.toBean(createReqVO, HrmSocialSecuritySchemeDO.class);
schemeMapper.insert(scheme);
+ saveSchemeDepts(scheme.getId(), createReqVO.getName(), createReqVO.getDeptIds());
return scheme.getId();
}
@Override
- public void updateScheme(HrmSocialSecuritySchemeDO scheme) {
- validateSchemeExists(scheme.getId());
- schemeMapper.updateById(scheme);
+ @Transactional(rollbackFor = Exception.class)
+ public void updateScheme(HrmSocialSecuritySchemeSaveReqVO updateReqVO) {
+ validateSchemeExists(updateReqVO.getId());
+ schemeMapper.updateById(BeanUtils.toBean(updateReqVO, HrmSocialSecuritySchemeDO.class));
+ saveSchemeDepts(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getDeptIds());
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void deleteScheme(Long id) {
validateSchemeExists(id);
+ schemeDeptMapper.deleteBySchemeId(id);
schemeMapper.deleteById(id);
}
@@ -51,10 +87,115 @@
return schemeMapper.selectListByStatus(status);
}
- private void validateSchemeExists(Long id) {
- if (schemeMapper.selectById(id) == null) {
- throw exception(SOCIAL_SECURITY_SCHEME_NOT_EXISTS);
+ @Override
+ public List<Long> getSchemeDeptIds(Long schemeId) {
+ return schemeDeptMapper.selectListBySchemeId(schemeId).stream()
+ .map(HrmSocialSecuritySchemeDeptDO::getDeptId)
+ .toList();
+ }
+
+ @Override
+ public Map<Long, List<Long>> getSchemeDeptIdMap(Collection<Long> schemeIds) {
+ if (CollUtil.isEmpty(schemeIds)) {
+ return Map.of();
+ }
+ return schemeDeptMapper.selectListBySchemeIds(schemeIds).stream()
+ .collect(Collectors.groupingBy(HrmSocialSecuritySchemeDeptDO::getSchemeId,
+ Collectors.mapping(HrmSocialSecuritySchemeDeptDO::getDeptId, Collectors.toList())));
+ }
+
+ @Override
+ public HrmSocialSecuritySchemeDO resolveSchemeByDeptId(Long deptId, LocalDate periodDate) {
+ // 1. 浼樺厛鍙栬閮ㄩ棬缁戝畾鐨勬柟妗�
+ if (deptId != null) {
+ List<Long> boundSchemeIds = schemeDeptMapper.selectListByDeptId(deptId).stream()
+ .map(HrmSocialSecuritySchemeDeptDO::getSchemeId)
+ .toList();
+ HrmSocialSecuritySchemeDO scheme = pickLatestEnabled(boundSchemeIds, periodDate);
+ if (scheme != null) {
+ return scheme;
+ }
+ }
+ // 2. 鍏滃簳鍙栧叏灞�榛樿鏂规锛氭湭缁戝畾浠讳綍閮ㄩ棬鐨勬柟妗堜腑鐢熸晥鏃ユ湡鏈�鏂拌��
+ Set<Long> boundSchemeIds = schemeDeptMapper.selectAllBoundSchemeIds();
+ List<Long> globalSchemeIds = schemeMapper.selectListByStatus(STATUS_ENABLE).stream()
+ .map(HrmSocialSecuritySchemeDO::getId)
+ .filter(id -> !boundSchemeIds.contains(id))
+ .toList();
+ return pickLatestEnabled(globalSchemeIds, periodDate);
+ }
+
+ /**
+ * 浠庡�欓�夋柟妗堜腑鍙栥�岀敓鏁堟棩鏈熶笉鏅氫簬鏍哥畻鏈熼棿銆嶇殑鏈�鏂颁竴鏉″惎鐢ㄦ柟妗�
+ *
+ * 鑻ュ叏閮ㄥ�欓�夋柟妗堥兘鏅氫簬鏍哥畻鏈熼棿锛堜緥濡傚垰寤哄ソ涓嬫湀鎵嶇敓鏁堢殑鏂规灏辨彁鍓嶆牳绠楋級锛屽垯閫�鍖栦负鍙栧叾涓敓鏁堟棩鏈熸渶鏂扮殑涓�鏉★紝
+ * 閬垮厤鏍哥畻閲戦闈欓粯钀藉埌浠g爜閲岀殑榛樿姣斾緥涓娿��
+ */
+ private HrmSocialSecuritySchemeDO pickLatestEnabled(Collection<Long> schemeIds, LocalDate periodDate) {
+ if (CollUtil.isEmpty(schemeIds)) {
+ return null;
+ }
+ List<HrmSocialSecuritySchemeDO> schemes = schemeMapper.selectList(
+ new LambdaQueryWrapperX<HrmSocialSecuritySchemeDO>()
+ .in(HrmSocialSecuritySchemeDO::getId, schemeIds)
+ .eq(HrmSocialSecuritySchemeDO::getStatus, STATUS_ENABLE)
+ .orderByDesc(HrmSocialSecuritySchemeDO::getEffectiveDate)
+ .orderByDesc(HrmSocialSecuritySchemeDO::getId));
+ if (CollUtil.isEmpty(schemes)) {
+ return null;
+ }
+ return schemes.stream()
+ .filter(scheme -> scheme.getEffectiveDate() == null
+ || !scheme.getEffectiveDate().isAfter(periodDate))
+ .findFirst()
+ .orElse(schemes.get(0));
+ }
+
+ /**
+ * 鏁寸粍鏇挎崲鏂规鐨勯�傜敤閮ㄩ棬锛氬厛鏍¢獙锛屽啀鍒犳棫琛屻�佹彃鏂拌
+ */
+ private void saveSchemeDepts(Long schemeId, String schemeName, List<Long> deptIds) {
+ List<Long> distinctDeptIds = CollUtil.isEmpty(deptIds) ? List.of()
+ : deptIds.stream().filter(Objects::nonNull).distinct().toList();
+ if (CollUtil.isNotEmpty(distinctDeptIds)) {
+ // 閮ㄩ棬蹇呴』瀛樺湪
+ deptApi.validateDeptList(distinctDeptIds);
+ // 涓�涓儴闂ㄥ彧鑳界粦瀹氫竴涓柟妗�
+ validateDeptNotBoundByOtherScheme(schemeId, schemeName, distinctDeptIds);
+ }
+ schemeDeptMapper.deleteBySchemeId(schemeId);
+ distinctDeptIds.forEach(deptId -> schemeDeptMapper.insert(
+ HrmSocialSecuritySchemeDeptDO.builder().schemeId(schemeId).deptId(deptId).build()));
+ }
+
+ /**
+ * 鏍¢獙杩欎簺閮ㄩ棬娌℃湁琚埆鐨勬柟妗堝崰鐢�
+ */
+ private void validateDeptNotBoundByOtherScheme(Long schemeId, String schemeName, List<Long> deptIds) {
+ List<HrmSocialSecuritySchemeDeptDO> bindings = schemeDeptMapper.selectListByDeptIds(deptIds);
+ if (CollUtil.isEmpty(bindings)) {
+ return;
+ }
+ // 鍚嶇О瑙f瀽鍙斁鍦ㄥ紓甯稿垎鏀紝閬垮厤姝e父淇濆瓨澶氭煡琛�
+ for (HrmSocialSecuritySchemeDeptDO binding : bindings) {
+ if (Objects.equals(binding.getSchemeId(), schemeId)) {
+ continue;
+ }
+ HrmSocialSecuritySchemeDO otherScheme = schemeMapper.selectById(binding.getSchemeId());
+ DeptRespDTO dept = deptApi.getDept(binding.getDeptId());
+ throw exception(SOCIAL_SECURITY_SCHEME_DEPT_EXISTS,
+ dept != null ? dept.getName() : "ID=" + binding.getDeptId(),
+ otherScheme != null ? otherScheme.getName() : "ID=" + binding.getSchemeId(),
+ schemeName);
}
}
-}
\ No newline at end of file
+ private HrmSocialSecuritySchemeDO validateSchemeExists(Long id) {
+ HrmSocialSecuritySchemeDO scheme = schemeMapper.selectById(id);
+ if (scheme == null) {
+ throw exception(SOCIAL_SECURITY_SCHEME_NOT_EXISTS);
+ }
+ return scheme;
+ }
+
+}
--
Gitblit v1.9.3