246 lines
12 KiB
Java
246 lines
12 KiB
Java
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;
|
||
}
|
||
|
||
|
||
}
|