package com.engine.bjcj220907.service.impl; import com.engine.bjcj220907.dao.AbroadBusinessDAO; import com.engine.bjcj220907.entity.AbroadBusiness; import com.engine.bjcj220907.entity.AbroadBusinessCountParam; import com.engine.bjcj220907.entity.AbroadBusinessDetail; import com.engine.bjcj220907.entity.AbroadBusinessResult; import com.engine.bjcj220907.service.AbroadBusinessCountService; import com.engine.core.impl.Service; import weaver.general.BaseBean; import java.util.*; import java.util.stream.Collectors; /** * @author Harryxzy * @date 2022/09/05 11:52 * @description 计算员工国外出差天数 */ public class AbroadBusinessCountServiceImpl extends Service implements AbroadBusinessCountService { public AbroadBusinessDAO getAbroadBusinessDAO(){ return new AbroadBusinessDAO(); } BaseBean baseBean = new BaseBean(); /** * @description 计算员工国外"出差补贴标准"天数,"境外津贴标准"天数, * @return String * @author Harryxzy * @date 2022/9/5 12:37 */ @Override public String countDays(AbroadBusinessCountParam param) { // 从境外工作记录表中查询所有国外出差数据 List abroadBusinesses = new ArrayList<>(); abroadBusinesses = getAbroadBusinessDAO().getList(); // 获取出差明细 baseBean.writeLog("开始将所有出差记录:"+abroadBusinesses.size()+"条转换为明细"); List abroadBusinessDetails = new ArrayList<>(); for(int i=0; i < abroadBusinesses.size();i++){ AbroadBusiness business = abroadBusinesses.get(i); Date c_start = business.getJwgzkssj(); Date c_end = business.getJwgzjssj(); // 境外工作开始时间 Calendar tempStart = Calendar.getInstance(); tempStart.setTime(c_start); tempStart.set(Calendar.HOUR_OF_DAY,0); tempStart.set(Calendar.MINUTE,0); tempStart.set(Calendar.SECOND,0); tempStart.set(Calendar.MILLISECOND,0); // 境外工作结束时间 Calendar tempEnd = Calendar.getInstance(); tempEnd.setTime(c_end); tempEnd.set(Calendar.HOUR_OF_DAY,0); tempEnd.set(Calendar.MINUTE, 0); tempEnd.set(Calendar.SECOND, 0); tempEnd.set(Calendar.MILLISECOND, 0); tempEnd.add(Calendar.DATE, 1); while (tempStart.before(tempEnd)) { abroadBusinessDetails.add(AbroadBusinessDetail.builder().xm(business.getUser()).date(tempStart.getTime()).jwgzdw(business.getJwgzdw()).build()); tempStart.add(Calendar.DAY_OF_YEAR, 1); } } baseBean.writeLog("将所有出差记录转换为明细完成共"+abroadBusinesses.size()+"条明细"); // 查询月份的年月(当月的28号11:59:59) Calendar searchCal = Calendar.getInstance(); searchCal.setTime(param.getMonth()); int year = searchCal.get(Calendar.YEAR); int month = searchCal.get(Calendar.MONTH)+1; int totalDays = searchCal.getActualMaximum(Calendar.DAY_OF_MONTH); searchCal.set(Calendar.DAY_OF_MONTH,28); searchCal.set(Calendar.HOUR_OF_DAY, 23); searchCal.set(Calendar.MINUTE, 59); searchCal.set(Calendar.SECOND, 59); searchCal.set(Calendar.MILLISECOND, 999); baseBean.writeLog("查询月:"+searchCal.getTime()); // 出差补贴发放月 Calendar sendMonth = Calendar.getInstance(); sendMonth.setTime(param.getMonth()); sendMonth.add(Calendar.MONTH, 1); baseBean.writeLog("出差补贴发放月:"+sendMonth.getTime()); // 查询上月29号30天前的年月日(24:00:00)(不是3月的情况) Calendar lastThirtyDays = Calendar.getInstance(); lastThirtyDays.set(Calendar.YEAR, year); lastThirtyDays.set(Calendar.MONTH, month-2); if(lastThirtyDays.getActualMaximum(Calendar.DAY_OF_MONTH)==28){ // 2月只有28天的情况 lastThirtyDays.add(Calendar.MONTH, 1); lastThirtyDays.set(Calendar.DAY_OF_MONTH, 1); lastThirtyDays.add(Calendar.DATE, -30); lastThirtyDays.set(Calendar.HOUR_OF_DAY, 0); lastThirtyDays.set(Calendar.MINUTE, 0); lastThirtyDays.set(Calendar.SECOND, 0); lastThirtyDays.set(Calendar.MILLISECOND, 0); }else{ lastThirtyDays.set(Calendar.DAY_OF_MONTH, 29); lastThirtyDays.add(Calendar.DATE, -30); lastThirtyDays.set(Calendar.HOUR_OF_DAY, 0); lastThirtyDays.set(Calendar.MINUTE, 0); lastThirtyDays.set(Calendar.SECOND, 0); lastThirtyDays.set(Calendar.MILLISECOND, 0); } baseBean.writeLog("上月29号30天前日期:"+lastThirtyDays.getTime()); // 获取所有人(搜索月28)到(上月29号30天前)的出差明细 List thisAndLastMonthBusinessDetail = getThisAndLastMonthBusinessDetail(abroadBusinessDetails, searchCal.getTime(),lastThirtyDays.getTime()); // 根据姓名进行分组 Map> collect = thisAndLastMonthBusinessDetail.stream().collect(Collectors.groupingBy(item -> item.getXm())); // 获取搜索月周期的第一天(正常是上月29号,2月例外) Calendar searchBeginCal = Calendar.getInstance(); searchBeginCal.setTime(lastThirtyDays.getTime()); searchBeginCal.add(Calendar.DATE,30); Date firstDay = searchBeginCal.getTime(); baseBean.writeLog("获取搜索月周期的第一天:"+firstDay); List results =new ArrayList<>(); for (Map.Entry> entry : collect.entrySet()) { // 每个人(搜索月28)到(上月29号30天前)的出差明细 List detail = entry.getValue(); List detailDate = detail.stream().map(AbroadBusinessDetail::getDate).collect(Collectors.toList()); // 前30天连续天数 int lastMonthCount=0; // 本月出差补贴标准天数 int thisMonthCount=0; // 本月境外津贴标准天数 int thisMonthAbroadCount=0; if(detailDate.contains(firstDay)){ // 出差明细中包含计算周期的第一天,需要判断前30天 Calendar lastMonthLastDayCal = Calendar.getInstance(); lastMonthLastDayCal.setTime(firstDay); lastMonthLastDayCal.add(Calendar.DATE,-1); if(detailDate.contains(lastMonthLastDayCal.getTime())){ // 出差明细中包含计算周期的前一天,存在跨月情况,计算周期第一天的前30天最后连续签到天数 lastMonthCount=1; for(int i=detailDate.indexOf((lastMonthLastDayCal.getTime())); i>0;i--){ lastMonthLastDayCal.add(Calendar.DATE,-1); if( detailDate.get(i-1).equals(lastMonthLastDayCal.getTime())){ lastMonthCount++; } else{ break; } } } if(lastMonthCount == 30){ thisMonthAbroadCount++; }else{ thisMonthCount++; } } // 过滤搜索周期(上月29-搜索月28)出差明细 List searchMonthDetails = detail.stream().filter(item -> { if( (searchCal.getTime().after(item.getDate()) || searchCal.getTime().equals(item.getDate())) && ( firstDay.before(item.getDate())|| firstDay.equals(item.getDate())) ){ return true; }else{return false;} }).collect(Collectors.toList()); if(searchMonthDetails.size()==0){ // 搜索周期内无数据 continue; } List searchMonthDetailDate = searchMonthDetails.stream().map(AbroadBusinessDetail::getDate).collect(Collectors.toList()); if((searchMonthDetailDate.size() + lastMonthCount) <=30){ // 前30天连续出差天数+本计算周期天数 没有超过30天 thisMonthCount = searchMonthDetailDate.size(); }else{ // 超过30天 if(lastMonthCount == 0){ // 满30天,但计算周期前一天无签到(不跨月) if(thisMonthCount == 0){ // 计算周期第一天没有签到则本月出差全为”出差补贴标准天数“(最多连续30天) thisMonthCount = searchMonthDetailDate.size(); }else{ // 计算周期第一天有签到 if(searchMonthDetailDate.size()<=30){ thisMonthCount=searchMonthDetailDate.size(); }else{ thisMonthCount=30; thisMonthAbroadCount=1; } } }else{ // 满30天,且计算周期前一天存在签到 if(thisMonthCount == 0 && thisMonthAbroadCount == 0){ // 计算周期第一天没有签到 thisMonthCount = searchMonthDetailDate.size(); }else{ // 计算周期第一天有签到 Calendar firstCal = Calendar.getInstance(); firstCal.setTime(firstDay); firstCal.add(Calendar.DATE, 1); int totalContinueDays=lastMonthCount+1; for(int i=1;i= 30){ thisMonthAbroadCount++; }else{ thisMonthCount++; } totalContinueDays++; }else{ // 不连续,计算余下出差天数,加入出差补贴标准天数 int remaining = searchMonthDetailDate.size() - i ; thisMonthCount+=remaining; break; } } } } } AbroadBusinessResult build = AbroadBusinessResult.builder().user(detail.get(0).getXm()).basicAllowanceDays(thisMonthCount).abroadAllowanceDays(thisMonthAbroadCount).totalDays(thisMonthCount + thisMonthAbroadCount) .month(param.getMonth()).sendMonth(sendMonth.getTime()).jwgzdw(detail.get(0).getJwgzdw()).build(); results.add(build); baseBean.writeLog("用户:"+detail.get(0).getXm()+"前30天连续出差天数:"+lastMonthCount+"本周期短期出差天数:"+thisMonthCount+"长期出差天数:"+thisMonthAbroadCount); } baseBean.writeLog("开始获取岗级、薪点、补贴标准信息等数据"); results = results.stream().map(result -> { getAbroadBusinessDAO().getJobInfo(result); return result; }).collect(Collectors.toList()); // 计算结果插入建模表中 baseBean.writeLog("计算结果插入建模表中"); getAbroadBusinessDAO().insertResult(results,param.getMonth()); return "success"; } // 获取搜索月28号到上月29号30天前的出差明细 public List getThisAndLastMonthBusinessDetail(List abroadBusinessDetails,Date endDate,Date startDate){ List thisAndLastMonthBusinessDay = abroadBusinessDetails.stream().filter(date ->{ if( ((startDate.before(date.getDate())) || (startDate.equals(date.getDate()))) && ((endDate.after(date.getDate())) || (endDate.equals(date.getDate()))) ){ return true; }else{return false;} }).collect(Collectors.toList()); return thisAndLastMonthBusinessDay; } }