薪资分析

This commit is contained in:
2025-06-24 18:05:13 +08:00
parent 6d3aa7fe06
commit e4edc70bbc
3 changed files with 106 additions and 66 deletions

View File

@@ -3,6 +3,9 @@ package com.ruoyi.oa.mapper;
import com.ruoyi.oa.domain.OaBindingItemDetail;
import com.ruoyi.oa.domain.vo.OaBindingItemDetailVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 绑定记录明细Mapper接口
@@ -11,5 +14,5 @@ import com.ruoyi.common.core.mapper.BaseMapperPlus;
* @date 2025-06-23
*/
public interface OaBindingItemDetailMapper extends BaseMapperPlus<OaBindingItemDetailMapper, OaBindingItemDetail, OaBindingItemDetailVo> {
List<OaBindingItemDetail> findByBindingId(@Param("bindingId") Long bindingId);
}

View File

@@ -177,7 +177,8 @@ public class OaEmployeeTemplateBindingServiceImpl implements IOaEmployeeTemplate
}
@Override
public Boolean calculateSalary(List<Long> employeeIds, Long payYear, Long payMonth,Long defaultInsuranceTemplateId, Long defaultSalaryTemplateId) {
public Boolean calculateSalary(List<Long> employeeIds, Long payYear, Long payMonth,
Long defaultInsuranceTemplateId, Long defaultSalaryTemplateId) {
// 参数校验
if (defaultInsuranceTemplateId == null || defaultSalaryTemplateId == null) {
throw new RuntimeException("请选择默认的薪资模板和社保模板");
@@ -187,92 +188,122 @@ public class OaEmployeeTemplateBindingServiceImpl implements IOaEmployeeTemplate
// 1. 检查本月是否已存在记录
OaEmployeeTemplateBinding exist = baseMapper.findByEmployeeAndMonth(employeeId, payYear, payMonth);
if (exist != null) {
// 已存在,跳过或更新
// 已存在,跳过
continue;
}
// 2. 获取上月的模板ID支持一键复制
// 2. 获取上月记录
Long lastMonth = (payMonth == 1) ? 12 : payMonth - 1;
Long lastYear = (payMonth == 1) ? payYear - 1 : payYear;
OaEmployeeTemplateBinding lastBinding = baseMapper.findByEmployeeAndMonth(employeeId, lastYear, lastMonth);
Long insuranceTemplateId;
Long salaryTemplateId;
if (lastBinding != null) {
// 存在上月记录,使用上月的模板
insuranceTemplateId = lastBinding.getInsuranceTemplateId();
salaryTemplateId = lastBinding.getSalaryTemplateId();
} else {
// 首次配置,使用前端传入的默认模板
insuranceTemplateId = defaultInsuranceTemplateId;
salaryTemplateId = defaultSalaryTemplateId;
// 将默认模板ID保存到员工表
// OaEmployeeTemplateBinding employee = new OaEmployeeTemplateBinding();
// employee.setEmployeeId(employeeId);
// employee.setInsuranceTemplateId(defaultInsuranceTemplateId);
// employee.setSalaryTemplateId(defaultSalaryTemplateId);
// baseMapper.updateById(employee);
}
// 3. 新建本月主表记录
OaEmployeeTemplateBinding binding = new OaEmployeeTemplateBinding();
binding.setEmployeeId(employeeId);
binding.setInsuranceTemplateId(insuranceTemplateId);
binding.setSalaryTemplateId(salaryTemplateId);
binding.setPayYear(payYear);
binding.setPayMonth(payMonth);
binding.setStatus("待发");
// binding.setNetSalary(BigDecimal.ZERO); // 确保设置默认值
// binding.setTotalCompanyCost(BigDecimal.ZERO);
if (lastBinding != null) {
// 存在上月记录复制上月的模板ID
binding.setInsuranceTemplateId(lastBinding.getInsuranceTemplateId());
binding.setSalaryTemplateId(lastBinding.getSalaryTemplateId());
} else {
// 首次配置,使用默认模板
binding.setInsuranceTemplateId(defaultInsuranceTemplateId);
binding.setSalaryTemplateId(defaultSalaryTemplateId);
}
// 插入主表记录
baseMapper.insert(binding);
// 4. 生成明细快照
List<OaSalaryTemplateDetail> salaryDetails = salaryDetailMapper.findByTemplateId(salaryTemplateId);
List<OaInsuranceTemplateDetail> insuranceDetails = insuranceDetailMapper.findByTemplateId(insuranceTemplateId);
BigDecimal totalSalary = BigDecimal.ZERO;
BigDecimal totalCompanyInsurance = BigDecimal.ZERO;
// 薪资明细
for (OaSalaryTemplateDetail detail : salaryDetails) {
BigDecimal paidAmount = detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO;
totalSalary = totalSalary.add(paidAmount);
OaBindingItemDetail item = new OaBindingItemDetail();
item.setBindingId(binding.getBindingId());
item.setTemplateType("salary");
item.setItemDetailId(detail.getSalaryDetailId());
item.setPaidAmount(paidAmount);
//打印item
System.out.println("item:"+item);
bindingItemDetailMapper.insert(item);
if (lastBinding != null) {
// 如果存在上月记录,复制上月的实际支付金额
copyLastMonthDetails(lastBinding.getBindingId(), binding.getBindingId());
} else {
// 首次配置,使用模板默认金额
createNewDetails(binding.getBindingId(), binding.getSalaryTemplateId(),
binding.getInsuranceTemplateId());
}
// 社保明细
for (OaInsuranceTemplateDetail detail : insuranceDetails) {
BigDecimal paidAmount = detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO;
totalCompanyInsurance = totalCompanyInsurance.add(paidAmount);
OaBindingItemDetail item = new OaBindingItemDetail();
item.setBindingId(binding.getBindingId());
item.setTemplateType("insurance");
item.setItemDetailId(detail.getInsuranceDetailId());
item.setPaidAmount(paidAmount);
bindingItemDetailMapper.insert(item);
}
// 5. 计算实发工资和单位总支出
BigDecimal netSalary = totalSalary;
//TODO 可扩展:减去个税、个人社保等
BigDecimal totalCompanyCost = netSalary.add(totalCompanyInsurance);
binding.setNetSalary(netSalary);
binding.setTotalCompanyCost(totalCompanyCost);
baseMapper.updateById(binding);
// 5. 更新主表的汇总金额
updateBindingTotals(binding.getBindingId());
}
return true;
}
/**
* 复制上月明细记录
*/
private void copyLastMonthDetails(Long lastBindingId, Long newBindingId) {
// 查询上月所有明细
List<OaBindingItemDetail> lastDetails = bindingItemDetailMapper.findByBindingId(lastBindingId);
for (OaBindingItemDetail lastDetail : lastDetails) {
OaBindingItemDetail newDetail = new OaBindingItemDetail();
newDetail.setBindingId(newBindingId);
newDetail.setTemplateType(lastDetail.getTemplateType());
newDetail.setItemDetailId(lastDetail.getItemDetailId());
newDetail.setPaidAmount(lastDetail.getPaidAmount()); // 复制实际支付金额
bindingItemDetailMapper.insert(newDetail);
}
}
/**
* 创建新的明细记录(使用模板默认值)
*/
private void createNewDetails(Long bindingId, Long salaryTemplateId, Long insuranceTemplateId) {
// 薪资明细
List<OaSalaryTemplateDetail> salaryDetails = salaryDetailMapper.findByTemplateId(salaryTemplateId);
for (OaSalaryTemplateDetail detail : salaryDetails) {
OaBindingItemDetail item = new OaBindingItemDetail();
item.setBindingId(bindingId);
item.setTemplateType("salary");
item.setItemDetailId(detail.getSalaryDetailId());
item.setPaidAmount(detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO);
bindingItemDetailMapper.insert(item);
}
// 社保明细
List<OaInsuranceTemplateDetail> insuranceDetails = insuranceDetailMapper.findByTemplateId(insuranceTemplateId);
for (OaInsuranceTemplateDetail detail : insuranceDetails) {
OaBindingItemDetail item = new OaBindingItemDetail();
item.setBindingId(bindingId);
item.setTemplateType("insurance");
item.setItemDetailId(detail.getInsuranceDetailId());
item.setPaidAmount(detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO);
bindingItemDetailMapper.insert(item);
}
}
/**
* 更新主表的汇总金额
*/
private void updateBindingTotals(Long bindingId) {
// 查询该binding下所有明细
List<OaBindingItemDetail> details = bindingItemDetailMapper.findByBindingId(bindingId);
BigDecimal totalSalary = BigDecimal.ZERO;
BigDecimal totalCost = BigDecimal.ZERO;
for (OaBindingItemDetail detail : details) {
if (detail.getPaidAmount() != null) {
if ("salary".equals(detail.getTemplateType())) {
totalSalary = totalSalary.add(detail.getPaidAmount());
}
totalCost = totalCost.add(detail.getPaidAmount());
}
}
// 更新主表
OaEmployeeTemplateBinding binding = new OaEmployeeTemplateBinding();
binding.setBindingId(bindingId);
binding.setNetSalary(totalSalary);
binding.setTotalCompanyCost(totalCost);
baseMapper.updateById(binding);
}
@Override
public Boolean finalizeSalary(List<String> bindingIds) {

View File

@@ -17,6 +17,12 @@
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="findByBindingId" resultType="com.ruoyi.oa.domain.OaBindingItemDetail">
SELECT *
FROM oa_binding_item_detail
WHERE binding_id = #{bindingId}
AND del_flag = 0
</select>
</mapper>