weaver-bjcj/src/com/engine/bjcj220907/service/impl/AbroadBusinessCountServiceI...

246 lines
12 KiB
Java
Raw Normal View History

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<AbroadBusiness> abroadBusinesses = new ArrayList<>();
abroadBusinesses = getAbroadBusinessDAO().getList();
// 获取出差明细
baseBean.writeLog("开始将所有出差记录:"+abroadBusinesses.size()+"条转换为明细");
List<AbroadBusinessDetail> 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<AbroadBusinessDetail> thisAndLastMonthBusinessDetail = getThisAndLastMonthBusinessDetail(abroadBusinessDetails, searchCal.getTime(),lastThirtyDays.getTime());
// 根据姓名进行分组
Map<Integer, List<AbroadBusinessDetail>> 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<AbroadBusinessResult> results =new ArrayList<>();
for (Map.Entry<Integer, List<AbroadBusinessDetail>> entry : collect.entrySet()) {
// 每个人(搜索月28)到(上月29号30天前)的出差明细
List<AbroadBusinessDetail> detail = entry.getValue();
List<Date> 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<AbroadBusinessDetail> 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<Date> 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<searchMonthDetailDate.size();i++){
if(searchMonthDetailDate.get(i).equals(firstCal.getTime())){
// 连续
firstCal.add(Calendar.DATE,1);
if(totalContinueDays >= 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<AbroadBusinessDetail> getThisAndLastMonthBusinessDetail(List<AbroadBusinessDetail> abroadBusinessDetails,Date endDate,Date startDate){
List<AbroadBusinessDetail> 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;
}
}