薪资分析
This commit is contained in:
@@ -3,6 +3,9 @@ package com.ruoyi.oa.mapper;
|
|||||||
import com.ruoyi.oa.domain.OaBindingItemDetail;
|
import com.ruoyi.oa.domain.OaBindingItemDetail;
|
||||||
import com.ruoyi.oa.domain.vo.OaBindingItemDetailVo;
|
import com.ruoyi.oa.domain.vo.OaBindingItemDetailVo;
|
||||||
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定记录明细Mapper接口
|
* 绑定记录明细Mapper接口
|
||||||
@@ -11,5 +14,5 @@ import com.ruoyi.common.core.mapper.BaseMapperPlus;
|
|||||||
* @date 2025-06-23
|
* @date 2025-06-23
|
||||||
*/
|
*/
|
||||||
public interface OaBindingItemDetailMapper extends BaseMapperPlus<OaBindingItemDetailMapper, OaBindingItemDetail, OaBindingItemDetailVo> {
|
public interface OaBindingItemDetailMapper extends BaseMapperPlus<OaBindingItemDetailMapper, OaBindingItemDetail, OaBindingItemDetailVo> {
|
||||||
|
List<OaBindingItemDetail> findByBindingId(@Param("bindingId") Long bindingId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,8 @@ public class OaEmployeeTemplateBindingServiceImpl implements IOaEmployeeTemplate
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
if (defaultInsuranceTemplateId == null || defaultSalaryTemplateId == null) {
|
||||||
throw new RuntimeException("请选择默认的薪资模板和社保模板");
|
throw new RuntimeException("请选择默认的薪资模板和社保模板");
|
||||||
@@ -187,90 +188,120 @@ public class OaEmployeeTemplateBindingServiceImpl implements IOaEmployeeTemplate
|
|||||||
// 1. 检查本月是否已存在记录
|
// 1. 检查本月是否已存在记录
|
||||||
OaEmployeeTemplateBinding exist = baseMapper.findByEmployeeAndMonth(employeeId, payYear, payMonth);
|
OaEmployeeTemplateBinding exist = baseMapper.findByEmployeeAndMonth(employeeId, payYear, payMonth);
|
||||||
if (exist != null) {
|
if (exist != null) {
|
||||||
// 已存在,跳过或更新
|
// 已存在,跳过
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 获取上月的模板ID(支持一键复制)
|
// 2. 获取上月记录
|
||||||
Long lastMonth = (payMonth == 1) ? 12 : payMonth - 1;
|
Long lastMonth = (payMonth == 1) ? 12 : payMonth - 1;
|
||||||
Long lastYear = (payMonth == 1) ? payYear - 1 : payYear;
|
Long lastYear = (payMonth == 1) ? payYear - 1 : payYear;
|
||||||
OaEmployeeTemplateBinding lastBinding = baseMapper.findByEmployeeAndMonth(employeeId, lastYear, lastMonth);
|
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. 新建本月主表记录
|
// 3. 新建本月主表记录
|
||||||
OaEmployeeTemplateBinding binding = new OaEmployeeTemplateBinding();
|
OaEmployeeTemplateBinding binding = new OaEmployeeTemplateBinding();
|
||||||
binding.setEmployeeId(employeeId);
|
binding.setEmployeeId(employeeId);
|
||||||
binding.setInsuranceTemplateId(insuranceTemplateId);
|
|
||||||
binding.setSalaryTemplateId(salaryTemplateId);
|
|
||||||
binding.setPayYear(payYear);
|
binding.setPayYear(payYear);
|
||||||
binding.setPayMonth(payMonth);
|
binding.setPayMonth(payMonth);
|
||||||
binding.setStatus("待发");
|
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);
|
baseMapper.insert(binding);
|
||||||
|
|
||||||
// 4. 生成明细快照
|
// 4. 生成明细快照
|
||||||
List<OaSalaryTemplateDetail> salaryDetails = salaryDetailMapper.findByTemplateId(salaryTemplateId);
|
if (lastBinding != null) {
|
||||||
List<OaInsuranceTemplateDetail> insuranceDetails = insuranceDetailMapper.findByTemplateId(insuranceTemplateId);
|
// 如果存在上月记录,复制上月的实际支付金额
|
||||||
|
copyLastMonthDetails(lastBinding.getBindingId(), binding.getBindingId());
|
||||||
|
} else {
|
||||||
|
// 首次配置,使用模板默认金额
|
||||||
|
createNewDetails(binding.getBindingId(), binding.getSalaryTemplateId(),
|
||||||
|
binding.getInsuranceTemplateId());
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal totalSalary = BigDecimal.ZERO;
|
// 5. 更新主表的汇总金额
|
||||||
BigDecimal totalCompanyInsurance = BigDecimal.ZERO;
|
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) {
|
for (OaSalaryTemplateDetail detail : salaryDetails) {
|
||||||
BigDecimal paidAmount = detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO;
|
|
||||||
totalSalary = totalSalary.add(paidAmount);
|
|
||||||
|
|
||||||
OaBindingItemDetail item = new OaBindingItemDetail();
|
OaBindingItemDetail item = new OaBindingItemDetail();
|
||||||
item.setBindingId(binding.getBindingId());
|
item.setBindingId(bindingId);
|
||||||
item.setTemplateType("salary");
|
item.setTemplateType("salary");
|
||||||
item.setItemDetailId(detail.getSalaryDetailId());
|
item.setItemDetailId(detail.getSalaryDetailId());
|
||||||
item.setPaidAmount(paidAmount);
|
item.setPaidAmount(detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO);
|
||||||
//打印item
|
|
||||||
System.out.println("item:"+item);
|
|
||||||
bindingItemDetailMapper.insert(item);
|
bindingItemDetailMapper.insert(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 社保明细
|
// 社保明细
|
||||||
|
List<OaInsuranceTemplateDetail> insuranceDetails = insuranceDetailMapper.findByTemplateId(insuranceTemplateId);
|
||||||
for (OaInsuranceTemplateDetail detail : insuranceDetails) {
|
for (OaInsuranceTemplateDetail detail : insuranceDetails) {
|
||||||
BigDecimal paidAmount = detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO;
|
|
||||||
totalCompanyInsurance = totalCompanyInsurance.add(paidAmount);
|
|
||||||
|
|
||||||
OaBindingItemDetail item = new OaBindingItemDetail();
|
OaBindingItemDetail item = new OaBindingItemDetail();
|
||||||
item.setBindingId(binding.getBindingId());
|
item.setBindingId(bindingId);
|
||||||
item.setTemplateType("insurance");
|
item.setTemplateType("insurance");
|
||||||
item.setItemDetailId(detail.getInsuranceDetailId());
|
item.setItemDetailId(detail.getInsuranceDetailId());
|
||||||
item.setPaidAmount(paidAmount);
|
item.setPaidAmount(detail.getAmount() != null ? detail.getAmount() : BigDecimal.ZERO);
|
||||||
bindingItemDetailMapper.insert(item);
|
bindingItemDetailMapper.insert(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 计算实发工资和单位总支出
|
|
||||||
BigDecimal netSalary = totalSalary;
|
|
||||||
//TODO 可扩展:减去个税、个人社保等
|
|
||||||
BigDecimal totalCompanyCost = netSalary.add(totalCompanyInsurance);
|
|
||||||
binding.setNetSalary(netSalary);
|
|
||||||
binding.setTotalCompanyCost(totalCompanyCost);
|
|
||||||
baseMapper.updateById(binding);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
/**
|
||||||
|
* 更新主表的汇总金额
|
||||||
|
*/
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,12 @@
|
|||||||
<result property="updateBy" column="update_by"/>
|
<result property="updateBy" column="update_by"/>
|
||||||
<result property="updateTime" column="update_time"/>
|
<result property="updateTime" column="update_time"/>
|
||||||
</resultMap>
|
</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>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user