package com.engine.bjcj220907.service.impl; import com.engine.bjcj220907.dao.MonthBonusDAO; import com.engine.bjcj220907.dao.OverseasAllowanceDAO; import com.engine.bjcj220907.entity.*; import com.engine.bjcj220907.service.GetKQ4OverseasAllowanceCountService; import com.engine.bjcj220907.service.OverseasAllowanceCountService; import com.engine.bjcj220907.utils.BjcjCommonUtils; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import weaver.general.BaseBean; import java.util.*; import java.util.stream.Collectors; /** * @author Harryxzy * @date 2022/09/26 14:03 * @description 境外津贴 */ public class OverseasAllowanceCountServiceImpl extends Service implements OverseasAllowanceCountService { BaseBean baseBean = new BaseBean(); public MonthBonusDAO getMonthBonusDAO(){ return new MonthBonusDAO(); } public OverseasAllowanceDAO getOverseasAllowanceDAO(){ return new OverseasAllowanceDAO(); } private GetKQ4OverseasAllowanceCountService GetKQ4OverseasAllowanceCountService() { return ServiceUtil.getService(GetKQ4OverseasAllowanceCountServiceImpl.class,user); } /** * @description 计算境外津贴 * @return void * @author Harryxzy * @date 2022/9/26 14:06 */ @Override public void countOverseasAllowance(Calendar countCal) { // 境外津贴包含:境外津贴(天标准)+境外工龄补贴(月标准)+艰苦地区补贴(天标准) // 考勤开始日期 Calendar startAttendanceCal = BjcjCommonUtils.getStartAttendanceCal(countCal.getTime()); // 考勤结束日期 Calendar endAttendanceCal = BjcjCommonUtils.getEndAttendanceCal(countCal.getTime()); baseBean.writeLog("考勤开始日期:"+startAttendanceCal.getTime()+",考勤结束日期:"+endAttendanceCal); // 获取境外津贴(天标准) --计算当月应常驻天数 // 获取所有人的境外常驻信息 List czInfos = getOverseasAllowanceDAO().getCZInfo(startAttendanceCal.getTime(),endAttendanceCal.getTime()); baseBean.writeLog("获取所有人的境外常驻信息,共:"+czInfos.size()); // 将境外常驻信息格式化 List jwCZInfos = formatJwCZInfo(czInfos,startAttendanceCal,endAttendanceCal); baseBean.writeLog("将境外常驻信息格式化,共:"+jwCZInfos.size()); // 如果用户在考勤周期内存在境外常驻信息则过滤出来,并且计算当月应常驻天数及境内工作天数 List results = new ArrayList<>(); jwCZInfos = getCZInfosAndCZDays(jwCZInfos, startAttendanceCal, endAttendanceCal,results); baseBean.writeLog("获取用户在考勤周期内存在境外常驻信息过滤出来,并且计算当月境外应常驻天数及境内工作天数,共::"+results.size()); // 计算考勤所属月员工的薪酬等级,获取相应的境外津贴标准 List users = results.stream().map(i -> i.getUser()).collect(Collectors.toList()); Map usersXCDJ = getOverseasAllowanceDAO().getXCDJByUsers(users,startAttendanceCal); baseBean.writeLog("获取所有员工考勤所属月的薪酬等级及所对应的境外津贴标准、四项补贴合计,共:"+usersXCDJ.size()); // 获取考勤员工的公务回国天数 及 缺勤日期 Attend4MonthBonus build = Attend4MonthBonus.builder().beginDate(startAttendanceCal.getTime()).endDate(endAttendanceCal.getTime()).build(); Map kqDatas = GetKQ4OverseasAllowanceCountService().getKQDatas(build,users); baseBean.writeLog("调用考勤接口获取公务回国天数 及 缺勤日期:"+kqDatas); // 处理国内应出勤,国内天数-休息天数 handleGnycq(results,kqDatas); // 获取员工公务回国国内工作日天数 Map> gwhgInfos = getOverseasAllowanceDAO().getGwhg(); baseBean.writeLog("获取年假建模中所有公务回国信息,共:"+gwhgInfos.size()); // 过滤考勤周期内的公务回国信息,并计算出国内工作日天数 Map validGwhgAndCountWorkdays = getValidGwhgAndCountWorkdays(gwhgInfos, startAttendanceCal.getTime(), endAttendanceCal.getTime()); baseBean.writeLog("过滤考勤周期内的公务回国信息,并计算出国内工作日天数:"+validGwhgAndCountWorkdays); // 封装计算薪酬等级、境外津贴标准、考勤天数、四项补助合计、公务回国国内工作日天数 getXcdjAndJwjtbz(results,usersXCDJ,kqDatas,validGwhgAndCountWorkdays,jwCZInfos); baseBean.writeLog("封装薪酬等级、境外津贴标准、考勤天数、境外实际常驻天数并计算实出勤天数、境外津贴,共:"+results.size()); // 处理第三国出差(2)、境外国内出差(3)的艰苦地区补贴 Map> dsgccJkdq = getOverseasAllowanceDAO().getDsgcc(); baseBean.writeLog("获取第三国出差(2)、境外国内出差(3)艰苦地区补贴,共:"+dsgccJkdq.size()); baseBean.writeLog("第三国出差(2)、境外国内出差(3)艰苦地区补贴:"+dsgccJkdq); // 封装第三国出差数、境外国内出差据到result中 getDsgcc(results,dsgccJkdq,startAttendanceCal.getTime(),endAttendanceCal.getTime()); // 处理艰苦地区补贴天数(境外常驻补贴天数=境外实出勤-第三国出差-境外国内出差) handleJkdqDays(results, kqDatas, gwhgInfos); // 计算艰苦地区补贴合计 coutJkdqbthj(results); // 四项补贴合计(天标准)*(公务回国工作日天数+国内工作日天数) countSxbthj(results); baseBean.writeLog("计算四项补贴合计:"+results.size()); // 将结果插入建模表中 getOverseasAllowanceDAO().insertOverseasAllowance(results); baseBean.writeLog("将结果插入建模表中"); } /** * 处理国内应出勤,国内天数-休息天数 * @param results * @param kqDatas */ private void handleGnycq(List results, Map kqDatas) { results.stream().forEach(item -> { List czList = item.getJkdqbts().stream().filter(jkdqbt -> Objects.equals(jkdqbt.getLx(), 0) || Objects.equals(jkdqbt.getLx(), 1)).collect(Collectors.toList()); List restDates =(List) kqDatas.get(item.getUser() + "-rest"); if(restDates != null && restDates.size() > 0){ int gnRestDays = 0; boolean[] flag = {false}; for(Date d : restDates){ flag[0] = false; czList.stream().forEach(cz -> { if(Objects.equals(cz.getLx(),0)){ if(d.after(cz.getJkdqKssj()) || cz.getJkdqKssj().equals(d)){ // 是国外休息 flag[0] = true; } }else{ // 结束常驻 if( BjcjCommonUtils.isBetween(d, cz.getJkdqKssj(), cz.getJkdqJssj()) ){ // 是国外休息 flag[0] = true; } } }); if(flag[0] == false){ gnRestDays++; } } item.setGngzts( item.getGngzts() -gnRestDays ); } }); } /** * @description 处理艰苦地区补贴天数(境外常驻补贴天数=境外实出勤-第三国出差-?) * @return void * @author Harryxzy * @date 2022/12/23 18:04 */ private void handleJkdqDays(List results, Map kqData, Map> gwhgInfos) { baseBean.writeLog("开始处理艰苦地区补贴天数"); results.forEach(result -> { // 获取境外常驻的艰苦地区 和 第三国出差及境外国内出差的艰苦地区 ArrayList dsgAndJwgncc = new ArrayList<>(); List jwcc = result.getJkdqbts().stream().filter(j -> { if (Objects.equals(j.getLx(), 0) || Objects.equals(j.getLx(), 1)) { return true; } else { dsgAndJwgncc.add(j); return false; } }).collect(Collectors.toList()); if( dsgAndJwgncc.size() > 0 ){ // 常驻期内存在第三国出差或境外国内出差 dsgAndJwgncc.stream().forEach(dsg -> { jwcc.stream().forEach(cc -> { if(BjcjCommonUtils.isBetween(dsg.getJkdqKssj(), cc.getJkdqKssj(), cc.getJkdqJssj())){ cc.setDays(cc.getDays()-dsg.getDays()); cc.setJkdqbt(cc.getDays() * cc.getJkdqbtbz()); } }); }); } // 缺勤List List qqDate = (List ) kqData.get(result.getUser() + "-qq"); // 公务回国List List gwhgList = gwhgInfos.get(new Integer(result.getUser())); baseBean.writeLog(result.getUser()+"缺勤List:"+qqDate); baseBean.writeLog(result.getUser()+"公务回国List:"+gwhgList); // 减去缺勤、公务回国 jwcc.stream().forEach(cc -> { Calendar countKs = Calendar.getInstance(); countKs.setTime(cc.getJkdqKssj()); Calendar countJs = Calendar.getInstance(); countJs.setTime(cc.getJkdqJssj()); while (countKs.before(countJs) || countJs.equals(countKs)){ // 是否存在缺勤 if(qqDate != null){ if(qqDate.contains(countKs.getTime())){ cc.setDays(cc.getDays()-1); } } if(gwhgList != null){ gwhgList.stream().forEach(gwhg ->{ boolean isBetween = BjcjCommonUtils.isBetween(countKs.getTime(), gwhg.getJwczksrq(), gwhg.getJwczjsrq()); if(isBetween){ // 常驻期间存在公务回国 cc.setDays(cc.getDays()-1); } }); } countKs.add(Calendar.DAY_OF_MONTH,1); } cc.setJkdqbt(cc.getDays() * cc.getJkdqbtbz()); }); }); baseBean.writeLog("处理艰苦地区补贴天数结束"); } /** * @description 计算艰苦地区补贴合计 * @return void * @author Harryxzy * @date 2022/10/24 14:11 */ private void coutJkdqbthj(List results) { results.stream().forEach(result->{ double[] total={0.0}; List jkdqbts = result.getJkdqbts(); jkdqbts.stream().forEach(j -> { total[0]=total[0]+j.getJkdqbt(); }); result.setJkdqbthj(total[0]); }); } /** * @description 获取用户在考勤周期内存在境外常驻信息过滤出来,并且计算当月境外应常驻天数及境内工作天数 * @return List * @author Harryxzy * @date 2022/9/26 16:29 */ public List getCZInfosAndCZDays(List jwCZInfos,Calendar startAttendanceCal,Calendar endAttendanceCal,List results ){ List collect = jwCZInfos.stream().filter(czInfo -> { List czDetails = czInfo.getInfos(); // 用于存储计算到哪一天的日期 Calendar c = Calendar.getInstance(); c.setTime(endAttendanceCal.getTime()); Calendar[] countDay = {c}; int[] ycq = {0}; int[] gnycq = {0}; List details = new ArrayList<>(); ArrayList jkdqbts = new ArrayList<>(); for (int i = 0; i < czDetails.size(); i++) { JwCZInfoDetail detail = czDetails.get(i); if (detail.getLx() == 0 && (detail.getJwczksrq().before(endAttendanceCal.getTime()) || detail.getJwczksrq().equals(endAttendanceCal.getTime()))) { // 涉及考勤周期内的开始常驻 if (detail.getJwczksrq().after(startAttendanceCal.getTime())) { // 开始常驻日期在 考勤开始日期后,结束日期前 int days = BjcjCommonUtils.getDays(detail.getJwczksrq(), endAttendanceCal.getTime()); ycq[0] += days; countDay[0].setTime(detail.getJwczksrq()); countDay[0].add(Calendar.DATE, -1); // 存入常驻天数用于计算艰苦地区补贴 // int days1 = BjcjCommonUtils.getDays(detail.getJwczksrq(), endAttendanceCal.getTime()); detail.setDays(days); JKDQBT jk = JKDQBT.builder().lx(detail.getLx()).days(days).jkdq(detail.getJkdq()).jkdqbtbz(detail.getJkdqbtbz()).jkdqbt((days*detail.getJkdqbtbz())).jkdqKssj(detail.getJwczksrq()).jkdqJssj( endAttendanceCal.getTime()).build(); jkdqbts.add(jk); } else { // 开始常驻日期在 考勤开始日期前(应出勤日期为自然日) int days = BjcjCommonUtils.getDays(startAttendanceCal.getTime(), endAttendanceCal.getTime()); // 存入常驻天数用于计算艰苦地区补贴 // int days1 = BjcjCommonUtils.getDays(startAttendanceCal.getTime(), endAttendanceCal.getTime()); detail.setDays(days); JKDQBT jk = JKDQBT.builder().lx(detail.getLx()).days(days).jkdq(detail.getJkdq()).jkdqbtbz(detail.getJkdqbtbz()).jkdqbt((days*detail.getJkdqbtbz())).jkdqKssj(startAttendanceCal.getTime()).jkdqJssj( endAttendanceCal.getTime()).build(); JWJT build = JWJT.builder().user(czInfo.getXm()).sfzh(czInfo.getSfzh()).jwycq(days).gngzts(0.0).kqMonth(endAttendanceCal.getTime()).jwgl(czInfo.getJsglts()).jwglbtybz(czInfo.getGlbtybz()).jwglbtrbz(czInfo.getGlbtrbz()).build(); ArrayList jkdqbtList = new ArrayList<>(); jkdqbtList.add(jk); build.setJkdqbts(jkdqbtList); results.add(build); return true; } } if (detail.getLx() == 1 && ((detail.getJwczksrq().before(endAttendanceCal.getTime()) || detail.getJwczksrq().equals(endAttendanceCal.getTime())) && (detail.getJwczjsrq().after(startAttendanceCal.getTime()) || detail.getJwczjsrq().equals(startAttendanceCal.getTime())))) { // 涉及考勤周期内的结束常驻 // 将区间转换为记录 Calendar starCal = Calendar.getInstance(); starCal.setTime(detail.getJwczksrq()); while (starCal.getTime().before(detail.getJwczjsrq()) || starCal.getTime().equals(detail.getJwczjsrq())) { details.add(starCal.getTime()); starCal.add(Calendar.DAY_OF_YEAR, 1); } // 修正常驻开始时间和结束时间 Calendar countStartCal = Calendar.getInstance(); countStartCal.setTime(detail.getJwczksrq()); Calendar countEndCal = Calendar.getInstance(); countEndCal.setTime(detail.getJwczjsrq()); if(countStartCal.getTime().before(startAttendanceCal.getTime())){ countStartCal.setTime(startAttendanceCal.getTime()); } if(countEndCal.getTime().after(endAttendanceCal.getTime())){ countEndCal.setTime(endAttendanceCal.getTime()); } int days = BjcjCommonUtils.getDays(countStartCal.getTime(), countEndCal.getTime()); detail.setDays(days); JKDQBT jk = JKDQBT.builder().lx(detail.getLx()).days(days).jkdq(detail.getJkdq()).jkdqbtbz(detail.getJkdqbtbz()).jkdqbt((days*detail.getJkdqbtbz())).jkdqbt((days*detail.getJkdqbtbz())).jkdqKssj(countStartCal.getTime()).jkdqJssj( countEndCal.getTime()).build(); jkdqbts.add(jk); } if (i == czDetails.size() - 1) { // 已经将所有考勤周期内境外常驻的区间时间转换为记录 Calendar aCal = Calendar.getInstance(); aCal.setTime(countDay[0].getTime()); aCal.set(Calendar.HOUR_OF_DAY, 0); aCal.set(Calendar.MINUTE, 0); aCal.set(Calendar.SECOND, 0); aCal.set(Calendar.MILLISECOND, 0); if (details.size() == 0 && countDay[0].getTime().equals(endAttendanceCal.getTime())) { // 该考勤周期内员工没有境外常驻信息 return false; } while (startAttendanceCal.getTime().before(aCal.getTime()) || startAttendanceCal.getTime().equals(aCal.getTime())) { if (details.contains(aCal.getTime())) { // 存在境外记录 ycq[0]++; aCal.add(Calendar.DATE, -1); } else { // 没有境外记录,判断是否是工作日(需考虑节假日) // if ((aCal.get(Calendar.DAY_OF_WEEK) != 1) && (aCal.get(Calendar.DAY_OF_WEEK) != 7)) { // 是工作日 gnycq[0]++; // } aCal.add(Calendar.DATE, -1); } } JWJT build = JWJT.builder().user(czInfo.getXm()).sfzh(czInfo.getSfzh()).jwycq(ycq[0]).gngzts(gnycq[0]).kqMonth(endAttendanceCal.getTime()).jwgl(czInfo.getJsglts()).jwglbtybz(czInfo.getGlbtybz()).jwglbtrbz(czInfo.getGlbtrbz()).build(); build.setJkdqbts(jkdqbts); results.add(build); return true; } } return false; }).collect(Collectors.toList()); return collect; } /** * @description 将获取到的缺勤天数(请假)、公务回国天数、薪酬等级与境外津贴标准与人员对应并计算出实出勤天数 * @return void * @author Harryxzy * @date 2022/9/27 15:37 */ public void getXcdjAndJwjtbz(List results ,Map usersXSDJ,Map kqDatas,Map validGwhgAndCountWorkdays,List jwCZInfos){ Map> czInfos = jwCZInfos.stream().collect(Collectors.toMap(JwCZInfo::getXm, JwCZInfo::getInfos)); results.stream().forEach(item-> { XcdjJwjtParam param = usersXSDJ.get(Integer.valueOf(item.getUser())); item.setXcdj(param.getXcdj()); item.setJwjtbz(param.getJwjtbz()); item.setSxbzhjbz(param.getSxbzhj()); item.setSxbzhjrbz(param.getSxbzhj()/21.75); if(item.getUser().equals("109")){ System.out.println("hi"); } if(kqDatas.get(item.getUser() + "-qq") == null){ // 目前该员工没有考勤数据 item.setGnQq(0.0); item.setJwQq(0.0); item.setGwhg(0.0); baseBean.writeLog("员工" +item.getUser()+"没有考勤数据!请核对考勤报表"); }else{ List qqDate =(List ) kqDatas.get(item.getUser() + "-qq"); double gnQqDays=0.0; double jwQqDays=0.0; // 判断是境内缺勤还是境外缺勤 ArrayList t = new ArrayList<>(); List jwCZInfoDetails = czInfos.get(item.getUser()); if(jwCZInfoDetails != null && jwCZInfoDetails.size()>0){ for(Date d : qqDate){ Boolean flag = false; for(int i=0; (i formatJwCZInfo(List czInfos,Calendar startAttendanceCal,Calendar endAttendanceCal) { Map> groupByName = czInfos.stream().collect(Collectors.groupingBy(item -> item.getXm())); int days = BjcjCommonUtils.getDays(startAttendanceCal.getTime(), endAttendanceCal.getTime()); List formatJwCZInfos = new ArrayList<>(); for (Map.Entry> entry : groupByName.entrySet()) { List values = entry.getValue(); JwCZInfo build = new JwCZInfo().builder().xm(values.get(0).getXm()).sfzh(values.get(0).getSfzh()).jsglts(values.get(0).getJsglts()) .glbtybz(values.get(0).getGlbtybz()).glbtrbz(values.get(0).getGlbtybz()/days) .infos(entry.getValue()).build(); formatJwCZInfos.add(build); } return formatJwCZInfos; } /** * @description 封装第三国出差和境外国内出差数据到results中 * @return void * @author Harryxzy * @date 2022/9/28 17:07 */ public void getDsgcc(List results,Map> dsgccJkdq,Date startAttendance,Date endAttendance) { results.stream().forEach(jwjt->{ Integer user = Integer.valueOf(jwjt.getUser()); if(dsgccJkdq.containsKey(user)){ // 该员工存在第三国出差数据 List jwCZInfoDetails = dsgccJkdq.get(user); for(int i=0; i < jwCZInfoDetails.size(); i++){ JwCZInfoDetail detail = jwCZInfoDetails.get(i); if ((detail.getJwczksrq().before(endAttendance) || detail.getJwczksrq().equals(endAttendance)) && (detail.getJwczjsrq().after(startAttendance) || detail.getJwczjsrq().equals(startAttendance))) { // 在考勤周期内的第三国出差数据 // 修正常驻开始时间和结束时间 Calendar countStartCal = Calendar.getInstance(); countStartCal.setTime(detail.getJwczksrq()); Calendar countEndCal = Calendar.getInstance(); countEndCal.setTime(detail.getJwczjsrq()); if(countStartCal.getTime().before(startAttendance)){ countStartCal.setTime(startAttendance); } if(countEndCal.getTime().after(endAttendance)){ countEndCal.setTime(endAttendance); } int days = BjcjCommonUtils.getDays(countStartCal.getTime(), countEndCal.getTime()); JKDQBT jk = JKDQBT.builder().lx(detail.getLx()).days(days).jkdq(detail.getJkdq()).jkdqKssj(countStartCal.getTime()).jkdqJssj(countEndCal.getTime()).jkdqbtbz(detail.getJkdqbtbz()).jkdqbt((days * detail.getJkdqbtbz())).build(); jwjt.getJkdqbts().add(jk); } } } }); } /** * @description 计算四项补助合计 = 四项补贴合计(天标准)*(公务回国工作日天数+国内工作日天数) * @return void * @author Harryxzy * @date 2022/9/29 17:59 */ private void countSxbthj(List results) { results.stream().forEach(result->{ // 获取员工的公务回国工作日天数和国内工作日天数 * 四项补助日标准 result.setSxbzhj((result.getGnscq()+result.getGwhgWorkdays()) * result.getSxbzhjrbz()); }); } /** * @description 过滤考勤周期内的公务回国信息,并计算出国内工作日天数 * @return void * @author Harryxzy * @date 2022/10/21 9:47 */ private Map getValidGwhgAndCountWorkdays(Map> gwhgInfos, Date startAttendance, Date endAttendance) { Map result = new HashMap(); for(Map.Entry> entrySet : gwhgInfos.entrySet()){ List values = entrySet.getValue(); values.stream().forEach(value ->{ if( (value.getJwczksrq().before(endAttendance) || value.getJwczksrq().equals(endAttendance)) && (value.getJwczjsrq().after(startAttendance) || value.getJwczjsrq().equals(startAttendance)) ){ // 在考勤周期内的公务回国,计算国内工作天数 Calendar countCal = Calendar.getInstance(); if(value.getJwczjsrq().after(endAttendance)){ countCal.setTime(endAttendance); }else { countCal.setTime(value.getJwczjsrq()); } Calendar countStarCal = Calendar.getInstance(); if(value.getJwczksrq().before(startAttendance)){ countStarCal.setTime(startAttendance); }else{ countStarCal.setTime(value.getJwczksrq()); } int workDays=0; while (countCal.getTime().after(countStarCal.getTime()) || countCal.getTime().equals(countStarCal.getTime())){ // 判断是否是工作日 if((countCal.get(Calendar.DAY_OF_WEEK) != 1) && (countCal.get(Calendar.DAY_OF_WEEK)!=7)){ workDays++; } countCal.add(Calendar.DATE,-1); } if(result.containsKey(entrySet.getKey())){ Integer integer = result.get(entrySet.getKey()); result.put(entrySet.getKey(), integer + workDays); }else{ result.put(entrySet.getKey(), workDays); } } }); } return result; } }