Browse Source

Merge branch 'Feature/Attendance.code.package' into 'develop'

Merge for Feature/attendance.code.package[考勤管理]移动考勤打卡分析需求修改,打卡策略可选择一天二次,三次,四次打卡,目前实现三种策略

See merge request o2oa/o2oa!603
李义 5 years ago
parent
commit
ffb823b4c4
15 changed files with 568 additions and 32 deletions
  1. 26 5
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceDetailMobileFactory.java
  2. 1 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/ActionListMobileWithFilter.java
  3. 447 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/ActionListMyMobileRecordToday.java
  4. 23 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/AttendanceDetailMobileAction.java
  5. 5 1
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailMobileService.java
  6. 10 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailServiceAdv.java
  7. 3 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/UserManagerService.java
  8. 1 1
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAdmin.java
  9. 3 3
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAppealInfo.java
  10. 4 4
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDetail.java
  11. 27 2
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDetailMobile.java
  12. 5 4
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDingtalkDetail.java
  13. 5 5
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceEmployeeConfig.java
  14. 5 4
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceQywxDetail.java
  15. 3 3
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceScheduleSetting.java

+ 26 - 5
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceDetailMobileFactory.java

@@ -24,13 +24,13 @@ public class AttendanceDetailMobileFactory extends AbstractFactory {
 	}
 
 	public List<String> listByEmployeeNameDateAndTime( String empName, String recordDateString, String signTime ) throws Exception {
-		if( empName == null || empName.isEmpty() ){
+		if( StringUtils.isEmpty( empName ) ){
 			throw new Exception("empName is null!");
 		}
-		if( recordDateString == null || recordDateString.isEmpty() ){
+		if( StringUtils.isEmpty( recordDateString ) ){
 			throw new Exception("recordDateString is null!");
 		}
-		if( signTime == null || signTime.isEmpty() ){
+		if( StringUtils.isEmpty( signTime ) ){
 			throw new Exception("signTime is null!");
 		}
 		EntityManager em = this.entityManagerContainer().get(AttendanceDetailMobile.class);
@@ -52,10 +52,10 @@ public class AttendanceDetailMobileFactory extends AbstractFactory {
 	 * @throws Exception
 	 */
 	public List<AttendanceDetailMobile> listAttendanceDetailMobileWithEmployee( String empName, String recordDateString) throws Exception {
-		if( empName == null || empName.isEmpty() ){
+		if( StringUtils.isEmpty( empName ) ){
 			throw new Exception("empName is null!");
 		}
-		if( recordDateString == null || recordDateString.isEmpty() ){
+		if( StringUtils.isEmpty( recordDateString ) ){
 			throw new Exception("recordDateString is null!");
 		}
 		EntityManager em = this.entityManagerContainer().get(AttendanceDetailMobile.class);
@@ -140,6 +140,27 @@ public class AttendanceDetailMobileFactory extends AbstractFactory {
 		return em.createQuery(cq.where(p)).setMaxResults( selectTotal ).getResultList();
 	}
 
+	public List<AttendanceDetailMobile> listAttendanceDetailMobile( String distinguishedName, String signDate ) throws Exception {
+		if( StringUtils.isEmpty( distinguishedName ) ){
+			throw new Exception("distinguishedName is null!");
+		}
+		if( StringUtils.isEmpty( signDate ) ){
+			throw new Exception("signDate is null!");
+		}
+		EntityManager em = this.entityManagerContainer().get( AttendanceDetailMobile.class );
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<AttendanceDetailMobile> cq = cb.createQuery(AttendanceDetailMobile.class);
+		Root<AttendanceDetailMobile> root = cq.from(AttendanceDetailMobile.class);
+		Predicate p = cb.isNotNull( root.get( AttendanceDetailMobile_.id ) );
+		if( StringUtils.isNotEmpty( distinguishedName ) ){
+			p = cb.and( p, cb.equal( root.get( AttendanceDetailMobile_.empNo ), distinguishedName ) );
+		}
+		if( StringUtils.isNotEmpty( signDate ) ){
+			p = cb.and( p, cb.equal( root.get( AttendanceDetailMobile_.recordDateString ), signDate ) );
+		}
+		return em.createQuery(cq.where(p)).setMaxResults( 100 ).getResultList();
+	}
+
 	public AttendanceDetailMobile get(String id) throws Exception {
 		return this.entityManagerContainer().find(id, AttendanceDetailMobile.class );
 	}

+ 1 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/ActionListMobileWithFilter.java

@@ -170,6 +170,7 @@ public class ActionListMobileWithFilter extends BaseAction {
 		}
 		result.setCount(total);
 		result.setData(wraps);
+
 		return result;
 	}
 

+ 447 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/ActionListMyMobileRecordToday.java

@@ -0,0 +1,447 @@
+package com.x.attendance.assemble.control.jaxrs.attendancedetail;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetailMobile;
+import com.x.attendance.entity.AttendanceScheduleSetting;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+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 javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 查询登录者当天的所有移动打卡信息
+ */
+public class ActionListMyMobileRecordToday extends BaseAction {
+
+	private static  Logger logger = LoggerFactory.getLogger(ActionListMyMobileRecordToday.class);
+	private DateOperation dateOperation = new DateOperation();
+
+	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson ) throws Exception {
+		ActionResult<Wo> result = new ActionResult<>();
+		EffectivePerson currentPerson = this.effectivePerson(request);
+		List<WoMobileRecord> wraps = new ArrayList<>();
+		List<AttendanceDetailMobile> attendanceDetailMobileList = null;
+		Long total = 0L;
+		Boolean check = true;
+		AttendanceScheduleSetting scheduleSetting = null;
+		WoScheduleSetting woScheduleSetting = null;
+		String signDate = dateOperation.getDateStringFromDate( new Date(), "YYYY-MM-DD");
+
+		//先查询该员工所有的考勤数据
+		if (check) {
+			try {
+				attendanceDetailMobileList = attendanceDetailServiceAdv.listAttendanceDetailMobile( effectivePerson.getDistinguishedName(), signDate );
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionAttendanceDetailProcess(e,
+						"根据条件查询员工手机打卡信息列表时发生异常.DistinguishedName:" + effectivePerson.getDistinguishedName() + ",Date:" + signDate);
+				result.error(exception);
+				logger.error(e, currentPerson, request, null);
+			}
+		}
+
+		if (check) {
+			if ( ListTools.isNotEmpty(attendanceDetailMobileList)) {
+				try {
+					wraps = WoMobileRecord.copier.copy(attendanceDetailMobileList);
+				} catch (Exception e) {
+					check = false;
+					Exception exception = new ExceptionAttendanceDetailProcess(e, "系统在转换员工手机打卡信息为输出对象时发生异常.");
+					result.error(exception);
+					logger.error(e, currentPerson, request, null);
+				}
+			}
+		}
+
+		//根据最后一次打卡信息,计算下一次打卡的信息
+		WoSignFeature woSignFeature = null;
+		if (check
+				&& !StringUtils.equalsAnyIgnoreCase("xadmin", effectivePerson.getName())
+				&& !StringUtils.equalsAnyIgnoreCase("cipher", effectivePerson.getName())) {
+			//打卡策略:1-两次打卡(上午上班,下午下班) 2-三次打卡(上午上班,下午下班加中午一次共三次) 3-四次打卡(上午下午都打上班下班卡)
+			scheduleSetting = attendanceScheduleSettingServiceAdv.getAttendanceScheduleSettingWithPerson( effectivePerson.getDistinguishedName(), effectivePerson.getDebugger() );
+
+			if( scheduleSetting != null ){
+				woScheduleSetting = WoScheduleSetting.copier.copy(scheduleSetting);
+
+				if( scheduleSetting.getSignProxy() == 3 ){
+					//3-四次打卡(上午下午都打上班下班卡)
+					woSignFeature = getWoSignFeatureWithProxy3(wraps, scheduleSetting);
+				}else if( scheduleSetting.getSignProxy() == 2 ){
+					//2-三次打卡(上午上班,下午下班加中午一次共三次)
+					woSignFeature = getWoSignFeatureWithProxy2(wraps, scheduleSetting);
+				}else{
+					//1-两次打卡(上午上班,下午下班)
+					woSignFeature = getWoSignFeatureWithProxy1(wraps, scheduleSetting);
+				}
+			}
+			if( woSignFeature != null ){
+				woSignFeature.setSignDate( signDate );
+			}
+		}
+
+		Wo wo = new Wo();
+		wo.setRecords( wraps );
+		wo.setFeature( woSignFeature );
+		wo.setScheduleSetting( woScheduleSetting );
+		result.setCount(total);
+		result.setData(wo);
+
+		return result;
+	}
+
+	/**
+	 * 计算下一次打卡是什么打卡
+	 * 3-四次打卡(上午下午都打上班下班卡)
+	 *
+	 * @param wraps
+	 * @param scheduleSetting
+	 * @return
+	 */
+	private WoSignFeature getWoSignFeatureWithProxy3(List<WoMobileRecord> wraps, AttendanceScheduleSetting scheduleSetting) throws Exception {
+		WoSignFeature woSignFeature = new WoSignFeature();
+		Date now = new Date();
+		Date onDutyTime = null, offDutyTime = null;
+		Date morningOffdutyTime = null, afternoonOndutyTime = null;
+		String todayDateStr = dateOperation.getDateStringFromDate( now, "YYYY-MM-DD");
+		SignRecordStatus signRecordStatus = null;
+
+		if( StringUtils.isEmpty( scheduleSetting.getMiddayRestStartTime())){
+			return null;
+		}
+
+		if( StringUtils.isEmpty( scheduleSetting.getMiddayRestEndTime())){
+			return null;
+		}
+
+		//计算,上班下班时间
+		onDutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getOnDutyTime() );
+		morningOffdutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getMiddayRestStartTime() );
+		afternoonOndutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getMiddayRestEndTime() );
+		offDutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getOffDutyTime() );
+
+		signRecordStatus = getSignRecordStatus( wraps, onDutyTime, morningOffdutyTime, afternoonOndutyTime, offDutyTime );
+
+		if( ListTools.isEmpty( wraps )){
+			//一次都没有打过,看看当前时间是上班还是下午,如果是上午,就是上午签到,如果是下午,就是下午签到
+			if( now.after(afternoonOndutyTime)){
+				//在下午下班时间之后了,下午上班签到打卡
+				woSignFeature.setSignSeq(1);
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_AFTERNOON_ONDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getOnDutyTime());
+			}else{
+				woSignFeature.setSignSeq(1);
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_ONDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getOnDutyTime());
+			}
+		}else{
+			woSignFeature.setSignSeq(2);
+			//当前是什么区间
+			if( onDutyTime.after(now)){
+				//上午上班之前,无论几次,都只可能是上午的下班卡
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_MORNING_OFFDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getMiddayRestStartTime());
+				woSignFeature.setSignSeq(2);
+			}else if( now.after(onDutyTime) && morningOffdutyTime.after(now)){
+				//上午上班时段: 上午签退
+				woSignFeature.setSignSeq(2);
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_MORNING_OFFDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getMiddayRestStartTime());
+			}else if( now.after(morningOffdutyTime) && afternoonOndutyTime.after( now )){
+				//午休时段:前一次打卡有可能上午签到卡,可能下午签到卡
+				if( signRecordStatus.alreadyOnduty ){ //已经上午签到过了,只有一次卡,应该就是签到
+					woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_MORNING_OFFDUTY );
+					woSignFeature.setSignTime(scheduleSetting.getMiddayRestStartTime());
+				}else if( signRecordStatus.alreadyAfternoonOnDuty){
+					//如果上午没有签到,是下午的签到的话,第二次就应该是下午签退打卡了
+					woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+					woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+				}
+			}else if( now.after(afternoonOndutyTime) && offDutyTime.after(now)){
+				//下午上班时段,如果前一次是下午签到,那么下一次就应该是下午签退了,否则,就是下午签到
+				if( signRecordStatus.alreadyAfternoonOnDuty){
+					woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY  );
+					woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+				}else{
+					woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_AFTERNOON_ONDUTY  );
+					woSignFeature.setSignTime(scheduleSetting.getMiddayRestEndTime());
+				}
+			}else{
+				//下午下班之后,只可能是下午的签到签退卡了
+				if( signRecordStatus.alreadyAfternoonOnDuty){
+					woSignFeature.setSignSeq(-1);
+					woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY  );
+					woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+				}else{
+					woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_AFTERNOON_ONDUTY  );
+					woSignFeature.setSignTime(scheduleSetting.getMiddayRestEndTime());
+				}
+			}
+		}
+		return woSignFeature;
+	}
+
+	/**
+	 * 计算下一次打卡是什么打卡
+	 * 2-三次打卡(上午上班,下午下班加中午一次共三次)
+	 *
+	 * @param wraps
+	 * @param scheduleSetting
+	 * @return
+	 */
+	private WoSignFeature getWoSignFeatureWithProxy2(List<WoMobileRecord> wraps, AttendanceScheduleSetting scheduleSetting) throws Exception {
+		WoSignFeature woSignFeature = new WoSignFeature();
+		SignRecordStatus signRecordStatus = null;
+
+		Date now = new Date();
+		Date middayRestEndTime = null;
+		Date onDutyTime = null, offDutyTime = null;
+		Date morningOffdutyTime = null, afternoonOndutyTime = null;
+		String todayDateStr = dateOperation.getDateStringFromDate( now, "YYYY-MM-DD");
+
+		//计算,上班下班时间
+		onDutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getOnDutyTime() );
+		morningOffdutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getMiddayRestStartTime() );
+		afternoonOndutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getMiddayRestEndTime() );
+		offDutyTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getOffDutyTime() );
+
+		signRecordStatus = getSignRecordStatus( wraps, onDutyTime, morningOffdutyTime, afternoonOndutyTime, offDutyTime );
+
+		if( ListTools.isEmpty( wraps )){
+			//一次都没有打过,不管几点,都是上班打卡
+			woSignFeature.setSignSeq(1);
+			woSignFeature.setSignName( "上班签到" );
+			woSignFeature.setSignTime(scheduleSetting.getOnDutyTime());
+		}else{
+			//打了一次,之后,有可能是中午签到打卡,有可能是下午下班签退打卡
+			if( wraps.size() == 1 ){
+				woSignFeature.setSignSeq(2);
+				//第一次打卡,肯定是打了上班卡,第二次就可能是午休或者下班卡了
+				if( StringUtils.isNotEmpty( scheduleSetting.getMiddayRestEndTime())){
+					middayRestEndTime = dateOperation.getDateFromString( todayDateStr + " " + scheduleSetting.getMiddayRestEndTime() );
+					//看当前时间,有没有过中午签到时间
+					if( middayRestEndTime !=null && middayRestEndTime.before( now )){
+						//在午休结束之后了,就是下班打卡了,上班和午休都缺卡了
+						woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+						woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+					}else{
+						//午休卡
+						woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_AFTERNOON );
+						woSignFeature.setSignTime(scheduleSetting.getMiddayRestEndTime());
+					}
+				}
+			}else if( wraps.size() == 2 ){
+				if( StringUtils.isNotEmpty( scheduleSetting.getMiddayRestEndTime())) {
+					middayRestEndTime = dateOperation.getDateFromString(todayDateStr + " " + scheduleSetting.getMiddayRestEndTime());
+					//只可能是签退卡了,如果签退卡都打了,那么就是不需要再打卡了。
+					//判断是否已经打了下班签退卡,看看是否有午休结束时间之后的打卡
+					Boolean exists_offDuty = false;
+					Date signTime = null;
+					for( WoMobileRecord record : wraps ){
+						signTime = dateOperation.getDateFromString(todayDateStr + " " + record.getSignTime() );
+						if( signTime.after( middayRestEndTime )){
+							exists_offDuty = true;
+							break;
+						}
+					}
+					if( exists_offDuty ){
+						woSignFeature.setSignSeq(-1);
+						woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+						woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+					}else{
+						woSignFeature.setSignSeq(3);
+						woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+						woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+					}
+				}
+			}else{
+				woSignFeature.setSignSeq(-1);
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+			}
+		}
+
+		return woSignFeature;
+	}
+
+	/**
+	 * 计算下一次打卡是什么打卡
+	 * 1-两次打卡(上午上班,下午下班)
+	 * @param wraps
+	 * @param scheduleSetting
+	 * @return
+	 */
+	private WoSignFeature getWoSignFeatureWithProxy1(List<WoMobileRecord> wraps, AttendanceScheduleSetting scheduleSetting) {
+		WoSignFeature woSignFeature = new WoSignFeature();
+		if( ListTools.isEmpty( wraps )){
+			//一次都没有打过,不管几点,都是上班打卡
+			woSignFeature.setSignSeq(1);
+			woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_ONDUTY );
+			woSignFeature.setSignTime(scheduleSetting.getOnDutyTime());
+		}else{
+			//打了一次,就是下班打卡,打了两次,就没有了
+			if( wraps.size() == 1 ){
+				woSignFeature.setSignSeq(2);
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+			}else{
+				woSignFeature.setSignSeq(-1); //没有需要的打卡了
+				woSignFeature.setSignName( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY );
+				woSignFeature.setSignTime(scheduleSetting.getOffDutyTime());
+			}
+		}
+		return woSignFeature;
+	}
+
+	private SignRecordStatus getSignRecordStatus(List<WoMobileRecord> wraps, Date onDutyTime, Date morningOffdutyTime, Date afternoonOndutyTime, Date offDutyTime) {
+		SignRecordStatus signRecordStatus = new SignRecordStatus();
+		if( ListTools.isNotEmpty( wraps )){
+			for( WoMobileRecord record : wraps ){
+				if( StringUtils.equalsAnyIgnoreCase( AttendanceDetailMobile.CHECKIN_TYPE_ONDUTY, record.getCheckin_type() )){
+					signRecordStatus.setAlreadyOnduty( true );
+				}
+				if( StringUtils.equalsAnyIgnoreCase( AttendanceDetailMobile.CHECKIN_TYPE_AFTERNOON, record.getCheckin_type() )){
+					signRecordStatus.setAlreadyAfternoon( true );
+				}
+				if( StringUtils.equalsAnyIgnoreCase( AttendanceDetailMobile.CHECKIN_TYPE_MORNING_OFFDUTY, record.getCheckin_type() )){
+					signRecordStatus.setAlreadyMorningOffDuty( true );
+				}
+				if( StringUtils.equalsAnyIgnoreCase( AttendanceDetailMobile.CHECKIN_TYPE_AFTERNOON_ONDUTY, record.getCheckin_type() )){
+					signRecordStatus.setAlreadyAfternoonOnDuty( true );
+				}
+				if( StringUtils.equalsAnyIgnoreCase( AttendanceDetailMobile.CHECKIN_TYPE_OFFDUTY, record.getCheckin_type() )){
+					signRecordStatus.setAlreadyOffDuty( true );
+				}
+			}
+		}
+		return signRecordStatus;
+	}
+
+	public static class SignRecordStatus {
+
+		@FieldDescribe("是否上午上班打卡过了ONDUTY")
+		private Boolean alreadyOnduty = false;
+
+		@FieldDescribe("是否上午下班打卡过了MORNING_OFFDUTY.")
+		private Boolean alreadyMorningOffDuty = false;
+
+		@FieldDescribe("是否下午上班打卡过了AFTERNOON_ONDUTY")
+		private Boolean alreadyAfternoonOnDuty = false;
+
+		@FieldDescribe("是否下午下班打卡过了OFFDUTY.")
+		private Boolean alreadyOffDuty = false;
+
+		@FieldDescribe("是否午间打卡过了AfternoonSign.")
+		private Boolean alreadyAfternoon = false;
+
+		public Boolean getAlreadyOnduty() { return alreadyOnduty; }
+
+		public void setAlreadyOnduty(Boolean alreadyOnduty) { this.alreadyOnduty = alreadyOnduty; }
+
+		public Boolean getAlreadyMorningOffDuty() { return alreadyMorningOffDuty; }
+
+		public void setAlreadyMorningOffDuty(Boolean alreadyMorningOffDuty) { this.alreadyMorningOffDuty = alreadyMorningOffDuty; }
+
+		public Boolean getAlreadyAfternoonOnDuty() { return alreadyAfternoonOnDuty; }
+
+		public void setAlreadyAfternoonOnDuty(Boolean alreadyAfternoonOnDuty) { this.alreadyAfternoonOnDuty = alreadyAfternoonOnDuty; }
+
+		public Boolean getAlreadyOffDuty() { return alreadyOffDuty; }
+
+		public void setAlreadyOffDuty(Boolean alreadyOffDuty) { this.alreadyOffDuty = alreadyOffDuty; }
+
+		public Boolean getAlreadyAfternoon() { return alreadyAfternoon; }
+
+		public void setAlreadyAfternoon(Boolean alreadyAfternoon) { this.alreadyAfternoon = alreadyAfternoon; }
+	}
+
+	public static class Wo{
+
+		@FieldDescribe("所有的打卡记录.")
+		private List<WoMobileRecord> records;
+
+		@FieldDescribe("个人相关的排班信息")
+		private WoScheduleSetting scheduleSetting;
+
+		@FieldDescribe("下一次打卡信息")
+		private WoSignFeature feature;
+
+		public WoScheduleSetting getScheduleSetting() { return scheduleSetting; }
+
+		public void setScheduleSetting(WoScheduleSetting scheduleSetting) { this.scheduleSetting = scheduleSetting; }
+
+		public List<WoMobileRecord> getRecords() { return records; }
+
+		public void setRecords(List<WoMobileRecord> records) { this.records = records; }
+
+		public WoSignFeature getFeature() { return feature; }
+
+		public void setFeature(WoSignFeature feature) { this.feature = feature; }
+	}
+
+	public static class WoMobileRecord extends AttendanceDetailMobile {
+
+		private static final long serialVersionUID = -5076990764713538973L;
+
+		public static WrapCopier<AttendanceDetailMobile, WoMobileRecord> copier = WrapCopierFactory.wo(AttendanceDetailMobile.class,
+				WoMobileRecord.class, null, JpaObject.FieldsInvisible);
+	}
+
+	public static class WoScheduleSetting extends AttendanceScheduleSetting {
+
+		private static final long serialVersionUID = -5076990764713538973L;
+
+		public static WrapCopier<AttendanceScheduleSetting, WoScheduleSetting> copier = WrapCopierFactory.wo(AttendanceScheduleSetting.class,
+				WoScheduleSetting.class, null, JpaObject.FieldsInvisible);
+	}
+
+	public static class WoSignFeature{
+
+		@FieldDescribe("下一次打卡次数,第一次为1")
+		private Integer signSeq = 1;
+
+		@FieldDescribe("打卡日期:yyyy-mm-dd.")
+		private String signDate = null;
+
+		@FieldDescribe("打卡时间:HH:mi:ss.")
+		private String signTime = null;
+
+		@FieldDescribe("打卡操作名称:上班打卡|下班打卡|午休打卡|上午下班打卡|下午上班打卡(根据不同的打卡策略稍有不同)....")
+		private String signName = "上班打卡";
+
+		@FieldDescribe("最晚打卡时间")
+		private Date latestSignTime;
+
+		public String getSignTime() { return signTime; }
+
+		public void setSignTime(String signTime) { this.signTime = signTime; }
+
+		public Integer getSignSeq() { return signSeq; }
+
+		public void setSignSeq(Integer signSeq) { this.signSeq = signSeq; }
+
+		public String getSignDate() { return signDate; }
+
+		public void setSignDate(String signDate) { this.signDate = signDate; }
+
+		public String getSignName() { return signName; }
+
+		public void setSignName(String signName) { this.signName = signName; }
+
+		public Date getLatestSignTime() { return latestSignTime; }
+
+		public void setLatestSignTime(Date latestSignTime) { this.latestSignTime = latestSignTime; }
+
+	}
+}

+ 23 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/AttendanceDetailMobileAction.java

@@ -58,6 +58,29 @@ public class AttendanceDetailMobileAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
+	@JaxrsMethodDescribe(value = "查询登录者当天的所有移动打卡信息记录", action = ActionListMyMobileRecordToday.class)
+	@Path("my")
+	@GET
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listMyRecords(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request ) {
+		ActionResult<ActionListMyMobileRecordToday.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		Boolean check = true;
+
+		if (check) {
+			try {
+				result = new ActionListMyMobileRecordToday().execute( request, effectivePerson );
+			} catch (Exception e) {
+				result = new ActionResult<>();
+				Exception exception = new ExceptionAttendanceDetailProcess(e, "查询登录者当天的所有移动打卡信息记录时发生异常!");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 	@JaxrsMethodDescribe(value = "移动打卡信息记录明细查询", action = ActionListMobileWithFilter.class)
 	@Path("filter/list/page/{page}/count/{count}")
 	@PUT

+ 5 - 1
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailMobileService.java

@@ -36,5 +36,9 @@ public class AttendanceDetailMobileService {
 		return business.getAttendanceDetailMobileFactory().listAttendanceDetailMobileWithEmployee( distinguishedName, recordDateString );
 	}
 
-	
+
+    public List<AttendanceDetailMobile> listAttendanceDetailMobile(EntityManagerContainer emc, String distinguishedName, String signDate) throws Exception {
+		Business business =  new Business( emc );
+		return business.getAttendanceDetailMobileFactory().listAttendanceDetailMobile( distinguishedName, signDate );
+    }
 }

+ 10 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailServiceAdv.java

@@ -211,6 +211,14 @@ public class AttendanceDetailServiceAdv {
 		}
 	}
 
+	public List<AttendanceDetailMobile> listAttendanceDetailMobile(String distinguishedName, String signDate) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			return attendanceDetailMobileService.listAttendanceDetailMobile( emc, distinguishedName, signDate );
+		} catch ( Exception e ) {
+			throw e;
+		}
+	}
+
 	public AttendanceDetailMobile getMobile(String id) throws Exception {
 		if( id == null || id.isEmpty() ){
 			return null;
@@ -283,4 +291,6 @@ public class AttendanceDetailServiceAdv {
 			throw e;
 		}
 	}
+
+
 }

+ 3 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/UserManagerService.java

@@ -69,6 +69,9 @@ public class UserManagerService {
 		Business business = null;
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			business = new Business(emc);
+			if( StringUtils.equalsAnyIgnoreCase( "xadmin", identity ) || StringUtils.equalsAnyIgnoreCase( "cipher", identity ) ){
+				return null;
+			}
 			return business.organization().unit().getWithIdentity( identity );
 		} catch ( Exception e ) {
 			throw e;

+ 1 - 1
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAdmin.java

@@ -79,7 +79,7 @@ public class AttendanceAdmin extends SliceJpaObject {
 
 	public static final String admin_FIELDNAME = "admin";
 	@FieldDescribe("管理员标识")
-	@Column(length = JpaObject.length_96B, name = ColumnNamePrefix + admin_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + admin_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + adminName_FIELDNAME)
 	private String admin = "";
 

+ 3 - 3
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAppealInfo.java

@@ -70,18 +70,18 @@ public class AttendanceAppealInfo extends SliceJpaObject {
 	private String detailId;
 
 	public static final String empName_FIELDNAME = "empName";
-	@FieldDescribe("申诉员工标识")
+	@FieldDescribe("申诉员工标识:distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + empName_FIELDNAME)
 	@CheckPersist(allowEmpty = false)
 	private String empName;
 
 	public static final String topUnitName_FIELDNAME = "topUnitName";
-	@FieldDescribe("员工所属顶层组织")
+	@FieldDescribe("员工所属顶层组织distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + topUnitName_FIELDNAME)
 	private String topUnitName;
 
 	public static final String unitName_FIELDNAME = "unitName";
-	@FieldDescribe("员工所属组织名称")
+	@FieldDescribe("员工所属组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + unitName_FIELDNAME)
 	@CheckPersist(allowEmpty = false)
 	private String unitName;

+ 4 - 4
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDetail.java

@@ -74,19 +74,19 @@ public class AttendanceDetail extends SliceJpaObject {
 	private String empNo;
 
 	public static final String empName_FIELDNAME = "empName";
-	@FieldDescribe("员工姓名")
-	@Column( length = JpaObject.length_96B, name = ColumnNamePrefix + empName_FIELDNAME)
+	@FieldDescribe("员工姓名distinguishedName")
+	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + empName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String empName;
 
 	public static final String topUnitName_FIELDNAME = "topUnitName";
-	@FieldDescribe("顶层组织名称")
+	@FieldDescribe("顶层组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + topUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String topUnitName;
 
 	public static final String unitName_FIELDNAME = "unitName";
-	@FieldDescribe("组织名称")
+	@FieldDescribe("组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + unitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String unitName;

+ 27 - 2
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDetailMobile.java

@@ -12,6 +12,7 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 
+import com.x.base.core.entity.AbstractPersistenceProperties;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.entity.JpaObject;
@@ -70,8 +71,8 @@ public class AttendanceDetailMobile extends SliceJpaObject {
 	private String empNo;
 
 	public static final String empName_FIELDNAME = "empName";
-	@FieldDescribe("员工姓名")
-	@Column( length = JpaObject.length_96B, name = ColumnNamePrefix + empName_FIELDNAME )
+	@FieldDescribe("员工姓名distinguishedName")
+	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + empName_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String empName;
 
@@ -88,6 +89,23 @@ public class AttendanceDetailMobile extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private Date recordDate;
 
+	public static final String CHECKIN_TYPE_ONDUTY = "上午上班打卡";
+	public static final String CHECKIN_TYPE_MORNING_OFFDUTY = "上午下班打卡";
+	public static final String CHECKIN_TYPE_AFTERNOON_ONDUTY = "下午上班打卡";
+	public static final String CHECKIN_TYPE_OFFDUTY = "下午下班打卡";
+//	public static final String CHECKIN_TYPE_OUTSIDE = "外出打卡";
+	public static final String CHECKIN_TYPE_AFTERNOON = "午间打卡";
+
+	public static final String checkin_type_FIELDNAME = "checkin_type";
+	@FieldDescribe("打卡类型。字符串,目前有:上午上班打卡,上午下班打卡,下午上班打卡,下午下班打卡,外出打卡,午间打卡")
+	@Column(name = ColumnNamePrefix + checkin_type_FIELDNAME, length = length_32B)
+	private String checkin_type;
+
+	public static final String checkin_time_FIELDNAME = "checkin_time";
+	@FieldDescribe("打卡时间。Unix时间戳")
+	@Column(name = ColumnNamePrefix + checkin_time_FIELDNAME )
+	private long checkin_time;
+
 	public static final String signTime_FIELDNAME = "signTime";
 	@FieldDescribe("打卡时间")
 	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + signTime_FIELDNAME )
@@ -245,4 +263,11 @@ public class AttendanceDetailMobile extends SliceJpaObject {
 		this.recordStatus = recordStatus;
 	}
 
+	public String getCheckin_type() { return checkin_type; }
+
+	public void setCheckin_type(String checkin_type) { this.checkin_type = checkin_type; }
+
+	public long getCheckin_time() { return checkin_time; }
+
+	public void setCheckin_time(long checkin_time) { this.checkin_time = checkin_time; }
 }

+ 5 - 4
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDingtalkDetail.java

@@ -1,6 +1,7 @@
 package com.x.attendance.entity;
 
 
+import com.x.base.core.entity.AbstractPersistenceProperties;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.entity.SliceJpaObject;
 import com.x.base.core.entity.annotation.ContainerEntity;
@@ -56,13 +57,13 @@ public class AttendanceDingtalkDetail extends SliceJpaObject  {
     private String userId;
 
     public static final String o2User_FIELDNAME = "o2User";
-    @FieldDescribe("O2OA用户")
-    @Column( length = length_128B, name = ColumnNamePrefix + o2User_FIELDNAME )
+    @FieldDescribe("O2OA用户distinguishedName")
+    @Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + o2User_FIELDNAME )
     private String o2User;
 
     public static final String o2Unit_FIELDNAME = "o2Unit";
-    @FieldDescribe("O2OA用户所在的组织")
-    @Column( length = length_128B, name = ColumnNamePrefix + o2Unit_FIELDNAME )
+    @FieldDescribe("O2OA用户所在的组织distinguishedName")
+    @Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + o2Unit_FIELDNAME )
     private String o2Unit;
 
     public static final String baseCheckTime_FIELDNAME = "baseCheckTime";

+ 5 - 5
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceEmployeeConfig.java

@@ -55,19 +55,19 @@ public class AttendanceEmployeeConfig extends SliceJpaObject {
 	 * =====
 	 */
 	public static final String topUnitName_FIELDNAME = "topUnitName";
-	@FieldDescribe("顶层组织名称")
+	@FieldDescribe("顶层组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + topUnitName_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String topUnitName = "";
 
 	public static final String topUnitOu_FIELDNAME = "topUnitOu";
-	@FieldDescribe("顶层组织编号")
+	@FieldDescribe("顶层组织编号distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + topUnitOu_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String topUnitOu = "";
 
 	public static final String unitName_FIELDNAME = "unitName";
-	@FieldDescribe("组织名称")
+	@FieldDescribe("组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + unitName_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String unitName = "";
@@ -79,8 +79,8 @@ public class AttendanceEmployeeConfig extends SliceJpaObject {
 	private String unitOu = "";
 
 	public static final String employeeName_FIELDNAME = "employeeName";
-	@FieldDescribe("员工姓名")
-	@Column( length = JpaObject.length_96B, name = ColumnNamePrefix + employeeName_FIELDNAME )
+	@FieldDescribe("员工姓名distinguishedName")
+	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + employeeName_FIELDNAME )
 	@CheckPersist(allowEmpty = false)
 	private String employeeName = "";
 

+ 5 - 4
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceQywxDetail.java

@@ -1,6 +1,7 @@
 package com.x.attendance.entity;
 
 
+import com.x.base.core.entity.AbstractPersistenceProperties;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.entity.SliceJpaObject;
 import com.x.base.core.entity.annotation.ContainerEntity;
@@ -46,13 +47,13 @@ public class AttendanceQywxDetail extends SliceJpaObject  {
 
 
     public static final String o2User_FIELDNAME = "o2User";
-    @FieldDescribe("O2用户")
-    @Column(name = ColumnNamePrefix + o2User_FIELDNAME, length = length_128B)
+    @FieldDescribe("O2用户distinguishedName")
+    @Column(name = ColumnNamePrefix + o2User_FIELDNAME, length = AbstractPersistenceProperties.organization_name_length)
     private String o2User;
 
     public static final String o2Unit_FIELDNAME = "o2Unit";
-    @FieldDescribe("O2用户所在的组织")
-    @Column(name = ColumnNamePrefix + o2Unit_FIELDNAME, length = length_128B)
+    @FieldDescribe("O2用户所在的组织distinguishedName")
+    @Column(name = ColumnNamePrefix + o2Unit_FIELDNAME, length = AbstractPersistenceProperties.organization_name_length)
     private String o2Unit;
 
     public static final String userid_FIELDNAME = "userid";

+ 3 - 3
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceScheduleSetting.java

@@ -60,21 +60,21 @@ public class AttendanceScheduleSetting extends SliceJpaObject {
 	 * =====
 	 */
 	public static final String topUnitName_FIELDNAME = "topUnitName";
-	@FieldDescribe("顶层组织名称")
+	@FieldDescribe("顶层组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + topUnitName_FIELDNAME )
 	@Index(name = TABLE + IndexNameMiddle + topUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String topUnitName;
 
 	public static final String unitName_FIELDNAME = "unitName";
-	@FieldDescribe("组织名称")
+	@FieldDescribe("组织名称distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + unitName_FIELDNAME )
 	@Index(name = TABLE + IndexNameMiddle + unitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String unitName;
 
 	public static final String unitOu_FIELDNAME = "unitOu";
-	@FieldDescribe("组织编号")
+	@FieldDescribe("组织编号distinguishedName")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + unitOu_FIELDNAME )
 	@Index(name = TABLE + IndexNameMiddle + unitOu_FIELDNAME)
 	@CheckPersist(allowEmpty = true)