tuqin
5 天以前 e2a6bb12ebb7ee07fbd5a428603995dbaccd1ce9
fix(hrm): 核算批量删除增加工资发放引用保护

问题:批量删除不限制状态,若删除已被「工资发放明细」引用的核算单,
hrm_salary_payment_detail.calculation_id 会指向不存在的记录,形成孤儿数据,
历史发放记录无法回溯金额来源。

处理:删除前批量查询 hrm_salary_payment_detail 的引用,
被引用的核算单跳过不删,返回实际删除条数(前端据此提示"X 条已进入工资发放流程,已跳过")。
状态限制保持不变(仍为勾选即删),仅保护已被发放流程引用的数据。

实测(mom-zyjc):3 条核算中 1 条挂在发放明细上,批量删除返回 2,
被引用的那条保留;解除引用后可正常删除;正式核算数据未受影响。
已修改2个文件
39 ■■■■■ 文件已修改
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/salary/HrmSalaryPaymentDetailMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/salary/HrmSalaryPaymentDetailMapper.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.hrm.dal.mysql.salary;
import cn.hutool.core.collection.CollUtil;
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;
@@ -7,6 +8,8 @@
import cn.iocoder.yudao.module.hrm.dal.dataobject.salary.HrmSalaryPaymentDetailDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -40,4 +43,17 @@
        return selectOne(HrmSalaryPaymentDetailDO::getCalculationId, calculationId);
    }
    /**
     * 批量查询:哪些核算单已被工资发放明细引用
     *
     * 用于删除核算单前做引用保护,避免发放明细变成孤儿数据。
     */
    default List<HrmSalaryPaymentDetailDO> selectListByCalculationIds(Collection<Long> calculationIds) {
        if (CollUtil.isEmpty(calculationIds)) {
            return Collections.emptyList();
        }
        return selectList(new LambdaQueryWrapperX<HrmSalaryPaymentDetailDO>()
                .in(HrmSalaryPaymentDetailDO::getCalculationId, calculationIds));
    }
}
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/HrmSalaryCalculationServiceImpl.java
@@ -881,8 +881,12 @@
    /**
     * 批量删除核算记录(全选后一键删除)
     *
     * 说明:按业务要求,批量删除不限制状态,勾选即删。
     * 不存在的 ID 直接跳过,不报错(避免前端勾选列表与库不一致时整体失败)。
     * 说明:
     * 1. 按业务要求,批量删除不限制核算单状态,勾选即删;
     * 2. 不存在的 ID 直接跳过,不报错(避免前端勾选列表与库不一致时整体失败);
     * 3. 已被「工资发放明细」引用的记录会跳过不删,避免发放明细变成孤儿数据。
     *
     * @return 实际删除的条数(可能小于传入条数)
     */
    @Override
    public Integer deleteSalaryCalculationList(List<Long> ids) {
@@ -895,8 +899,19 @@
        if (CollUtil.isEmpty(existIds)) {
            return 0;
        }
        salaryCalculationMapper.deleteByIds(existIds);
        return existIds.size();
        // 引用保护:已进入工资发放流程的核算单不允许删除
        Set<Long> referencedIds = salaryPaymentDetailMapper.selectListByCalculationIds(existIds).stream()
                .map(HrmSalaryPaymentDetailDO::getCalculationId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        List<Long> deletableIds = existIds.stream()
                .filter(id -> !referencedIds.contains(id))
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(deletableIds)) {
            return 0;
        }
        salaryCalculationMapper.deleteByIds(deletableIds);
        return deletableIds.size();
    }
}