| | |
| | | |
| | | 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.dto.UserAccountDto; |
| | | import com.ruoyi.production.dto.UserProductionAccountingDto; |
| | | 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.SysUserDeptMapper; |
| | | 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.mapper.SchemeApplicableStaffMapper; |
| | | import com.ruoyi.staff.pojo.SchemeInsuranceDetail; |
| | | import com.ruoyi.staff.pojo.StaffOnJob; |
| | | import com.ruoyi.staff.service.SchemeApplicableStaffService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.util.*; |
| | | 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; |
| | | |
| | | /** |
| | |
| | | * @since 2026-03-05 11:50:17 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class SchemeApplicableStaffServiceImpl extends ServiceImpl<SchemeApplicableStaffMapper, SchemeApplicableStaff> 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; |
| | | 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 |
| | |
| | | schemeApplicableStaffLambdaQueryWrapper.like(SchemeApplicableStaff::getTitle, schemeApplicableStaff.getTitle()); |
| | | } |
| | | } |
| | | schemeApplicableStaffLambdaQueryWrapper.orderByDesc(SchemeApplicableStaff::getId); |
| | | Page<SchemeApplicableStaff> page1 = schemeApplicableStaffMapper.selectPage(page, schemeApplicableStaffLambdaQueryWrapper); |
| | | List<Long> collect = page1.getRecords().stream().map(SchemeApplicableStaff::getId).collect(Collectors.toList()); |
| | | if(CollectionUtils.isEmpty(collect)){ |
| | |
| | | * @param id |
| | | */ |
| | | public void calculateByEmployeeId(Integer id,Map<String, Object> map,String date) { |
| | | // 1. 入参校验 |
| | | if (id == null) { |
| | | return; // 或返回空列表,根据业务需求调整 |
| | | if (id == null || map == null) { |
| | | return; |
| | | } |
| | | Long staffId = id.longValue(); |
| | | // 社保金额 |
| | | BigDecimal socialPersonal = new BigDecimal("0.00"); |
| | | // 公积金金额 |
| | | BigDecimal fundPersonal = new BigDecimal("0.00"); |
| | | // 基本工资 |
| | | BigDecimal basicSalary = new BigDecimal("0.00"); |
| | | map.put("fundPersonal", fundPersonal); // 公积金 |
| | | map.put("socialPersonal", socialPersonal); // 社保金额 |
| | | 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, socialPersonal, fundPersonal); |
| | | map.put("salaryTax", bigDecimal); |
| | | // 计时工资 计件工资 |
| | | 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){ |
| | | 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); |
| | | pieceSalary = normalizeMoney(byUserId.getAccountBalance()); |
| | | hourlySalary = normalizeMoney(byUserId.getAccount()); |
| | | } |
| | | // 2. 查询该人员对应的社保方案 |
| | | |
| | | // 查询该人员对应的社保方案 |
| | | List<SchemeApplicableStaff> schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId); |
| | | if (CollectionUtils.isEmpty(schemeList)) { |
| | | return; // 无匹配方案,返回空列表 |
| | | } |
| | | // 3. 为每个方案关联明细列表 |
| | | for (SchemeApplicableStaff scheme : schemeList) { |
| | | List<SchemeInsuranceDetail> 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)); |
| | | if (!CollectionUtils.isEmpty(schemeList)) { |
| | | for (SchemeApplicableStaff scheme : schemeList) { |
| | | List<SchemeInsuranceDetail> 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); |
| | | // 个税金额(社保版) |
| | | bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, socialPersonal, fundPersonal); |
| | | map.put("salaryTax", bigDecimal); |
| | | // 应扣工资 |
| | | map.put("deductSalary", bigDecimal.add(fundPersonal).add(socialPersonal)); |
| | | // 实发工资 |
| | | map.put("netSalary", basicSalary.subtract(bigDecimal).subtract(fundPersonal).subtract(socialPersonal)); |
| | | |
| | | map.put("otherDeduct", otherDeduct); |
| | | map.put("socialSupplementAmount", socialSupplementAmount); |
| | | map.put("grossSalary", grossSalary); |
| | | map.put("salaryTax", salaryTax); |
| | | map.put("deductSalary", deductSalary); |
| | | map.put("netSalary", netSalary); |
| | | } |
| | | |
| | | /** |
| | |
| | | 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<SchemeInsuranceDetail> 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<String, Object> map, String key) { |
| | | return map != null && map.get(key) != null; |
| | | } |
| | | |
| | | private boolean hasText(Map<String, Object> 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<String, Object> 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); |
| | | } |
| | | } |