From d85ec778237cd9af68c8d6b96895d22e0cf158df Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期一, 02 十一月 2026 14:15:17 +0800
Subject: [PATCH] fix(hrm/system): 修复调岗申请与提交报错、公积金误扣、用户搜索,新增核算批量删除

---
 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java          |    3 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationService.java                 |    8 ++
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java         |   54 +++++++++++++
 yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java                               |    1 
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java     |    8 ++
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/HrmTransferApplicationController.java |   13 ++
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationService.java             |    8 ++
 sql/mysql/hrm_transfer_application_nullable_current.sql                                                                    |   41 ++++++++++
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java             |   44 ++++++++--
 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java                       |   10 ++
 10 files changed, 176 insertions(+), 14 deletions(-)

diff --git a/sql/mysql/hrm_transfer_application_nullable_current.sql b/sql/mysql/hrm_transfer_application_nullable_current.sql
new file mode 100644
index 0000000..4471073
--- /dev/null
+++ b/sql/mysql/hrm_transfer_application_nullable_current.sql
@@ -0,0 +1,41 @@
+-- =============================================
+-- 璋冨矖鐢宠锛氬厑璁搞�屽師閮ㄩ棬銆嶃�屽師宀椾綅銆嶄负绌�
+--
+-- 闂锛歨rm_transfer_application.current_dept_id / current_post_id 涓� NOT NULL 涓旀棤榛樿鍊硷紝
+--       鑰屽鎴风幆澧� 133 涓憳宸ュ叏閮ㄦ病鏈夐厤缃矖浣嶏紙hrm_employee.post_id 涓� NULL锛夛紝
+--       鍓嶇鎻愪氦璋冨矖鐢宠鏃惰繖涓や釜瀛楁涓虹┖ 鈫� insert 鎶�
+--       "Field 'current_post_id' doesn't have a default value" 鈫� 璋冨矖鐢宠涓�鐩存彁浜ゅけ璐ャ��
+--
+-- 澶勭悊锛氭妸杩欎袱鍒楁敼涓哄厑璁� NULL銆傚師閮ㄩ棬/鍘熷矖浣嶅睘浜庛�岀敵璇锋椂鐨勫揩鐓с�嶏紝鍛樺伐妗f鏈厤缃椂涓虹┖鏄悎鐞嗙殑锛�
+--       涓嶅簲鍥犳闃绘柇鐢宠銆傜洰鏍囬儴闂�/鐩爣宀椾綅浠嶄繚鎸� NOT NULL锛堝墠绔繀濉紝灞炰簬涓氬姟蹇呴渶锛夈��
+--
+-- 鑴氭湰鍙噸澶嶆墽琛岋紙骞傜瓑锛�
+-- =============================================
+SET NAMES utf8mb4;
+
+SET @sch := DATABASE();
+
+-- 1. 鍘熷矖浣嶅厑璁镐负绌�
+SET @nullable := (SELECT IS_NULLABLE FROM information_schema.COLUMNS
+    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_transfer_application' AND COLUMN_NAME = 'current_post_id');
+SET @sql := IF(@nullable = 'NO',
+    'ALTER TABLE `hrm_transfer_application` MODIFY COLUMN `current_post_id` bigint NULL DEFAULT NULL COMMENT ''鍘熷矖浣岻D锛堝憳宸ユ湭閰嶇疆宀椾綅鏃朵负绌猴級''',
+    'SELECT ''current_post_id 宸插厑璁镐负绌�'' AS msg');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- 2. 鍘熼儴闂ㄥ厑璁镐负绌�
+SET @nullable := (SELECT IS_NULLABLE FROM information_schema.COLUMNS
+    WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_transfer_application' AND COLUMN_NAME = 'current_dept_id');
+SET @sql := IF(@nullable = 'NO',
+    'ALTER TABLE `hrm_transfer_application` MODIFY COLUMN `current_dept_id` bigint NULL DEFAULT NULL COMMENT ''鍘熼儴闂↖D锛堝憳宸ユ湭閰嶇疆閮ㄩ棬鏃朵负绌猴級''',
+    'SELECT ''current_dept_id 宸插厑璁镐负绌�'' AS msg');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- 3. 鏍稿
+SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
+FROM information_schema.COLUMNS
+WHERE TABLE_SCHEMA = @sch AND TABLE_NAME = 'hrm_transfer_application'
+  AND COLUMN_NAME IN ('current_dept_id','current_post_id','target_dept_id','target_post_id')
+ORDER BY ORDINAL_POSITION;
+
+SELECT '璋冨矖鐢宠 鍘熼儴闂�/鍘熷矖浣� 鍏佽涓虹┖ 鍒濆鍖栧畬鎴�' AS result;
diff --git a/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java b/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
index 5b4f221..cf274d8 100644
--- a/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
+++ b/yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
@@ -52,6 +52,7 @@
     ErrorCode TRANSFER_APPLICATION_SAME_DEPT = new ErrorCode(1_030_002_005, "璋冨矖澶辫触锛屽師鍥狅細鐩爣閮ㄩ棬涓庡師閮ㄩ棬鐩稿悓");
     ErrorCode TRANSFER_APPLICATION_SAME_POST = new ErrorCode(1_030_002_006, "璋冨矖澶辫触锛屽師鍥狅細鐩爣宀椾綅涓庡師宀椾綅鐩稿悓");
     ErrorCode TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_002_007, "璋冨矖瀹℃壒娴佺▼涓嶅瓨鍦�");
+    ErrorCode TRANSFER_APPLICATION_CANCEL_FAIL_NOT_PROCESS = new ErrorCode(1_030_002_008, "璋冨矖鐢宠鎾ら攢澶辫触锛屽師鍥狅細涓嶆槸瀹℃壒涓姸鎬�");
 
     // ========== 绂昏亴鐢宠 1-030-003-000 ==========
     ErrorCode RESIGNATION_APPLICATION_NOT_EXISTS = new ErrorCode(1_030_003_000, "绂昏亴鐢宠涓嶅瓨鍦�");
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/HrmTransferApplicationController.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/HrmTransferApplicationController.java
index 83cd690..460a652 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/HrmTransferApplicationController.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/HrmTransferApplicationController.java
@@ -82,10 +82,10 @@
     @PostMapping("/submit")
     @Operation(summary = "鎻愪氦璋冨矖鐢宠瀹℃壒")
     @Parameter(name = "id", description = "鐢宠ID", required = true)
-    @Parameter(name = "processDefinitionKey", description = "娴佺▼瀹氫箟Key", required = true)
+    @Parameter(name = "processDefinitionKey", description = "娴佺▼瀹氫箟Key锛堜笉浼犳椂鑷姩浣跨敤銆岃皟鍔ㄥ鎵广�嶅垎绫讳笅鏈�鏂扮殑娲昏穬娴佺▼锛�")
     @PreAuthorize("@ss.hasPermission('hrm:transfer:submit')")
     public CommonResult<Boolean> submitTransferApplication(@RequestParam("id") Long id,
-                                                           @RequestParam("processDefinitionKey") String processDefinitionKey) {
+                                                           @RequestParam(value = "processDefinitionKey", required = false) String processDefinitionKey) {
         Long userId = SecurityFrameworkUtils.getLoginUserId();
         transferApplicationService.submitTransferApplication(id, processDefinitionKey, userId);
         return success(true);
@@ -98,6 +98,15 @@
         return success(transferApplicationService.getApproveProcessDefinitionList());
     }
 
+    @PostMapping("/cancel")
+    @Operation(summary = "鎾ら攢璋冨矖鐢宠")
+    @Parameter(name = "id", description = "鐢宠ID", required = true)
+    @PreAuthorize("@ss.hasPermission('hrm:transfer:cancel')")
+    public CommonResult<Boolean> cancelTransferApplication(@RequestParam("id") Long id) {
+        transferApplicationService.cancelTransferApplication(id, SecurityFrameworkUtils.getLoginUserId());
+        return success(true);
+    }
+
     @GetMapping("/export-excel")
     @Operation(summary = "瀵煎嚭璋冨矖鐢宠 Excel")
     @PreAuthorize("@ss.hasPermission('hrm:transfer:export')")
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java
index d32cdd2..1eb277c 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java
@@ -161,6 +161,14 @@
         return success(true);
     }
 
+    @DeleteMapping("/delete-batch")
+    @Operation(summary = "鎵归噺鍒犻櫎钖叕鏍哥畻璁板綍", description = "鍏ㄩ�夊悗涓�閿垹闄わ紝涓嶉檺鍒剁姸鎬�")
+    @Parameter(name = "ids", description = "鏍哥畻ID鍒楄〃", required = true)
+    @PreAuthorize("@ss.hasPermission('hrm:salary-calculation:delete')")
+    public CommonResult<Integer> deleteSalaryCalculationList(@RequestParam("ids") List<Long> ids) {
+        return success(salaryCalculationService.deleteSalaryCalculationList(ids));
+    }
+
     @GetMapping("/export-excel")
     @Operation(summary = "瀵煎嚭钖叕鏍哥畻 Excel")
     @PreAuthorize("@ss.hasPermission('hrm:salary-calculation:export')")
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationService.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationService.java
index 3a2283b..62e2da4 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationService.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationService.java
@@ -83,6 +83,14 @@
     void submitTransferApplication(Long id, String processDefinitionKey, Long userId);
 
     /**
+     * 鎾ら攢璋冨矖鐢宠锛堝鎵逛腑 鈫� 宸叉挙閿�锛�
+     *
+     * @param id     鐢宠ID
+     * @param userId 鎿嶄綔浜猴紙褰撳墠鐧诲綍鐢ㄦ埛锛�
+     */
+    void cancelTransferApplication(Long id, Long userId);
+
+    /**
      * 鑾峰彇鍙敤鐨勫鎵规祦绋嬪畾涔夊垪琛�
      *
      * @return 娴佺▼瀹氫箟鍒楄〃
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
index 3d02148..b436b05 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
@@ -1,14 +1,17 @@
 package cn.iocoder.yudao.module.hrm.service.approval;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO;
 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
 import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationPageReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationSaveReqVO;
@@ -35,6 +38,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -77,6 +81,8 @@
     private StorageAttachmentApi storageAttachmentApi;
     @Resource
     private BpmProcessDefinitionService bpmProcessDefinitionService;
+    @Resource
+    private BpmProcessInstanceService bpmProcessInstanceService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -269,17 +275,41 @@
             throw exception(TRANSFER_APPLICATION_SUBMIT_FAIL_NOT_DRAFT);
         }
         validateApproveCategoryAndProcessDefinition();
-        ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey);
+        // 鏈寚瀹氭祦绋嬪畾涔� Key 鏃讹紝鑷姩鍙栥�岃皟鍔ㄥ鎵广�嶅垎绫讳笅褰撳墠娲昏穬鐨勬祦绋嬶紝
+        // 閬垮厤鍓嶇鏈紶 key 瀵艰嚧鎺ュ彛鍙傛暟缂哄け鐩存帴鎶ョ郴缁熷紓甯�
+        String key = resolveProcessDefinitionKey(processDefinitionKey);
+        ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(key);
         if (processDefinition == null) {
             throw exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
         }
         String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
-                .setProcessDefinitionKey(processDefinitionKey).setBusinessKey(String.valueOf(id)));
+                .setProcessDefinitionKey(key).setBusinessKey(String.valueOf(id)));
         transferApplicationMapper.updateById(HrmTransferApplicationDO.builder()
                 .id(id)
                 .processInstanceId(processInstanceId)
                 .status(HrmAuditStatusEnum.PROCESS.getStatus())
                 .build());
+    }
+
+    /**
+     * 瑙f瀽娴佺▼瀹氫箟 Key锛氫紭鍏堜娇鐢ㄨ皟鐢ㄦ柟浼犲叆鍊硷紝涓虹┖鏃跺彇銆岃皟鍔ㄥ鎵广�嶅垎绫讳笅鏈�鏂扮殑娲昏穬娴佺▼
+     */
+    private String resolveProcessDefinitionKey(String processDefinitionKey) {
+        if (StrUtil.isNotBlank(processDefinitionKey)) {
+            return processDefinitionKey.trim();
+        }
+        List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService
+                .getProcessDefinitionInfoListByCategory(APPROVE_CATEGORY_CODE);
+        if (CollUtil.isEmpty(definitionInfoList)) {
+            throw exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
+        }
+        Set<String> processDefinitionIds = convertSet(definitionInfoList, BpmProcessDefinitionInfoDO::getProcessDefinitionId);
+        List<ProcessDefinition> processDefinitions = bpmProcessDefinitionService.getProcessDefinitionList(processDefinitionIds);
+        return processDefinitions.stream()
+                .filter(pd -> !pd.isSuspended())
+                .max(Comparator.comparingInt(ProcessDefinition::getVersion))
+                .map(ProcessDefinition::getKey)
+                .orElseThrow(() -> exception(TRANSFER_APPLICATION_BPM_PROCESS_DEFINITION_NOT_EXISTS));
     }
 
     private void validateApproveCategoryAndProcessDefinition() {
@@ -302,6 +332,26 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void cancelTransferApplication(Long id, Long userId) {
+        HrmTransferApplicationDO application = validateTransferApplicationExists(id);
+        if (ObjUtil.notEqual(application.getStatus(), HrmAuditStatusEnum.PROCESS.getStatus())) {
+            throw exception(TRANSFER_APPLICATION_CANCEL_FAIL_NOT_PROCESS);
+        }
+        // 鍙栨秷瀵瑰簲鐨� BPM 娴佺▼瀹炰緥锛堜互鍙戣捣浜鸿韩浠芥挙閿�锛�
+        if (StrUtil.isNotBlank(application.getProcessInstanceId())) {
+            BpmProcessInstanceCancelReqVO cancelReqVO = new BpmProcessInstanceCancelReqVO();
+            cancelReqVO.setId(application.getProcessInstanceId());
+            cancelReqVO.setReason("鍛樺伐鎾ら攢璋冨矖鐢宠");
+            bpmProcessInstanceService.cancelProcessInstanceByStartUser(userId, cancelReqVO);
+        }
+        transferApplicationMapper.updateById(HrmTransferApplicationDO.builder()
+                .id(id)
+                .status(HrmAuditStatusEnum.CANCEL.getStatus())
+                .build());
+    }
+
+    @Override
     public List<Map<String, Object>> getApproveProcessDefinitionList() {
         validateApproveCategoryAndProcessDefinition();
         List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationService.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationService.java
index 5c12c9c..f654004 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationService.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationService.java
@@ -61,6 +61,14 @@
     void deleteSalaryCalculation(Long id);
 
     /**
+     * 鎵归噺鍒犻櫎鏍哥畻璁板綍锛堜笉闄愬埗鐘舵�侊紝鍕鹃�夊嵆鍒狅級
+     *
+     * @param ids 鏍哥畻璁板綍 ID 鍒楄〃
+     * @return 瀹為檯鍒犻櫎鐨勬潯鏁�
+     */
+    Integer deleteSalaryCalculationList(List<Long> ids);
+
+    /**
      * 鑾峰緱鎸囧畾鍛ㄦ湡鐨勮柂閰牳绠楀垪琛�
      */
     List<HrmSalaryCalculationDO> getSalaryCalculationListByPeriod(String period);
diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
index 5ed819e..8c61cad 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
@@ -277,19 +277,17 @@
         BigDecimal socialSecurityBase = (socialSecurity != null && socialSecurity.getSocialSecurityBase() != null)
                 ? socialSecurity.getSocialSecurityBase() : baseSalary;
 
-        // 鑾峰彇鍏Н閲戝熀鏁帮細鍛樺伐绀句繚妗f > 鍛樺伐鍩烘湰宸ヨ祫
-        BigDecimal housingFundBase = (socialSecurity != null && socialSecurity.getHousingFundBase() != null)
-                ? socialSecurity.getHousingFundBase() : baseSalary;
-
-        // 浠庢柟妗堜腑鑾峰彇缂寸撼姣斾緥锛堜紭鍏堜娇鐢ㄦ柟妗堜腑鐨勬瘮渚嬶紝鍚﹀垯浣跨敤榛樿姣斾緥锛�
+        // 浠庢柟妗堜腑鑾峰彇绀句繚缂寸撼姣斾緥锛堟柟妗堟湭閰嶇疆鏃跺洖閫�榛樿姣斾緥锛�
         BigDecimal pensionPersonalRatio = (scheme != null && scheme.getPensionPersonalRatio() != null)
                 ? scheme.getPensionPersonalRatio() : DEFAULT_PENSION_PERSONAL_RATIO;
         BigDecimal medicalPersonalRatio = (scheme != null && scheme.getMedicalPersonalRatio() != null)
                 ? scheme.getMedicalPersonalRatio() : DEFAULT_MEDICAL_PERSONAL_RATIO;
         BigDecimal unemploymentPersonalRatio = (scheme != null && scheme.getUnemploymentPersonalRatio() != null)
                 ? scheme.getUnemploymentPersonalRatio() : DEFAULT_UNEMPLOYMENT_PERSONAL_RATIO;
-        BigDecimal housingFundPersonalRatio = (scheme != null && scheme.getHousingFundPersonalRatio() != null)
-                ? scheme.getHousingFundPersonalRatio() : DEFAULT_HOUSING_FUND_PERSONAL_RATIO;
+
+        // 鍏Н閲戜釜浜烘瘮渚嬶細鍙彇鏂规閰嶇疆鍊硷紝涓嶅啀鍥為��榛樿姣斾緥銆�
+        // 鍚﹀垯銆屽叕鍙告病閰嶅叕绉噾鏂规銆嶆椂浼氳鎸夐粯璁� 12% 鎵f锛堣繖灏辨槸瀹㈡埛鍙嶉鐨勯棶棰橈級銆�
+        BigDecimal housingFundPersonalRatio = scheme != null ? scheme.getHousingFundPersonalRatio() : null;
 
         // 绀句繚鎵i櫎 = 鍩烘暟 脳 (鍏昏�佷釜浜烘瘮渚� + 鍖荤枟涓汉姣斾緥 + 澶变笟涓汉姣斾緥)
         BigDecimal socialSecurityDeduction = socialSecurityBase
@@ -298,8 +296,15 @@
                 .add(socialSecurityBase.multiply(unemploymentPersonalRatio))
                 .setScale(2, RoundingMode.HALF_UP);
 
-        // 鍏Н閲戞墸闄� = 鍩烘暟 脳 鍏Н閲戜釜浜烘瘮渚�
-        BigDecimal housingFundDeduction = housingFundBase.multiply(housingFundPersonalRatio).setScale(2, RoundingMode.HALF_UP);
+        // 鍏Н閲戞墸闄わ細蹇呴』鍚屾椂婊¤冻銆屾柟妗堥厤缃簡鍏Н閲戞瘮渚� > 0銆嶄笖銆屽憳宸ユ。妗堥厤缃簡鍏Н閲戝熀鏁� > 0銆嶆墠鎵f锛�
+        // 浠讳竴涓嶆弧瓒抽兘瑙嗕负鍏徃鏈即绾冲叕绉噾锛屾墸娆句负 0銆�
+        BigDecimal housingFundDeduction = BigDecimal.ZERO;
+        BigDecimal housingFundBase = socialSecurity != null ? socialSecurity.getHousingFundBase() : null;
+        if (housingFundPersonalRatio != null && housingFundPersonalRatio.signum() > 0
+                && housingFundBase != null && housingFundBase.signum() > 0) {
+            housingFundDeduction = housingFundBase.multiply(housingFundPersonalRatio)
+                    .setScale(2, RoundingMode.HALF_UP);
+        }
 
         // 璁$畻璇峰亣鎵f
         BigDecimal leaveDeduction = calculateLeaveDeduction(employee, period, baseSalary);
@@ -873,4 +878,25 @@
         salaryCalculationMapper.deleteById(id);
     }
 
+    /**
+     * 鎵归噺鍒犻櫎鏍哥畻璁板綍锛堝叏閫夊悗涓�閿垹闄わ級
+     *
+     * 璇存槑锛氭寜涓氬姟瑕佹眰锛屾壒閲忓垹闄や笉闄愬埗鐘舵�侊紝鍕鹃�夊嵆鍒犮��
+     * 涓嶅瓨鍦ㄧ殑 ID 鐩存帴璺宠繃锛屼笉鎶ラ敊锛堥伩鍏嶅墠绔嬀閫夊垪琛ㄤ笌搴撲笉涓�鑷存椂鏁翠綋澶辫触锛夈��
+     */
+    @Override
+    public Integer deleteSalaryCalculationList(List<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return 0;
+        }
+        List<Long> existIds = salaryCalculationMapper.selectBatchIds(ids).stream()
+                .map(HrmSalaryCalculationDO::getId)
+                .collect(Collectors.toList());
+        if (CollUtil.isEmpty(existIds)) {
+            return 0;
+        }
+        salaryCalculationMapper.deleteByIds(existIds);
+        return existIds.size();
+    }
+
 }
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java
index 7dadb51..24dbd88 100644
--- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java
@@ -22,6 +22,9 @@
     @Schema(description = "鐢ㄦ埛璐﹀彿锛屾ā绯婂尮閰�", example = "yudao")
     private String username;
 
+    @Schema(description = "鍏抽敭璇嶏紝鍚屾椂妯$硦鍖归厤銆岃处鍙枫�嶄笌銆屽鍚嶃�嶏紙渚涢�夋嫨鐢ㄦ埛寮圭獥鐨勬悳绱㈡浣跨敤锛�", example = "寮犱笁")
+    private String keyword;
+
     @Schema(description = "鎵嬫満鍙风爜锛屾ā绯婂尮閰�", example = "yudao")
     private String mobile;
 
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java
index c0c9be8..bde2c9e 100644
--- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.system.dal.mysql.user;
 
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -26,7 +27,14 @@
     }
 
     default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds, Collection<Long> userIds) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
+        LambdaQueryWrapperX<AdminUserDO> wrapper = new LambdaQueryWrapperX<>();
+        // 鍏抽敭璇嶏細鍚屾椂妯$硦鍖归厤銆岃处鍙枫�嶄笌銆屽鍚嶃�嶏紝渚涢�夋嫨鐢ㄦ埛寮圭獥鐨勬悳绱㈡浣跨敤
+        if (StrUtil.isNotBlank(reqVO.getKeyword())) {
+            String keyword = reqVO.getKeyword().trim();
+            wrapper.and(w -> w.like(AdminUserDO::getUsername, keyword)
+                    .or().like(AdminUserDO::getNickname, keyword));
+        }
+        return selectPage(reqVO, wrapper
                 .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
                 .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
                 .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())

--
Gitblit v1.9.3