package com.ruoyi.staff.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.production.bean.dto.UserAccountDto; import com.ruoyi.production.bean.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.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.staff.controller.TaxCalculator; import com.ruoyi.staff.mapper.SchemeApplicableStaffMapper; import com.ruoyi.staff.mapper.SchemeInsuranceDetailMapper; import com.ruoyi.staff.mapper.StaffOnJobMapper; import com.ruoyi.staff.pojo.SchemeApplicableStaff; import com.ruoyi.staff.pojo.SchemeInsuranceDetail; import com.ruoyi.staff.pojo.StaffOnJob; import com.ruoyi.staff.service.SchemeApplicableStaffService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; /** *

* 社保方案适用人员表 服务实现类 *

* * @author 芯导软件(江苏)有限公司 * @since 2026-03-05 11:50:17 */ @Service @RequiredArgsConstructor public class SchemeApplicableStaffServiceImpl extends ServiceImpl implements SchemeApplicableStaffService { private final SchemeApplicableStaffMapper schemeApplicableStaffMapper; private final SchemeInsuranceDetailMapper schemeInsuranceDetailMapper; private final SysUserMapper sysUserMapper; private final SysDeptMapper sysDeptMapper; private final StaffOnJobMapper staffOnJobMapper; private final 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()); } } schemeApplicableStaffLambdaQueryWrapper.orderByDesc(SchemeApplicableStaff::getId); 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) { if (id == null || map == null) { return; } Long staffId = id.longValue(); StaffOnJob staffOnJobDto = staffOnJobMapper.selectById(staffId); if(staffOnJobDto == null){ return; } BigDecimal basicSalary = hasValue(map, "basicSalary") ? normalizeMoney(getBigDecimal(map, "basicSalary")) : normalizeMoney(staffOnJobDto.getBasicSalary()); BigDecimal otherIncome = normalizeMoney(getBigDecimal(map, "otherIncome")); BigDecimal otherDeduct = normalizeMoney(getBigDecimal(map, "otherDeduct")); BigDecimal socialSupplementAmount = hasValue(map, "socialSupplementAmount") ? normalizeMoney(getBigDecimal(map, "socialSupplementAmount")) : calculateLatestDeptSocialSupplementAmount(staffOnJobDto); BigDecimal pieceSalary = normalizeMoney(getBigDecimal(map, "pieceSalary")); BigDecimal hourlySalary = normalizeMoney(getBigDecimal(map, "hourlySalary")); BigDecimal socialPersonal = normalizeMoney(getBigDecimal(map, "socialPersonal")); BigDecimal fundPersonal = normalizeMoney(getBigDecimal(map, "fundPersonal")); UserProductionAccountingDto userProductionAccountingDto = new UserProductionAccountingDto(); userProductionAccountingDto.setUserId(getUidByStaffId(staffId)); userProductionAccountingDto.setDate(date); UserAccountDto byUserId = salesLedgerProductionAccountingService.getByUserId(userProductionAccountingDto); if(byUserId != null){ pieceSalary = normalizeMoney(byUserId.getAccountBalance()); hourlySalary = normalizeMoney(byUserId.getAccount()); } // 查询该人员对应的社保方案 List schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId); if (!CollectionUtils.isEmpty(schemeList)) { for (SchemeApplicableStaff scheme : schemeList) { List detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(scheme.getId()); if(CollectionUtils.isEmpty(detailList)){ continue; } for (SchemeInsuranceDetail detail : detailList) { if("公积金".equals(detail.getInsuranceType())){ fundPersonal = fundPersonal.add(calculateByEmployeeIdType(detail.getInsuranceType(), fundPersonal, staffOnJobDto, detail)); }else{ socialPersonal = socialPersonal.add(calculateByEmployeeIdType(detail.getInsuranceType(), socialPersonal, staffOnJobDto, detail)); } } } } BigDecimal grossSalary = basicSalary.add(pieceSalary).add(hourlySalary).add(otherIncome); BigDecimal salaryTax = TaxCalculator.calculateMonthlyTax( grossSalary, socialPersonal.add(socialSupplementAmount), fundPersonal ); BigDecimal deductSalary = salaryTax .add(fundPersonal) .add(socialPersonal) .add(socialSupplementAmount) .add(otherDeduct); BigDecimal netSalary = grossSalary.subtract(deductSalary); if (!hasText(map, "staffName")) { map.put("staffName", staffOnJobDto.getStaffName()); } if (!hasText(map, "nation")) { map.put("nation", staffOnJobDto.getNation()); } map.put("basicSalary", basicSalary); map.put("pieceSalary", pieceSalary); map.put("hourlySalary", hourlySalary); map.put("otherIncome", otherIncome); map.put("socialPersonal", socialPersonal); map.put("fundPersonal", fundPersonal); map.put("otherDeduct", otherDeduct); map.put("socialSupplementAmount", socialSupplementAmount); map.put("grossSalary", grossSalary); map.put("salaryTax", salaryTax); map.put("deductSalary", deductSalary); map.put("netSalary", netSalary); } /** * 通过员工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; } private BigDecimal calculateLatestDeptSocialSupplementAmount(StaffOnJob staffOnJobDto) { if (staffOnJobDto == null || staffOnJobDto.getSysDeptId() == null) { return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); } SchemeApplicableStaff latestScheme = schemeApplicableStaffMapper.selectLatestSchemeByDeptId(staffOnJobDto.getSysDeptId()); if (latestScheme == null) { return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); } List detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(latestScheme.getId()); if (CollectionUtils.isEmpty(detailList)) { return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); } BigDecimal socialSupplementAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); for (SchemeInsuranceDetail detail : detailList) { if (!"公积金".equals(detail.getInsuranceType())) { socialSupplementAmount = socialSupplementAmount.add( calculateByEmployeeIdType(detail.getInsuranceType(), socialSupplementAmount, staffOnJobDto, detail) ); } } return socialSupplementAmount.setScale(2, RoundingMode.HALF_UP); } private boolean hasValue(Map map, String key) { return map != null && map.get(key) != null; } private boolean hasText(Map map, String key) { if (map == null) { return false; } Object value = map.get(key); return value != null && !String.valueOf(value).trim().isEmpty(); } private BigDecimal getBigDecimal(Map map, String key) { if (map == null) { return null; } Object value = map.get(key); if (value == null) { return null; } if (value instanceof BigDecimal) { return (BigDecimal) value; } if (value instanceof Number) { return new BigDecimal(String.valueOf(value)); } String text = String.valueOf(value).trim(); if (text.isEmpty()) { return null; } return new BigDecimal(text); } private BigDecimal normalizeMoney(BigDecimal value) { return value == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : value.setScale(2, RoundingMode.HALF_UP); } }