package com.ruoyi.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.service.DictService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.pay.domain.*;
import com.ruoyi.pay.domain.bo.*;
import com.ruoyi.pay.domain.vo.*;
import com.ruoyi.pay.enums.PayCalcType;
import com.ruoyi.pay.mapper.*;
import com.ruoyi.pay.util.SalaryExportUtil;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.pay.service.IPaySalaryReportService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工资明细总Service业务层处理
 *
 * @author ruoyi
 * @date 2025-05-12
 */
@RequiredArgsConstructor
@Service
public class PaySalaryReportServiceImpl implements IPaySalaryReportService {

    private final PaySalaryReportMapper baseMapper;
    private final PayEmployeeInfoMapper payEmployeeInfoMapper;
    private final DictService dictService;
    @Resource
    private PayBaohuoWorktimeMapper payBaohuoWorktimeMapper;
    @Resource
    private PayBaohuoWorktimeServiceImpl payBaohuoWorktimeService;
    @Resource
    private PayBaohuoEmployeeMapper sgrBaohuoEmployeeMapper;
    @Resource
    private PayButieEmplyeeMapper sgrButieEmplyeeMapper;
    @Resource
    private PayButieServiceImpl butieService;
    @Resource
    private PayWorkOrderEmployeeMapper sgrWorkOrderEmployeeMapper;
    @Resource
    private PayWorkTimeMapper sgrWorkTimeMapper;
    @Resource
    private PayWorkTimeServiceImpl payWorkTimeService;
    @Resource
    private PayRequireAttendanceReportMapper sgrRequireAttendanceReportMapper;
    @Resource
    private PayRequireAttendanceReportServiceImpl payRequireAttendanceReportService;
    @Resource
    private PayDayWorkHoursMapper sgrDayWorkHoursMapper;
    @Resource
    private PayDayWorkHoursServiceImpl payDayWorkHoursService;
    @Resource
    private PayDwHoursContrastMapper sgrDwHoursContrastMapper;
    @Resource
    private PayEmployeeInfoServiceImpl employeeInfoService;
    @Resource
    private PayEmployeeInfoMapper employeeInfoMapper;
    @Resource
    private PaySalaryReportMapper sgrSalaryReportMapper;


    /**
     * 查询工资明细总
     */
    @Override
    public PaySalaryReportVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询工资明细总列表
     */
    @Override
    public TableDataInfo<PaySalaryReportVo> queryPageList(PaySalaryReportBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PaySalaryReport> lqw = buildQueryWrapper(bo);
        Page<PaySalaryReportVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询最近一个月的工资
     */
    @Override
    public TableDataInfo<PaySalaryReportVo> queryLastMonthReport(Long tenantId, PageQuery pageQuery) {
        LambdaQueryWrapper<PaySalaryReport> lqw = new LambdaQueryWrapper<>();
        lqw.eq(tenantId != null, PaySalaryReport::getTenantId, tenantId);
        Page<PaySalaryReportVo> result =  baseMapper.queryLastMonthReport(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询工资明细总列表
     */
    @Override
    public List<PaySalaryReportVo> queryList(PaySalaryReportBo bo) {
        LambdaQueryWrapper<PaySalaryReport> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PaySalaryReport> buildQueryWrapper(PaySalaryReportBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PaySalaryReport> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getTenantId() != null, PaySalaryReport::getTenantId, bo.getTenantId());
        lqw.eq(StringUtils.isNotBlank(bo.getYear()), PaySalaryReport::getYear, bo.getYear());
        lqw.eq(StringUtils.isNotBlank(bo.getMonth()), PaySalaryReport::getMonth, bo.getMonth());
        lqw.eq(bo.getDeptId() != null, PaySalaryReport::getDeptId, bo.getDeptId());
        lqw.like(StringUtils.isNotBlank(bo.getDeptName()), PaySalaryReport::getDeptName, bo.getDeptName());
        lqw.eq(bo.getEmployeeId() != null, PaySalaryReport::getEmployeeId, bo.getEmployeeId());
        lqw.like(StringUtils.isNotBlank(bo.getEmployeeName()), PaySalaryReport::getEmployeeName, bo.getEmployeeName());
        lqw.eq(bo.getBasicSalary() != null, PaySalaryReport::getBasicSalary, bo.getBasicSalary());
        lqw.eq(bo.getActuallyDays() != null, PaySalaryReport::getActuallyDays, bo.getActuallyDays());
        lqw.eq(bo.getActuallyHours() != null, PaySalaryReport::getActuallyHours, bo.getActuallyHours());
        lqw.eq(bo.getDayWorkHours() != null, PaySalaryReport::getDayWorkHours, bo.getDayWorkHours());
        lqw.eq(bo.getWorkOrderHours() != null, PaySalaryReport::getWorkOrderHours, bo.getWorkOrderHours());
        lqw.eq(bo.getOvertimeWorkHours() != null, PaySalaryReport::getOvertimeWorkHours, bo.getOvertimeWorkHours());
        lqw.eq(bo.getRigongHelpHours() != null, PaySalaryReport::getRigongHelpHours, bo.getRigongHelpHours());
        lqw.eq(bo.getDayWorkPay() != null, PaySalaryReport::getDayWorkPay, bo.getDayWorkPay());
        lqw.eq(bo.getWorkOrderPay() != null, PaySalaryReport::getWorkOrderPay, bo.getWorkOrderPay());
        lqw.eq(bo.getOvertime() != null, PaySalaryReport::getOvertime, bo.getOvertime());
        lqw.eq(bo.getBanggongPay() != null, PaySalaryReport::getBanggongPay, bo.getBanggongPay());
        lqw.eq(bo.getZhibanOrLahuo() != null, PaySalaryReport::getZhibanOrLahuo, bo.getZhibanOrLahuo());
        lqw.eq(bo.getHoliday() != null, PaySalaryReport::getHoliday, bo.getHoliday());
        lqw.eq(bo.getPost() != null, PaySalaryReport::getPost, bo.getPost());
        lqw.eq(bo.getPhoneCharge() != null, PaySalaryReport::getPhoneCharge, bo.getPhoneCharge());
        lqw.eq(bo.getContract() != null, PaySalaryReport::getContract, bo.getContract());
        lqw.eq(bo.getFullTime() != null, PaySalaryReport::getFullTime, bo.getFullTime());
        lqw.eq(bo.getDiffOfLastMonth() != null, PaySalaryReport::getDiffOfLastMonth, bo.getDiffOfLastMonth());
        lqw.eq(bo.getShoudPayMoney() != null, PaySalaryReport::getShoudPayMoney, bo.getShoudPayMoney());
        lqw.eq(bo.getLate() != null, PaySalaryReport::getLate, bo.getLate());
        lqw.eq(bo.getInsurance() != null, PaySalaryReport::getInsurance, bo.getInsurance());
        lqw.eq(bo.getActuallyPayMoney() != null, PaySalaryReport::getActuallyPayMoney, bo.getActuallyPayMoney());
        lqw.eq(StringUtils.isNotBlank(bo.getAllButieData()), PaySalaryReport::getAllButieData, bo.getAllButieData());
        lqw.eq(StringUtils.isNotBlank(bo.getNote()), PaySalaryReport::getNote, bo.getNote());
        lqw.eq(bo.getEmpQuery() != null, PaySalaryReport::getEmpQuery, bo.getEmpQuery());
        return lqw;
    }

    /**
     * 新增工资明细总
     */
    @Override
    public Boolean insertByBo(PaySalaryReportBo bo) {
        PaySalaryReport add = BeanUtil.toBean(bo, PaySalaryReport.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改工资明细总
     */
    @Override
    public Boolean updateByBo(PaySalaryReportBo bo) {
        PaySalaryReport update = BeanUtil.toBean(bo, PaySalaryReport.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    @Override
    public Boolean updateByBo2(PaySalaryReport entity) {
        PaySalaryReportBo bo = BeanUtil.toBean(entity, PaySalaryReportBo.class);
        UpdateWrapper<PaySalaryReport> upw =new UpdateWrapper<>();
        upw.set(bo.getEmpQuery() != null,"emp_query",bo.getEmpQuery())
            .eq("year",entity.getYear()).eq("month",entity.getMonth());
        return baseMapper.update(entity,upw) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PaySalaryReport entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除工资明细总
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public void export(HttpServletRequest request, HttpServletResponse response, List<PaySalaryReportVo> list) {
        //创建excel表头
        List<String> column = new ArrayList<>();
        column.add("年");
        column.add("月");
        column.add("部门名称");
        column.add("员工姓名");
        column.add("基本工资");
        column.add("实际出勤天数");
        column.add("实际出勤小时数");
        column.add("出勤工时");
        column.add("包活工时");
        column.add("加班工时");
        column.add("日工帮工工时");
        column.add("日工工资");
        column.add("包活工资");
        column.add("加班工资");
        column.add("帮工工资");

        //解决导出不同月份数据  并且月份中补贴项不同的情况
        List<ButieMoneyAndTypes> allButie=new ArrayList<>();
        for(PaySalaryReportVo report : list){
            String jsonString = report.getAllButieData();
            List<ButieMoneyAndTypes> butieMoney = JSON.parseArray(jsonString, ButieMoneyAndTypes.class);
            allButie.addAll(butieMoney);
        }
        List<ButieMoneyAndTypes> buties = allButie.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
            -> new TreeSet<ButieMoneyAndTypes>(Comparator.comparing(ButieMoneyAndTypes :: getBuTieName))), ArrayList::new));
        //获取type类型为1的补贴项
        List<ButieMoneyAndTypes> butie1 = buties.stream().filter(butieMoney -> "1".equals(butieMoney.getType())).collect(Collectors.toList());
        //获取type类型为0的补贴项
        List<ButieMoneyAndTypes> butie0 = buties.stream().filter(butieMoney -> "0".equals(butieMoney.getType())).collect(Collectors.toList());
        //循环遍历补贴项
        for (ButieMoneyAndTypes butie : butie1) {
            column.add(butie.getBuTieName());
        }
        column.add("应付工资");
        for (ButieMoneyAndTypes butie : butie0) {
            column.add(butie.getBuTieName());
        }
        //合并type补贴项  1的在前面
        butie1.addAll(butie0);
        column.add("实发工资");
        column.add("开户行");
        column.add("银行卡号");
        column.add("备注说明");  //补贴项中有一项客户起名备注导致导出时被覆盖为真正的备注信息，这备注改名为备注说明避免上述情况

        //表头对应的数据
        List<Map<String, Object>> data = new ArrayList<>();

        //遍历获取到的需要导出的数据，k要和表头一样
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> dataMap = new HashMap<>();
            PaySalaryReportVo sr = list.get(i);
            int j = 0;
            dataMap.put(column.get(j), sr.getYear());
            dataMap.put(column.get(++j), sr.getMonth());
            dataMap.put(column.get(++j), sr.getDeptName());
            dataMap.put(column.get(++j), sr.getEmployeeName());
            dataMap.put(column.get(++j), new BigDecimal(sr.getBasicSalary().stripTrailingZeros().toPlainString()));
            dataMap.put(column.get(++j), sr.getActuallyDays());
            dataMap.put(column.get(++j), sr.getActuallyHours());
            dataMap.put(column.get(++j), sr.getDayWorkHours());
            dataMap.put(column.get(++j), sr.getWorkOrderHours());
            dataMap.put(column.get(++j), sr.getOvertimeWorkHours());
            dataMap.put(column.get(++j), sr.getRigongHelpHours());  //客户要求添加日工帮工工时展示
            dataMap.put(column.get(++j), new BigDecimal(sr.getDayWorkPay().stripTrailingZeros().toPlainString()));
            dataMap.put(column.get(++j), new BigDecimal(sr.getWorkOrderPay().stripTrailingZeros().toPlainString()));
            dataMap.put(column.get(++j), new BigDecimal(sr.getOvertime().stripTrailingZeros().toPlainString()));
            dataMap.put(column.get(++j), new BigDecimal(sr.getBanggongPay().stripTrailingZeros().toPlainString()));
            boolean flag2 = false;
            //循环遍历补贴项
            for (ButieMoneyAndTypes butie : butie1) {
                // 获取该员工的补贴项
                List<ButieMoneyAndTypes> butieMoneyList = JSON.parseArray(sr.getAllButieData(), ButieMoneyAndTypes.class);
                // 获取到循环列对应的补贴项
                List<ButieMoneyAndTypes> filterList = butieMoneyList.stream().filter(s -> s.getBuTieName().equals(butie.getBuTieName())).collect(Collectors.toList());
                //补贴项完毕  添加应付工资   后面继续添加扣减项
                if ("0".equals(butie.getType()) && !flag2) { // 扣减项
                    flag2 = true;
                    dataMap.put(column.get(++j), new BigDecimal(sr.getShoudPayMoney().stripTrailingZeros().toPlainString()));
                }
                //判断是否存在该项补贴  不存在存0
                if(filterList!=null&&filterList.size()>0){
                    // 获取对应的补贴金额并去掉金额末尾多余的0
                    BigDecimal money = new BigDecimal(filterList.get(0).getMoney().stripTrailingZeros().toPlainString());

                    if (column.get(++j).equals(butie.getBuTieName())) {
                        dataMap.put(column.get(j), money);
                    }
                }else{
                    if (column.get(++j).equals(butie.getBuTieName())) {
                        dataMap.put(column.get(j), new BigDecimal("0").stripTrailingZeros().toPlainString());
                    }
                }

            }
            dataMap.put(column.get(++j), new BigDecimal(sr.getActuallyPayMoney().stripTrailingZeros().toPlainString()));
            PayEmployeeInfo empInfo = payEmployeeInfoMapper.selectSgrEmployeeInfoByIdHasDel(sr.getEmployeeId());
            if (ObjectUtil.isNotNull(empInfo)) {
                dataMap.put(column.get(++j), empInfo.getOpeningBank());
                dataMap.put(column.get(++j), empInfo.getBankCardNumber());
                dataMap.put(column.get(++j), sr.getNote());
                data.add(dataMap);
            }
        }

        //调用导出工具类
        SalaryExportUtil.exportExcel("工资明细表", column, data, request, response);

    }

    @Override
    @Transactional
    public R<Void> generateSalaryReport(String date, boolean updateSupport, Long tenantId) {
        Integer successNums = 0;
        Integer failedNums = 0;
        StringBuffer successMsg = new StringBuffer();
        StringBuffer failedMsg = new StringBuffer();
        String year = date.split("-")[0];
        String month = date.split("-")[1];
        Date yearMonth;
        try {
            yearMonth = new SimpleDateFormat("yyyy-MM").parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return R.fail("系统日期格式转换错误");
        }
        PaySalaryReportBo re = new PaySalaryReportBo();
        re.setTenantId(tenantId);
        re.setYear(year);
        re.setMonth(month);
        List<PaySalaryReportVo> sgrSalaryReports = this.queryList(re);
        if (sgrSalaryReports != null && sgrSalaryReports.size() > 0) {
            if (updateSupport) {
                //已有本月数据  做更新操作
                List<Long> collect = sgrSalaryReports.stream().map(PaySalaryReportVo::getId).collect(Collectors.toList());
                    baseMapper.deleteBatchIds(collect);
            } else {
                return R.ok("如需更新生成报表，请勾选更新");
            }
        }

        //1.拿到所有员工信息
        //测试单个员工
/*        SgrEmployeeInfo emp =new SgrEmployeeInfo();
        emp.setName("卢志伟");
        List<SgrEmployeeInfo> employeeInfoList = sgrEmployeeInfoMapper.selectSgrEmployeeInfoList(emp);*/
        PayEmployeeInfoBo employeeInfoBo = new PayEmployeeInfoBo();
        employeeInfoBo.setTenantId(tenantId);
        List<PayEmployeeInfoVo> employeeInfoList = employeeInfoService.queryList(employeeInfoBo);

        //获取所有补贴类型
        PayButieBo butiebo = new PayButieBo();
        butiebo.setTenantId(tenantId);
        List<PayButieVo> sgrButies = butieService.queryList(butiebo);
        for (PayEmployeeInfoVo employeeInfo : employeeInfoList) {
            if (employeeInfo.getPayCalcType() == null) {
                failedNums++;
                failedMsg.append("<br/>" + employeeInfo.getName() + "：的工资计算类型不能为空");
                continue;
            }
            if (employeeInfo.getBasicSalary() == null) {
                failedNums++;
                failedMsg.append("<br/>" + employeeInfo.getName() + "：的基本工资信息不能为空");
                continue;
            }
            PaySalaryReport sgrSalaryReport = new PaySalaryReport();
            String empName = employeeInfo.getName();
            sgrSalaryReport.setTenantId(tenantId);
            sgrSalaryReport.setEmployeeId(employeeInfo.getId());
            sgrSalaryReport.setEmployeeName(employeeInfo.getName());
            sgrSalaryReport.setYear(year);
            sgrSalaryReport.setMonth(month);
            sgrSalaryReport.setBasicSalary(employeeInfo.getBasicSalary());
            sgrSalaryReport.setDeptId(employeeInfo.getDeptId());
            //当type类型为包月时只能在此保存部门名称
            String DeptName = employeeInfoMapper.selectDeptNameByDeptNo(employeeInfo.getDeptId());
            sgrSalaryReport.setDeptName(DeptName);

            //1.根据员工信息获取应出勤信息、包活及流程卡信息、补贴信息
            //1.1获取应出勤信息
            PayRequireAttendanceReportBo attendanceReport1 = new PayRequireAttendanceReportBo();
            attendanceReport1.setTenantId(tenantId);
            attendanceReport1.setEmpName(empName);
            attendanceReport1.setYear(year);
            attendanceReport1.setMonth(month);
            PayRequireAttendanceReportVo attendanceReport =BeanUtil.toBean(attendanceReport1,PayRequireAttendanceReportVo.class);
            BigDecimal yingchuqintianshu = BigDecimal.ZERO;
            List<PayRequireAttendanceReportVo> attendanceReports = payRequireAttendanceReportService.queryList(attendanceReport1);
            if (attendanceReports != null && attendanceReports.size() > 0) {
                attendanceReport = attendanceReports.get(0);
                if (attendanceReport.getRequireDays().equals(0L)) {
                    failedNums++;
                    failedMsg.append("<br/>错误：" + employeeInfo.getName() + "的应出勤天数为0");
                    continue;
                }
                if (attendanceReport.getLeaveDays() == null) {
                    attendanceReport.setLeaveDays(new BigDecimal("0"));
                }
                yingchuqintianshu = new BigDecimal(attendanceReport.getRequireDays());
                sgrSalaryReport.setActuallyDays(attendanceReport.getAvtiveDays());
                sgrSalaryReport.setActuallyHours(attendanceReport.getAttendanceHours());
                sgrSalaryReport.setOvertimeWorkHours(attendanceReport.getOvertimeHours());
                sgrSalaryReport.setNote(attendanceReport.getRemark());
            } else if (!employeeInfo.getPayCalcType().equals(PayCalcType.TYPE5.getValue())) {
                failedNums++;
                failedMsg.append("<br/>未找到:" + employeeInfo.getName() + "的应出勤信息");
                continue;
                // return AjaxResult.error("未找到"+employeeInfo.getName()+"的应出勤信息");
            }
            //1.2获取员工日工工时信息
            PayDayWorkHoursQuery sgrdayworkHoursQuery = new PayDayWorkHoursQuery();
            BigDecimal rigongbanggong = BigDecimal.ZERO; //日工帮工小时数
            sgrdayworkHoursQuery.setDwYearMonth(date);
            sgrdayworkHoursQuery.setEmpName(employeeInfo.getName());
            List<PayDayWorkHoursQuery> sgrDayWorkHoursQueryList = payDayWorkHoursService.selectPayDayWorkHoursList2(sgrdayworkHoursQuery);
            if (sgrDayWorkHoursQueryList != null && sgrDayWorkHoursQueryList.size() > 0) {
                for (PayDayWorkHoursQuery dayWorkHour : sgrDayWorkHoursQueryList) {
                    for (PayDwHoursContrast dwHoursContrast : dayWorkHour.getDwHoursContrasts()) {
                        if (dwHoursContrast.getIsHelper() == 1) {
                            BigDecimal datePoor = dwHoursContrast.getHours();
                            rigongbanggong = rigongbanggong.add(datePoor);
                        }
                    }
                }
            }
            /*if(employeeInfo.getName().equals("赵向进")){   //测试使用的
                System.out.println(".....");
            }*/
            sgrSalaryReport.setRigongHelpHours(rigongbanggong);//2023-10-16 客户要求展示日工帮工工时

            //1.3获取员工包活及流程卡信息
            //流程卡工时
            PayWorkTimeBo workTime = new PayWorkTimeBo();
            workTime.setEmpId(employeeInfo.getId());
            workTime.setDate(yearMonth);
            List<PayWorkTimeVo> sgrWorkTimes = payWorkTimeService.queryList(workTime);
            BigDecimal baohuogongshi = BigDecimal.ZERO; //包活工时
            if (sgrWorkTimes != null && sgrWorkTimes.size() > 0) {
                for (PayWorkTimeVo time : sgrWorkTimes) {
                    baohuogongshi = baohuogongshi.add(time.getValidHours());
                }
            }
            //包活工时
            PayBaohuoWorktime bhtime = new PayBaohuoWorktime();
            bhtime.setEmpId(employeeInfo.getId());
            bhtime.setDate(yearMonth);
            List<PayBaohuoWorktime> bhtimes = payBaohuoWorktimeMapper.selectBaohuoWorktimeList(bhtime);
            if (bhtimes != null && bhtimes.size() > 0) {
                for (PayBaohuoWorktime btime : bhtimes) {
                    baohuogongshi = baohuogongshi.add(btime.getValidHours());
                }
            }
            //流程卡工资
            BigDecimal baohuogongzi = BigDecimal.ZERO;  //包活工资
            BigDecimal baohuobanggongGZ = BigDecimal.ZERO;//包活帮工工资
            PayWorkOrderEmployeeBo woEmployee = new PayWorkOrderEmployeeBo();
            woEmployee.setEmpName(empName);
            woEmployee.setIntime(yearMonth);
            woEmployee.setTenantId(tenantId);
            List<PayWorkOrderEmployee> woEmployees = sgrWorkOrderEmployeeMapper.selectPayWorkOrderEmployeeList1(woEmployee);
            for (PayWorkOrderEmployee woe : woEmployees) {
                if (woe.getHelper() == 0) {
                    baohuogongzi = baohuogongzi.add(woe.getAmount());
                } else {
                    baohuobanggongGZ = baohuobanggongGZ.add(woe.getAmount());
                }
            }

            //包活工资
            PayBaohuoEmployeeBo bhEmployee = new PayBaohuoEmployeeBo();
            bhEmployee.setTenantId(tenantId);
            bhEmployee.setEmpName(empName);
            bhEmployee.setIntime(yearMonth);
            List<PayBaohuoEmployee> bhEmployees = sgrBaohuoEmployeeMapper.selectSgrBaohuoEmployeeList1(bhEmployee);
            for (PayBaohuoEmployee bhe : bhEmployees) {
                if (bhe.getHelper() == 0) {
                    baohuogongzi = baohuogongzi.add(bhe.getAmount());
                } else {
                    baohuobanggongGZ = baohuobanggongGZ.add(bhe.getAmount());
                }
            }
            sgrSalaryReport.setWorkOrderHours(baohuogongshi);
            sgrSalaryReport.setWorkOrderPay(baohuogongzi.setScale(2, BigDecimal.ROUND_HALF_UP));

            //1.4获取补贴信息
            List<ButieMoneyAndTypes> butieMoneyAndTypesList = new ArrayList<>();
            for (PayButieVo butie : sgrButies) {
                ButieMoneyAndTypes butieMoneyAndType = new ButieMoneyAndTypes();
                BigDecimal money = sgrButieEmplyeeMapper.getMoneyByInfo(employeeInfo.getId(), butie.getId(), date);
                butieMoneyAndType.setBuTieName(butie.getName());
                //补贴扣减全勤和津贴需要按比例发放
/*                if(money.compareTo(BigDecimal.ZERO)!=0){
                    if((butie.getName().equals("全勤奖")||butie.getName().equals("岗位津贴"))&&!employeeInfo.getPayCalcType().equals(PayCalcType.TYPE5.getValue())
                    &&attendanceReport.getRequireDays().longValue()>attendanceReport.getAvtiveDays().longValue()){
                        BigDecimal moneyPerHour = money.divide(new BigDecimal(attendanceReport.getRequireDays()),4,BigDecimal.ROUND_HALF_UP)
                                .divide(employeeInfo.getHoursPerDay(),4,BigDecimal.ROUND_HALF_UP);
                        money =moneyPerHour.multiply(new BigDecimal(attendanceReport.getAvtiveDays()).multiply(employeeInfo.getHoursPerDay()).add(attendanceReport.getAttendanceHours()));
                    }
                }*/
                butieMoneyAndType.setMoney(money.setScale(2, BigDecimal.ROUND_HALF_UP));
                butieMoneyAndType.setType(butie.getType());
                butieMoneyAndTypesList.add(butieMoneyAndType);
            }
            sgrSalaryReport.setAllButieData(JSON.toJSONString(butieMoneyAndTypesList));

           /* SgrButieEmplyee butieEmplyee = new SgrButieEmplyee();
            butieEmplyee.setButieId(employeeInfo.getId());
            butieEmplyee.setDate(date);
            List<SgrButieEmplyee> butieEmplyeeList=sgrButieEmplyeeMapper.selectSgrButieEmplyeeList(butieEmplyee);
            if(butieEmplyeeList!=null&&butieEmplyeeList.size()>0){
                hasBuTie=true;
                sgrSalaryReport.setAllBieteiData(JSON.toJSONString(butieEmplyeeList.get(0)));
            }else{
                sgrSalaryReport.setAllBieteiData(JSON.toJSONString(new SgrButieEmplyee()));
            }*/

            //根据不同计算类型计算
            String payCalcType = employeeInfo.getPayCalcType();
            BigDecimal yingfagongzi;
            BigDecimal shifagongzi;
            BigDecimal chuqingongshi = BigDecimal.ZERO;
            BigDecimal jiabangongzi = BigDecimal.ZERO;
            BigDecimal rigongbanggongGZ = BigDecimal.ZERO;
            BigDecimal payPerHour;
            if (!payCalcType.equals(PayCalcType.TYPE5.getValue())) {
                //出勤工时=实际出勤天数*每日小时数+实际出勤小时数
                chuqingongshi = new BigDecimal(sgrSalaryReport.getActuallyDays()).multiply(employeeInfo.getHoursPerDay()).add(sgrSalaryReport.getActuallyHours());
            }
            sgrSalaryReport.setDayWorkHours(chuqingongshi);
            BigDecimal rigonggongzi = BigDecimal.ZERO;
            //日工工时=出勤工时-包活工时-日工帮工
            BigDecimal rigonghours = chuqingongshi.subtract(baohuogongshi).subtract(rigongbanggong);//日工工时数
            /*0:日薪(日工工资+包活工资)
            1:月薪(日工工资+包活工资)
            2:喷涂按小时数(16/17、17/18)
            3.外贸按小时数(17/21)
            4.包月工资*/
            switch (payCalcType) {
                case "0": //工资计算类型：日薪（日工工资+包活工资）
                    //日工工资=基本工资/每日应出勤工时*日工工时
                    payPerHour = sgrSalaryReport.getBasicSalary().divide(employeeInfo.getHoursPerDay(), 4, BigDecimal.ROUND_HALF_UP);
                    rigonggongzi = payPerHour.multiply(rigonghours);
                    jiabangongzi = payPerHour.multiply(new BigDecimal("1.3")).multiply(sgrSalaryReport.getOvertimeWorkHours());
                    rigongbanggongGZ = payPerHour.multiply(rigongbanggong);
                    break;
                case "1":   //工资计算类型：月薪（日工工资+包活工资）
                    //小时工资=基本工资/应出勤天数/员工每日应出勤小时数
                    // 日工工资==小时工资 *（实际出勤天数 *员工每日应出勤小时数 +实际出勤小时数）
                    payPerHour = sgrSalaryReport.getBasicSalary().divide(yingchuqintianshu, 4, BigDecimal.ROUND_HALF_UP).
                        divide(employeeInfo.getHoursPerDay(), 4, BigDecimal.ROUND_HALF_UP);
                    rigonggongzi = payPerHour.multiply(rigonghours);
                    jiabangongzi = payPerHour.multiply(new BigDecimal("1.3")).multiply(sgrSalaryReport.getOvertimeWorkHours());
                    rigongbanggongGZ = payPerHour.multiply(rigongbanggong);
                    break;
                case "2":  //工资计算类型：喷涂按小时
                    //出勤工时需要达到234并且本月请假天数不能超过4天   工时工资按高工资计算
                    //客户需求修改：去掉234小时的判断
                    //客户需求修改：喷涂计算时薪，符合条件原来+1元， 现在改为+2元  （将这个值2存储到字典中 hourpayDiff）
                    //2024-8-15客户需求修改：请假天数<=4天 原来+字典值+2元， 改为不加钱， （ 将字典hourpayDiff值改为0--已修改 ），(并且新增：如果请假大于4天扣200元——未修改，客户自己加减)
                    // if (chuqingongshi.compareTo(new BigDecimal("234")) >= 0 && attendanceReport.getLeaveDays().compareTo(new BigDecimal("4")) <= 0) {  //>=234小时  时薪+1元
                    if (attendanceReport.getLeaveDays().compareTo(new BigDecimal("4")) <= 0) {  //符合条件： 时薪 +字典设定值 元
                        String diff = dictService.getDictValue("pay_hourpay_diff","diff");
                        payPerHour = sgrSalaryReport.getBasicSalary().add(new BigDecimal(diff));
                    } else {
                        payPerHour = sgrSalaryReport.getBasicSalary();
                    }
                    rigonggongzi = payPerHour.multiply(rigonghours);
                    rigongbanggongGZ = payPerHour.multiply(rigongbanggong);

                    break;
                case "3":   //工资计算类型：外贸按小时
                    rigonggongzi = sgrSalaryReport.getBasicSalary().multiply(rigonghours);
                    rigongbanggongGZ = sgrSalaryReport.getBasicSalary().multiply(rigongbanggong);
                    break;
                case "4":   //工资计算类型：包月
                    rigonggongzi = sgrSalaryReport.getBasicSalary();
                    break;
            }
            sgrSalaryReport.setDayWorkPay(rigonggongzi.setScale(2, BigDecimal.ROUND_HALF_UP));
            sgrSalaryReport.setWorkOrderPay(baohuogongzi.setScale(2, BigDecimal.ROUND_HALF_UP));
            sgrSalaryReport.setOvertime(jiabangongzi.setScale(2, BigDecimal.ROUND_HALF_UP));
            //帮贡工资计算
            BigDecimal banggonggongzi = baohuobanggongGZ.add(rigongbanggongGZ);
            sgrSalaryReport.setBanggongPay(banggonggongzi.setScale(2, BigDecimal.ROUND_HALF_UP));

            //应付工资=日工工资+包活工资+加班工资+帮工工资+增补项    值班、拉货工资   节假日工资 	 岗位津贴 	补贴（话费及其他）   合同补助 	 全勤奖 	 帮工工资 	上月差异
            yingfagongzi = rigonggongzi.add(baohuogongzi).add(jiabangongzi).add(banggonggongzi);
            //遍历补贴扣减项
            BigDecimal koujianxiang = BigDecimal.ZERO;
            for (ButieMoneyAndTypes butieMoney : butieMoneyAndTypesList) {
                if (butieMoney.getType().equals("1")) {
                    yingfagongzi = yingfagongzi.add(butieMoney.getMoney());
                } else {
                    koujianxiang = koujianxiang.add(butieMoney.getMoney());
                }
            }

            //实发工资=应付工资-扣减项  迟到-党费
            shifagongzi = yingfagongzi.subtract(koujianxiang);
            sgrSalaryReport.setShoudPayMoney(yingfagongzi.setScale(2, BigDecimal.ROUND_HALF_UP));
            sgrSalaryReport.setActuallyPayMoney(shifagongzi.setScale(0, BigDecimal.ROUND_HALF_UP));
            int result = baseMapper.insert(sgrSalaryReport);
            if (result > 0) {
                successNums++;
                successMsg.append("<br/>" + employeeInfo.getName() + "操作成功");
            } else {
                failedNums++;
                failedMsg.append("<br/>" + employeeInfo.getName() + "添加到数据库时服务器异常");
            }
        }
        if (failedNums > 0) {
            failedMsg.insert(0, "生成成功:" + successNums + "条，生成失败:" + failedNums + "条，错误如下：");
            return R.fail(failedMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部生成成功！共 " + successNums + " 条，数据如下：");
        }
        return R.ok(successMsg.toString());

    }
}
