Просмотр исходного кода

移动考勤打卡分析需求修改

o2lee 5 лет назад
Родитель
Сommit
6a6e94cb0f

+ 19 - 3
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/ActionReciveAttendanceMobile.java

@@ -1,10 +1,8 @@
 package com.x.attendance.assemble.control.jaxrs.attendancedetail;
 
 import java.util.Date;
-import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
-
 import org.apache.commons.lang3.StringUtils;
 
 import com.google.gson.JsonElement;
@@ -120,7 +118,25 @@ public class ActionReciveAttendanceMobile extends BaseAction {
 				logger.error( e, currentPerson, request, null);
 			}
 		}
-		
+
+//		AttendanceScheduleSetting scheduleSetting = attendanceScheduleSettingService.getAttendanceScheduleSettingWithPerson( detail.getEmpName(), debugger );
+//		if( scheduleSetting == null ){
+//			throw new Exception("scheduleSetting is null, empName:" + detail.getEmpName() );
+//		}
+
+//		//获取打卡策略:两次,三次还是四次
+//		//根据考勤打卡规则来判断启用何种规则来进行考勤结果分析
+//		if ( 1 == scheduleSetting.getSignProxy() ){
+//			//1、一天只打上下班两次卡
+//
+//		}else if( 2 == scheduleSetting.getSignProxy() ){
+//			//2、一天三次打卡:打上班,下班两次卡外,中午休息时间也需要打一次卡,以确保员工在公司活动
+//
+//		}else if( 3 == scheduleSetting.getSignProxy() ){
+//			//3、一天四次打卡:打上午上班,上午下班,下午上班,下午下班四次卡
+//
+//		}
+
 		if( check ){
 			//对该员工的所有移动考勤数据进行一个整合
 			attendanceDetailServiceAdv.pushToDetail( currentPerson.getDistinguishedName(), attendanceDetailMobile.getRecordDateString(), effectivePerson.getDebugger() );

+ 31 - 25
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/ComposeDetailWithMobileInSignProxy1.java

@@ -7,7 +7,7 @@ import com.x.attendance.entity.AttendanceScheduleSetting;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.ListTools;
-import org.apache.commons.lang3.StringUtils;
+import org.codehaus.plexus.util.StringUtils;
 
 import java.util.Date;
 import java.util.List;
@@ -36,33 +36,33 @@ class ComposeDetailWithMobileInSignProxy1 {
 		AttendanceDetailMobile mobileDetail = mobileDetails.get( 0 );
 		String onDutyTime = getOnDutyTime( mobileDetails );
 		String offDutyTime = getOffDutyTime( mobileDetails );
-		//					detail = new AttendanceDetail();
-//					detail.setEmpNo( mobileDetail.getEmpNo() );
-//					detail.setEmpName( mobileDetail.getEmpName() );
-//					if( mobileDetail.getRecordDate() != null ) {
-//						detail.setYearString( dateOperation.getYear( mobileDetail.getRecordDate() ) );
-//						detail.setMonthString( dateOperation.getMonth( mobileDetail.getRecordDate() ) );
-//					}
-//					detail.setRecordDateString( mobileDetail.getRecordDateString() );
-//					detail.setOnDutyTime( onDutyTime );
-//					detail.setOffDutyTime( offDutyTime );
-//					detail.setRecordStatus( 0 );
 
-		//					detail.setEmpNo( mobileDetail.getEmpNo() );
-//					detail.setEmpName( mobileDetail.getEmpName() );
-//					if( mobileDetail.getRecordDate() != null ) {
-//						detail.setYearString( dateOperation.getYear( mobileDetail.getRecordDate() ) );
-//						detail.setMonthString( dateOperation.getMonth( mobileDetail.getRecordDate() ) );
-//					}
-//					detail.setRecordDateString( mobileDetail.getRecordDateString() );
-//					detail.setOnDutyTime( onDutyTime );
-//					detail.setOffDutyTime( offDutyTime );
-//					detail.setRecordStatus( 0 );
-//					detail.setBatchName( "FromMobile_" + dateOperation.getNowTimeChar() );
-
-		return null;
+		//组织员工当天的考勤打卡记录
+		AttendanceDetail detail = new AttendanceDetail();
+		detail.setEmpNo( mobileDetail.getEmpNo() );
+		detail.setEmpName( mobileDetail.getEmpName() );
+		if( mobileDetail.getRecordDate() != null ) {
+			detail.setYearString( dateOperation.getYear( mobileDetail.getRecordDate() ) );
+			detail.setMonthString( dateOperation.getMonth( mobileDetail.getRecordDate() ) );
+		}
+		detail.setRecordDateString( mobileDetail.getRecordDateString() );
+		detail.setOnDutyTime( onDutyTime );
+		if( StringUtils.equals(offDutyTime, onDutyTime ) ){
+			detail.setOffDutyTime( null );
+		}else{
+			detail.setOffDutyTime( offDutyTime ); //最晚的一次打卡作为当天的下班签退打卡
+		}
+		detail.setRecordStatus( 0 );
+		detail.setBatchName( "FromMobile_" + dateOperation.getNowTimeChar() );
+		return detail;
 	}
 
+	/**
+	 * 将最晚的一次打卡时间设置为下班打卡时间
+	 * @param mobileDetails
+	 * @return
+	 * @throws Exception
+	 */
 	private String getOffDutyTime( List<AttendanceDetailMobile> mobileDetails ) throws Exception {
 		Date offDutyTime = null;
 		Date signTime = null;
@@ -82,6 +82,12 @@ class ComposeDetailWithMobileInSignProxy1 {
 		return offDutyTimeString;
 	}
 
+	/**
+	 * 将第一次打卡时间,设置为上班打卡时间
+	 * @param mobileDetails
+	 * @return
+	 * @throws Exception
+	 */
 	private String getOnDutyTime(List<AttendanceDetailMobile> mobileDetails) throws Exception {
 		Date onDutyTime = null;
 		Date signTime = null;

+ 129 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/ComposeDetailWithMobileInSignProxy2.java

@@ -6,7 +6,10 @@ import com.x.attendance.entity.AttendanceDetailMobile;
 import com.x.attendance.entity.AttendanceScheduleSetting;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import org.codehaus.plexus.util.StringUtils;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -18,8 +21,132 @@ class ComposeDetailWithMobileInSignProxy2 {
 	private static  Logger logger = LoggerFactory.getLogger( ComposeDetailWithMobileInSignProxy2.class );
 	private DateOperation dateOperation = new DateOperation();
 
+	/**
+	 * 组织一个完整的打卡记录,有午休时间记录
+	 * 1、上班打卡时间:最早的一次打卡就是上班打卡时间
+	 * 2、中午打卡时间,计算午休开始和结束时间内,最晚的那一次打卡时间作为午休打卡时间
+	 * 3、下班打卡时间:取最晚的一次打卡
+	 * @param mobileDetails
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 * @throws Exception
+	 */
+	public AttendanceDetail compose(List<AttendanceDetailMobile> mobileDetails, AttendanceScheduleSetting scheduleSetting, Boolean debugger) throws Exception {
+		AttendanceDetailMobile mobileDetail = mobileDetails.get( 0 );
+		String onDutyTime = getOnDutyTime( mobileDetails );
+		String offDutyTime = getOffDutyTime( mobileDetails );
 
-	public AttendanceDetail compose(List<AttendanceDetailMobile> mobileDetails, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
-		return null;
+		if(StringUtils.isEmpty( scheduleSetting.getMiddayRestStartTime() )){
+			scheduleSetting.setMiddayRestStartTime("11:30");
+		}
+
+		if(StringUtils.isEmpty( scheduleSetting.getMiddayRestEndTime() )){
+			scheduleSetting.setMiddayRestStartTime("13:30");
+		}
+
+		String morningOffdutyTime = getMorningOffDutyTime( mobileDetails, scheduleSetting.getMiddayRestStartTime(), scheduleSetting.getMiddayRestEndTime() );
+
+		//组织员工当天的考勤打卡记录
+		AttendanceDetail detail = new AttendanceDetail();
+		detail.setEmpNo( mobileDetail.getEmpNo() );
+		detail.setEmpName( mobileDetail.getEmpName() );
+		if( mobileDetail.getRecordDate() != null ) {
+			detail.setYearString( dateOperation.getYear( mobileDetail.getRecordDate() ) );
+			detail.setMonthString( dateOperation.getMonth( mobileDetail.getRecordDate() ) );
+		}
+		detail.setRecordDateString( mobileDetail.getRecordDateString() );
+		detail.setOnDutyTime( onDutyTime ); //最早的一次打卡作为当天的上班签到打卡
+		if( StringUtils.equals(morningOffdutyTime, onDutyTime )){
+			detail.setMorningOffdutyTime( null );
+		}else{
+			detail.setMorningOffdutyTime( morningOffdutyTime ); //午休打卡时间
+		}
+		if( StringUtils.equals(offDutyTime, onDutyTime ) || StringUtils.equals(morningOffdutyTime, offDutyTime ) ){
+			detail.setOffDutyTime( null );
+		}else{
+			detail.setOffDutyTime( offDutyTime ); //最晚的一次打卡作为当天的下班签退打卡
+		}
+		detail.setRecordStatus( 0 );
+		detail.setBatchName( "FromMobile_" + dateOperation.getNowTimeChar() );
+		return detail;
+	}
+
+	/**
+	 * 计算午休开始和结束时间内,最晚的那一次打卡时间作为午休打卡时间
+	 * @param mobileDetails
+	 * @param middayRestStartTime
+	 * @param middayRestEndTime
+	 * @return
+	 */
+	private String getMorningOffDutyTime(List<AttendanceDetailMobile> mobileDetails, String middayRestStartTime, String middayRestEndTime) throws Exception {
+		Date moningOndutyTime = null;
+		Date signTime = null, restStartTime=null, restEndTime = null;
+		String resultTime = null;
+		if( ListTools.isNotEmpty( mobileDetails ) && mobileDetails.size() >=2 ) {
+			for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+				signTime = dateOperation.getDateFromString( detailMobile.getSignTime() );
+				restStartTime = dateOperation.getDateFromString( middayRestStartTime );
+				restEndTime = dateOperation.getDateFromString( middayRestEndTime );
+				if( moningOndutyTime != null && signTime != null && restStartTime.before( signTime ) && restEndTime.after( signTime )) {
+					if( moningOndutyTime.before( signTime ) ){
+						moningOndutyTime = signTime;
+						resultTime = detailMobile.getSignTime();
+					}
+				}else if( moningOndutyTime == null ){
+					moningOndutyTime = signTime;
+					resultTime = detailMobile.getSignTime();
+				}
+			}
+		}
+		return resultTime;
+	}
+
+	/**
+	 * 将最晚的一次打卡时间设置为下班打卡时间
+	 * @param mobileDetails
+	 * @return
+	 * @throws Exception
+	 */
+	private String getOffDutyTime( List<AttendanceDetailMobile> mobileDetails ) throws Exception {
+		Date offDutyTime = null;
+		Date signTime = null;
+		String offDutyTimeString = null;
+		if( ListTools.isNotEmpty( mobileDetails ) && mobileDetails.size() >=2 ) {
+			for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+				signTime = dateOperation.getDateFromString(detailMobile.getSignTime() );
+				if( offDutyTime != null && signTime != null && offDutyTime.before( signTime )) {
+					offDutyTime = signTime;
+					offDutyTimeString = detailMobile.getSignTime();
+				}else if( offDutyTime == null ){
+					offDutyTime = signTime;
+					offDutyTimeString = detailMobile.getSignTime();
+				}
+			}
+		}
+		return offDutyTimeString;
+	}
+
+	/**
+	 * 将第一次打卡时间,设置为上班打卡时间
+	 * @param mobileDetails
+	 * @return
+	 * @throws Exception
+	 */
+	private String getOnDutyTime(List<AttendanceDetailMobile> mobileDetails) throws Exception {
+		Date onDutyTime = null;
+		Date signTime = null;
+		String onDutyTimeString = null;
+		for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+			signTime = dateOperation.getDateFromString(detailMobile.getSignTime() );
+			if( onDutyTime != null && signTime != null && onDutyTime.after( signTime )) {
+				onDutyTime = signTime;
+				onDutyTimeString = detailMobile.getSignTime();
+			}else if( onDutyTime == null ){
+				onDutyTime = signTime;
+				onDutyTimeString = detailMobile.getSignTime();
+			}
+		}
+		return onDutyTimeString;
 	}
 }

+ 175 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/ComposeDetailWithMobileInSignProxy3.java

@@ -6,7 +6,10 @@ import com.x.attendance.entity.AttendanceDetailMobile;
 import com.x.attendance.entity.AttendanceScheduleSetting;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import org.codehaus.plexus.util.StringUtils;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -18,8 +21,178 @@ class ComposeDetailWithMobileInSignProxy3 {
 	private static  Logger logger = LoggerFactory.getLogger( ComposeDetailWithMobileInSignProxy3.class );
 	private DateOperation dateOperation = new DateOperation();
 
+	/**
+	 * 组织一个完整的打卡记录,有午休时间记录
+	 * 1、上午上班打卡时间:上午上班时段中,最早的一次打卡时间就是上午上班打卡时间
+	 * 2、上午下班打卡时间:上午上班时段中,最晚的一次打卡时间就是上午下班打卡时间
+	 * 3、下午上班打卡时间:下午上班时段中,最早的一次打卡时间就是下午上班打卡时间
+	 * 3、下午下班打卡时间:下午上班时段中,最晚的一次打卡时间就是下午下班打卡时间
+	 * @param mobileDetails
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 * @throws Exception
+	 */
+	public AttendanceDetail compose(List<AttendanceDetailMobile> mobileDetails, AttendanceScheduleSetting scheduleSetting, Boolean debugger) throws Exception {
+		AttendanceDetailMobile mobileDetail = mobileDetails.get( 0 );
+		if(StringUtils.isEmpty( scheduleSetting.getMiddayRestStartTime() )){
+			scheduleSetting.setMiddayRestStartTime("11:30");
+		}
+		if(StringUtils.isEmpty( scheduleSetting.getMiddayRestEndTime() )){
+			scheduleSetting.setMiddayRestStartTime("13:30");
+		}
+		String middayRestStartTime = scheduleSetting.getMiddayRestStartTime();
+		String middayRestEndTime = scheduleSetting.getMiddayRestEndTime();
+		String onWorkTimeStr = scheduleSetting.getOnDutyTime();
+		String offWorkTimeStr = scheduleSetting.getOffDutyTime();
+		String onDutyTime = getOnDutyTime( mobileDetails, middayRestStartTime );
+		String offDutyTime = getOffDutyTime( mobileDetails, middayRestEndTime );
+		String morningOffdutyTime = getMorningOffDutyTime(mobileDetails, onWorkTimeStr, middayRestEndTime);
+		String afternoonOndutyTime = getAfternoonOnDutyTime( mobileDetails, middayRestStartTime, offWorkTimeStr );
 
-	public AttendanceDetail compose(List<AttendanceDetailMobile> mobileDetails, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
-		return null;
+		//组织员工当天的考勤打卡记录
+		AttendanceDetail detail = new AttendanceDetail();
+		detail.setEmpNo( mobileDetail.getEmpNo() );
+		detail.setEmpName( mobileDetail.getEmpName() );
+		if( mobileDetail.getRecordDate() != null ) {
+			detail.setYearString( dateOperation.getYear( mobileDetail.getRecordDate() ) );
+			detail.setMonthString( dateOperation.getMonth( mobileDetail.getRecordDate() ) );
+		}
+		detail.setRecordDateString( mobileDetail.getRecordDateString() );
+		detail.setOnDutyTime( onDutyTime ); //上午上班签到打卡
+		detail.setMorningOffdutyTime( morningOffdutyTime ); //上午下班打卡
+		detail.setAfternoonOnDutyTime( afternoonOndutyTime ); //下午上班打卡
+		detail.setOffDutyTime( offDutyTime ); //下午下班签退打卡
+		detail.setRecordStatus( 0 );
+		detail.setBatchName( "FromMobile_" + dateOperation.getNowTimeChar() );
+		return detail;
+	}
+
+	/**
+	 * 计算上午下班打卡时间:离上午上班时间最近的一次打卡时间
+	 * 取上午上班之后,到下午上班之前最晚的打卡记录
+	 *
+	 * @param mobileDetails
+	 * @param onWorkTimeStr 上午上班时间
+	 * @param middayRestEndTime 下午上班时间
+	 * @return
+	 */
+	private String getMorningOffDutyTime(List<AttendanceDetailMobile> mobileDetails, String onWorkTimeStr, String middayRestEndTime) throws Exception {
+		Date moningOffdutyTime = null;
+		Date signTime = null, afternoonOnDutyTime = null, onWorkTime = null;
+		String result = null;
+		if( ListTools.isNotEmpty( mobileDetails ) && mobileDetails.size() >=2 ) {
+			for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+				signTime = dateOperation.getDateFromString( detailMobile.getSignTime() );
+				afternoonOnDutyTime = dateOperation.getDateFromString( middayRestEndTime );
+				onWorkTime = dateOperation.getDateFromString( onWorkTimeStr );
+
+				//去掉上午上班前和下午上班后的打卡信息
+				if( signTime.before( onWorkTime ) || signTime.after( afternoonOnDutyTime )){
+					continue;
+				}
+				if( moningOffdutyTime != null && signTime != null && moningOffdutyTime.before( signTime ) ) {
+					moningOffdutyTime = signTime;
+					result = detailMobile.getSignTime();
+				}else if( moningOffdutyTime == null ){
+					moningOffdutyTime = signTime;
+					result = detailMobile.getSignTime();
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 计算下午上班打卡:离下午上班时间最近的一次打卡时间
+	 * 取上午下班之后,下午下班之前最早的一次打卡时间
+	 * @param mobileDetails
+	 * @param middayRestStartTime
+	 * @param offWorkTimeStr
+	 * @return
+	 */
+	private String getAfternoonOnDutyTime(List<AttendanceDetailMobile> mobileDetails, String middayRestStartTime, String offWorkTimeStr ) throws Exception {
+		Date afternoonOnDutyTime = null;
+		Date signTime = null, morningOffWorkTime=null, offWorkTime = null;
+		String result = null;
+		if( ListTools.isNotEmpty( mobileDetails ) && mobileDetails.size() >=2 ) {
+			for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+				signTime = dateOperation.getDateFromString( detailMobile.getSignTime() );
+				morningOffWorkTime = dateOperation.getDateFromString( middayRestStartTime );
+				offWorkTime = dateOperation.getDateFromString( offWorkTimeStr );
+
+				//上午下班之前的打卡和下午下班之后的打卡不算,取上午下班后到下午下班之前最量的一次打卡
+				if( signTime.before(morningOffWorkTime) || signTime.after( offWorkTime )){
+					continue;
+				}
+				if( afternoonOnDutyTime != null && signTime != null && signTime.before( afternoonOnDutyTime )) {
+					afternoonOnDutyTime = signTime;
+					result = detailMobile.getSignTime();
+				}else if( afternoonOnDutyTime == null ){
+					afternoonOnDutyTime = signTime;
+					result = detailMobile.getSignTime();
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 将下午上班之后所有的打卡中最晚的一次作为当天下午下班的签退打卡
+	 *
+	 * @param mobileDetails
+	 * @return
+	 * @throws Exception
+	 */
+	private String getOffDutyTime( List<AttendanceDetailMobile> mobileDetails, String middayRestEndTime ) throws Exception {
+		Date offDutyTime = null, signTime = null, afterOndutyTime=null;
+		String result = null;
+
+		for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+			signTime = dateOperation.getDateFromString(detailMobile.getSignTime() );
+			afterOndutyTime = dateOperation.getDateFromString( middayRestEndTime );
+			//下午上班前的打卡就不算到下午下班打卡了
+			if( signTime.before( afterOndutyTime )){
+				continue;
+			}
+			if( offDutyTime != null && signTime != null && offDutyTime.before( signTime )) {
+				offDutyTime = signTime;
+				result = detailMobile.getSignTime();
+			}else if( offDutyTime == null ){
+				offDutyTime = signTime;
+				result = detailMobile.getSignTime();
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 将第一次打卡时间,设置为上班打卡时间
+	 * 只可能在第一区间和第二区间,在上午下班时间之前打卡才能算当天上午的上班打卡
+	 * @param mobileDetails
+	 * @param middayRestStartTime
+	 * @return
+	 * @throws Exception
+	 */
+	private String getOnDutyTime(List<AttendanceDetailMobile> mobileDetails, String middayRestStartTime ) throws Exception {
+		Date onDutyTime = null, signTime = null, morningOffdutyTime=null;
+		String result = null;
+
+		for( AttendanceDetailMobile detailMobile : mobileDetails ) {
+			signTime = dateOperation.getDateFromString(detailMobile.getSignTime() );
+			morningOffdutyTime = dateOperation.getDateFromString( middayRestStartTime );
+			//排除在上午下班时间之后的打卡
+			if( signTime.after( morningOffdutyTime )){
+				continue;
+			}
+			if( onDutyTime != null && signTime != null && onDutyTime.after( signTime )) {
+				onDutyTime = signTime;
+				result = detailMobile.getSignTime();
+			}else if( onDutyTime == null ){
+				onDutyTime = signTime;
+				result = detailMobile.getSignTime();
+			}
+		}
+		return result;
 	}
 }