薪资计算逻辑

This commit is contained in:
2025-06-23 18:04:49 +08:00
parent 3b0d223da5
commit 3d6fe57c50
58 changed files with 3522 additions and 1 deletions

View File

@@ -0,0 +1,49 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaBindingItemDetail;
import com.ruoyi.oa.domain.vo.OaBindingItemDetailVo;
import com.ruoyi.oa.domain.bo.OaBindingItemDetailBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 绑定记录明细Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaBindingItemDetailService {
/**
* 查询绑定记录明细
*/
OaBindingItemDetailVo queryById(Long bindingItemId);
/**
* 查询绑定记录明细列表
*/
TableDataInfo<OaBindingItemDetailVo> queryPageList(OaBindingItemDetailBo bo, PageQuery pageQuery);
/**
* 查询绑定记录明细列表
*/
List<OaBindingItemDetailVo> queryList(OaBindingItemDetailBo bo);
/**
* 新增绑定记录明细
*/
Boolean insertByBo(OaBindingItemDetailBo bo);
/**
* 修改绑定记录明细
*/
Boolean updateByBo(OaBindingItemDetailBo bo);
/**
* 校验并批量删除绑定记录明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaEmployee;
import com.ruoyi.oa.domain.vo.OaEmployeeVo;
import com.ruoyi.oa.domain.bo.OaEmployeeBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 员工基础信息Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaEmployeeService {
/**
* 查询员工基础信息
*/
OaEmployeeVo queryById(Long employeeId);
/**
* 查询员工基础信息列表
*/
TableDataInfo<OaEmployeeVo> queryPageList(OaEmployeeBo bo, PageQuery pageQuery);
/**
* 查询员工基础信息列表
*/
List<OaEmployeeVo> queryList(OaEmployeeBo bo);
/**
* 新增员工基础信息
*/
Boolean insertByBo(OaEmployeeBo bo);
/**
* 修改员工基础信息
*/
Boolean updateByBo(OaEmployeeBo bo);
/**
* 校验并批量删除员工基础信息信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,54 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaEmployeeTemplateBinding;
import com.ruoyi.oa.domain.vo.EmployeeSalaryRecordVo;
import com.ruoyi.oa.domain.vo.OaEmployeeTemplateBindingVo;
import com.ruoyi.oa.domain.bo.OaEmployeeTemplateBindingBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 员工模板绑定及月度发放记录Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaEmployeeTemplateBindingService {
/**
* 查询员工模板绑定及月度发放记录
*/
OaEmployeeTemplateBindingVo queryById(Long bindingId);
/**
* 查询员工模板绑定及月度发放记录列表
*/
TableDataInfo<OaEmployeeTemplateBindingVo> queryPageList(OaEmployeeTemplateBindingBo bo, PageQuery pageQuery);
/**
* 查询员工模板绑定及月度发放记录列表
*/
List<OaEmployeeTemplateBindingVo> queryList(OaEmployeeTemplateBindingBo bo);
/**
* 新增员工模板绑定及月度发放记录
*/
Boolean insertByBo(OaEmployeeTemplateBindingBo bo);
/**
* 修改员工模板绑定及月度发放记录
*/
Boolean updateByBo(OaEmployeeTemplateBindingBo bo);
/**
* 校验并批量删除员工模板绑定及月度发放记录信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
Boolean calculateSalary(List<Long> employeeIds, Long payYear, Long payMonth,Long defaultInsuranceTemplateId, Long defaultSalaryTemplateId);
Boolean finalizeSalary(List<Long> bindingIds);
List<EmployeeSalaryRecordVo> querySalaryHistory(Long employeeId);
}

View File

@@ -0,0 +1,49 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaInsuranceTemplateDetail;
import com.ruoyi.oa.domain.vo.OaInsuranceTemplateDetailVo;
import com.ruoyi.oa.domain.bo.OaInsuranceTemplateDetailBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 社保/公积金模板明细Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaInsuranceTemplateDetailService {
/**
* 查询社保/公积金模板明细
*/
OaInsuranceTemplateDetailVo queryById(Long insuranceDetailId);
/**
* 查询社保/公积金模板明细列表
*/
TableDataInfo<OaInsuranceTemplateDetailVo> queryPageList(OaInsuranceTemplateDetailBo bo, PageQuery pageQuery);
/**
* 查询社保/公积金模板明细列表
*/
List<OaInsuranceTemplateDetailVo> queryList(OaInsuranceTemplateDetailBo bo);
/**
* 新增社保/公积金模板明细
*/
Boolean insertByBo(OaInsuranceTemplateDetailBo bo);
/**
* 修改社保/公积金模板明细
*/
Boolean updateByBo(OaInsuranceTemplateDetailBo bo);
/**
* 校验并批量删除社保/公积金模板明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaInsuranceTemplate;
import com.ruoyi.oa.domain.vo.OaInsuranceTemplateVo;
import com.ruoyi.oa.domain.bo.OaInsuranceTemplateBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 社保/公积金模板主Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaInsuranceTemplateService {
/**
* 查询社保/公积金模板主
*/
OaInsuranceTemplateVo queryById(Long insuranceTemplateId);
/**
* 查询社保/公积金模板主列表
*/
TableDataInfo<OaInsuranceTemplateVo> queryPageList(OaInsuranceTemplateBo bo, PageQuery pageQuery);
/**
* 查询社保/公积金模板主列表
*/
List<OaInsuranceTemplateVo> queryList(OaInsuranceTemplateBo bo);
/**
* 新增社保/公积金模板主
*/
Boolean insertByBo(OaInsuranceTemplateBo bo);
/**
* 修改社保/公积金模板主
*/
Boolean updateByBo(OaInsuranceTemplateBo bo);
/**
* 校验并批量删除社保/公积金模板主信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaSalaryTemplateDetail;
import com.ruoyi.oa.domain.vo.OaSalaryTemplateDetailVo;
import com.ruoyi.oa.domain.bo.OaSalaryTemplateDetailBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 薪资模板明细Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaSalaryTemplateDetailService {
/**
* 查询薪资模板明细
*/
OaSalaryTemplateDetailVo queryById(Long salaryDetailId);
/**
* 查询薪资模板明细列表
*/
TableDataInfo<OaSalaryTemplateDetailVo> queryPageList(OaSalaryTemplateDetailBo bo, PageQuery pageQuery);
/**
* 查询薪资模板明细列表
*/
List<OaSalaryTemplateDetailVo> queryList(OaSalaryTemplateDetailBo bo);
/**
* 新增薪资模板明细
*/
Boolean insertByBo(OaSalaryTemplateDetailBo bo);
/**
* 修改薪资模板明细
*/
Boolean updateByBo(OaSalaryTemplateDetailBo bo);
/**
* 校验并批量删除薪资模板明细信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.ruoyi.oa.service;
import com.ruoyi.oa.domain.OaSalaryTemplate;
import com.ruoyi.oa.domain.vo.OaSalaryTemplateVo;
import com.ruoyi.oa.domain.bo.OaSalaryTemplateBo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 薪资模板主Service接口
*
* @author ruoyi
* @date 2025-06-23
*/
public interface IOaSalaryTemplateService {
/**
* 查询薪资模板主
*/
OaSalaryTemplateVo queryById(Long salaryTemplateId);
/**
* 查询薪资模板主列表
*/
TableDataInfo<OaSalaryTemplateVo> queryPageList(OaSalaryTemplateBo bo, PageQuery pageQuery);
/**
* 查询薪资模板主列表
*/
List<OaSalaryTemplateVo> queryList(OaSalaryTemplateBo bo);
/**
* 新增薪资模板主
*/
Boolean insertByBo(OaSalaryTemplateBo bo);
/**
* 修改薪资模板主
*/
Boolean updateByBo(OaSalaryTemplateBo bo);
/**
* 校验并批量删除薪资模板主信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,112 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaBindingItemDetailBo;
import com.ruoyi.oa.domain.vo.OaBindingItemDetailVo;
import com.ruoyi.oa.domain.OaBindingItemDetail;
import com.ruoyi.oa.mapper.OaBindingItemDetailMapper;
import com.ruoyi.oa.service.IOaBindingItemDetailService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 绑定记录明细Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaBindingItemDetailServiceImpl implements IOaBindingItemDetailService {
private final OaBindingItemDetailMapper baseMapper;
/**
* 查询绑定记录明细
*/
@Override
public OaBindingItemDetailVo queryById(Long bindingItemId){
return baseMapper.selectVoById(bindingItemId);
}
/**
* 查询绑定记录明细列表
*/
@Override
public TableDataInfo<OaBindingItemDetailVo> queryPageList(OaBindingItemDetailBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaBindingItemDetail> lqw = buildQueryWrapper(bo);
Page<OaBindingItemDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询绑定记录明细列表
*/
@Override
public List<OaBindingItemDetailVo> queryList(OaBindingItemDetailBo bo) {
LambdaQueryWrapper<OaBindingItemDetail> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaBindingItemDetail> buildQueryWrapper(OaBindingItemDetailBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaBindingItemDetail> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getBindingId() != null, OaBindingItemDetail::getBindingId, bo.getBindingId());
lqw.eq(StringUtils.isNotBlank(bo.getTemplateType()), OaBindingItemDetail::getTemplateType, bo.getTemplateType());
lqw.eq(bo.getItemDetailId() != null, OaBindingItemDetail::getItemDetailId, bo.getItemDetailId());
lqw.eq(bo.getPaidAmount() != null, OaBindingItemDetail::getPaidAmount, bo.getPaidAmount());
return lqw;
}
/**
* 新增绑定记录明细
*/
@Override
public Boolean insertByBo(OaBindingItemDetailBo bo) {
OaBindingItemDetail add = BeanUtil.toBean(bo, OaBindingItemDetail.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setBindingItemId(add.getBindingItemId());
}
return flag;
}
/**
* 修改绑定记录明细
*/
@Override
public Boolean updateByBo(OaBindingItemDetailBo bo) {
OaBindingItemDetail update = BeanUtil.toBean(bo, OaBindingItemDetail.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaBindingItemDetail entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除绑定记录明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,110 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaEmployeeBo;
import com.ruoyi.oa.domain.vo.OaEmployeeVo;
import com.ruoyi.oa.domain.OaEmployee;
import com.ruoyi.oa.mapper.OaEmployeeMapper;
import com.ruoyi.oa.service.IOaEmployeeService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 员工基础信息Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaEmployeeServiceImpl implements IOaEmployeeService {
private final OaEmployeeMapper baseMapper;
/**
* 查询员工基础信息
*/
@Override
public OaEmployeeVo queryById(Long employeeId){
return baseMapper.selectVoById(employeeId);
}
/**
* 查询员工基础信息列表
*/
@Override
public TableDataInfo<OaEmployeeVo> queryPageList(OaEmployeeBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaEmployee> lqw = buildQueryWrapper(bo);
Page<OaEmployeeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询员工基础信息列表
*/
@Override
public List<OaEmployeeVo> queryList(OaEmployeeBo bo) {
LambdaQueryWrapper<OaEmployee> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaEmployee> buildQueryWrapper(OaEmployeeBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaEmployee> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getEmployeeName()), OaEmployee::getEmployeeName, bo.getEmployeeName());
lqw.eq(StringUtils.isNotBlank(bo.getCompany()), OaEmployee::getCompany, bo.getCompany());
return lqw;
}
/**
* 新增员工基础信息
*/
@Override
public Boolean insertByBo(OaEmployeeBo bo) {
OaEmployee add = BeanUtil.toBean(bo, OaEmployee.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setEmployeeId(add.getEmployeeId());
}
return flag;
}
/**
* 修改员工基础信息
*/
@Override
public Boolean updateByBo(OaEmployeeBo bo) {
OaEmployee update = BeanUtil.toBean(bo, OaEmployee.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaEmployee entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除员工基础信息
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,274 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.*;
import com.ruoyi.oa.domain.vo.EmployeeSalaryRecordVo;
import com.ruoyi.oa.domain.vo.OaBindingItemDetailVo;
import com.ruoyi.oa.mapper.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaEmployeeTemplateBindingBo;
import com.ruoyi.oa.domain.vo.OaEmployeeTemplateBindingVo;
import com.ruoyi.oa.service.IOaEmployeeTemplateBindingService;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* 员工模板绑定及月度发放记录Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaEmployeeTemplateBindingServiceImpl implements IOaEmployeeTemplateBindingService {
@Autowired
private final OaEmployeeTemplateBindingMapper baseMapper;
@Autowired
private final OaBindingItemDetailMapper bindingItemDetailMapper;
@Autowired
private final OaEmployeeMapper employeeMapper;
@Autowired
private final OaSalaryTemplateDetailMapper salaryDetailMapper;
@Autowired
private final OaInsuranceTemplateDetailMapper insuranceDetailMapper;
/**
* 查询员工模板绑定及月度发放记录
*/
@Override
public OaEmployeeTemplateBindingVo queryById(Long bindingId){
return baseMapper.selectVoById(bindingId);
}
/**
* 查询员工模板绑定及月度发放记录列表
*/
@Override
public TableDataInfo<OaEmployeeTemplateBindingVo> queryPageList(OaEmployeeTemplateBindingBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaEmployeeTemplateBinding> lqw = buildQueryWrapper(bo);
Page<OaEmployeeTemplateBindingVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询员工模板绑定及月度发放记录列表
*/
@Override
public List<OaEmployeeTemplateBindingVo> queryList(OaEmployeeTemplateBindingBo bo) {
LambdaQueryWrapper<OaEmployeeTemplateBinding> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaEmployeeTemplateBinding> buildQueryWrapper(OaEmployeeTemplateBindingBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaEmployeeTemplateBinding> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getEmployeeId() != null, OaEmployeeTemplateBinding::getEmployeeId, bo.getEmployeeId());
lqw.eq(bo.getInsuranceTemplateId() != null, OaEmployeeTemplateBinding::getInsuranceTemplateId, bo.getInsuranceTemplateId());
lqw.eq(bo.getSalaryTemplateId() != null, OaEmployeeTemplateBinding::getSalaryTemplateId, bo.getSalaryTemplateId());
lqw.eq(bo.getPayYear() != null, OaEmployeeTemplateBinding::getPayYear, bo.getPayYear());
lqw.eq(bo.getPayMonth() != null, OaEmployeeTemplateBinding::getPayMonth, bo.getPayMonth());
lqw.eq(bo.getNetSalary() != null, OaEmployeeTemplateBinding::getNetSalary, bo.getNetSalary());
lqw.eq(bo.getTotalCompanyCost() != null, OaEmployeeTemplateBinding::getTotalCompanyCost, bo.getTotalCompanyCost());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OaEmployeeTemplateBinding::getStatus, bo.getStatus());
return lqw;
}
/**
* 新增员工模板绑定及月度发放记录
*/
@Override
public Boolean insertByBo(OaEmployeeTemplateBindingBo bo) {
OaEmployeeTemplateBinding add = BeanUtil.toBean(bo, OaEmployeeTemplateBinding.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setBindingId(add.getBindingId());
}
return flag;
}
/**
* 修改员工模板绑定及月度发放记录
*/
@Override
public Boolean updateByBo(OaEmployeeTemplateBindingBo bo) {
OaEmployeeTemplateBinding update = BeanUtil.toBean(bo, OaEmployeeTemplateBinding.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaEmployeeTemplateBinding entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除员工模板绑定及月度发放记录
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public Boolean calculateSalary(List<Long> employeeIds, Long payYear, Long payMonth,Long defaultInsuranceTemplateId, Long defaultSalaryTemplateId) {
// 参数校验
if (defaultInsuranceTemplateId == null || defaultSalaryTemplateId == null) {
throw new RuntimeException("请选择默认的薪资模板和社保模板");
}
for (Long employeeId : employeeIds) {
// 1. 检查本月是否已存在记录
OaEmployeeTemplateBinding exist = baseMapper.findByEmployeeAndMonth(employeeId, payYear, payMonth);
if (exist != null) {
// 已存在,跳过或更新
continue;
}
// 2. 获取上月的模板ID支持一键复制
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("待发");
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);
bindingItemDetailMapper.insert(item);
}
// 社保明细
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);
}
return true;
}
@Override
public Boolean finalizeSalary(List<Long> bindingIds) {
for (Long id : bindingIds) {
OaEmployeeTemplateBinding binding = baseMapper.selectById(id);
if (binding != null && !"已发".equals(binding.getStatus())) {
binding.setStatus("已发");
baseMapper.updateById(binding);
}
}
return true;
}
@Override
public List<EmployeeSalaryRecordVo> querySalaryHistory(Long employeeId) {
List<OaEmployeeTemplateBinding> list = baseMapper.selectList(
new LambdaQueryWrapper<OaEmployeeTemplateBinding>().eq(OaEmployeeTemplateBinding::getEmployeeId, employeeId)
.orderByDesc(OaEmployeeTemplateBinding::getPayYear, OaEmployeeTemplateBinding::getPayMonth)
);
return list.stream().map(this::toVo).collect(Collectors.toList());
}
// 工具方法主表转VO并查明细
private EmployeeSalaryRecordVo toVo(OaEmployeeTemplateBinding binding) {
if (binding == null) return null;
EmployeeSalaryRecordVo vo = new EmployeeSalaryRecordVo();
BeanUtils.copyProperties(binding, vo);
OaEmployee emp = employeeMapper.selectById(binding.getEmployeeId());
if (emp != null) {
vo.setEmployeeName(emp.getEmployeeName());
vo.setCompany(emp.getCompany());
}
List<OaBindingItemDetail> allDetails = bindingItemDetailMapper.selectList(
new LambdaQueryWrapper<OaBindingItemDetail>().eq(OaBindingItemDetail::getBindingId, binding.getBindingId())
);
vo.setSalaryDetails(allDetails.stream().filter(d -> "salary".equals(d.getTemplateType()))
.map(this::toDetailVo).collect(Collectors.toList()));
vo.setInsuranceDetails(allDetails.stream().filter(d -> "insurance".equals(d.getTemplateType()))
.map(this::toDetailVo).collect(Collectors.toList()));
return vo;
}
private OaBindingItemDetailVo toDetailVo(OaBindingItemDetail detail) {
OaBindingItemDetailVo vo = new OaBindingItemDetailVo();
BeanUtils.copyProperties(detail, vo);
// 可补充itemName等
return vo;
}
}

View File

@@ -0,0 +1,111 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaInsuranceTemplateDetailBo;
import com.ruoyi.oa.domain.vo.OaInsuranceTemplateDetailVo;
import com.ruoyi.oa.domain.OaInsuranceTemplateDetail;
import com.ruoyi.oa.mapper.OaInsuranceTemplateDetailMapper;
import com.ruoyi.oa.service.IOaInsuranceTemplateDetailService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 社保/公积金模板明细Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaInsuranceTemplateDetailServiceImpl implements IOaInsuranceTemplateDetailService {
private final OaInsuranceTemplateDetailMapper baseMapper;
/**
* 查询社保/公积金模板明细
*/
@Override
public OaInsuranceTemplateDetailVo queryById(Long insuranceDetailId){
return baseMapper.selectVoById(insuranceDetailId);
}
/**
* 查询社保/公积金模板明细列表
*/
@Override
public TableDataInfo<OaInsuranceTemplateDetailVo> queryPageList(OaInsuranceTemplateDetailBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaInsuranceTemplateDetail> lqw = buildQueryWrapper(bo);
Page<OaInsuranceTemplateDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询社保/公积金模板明细列表
*/
@Override
public List<OaInsuranceTemplateDetailVo> queryList(OaInsuranceTemplateDetailBo bo) {
LambdaQueryWrapper<OaInsuranceTemplateDetail> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaInsuranceTemplateDetail> buildQueryWrapper(OaInsuranceTemplateDetailBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaInsuranceTemplateDetail> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getInsuranceTemplateId() != null, OaInsuranceTemplateDetail::getInsuranceTemplateId, bo.getInsuranceTemplateId());
lqw.eq(StringUtils.isNotBlank(bo.getInsuranceType()), OaInsuranceTemplateDetail::getInsuranceType, bo.getInsuranceType());
lqw.eq(bo.getAmount() != null, OaInsuranceTemplateDetail::getAmount, bo.getAmount());
return lqw;
}
/**
* 新增社保/公积金模板明细
*/
@Override
public Boolean insertByBo(OaInsuranceTemplateDetailBo bo) {
OaInsuranceTemplateDetail add = BeanUtil.toBean(bo, OaInsuranceTemplateDetail.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setInsuranceDetailId(add.getInsuranceDetailId());
}
return flag;
}
/**
* 修改社保/公积金模板明细
*/
@Override
public Boolean updateByBo(OaInsuranceTemplateDetailBo bo) {
OaInsuranceTemplateDetail update = BeanUtil.toBean(bo, OaInsuranceTemplateDetail.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaInsuranceTemplateDetail entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除社保/公积金模板明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,109 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaInsuranceTemplateBo;
import com.ruoyi.oa.domain.vo.OaInsuranceTemplateVo;
import com.ruoyi.oa.domain.OaInsuranceTemplate;
import com.ruoyi.oa.mapper.OaInsuranceTemplateMapper;
import com.ruoyi.oa.service.IOaInsuranceTemplateService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 社保/公积金模板主Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaInsuranceTemplateServiceImpl implements IOaInsuranceTemplateService {
private final OaInsuranceTemplateMapper baseMapper;
/**
* 查询社保/公积金模板主
*/
@Override
public OaInsuranceTemplateVo queryById(Long insuranceTemplateId){
return baseMapper.selectVoById(insuranceTemplateId);
}
/**
* 查询社保/公积金模板主列表
*/
@Override
public TableDataInfo<OaInsuranceTemplateVo> queryPageList(OaInsuranceTemplateBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaInsuranceTemplate> lqw = buildQueryWrapper(bo);
Page<OaInsuranceTemplateVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询社保/公积金模板主列表
*/
@Override
public List<OaInsuranceTemplateVo> queryList(OaInsuranceTemplateBo bo) {
LambdaQueryWrapper<OaInsuranceTemplate> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaInsuranceTemplate> buildQueryWrapper(OaInsuranceTemplateBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaInsuranceTemplate> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getTemplateName()), OaInsuranceTemplate::getTemplateName, bo.getTemplateName());
return lqw;
}
/**
* 新增社保/公积金模板主
*/
@Override
public Boolean insertByBo(OaInsuranceTemplateBo bo) {
OaInsuranceTemplate add = BeanUtil.toBean(bo, OaInsuranceTemplate.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setInsuranceTemplateId(add.getInsuranceTemplateId());
}
return flag;
}
/**
* 修改社保/公积金模板主
*/
@Override
public Boolean updateByBo(OaInsuranceTemplateBo bo) {
OaInsuranceTemplate update = BeanUtil.toBean(bo, OaInsuranceTemplate.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaInsuranceTemplate entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除社保/公积金模板主
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,112 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaSalaryTemplateDetailBo;
import com.ruoyi.oa.domain.vo.OaSalaryTemplateDetailVo;
import com.ruoyi.oa.domain.OaSalaryTemplateDetail;
import com.ruoyi.oa.mapper.OaSalaryTemplateDetailMapper;
import com.ruoyi.oa.service.IOaSalaryTemplateDetailService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 薪资模板明细Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaSalaryTemplateDetailServiceImpl implements IOaSalaryTemplateDetailService {
private final OaSalaryTemplateDetailMapper baseMapper;
/**
* 查询薪资模板明细
*/
@Override
public OaSalaryTemplateDetailVo queryById(Long salaryDetailId){
return baseMapper.selectVoById(salaryDetailId);
}
/**
* 查询薪资模板明细列表
*/
@Override
public TableDataInfo<OaSalaryTemplateDetailVo> queryPageList(OaSalaryTemplateDetailBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaSalaryTemplateDetail> lqw = buildQueryWrapper(bo);
Page<OaSalaryTemplateDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询薪资模板明细列表
*/
@Override
public List<OaSalaryTemplateDetailVo> queryList(OaSalaryTemplateDetailBo bo) {
LambdaQueryWrapper<OaSalaryTemplateDetail> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaSalaryTemplateDetail> buildQueryWrapper(OaSalaryTemplateDetailBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaSalaryTemplateDetail> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getSalaryTemplateId() != null, OaSalaryTemplateDetail::getSalaryTemplateId, bo.getSalaryTemplateId());
lqw.eq(StringUtils.isNotBlank(bo.getSalaryItem()), OaSalaryTemplateDetail::getSalaryItem, bo.getSalaryItem());
lqw.eq(bo.getAmount() != null, OaSalaryTemplateDetail::getAmount, bo.getAmount());
lqw.eq(bo.getRate() != null, OaSalaryTemplateDetail::getRate, bo.getRate());
return lqw;
}
/**
* 新增薪资模板明细
*/
@Override
public Boolean insertByBo(OaSalaryTemplateDetailBo bo) {
OaSalaryTemplateDetail add = BeanUtil.toBean(bo, OaSalaryTemplateDetail.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setSalaryDetailId(add.getSalaryDetailId());
}
return flag;
}
/**
* 修改薪资模板明细
*/
@Override
public Boolean updateByBo(OaSalaryTemplateDetailBo bo) {
OaSalaryTemplateDetail update = BeanUtil.toBean(bo, OaSalaryTemplateDetail.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaSalaryTemplateDetail entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除薪资模板明细
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,109 @@
package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaSalaryTemplateBo;
import com.ruoyi.oa.domain.vo.OaSalaryTemplateVo;
import com.ruoyi.oa.domain.OaSalaryTemplate;
import com.ruoyi.oa.mapper.OaSalaryTemplateMapper;
import com.ruoyi.oa.service.IOaSalaryTemplateService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 薪资模板主Service业务层处理
*
* @author ruoyi
* @date 2025-06-23
*/
@RequiredArgsConstructor
@Service
public class OaSalaryTemplateServiceImpl implements IOaSalaryTemplateService {
private final OaSalaryTemplateMapper baseMapper;
/**
* 查询薪资模板主
*/
@Override
public OaSalaryTemplateVo queryById(Long salaryTemplateId){
return baseMapper.selectVoById(salaryTemplateId);
}
/**
* 查询薪资模板主列表
*/
@Override
public TableDataInfo<OaSalaryTemplateVo> queryPageList(OaSalaryTemplateBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<OaSalaryTemplate> lqw = buildQueryWrapper(bo);
Page<OaSalaryTemplateVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询薪资模板主列表
*/
@Override
public List<OaSalaryTemplateVo> queryList(OaSalaryTemplateBo bo) {
LambdaQueryWrapper<OaSalaryTemplate> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<OaSalaryTemplate> buildQueryWrapper(OaSalaryTemplateBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OaSalaryTemplate> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getTemplateName()), OaSalaryTemplate::getTemplateName, bo.getTemplateName());
return lqw;
}
/**
* 新增薪资模板主
*/
@Override
public Boolean insertByBo(OaSalaryTemplateBo bo) {
OaSalaryTemplate add = BeanUtil.toBean(bo, OaSalaryTemplate.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setSalaryTemplateId(add.getSalaryTemplateId());
}
return flag;
}
/**
* 修改薪资模板主
*/
@Override
public Boolean updateByBo(OaSalaryTemplateBo bo) {
OaSalaryTemplate update = BeanUtil.toBean(bo, OaSalaryTemplate.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OaSalaryTemplate entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除薪资模板主
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -102,7 +102,7 @@ public class SysOaProjectServiceImpl implements ISysOaProjectService {
" - COALESCE(finance_details.total_expenditure, 0)" +
")";
// 不用 wrapper.having(...)
// 不用 wrapper.having(...)
if ("profit".equals(profitType)) {
wrapper.apply(profitLossExpr + " > 0");
} else if ("loss".equals(profitType)) {