huminmin
6 小时以前 f688d1656a6542f1756f62e2f10a11ff4489674a
修改社保工资计算
已添加1个文件
已修改7个文件
287 ■■■■ 文件已修改
src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/dto/StaffSalaryCalculateDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
@@ -5,6 +5,7 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.staff.dto.CalculateSalaryDto;
import com.ruoyi.staff.dto.StaffSalaryCalculateDto;
import com.ruoyi.staff.pojo.StaffSalaryMain;
import com.ruoyi.staff.service.StaffSalaryMainService;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -43,6 +44,12 @@
        return staffSalaryMainService.calculateSalary(calculateSalaryDto);
    }
    @Operation(summary = "按员工重算工资明细")
    @PostMapping("/calculateByEmployeeId")
    public AjaxResult calculateByEmployeeId(@RequestBody StaffSalaryCalculateDto staffSalaryCalculateDto) {
        return staffSalaryMainService.calculateSalaryByEmployee(staffSalaryCalculateDto);
    }
    @PostMapping("/add")
    @Operation(summary = "新建工资表")
    @Log(title = "新建工资表", businessType = BusinessType.INSERT)
src/main/java/com/ruoyi/staff/dto/StaffSalaryCalculateDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.staff.dto;
import com.ruoyi.staff.pojo.StaffSalaryDetail;
import lombok.Data;
/**
 * å•个员工工资重算参数
 */
@Data
public class StaffSalaryCalculateDto extends StaffSalaryDetail {
    /**
     * å·¥èµ„月份,格式 yyyy-MM
     */
    private String salaryMonth;
}
src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java
@@ -26,6 +26,13 @@
    List<SchemeApplicableStaff> selectSchemeByStaffId(@Param("staffId") Long staffId);
    /**
     * æ ¹æ®éƒ¨é—¨ID查询最新社保方案
     * @param deptId éƒ¨é—¨ID
     * @return æœ€æ–°ç¤¾ä¿æ–¹æ¡ˆ
     */
    SchemeApplicableStaff selectLatestSchemeByDeptId(@Param("deptId") Long deptId);
    /**
     * æ ¹æ®ç¤¾ä¿æ–¹æ¡ˆID查询对应的明细列表
     * @param schemeId ç¤¾ä¿æ–¹æ¡ˆID
     * @return æ–¹æ¡ˆæ˜Žç»†åˆ—表
src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
@@ -68,6 +68,9 @@
    @Schema(description = "其他支出")
    private BigDecimal otherDeduct;
    @Schema(description = "社保补缴")
    private BigDecimal socialSupplementAmount;
    @Schema(description = "工资个税")
    private BigDecimal salaryTax;
src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.staff.dto.CalculateSalaryDto;
import com.ruoyi.staff.dto.StaffSalaryCalculateDto;
import com.ruoyi.staff.pojo.StaffSalaryMain;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -27,4 +28,6 @@
    AjaxResult delete(List<Long> ids);
    AjaxResult calculateSalary(CalculateSalaryDto calculateSalaryDto);
    AjaxResult calculateSalaryByEmployee(StaffSalaryCalculateDto staffSalaryCalculateDto);
}
src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
@@ -25,6 +25,7 @@
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;
@@ -153,100 +154,85 @@
     * @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);
    }
    /**
@@ -290,4 +276,64 @@
        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);
    }
}
src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
@@ -7,6 +7,7 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
import com.ruoyi.staff.dto.CalculateSalaryDto;
import com.ruoyi.staff.dto.StaffSalaryCalculateDto;
import com.ruoyi.staff.mapper.StaffLeaveMapper;
import com.ruoyi.staff.mapper.StaffSalaryDetailMapper;
import com.ruoyi.staff.mapper.StaffSalaryMainMapper;
@@ -20,6 +21,7 @@
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -135,6 +137,43 @@
        return AjaxResult.success(mapList);
    }
    @Override
    public AjaxResult calculateSalaryByEmployee(StaffSalaryCalculateDto staffSalaryCalculateDto) {
        if (staffSalaryCalculateDto == null
                || staffSalaryCalculateDto.getStaffOnJobId() == null
                || StringUtils.isEmpty(staffSalaryCalculateDto.getSalaryMonth())) {
            return AjaxResult.error("参数错误");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("id", staffSalaryCalculateDto.getStaffOnJobId());
        map.put("staffOnJobId", staffSalaryCalculateDto.getStaffOnJobId());
        map.put("salaryMonth", staffSalaryCalculateDto.getSalaryMonth());
        map.put("staffName", staffSalaryCalculateDto.getStaffName());
        map.put("postName", staffSalaryCalculateDto.getPostName());
        map.put("deptName", staffSalaryCalculateDto.getDeptName());
        if (staffSalaryCalculateDto.getBasicSalary() != null) {
            map.put("basicSalary", staffSalaryCalculateDto.getBasicSalary());
        }
        map.put("pieceSalary", staffSalaryCalculateDto.getPieceSalary());
        map.put("hourlySalary", staffSalaryCalculateDto.getHourlySalary());
        map.put("otherIncome", staffSalaryCalculateDto.getOtherIncome());
        map.put("socialPersonal", staffSalaryCalculateDto.getSocialPersonal());
        map.put("fundPersonal", staffSalaryCalculateDto.getFundPersonal());
        map.put("otherDeduct", staffSalaryCalculateDto.getOtherDeduct());
        map.put("socialSupplementAmount", staffSalaryCalculateDto.getSocialSupplementAmount());
        map.put("salaryTax", staffSalaryCalculateDto.getSalaryTax());
        map.put("grossSalary", staffSalaryCalculateDto.getGrossSalary());
        map.put("deductSalary", staffSalaryCalculateDto.getDeductSalary());
        map.put("netSalary", staffSalaryCalculateDto.getNetSalary());
        map.put("remark", staffSalaryCalculateDto.getRemark());
        schemeApplicableStaffService.calculateByEmployeeId(
                staffSalaryCalculateDto.getStaffOnJobId().intValue(),
                map,
                staffSalaryCalculateDto.getSalaryMonth()
        );
        return AjaxResult.success(map);
    }
    public List<Map<String, Object>> setSchemeApplicableStaffUserInfo(List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return new ArrayList<>();
src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml
@@ -25,6 +25,20 @@
        create_time DESC
    </select>
    <!-- æ ¹æ®éƒ¨é—¨ID查询最新社保方案 -->
    <select id="selectLatestSchemeByDeptId" resultType="com.ruoyi.staff.pojo.SchemeApplicableStaff">
        SELECT
        <include refid="schemeColumns"/>
        FROM
        scheme_applicable_staff
        WHERE
        1 = 1
        AND FIND_IN_SET(#{deptId}, dept_ids)
        ORDER BY
        create_time DESC
        LIMIT 1
    </select>
    <!-- æŸ¥è¯¢æ–¹æ¡ˆå¯¹åº”的明细 -->
    <select id="selectDetailBySchemeId" resultType="com.ruoyi.staff.pojo.SchemeInsuranceDetail">
        SELECT