package com.ruoyi.staff.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.production.dto.UserAccountDto;
import com.ruoyi.production.dto.UserProductionAccountingDto;
import com.ruoyi.production.service.SalesLedgerProductionAccountingService;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.domain.SysUserDept;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.staff.controller.TaxCalculator;
import com.ruoyi.staff.dto.StaffOnJobDto;
import com.ruoyi.staff.mapper.SchemeInsuranceDetailMapper;
import com.ruoyi.staff.mapper.StaffOnJobMapper;
import com.ruoyi.staff.pojo.SchemeApplicableStaff;
import com.ruoyi.staff.mapper.SchemeApplicableStaffMapper;
import com.ruoyi.staff.pojo.SchemeInsuranceDetail;
import com.ruoyi.staff.pojo.StaffOnJob;
import com.ruoyi.staff.service.IStaffOnJobService;
import com.ruoyi.staff.service.SchemeApplicableStaffService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* 社保方案适用人员表 服务实现类
*
*
* @author 芯导软件(江苏)有限公司
* @since 2026-03-05 11:50:17
*/
@Service
public class SchemeApplicableStaffServiceImpl extends ServiceImpl implements SchemeApplicableStaffService {
@Autowired
private SchemeApplicableStaffMapper schemeApplicableStaffMapper;
@Autowired
private SchemeInsuranceDetailMapper schemeInsuranceDetailMapper;
@Autowired
private SysUserDeptMapper sysUserDeptMapper;
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private SysDeptMapper sysDeptMapper;
@Autowired
private StaffOnJobMapper staffOnJobMapper;
@Autowired
private SalesLedgerProductionAccountingService salesLedgerProductionAccountingService;
@Override
public AjaxResult listPage(Page page, SchemeApplicableStaff schemeApplicableStaff) {
LambdaQueryWrapper schemeApplicableStaffLambdaQueryWrapper = new LambdaQueryWrapper<>();
if(schemeApplicableStaff != null){
if(StringUtils.isNotEmpty(schemeApplicableStaff.getTitle())){
schemeApplicableStaffLambdaQueryWrapper.like(SchemeApplicableStaff::getTitle, schemeApplicableStaff.getTitle());
}
}
Page page1 = schemeApplicableStaffMapper.selectPage(page, schemeApplicableStaffLambdaQueryWrapper);
List collect = page1.getRecords().stream().map(SchemeApplicableStaff::getId).collect(Collectors.toList());
if(CollectionUtils.isEmpty(collect)){
return AjaxResult.success(page1);
}
List schemeInsuranceDetails = schemeInsuranceDetailMapper
.selectList(new LambdaQueryWrapper()
.in(SchemeInsuranceDetail::getSchemeId, collect));
page1.getRecords().forEach(item -> {
item.setSchemeInsuranceDetailList(schemeInsuranceDetails
.stream()
.filter(detail -> detail.getSchemeId().equals(item.getId()))
.collect(Collectors.toList()));
SysUser sysUser = sysUserMapper.selectUserById(item.getCreateUser().longValue());
item.setCreateUserName(sysUser == null ? "未知" : sysUser.getNickName());
// 获取部门信息
String[] split = item.getDeptIds().split(",");
List sysDepts = sysDeptMapper.selectList(new LambdaQueryWrapper()
.in(SysDept::getDeptId, Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList())));
if(!CollectionUtils.isEmpty(sysDepts)){
item.setDeptNames(sysDepts.stream().map(SysDept::getDeptName).collect(Collectors.joining(",")));
}
});
return AjaxResult.success(page1);
}
public void setSchemeApplicableStaffUserInfo(SchemeApplicableStaff schemeApplicableStaff) {
// 通过部门获取人员id
String[] split = schemeApplicableStaff.getDeptIds().split(",");
List staffOnJobs = staffOnJobMapper.selectList(new LambdaQueryWrapper()
.in(StaffOnJob::getSysDeptId, Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList())));
if(CollectionUtils.isEmpty(staffOnJobs)){
throw new IllegalArgumentException("部门下无员工");
}
schemeApplicableStaff.setStaffIds(staffOnJobs
.stream()
.map(StaffOnJob::getId)
.filter(Objects::nonNull) // 过滤掉 null 值
.map(String::valueOf)
.collect(Collectors.joining( ",")));
schemeApplicableStaff.setStaffNames(staffOnJobs.stream().map(StaffOnJob::getStaffName).collect(Collectors.joining(",")));
}
@Override
public AjaxResult add(SchemeApplicableStaff schemeApplicableStaff) {
if(schemeApplicableStaff == null){
return AjaxResult.error("参数错误");
}
if(CollectionUtils.isEmpty(schemeApplicableStaff.getSchemeInsuranceDetailList())){
return AjaxResult.error("请选择方案明细");
}
setSchemeApplicableStaffUserInfo(schemeApplicableStaff); //根据部门设置用户信息
int insert = schemeApplicableStaffMapper.insert(schemeApplicableStaff);
schemeApplicableStaff.getSchemeInsuranceDetailList().forEach(item -> {
item.setSchemeId(schemeApplicableStaff.getId());
schemeInsuranceDetailMapper.insert(item);
});
return AjaxResult.success(insert);
}
@Override
public AjaxResult updateSchemeApplicableStaff(SchemeApplicableStaff schemeApplicableStaff) {
if(schemeApplicableStaff == null){
return AjaxResult.error("参数错误");
}
setSchemeApplicableStaffUserInfo(schemeApplicableStaff); //根据部门设置用户信息
int update = schemeApplicableStaffMapper.updateById(schemeApplicableStaff);
// 先删,重新绑定
schemeInsuranceDetailMapper.delete(new LambdaQueryWrapper()
.eq(SchemeInsuranceDetail::getSchemeId, schemeApplicableStaff.getId()));
schemeApplicableStaff.getSchemeInsuranceDetailList().forEach(item -> {
item.setSchemeId(schemeApplicableStaff.getId());
schemeInsuranceDetailMapper.insert(item);
});
return AjaxResult.success(update);
}
@Override
public AjaxResult delete(List ids) {
if (CollectionUtils.isEmpty(ids)) {
return AjaxResult.error("参数错误");
}
int delete = schemeApplicableStaffMapper.deleteBatchIds(ids);
schemeInsuranceDetailMapper.delete(new LambdaQueryWrapper()
.in(SchemeInsuranceDetail::getSchemeId, ids));
return AjaxResult.success(delete);
}
/**
* 通过员工id计算社保方案
* @param id
*/
public void calculateByEmployeeId(Integer id,Map map,String date) {
// 1. 入参校验
if (id == null) {
return; // 或返回空列表,根据业务需求调整
}
Long staffId = id.longValue();
// 社保金额
BigDecimal schemeAmount = new BigDecimal("0.00");
// 公积金金额
BigDecimal gjj = new BigDecimal("0.00");
// 基本工资
BigDecimal basicSalary = new BigDecimal("0.00");
map.put("gjj", gjj); // 公积金
map.put("schemeAmount", schemeAmount); // 社保金额
map.put("basicSalary", basicSalary); // 基本工资
// 个税金额
BigDecimal salaryTax = new BigDecimal("0.00");
map.put("salaryTax", salaryTax);
// 计件工资
BigDecimal pieceSalary = new BigDecimal("0.00");
map.put("pieceSalary", pieceSalary);
// 计时工资
BigDecimal hourlySalary = new BigDecimal("0.00");
map.put("hourlySalary", hourlySalary);
// 其他收入
BigDecimal otherIncome = new BigDecimal("0.00");
map.put("otherIncome", otherIncome);
// 其他支出
BigDecimal otherDeduct = new BigDecimal("0.00");
map.put("otherDeduct", otherDeduct);
// 应发工资
BigDecimal grossSalary = new BigDecimal("0.00");
map.put("grossSalary", grossSalary);
// 应扣工资
BigDecimal deductSalary = new BigDecimal("0.00");
map.put("deductSalary", deductSalary);
// 实发工资
BigDecimal netSalary = new BigDecimal("0.00");
map.put("netSalary", netSalary);
// 调用基本工资
StaffOnJob staffOnJobDto = staffOnJobMapper.selectById(staffId);
if(staffOnJobDto == null){
return;
}
basicSalary = staffOnJobDto.getBasicSalary();
map.put("basicSalary", basicSalary);
// 应发工资
map.put("grossSalary", basicSalary);
// 个税金额(无社保版)
BigDecimal bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, schemeAmount, gjj);
map.put("salaryTax", bigDecimal);
// 计时工资 计件工资
UserProductionAccountingDto userProductionAccountingDto = new UserProductionAccountingDto();
userProductionAccountingDto.setUserId(getUidByStaffId(staffId));
userProductionAccountingDto.setDate(date);
UserAccountDto byUserId = salesLedgerProductionAccountingService.getByUserId(userProductionAccountingDto);
if(byUserId != null){
map.put("pieceSalary", byUserId.getAccountBalance());
map.put("hourlySalary", byUserId.getAccount());
// 应发 实发增加
grossSalary = grossSalary.add(byUserId.getAccountBalance()).add(byUserId.getAccount());
map.put("grossSalary", grossSalary);
netSalary = netSalary.add(byUserId.getAccountBalance()).add(byUserId.getAccount());
map.put("netSalary", netSalary);
}
// 2. 查询该人员对应的社保方案
List schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId);
if (CollectionUtils.isEmpty(schemeList)) {
return; // 无匹配方案,返回空列表
}
// 3. 为每个方案关联明细列表
for (SchemeApplicableStaff scheme : schemeList) {
List detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(scheme.getId());
// 根据明细列表计算社保缴费金额
if(CollectionUtils.isEmpty(detailList)){
continue;
}
for (SchemeInsuranceDetail detail : detailList) {
if("住房公积金".equals(detail.getInsuranceType())){
gjj = gjj.add(calculateByEmployeeIdType(detail.getInsuranceType(),gjj, staffOnJobDto, detail));
}else{
schemeAmount = schemeAmount.add(calculateByEmployeeIdType(detail.getInsuranceType(),schemeAmount, staffOnJobDto, detail));
}
}
}
map.put("schemeAmount", schemeAmount);
map.put("gjj", gjj);
// 个税金额(社保版)
bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, schemeAmount, gjj);
map.put("salaryTax", bigDecimal);
// 应扣工资
map.put("deductSalary", bigDecimal.add(gjj).add(schemeAmount));
// 实发工资
map.put("netSalary", basicSalary.subtract(bigDecimal).subtract(gjj).subtract(schemeAmount));
}
/**
* 通过员工Id获取用户id
* @param staffId
* @return
*/
public Long getUidByStaffId(Long staffId){
StaffOnJob staffOnJob = staffOnJobMapper.selectById(staffId);
if(staffOnJob == null){
return -1L; // 返回不存在Id
}
SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper()
.eq(SysUser::getUserName, staffOnJob.getStaffNo())
.eq(SysUser::getDelFlag, "0")
.last("limit 1"));
if(sysUser == null){
return -1L; // 返回不存在Id
}
return sysUser.getUserId();
}
/**
* 计算
* @param type
* @param bigDecimal
* @param staffOnJobDto
* @param detail
* @return
*/
public BigDecimal calculateByEmployeeIdType(String type,BigDecimal bigDecimal, StaffOnJob staffOnJobDto,SchemeInsuranceDetail detail) {
// 判断是否调用基本工资
if (detail.getUseBasicSalary() == 1) {
BigDecimal divide = detail.getPaymentBase().multiply(detail.getPersonalRatio()).divide(new BigDecimal("100"), 2);
bigDecimal = bigDecimal.add(divide);
}else{
// 调用基本工资
BigDecimal multiply = staffOnJobDto.getBasicSalary().multiply(detail.getPersonalRatio().divide(new BigDecimal("100"), 2));
bigDecimal = bigDecimal.add(multiply);
}
bigDecimal = bigDecimal.add(detail.getPersonalFixed());
return bigDecimal;
}
}