huminmin
7 小时以前 6be17495cd29ba8b28af35da7ba171cbc0d61c21
根据单个员工计算工资
已添加1个文件
已修改4个文件
293 ■■■■■ 文件已修改
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/service/StaffSalaryMainService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | 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 = "通过员工id重算单个员工工资")
    @PostMapping("/calculateByEmployeeId")
    public AjaxResult calculateByEmployeeId(@RequestBody StaffSalaryCalculateDto calculateSalaryCalculateDto) {
        return staffSalaryMainService.calculateSalaryByEmployee(calculateSalaryCalculateDto);
    }
    @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/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 calculateSalaryCalculateDto);
}
src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
@@ -164,91 +164,84 @@
            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("socialSupplementAmount", BigDecimal.ZERO); // ç¤¾ä¿è¡¥ç¼´é‡‘额
        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);
        // æ ¹æ®æŽ’班数据计算白班天数和夜班天数
        BigDecimal dayDays = new BigDecimal("0.00");
        BigDecimal nightDays = new BigDecimal("0.00");
        // å‰ç«¯ä¼ å…¥çš„可编辑值优先,其余字段由后端统一计算
        boolean hasBasicSalaryInput = hasValue(map, "basicSalary");
        boolean hasDayDaysInput = hasValue(map, "dayDays");
        boolean hasNightDaysInput = hasValue(map, "nightDays");
        boolean hasPieceSalaryInput = hasValue(map, "pieceSalary");
        boolean hasHourlySalaryInput = hasValue(map, "hourlySalary");
        boolean hasSocialPersonalInput = hasValue(map, "socialPersonal");
        boolean hasFundPersonalInput = hasValue(map, "fundPersonal");
        BigDecimal basicSalary = getBigDecimal(map, "basicSalary");
        BigDecimal dayDays = getBigDecimal(map, "dayDays");
        BigDecimal nightDays = getBigDecimal(map, "nightDays");
        BigDecimal pieceSalary = getBigDecimal(map, "pieceSalary");
        BigDecimal hourlySalary = getBigDecimal(map, "hourlySalary");
        BigDecimal otherIncome = getBigDecimal(map, "otherIncome");
        BigDecimal otherDeduct = getBigDecimal(map, "otherDeduct");
        BigDecimal socialPersonalInput = getBigDecimal(map, "socialPersonal");
        BigDecimal fundPersonalInput = getBigDecimal(map, "fundPersonal");
        BigDecimal socialPersonal = BigDecimal.ZERO;
        BigDecimal fundPersonal = BigDecimal.ZERO;
        BigDecimal salaryTax = BigDecimal.ZERO;
        BigDecimal grossSalary = BigDecimal.ZERO;
        BigDecimal deductSalary = BigDecimal.ZERO;
        BigDecimal netSalary = BigDecimal.ZERO;
        BigDecimal dayDaysInput = dayDays;
        BigDecimal nightDaysInput = nightDays;
        otherIncome = defaultIfNull(otherIncome);
        otherDeduct = defaultIfNull(otherDeduct);
        map.put("socialSupplementAmount", BigDecimal.ZERO);
        // æŸ¥è¯¢å½“月排班记录
        List<PersonalShift> shiftList = personalShiftMapper.selectList(new LambdaQueryWrapper<PersonalShift>()
                .eq(PersonalShift::getStaffOnJobId, staffId)
                .like(PersonalShift::getWorkTime, date));
        BigDecimal computedDayDays = BigDecimal.ZERO;
        BigDecimal computedNightDays = BigDecimal.ZERO;
        if (!hasDayDaysInput || !hasNightDaysInput) {
            List<PersonalShift> shiftList = personalShiftMapper.selectList(new LambdaQueryWrapper<PersonalShift>()
                    .eq(PersonalShift::getStaffOnJobId, staffId)
                    .like(PersonalShift::getWorkTime, date));
        if(!CollectionUtils.isEmpty(shiftList)){
            // æ”¶é›†æ‰€æœ‰ç­æ¬¡é…ç½®ID
            List<Integer> configIds = shiftList.stream()
                    .map(PersonalShift::getPersonalAttendanceLocationConfigId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(shiftList)){
                // æ”¶é›†æ‰€æœ‰ç­æ¬¡é…ç½®ID
                List<Integer> configIds = shiftList.stream()
                        .map(PersonalShift::getPersonalAttendanceLocationConfigId)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(configIds)){
                // æŸ¥è¯¢ç­æ¬¡é…ç½®ä¿¡æ¯
                List<PersonalAttendanceLocationConfig> configList = personalAttendanceLocationConfigMapper.selectList(
                        new LambdaQueryWrapper<PersonalAttendanceLocationConfig>()
                                .in(PersonalAttendanceLocationConfig::getId, configIds));
                if(!CollectionUtils.isEmpty(configIds)){
                    // æŸ¥è¯¢ç­æ¬¡é…ç½®ä¿¡æ¯
                    List<PersonalAttendanceLocationConfig> configList = personalAttendanceLocationConfigMapper.selectList(
                            new LambdaQueryWrapper<PersonalAttendanceLocationConfig>()
                                    .in(PersonalAttendanceLocationConfig::getId, configIds));
                // æž„建班次配置映射
                Map<Integer, String> configMap = configList.stream()
                        .collect(Collectors.toMap(
                                PersonalAttendanceLocationConfig::getId,
                                PersonalAttendanceLocationConfig::getShift,
                                (a, b) -> a));
                    // æž„建班次配置映射
                    Map<Integer, String> configMap = configList.stream()
                            .collect(Collectors.toMap(
                                    PersonalAttendanceLocationConfig::getId,
                                    PersonalAttendanceLocationConfig::getShift,
                                    (a, b) -> a));
                // ç»Ÿè®¡ç™½ç­å’Œå¤œç­å¤©æ•°
                for (PersonalShift shift : shiftList) {
                    Integer configId = shift.getPersonalAttendanceLocationConfigId();
                    String shiftName = configMap.get(configId);
                    if(shiftName != null){
                        // æ ¹æ®ç­æ¬¡åç§°åˆ¤æ–­ï¼šåŒ…含"白"或"日"为白班,包含"夜"为夜班
                        if(shiftName.contains("白") || shiftName.contains("日")){
                            dayDays = dayDays.add(BigDecimal.ONE);
                        } else if(shiftName.contains("夜")){
                            nightDays = nightDays.add(BigDecimal.ONE);
                    // ç»Ÿè®¡ç™½ç­å’Œå¤œç­å¤©æ•°
                    for (PersonalShift shift : shiftList) {
                        Integer configId = shift.getPersonalAttendanceLocationConfigId();
                        String shiftName = configMap.get(configId);
                        if(shiftName != null){
                            // æ ¹æ®ç­æ¬¡åç§°åˆ¤æ–­ï¼šåŒ…含"白"或"日"为白班,包含"夜"为夜班
                            if(shiftName.contains("白") || shiftName.contains("日")){
                                computedDayDays = computedDayDays.add(BigDecimal.ONE);
                            } else if(shiftName.contains("夜")){
                                computedNightDays = computedNightDays.add(BigDecimal.ONE);
                            }
                        }
                    }
                }
            }
        }
        dayDays = hasDayDaysInput ? defaultIfNull(dayDaysInput) : computedDayDays;
        nightDays = hasNightDaysInput ? defaultIfNull(nightDaysInput) : computedNightDays;
        map.put("dayDays", dayDays); // ç™½ç­å¤©æ•°
        map.put("nightDays", nightDays); // å¤œç­å¤©æ•°
        // æŸ¥è¯¢é¤è¡¥å’Œå¤œç­è¡¥è´´
        // è®¡ç®—餐补(回族特有)和夜班补助
        BigDecimal mealAmount = new BigDecimal("0.00"); // é¤è¡¥
        BigDecimal nightAmount = new BigDecimal("0.00"); // å¤œç­è¡¥åŠ©
        // èŽ·å–é¤è¡¥å’Œå¤œç­è¡¥è´´æ ‡å‡†ï¼ˆä»Žè¡¥è´´é…ç½®ä¸­èŽ·å–ï¼‰
        SubsidyConfiguration subsidyConfig = subsidyConfigurationMapper.selectOne(null);
@@ -265,7 +258,17 @@
            return;
        }
        if (!hasBasicSalaryInput) {
            basicSalary = defaultIfNull(staffOnJobDto.getBasicSalary());
        } else {
            basicSalary = defaultIfNull(basicSalary);
        }
        String nation = staffOnJobDto.getNation();
        // æŸ¥è¯¢é¤è¡¥å’Œå¤œç­è¡¥è´´
        // è®¡ç®—餐补(回族特有)和夜班补助
        BigDecimal mealAmount = new BigDecimal("0.00"); // é¤è¡¥
        BigDecimal nightAmount = new BigDecimal("0.00"); // å¤œç­è¡¥åŠ©
        if("回族".equals(nation)){
            mealAmount = dayDays.add(nightDays).multiply(mealStandard);
        }
@@ -277,28 +280,37 @@
        map.put("nightAmount", nightAmount); // å¤œç­è¡¥åŠ©
        // è°ƒç”¨åŸºæœ¬å·¥èµ„
        basicSalary = staffOnJobDto.getBasicSalary();
        map.put("basicSalary", basicSalary);
        // åº”发工资(基本工资+餐补+夜班补助+其他收入)
        grossSalary = basicSalary.add(mealAmount).add(nightAmount).add(otherIncome);
        map.put("otherIncome", otherIncome);
        map.put("otherDeduct", otherDeduct);
        // è®¡æ—¶å·¥èµ„ è®¡ä»¶å·¥èµ„
        if (!hasPieceSalaryInput || !hasHourlySalaryInput) {
            UserProductionAccountingDto userProductionAccountingDto = new UserProductionAccountingDto();
            userProductionAccountingDto.setUserId(getUidByStaffId(staffId));
            userProductionAccountingDto.setDate(date);
            UserAccountDto byUserId = salesLedgerProductionAccountingService.getByUserId(userProductionAccountingDto);
            if(byUserId != null){
                if (!hasPieceSalaryInput) {
                    pieceSalary = byUserId.getAccountBalance();
                }
                if (!hasHourlySalaryInput) {
                    hourlySalary = byUserId.getAccount();
                }
            }
        }
        map.put("pieceSalary", defaultIfNull(pieceSalary));
        map.put("hourlySalary", defaultIfNull(hourlySalary));
        // åº”发工资(基本工资+餐补+夜班补助+计件工资+计时工资+其他收入)
        grossSalary = basicSalary
                .add(mealAmount)
                .add(nightAmount)
                .add(defaultIfNull(pieceSalary))
                .add(defaultIfNull(hourlySalary))
                .add(otherIncome);
        map.put("grossSalary", grossSalary);
        // å®žå‘工资初始值
        netSalary = grossSalary;
        map.put("netSalary", netSalary);
        // è®¡æ—¶å·¥èµ„ è®¡ä»¶å·¥èµ„
        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<SchemeApplicableStaff> schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId);
        if (CollectionUtils.isEmpty(schemeList)) {
@@ -320,25 +332,30 @@
                socialPersonal = socialPersonal.add(amount);
            }
        }
        BigDecimal currentMonthSocialPersonal = socialPersonal;
        BigDecimal currentMonthSocialPersonal = hasSocialPersonalInput ? defaultIfNull(socialPersonalInput) : socialPersonal;
        if (!hasSocialPersonalInput) {
            map.put("socialPersonal", currentMonthSocialPersonal);
        }
        BigDecimal resolvedFundPersonal = hasFundPersonalInput ? defaultIfNull(fundPersonalInput) : fundPersonal;
        if (!hasFundPersonalInput) {
            map.put("fundPersonal", resolvedFundPersonal);
        }
        BigDecimal socialSupplementAmount = calculateSocialSupplementAmount(
                staffId,
                staffOnJobDto,
                targetMonth,
                currentScheme,
                currentDetailList,
                socialPersonal
                currentMonthSocialPersonal
        );
        BigDecimal totalSocialPersonal = currentMonthSocialPersonal.add(socialSupplementAmount);
        map.put("socialPersonal", currentMonthSocialPersonal);
        map.put("fundPersonal", fundPersonal);
        map.put("socialSupplementAmount", socialSupplementAmount);
        // ä¸ªç¨Žé‡‘额(社保版)
        BigDecimal bigDecimal = TaxCalculator.calculateMonthlyTax(grossSalary, totalSocialPersonal, fundPersonal);
        BigDecimal bigDecimal = TaxCalculator.calculateMonthlyTax(grossSalary, totalSocialPersonal, resolvedFundPersonal);
        map.put("salaryTax", bigDecimal);
        // åº”扣工资 = ä¸ªç¨Ž + å…¬ç§¯é‡‘个人 + ç¤¾ä¿ä¸ªäºº + ç¤¾ä¿è¡¥ç¼´ + å…¶ä»–支出
        deductSalary = bigDecimal.add(fundPersonal).add(totalSocialPersonal).add(otherDeduct);
        deductSalary = bigDecimal.add(resolvedFundPersonal).add(totalSocialPersonal).add(otherDeduct);
        map.put("deductSalary", deductSalary);
        // å®žå‘工资 = åº”发工资 - åº”扣工资
@@ -347,6 +364,32 @@
    }
    private BigDecimal getBigDecimal(Map<String, Object> map, String key) {
        if (map == null || !map.containsKey(key) || map.get(key) == null) {
            return null;
        }
        Object value = map.get(key);
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Number) {
            return new BigDecimal(value.toString());
        }
        String text = String.valueOf(value).trim();
        if (text.isEmpty()) {
            return null;
        }
        return new BigDecimal(text);
    }
    private boolean hasValue(Map<String, Object> map, String key) {
        return map != null && map.containsKey(key) && map.get(key) != null;
    }
    private BigDecimal defaultIfNull(BigDecimal value) {
        return value == null ? BigDecimal.ZERO : value;
    }
    /**
     * é€šè¿‡å‘˜å·¥Id获取用户id
     * @param staffId
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,38 @@
        return AjaxResult.success(mapList);
    }
    @Override
    public AjaxResult calculateSalaryByEmployee(StaffSalaryCalculateDto calculateSalaryCalculateDto) {
        if (calculateSalaryCalculateDto == null || calculateSalaryCalculateDto.getStaffOnJobId() == null
                || StringUtils.isEmpty(calculateSalaryCalculateDto.getSalaryMonth())) {
            return AjaxResult.error("参数错误");
        }
        Map<String, Object> result = new HashMap<>();
        result.put("id", calculateSalaryCalculateDto.getStaffOnJobId().intValue());
        result.put("staffOnJobId", calculateSalaryCalculateDto.getStaffOnJobId());
        result.put("basicSalary", calculateSalaryCalculateDto.getBasicSalary());
        result.put("dayDays", calculateSalaryCalculateDto.getDayDays());
        result.put("nightDays", calculateSalaryCalculateDto.getNightDays());
        result.put("pieceSalary", calculateSalaryCalculateDto.getPieceSalary());
        result.put("hourlySalary", calculateSalaryCalculateDto.getHourlySalary());
        result.put("otherIncome", calculateSalaryCalculateDto.getOtherIncome());
        result.put("otherDeduct", calculateSalaryCalculateDto.getOtherDeduct());
        result.put("socialPersonal", calculateSalaryCalculateDto.getSocialPersonal());
        result.put("fundPersonal", calculateSalaryCalculateDto.getFundPersonal());
        result.put("salaryTax", calculateSalaryCalculateDto.getSalaryTax());
        result.put("grossSalary", calculateSalaryCalculateDto.getGrossSalary());
        result.put("deductSalary", calculateSalaryCalculateDto.getDeductSalary());
        result.put("netSalary", calculateSalaryCalculateDto.getNetSalary());
        result.put("remark", calculateSalaryCalculateDto.getRemark());
        result.put("salaryMonth", calculateSalaryCalculateDto.getSalaryMonth());
        schemeApplicableStaffService.calculateByEmployeeId(
                calculateSalaryCalculateDto.getStaffOnJobId().intValue(),
                result,
                calculateSalaryCalculateDto.getSalaryMonth()
        );
        return AjaxResult.success(result);
    }
    public List<Map<String, Object>> setSchemeApplicableStaffUserInfo(List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return new ArrayList<>();