Browse Source

考勤打卡需求修改

o2lee 5 years ago
parent
commit
b8c49b2337
43 changed files with 2382 additions and 1106 deletions
  1. 5 1
      o2server/x_attendance_assemble_control/pom.xml
  2. 35 55
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/common/date/DateOperation.java
  3. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueAttendanceDetailStatistic.java
  4. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueDingdingAttendance.java
  5. 2 4
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueDingdingPersonStatistic.java
  6. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueDingdingUnitStatistic.java
  7. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueuePersonAttendanceDetailAnalyse.java
  8. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueQywxAttendanceSync.java
  9. 2 3
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueQywxPersonStatistic.java
  10. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueQywxUnitStatistic.java
  11. 8 8
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/ThisApplication.java
  12. 10 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealAudit.java
  13. 13 3
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealCheck.java
  14. 34 27
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealCreate.java
  15. 118 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealCreateWithWorkFlow.java
  16. 0 112
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealProcessFirst.java
  17. 0 114
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealProcessSecond.java
  18. 0 228
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAttendanceDetailAppeal.java
  19. 0 46
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAttendanceDetailArchive.java
  20. 146 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionWorkFlowSync.java
  21. 56 4
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/AttendanceAppealInfoAction.java
  22. 12 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ExceptionAppealAuditInfoNotExists.java
  23. 1 1
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendancedetail/ActionReciveAttendanceMobile.java
  24. 55 15
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceAppealInfoService.java
  25. 71 9
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceAppealInfoServiceAdv.java
  26. 302 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailAnalyseCoreService.java
  27. 2 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailAnalyseService.java
  28. 219 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailAnalyseSignProxy1.java
  29. 247 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailAnalyseSignProxy2.java
  30. 285 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailAnalyseSignProxy3.java
  31. 34 88
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceDetailServiceAdv.java
  32. 1 1
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceSettingService.java
  33. 101 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/ComposeDetailWithMobileInSignProxy1.java
  34. 25 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/ComposeDetailWithMobileInSignProxy2.java
  35. 25 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/ComposeDetailWithMobileInSignProxy3.java
  36. 244 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/WorkFlowSyncService.java
  37. 1 1
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAdmin.java
  38. 14 11
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAppealAuditInfo.java
  39. 145 149
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAppealInfo.java
  40. 29 9
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceDetail.java
  41. 2 2
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceScheduleSetting.java
  42. 0 1
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceSetting.java
  43. 126 198
      o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/DateOperation.java

+ 5 - 1
o2server/x_attendance_assemble_control/pom.xml

@@ -24,7 +24,11 @@
 			<groupId>o2oa</groupId>
 			<artifactId>x_organization_core_express</artifactId>
 		</dependency>
-	</dependencies>
+        <dependency>
+            <groupId>o2oa</groupId>
+            <artifactId>x_processplatform_core_entity</artifactId>
+        </dependency>
+    </dependencies>
 	<build>
 		<plugins>
 			<plugin>

+ 35 - 55
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/common/date/DateOperation.java

@@ -149,26 +149,25 @@ public class DateOperation {
 		}
 		return dateString;
 	}
-	
+
 	/**
 	 * 得到某日期加上或减去天数后的日期,day为负数时减去
-	 * 
-	 * @param date
-	 * @param month
-	 * @return "yyyy-MM-dd"
-	 * @throws Exception 
+	 * @param dateString
+	 * @param day
+	 * @param style
+	 * @return
+	 * @throws Exception
 	 */
 	public  String getDayAdd(String dateString, int day, String style) throws Exception {
 		Date date = getDateFromString(dateString, style);
 		return getDayAdd(date, day);
 	}
-	
+
 	/**
 	 * 得到某日期加上或减去天数后的日期,day为负数时减去
-	 * 
 	 * @param date
-	 * @param month
-	 * @return "yyyy-MM-dd"
+	 * @param day
+	 * @return
 	 */
 	public  String getDayAdd(Date date, int day) {
 		Calendar calendar = Calendar.getInstance();
@@ -190,13 +189,12 @@ public class DateOperation {
 		calendar.add(Calendar.MONTH, month);
 		return format1.format(calendar.getTime());
 	}
-	
+
 	/**
 	 * 得到某日期加上或减去分钟后的日期,min为负数时减去
-	 * 
 	 * @param date
-	 * @param month
-	 * @return "yyyy-MM-dd HH:mi:ss"
+	 * @param min
+	 * @return
 	 */
 	public  String getMinutesAdd(Date date, int min) {
 		Calendar calendar = Calendar.getInstance();
@@ -204,11 +202,10 @@ public class DateOperation {
 		calendar.add(Calendar.MINUTE, min);
 		return format3.format(calendar.getTime());
 	}
+
 	/**
 	 * 得到某日期的日
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 */
 	public  String getDay(Date date) {
@@ -227,11 +224,10 @@ public class DateOperation {
 		}
 		return Integer.parseInt(result);
 	}
+
 	/**
 	 * 得到某日期的月份
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 */
 	public  String getMonth(Date date) {
@@ -253,9 +249,7 @@ public class DateOperation {
 
 	/**
 	 * 得到某日期的年份
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 */
 	public  String getYear(Date date) {
@@ -274,11 +268,10 @@ public class DateOperation {
 		}
 		return Integer.parseInt(result);
 	}
+
 	/**
 	 * 得到某日期的小时
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 */
 	public  String getHour(Date date) {
@@ -288,31 +281,28 @@ public class DateOperation {
 			return "0";
 		}
 	}
+
 	/**
 	 * 得到某日期的分钟
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 */
 	public  String getMinites(Date date) {
 		return format12.format(date);
 	}
+
 	/**
 	 * 得到某日期的秒
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 */
 	public  String getSeconds(Date date) {
 		return format13.format(date);
 	}
+
 	/**
 	 * 得到某年有多少天
-	 * 
-	 * @param String
-	 *            date "yyyy-MM-dd"
+	 * @param date
 	 * @return
 	 * @throws ParseException
 	 */
@@ -325,9 +315,7 @@ public class DateOperation {
 
 	/**
 	 * 得到某年有多少天
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 * @throws ParseException
 	 */
@@ -340,9 +328,7 @@ public class DateOperation {
 
 	/**
 	 * 得到某年有多少天
-	 * 
-	 * @param String
-	 *            year "yyyy"
+	 * @param year
 	 * @return
 	 * @throws ParseException
 	 */
@@ -355,9 +341,7 @@ public class DateOperation {
 
 	/**
 	 * 得到某月有多少天
-	 * 
-	 * @param String
-	 *            date "yyyy-MM-dd"
+	 * @param date
 	 * @return
 	 * @throws ParseException
 	 */
@@ -369,9 +353,7 @@ public class DateOperation {
 
 	/**
 	 * 得到某月有多少天
-	 * 
-	 * @param String
-	 *            date "yyyy-MM"
+	 * @param date
 	 * @return
 	 * @throws ParseException
 	 */
@@ -384,9 +366,7 @@ public class DateOperation {
 
 	/**
 	 * 得到某月有多少天
-	 * 
-	 * @param Date
-	 *            date
+	 * @param date
 	 * @return
 	 * @throws ParseException
 	 */
@@ -468,12 +448,12 @@ public class DateOperation {
 		dayNumber = (date2.getTime() - date1.getTime()) / mins;
 		return dayNumber;
 	}
+
 	/**
-	 * 
-	 * 日期格式转换
-	 * 从YYYY-MM-DD转换到YYYYMMDD
-	 * @param date
-	 * @throws ParseException 
+	 * 日期格式转换 从YYYY-MM-DD转换到YYYYMMDD
+	 * @param dateString
+	 * @return
+	 * @throws ParseException
 	 */
 	public  String changeDateFormat(String dateString) throws ParseException{
 		Date date;

+ 2 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/AttendanceDetailStatisticQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueAttendanceDetailStatistic.java

@@ -16,9 +16,9 @@ import java.util.Map;
 /**
  * 对单个员工的打卡信息进行分析的队列
  */
-public class AttendanceDetailStatisticQueue extends AbstractQueue<String> {
+public class QueueAttendanceDetailStatistic extends AbstractQueue<String> {
 
-    private static final Logger logger = LoggerFactory.getLogger(AttendanceDetailStatisticQueue.class);
+    private static final Logger logger = LoggerFactory.getLogger(QueueAttendanceDetailStatistic.class);
 
     @Override
     protected void execute( String logId ) throws Exception {

+ 2 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/DingdingAttendanceQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueDingdingAttendance.java

@@ -34,9 +34,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class DingdingAttendanceQueue extends AbstractQueue<DingdingQywxSyncRecord> {
+public class QueueDingdingAttendance extends AbstractQueue<DingdingQywxSyncRecord> {
 
-    private static final Logger logger = LoggerFactory.getLogger(DingdingAttendanceQueue.class);
+    private static final Logger logger = LoggerFactory.getLogger(QueueDingdingAttendance.class);
 
     @Override
     protected void execute(DingdingQywxSyncRecord record) throws Exception {

+ 2 - 4
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/DingdingPersonStatisticQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueDingdingPersonStatistic.java

@@ -2,8 +2,6 @@ package com.x.attendance.assemble.control;
 
 import com.x.attendance.entity.AttendanceDingtalkDetail;
 import com.x.attendance.entity.StatisticDingdingPersonForMonth;
-import com.x.attendance.entity.StatisticDingdingUnitForDay;
-import com.x.attendance.entity.StatisticDingdingUnitForMonth;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.project.Application;
@@ -25,8 +23,8 @@ import java.util.List;
  * Created by fancyLou on 2020-04-05.
  * Copyright © 2020 O2. All rights reserved.
  */
-public class DingdingPersonStatisticQueue extends AbstractQueue<Date> {
-    private static final Logger logger = LoggerFactory.getLogger(DingdingPersonStatisticQueue.class);
+public class QueueDingdingPersonStatistic extends AbstractQueue<Date> {
+    private static final Logger logger = LoggerFactory.getLogger(QueueDingdingPersonStatistic.class);
 
     @Override
     protected void execute(Date date) throws Exception {

+ 2 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/DingdingUnitStatisticQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueDingdingUnitStatistic.java

@@ -19,8 +19,8 @@ import java.util.List;
  * Created by fancyLou on 2020-04-05.
  * Copyright © 2020 O2. All rights reserved.
  */
-public class DingdingUnitStatisticQueue extends AbstractQueue<Date> {
-    private static final Logger logger = LoggerFactory.getLogger(DingdingUnitStatisticQueue.class);
+public class QueueDingdingUnitStatistic extends AbstractQueue<Date> {
+    private static final Logger logger = LoggerFactory.getLogger(QueueDingdingUnitStatistic.class);
 
     @Override
     protected void execute(Date date) throws Exception {

+ 2 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/PersonAttendanceDetailAnalyseQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueuePersonAttendanceDetailAnalyse.java

@@ -20,9 +20,9 @@ import java.util.Map;
 /**
  * 对单个员工的打卡信息进行分析的队列
  */
-public class PersonAttendanceDetailAnalyseQueue extends AbstractQueue<String> {
+public class QueuePersonAttendanceDetailAnalyse extends AbstractQueue<String> {
 
-    private static final Logger logger = LoggerFactory.getLogger(PersonAttendanceDetailAnalyseQueue.class);
+    private static final Logger logger = LoggerFactory.getLogger(QueuePersonAttendanceDetailAnalyse.class);
 
     @Override
     protected void execute( String detailId ) throws Exception {

+ 2 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QywxAttendanceSyncQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueQywxAttendanceSync.java

@@ -33,9 +33,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-public class QywxAttendanceSyncQueue  extends AbstractQueue<DingdingQywxSyncRecord> {
+public class QueueQywxAttendanceSync extends AbstractQueue<DingdingQywxSyncRecord> {
 
-    private static final Logger logger = LoggerFactory.getLogger(QywxAttendanceSyncQueue.class);
+    private static final Logger logger = LoggerFactory.getLogger(QueueQywxAttendanceSync.class);
 
 
     @Override

+ 2 - 3
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QywxPersonStatisticQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueQywxPersonStatistic.java

@@ -1,6 +1,5 @@
 package com.x.attendance.assemble.control;
 
-import com.x.attendance.entity.AttendanceDingtalkDetail;
 import com.x.attendance.entity.AttendanceQywxDetail;
 import com.x.attendance.entity.StatisticQywxPersonForMonth;
 import com.x.base.core.container.EntityManagerContainer;
@@ -25,8 +24,8 @@ import java.util.stream.Collectors;
  * Created by fancyLou on 2020-04-05.
  * Copyright © 2020 O2. All rights reserved.
  */
-public class QywxPersonStatisticQueue extends AbstractQueue<Date> {
-    private static final Logger logger = LoggerFactory.getLogger(QywxPersonStatisticQueue.class);
+public class QueueQywxPersonStatistic extends AbstractQueue<Date> {
+    private static final Logger logger = LoggerFactory.getLogger(QueueQywxPersonStatistic.class);
 
     @Override
     protected void execute(Date date) throws Exception {

+ 2 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QywxUnitStatisticQueue.java → o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/QueueQywxUnitStatistic.java

@@ -18,8 +18,8 @@ import java.util.stream.Collectors;
  * Created by fancyLou on 2020-04-05.
  * Copyright © 2020 O2. All rights reserved.
  */
-public class QywxUnitStatisticQueue extends AbstractQueue<Date> {
-    private static final Logger logger = LoggerFactory.getLogger(QywxUnitStatisticQueue.class);
+public class QueueQywxUnitStatistic extends AbstractQueue<Date> {
+    private static final Logger logger = LoggerFactory.getLogger(QueueQywxUnitStatistic.class);
 
     @Override
     protected void execute(Date date) throws Exception {

+ 8 - 8
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/ThisApplication.java

@@ -16,15 +16,15 @@ public class ThisApplication {
 		return context;
 	}
 
-	public static DingdingAttendanceQueue dingdingQueue = new DingdingAttendanceQueue();
-	public static QywxAttendanceSyncQueue qywxQueue = new QywxAttendanceSyncQueue();
-	public static QywxUnitStatisticQueue unitQywxStatisticQueue = new QywxUnitStatisticQueue();
-	public static QywxPersonStatisticQueue personQywxStatisticQueue = new QywxPersonStatisticQueue();
-	public static DingdingPersonStatisticQueue personStatisticQueue = new DingdingPersonStatisticQueue();
-	public static DingdingUnitStatisticQueue unitStatisticQueue = new DingdingUnitStatisticQueue();
+	public static QueueDingdingAttendance dingdingQueue = new QueueDingdingAttendance();
+	public static QueueQywxAttendanceSync qywxQueue = new QueueQywxAttendanceSync();
+	public static QueueQywxUnitStatistic unitQywxStatisticQueue = new QueueQywxUnitStatistic();
+	public static QueueQywxPersonStatistic personQywxStatisticQueue = new QueueQywxPersonStatistic();
+	public static QueueDingdingPersonStatistic personStatisticQueue = new QueueDingdingPersonStatistic();
+	public static QueueDingdingUnitStatistic unitStatisticQueue = new QueueDingdingUnitStatistic();
 
-	public static PersonAttendanceDetailAnalyseQueue detailAnalyseQueue = new PersonAttendanceDetailAnalyseQueue();
-	public static AttendanceDetailStatisticQueue detailStatisticQueue = new AttendanceDetailStatisticQueue();
+	public static QueuePersonAttendanceDetailAnalyse detailAnalyseQueue = new QueuePersonAttendanceDetailAnalyse();
+	public static QueueAttendanceDetailStatistic detailStatisticQueue = new QueueAttendanceDetailStatistic();
 
 
 	public static void init() throws Exception {

+ 10 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealAudit.java

@@ -10,6 +10,7 @@ import com.google.gson.JsonElement;
 import com.x.attendance.assemble.control.ExceptionWrapInConvert;
 import com.x.attendance.entity.AttendanceAppealInfo;
 import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
@@ -19,8 +20,7 @@ public class ActionAppealAudit extends BaseAction {
 
 	private static Logger logger = LoggerFactory.getLogger(ActionAppealAudit.class);
 
-	protected ActionResult<Wo> execute(HttpServletRequest request, EffectivePerson effectivePerson,
-			JsonElement jsonElement) throws Exception {
+	protected ActionResult<Wo> execute(HttpServletRequest request, EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
 		ActionResult<Wo> result = new ActionResult<>();
 		Wo wo = new Wo();
 		List<String> ids = null;
@@ -144,8 +144,13 @@ public class ActionAppealAudit extends BaseAction {
 
 		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
 
+		@FieldDescribe("需要复核的ID列表")
 		private List<String> ids = null;
 
+		@FieldDescribe("审批意见")
+		private String opinion1;
+
+		@FieldDescribe("申诉人的身份,考勤人员身份:如果考勤人员属于多个组织,可以选择一个身份进行申诉信息绑定.")
 		private String identity = null;
 
 		public String getIdentity() {
@@ -164,6 +169,9 @@ public class ActionAppealAudit extends BaseAction {
 			this.ids = ids;
 		}
 
+		public String getOpinion1() { return opinion1; }
+
+		public void setOpinion1(String opinion1) { this.opinion1 = opinion1; }
 	}
 
 	public static class Wo {

+ 13 - 3
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealCheck.java

@@ -4,12 +4,14 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
+import javax.persistence.Column;
 import javax.servlet.http.HttpServletRequest;
 
 import com.google.gson.JsonElement;
 import com.x.attendance.assemble.control.ExceptionWrapInConvert;
 import com.x.attendance.entity.AttendanceAppealInfo;
 import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
@@ -134,14 +136,19 @@ public class ActionAppealCheck extends BaseAction {
 		return result;
 	}
 	
-public static class Wi extends AttendanceAppealInfo {
+	public static class Wi extends AttendanceAppealInfo {
 		
 		private static final long serialVersionUID = -5076990764713538973L;
 		
 		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
-		
+
+		@FieldDescribe("需要复核的ID列表")
 		private List<String> ids = null;
 
+		@FieldDescribe("复核意见")
+		private String opinion2;
+
+		@FieldDescribe("申诉人的身份,考勤人员身份:如果考勤人员属于多个组织,可以选择一个身份进行申诉信息绑定.")
 		private String identity = null;
 
 		public String getIdentity() {
@@ -159,7 +166,10 @@ public static class Wi extends AttendanceAppealInfo {
 		public void setIds(List<String> ids) {
 			this.ids = ids;
 		}
-		
+
+		public String getOpinion2() { return opinion2; }
+
+		public void setOpinion2(String opinion2) { this.opinion2 = opinion2; }
 	}
 	
 	public static class Wo {

+ 34 - 27
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealCreate.java

@@ -3,9 +3,11 @@ package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
 import com.google.gson.JsonElement;
 import com.x.attendance.assemble.control.ExceptionWrapInConvert;
 import com.x.attendance.entity.AppealConfig;
+import com.x.attendance.entity.AttendanceAppealAuditInfo;
 import com.x.attendance.entity.AttendanceAppealInfo;
 import com.x.attendance.entity.AttendanceDetail;
 import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WoId;
@@ -23,6 +25,7 @@ public class ActionAppealCreate extends BaseAction {
 	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id, JsonElement jsonElement ) throws Exception {
 		ActionResult<Wo> result = new ActionResult<>();
 		AttendanceAppealInfo attendanceAppealInfo = null;
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = null;
 		AttendanceDetail attendanceDetail = null;
 		String appealAuditPersonName = null;
 		String appealCheckPersonName = null;
@@ -59,13 +62,7 @@ public class ActionAppealCreate extends BaseAction {
 				logger.error(e, effectivePerson, request, null);
 			}
 		}
-		
-		if (check) {
-			// 利用打卡记录中的信息,创建一个申诉信息记录
-			attendanceAppealInfo = attendanceSettingServiceAdv.composeAppealInfoWithDetailInfo( attendanceDetail, 
-					wrapIn.getReason(), wrapIn.getAppealReason(),  wrapIn.getSelfHolidayType(),  wrapIn.getAddress(), 
-					wrapIn.getStartTime(),  wrapIn.getEndTime(),  wrapIn.getAppealDescription() );
-		}
+
 		if (check) {
 			try {
 				appeal_auditor_type = attendanceSettingServiceAdv.getValueByCode( "APPEAL_AUDITOR_TYPE" );
@@ -79,19 +76,30 @@ public class ActionAppealCreate extends BaseAction {
 				logger.error( e, effectivePerson, request, null);
 			}
 		}
+
+		if (check) {
+			// 利用打卡记录中的信息,创建一个申诉信息记录
+			attendanceAppealInfo = attendanceSettingServiceAdv.composeAppealInfoWithDetailInfo( attendanceDetail, 
+					wrapIn.getReason(), wrapIn.getAppealReason(),  wrapIn.getSelfHolidayType(),  wrapIn.getAddress(), 
+					wrapIn.getStartTime(),  wrapIn.getEndTime(),  wrapIn.getAppealDescription() );
+			// 创建一个申诉审批记录信息
+			attendanceAppealAuditInfo = new AttendanceAppealAuditInfo();
+			attendanceAppealAuditInfo.setId( attendanceAppealInfo.getId());
+			attendanceAppealAuditInfo.setDetailId( attendanceDetail.getId() );
+		}
+
 		
 		//查询申诉审核人
 		if (check) {
 			if( StringUtils.isNotEmpty( appeal_auditor_type ) ) {
 				try {
-//					System.out.println("personName:" + personName );
-//					System.out.println("attendanceAppealInfo.getUnitName():" + attendanceAppealInfo.getUnitName() );
-//					System.out.println("wrapIn.getIdentity():" + wrapIn.getIdentity() );
 					appealAuditPersonName = attendanceAppealInfoServiceAdv.getAppealAuditPerson( personName, attendanceAppealInfo.getUnitName(), wrapIn.getIdentity() );
 					if( StringUtils.isNotEmpty( appealAuditPersonName )){
 						appealAuditPersonName = userManagerService.getPersonNameByIdentity(appealAuditPersonName);
-						attendanceAppealInfo.setProcessPerson1( appealAuditPersonName );
+						attendanceAppealAuditInfo.setProcessPerson1( appealAuditPersonName );
+						attendanceAppealAuditInfo.setCurrentProcessor( appealAuditPersonName );
 						attendanceAppealInfo.setCurrentProcessor( appealAuditPersonName );// 将第一个处理人设置为当前处理人
+						attendanceAppealAuditInfo.setAuditFlowType( AppealConfig.APPEAL_AUDIFLOWTYPE_BUILTIN );
 					}
 				}catch( Exception e ) {
 					check = false;
@@ -112,7 +120,8 @@ public class ActionAppealCreate extends BaseAction {
 				if( StringUtils.isEmpty(appeal_auditor_type)) {
 					message = "申诉审核人类别未配置!";
 				}else if( "无".equals( appeal_auditor_type.trim() )){//当前人处理
-					attendanceAppealInfo.setProcessPerson1( effectivePerson.getDistinguishedName() );
+					attendanceAppealAuditInfo.setProcessPerson1( effectivePerson.getDistinguishedName() );
+					attendanceAppealAuditInfo.setCurrentProcessor( effectivePerson.getDistinguishedName() );// 将第一个处理人设置为当前处理人
 					attendanceAppealInfo.setCurrentProcessor( effectivePerson.getDistinguishedName() );// 将第一个处理人设置为当前处理人
 				}else if( AppealConfig.APPEAL_AUDITTYPE_UNITDUTY.equals( appeal_auditor_type )){
 					unitLevelName = userManagerService.getUnitLevelNameWithName( attendanceDetail.getUnitName() );
@@ -136,7 +145,7 @@ public class ActionAppealCreate extends BaseAction {
 			if( StringUtils.isNotEmpty( appeal_checker_type ) && !"无".equals( appeal_auditor_type  ) ) {
 				try {
 					appealCheckPersonName = attendanceAppealInfoServiceAdv.getAppealCheckPerson( personName, attendanceAppealInfo.getUnitName(), wrapIn.getIdentity() );
-					attendanceAppealInfo.setProcessPerson2( appealCheckPersonName );
+					attendanceAppealAuditInfo.setProcessPerson2( appealCheckPersonName );
 				}catch( Exception e ) {
 					check = false;
 					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据根据考勤人员查询申诉复核人信息时发生异常!personName:"+personName );
@@ -177,13 +186,13 @@ public class ActionAppealCreate extends BaseAction {
 		//查询申诉审核人所属组织
 		if (check) {
 			if( AppealConfig.APPEAL_AUDITTYPE_UNITDUTY.equalsIgnoreCase( appeal_auditor_type ) ) {
-				attendanceAppealInfo.setProcessPersonUnit1(
+				attendanceAppealAuditInfo.setProcessPersonUnit1(
 						attendanceAppealInfoServiceAdv.getPersonUnitName( appealAuditPersonName, attendanceDetail.getUnitName(), wrapIn.getIdentity() ) );
 			}else {
 				//汇报对象,指定人以及人员属性中指定的人员,根据人员姓名取首选组织(第一个)
 				if( StringUtils.isNotEmpty( appealAuditPersonName ) ) {
 					try {//获取审核人组织信息
-						attendanceAppealInfo.setProcessPersonUnit1( userManagerService.getUnitNameWithPersonName( appealAuditPersonName ));
+						attendanceAppealAuditInfo.setProcessPersonUnit1( userManagerService.getUnitNameWithPersonName( appealAuditPersonName ));
 					}catch( Exception e ) {
 						check = false;
 						Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据审核人获取组织信息时发生异常。");
@@ -196,9 +205,9 @@ public class ActionAppealCreate extends BaseAction {
 		}
 		//根据所属组织名称查询申诉审核人所属顶层组织
 		if (check) {
-			if( StringUtils.isNotEmpty( attendanceAppealInfo.getProcessPersonUnit1() )) {
+			if( StringUtils.isNotEmpty( attendanceAppealAuditInfo.getProcessPersonUnit1() )) {
 				try {
-					attendanceAppealInfo.setProcessPersonTopUnit1( userManagerService.getTopUnitNameWithUnitName( attendanceAppealInfo.getProcessPersonUnit1() ) );
+					attendanceAppealAuditInfo.setProcessPersonTopUnit1( userManagerService.getTopUnitNameWithUnitName( attendanceAppealAuditInfo.getProcessPersonUnit1() ) );
 				}catch( Exception e ) {
 					check = false;
 					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据审核人获取顶层组织信息时发生异常。");
@@ -212,12 +221,12 @@ public class ActionAppealCreate extends BaseAction {
 		//查询申诉复核人所属组织
 		if (check) {
 			if( AppealConfig.APPEAL_AUDITTYPE_UNITDUTY.equalsIgnoreCase( appeal_auditor_type ) ) {
-				attendanceAppealInfo.setProcessPersonUnit2( attendanceAppealInfoServiceAdv.getPersonUnitName( appealCheckPersonName, attendanceDetail.getUnitName(), wrapIn.getIdentity() ) );
+				attendanceAppealAuditInfo.setProcessPersonUnit2( attendanceAppealInfoServiceAdv.getPersonUnitName( appealCheckPersonName, attendanceDetail.getUnitName(), wrapIn.getIdentity() ) );
 			}else {
 				//汇报对象,指定人以及人员属性中指定的人员,根据人员姓名取首选组织(第一个)
 				if( appealCheckPersonName != null  && !appealCheckPersonName.isEmpty() ) {
 					try {//获取复核人组织信息
-						attendanceAppealInfo.setProcessPersonUnit2( userManagerService.getUnitNameWithPersonName( appealCheckPersonName ));
+						attendanceAppealAuditInfo.setProcessPersonUnit2( userManagerService.getUnitNameWithPersonName( appealCheckPersonName ));
 					}catch( Exception e ) {
 						check = false;
 						Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据复核人获取组织信息时发生异常。");
@@ -230,9 +239,9 @@ public class ActionAppealCreate extends BaseAction {
 		}
 		//根据所属组织名称查询申诉复核人所属顶层组织
 		if (check) {
-			if( StringUtils.isNotEmpty(attendanceAppealInfo.getProcessPersonUnit2())) {
+			if( StringUtils.isNotEmpty(attendanceAppealAuditInfo.getProcessPersonUnit2())) {
 				try {//获取复核人顶层组织信息
-					attendanceAppealInfo.setProcessPersonTopUnit2(  userManagerService.getTopUnitNameWithUnitName( attendanceAppealInfo.getProcessPersonUnit2()) );
+					attendanceAppealAuditInfo.setProcessPersonTopUnit2(  userManagerService.getTopUnitNameWithUnitName( attendanceAppealAuditInfo.getProcessPersonUnit2()) );
 				}catch( Exception e ) {
 					check = false;
 					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据复核人获取顶层组织信息时发生异常。");
@@ -245,8 +254,8 @@ public class ActionAppealCreate extends BaseAction {
 		//保存申诉信息
 		if (check) {
 			try {
-				attendanceAppealInfo = attendanceAppealInfoServiceAdv.saveNewAppeal( attendanceAppealInfo );
-				result.setData(new Wo(id));
+				attendanceAppealInfo = attendanceAppealInfoServiceAdv.saveNewAppeal( attendanceAppealInfo, attendanceAppealAuditInfo );
+				result.setData(new Wo(attendanceAppealInfo.getId()));
 			} catch (Exception e) {
 				check = false;
 				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在保存考勤申诉信息息时发生异常。");
@@ -260,7 +269,7 @@ public class ActionAppealCreate extends BaseAction {
 				attendanceNoticeService.notifyAttendanceAppealProcessness1Message(attendanceAppealInfo);
 			} catch (Exception e) {
 				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "申诉信息提交成功,向申诉当前处理人发送通知消息发生异常!name:"+attendanceAppealInfo.getProcessPerson1());
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "申诉信息提交成功,向申诉当前处理人发送通知消息发生异常!name:"+attendanceAppealAuditInfo.getProcessPerson1());
 				result.error(exception);
 				logger.error(e, effectivePerson, request, null);
 			}
@@ -274,9 +283,7 @@ public class ActionAppealCreate extends BaseAction {
 		
 		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
 
-		/**
-		 * 考勤人员身份:如果考勤人员属于多个组织,可以选择一个身份进行申诉信息绑定
-		 */
+		@FieldDescribe("申诉人的身份,考勤人员身份:如果考勤人员属于多个组织,可以选择一个身份进行申诉信息绑定.")
 		private String identity = null;
 
 		public String getIdentity() {

+ 118 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealCreateWithWorkFlow.java

@@ -0,0 +1,118 @@
+package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
+
+import com.google.gson.JsonElement;
+import com.x.attendance.assemble.control.ExceptionWrapInConvert;
+import com.x.attendance.entity.AppealConfig;
+import com.x.attendance.entity.AttendanceAppealAuditInfo;
+import com.x.attendance.entity.AttendanceAppealInfo;
+import com.x.attendance.entity.AttendanceDetail;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActionAppealCreateWithWorkFlow extends BaseAction {
+	
+	private static  Logger logger = LoggerFactory.getLogger( ActionAppealCreateWithWorkFlow.class );
+	
+	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id, JsonElement jsonElement ) throws Exception {
+		ActionResult<Wo> result = new ActionResult<>();
+		AttendanceAppealInfo attendanceAppealInfo = null;
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = null;
+		AttendanceDetail attendanceDetail = null;
+		Wi wrapIn = null;
+		Boolean check = true;
+
+		try {
+			wrapIn = this.convertToWrapIn(jsonElement, Wi.class);
+			if( StringUtils.isEmpty( wrapIn.getJobId() )){
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess("使用流程启动申诉时,工作流的jobId不允许为空");
+				result.error(exception);
+			}
+		} catch (Exception e) {
+			check = false;
+			Exception exception = new ExceptionWrapInConvert(e, jsonElement);
+			result.error(exception);
+			logger.error(e, effectivePerson, request, null);
+		}
+
+		if (check) {
+			try {
+				attendanceDetail = attendanceDetailServiceAdv.get( id );
+				if ( attendanceDetail == null ) {
+					check = false;
+					Exception exception = new ExceptionAttendanceDetailNotExists(id);
+					result.error( exception );
+				}
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据ID查询员工打卡信息时发生异常!ID:"+id);
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+
+		if (check) {
+			// 利用打卡记录中的信息,创建一个申诉信息记录
+			attendanceAppealInfo = attendanceSettingServiceAdv.composeAppealInfoWithDetailInfo( attendanceDetail, 
+					wrapIn.getReason(), wrapIn.getAppealReason(),  wrapIn.getSelfHolidayType(),  wrapIn.getAddress(), 
+					wrapIn.getStartTime(),  wrapIn.getEndTime(),  wrapIn.getAppealDescription() );
+			// 创建一个申诉审批记录信息
+			attendanceAppealAuditInfo = new AttendanceAppealAuditInfo();
+			attendanceAppealAuditInfo.setId( attendanceAppealInfo.getId());
+			attendanceAppealAuditInfo.setDetailId( attendanceDetail.getId() );
+			attendanceAppealAuditInfo.setAuditFlowType( AppealConfig.APPEAL_AUDIFLOWTYPE_WORKFLOW );
+			attendanceAppealAuditInfo.setWorkId( wrapIn.getJobId());
+		}
+
+		//保存申诉信息
+		if (check) {
+			try {
+				attendanceAppealInfo = attendanceAppealInfoServiceAdv.saveNewAppeal( attendanceAppealInfo, attendanceAppealAuditInfo );
+				result.setData(new Wo(attendanceAppealInfo.getId()));
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在保存考勤申诉信息息时发生异常。");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+		return result;
+	}
+	
+	public static class Wi extends AttendanceAppealInfo {
+		
+		private static final long serialVersionUID = -5076990764713538973L;
+		
+		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
+
+		@FieldDescribe("申诉人的身份,考勤人员身份:如果考勤人员属于多个组织,可以选择一个身份进行申诉信息绑定.")
+		private String identity = null;
+
+		@FieldDescribe("考勤流程的JOBID.")
+		private String jobId = null;
+
+		public String getJobId() { return jobId; }
+
+		public void setJobId(String jobId) { this.jobId = jobId; }
+
+		public String getIdentity() { return identity; }
+
+		public void setIdentity(String identity) { this.identity = identity; }
+	}
+	
+	public static class Wo extends WoId {
+		public Wo( String id ) {
+			setId( id );
+		}
+	}
+}

+ 0 - 112
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealProcessFirst.java

@@ -1,112 +0,0 @@
-package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import com.google.gson.JsonElement;
-import com.x.attendance.assemble.control.ExceptionWrapInConvert;
-import com.x.attendance.entity.AttendanceAppealInfo;
-import com.x.base.core.entity.JpaObject;
-import com.x.base.core.project.http.ActionResult;
-import com.x.base.core.project.http.EffectivePerson;
-import com.x.base.core.project.jaxrs.WoId;
-import com.x.base.core.project.logger.Logger;
-import com.x.base.core.project.logger.LoggerFactory;
-
-public class ActionAppealProcessFirst extends BaseAction {
-	
-	private static  Logger logger = LoggerFactory.getLogger( ActionAppealProcessFirst.class );
-	
-	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id, JsonElement jsonElement ) throws Exception {
-		ActionResult<Wo> result = new ActionResult<>();
-		String unitName = null;
-		String topUnitName = null;
-		AttendanceAppealInfo attendanceAppealInfo = null;
-		Wi wrapIn = null;
-		Boolean check = true;
-
-		try {
-			wrapIn = this.convertToWrapIn(jsonElement, Wi.class);
-		} catch (Exception e) {
-			check = false;
-			Exception exception = new ExceptionWrapInConvert(e, jsonElement);
-			result.error(exception);
-			logger.error(e, effectivePerson, request, null);
-		}
-
-		if (check) {
-			try {
-				attendanceAppealInfo = attendanceAppealInfoServiceAdv.get(id);
-				if (attendanceAppealInfo == null) {
-					check = false;
-					Exception exception = new ExceptionAttendanceAppealNotExists(id);
-					result.error(exception);
-				}
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据ID查询考勤申诉信息数据时发生异常。ID:"+ id);
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		if (check) {
-			try {
-				unitName = userManagerService.getUnitNameWithPersonName(effectivePerson.getDistinguishedName());
-				if (unitName != null) {
-					topUnitName = userManagerService.getTopUnitNameWithUnitName( unitName );
-				} else {
-					check = false;
-					Exception exception = new ExceptionPersonHasNoUnit(effectivePerson.getDistinguishedName());
-					result.error(exception);
-				}
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统根据员工姓名查询组织信息时发生异常!name:"+effectivePerson.getDistinguishedName());
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		if (check) {
-			try {
-				attendanceAppealInfo = attendanceAppealInfoServiceAdv.firstProcessAttendanceAppeal(id, unitName, topUnitName, effectivePerson.getDistinguishedName(), // processorName
-						new Date(), // processTime
-						wrapIn.getOpinion1(), // opinion
-						wrapIn.getStatus() // status审批状态:0-待处理,1-审批通过,-1-审批不能过,2-需要下一次审批
-				);
-				result.setData(new Wo(id));
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, id);
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		return result;
-	}
-	
-	public static class Wi extends AttendanceAppealInfo {
-		
-		private static final long serialVersionUID = -5076990764713538973L;
-		
-		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
-
-		private String identity = null;
-
-		public String getIdentity() {
-			return identity;
-		}
-
-		public void setIdentity(String identity) {
-			this.identity = identity;
-		}
-	}
-	
-	public static class Wo extends WoId {
-		public Wo( String id ) {
-			setId( id );
-		}
-	}
-}

+ 0 - 114
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAppealProcessSecond.java

@@ -1,114 +0,0 @@
-package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import com.google.gson.JsonElement;
-import com.x.attendance.assemble.control.ExceptionWrapInConvert;
-import com.x.attendance.entity.AttendanceAppealInfo;
-import com.x.base.core.entity.JpaObject;
-import com.x.base.core.project.http.ActionResult;
-import com.x.base.core.project.http.EffectivePerson;
-import com.x.base.core.project.jaxrs.WoId;
-import com.x.base.core.project.logger.Logger;
-import com.x.base.core.project.logger.LoggerFactory;
-
-public class ActionAppealProcessSecond extends BaseAction {
-	
-	private static Logger logger = LoggerFactory.getLogger( ActionAppealProcessSecond.class );
-	
-	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id, JsonElement jsonElement ) throws Exception {
-		ActionResult<Wo> result = new ActionResult<>();
-		String unitName = null;
-		String topUnitName = null;
-		AttendanceAppealInfo attendanceAppealInfo = null;
-		Wi wrapIn = null;
-		Boolean check = true;
-
-		try {
-			wrapIn = this.convertToWrapIn(jsonElement, Wi.class);
-		} catch (Exception e) {
-			check = false;
-			Exception exception = new ExceptionWrapInConvert(e, jsonElement);
-			result.error(exception);
-			logger.error(e, effectivePerson, request, null);
-		}
-
-		if (check) {
-			try {
-				attendanceAppealInfo = attendanceAppealInfoServiceAdv.get(id);
-				if (attendanceAppealInfo == null) {
-					check = false;
-					Exception exception = new ExceptionAttendanceAppealNotExists(id);
-					result.error(exception);
-				}
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据ID查询考勤申诉信息记录数据时发生异常。ID:"+ id);
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		if (check) {
-			try {
-				unitName = userManagerService.getUnitNameWithPersonName(effectivePerson.getDistinguishedName());
-				if (unitName != null) {
-					topUnitName = userManagerService.getTopUnitNameWithUnitName( unitName );
-				} else {
-					check = false;
-					Exception exception = new ExceptionPersonHasNoUnit(effectivePerson.getDistinguishedName());
-					result.error(exception);
-				}
-			} catch (Exception e) {
-				check = false;
-				result.error(e);
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统根据员工姓名查询组织信息时发生异常!name:"+effectivePerson.getDistinguishedName());
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		if (check) {
-			try {
-				attendanceAppealInfo = attendanceAppealInfoServiceAdv.secondProcessAttendanceAppeal(id, unitName, topUnitName, effectivePerson.getDistinguishedName(), // processorName
-						new Date(), // processTime
-						wrapIn.getOpinion2(), // opinion
-						wrapIn.getStatus() // status
-				);
-				result.setData(new Wo(id));
-			} catch (Exception e) {
-				check = false;
-				result.error(e);
-				Exception exception = new ExceptionAttendanceAppealProcess(e, id);
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		return result;
-	}
-	
-	public static class Wi extends AttendanceAppealInfo {
-		
-		private static final long serialVersionUID = -5076990764713538973L;
-		
-		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
-
-		private String identity = null;
-
-		public String getIdentity() {
-			return identity;
-		}
-
-		public void setIdentity(String identity) {
-			this.identity = identity;
-		}
-	}
-	
-	public static class Wo extends WoId {
-		public Wo( String id ) {
-			setId( id );
-		}
-	}
-}

+ 0 - 228
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAttendanceDetailAppeal.java

@@ -1,228 +0,0 @@
-package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import com.x.attendance.entity.AppealConfig;
-import org.apache.commons.lang3.StringUtils;
-
-import com.google.gson.JsonElement;
-import com.x.attendance.assemble.control.ExceptionWrapInConvert;
-import com.x.attendance.entity.AttendanceAppealInfo;
-import com.x.attendance.entity.AttendanceDetail;
-import com.x.base.core.entity.JpaObject;
-import com.x.base.core.project.http.ActionResult;
-import com.x.base.core.project.http.EffectivePerson;
-import com.x.base.core.project.jaxrs.WoId;
-import com.x.base.core.project.logger.Logger;
-import com.x.base.core.project.logger.LoggerFactory;
-
-public class ActionAttendanceDetailAppeal extends BaseAction {
-	
-	private static Logger logger = LoggerFactory.getLogger( ActionAttendanceDetailAppeal.class );
-	
-	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id, JsonElement jsonElement ) throws Exception {
-		ActionResult<Wo> result = new ActionResult<>();
-		AttendanceAppealInfo attendanceAppealInfo = null;
-		AttendanceDetail attendanceDetail = null;
-		String appealAuditPersonName = null;
-		String appealCheckPersonName = null;
-		String appeal_auditor_type = null;
-		String appeal_checker_type = null;
-		String personName = null;
-		Wi wrapIn = null;
-		Boolean check = true;
-
-		try {
-			wrapIn = this.convertToWrapIn(jsonElement, Wi.class);
-		} catch (Exception e) {
-			check = false;
-			Exception exception = new ExceptionWrapInConvert(e, jsonElement);
-			result.error(exception);
-			logger.error(e, effectivePerson, request, null);
-		}
-		if (check) {
-			try {
-				attendanceDetail = attendanceDetailServiceAdv.get( id );
-				if ( attendanceDetail == null ) {
-					check = false;
-					Exception exception = new ExceptionAttendanceDetailNotExists(id);
-					result.error(exception);
-				}else {
-					personName = attendanceDetail.getEmpName();
-				}
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据ID查询员工打卡信息时发生异常!ID:"+id);
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		if (check) {
-			// 利用打卡记录中的信息,创建一个申诉信息记录
-			attendanceAppealInfo = attendanceSettingServiceAdv.composeAppealInfoWithDetailInfo(attendanceDetail, 
-					wrapIn.getReason(), wrapIn.getAppealReason(),  wrapIn.getSelfHolidayType(),  wrapIn.getAddress(), 
-					wrapIn.getStartTime(),  wrapIn.getEndTime(),  wrapIn.getAppealDescription() );
-		}
-		if (check) {
-			try {
-				appeal_auditor_type = attendanceSettingServiceAdv.getValueByCode( "APPEAL_AUDITOR_TYPE" );
-				appeal_checker_type = attendanceSettingServiceAdv.getValueByCode( "APPEAL_CHECKER_TYPE" );
-			}catch( Exception e ) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess( e, "系统在获取申诉审核配置时发生异常!" );
-				result.error( exception);
-				logger.error( e, effectivePerson, request, null);
-			}
-		}
-		//查询申诉审核人
-		if (check) {
-			if( StringUtils.isNotEmpty( appeal_auditor_type ) ) {
-				try {
-					appealAuditPersonName = attendanceAppealInfoServiceAdv.getAppealAuditPerson( personName, attendanceAppealInfo.getUnitName(), wrapIn.getIdentity() );
-					attendanceAppealInfo.setProcessPerson1( appealAuditPersonName );
-					attendanceAppealInfo.setCurrentProcessor( appealAuditPersonName );// 将第一个处理人设置为当前处理人
-				}catch( Exception e ) {
-					check = false;
-					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据根据考勤人员查询申诉审核人信息时发生异常!personName:"+personName );
-					result.error(exception);
-					logger.warn( "系统在根据根据考勤人员查询申诉审核人信息时发生异常!personName:"+personName );
-					logger.error(e, effectivePerson, request, null);
-				}
-			}
-		}
-		//查询申诉复核人
-		if (check) {
-			if( StringUtils.isNotEmpty( appeal_checker_type ) ) {
-				try {
-					appealCheckPersonName = attendanceAppealInfoServiceAdv.getAppealCheckPerson( personName, attendanceAppealInfo.getUnitName(), wrapIn.getIdentity() );
-					attendanceAppealInfo.setProcessPerson2( appealCheckPersonName );
-				}catch( Exception e ) {
-					check = false;
-					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据根据考勤人员查询申诉复核人信息时发生异常!personName:"+personName );
-					result.error(exception);
-					logger.warn( "系统在根据根据考勤人员查询申诉复核人信息时发生异常!personName:"+personName );
-					logger.error(e, effectivePerson, request, null);
-				}
-			}
-		}
-		//查询申诉审核人所属组织
-		if (check) {
-			if( AppealConfig.APPEAL_AUDITTYPE_UNITDUTY.equalsIgnoreCase( appeal_auditor_type ) ) {
-				attendanceAppealInfo.setProcessPersonUnit1( attendanceAppealInfoServiceAdv.getPersonUnitName( appealAuditPersonName, attendanceDetail.getUnitName(), wrapIn.getIdentity() ) );
-			}else {
-				//汇报对象,指定人以及人员属性中指定的人员,根据人员姓名取首选组织(第一个)
-				if( appealAuditPersonName != null  && !appealAuditPersonName.isEmpty() ) {
-					try {//获取审核人组织信息
-						attendanceAppealInfo.setProcessPersonUnit1( userManagerService.getUnitNameWithPersonName( appealAuditPersonName ));
-					}catch( Exception e ) {
-						check = false;
-						Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据审核人获取组织信息时发生异常。");
-						result.error(exception);
-						logger.warn( "系统在根据审核人获取组织信息时发生异常!personName:"+appealAuditPersonName );
-						logger.error(e, effectivePerson, request, null);
-					}
-				}
-			}
-		}
-		//根据所属组织名称查询申诉审核人所属顶层组织
-		if (check) {
-			if( attendanceAppealInfo.getProcessPersonUnit1() != null  && !attendanceAppealInfo.getProcessPersonUnit1().isEmpty() ) {
-				try {
-					attendanceAppealInfo.setProcessPersonTopUnit1( userManagerService.getTopUnitNameWithUnitName( attendanceAppealInfo.getProcessPersonUnit1() ) );
-				}catch( Exception e ) {
-					check = false;
-					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据审核人获取顶层组织信息时发生异常。");
-					result.error(exception);
-					logger.warn( "系统在根据审核人获取顶层组织信息时发生异常!personName:"+appealAuditPersonName );
-					logger.error(e, effectivePerson, request, null);
-				}
-			}
-		}
-		//查询申诉复核人所属组织
-		if (check) {
-			if( AppealConfig.APPEAL_AUDITTYPE_UNITDUTY.equalsIgnoreCase( appeal_auditor_type ) ) {
-				attendanceAppealInfo.setProcessPersonUnit2( attendanceAppealInfoServiceAdv.getPersonUnitName( appealCheckPersonName, attendanceDetail.getUnitName(), wrapIn.getIdentity() ) );
-			}else {
-				//汇报对象,指定人以及人员属性中指定的人员,根据人员姓名取首选组织(第一个)
-				if( appealCheckPersonName != null  && !appealCheckPersonName.isEmpty() ) {
-					try {//获取复核人组织信息
-						attendanceAppealInfo.setProcessPersonUnit2( userManagerService.getUnitNameWithPersonName( appealCheckPersonName ));
-					}catch( Exception e ) {
-						check = false;
-						Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据复核人获取组织信息时发生异常。");
-						result.error(exception);
-						logger.warn( "系统在根据审核人获取组织信息时发生异常!personName:"+appealCheckPersonName );
-						logger.error(e, effectivePerson, request, null);
-					}
-				}
-			}
-		}
-		//根据所属组织名称查询申诉复核人所属顶层组织
-		if (check) {
-			if( attendanceAppealInfo.getProcessPersonUnit2() != null  && !attendanceAppealInfo.getProcessPersonUnit2().isEmpty() ) {
-				try {//获取复核人顶层组织信息
-					attendanceAppealInfo.setProcessPersonTopUnit2(  userManagerService.getTopUnitNameWithUnitName( attendanceAppealInfo.getProcessPersonUnit2()) );
-				}catch( Exception e ) {
-					check = false;
-					Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据复核人获取顶层组织信息时发生异常。");
-					result.error(exception);
-					logger.warn( "系统在根据审核人获取顶层组织信息时发生异常!personName:"+appealCheckPersonName );
-					logger.error(e, effectivePerson, request, null);
-				}
-			}
-		}
-		//保存申诉信息
-		if (check) {
-			try {
-				attendanceAppealInfo = attendanceAppealInfoServiceAdv.saveNewAppeal( attendanceAppealInfo );
-				result.setData(new Wo(id));
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在保存考勤申诉信息息时发生异常。");
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		if (check) {
-			// 填充申诉信息内容 - 申诉信息成功生成.尝试向当前处理人[" + attendanceAppealInfo.getCurrentProcessor() + "]发送消息通知......
-			try {
-				attendanceNoticeService.notifyAttendanceAppealProcessness1Message(attendanceAppealInfo);
-			} catch (Exception e) {
-				check = false;
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "申诉信息提交成功,向申诉当前处理人发送通知消息发生异常!name:"+attendanceAppealInfo.getProcessPerson1());
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		return result;
-	}
-	
-	public static class Wi extends AttendanceAppealInfo {
-		
-		private static final long serialVersionUID = -5076990764713538973L;
-		
-		public static List<String> Excludes = new ArrayList<String>(JpaObject.FieldsUnmodify);
-
-		/**
-		 * 考勤人员身份:如果考勤人员属于多个组织,可以选择一个身份进行申诉信息绑定
-		 */
-		private String identity = null;
-
-		public String getIdentity() {
-			return identity;
-		}
-
-		public void setIdentity(String identity) {
-			this.identity = identity;
-		}
-	}
-	
-	public static class Wo extends WoId {
-		public Wo( String id ) {
-			setId( id );
-		}
-	}
-}

+ 0 - 46
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionAttendanceDetailArchive.java

@@ -1,46 +0,0 @@
-package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.lang3.StringUtils;
-import com.x.base.core.project.http.ActionResult;
-import com.x.base.core.project.http.EffectivePerson;
-import com.x.base.core.project.jaxrs.WoId;
-import com.x.base.core.project.logger.Logger;
-import com.x.base.core.project.logger.LoggerFactory;
-
-public class ActionAttendanceDetailArchive extends BaseAction {
-	
-	private static  Logger logger = LoggerFactory.getLogger( ActionAttendanceDetailArchive.class );
-	
-	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id ) throws Exception {
-		ActionResult<Wo> result = new ActionResult<>();
-
-		if ( StringUtils.isNotEmpty( id )) { // 归档指定的考勤申诉记录
-			try {
-				attendanceAppealInfoServiceAdv.archive(id);
-				result.setData(new Wo(id));
-			} catch (Exception e) {
-				result.error(e);
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "归档考勤打卡申诉信息时发生异常。ID:" + id);
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		} else { // 归档所有的考勤申诉记录
-			try {
-				attendanceAppealInfoServiceAdv.archiveAll();
-			} catch (Exception e) {
-				Exception exception = new ExceptionAttendanceAppealProcess(e, "归档全部考勤申诉信息数据时发生异常");
-				result.error(exception);
-				logger.error(e, effectivePerson, request, null);
-			}
-		}
-		return result;
-	}
-	
-	public static class Wo extends WoId {
-		public Wo( String id ) {
-			setId( id );
-		}
-	}
-}

+ 146 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ActionWorkFlowSync.java

@@ -0,0 +1,146 @@
+package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
+
+import com.google.gson.JsonElement;
+import com.x.attendance.assemble.control.ExceptionWrapInConvert;
+import com.x.attendance.assemble.control.service.WorkFlowSyncService;
+import com.x.attendance.entity.AttendanceAppealAuditInfo;
+import com.x.attendance.entity.AttendanceAppealInfo;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+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.List;
+
+public class ActionWorkFlowSync extends BaseAction {
+	
+	private static  Logger logger = LoggerFactory.getLogger( ActionWorkFlowSync.class );
+	
+	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String id, JsonElement jsonElement ) throws Exception {
+		ActionResult<Wo> result = new ActionResult<>();
+		AttendanceAppealInfo attendanceAppealInfo = null;
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = null;
+		WorkFlowSyncService.WoWorkComplex woWorkComplex = null;
+		ActionAppealCreate.Wi wrapIn = null;
+		Boolean check = true;
+
+		if (check) {
+			if ( StringUtils.isNotEmpty( id )) {
+				check = false;
+				result.error(new Exception("传入的workId为空,或者不合法,无法同步流程数据。"));
+			}
+		}
+
+		if (check) {
+			try {
+				wrapIn = this.convertToWrapIn(jsonElement, ActionAppealCreate.Wi.class);
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionWrapInConvert(e, jsonElement);
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+
+		if (check) {
+			if( wrapIn.getStatus() != 0 & wrapIn.getStatus() != 1 &wrapIn.getStatus() != -1 &wrapIn.getStatus() != 9 ){
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess( "传入的申诉状态不合法。status:" + wrapIn.getStatus());
+				result.error(exception);
+			}
+		}
+
+		if (check) {
+			try {
+				attendanceAppealInfo = attendanceAppealInfoServiceAdv.get(id);
+				if( attendanceAppealInfo == null ){
+					check = false;
+					Exception exception = new ExceptionAttendanceAppealNotExists( id );
+					result.error(exception);
+				}
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据ID查询考勤申诉记录数据时发生异常。ID:" + id);
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+
+		if (check) {
+			try {
+				attendanceAppealAuditInfo = attendanceAppealInfoServiceAdv.getAppealAuditInfo(id);
+				if( attendanceAppealAuditInfo == null ){
+					check = false;
+					Exception exception = new ExceptionAppealAuditInfoNotExists( id );
+					result.error(exception);
+				}
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在根据ID查询考勤申诉审批记录数据时发生异常。ID:" + id);
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+
+		if (check) {
+			try {
+				woWorkComplex = WorkFlowSyncService.getWorkComplex( attendanceAppealAuditInfo.getWorkId() );
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在获取考勤打卡申诉流程信息时发生异常。ID:" + attendanceAppealAuditInfo.getWorkId() );
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+
+		if (check) {
+			try {
+				String processorName = null;
+				String activityType = null;
+
+				if(ListTools.isEmpty( woWorkComplex.getTaskList() )){
+					processorName = null;
+				}else{
+					processorName = woWorkComplex.getTaskList().get(0).getIdentity();
+				}
+				activityType = woWorkComplex.getActivity().getActivityType().name();
+
+				attendanceAppealInfoServiceAdv.syncAppealStatus( attendanceAppealInfo, activityType, processorName, wrapIn.getStatus() );
+
+				result.setData(new Wo(id));
+			} catch (Exception e) {
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "系统在同步考勤打卡申诉流程信息时发生异常。ID:" + id);
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+		return result;
+	}
+
+	public static class Wi {
+
+		@FieldDescribe("申诉状态:0-未申诉,1-申诉中,-1-申诉未通过,9-申诉通过.")
+		private Integer status = null;
+
+		public Integer getStatus() {
+			return status;
+		}
+
+		public void setStatus(Integer status) {
+			this.status = status;
+		}
+	}
+
+	public static class Wo extends WoId {
+		public Wo( String id ) {
+			setId( id );
+		}
+	}
+}

+ 56 - 4
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/AttendanceAppealInfoAction.java

@@ -83,13 +83,12 @@ public class AttendanceAppealInfoAction extends StandardJaxrsAction {
 
 	/**
 	 * 对某条打卡记录进行申诉
-	 * 
+	 * @param asyncResponse
 	 * @param request
 	 * @param id
-	 * @param wrapIn
-	 * @return
+	 * @param jsonElement
 	 */
-	@JaxrsMethodDescribe(value = "根据ID对考勤结果申诉信息提起申诉", action = ActionAppealCreate.class)
+	@JaxrsMethodDescribe(value = "根据ID对考勤结果申诉信息提起申诉", action = ActionAppealCreate.class )
 	@PUT
 	@Path("appeal/{id}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@@ -112,6 +111,36 @@ public class AttendanceAppealInfoAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
+	/**
+	 * 对某条打卡记录进行申诉
+	 * @param asyncResponse
+	 * @param request
+	 * @param id
+	 * @param jsonElement
+	 */
+	@JaxrsMethodDescribe(value = "根据ID对考勤结果申诉信息提起申诉", action = ActionAppealCreateWithWorkFlow.class )
+	@PUT
+	@Path("workflow/appeal/{id}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void createWithWorkFlow(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+					   @JaxrsParameterDescribe("考勤申诉信息ID") @PathParam("id") String id, JsonElement jsonElement) {
+		ActionResult<ActionAppealCreateWithWorkFlow.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		Boolean check = true;
+		if (check) {
+			try {
+				result = new ActionAppealCreateWithWorkFlow().execute(request, effectivePerson, id, jsonElement);
+			} catch (Exception e) {
+				result = new ActionResult<>();
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "根据ID对打卡结果进行申诉时发生异常!");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 	@JaxrsMethodDescribe(value = "根据ID列表对考勤申诉信息进行审核操作, 参数:ids(申诉ID列表),opinion(审核意见), status(审核状态:1-通过;2-需要进行复核;-1-不通过)", action = ActionAppealAudit.class)
 	@PUT
 	@Path("audit")
@@ -228,4 +257,27 @@ public class AttendanceAppealInfoAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
+
+	@JaxrsMethodDescribe(value = "根据考勤申诉ID,更新流程的审批信息", action = ActionWorkFlowSync.class)
+	@GET
+	@Path("workflow/sync/{id}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void archive(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+						@JaxrsParameterDescribe("考勤申诉信息ID") @PathParam("id") String id, JsonElement jsonElement) {
+		ActionResult<ActionWorkFlowSync.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		Boolean check = true;
+		if (check) {
+			try {
+				result = new ActionWorkFlowSync().execute(request, effectivePerson, id, jsonElement);
+			} catch (Exception e) {
+				result = new ActionResult<>();
+				Exception exception = new ExceptionAttendanceAppealProcess(e, "根据ID对打卡结果进行归档时发生异常!");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
 }

+ 12 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attendanceappealinfo/ExceptionAppealAuditInfoNotExists.java

@@ -0,0 +1,12 @@
+package com.x.attendance.assemble.control.jaxrs.attendanceappealinfo;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionAppealAuditInfoNotExists extends PromptException {
+
+	private static final long serialVersionUID = 1859164370743532895L;
+
+	public ExceptionAppealAuditInfoNotExists(String id ) {
+		super("员工打卡申诉审批信息不存在!ID:" + id );
+	}
+}

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

@@ -123,7 +123,7 @@ public class ActionReciveAttendanceMobile extends BaseAction {
 		
 		if( check ){
 			//对该员工的所有移动考勤数据进行一个整合
-			attendanceDetailServiceAdv.pushToDetail( currentPerson.getDistinguishedName(), attendanceDetailMobile.getRecordDateString() );
+			attendanceDetailServiceAdv.pushToDetail( currentPerson.getDistinguishedName(), attendanceDetailMobile.getRecordDateString(), effectivePerson.getDebugger() );
 
 		}
 		return result;

+ 55 - 15
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceAppealInfoService.java

@@ -3,12 +3,13 @@ package com.x.attendance.assemble.control.service;
 import java.util.Date;
 import java.util.List;
 
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceAppealAuditInfo;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.attendance.assemble.control.Business;
 import com.x.attendance.entity.AttendanceAppealInfo;
 import com.x.attendance.entity.AttendanceDetail;
-import com.x.attendance.entity.DateOperation;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.entity.annotation.CheckPersistType;
@@ -43,22 +44,37 @@ public class AttendanceAppealInfoService {
 		}
 	}
 
-	public AttendanceAppealInfo save( EntityManagerContainer emc, AttendanceAppealInfo attendanceAppealInfo ) throws Exception {
+	public AttendanceAppealInfo save( EntityManagerContainer emc, AttendanceAppealInfo attendanceAppealInfo, AttendanceAppealAuditInfo attendanceAppealAuditInfo ) throws Exception {
 		AttendanceDetail attendanceDetail = null;
 		AttendanceAppealInfo attendanceAppealInfo_temp = null;
-		emc.beginTransaction(AttendanceAppealInfo.class);
-		emc.beginTransaction(AttendanceDetail.class);
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo_temp = null;
+
 		attendanceAppealInfo_temp = emc.find( attendanceAppealInfo.getId(), AttendanceAppealInfo.class);
+		attendanceAppealAuditInfo_temp = emc.find( attendanceAppealInfo.getId(), AttendanceAppealAuditInfo.class);
 		attendanceDetail = emc.find( attendanceAppealInfo.getDetailId(), AttendanceDetail.class);
+
 		if( attendanceDetail == null ){
 			throw new Exception("attendance detail info not exists.");
 		}else{
+			emc.beginTransaction( AttendanceDetail.class );
+			emc.beginTransaction( AttendanceAppealInfo.class );
+			emc.beginTransaction( AttendanceAppealAuditInfo.class );
+
 			if ( attendanceAppealInfo_temp != null ) {
 				attendanceAppealInfo.copyTo( attendanceAppealInfo_temp, JpaObject.FieldsUnmodify );
 				emc.check( attendanceAppealInfo_temp, CheckPersistType.all );				
 			}else{
 				emc.persist( attendanceAppealInfo, CheckPersistType.all);
 			}
+
+			if ( attendanceAppealAuditInfo_temp != null ) {
+				attendanceAppealAuditInfo.copyTo( attendanceAppealAuditInfo_temp, JpaObject.FieldsUnmodify );
+				attendanceAppealAuditInfo.setId(attendanceAppealInfo.getId());
+				emc.check( attendanceAppealAuditInfo_temp, CheckPersistType.all );
+			}else{
+				emc.persist( attendanceAppealAuditInfo, CheckPersistType.all);
+			}
+
 			//将打卡记录表里的打卡数据置为正在申诉中
 			attendanceDetail.setAppealStatus(1);
 			attendanceDetail.setAppealProcessor( attendanceAppealInfo.getCurrentProcessor() );
@@ -72,21 +88,34 @@ public class AttendanceAppealInfoService {
 
 	public AttendanceAppealInfo updateAppealProcessInfoForFirstProcess(EntityManagerContainer emc, String id, String unitName,
 			String topUnitName, String processor, Date processTime, String opinion, Integer status, Boolean autoCommit ) throws Exception {
+
 		AttendanceAppealInfo attendanceAppealInfo = emc.find(id, AttendanceAppealInfo.class);
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = emc.find(id, AttendanceAppealAuditInfo.class);
 		if( attendanceAppealInfo == null ){
 			throw new Exception( "attendanceAppealInfo{'id':'"+ id +"'} not exists." );
 		}
 		if( autoCommit ){
 			emc.beginTransaction(AttendanceAppealInfo.class);
+			emc.beginTransaction(AttendanceAppealAuditInfo.class);
 		}
-		attendanceAppealInfo.setProcessPersonUnit1( unitName );
-		attendanceAppealInfo.setProcessPersonTopUnit1(topUnitName);
-		attendanceAppealInfo.setProcessPerson1( processor );
-		attendanceAppealInfo.setProcessTime1(new Date());
-		attendanceAppealInfo.setOpinion1( opinion );
+		if( attendanceAppealAuditInfo == null ){
+			attendanceAppealAuditInfo = new AttendanceAppealAuditInfo();
+			attendanceAppealAuditInfo.setId( attendanceAppealInfo.getId() );
+			emc.persist( attendanceAppealAuditInfo, CheckPersistType.all );
+		}
+		attendanceAppealAuditInfo.setProcessPersonUnit1( unitName );
+		attendanceAppealAuditInfo.setProcessPersonTopUnit1(topUnitName);
+		attendanceAppealAuditInfo.setProcessPerson1( processor );
+		if( processTime == null ){
+			attendanceAppealAuditInfo.setProcessTime1( new Date() );
+		}else{
+			attendanceAppealAuditInfo.setProcessTime1( processTime );
+		}
+		attendanceAppealAuditInfo.setOpinion1( opinion );
 		attendanceAppealInfo.setStatus( status );
 		emc.check(attendanceAppealInfo, CheckPersistType.all);
-		
+		emc.check(attendanceAppealAuditInfo, CheckPersistType.all);
+
 		if( autoCommit ){
 			emc.commit();
 		}
@@ -97,17 +126,28 @@ public class AttendanceAppealInfoService {
 			String unitName, String topUnitName, String processor, Date processTime, String opinion,
 			Integer status, Boolean autoCommit ) throws Exception {
 		AttendanceAppealInfo attendanceAppealInfo = emc.find(id, AttendanceAppealInfo.class);
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = emc.find(id, AttendanceAppealAuditInfo.class);
 		if( attendanceAppealInfo == null ){
 			throw new Exception( "attendanceAppealInfo{'id':'"+ id +"'} not exists." );
 		}
 		if( autoCommit ){
 			emc.beginTransaction(AttendanceAppealInfo.class);
+			emc.beginTransaction(AttendanceAppealAuditInfo.class);
+		}
+		if( attendanceAppealAuditInfo == null ){
+			attendanceAppealAuditInfo = new AttendanceAppealAuditInfo();
+			attendanceAppealAuditInfo.setId( attendanceAppealInfo.getId() );
+			emc.persist( attendanceAppealAuditInfo, CheckPersistType.all );
+		}
+		attendanceAppealAuditInfo.setProcessPersonUnit2( unitName );
+		attendanceAppealAuditInfo.setProcessPersonTopUnit2(topUnitName);
+		attendanceAppealAuditInfo.setProcessPerson2( processor );
+		if( processTime == null ){
+			attendanceAppealAuditInfo.setProcessTime2( new Date() );
+		}else{
+			attendanceAppealAuditInfo.setProcessTime2(processTime);
 		}
-		attendanceAppealInfo.setProcessPersonUnit2( unitName );
-		attendanceAppealInfo.setProcessPersonTopUnit2(topUnitName);
-		attendanceAppealInfo.setProcessPerson2( processor );
-		attendanceAppealInfo.setProcessTime2(new Date());
-		attendanceAppealInfo.setOpinion2( opinion );
+		attendanceAppealAuditInfo.setOpinion2( opinion );
 		attendanceAppealInfo.setStatus( status );
 		emc.check(attendanceAppealInfo, CheckPersistType.all);
 		

+ 71 - 9
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/service/AttendanceAppealInfoServiceAdv.java

@@ -2,10 +2,7 @@ package com.x.attendance.assemble.control.service;
 
 import com.x.attendance.assemble.common.date.DateOperation;
 import com.x.attendance.assemble.control.Business;
-import com.x.attendance.entity.AppealConfig;
-import com.x.attendance.entity.AttendanceAppealInfo;
-import com.x.attendance.entity.AttendanceDetail;
-import com.x.attendance.entity.AttendanceSetting;
+import com.x.attendance.entity.*;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.annotation.CheckPersistType;
@@ -47,9 +44,9 @@ public class AttendanceAppealInfoServiceAdv {
 		}
 	}
 
-	public AttendanceAppealInfo saveNewAppeal( AttendanceAppealInfo attendanceAppealInfo ) throws Exception {
+	public AttendanceAppealInfo saveNewAppeal( AttendanceAppealInfo attendanceAppealInfo, AttendanceAppealAuditInfo attendanceAppealAuditInfo ) throws Exception {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-			return attendanceAppealInfoService.save( emc, attendanceAppealInfo );	
+			return attendanceAppealInfoService.save( emc, attendanceAppealInfo, attendanceAppealAuditInfo );
 		} catch ( Exception e ) {
 			throw e;
 		}
@@ -233,23 +230,28 @@ public class AttendanceAppealInfoServiceAdv {
 	 * @throws Exception
 	 */
 	public AttendanceAppealInfo firstProcessAttendanceAppeal( String id, String unitName, String topUnitName, String processor, Date processTime, String opinion, Integer status ) throws Exception {
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = null;
 		AttendanceAppealInfo attendanceAppealInfo = null;
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			//修改申诉信息状态和处理过程信息
+			emc.beginTransaction( AttendanceAppealAuditInfo.class );
 			emc.beginTransaction( AttendanceAppealInfo.class );
 			emc.beginTransaction( AttendanceDetail.class );
 			attendanceAppealInfo = attendanceAppealInfoService.updateAppealProcessInfoForFirstProcess( emc, id, unitName, topUnitName, processor, processTime, opinion, status, false );
 			if( attendanceAppealInfo != null ){
+				attendanceAppealAuditInfo = emc.find( id, AttendanceAppealAuditInfo.class );
 				if ( status == 1 ) {
 					attendanceAppealInfo.setCurrentProcessor( null );
 					attendanceDetailService.updateAppealProcessStatus( emc, id, 9, false );
 					attendanceNoticeService.notifyAttendanceAppealAcceptMessage( attendanceAppealInfo, attendanceAppealInfo.getEmpName() );
 				} else if ( status == 2 ) {// 如果需要继续第二级审批
 					//判断是否存在用户的复核人信息
-					if( attendanceAppealInfo.getProcessPerson2() == null || attendanceAppealInfo.getProcessPerson2().isEmpty() ) {
+					if( attendanceAppealAuditInfo.getProcessPerson2() == null || attendanceAppealAuditInfo.getProcessPerson2().isEmpty() ) {
 						attendanceDetailService.updateAppealProcessStatus( emc, id, 1, false );
-						attendanceAppealInfo.setCurrentProcessor( attendanceAppealInfo.getProcessPerson2() );
+						attendanceAppealAuditInfo.setCurrentProcessor( attendanceAppealAuditInfo.getProcessPerson2() );
+						attendanceAppealInfo.setCurrentProcessor( attendanceAppealAuditInfo.getProcessPerson2() );
 						emc.check( attendanceAppealInfo, CheckPersistType.all );
+						emc.check( attendanceAppealAuditInfo, CheckPersistType.all );
 						attendanceNoticeService.notifyAttendanceAppealProcessness2Message( attendanceAppealInfo );
 					}
 				} else {// 如果审批不通过
@@ -265,15 +267,30 @@ public class AttendanceAppealInfoServiceAdv {
 		return attendanceAppealInfo;
 	}
 
+	/**
+	 *
+	 * @param id
+	 * @param unitName
+	 * @param topUnitName
+	 * @param processor
+	 * @param processTime
+	 * @param opinion
+	 * @param status //申诉状态:0-未申诉,1-申诉中,-1-申诉未通过,9-申诉通过
+	 * @return
+	 * @throws Exception
+	 */
 	public AttendanceAppealInfo secondProcessAttendanceAppeal( String id, String unitName, String topUnitName,
 			String processor, Date processTime, String opinion, Integer status ) throws Exception {
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = null;
 		AttendanceAppealInfo attendanceAppealInfo = null;
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			//修改申诉信息状态和处理过程信息
+			emc.beginTransaction( AttendanceAppealAuditInfo.class );
 			emc.beginTransaction( AttendanceAppealInfo.class );
 			emc.beginTransaction( AttendanceDetail.class );
 			attendanceAppealInfo = attendanceAppealInfoService.updateAppealProcessInfoForSecondProcess( emc, id, unitName, topUnitName, processor, processTime, opinion, status, false );
 			if( attendanceAppealInfo != null ){
+				attendanceAppealAuditInfo = emc.find( id, AttendanceAppealAuditInfo.class );
 				if ( status == 1 ) {
 					attendanceDetailService.updateAppealProcessStatus( emc, id, 9, false );
 					attendanceNoticeService.notifyAttendanceAppealAcceptMessage( attendanceAppealInfo, attendanceAppealInfo.getEmpName() );
@@ -282,6 +299,7 @@ public class AttendanceAppealInfoServiceAdv {
 					attendanceNoticeService.notifyAttendanceAppealRejectMessage( attendanceAppealInfo, attendanceAppealInfo.getEmpName());
 				}
 				attendanceAppealInfo.setCurrentProcessor( null );
+				attendanceAppealAuditInfo.setCurrentProcessor( null );
 			}
 			emc.commit();
 		} catch ( Exception e ) {
@@ -347,5 +365,49 @@ public class AttendanceAppealInfoServiceAdv {
 		}
 	}
 
-	
+
+	public AttendanceAppealAuditInfo getAppealAuditInfo(String id) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			emc.find( id, AttendanceAppealAuditInfo.class );
+		} catch ( Exception e ) {
+			throw e;
+		}
+		return null;
+	}
+
+
+	/**
+	 * 申诉状态:0-未申诉,1-申诉中,-1-申诉未通过,9-申诉通过
+	 * @param attendanceAppealInfo
+	 * @param activityType
+	 * @param currentProcessor
+	 * @param status
+	 * @throws Exception
+	 */
+	public void syncAppealStatus( AttendanceAppealInfo attendanceAppealInfo, String activityType, String currentProcessor, Integer status ) throws Exception {
+
+		AttendanceAppealAuditInfo attendanceAppealAuditInfo = null;
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			attendanceAppealInfo = emc.find( attendanceAppealInfo.getId(), AttendanceAppealInfo.class );
+			attendanceAppealAuditInfo = emc.find( attendanceAppealInfo.getId(), AttendanceAppealAuditInfo.class );
+
+			emc.beginTransaction( AttendanceAppealInfo.class );
+			emc.beginTransaction( AttendanceAppealAuditInfo.class );
+
+			attendanceAppealInfo.setStatus(status);
+			if( StringUtils.equalsAnyIgnoreCase( "end", activityType )){//审核结束了
+				attendanceAppealInfo.setCurrentProcessor( null );
+				attendanceAppealAuditInfo.setCurrentProcessor( null );
+			}else{
+				attendanceAppealInfo.setCurrentProcessor( currentProcessor );
+				attendanceAppealAuditInfo.setCurrentProcessor( currentProcessor );
+			}
+			emc.commit();
+		} catch ( Exception e ) {
+			throw e;
+		}
+
+
+
+	}
 }

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

@@ -0,0 +1,302 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.assemble.control.Business;
+import com.x.attendance.assemble.control.factory.AttendanceStatisticRequireLogFactory;
+import com.x.attendance.assemble.control.jaxrs.attendancedetail.AttendanceCycles;
+import com.x.attendance.entity.*;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.annotation.CheckPersistType;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.*;
+
+/**
+ * 考勤打卡记录分析服务类
+ * @author LIYI
+ *
+ */
+class AttendanceDetailAnalyseCoreService {
+	
+	private static  Logger logger = LoggerFactory.getLogger( AttendanceDetailAnalyseCoreService.class );
+	private AttendanceSelfHolidayService attendanceSelfHolidayService = new AttendanceSelfHolidayService();
+	private AttendanceScheduleSettingService attendanceScheduleSettingService = new AttendanceScheduleSettingService();
+	private AttendanceStatisticalCycleService attendanceStatisticalCycleService = new AttendanceStatisticalCycleService();
+	private static DateOperation dateOperation = new DateOperation();
+	private UserManagerService userManagerService = new UserManagerService();
+
+	/**
+	 * 打卡记录分析核心方法,分析一条打卡记录信息<br/>
+		<b>迟到</b>:晚于最迟“迟到起算时间”,(当天为非周末非节假日正常上班日,并且未请假,或者当天是调休的工作日)<br/>
+		<b>早退</b>:下班打卡时间早于“迟到起算时间”,并且工作当日时间不满9个小时,(当天为非周末非节假日正常上班日,并且未请假,或者当天是调休的工作日)<br/>
+		<b>异常</b>:缺少签到退中的1条打卡数据 或者 上下班打卡时间都在最迟起算时间内,不满9个小时,(当天为非周末非节假日正常上班日,并且未请假,或者当天是调休的工作日)<br/>
+		<b>缺勤</b>:当天没有打卡数据,并且当天是工作日(当天为非周末非节假日正常上班日,并且未请假,或者当天是调休的工作日)
+	 * @param detail
+	 * @param scheduleSetting
+	 * @throws Exception 
+	 */
+	AttendanceDetail analyseCore( AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger ) throws Exception {
+		if( dateOperation == null ){
+			dateOperation = new DateOperation();
+		}
+		if( detail == null ){
+			throw new Exception("detail is null!" );
+		}
+		if( scheduleSetting == null ){
+			throw new Exception("scheduleSetting is null, empName:" + detail.getEmpName() );
+		}
+		//根据考勤打卡规则来判断启用何种规则来进行考勤结果分析
+		if ( 1 == scheduleSetting.getSignProxy() ){
+			//1、一天只打上下班两次卡
+			detail = new AttendanceDetailAnalyseSignProxy1().analyse(detail, scheduleSetting, debugger);
+		}else if( 2 == scheduleSetting.getSignProxy() ){
+			//2、一天三次打卡:打上班,下班两次卡外,中午休息时间也需要打一次卡,以确保员工在公司活动
+			detail = new AttendanceDetailAnalyseSignProxy2().analyse(detail, scheduleSetting, debugger);
+		}else if( 3 == scheduleSetting.getSignProxy() ){
+			//3、一天四次打卡:打上午上班,上午下班,下午上班,下午下班四次卡
+			detail = new AttendanceDetailAnalyseSignProxy3().analyse(detail, scheduleSetting, debugger);
+		}
+		return detail;
+	}
+
+	static Date getAfternoonOndutyTimeFromDetail(AttendanceDetail detail, Boolean debugger) {
+		if( StringUtils.isNotEmpty( detail.getMorningOffdutyTime()) ){
+			try {
+				logger.debug( debugger, "格式化[下午上班签到时间]afternoonOndutyTime=" +  detail.getRecordDateString() + " " + detail.getAfternoonOnDutyTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + detail.getAfternoonOnDutyTime() );
+			} catch (Exception e) {
+				detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,afternoonOndutyTime=" + detail.getRecordDateString() + " " + detail.getAfternoonOnDutyTime() );
+				logger.warn( "系统进行时间转换时发生异常,afternoonOndutyTime=" + detail.getRecordDateString() + " " + detail.getAfternoonOnDutyTime() );
+				logger.error(e);
+			}
+		}else{
+			logger.debug( debugger, ">>>>>>>>>>上午下班签退时间为空!");
+		}
+		return null;
+	}
+
+	static Date getMorningOffdutyTimeFromDetail(AttendanceDetail detail, Boolean debugger) {
+		if( StringUtils.isNotEmpty( detail.getMorningOffdutyTime()) ){
+			try {
+				logger.debug( debugger, "格式化[上午下班签退时间]morningOffdutyTime=" +  detail.getRecordDateString() + " " + detail.getMorningOffdutyTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + detail.getMorningOffdutyTime() );
+			} catch (Exception e) {
+				detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,morningOffdutyTime=" + detail.getRecordDateString() + " " + detail.getMorningOffdutyTime() );
+				logger.warn( "系统进行时间转换时发生异常,morningOffdutyTime=" + detail.getRecordDateString() + " " + detail.getMorningOffdutyTime() );
+				logger.error(e);
+			}
+		}else{
+			logger.debug( debugger, ">>>>>>>>>>上午下班签退时间为空!");
+		}
+		return null;
+	}
+
+	static Date getAbsenceStartTimeFromDetail(AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		if( StringUtils.isNotEmpty( scheduleSetting.getAbsenceStartTime() ) ){
+			try {
+				logger.debug( debugger, ">>>>>>>>>>格式化[缺勤起算时间]absenceStartTime=" +  detail.getRecordDateString() + " " + scheduleSetting.getAbsenceStartTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + scheduleSetting.getAbsenceStartTime() );
+			} catch (Exception e) {
+				detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,absenceStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getAbsenceStartTime() );
+				logger.warn( "系统进行时间转换时发生异常,absenceStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getAbsenceStartTime() );
+				logger.error(e);
+			}
+		}else{
+			logger.debug( debugger, ">>>>>>>>>>上午缺勤时间设置为空!系统将不判上午缺勤情况");
+		}
+		return null;
+	}
+
+	static Date getLeaveEarlyStartTimeFromDetail(AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		if( StringUtils.isNotEmpty( scheduleSetting.getLeaveEarlyStartTime() ) ){
+			try {
+				logger.debug( debugger, ">>>>>>>>>>格式化[早退起算时间]leaveEarlyStartTime=" +  detail.getRecordDateString() + " " + scheduleSetting.getLeaveEarlyStartTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + scheduleSetting.getLeaveEarlyStartTime() );
+			} catch (Exception e) {
+				detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,leaveEarlyStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getLeaveEarlyStartTime() );
+				logger.warn( "系统进行时间转换时发生异常,leaveEarlyStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getLeaveEarlyStartTime() );
+				logger.error(e);
+			}
+		}else{
+			logger.debug( debugger, ">>>>>>>>>>早退时间设置为空!系统将不判断早退情况");
+		}
+		return null;
+	}
+
+	static Date getLateStartTimeFromDetail(AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		if( StringUtils.isNotEmpty( scheduleSetting.getLateStartTime() ) ){
+			try {
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + scheduleSetting.getLateStartTime() );
+			} catch (Exception e) {
+				detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,lateStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getLateStartTime() );
+				logger.warn( "系统进行时间转换时发生异常,lateStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getLateStartTime());
+				logger.error(e);
+			}
+		}else{
+			logger.debug( debugger, ">>>>>>>>>>迟到时间设置为空!系统将不判断迟到情况");
+		}
+		return null;
+	}
+
+
+	/**
+	 * 根据已经完善过的考勤打卡记录,获取当天的上午下班(中午休息开始)打卡时间
+	 * @param detail
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 */
+	static Date getMiddleRestStartTimeFromDetail(AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		try {
+			if( StringUtils.isEmpty( detail.getOnDutyTime() ) ){
+				logger.debug( debugger, "middleRestEndTime " );
+			}else{
+				logger.debug(debugger, "middleRestStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getMiddayRestStartTime());
+				return dateOperation.getDateFromString(detail.getRecordDateString() + " " + detail.getMiddayRestStartTime());
+			}
+		} catch (Exception e) {
+			detail.setDescription(detail.getDescription() + "; 系统进行时间转换时发生异常,middleRestStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getMiddayRestStartTime() + " - " + scheduleSetting.getMiddayRestEndTime());
+			logger.debug(debugger, "系统进行时间转换时发生异常,middleRestStartTime=" + detail.getRecordDateString() + " " + scheduleSetting.getMiddayRestStartTime() + " - " + scheduleSetting.getMiddayRestEndTime());
+			logger.error(e);
+		}
+		return null;
+	}
+
+	/**
+	 * 根据已经完善过的考勤打卡记录,获取当天的下午上班(中午休息结束)打卡时间
+	 * @param detail
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 */
+	static Date getMiddleRestEndTimeFromDetail(AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		try {
+			if( StringUtils.isEmpty( detail.getOnDutyTime() ) ){
+				logger.debug( debugger, "middleRestEndTime " );
+			}else{
+				logger.debug(debugger, "middleRestEndTime=" + detail.getRecordDateString() + " " + scheduleSetting.getMiddayRestEndTime());
+				return dateOperation.getDateFromString(detail.getRecordDateString() + " " + detail.getMiddayRestEndTime());
+			}
+		} catch (Exception e) {
+			detail.setDescription(detail.getDescription() + "; 系统进行时间转换时发生异常,middleRestEndTime=" + detail.getRecordDateString() + " " + scheduleSetting.getMiddayRestStartTime() + " - " + scheduleSetting.getMiddayRestEndTime());
+			logger.debug(debugger, "系统进行时间转换时发生异常,middleRestEndTime=" + detail.getRecordDateString() + " " + scheduleSetting.getMiddayRestStartTime() + " - " + scheduleSetting.getMiddayRestEndTime());
+			logger.error(e);
+		}
+		return null;
+	}
+
+	/**
+	 * 根据已经完善过的考勤打卡记录,获取当天的上班打卡时间
+	 * @param detail
+	 * @param debugger
+	 * @return
+	 */
+	static Date getOnWorkTimeFromDetail(AttendanceDetail detail, Boolean debugger) {
+		try {
+			if( StringUtils.isEmpty( detail.getOnDutyTime() ) ){
+				logger.debug( debugger, "onWorkTime " );
+			}else{
+				logger.debug( debugger, "onWorkTime=" +  detail.getRecordDateString() + " " + detail.getOnWorkTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + detail.getOnWorkTime() );
+			}
+		} catch (Exception e) {
+			detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,onWorkTime=" + detail.getRecordDateString() + " " + detail.getOnWorkTime() );
+			logger.debug( debugger, "系统进行时间转换时发生异常,onWorkTime=" + detail.getRecordDateString() + " " + detail.getOnWorkTime());
+			logger.error(e);
+		}
+		return null;
+	}
+
+	/**
+	 * 根据已经完善过的考勤打卡记录,获取当天的上班打卡时间
+	 * @param detail
+	 * @param debugger
+	 * @return
+	 */
+	static Date getOffWorkTimeFromDetail(AttendanceDetail detail, Boolean debugger) {
+		try {
+			if( StringUtils.isEmpty( detail.getOnDutyTime() ) ){
+				logger.debug( debugger, "offWorkTime为空 " );
+			}else{
+				logger.debug( debugger, "offWorkTime=" +  detail.getRecordDateString() + " " + detail.getOffWorkTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + detail.getOffWorkTime() );
+			}
+		} catch (Exception e) {
+			detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,offWorkTime=" + detail.getRecordDateString() + " " + detail.getOffWorkTime() );
+			logger.debug( debugger, "系统进行时间转换时发生异常,offWorkTime=" + detail.getRecordDateString() + " " + detail.getOffWorkTime() );
+			logger.error(e);
+		}
+		return null;
+	}
+
+	/**
+	 * 根据已经完善过的考勤打卡记录,获取当天的上班实际签到时间
+	 * @param detail
+	 * @param debugger
+	 * @return
+	 */
+	static Date getOnDutyTimeFromDetail(AttendanceDetail detail, Boolean debugger) {
+		try {
+			if( StringUtils.isEmpty( detail.getOnDutyTime() ) ){
+				logger.debug( debugger, "onDutyTime为空 " );
+			}else{
+				logger.debug( debugger, "onDutyTime=" + detail.getRecordDateString() + " " + detail.getOnDutyTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + detail.getOnDutyTime() );
+			}
+		} catch (Exception e) {
+			detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,onDutyTime=" + detail.getRecordDateString() + " " + detail.getOnDutyTime() );
+			logger.debug( debugger, "系统进行时间转换时发生异常,onDutyTime=" + detail.getRecordDateString() + " " + detail.getOnDutyTime());
+			logger.error(e);
+		}
+		return null;
+	}
+	/**
+	 * 根据已经完善过的考勤打卡记录,获取当天的上班实际签退时间
+	 * @param detail
+	 * @param debugger
+	 * @return
+	 */
+	static Date getOffDutyTimeFromDetail(AttendanceDetail detail, Boolean debugger) {
+		try {
+			if( StringUtils.isEmpty( detail.getOnDutyTime() ) ){
+				logger.debug( debugger, "offDutyTime " );
+			}else{
+				logger.debug( debugger, "offDutyTime=" + detail.getRecordDateString() + " " + detail.getOffDutyTime() );
+				return dateOperation.getDateFromString( detail.getRecordDateString() + " " + detail.getOffDutyTime() );
+			}
+		} catch (Exception e) {
+			detail.setDescription( detail.getDescription() + "; 系统进行时间转换时发生异常,offDutyTime=" + detail.getRecordDateString() + " " + detail.getOffDutyTime() );
+			logger.debug( debugger, "系统进行时间转换时发生异常,offDutyTime=" + detail.getRecordDateString() + " " + detail.getOffDutyTime());
+			logger.error(e);
+		}
+		return null;
+	}
+
+	/**
+	 * 分析打卡信息,为打卡数据增加缺勤天数信息,默认为0,每次递增0.5天
+	 * @param detail
+	 */
+	static void increaseAbsenceStatusForAttendanceDetail(AttendanceDetail detail) {
+		Double absence = detail.getAbsence();
+		if (absence < 1.0) {
+			detail.setAbsence( absence + 0.5 );
+		}
+	}
+
+	//
+
+	/**
+	 * 分析打卡信息,为打卡数据计算出勤天数信息,默认为1,每次递减0.5天
+	 * @param detail
+	 */
+	static void increaseAttendanceStatusForAttendanceDetail(AttendanceDetail detail) {
+		Double attendance = detail.getAttendance();
+		if (attendance > 0.0) {
+			detail.setAttendance(attendance - 0.5);
+		}
+	}
+
+}

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

@@ -41,7 +41,7 @@ public class AttendanceDetailAnalyseService {
 	private AttendanceScheduleSettingService attendanceScheduleSettingService = new AttendanceScheduleSettingService();
 	private AttendanceStatisticalCycleService statisticalCycleService = new AttendanceStatisticalCycleService();
 	private AttendanceWorkDayConfigService workDayConfigService = new AttendanceWorkDayConfigService();
-//	private AttendanceDetailAnalyseCoreService attendanceDetailAnalyseCoreService = new AttendanceDetailAnalyseCoreService();
+	private AttendanceDetailAnalyseCoreService attendanceDetailAnalyseCoreService = new AttendanceDetailAnalyseCoreService();
 	private DateOperation dateOperation = new DateOperation();
 	private UserManagerService userManagerService = new UserManagerService();
 
@@ -390,7 +390,7 @@ public class AttendanceDetailAnalyseService {
 			if( check ){
 				try{
 					//使用分析核心算法进行考勤状态分析
-//					detail = attendanceDetailAnalyseCoreService.analyseCore( detail, scheduleSetting, dateOperation, debugger );
+					detail = attendanceDetailAnalyseCoreService.analyseCore( detail, scheduleSetting, debugger );
 				}catch( Exception e ){
 					check = false;
 					logger.warn( "system analyse detail by on and off work time for advance analyse got an exception." + detail.getEmpName() );

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

@@ -0,0 +1,219 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetail;
+import com.x.attendance.entity.AttendanceScheduleSetting;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Date;
+
+/**
+ * 考勤打卡记录分析服务类
+ * 1、一天只打上下班两次卡
+ */
+class AttendanceDetailAnalyseSignProxy1 {
+	
+	private static  Logger logger = LoggerFactory.getLogger( AttendanceDetailAnalyseSignProxy1.class );
+	private DateOperation dateOperation = new DateOperation();
+
+	/**
+	 * 对打卡策略1,一天上午上班,下午下班两次打卡策略分析当前的考勤打卡记录
+	 * @param detail
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 */
+	public AttendanceDetail analyse( AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger ) throws Exception {
+		Date onDutyTime = null, offDutyTime = null;
+		Date onWorkTime = null, offWorkTime = null;
+		Date lateStartTime = null, leaveEarlyStartTime = null, absenceStartTime = null, afternoonStartTime = null;
+
+		//周末,并且未调休为工作日或者是节假日
+		Boolean isNotWorkDay = ( detail.getIsWeekend() && !detail.getIsWorkday()) || detail.getIsHoliday();
+
+		//员工请假状态
+		Boolean isSelfHoliday_FullDay = detail.getIsGetSelfHolidays() && "全天".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday_Morning = detail.getIsGetSelfHolidays() && "上午".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday_Afternoon = detail.getIsGetSelfHolidays() && "下午".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday = isSelfHoliday_Afternoon || isSelfHoliday_Morning || isSelfHoliday_FullDay;
+
+		//先初始化当前打卡信息中的上下班时间要求,该要求是是根据员工所在组织排班信息获取到的
+		onWorkTime = AttendanceDetailAnalyseCoreService.getOnWorkTimeFromDetail( detail, debugger );
+		offWorkTime = AttendanceDetailAnalyseCoreService.getOffWorkTimeFromDetail( detail, debugger );
+		lateStartTime = AttendanceDetailAnalyseCoreService.getLateStartTimeFromDetail( detail, scheduleSetting, debugger );
+		leaveEarlyStartTime = AttendanceDetailAnalyseCoreService.getLeaveEarlyStartTimeFromDetail( detail, scheduleSetting, debugger );
+		absenceStartTime = AttendanceDetailAnalyseCoreService.getAbsenceStartTimeFromDetail( detail, scheduleSetting, debugger );
+		afternoonStartTime = AttendanceDetailAnalyseCoreService.getMiddleRestEndTimeFromDetail( detail, scheduleSetting, debugger );
+
+		if ( onWorkTime != null && offWorkTime != null ) {
+			logger.debug( debugger, "上下班排班信息获取正常:onWorkTime=" +  onWorkTime + ", offWorkTime="+offWorkTime );
+			onDutyTime = AttendanceDetailAnalyseCoreService.getOnDutyTimeFromDetail( detail, debugger );
+			offDutyTime = AttendanceDetailAnalyseCoreService.getOffDutyTimeFromDetail( detail, debugger );
+
+			//规则:如果员工没有签到并且没有签退,一条打卡时间都没有,那么可能会是算缺勤的
+			if ( onDutyTime == null && offDutyTime == null ) {
+				//如果员工已经全天请假了,则不算缺勤,考勤结果正常
+				if( isSelfHoliday_FullDay || isNotWorkDay ){
+					logger.debug( debugger, "全天请假不计缺勤。" );
+					detail.setAttendance( 0.0 );
+					detail.setIsAbsent( false );
+					detail.setAbsence( 0.0 );
+					detail.setAbsentDayTime( "无" );
+					detail.setWorkTimeDuration( 0L );
+				}else{
+					//否则,没有打卡,又不是请假也不是周末和节假日,那么需要计为缺勤(如果员工没有签到并且没有签退,一条打卡时间都没有)
+					logger.debug( debugger, "未请假,工作日,计缺勤1天。" );
+					detail.setAttendance( 0.0 );
+					detail.setIsAbsent( true );
+					detail.setAbsence( 1.0 );
+					detail.setAbsentDayTime("全天");
+					detail.setWorkTimeDuration( 0L );
+				}
+			}else{
+				detail.setAttendance( 1.0 );//默认为全天出勤了
+				detail.setIsAbsent( false );//默认为未缺勤
+				detail.setAbsence( 0.0 );//默认为未缺勤
+
+				//上午如果员工已经签到
+				if( onDutyTime != null ){
+
+					logger.debug( debugger, "上午打过卡,时间:onDutyTime=" + onDutyTime );
+
+					//缺勤起算时间:absenceStartTimes可以不配置,如果不配置,则为null,则不会在为打卡时间过晚而导致缺勤
+					//上午签到过了,如果排班设置里已经配置过了缺勤起算时间,那么判断员工是否已经缺勤,如果未休假,则视为缺勤半天
+					if( absenceStartTime != null && onDutyTime.after( absenceStartTime )){
+						logger.debug( debugger, "上午打卡时间晚于缺勤计时时间:" + absenceStartTime );
+						//判断员工是否已经请假过了
+						if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假不计出勤,但请过假了不算缺勤" );
+							detail.setIsAbsent( false );
+							detail.setAbsence(0.0);
+						}else{
+							logger.debug( debugger, "没请假,缺勤半天" );
+							detail.setAbsentDayTime("上午");
+							detail.setIsAbsent( true );
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);//递增缺勤天数 + 0.5
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);//递减出勤天数 - 0.5
+						}
+					}else if( lateStartTime != null && onDutyTime.after( lateStartTime )){
+						//上午签到过了,并没有超过缺勤起算时间,如果排班设置里已经配置过了迟到起算时间,那么判断员工是否已经迟到,如果未休假也不是周末的话
+						logger.debug( debugger, "上午打卡时间晚于迟到计时时间......" );
+						if( isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请过假了不算迟到" );
+							detail.setLateTimeDuration( 0L ); //请假了不算迟到
+							detail.setIsLate( false );//请假了不算迟到
+						}else{
+							//迟到计算从上班时间开始计算,不是迟到起算时间
+							long minutes = dateOperation.getMinutes( onWorkTime, onDutyTime );
+							detail.setLateTimeDuration( minutes );//没请假算迟到时长
+							detail.setIsLate( true );//没请假算迟到
+							logger.debug( debugger, "计迟到一次,迟到时长:minutes=" + minutes );
+						}
+
+					}
+				}else{
+					logger.debug( debugger, "员工上午缺卡" );
+					if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+						logger.debug( debugger, "请假不计考勤,不需要打卡,不算异常" );
+						detail.setIsAbsent( false );
+						detail.setAbnormalDutyDayTime("无");
+						detail.setIsAbnormalDuty( false );
+					}else{
+						logger.debug(debugger, "没打卡,没请假,工作日,算缺勤。");
+						detail.setAbnormalDutyDayTime("上午");
+						detail.setIsAbnormalDuty(true);
+						detail.setAbsentDayTime("上午");
+						detail.setIsAbsent(true);
+						AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+						AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+					}
+					logger.debug( debugger, "上午工作时长, 未打卡:minutes= 0 分钟。" );
+					detail.setWorkTimeDuration( 0L );
+				}
+
+				//如果下午员工已经签退
+				if( offDutyTime != null ){
+					long minutes = 0L;
+					logger.debug( debugger, "早退计时时间:leaveEarlyStartTime=" + leaveEarlyStartTime );
+					if( leaveEarlyStartTime != null && offDutyTime.before( leaveEarlyStartTime )){
+						logger.debug( debugger, "下午打卡时间早于早退计时时间" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假、休息天不计考勤,不算出勤,不算早退" );
+							detail.setLeaveEarlierTimeDuration( 0L );
+							detail.setIsLeaveEarlier( false );
+						}else{
+							minutes = dateOperation.getMinutes( offDutyTime, offWorkTime );//计算早退时长
+							detail.setLeaveEarlierTimeDuration(minutes); //早退时长
+							detail.setIsLeaveEarlier( true );
+						}
+					}
+//					else if ((leaveEarlyStartTime != null && offDutyTime.after(leaveEarlyStartTime)) && offDutyTime.before(offWorkTime)) {
+//						//打卡在早退起算之后,并在下班时间之前
+//						logger.debug(debugger, "下午打卡时间晚于早退计时时间早于下班时间......");
+//						if ( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ) {
+//							logger.debug(debugger, ">>>>>>>>>>请幸运,请假不计考勤,出勤只算半天,但请过假了不算早退");
+//							detail.setLeaveEarlierTimeDuration(0L);
+//							detail.setIsLeaveEarlier(false);
+//						} else {
+//							minutes = dateOperation.getMinutes(offDutyTime, offWorkTime);//计算早退时长
+//							detail.setLeaveEarlierTimeDuration(minutes); //早退时长
+//							detail.setIsLeaveEarlier(true);
+//						}
+//					}
+					//下午已经签退了,现在计算全天的工作时长
+					if( afternoonStartTime != null ){ //已经配置过了下午上班时间
+						minutes = dateOperation.getMinutes( afternoonStartTime, offDutyTime);
+						logger.debug( debugger, "计算下午工作时长, 从"+ afternoonStartTime +"到" + offDutyTime + " :minutes=" + minutes + "分钟。" );
+						logger.debug( debugger, "计算全天工作时长, "+ detail.getWorkTimeDuration() +"+" + minutes + "=" + detail.getWorkTimeDuration() + minutes + "分钟。" );
+						detail.setWorkTimeDuration( detail.getWorkTimeDuration() + minutes );//记录上午的工作时长 + 下午工作时长
+					}else{
+						minutes = dateOperation.getMinutes( onDutyTime, offDutyTime);
+						detail.setWorkTimeDuration( minutes );//记录上午的工作时长 + 下午工作时长
+						logger.debug( debugger, "直接计算全天工作时长, 从"+ onDutyTime +"到" + offDutyTime + " :minutes=" + minutes + "分钟。" );
+					}
+				}else{
+					//员工未签退:有两种情况,还没有到打卡时间,或者说没有打卡
+					//如果打卡是今天,但是今天还没有结束
+					if( detail.getRecordDateString().equals( dateOperation.getNowDate() )) {
+//						detail.setAbnormalDutyDayTime("无");
+//						detail.setIsAbnormalDuty(false);
+						logger.debug( debugger, "今天还未结束,先不分析结果。" );
+					}else {
+						logger.debug( debugger, "员工下午未打卡,属于异常状态,缺卡" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假或者非工作日不计考勤,不需要打卡,不算异常状态" );
+							detail.setLeaveEarlierTimeDuration( 0L );
+							detail.setIsLeaveEarlier( false );
+						}else{
+							if(StringUtils.isNotEmpty( detail.getAbnormalDutyDayTime() )){
+								detail.setAbnormalDutyDayTime("上午|下午");
+							}else {
+								detail.setAbnormalDutyDayTime("下午");
+							}
+							if(StringUtils.isNotEmpty( detail.getAbsentDayTime() )){
+								detail.setAbsentDayTime("全天");
+							}else{
+								detail.setAbsentDayTime("下午");
+							}
+							detail.setIsAbnormalDuty(true);
+							detail.setIsAbsent(true);
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+							logger.debug( debugger, "没请假,未打卡,算缺卡和缺勤状态。" );
+						}
+
+						//员工未签退,计算全天的工作时长,下午的时长不计算
+//						detail.setWorkTimeDuration( 0L );
+						logger.debug( debugger, "员工未签退,全天工作时长暂时记为0分钟,等待补卡或者补提请假申请。" );
+					}
+				}
+			}
+			detail.setRecordStatus( 1 );
+		}else{
+			logger.warn( "上下班排班信未正确配置,无法正常分析考勤记录:onWorkTime=" +  onWorkTime + ", offWorkTime="+offWorkTime );
+		}
+		return detail;
+	}
+}

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

@@ -0,0 +1,247 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetail;
+import com.x.attendance.entity.AttendanceScheduleSetting;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Date;
+
+/**
+ * 考勤打卡记录分析服务类
+ * 2、一天三次打卡:打上班,下班两次卡外,中午休息时间也需要打一次卡,以确保员工在公司活动
+ *
+ */
+class AttendanceDetailAnalyseSignProxy2 {
+	
+	private static  Logger logger = LoggerFactory.getLogger( AttendanceDetailAnalyseSignProxy2.class );
+	private DateOperation dateOperation = new DateOperation();
+
+	/**
+	 * 对打卡策略1,一天上午上班,下午下班两次打卡策略分析当前的考勤打卡记录
+	 * @param detail
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 */
+	public AttendanceDetail analyse( AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger ) throws Exception {
+		Date onWorkTime = null, offWorkTime = null;
+		Date onDutyTime = null, offDutyTime = null, middleDutyTime = null;
+		Date lateStartTime = null, leaveEarlyStartTime = null, absenceStartTime = null, morningEndTime = null, afternoonStartTime = null;
+
+		//周末,并且未调休为工作日或者是节假日
+		Boolean isNotWorkDay = ( detail.getIsWeekend() && !detail.getIsWorkday()) || detail.getIsHoliday();
+
+		//员工请假状态
+		Boolean isSelfHoliday_FullDay = detail.getIsGetSelfHolidays() && "全天".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday_Morning = detail.getIsGetSelfHolidays() && "上午".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday_Afternoon = detail.getIsGetSelfHolidays() && "下午".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday = isSelfHoliday_Afternoon || isSelfHoliday_Morning || isSelfHoliday_FullDay;
+
+		//先初始化当前打卡信息中的上下班时间要求,该要求是是根据员工所在组织排班信息获取到的
+		onWorkTime = AttendanceDetailAnalyseCoreService.getOnWorkTimeFromDetail( detail, debugger );
+		offWorkTime = AttendanceDetailAnalyseCoreService.getOffWorkTimeFromDetail( detail, debugger );
+		middleDutyTime = AttendanceDetailAnalyseCoreService.getMorningOffdutyTimeFromDetail( detail, debugger );
+
+		lateStartTime = AttendanceDetailAnalyseCoreService.getLateStartTimeFromDetail( detail, scheduleSetting, debugger );
+		leaveEarlyStartTime = AttendanceDetailAnalyseCoreService.getLeaveEarlyStartTimeFromDetail( detail, scheduleSetting, debugger );
+		absenceStartTime = AttendanceDetailAnalyseCoreService.getAbsenceStartTimeFromDetail( detail, scheduleSetting, debugger );
+		morningEndTime = AttendanceDetailAnalyseCoreService.getMiddleRestStartTimeFromDetail( detail, scheduleSetting, debugger );
+		afternoonStartTime = AttendanceDetailAnalyseCoreService.getMiddleRestEndTimeFromDetail( detail, scheduleSetting, debugger );
+
+		if ( onWorkTime != null && offWorkTime != null && morningEndTime != null && afternoonStartTime != null ) {
+			logger.debug( debugger, "上下班排班信息获取正常:onWorkTime=" +  onWorkTime + ", morningEndTime="+morningEndTime + ", afternoonStartTime="+afternoonStartTime + ", offWorkTime="+offWorkTime );
+			logger.debug( debugger, "上下班签到信息获取正常:onDutyTime=" +  onDutyTime + ", middleDutyTime="+middleDutyTime + ", offDutyTime="+offDutyTime );
+
+			onDutyTime = AttendanceDetailAnalyseCoreService.getOnDutyTimeFromDetail( detail, debugger );
+			offDutyTime = AttendanceDetailAnalyseCoreService.getOffDutyTimeFromDetail( detail, debugger );
+
+			//规则:如果员工没有签到并且没有签退,一条打卡时间都没有,那么可能会是算缺勤的
+			if ( onDutyTime == null && offDutyTime == null ) {
+				//如果员工已经全天请假了,则不算缺勤,考勤结果正常
+				if( isSelfHoliday_FullDay || isNotWorkDay ){
+					logger.debug( debugger, "全天请假不计缺勤。" );
+					detail.setAttendance( 0.0 );
+					detail.setIsAbsent( false );
+					detail.setAbsence( 0.0 );
+					detail.setAbsentDayTime( "无" );
+					detail.setWorkTimeDuration( 0L );
+				}else{
+					//否则,没有打卡,又不是请假也不是周末和节假日,那么需要计为缺勤(如果员工没有签到并且没有签退,一条打卡时间都没有)
+					logger.debug( debugger, "未请假,工作日,计缺勤1天。" );
+					detail.setAttendance( 0.0 );
+					detail.setIsAbsent( true );
+					detail.setAbsence( 1.0 );
+					detail.setAbsentDayTime("全天");
+					detail.setWorkTimeDuration( 0L );
+				}
+			}else{
+				detail.setAttendance( 1.0 );//默认为全天出勤了
+				detail.setIsAbsent( false );//默认为未缺勤
+				detail.setAbsence( 0.0 );//默认为未缺勤
+
+				//=========================================================================================================
+				//=====上午  如果员工已经签到================================================================================
+				//=========================================================================================================
+				if( onDutyTime != null ){
+
+					logger.debug( debugger, "上午打过卡,时间:onDutyTime=" + onDutyTime );
+
+					//缺勤起算时间:absenceStartTimes可以不配置,如果不配置,则为null,则不会在为打卡时间过晚而导致缺勤
+					//上午签到过了,如果排班设置里已经配置过了缺勤起算时间,那么判断员工是否已经缺勤,如果未休假,则视为缺勤半天
+					if( absenceStartTime != null && onDutyTime.after( absenceStartTime )){
+						logger.debug( debugger, "上午打卡时间晚于缺勤计时时间:" + absenceStartTime );
+						//判断员工是否已经请假过了
+						if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假不计出勤,但请过假了不算缺勤" );
+							detail.setIsAbsent( false );
+							detail.setAbsence(0.0);
+						}else{
+							logger.debug( debugger, "没请假,缺勤半天" );
+							detail.setAbsentDayTime("上午");
+							detail.setIsAbsent( true );
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);//递增缺勤天数 + 0.5
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);//递减出勤天数 - 0.5
+						}
+					}else if( lateStartTime != null && onDutyTime.after( lateStartTime )){
+						//上午签到过了,并没有超过缺勤起算时间,如果排班设置里已经配置过了迟到起算时间,那么判断员工是否已经迟到,如果未休假也不是周末的话
+						logger.debug( debugger, "上午打卡时间晚于迟到计时时间......" );
+						if( isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请过假了不算迟到" );
+							detail.setLateTimeDuration( 0L ); //请假了不算迟到
+							detail.setIsLate( false );//请假了不算迟到
+						}else{
+							//迟到计算从上班时间开始计算,不是迟到起算时间
+							long minutes = dateOperation.getMinutes( onWorkTime, onDutyTime );
+							detail.setLateTimeDuration( minutes );//没请假算迟到时长
+							detail.setIsLate( true );//没请假算迟到
+							logger.debug( debugger, "计迟到一次,迟到时长:minutes=" + minutes );
+						}
+
+					}
+				}else{
+					logger.debug( debugger, "员工上午缺卡" );
+					if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+						logger.debug( debugger, "请假不计考勤,不需要打卡,不算异常" );
+						detail.setIsAbsent( false );
+						detail.setAbnormalDutyDayTime("无");
+						detail.setIsAbnormalDuty( false );
+					}else{
+						logger.debug(debugger, "没打卡,没请假,工作日,算缺勤。");
+						detail.setAbnormalDutyDayTime("上午");
+						detail.setIsAbnormalDuty(true);
+						detail.setAbsentDayTime("上午");
+						detail.setIsAbsent(true);
+						AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+						AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+					}
+					logger.debug( debugger, "上午工作时长, 未打卡:minutes= 0 分钟。" );
+					detail.setWorkTimeDuration( 0L );
+				}
+
+				//=========================================================================================================
+				//=====中午  如果员工已经签到, 中午签到只是一个记录 ,如果未签到,则记录中缺卡 ================================================================================
+				//=========================================================================================================
+				if( middleDutyTime == null ){
+					if ( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ) {
+						logger.debug(debugger, "请假不计考勤,不算出勤");
+						detail.setIsAbsent(false);
+						detail.setAbsence(0.0);
+					} else {
+						logger.debug(debugger, "没请假,中午缺卡");
+						if(StringUtils.isNotEmpty( detail.getAbnormalDutyDayTime() )){
+							detail.setAbnormalDutyDayTime("上午|中午");
+						}else {
+							detail.setAbnormalDutyDayTime("中午");
+						}
+						detail.setIsAbnormalDuty(true);
+					}
+				}
+
+				//=========================================================================================================
+				//=====下午  如果员工已经签退================================================================================
+				//=========================================================================================================
+				if( offDutyTime != null ){
+					long minutes = 0L;
+					logger.debug( debugger, "早退计时时间:leaveEarlyStartTime=" + leaveEarlyStartTime );
+					if( leaveEarlyStartTime != null && offDutyTime.before( leaveEarlyStartTime )){
+						logger.debug( debugger, "下午打卡时间早于早退计时时间" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假、休息天不计考勤,不算出勤,不算早退" );
+							detail.setLeaveEarlierTimeDuration( 0L );
+							detail.setIsLeaveEarlier( false );
+						}else{
+							minutes = dateOperation.getMinutes( offDutyTime, offWorkTime );//计算早退时长
+							detail.setLeaveEarlierTimeDuration(minutes); //早退时长
+							detail.setIsLeaveEarlier( true );
+						}
+					}
+//					else if ((leaveEarlyStartTime != null && offDutyTime.after(leaveEarlyStartTime)) && offDutyTime.before(offWorkTime)) {
+//						//打卡在早退起算之后,并在下班时间之前
+//						logger.debug(debugger, "下午打卡时间晚于早退计时时间早于下班时间......");
+//						if ( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ) {
+//							logger.debug(debugger, "请假不计考勤,出勤只算半天,但请过假了不算早退");
+//							detail.setLeaveEarlierTimeDuration(0L);
+//							detail.setIsLeaveEarlier(false);
+//						} else {
+//							minutes = dateOperation.getMinutes(offDutyTime, offWorkTime);//计算早退时长
+//							detail.setLeaveEarlierTimeDuration(minutes); //早退时长
+//							detail.setIsLeaveEarlier(true);
+//						}
+//					}
+					//下午已经签退了,现在计算全天的工作时长
+					if( afternoonStartTime != null ){ //已经配置过了下午上班时间
+						minutes = dateOperation.getMinutes( afternoonStartTime, offDutyTime);
+						logger.debug( debugger, "计算下午工作时长, 从"+ afternoonStartTime +"到" + offDutyTime + " :minutes=" + minutes + "分钟。" );
+						logger.debug( debugger, "直接计算全天工作时长, "+ detail.getWorkTimeDuration() +"+" + minutes + "=" + detail.getWorkTimeDuration() + minutes + "分钟。" );
+						detail.setWorkTimeDuration( detail.getWorkTimeDuration() + minutes );//记录上午的工作时长 + 下午工作时长
+					}else{
+						minutes = dateOperation.getMinutes( onDutyTime, offDutyTime);
+						logger.debug( debugger, "直接计算全天工作时长, 从"+ onDutyTime +"到" + offDutyTime + " :minutes=" + minutes + "分钟。" );
+					}
+				}else{
+					//员工未签退:有两种情况,还没有到打卡时间,或者说没有打卡
+					//如果打卡是今天,但是今天还没有结束
+					if( detail.getRecordDateString().equals( dateOperation.getNowDate() )) {
+//						detail.setAbnormalDutyDayTime("无");
+//						detail.setIsAbnormalDuty(false);
+						logger.debug( debugger, "今天还未结束,先不分析结果。" );
+					}else {
+						logger.debug( debugger, "员工下午未打卡,属于异常状态,缺卡" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假或者非工作日不计考勤,不需要打卡,不算异常状态" );
+							detail.setLeaveEarlierTimeDuration( 0L );
+							detail.setIsLeaveEarlier( false );
+						}else{
+							if(StringUtils.isNotEmpty( detail.getAbnormalDutyDayTime() )){
+								detail.setAbnormalDutyDayTime("上午|下午");
+							}else {
+								detail.setAbnormalDutyDayTime("下午");
+							}
+							if(StringUtils.isNotEmpty( detail.getAbsentDayTime() )){
+								detail.setAbsentDayTime("全天");
+							}else{
+								detail.setAbsentDayTime("下午");
+							}
+							detail.setIsAbnormalDuty(true);
+							detail.setIsAbsent(true);
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+							logger.debug( debugger, "没请假,未打卡,算缺卡和缺勤状态。" );
+						}
+
+						//员工未签退,计算全天的工作时长,下午的时长不计算
+						detail.setWorkTimeDuration( 0L );
+						logger.debug( debugger, "员工未签退,全天工作时长暂时记为0分钟,等待补卡或者补提请假申请。" );
+					}
+				}
+			}
+			detail.setRecordStatus( 1 );
+		}else{
+			logger.warn( "上下班排班信未正确配置,无法正常分析考勤记录:onWorkTime=" +  onWorkTime + ", morningEndTime="+morningEndTime + ", afternoonStartTime="+afternoonStartTime + ", offWorkTime="+offWorkTime );
+		}
+		return detail;
+	}
+}

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

@@ -0,0 +1,285 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetail;
+import com.x.attendance.entity.AttendanceScheduleSetting;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Date;
+
+/**
+ * 考勤打卡记录分析服务类
+ * 2、一天三次打卡:打上班,下班两次卡外,中午休息时间也需要打一次卡,以确保员工在公司活动
+ *
+ */
+class AttendanceDetailAnalyseSignProxy3 {
+	
+	private static  Logger logger = LoggerFactory.getLogger( AttendanceDetailAnalyseSignProxy3.class );
+	private DateOperation dateOperation = new DateOperation();
+
+	/**
+	 * 3、一天四次打卡:打上午上班,上午下班,下午上班,下午下班四次卡
+	 * @param detail
+	 * @param scheduleSetting
+	 * @param debugger
+	 * @return
+	 */
+	public AttendanceDetail analyse( AttendanceDetail detail, AttendanceScheduleSetting scheduleSetting, Boolean debugger ) throws Exception {
+		Date onWorkTime = null, offWorkTime = null;
+		Date onDutyTime = null, offDutyTime = null, morningOffdutyTime = null, afternoonOndutyTime = null;
+		Date lateStartTime = null, leaveEarlyStartTime = null, absenceStartTime = null, morningEndTime = null, afternoonStartTime = null;
+
+		//周末,并且未调休为工作日或者是节假日
+		Boolean isNotWorkDay = ( detail.getIsWeekend() && !detail.getIsWorkday()) || detail.getIsHoliday();
+
+		//员工请假状态
+		Boolean isSelfHoliday_FullDay = detail.getIsGetSelfHolidays() && "全天".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday_Morning = detail.getIsGetSelfHolidays() && "上午".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday_Afternoon = detail.getIsGetSelfHolidays() && "下午".equalsIgnoreCase( detail.getSelfHolidayDayTime() );
+		Boolean isSelfHoliday = isSelfHoliday_Afternoon || isSelfHoliday_Morning || isSelfHoliday_FullDay;
+
+		//先初始化当前打卡信息中的上下班时间要求,该要求是是根据员工所在组织排班信息获取到的
+		onWorkTime = AttendanceDetailAnalyseCoreService.getOnWorkTimeFromDetail( detail, debugger );
+		offWorkTime = AttendanceDetailAnalyseCoreService.getOffWorkTimeFromDetail( detail, debugger );
+		onDutyTime = AttendanceDetailAnalyseCoreService.getOnDutyTimeFromDetail( detail, debugger );
+		offDutyTime = AttendanceDetailAnalyseCoreService.getOffDutyTimeFromDetail( detail, debugger );
+		morningOffdutyTime = AttendanceDetailAnalyseCoreService.getMorningOffdutyTimeFromDetail( detail, debugger );
+		afternoonOndutyTime = AttendanceDetailAnalyseCoreService.getAfternoonOndutyTimeFromDetail( detail, debugger );
+
+		lateStartTime = AttendanceDetailAnalyseCoreService.getLateStartTimeFromDetail( detail, scheduleSetting, debugger );
+		leaveEarlyStartTime = AttendanceDetailAnalyseCoreService.getLeaveEarlyStartTimeFromDetail( detail, scheduleSetting, debugger );
+		absenceStartTime = AttendanceDetailAnalyseCoreService.getAbsenceStartTimeFromDetail( detail, scheduleSetting, debugger );
+		morningEndTime = AttendanceDetailAnalyseCoreService.getMiddleRestStartTimeFromDetail( detail, scheduleSetting, debugger );
+		afternoonStartTime = AttendanceDetailAnalyseCoreService.getMiddleRestEndTimeFromDetail( detail, scheduleSetting, debugger );
+
+
+		if ( onWorkTime != null && offWorkTime != null && morningEndTime != null && afternoonStartTime != null ) {
+			logger.debug( debugger, "上下班排班信息获取正常:onWorkTime=" +  onWorkTime + ", morningEndTime="+morningEndTime + ", afternoonStartTime="+afternoonStartTime + ", offWorkTime="+offWorkTime );
+			logger.debug( debugger, "上下班签到信息获取正常:onDutyTime=" +  onDutyTime + ", morningOffdutyTime="+morningOffdutyTime + ", afternoonOndutyTime="+afternoonOndutyTime + ", offDutyTime="+offDutyTime );
+
+			//规则:如果员工没有签到并且没有签退,一条打卡时间都没有,那么可能会是算缺勤的
+			if ( onDutyTime == null && offDutyTime == null ) {
+				//如果员工已经全天请假了,则不算缺勤,考勤结果正常
+				if( isSelfHoliday_FullDay || isNotWorkDay ){
+					logger.debug( debugger, "全天请假不计缺勤。" );
+					detail.setAttendance( 0.0 );
+					detail.setIsAbsent( false );
+					detail.setAbsence( 0.0 );
+					detail.setAbsentDayTime( "无" );
+					detail.setWorkTimeDuration( 0L );
+				}else{
+					//否则,没有打卡,又不是请假也不是周末和节假日,那么需要计为缺勤(如果员工没有签到并且没有签退,一条打卡时间都没有)
+					logger.debug( debugger, "未请假,工作日,计缺勤1天。" );
+					detail.setAttendance( 0.0 );
+					detail.setIsAbsent( true );
+					detail.setAbsence( 1.0 );
+					detail.setAbsentDayTime("全天");
+					detail.setWorkTimeDuration( 0L );
+				}
+			}else{
+				detail.setAttendance( 1.0 );//默认为全天出勤了
+				detail.setIsAbsent( false );//默认为未缺勤
+				detail.setAbsence( 0.0 );//默认为未缺勤
+
+				//=========================================================================================================
+				//=====上午  如果员工已经签到================================================================================
+				//=========================================================================================================
+				if( onDutyTime != null ){
+					logger.debug( debugger, "上午打过卡,时间:onDutyTime=" + onDutyTime );
+					//缺勤起算时间:absenceStartTimes可以不配置,如果不配置,则为null,则不会在为打卡时间过晚而导致缺勤
+					//上午签到过了,如果排班设置里已经配置过了缺勤起算时间,那么判断员工是否已经缺勤,如果未休假,则视为缺勤半天
+					if( absenceStartTime != null && onDutyTime.after( absenceStartTime )){
+						logger.debug( debugger, "上午打卡时间晚于缺勤计时时间:" + absenceStartTime );
+						//判断员工是否已经请假过了
+						if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假不计出勤,但请过假了不算缺勤" );
+							detail.setIsAbsent( false );
+							detail.setAbsence(0.0);
+						}else{
+							logger.debug( debugger, "没请假,缺勤半天" );
+							detail.setAbsentDayTime("上午");
+							detail.setIsAbsent( true );
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);//递增缺勤天数 + 0.5
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);//递减出勤天数 - 0.5
+						}
+					}else if( lateStartTime != null && onDutyTime.after( lateStartTime )){
+						//上午签到过了,并没有超过缺勤起算时间,如果排班设置里已经配置过了迟到起算时间,那么判断员工是否已经迟到,如果未休假也不是周末的话
+						logger.debug( debugger, "上午打卡时间晚于迟到计时时间......" );
+						if( isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请过假了不算迟到" );
+							detail.setLateTimeDuration( 0L ); //请假了不算迟到
+							detail.setIsLate( false );//请假了不算迟到
+						}else{
+							//迟到计算从上班时间开始计算,不是迟到起算时间
+							long minutes = dateOperation.getMinutes( onWorkTime, onDutyTime );
+							detail.setLateTimeDuration( minutes );//没请假算迟到时长
+							detail.setIsLate( true );//没请假算迟到
+							logger.debug( debugger, "计迟到一次,迟到时长:minutes=" + minutes );
+						}
+
+					}
+				}else{
+					logger.debug( debugger, "员工上午缺卡" );
+					if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+						logger.debug( debugger, "请假不计考勤,不需要打卡,不算异常" );
+						detail.setIsAbsent( false );
+						detail.setAbnormalDutyDayTime("无");
+						detail.setIsAbnormalDuty( false );
+					}else{
+						logger.debug(debugger, "没打卡,没请假,工作日,算缺勤。");
+						detail.setAbnormalDutyDayTime("上午");
+						detail.setIsAbnormalDuty(true);
+						detail.setAbsentDayTime("上午");
+						detail.setIsAbsent(true);
+						AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+						AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+					}
+					logger.debug( debugger, "上午工作时长, 未打卡:minutes= 0 分钟。" );
+					detail.setWorkTimeDuration( 0L );
+				}
+
+				//=========================================================================================================
+				//=====上午  如果员工已经签退 morningOffdutyTime================================================================================
+				//=========================================================================================================
+				if( morningOffdutyTime != null ){//打卡签退,上午不判断是否早退
+					long minutes = 0L;
+					//上午已经签退了,现在计算上午的工作时长
+					minutes = dateOperation.getMinutes( onDutyTime, morningOffdutyTime);
+					detail.setWorkTimeDuration( minutes );
+					logger.debug( debugger, "直接计算上午工作时长, 从"+ onDutyTime +"到" + morningOffdutyTime + " :minutes=" + minutes + "分钟。" );
+				}else{
+					//看看时间是否已经到了下午上班时间
+					if( new Date().before(afternoonStartTime )){
+						logger.debug( debugger, "上午还未结束,先不分析结果。" );
+					}else{
+						logger.debug( debugger, "员工上午未签退,属于异常状态,缺卡" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假或者非工作日不计考勤,不需要打卡,不算异常状态" );
+//							detail.setLeaveEarlierTimeDuration( 0L );
+//							detail.setIsLeaveEarlier( false );
+						}else{
+							detail.setAbnormalDutyDayTime("上午");
+							detail.setAbsentDayTime("上午");
+							detail.setIsAbnormalDuty(true);
+							detail.setIsAbsent(true);
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+							logger.debug( debugger, "没请假,未打卡,算缺卡和缺勤状态。" );
+						}
+						//员工未签退,计算全天的工作时长,下午的时长不计算
+						detail.setWorkTimeDuration( 0L );
+						logger.debug( debugger, "员工未签退,上午工作时长暂时记为0分钟,等待补卡或者补提请假申请。" );
+					}
+				}
+
+				//=========================================================================================================
+				//=====下午  如果员工已经签退 afternoonOndutyTime================================================================================
+				//=========================================================================================================
+				if( afternoonOndutyTime != null ){
+					logger.debug( debugger, "下午打卡签到,时间:afternoonOndutyTime=" + afternoonOndutyTime );
+				}else{
+					if( new Date().after( afternoonStartTime )){
+						logger.debug( debugger, "员工下午上班缺卡" );
+						if(  isSelfHoliday_Morning || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假不计考勤,不需要打卡,不算异常" );
+//							detail.setIsAbsent( false );
+//							detail.setAbnormalDutyDayTime("无");
+//							detail.setIsAbnormalDuty( false );
+						}else{
+							logger.debug(debugger, "没打卡,没请假,工作日,算缺勤。");
+							detail.setAbnormalDutyDayTime("下午");
+							detail.setIsAbnormalDuty(true);
+							detail.setAbsentDayTime("下午");
+							detail.setIsAbsent(true);
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+						}
+						logger.debug( debugger, "下午工作时长, 未打卡:minutes= 0 分钟。" );
+//						detail.setWorkTimeDuration( 0L );
+					}
+				}
+
+				//=========================================================================================================
+				//=====下午  如果员工已经签退================================================================================
+				//=========================================================================================================
+				if( offDutyTime != null ){
+					long minutes = 0L;
+					logger.debug( debugger, "早退计时时间:leaveEarlyStartTime=" + leaveEarlyStartTime );
+					if( leaveEarlyStartTime != null && offDutyTime.before( leaveEarlyStartTime )){
+						logger.debug( debugger, "下午打卡时间早于早退计时时间" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假、休息天不计考勤,不算出勤,不算早退" );
+							detail.setLeaveEarlierTimeDuration( 0L );
+							detail.setIsLeaveEarlier( false );
+						}else{
+							minutes = dateOperation.getMinutes( offDutyTime, offWorkTime );//计算早退时长
+							detail.setLeaveEarlierTimeDuration(minutes); //早退时长
+							detail.setIsLeaveEarlier( true );
+						}
+					}
+//					else if ((leaveEarlyStartTime != null && offDutyTime.after(leaveEarlyStartTime)) && offDutyTime.before(offWorkTime)) {
+//						//打卡在早退起算之后,并在下班时间之前
+//						logger.debug(debugger, "下午打卡时间晚于早退计时时间早于下班时间......");
+//						if ( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ) {
+//							logger.debug(debugger, "请假不计考勤,出勤只算半天,但请过假了不算早退");
+//							detail.setLeaveEarlierTimeDuration(0L);
+//							detail.setIsLeaveEarlier(false);
+//						} else {
+//							minutes = dateOperation.getMinutes(offDutyTime, offWorkTime);//计算早退时长
+//							detail.setLeaveEarlierTimeDuration(minutes); //早退时长
+//							detail.setIsLeaveEarlier(true);
+//						}
+//					}
+					//下午已经签退了,现在计算全天的工作时长
+					if( afternoonStartTime != null ){ //已经配置过了下午上班时间
+						minutes = dateOperation.getMinutes( afternoonStartTime, offDutyTime);
+						logger.debug( debugger, "计算下午工作时长, 从"+ afternoonStartTime +"到" + offDutyTime + " :minutes=" + minutes + "分钟。" );
+						logger.debug( debugger, "直接计算全天工作时长, "+ detail.getWorkTimeDuration() +"+" + minutes + "=" + detail.getWorkTimeDuration() + minutes + "分钟。" );
+						detail.setWorkTimeDuration( detail.getWorkTimeDuration() + minutes );//记录上午的工作时长 + 下午工作时长
+					}
+				}else{
+					//员工未签退:有两种情况,还没有到打卡时间,或者说没有打卡
+					//如果打卡是今天,但是今天还没有结束
+					if( detail.getRecordDateString().equals( dateOperation.getNowDate() )) {
+						detail.setAbnormalDutyDayTime("无");
+						detail.setIsAbnormalDuty(false);
+						logger.debug( debugger, "今天还未结束,先不分析结果。" );
+					}else {
+						logger.debug( debugger, "员工下午未打卡,属于异常状态,缺卡" );
+						if( isSelfHoliday_Afternoon || isSelfHoliday_Afternoon || isNotWorkDay ){
+							logger.debug( debugger, "请假或者非工作日不计考勤,不需要打卡,不算异常状态" );
+							detail.setLeaveEarlierTimeDuration( 0L );
+							detail.setIsLeaveEarlier( false );
+						}else{
+							if(StringUtils.isNotEmpty( detail.getAbnormalDutyDayTime() )){
+								detail.setAbnormalDutyDayTime("上午|下午");
+							}else {
+								detail.setAbnormalDutyDayTime("下午");
+							}
+							if(StringUtils.isNotEmpty( detail.getAbsentDayTime() )){
+								detail.setAbsentDayTime("全天");
+							}else{
+								detail.setAbsentDayTime("下午");
+							}
+							detail.setIsAbnormalDuty(true);
+							detail.setIsAbsent(true);
+							AttendanceDetailAnalyseCoreService.increaseAbsenceStatusForAttendanceDetail(detail);
+							AttendanceDetailAnalyseCoreService.increaseAttendanceStatusForAttendanceDetail(detail);
+							logger.debug( debugger, "没请假,未打卡,算缺卡和缺勤状态。" );
+						}
+
+						//员工未签退,计算全天的工作时长,下午的时长不计算
+//						detail.setWorkTimeDuration( 0L );
+						logger.debug( debugger, "员工未签退,全天工作时长暂时记为0分钟,等待补卡或者补提请假申请。" );
+					}
+				}
+			}
+			detail.setRecordStatus( 1 );
+		}else{
+			logger.warn( "上下班排班信未正确配置,无法正常分析考勤记录:onWorkTime=" +  onWorkTime + ", morningEndTime="+morningEndTime + ", afternoonStartTime=" +  afternoonStartTime + ", offWorkTime="+offWorkTime );
+		}
+		return detail;
+	}
+}

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

@@ -5,15 +5,11 @@ import java.util.List;
 import java.util.Map;
 
 import com.x.attendance.assemble.control.ThisApplication;
+import com.x.attendance.entity.*;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.attendance.assemble.common.date.DateOperation;
 import com.x.attendance.assemble.control.Business;
-import com.x.attendance.entity.AttendanceDetail;
-import com.x.attendance.entity.AttendanceDetailMobile;
-import com.x.attendance.entity.AttendanceEmployeeConfig;
-import com.x.attendance.entity.AttendanceStatisticalCycle;
-import com.x.attendance.entity.AttendanceWorkDayConfig;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.annotation.CheckPersistType;
@@ -26,6 +22,7 @@ public class AttendanceDetailServiceAdv {
 	private static  Logger logger = LoggerFactory.getLogger( AttendanceDetailServiceAdv.class );
 	private AttendanceDetailService attendanceDetailService = new AttendanceDetailService();
 	private AttendanceDetailMobileService attendanceDetailMobileService = new AttendanceDetailMobileService();
+	private AttendanceScheduleSettingService attendanceScheduleSettingService = new AttendanceScheduleSettingService();
 //	protected AttendanceDetailAnalyseServiceAdv attendanceDetailAnalyseServiceAdv = new AttendanceDetailAnalyseServiceAdv();
 //	protected AttendanceWorkDayConfigServiceAdv attendanceWorkDayConfigServiceAdv = new AttendanceWorkDayConfigServiceAdv();
 //	protected AttendanceStatisticalCycleServiceAdv attendanceStatisticCycleServiceAdv = new AttendanceStatisticalCycleServiceAdv();
@@ -225,47 +222,46 @@ public class AttendanceDetailServiceAdv {
 		}
 	}
 
-	public void pushToDetail(String distinguishedName, String recordDateString ) throws Exception {
+	/**
+	 * 根据所有的移动打卡记录来组织一个完整的打卡记录
+	 * @param distinguishedName
+	 * @param recordDateString
+	 * @throws Exception
+	 */
+	public void pushToDetail(String distinguishedName, String recordDateString, Boolean debugger ) throws Exception {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			List<AttendanceDetailMobile> mobileDetails = attendanceDetailMobileService.listAttendanceDetailMobileWithEmployee( emc, distinguishedName, recordDateString );
 			if( ListTools.isNotEmpty( mobileDetails )) {
-				AttendanceDetailMobile mobileDetail = mobileDetails.get( 0 );
-				String onDutyTime = getOnDutyTime( mobileDetails );
-				String offDutyTime = getOffDutyTime( mobileDetails );
-				
-				AttendanceDetail detail = attendanceDetailService.listDetailWithEmployee( emc, distinguishedName, recordDateString );
-				if( detail == null ) {
-					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.setBatchName( "FromMobile_" + dateOperation.getNowTimeChar() );	
-					
+				AttendanceDetail detail_old = attendanceDetailService.listDetailWithEmployee( emc, distinguishedName, recordDateString );
+				AttendanceDetail detail = 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、一天只打上下班两次卡
+					detail = new ComposeDetailWithMobileInSignProxy1().compose( mobileDetails, scheduleSetting, debugger);
+				}else if( 2 == scheduleSetting.getSignProxy() ){
+					//2、一天三次打卡:打上班,下班两次卡外,中午休息时间也需要打一次卡,以确保员工在公司活动
+					detail = new ComposeDetailWithMobileInSignProxy2().compose( mobileDetails, scheduleSetting, debugger);
+				}else if( 3 == scheduleSetting.getSignProxy() ){
+					//3、一天四次打卡:打上午上班,上午下班,下午上班,下午下班四次卡
+					detail = new ComposeDetailWithMobileInSignProxy3().compose( mobileDetails, scheduleSetting, debugger);
+				}
+
+				if( detail_old == null ) {
+					detail.setBatchName( "FromMobile_" + dateOperation.getNowTimeChar() );
 					emc.beginTransaction( AttendanceDetail.class );
 					emc.persist( detail , CheckPersistType.all );
 					emc.commit();
 				}else {
-					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() );	
-					
 					emc.beginTransaction( AttendanceDetail.class );
-					emc.check( detail , CheckPersistType.all );
+					detail.copyTo( detail_old );
+					emc.check( detail_old , CheckPersistType.all );
 					emc.commit();
 				}
 
@@ -282,59 +278,9 @@ public class AttendanceDetailServiceAdv {
 				} catch ( Exception e1 ) {
 					e1.printStackTrace();
 				}
-
-//				List<AttendanceWorkDayConfig> attendanceWorkDayConfigList = null;
-//				Map<String, Map<String, List<AttendanceStatisticalCycle>>> topUnitAttendanceStatisticalCycleMap = null;
-//				try {
-//					attendanceWorkDayConfigList = attendanceWorkDayConfigServiceAdv.listAll();
-//					topUnitAttendanceStatisticalCycleMap = attendanceStatisticCycleServiceAdv.getCycleMapFormAllCycles( false );
-//
-//					attendanceDetailAnalyseServiceAdv.analyseAttendanceDetail( detail, attendanceWorkDayConfigList, topUnitAttendanceStatisticalCycleMap, false );
-//					logger.info( ">>>>>>>>>>attendance detail analyse completed.person:" + detail.getEmpName() + ", date:" + detail.getRecordDateString());
-//
-//				} catch (Exception e) {
-//					e.printStackTrace();
-//				}
 			}
 		} catch ( Exception e ) {
 			throw e;
 		}
 	}
-
-	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;
-	}
-
-	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;
-	}
-	
 }

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

@@ -130,7 +130,7 @@ public class AttendanceSettingService {
 		type = "select";
 		selectContent = AppealConfig.APPEAL_AUDIFLOWTYPE_WORKFLOW + "|" + AppealConfig.APPEAL_AUDIFLOWTYPE_BUILTIN;
 		isMultiple = false;
-		description = "考勤结果申诉审核人确定方式:可选值:"+AppealConfig.APPEAL_AUDIFLOWTYPE_BUILTIN+"|"+ AppealConfig.APPEAL_AUDIFLOWTYPE_BUILTIN +"。此配置控制考勤结果申诉流程为自定义流程或者内置审批步骤(审核-复核)。";
+		description = "考勤结果申诉审核人确定方式:可选值:"+AppealConfig.APPEAL_AUDIFLOWTYPE_BUILTIN+"|"+ AppealConfig.APPEAL_AUDIFLOWTYPE_WORKFLOW +"。此配置控制考勤结果申诉流程为自定义流程或者内置审批步骤(审核-复核)。";
 		try {
 			checkAndInitSystemConfig("APPEAL_AUDIFLOWTYPE", "考勤结果申诉流程类型", value, description, type, selectContent, isMultiple, ++ordernumber );
 		} catch (Exception e) {

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

@@ -0,0 +1,101 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetail;
+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.apache.commons.lang3.StringUtils;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 考勤打卡记录分析服务类
+ * 1、一天只打上下班两次卡
+ */
+class ComposeDetailWithMobileInSignProxy1 {
+	
+	private static  Logger logger = LoggerFactory.getLogger( ComposeDetailWithMobileInSignProxy1.class );
+	private DateOperation dateOperation = new DateOperation();
+
+
+	/**
+	 * 组织一个完整的打卡记录
+	 * 1、上班打卡时间:最早的一次打卡就是上班打卡时间(考虑一下有没有配置中午休息时间,如果有午休时间,上班打卡需要按时间来计算)
+	 * 2、下班打卡时间:第二次以后的打卡都是下班打卡,取最晚的一次
+	 * @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 );
+		//					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;
+	}
+
+	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;
+	}
+
+	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;
+	}
+}

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

@@ -0,0 +1,25 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetail;
+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 java.util.List;
+
+/**
+ * 考勤打卡记录分析服务类
+ * 2、一天三次打卡:打上班,下班两次卡外,中午休息时间也需要打一次卡,以确保员工在公司活动
+ */
+class ComposeDetailWithMobileInSignProxy2 {
+	
+	private static  Logger logger = LoggerFactory.getLogger( ComposeDetailWithMobileInSignProxy2.class );
+	private DateOperation dateOperation = new DateOperation();
+
+
+	public AttendanceDetail compose(List<AttendanceDetailMobile> mobileDetails, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		return null;
+	}
+}

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

@@ -0,0 +1,25 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.common.date.DateOperation;
+import com.x.attendance.entity.AttendanceDetail;
+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 java.util.List;
+
+/**
+ * 考勤打卡记录分析服务类
+ * 3、一天四次打卡:打上午上班,上午下班,下午上班,下午下班四次卡
+ */
+class ComposeDetailWithMobileInSignProxy3 {
+	
+	private static  Logger logger = LoggerFactory.getLogger( ComposeDetailWithMobileInSignProxy3.class );
+	private DateOperation dateOperation = new DateOperation();
+
+
+	public AttendanceDetail compose(List<AttendanceDetailMobile> mobileDetails, AttendanceScheduleSetting scheduleSetting, Boolean debugger) {
+		return null;
+	}
+}

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

@@ -0,0 +1,244 @@
+package com.x.attendance.assemble.control.service;
+
+import com.x.attendance.assemble.control.ThisApplication;
+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.connection.ActionResponse;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.x_processplatform_assemble_surface;
+import com.x.processplatform.core.entity.content.*;
+import com.x.processplatform.core.entity.element.ActivityType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class WorkFlowSyncService {
+
+	public static WoWorkComplex getWorkComplex( String workId ) throws Exception {
+		String serviceUri = "work/" + workId;
+		ActionResponse resp = ThisApplication.context().applications().getQuery(
+				x_processplatform_assemble_surface.class, serviceUri
+		);
+		WoWorkComplex wo = resp.getData( WoWorkComplex.class );
+		return wo;
+	}
+
+	public static class WoWorkComplex extends GsonPropertyObject {
+
+		@FieldDescribe("活动节点")
+		private WoActivity activity;
+
+		@FieldDescribe("工作")
+		private WoWork work;
+
+		@FieldDescribe("待办对象列表")
+		private List<WoTask> taskList = new ArrayList<>();
+
+		@FieldDescribe("工作日志对象")
+		private List<WoWorkLog> workLogList = new ArrayList<>();
+
+		public WoActivity getActivity() {
+			return activity;
+		}
+
+		public WoWork getWork() {
+			return work;
+		}
+
+		public List<WoWorkLog> getWorkLogList() {
+			return workLogList;
+		}
+
+		public void setActivity(WoActivity activity) {
+			this.activity = activity;
+		}
+
+		public void setWork(WoWork work) {
+			this.work = work;
+		}
+
+		public void setWorkLogList(List<WoWorkLog> workLogList) {
+			this.workLogList = workLogList;
+		}
+
+		public List<WoTask> getTaskList() {
+			return taskList;
+		}
+
+		public void setTaskList(List<WoTask> taskList) {
+			this.taskList = taskList;
+		}
+	}
+
+	public static class WoActivity extends GsonPropertyObject {
+
+		private String id;
+
+		private String name;
+
+		private String description;
+
+		private String alias;
+
+		private String position;
+
+		private ActivityType activityType;
+
+		private String resetRange;
+
+		private Integer resetCount;
+
+		public String getName() {
+			return name;
+		}
+
+		public void setName(String name) {
+			this.name = name;
+		}
+
+		public String getDescription() {
+			return description;
+		}
+
+		public void setDescription(String description) {
+			this.description = description;
+		}
+
+		public String getAlias() {
+			return alias;
+		}
+
+		public void setAlias(String alias) {
+			this.alias = alias;
+		}
+
+		public String getPosition() {
+			return position;
+		}
+
+		public void setPosition(String position) {
+			this.position = position;
+		}
+
+		public ActivityType getActivityType() {
+			return activityType;
+		}
+
+		public void setActivityType(ActivityType activityType) {
+			this.activityType = activityType;
+		}
+
+		public String getId() {
+			return id;
+		}
+
+		public void setId(String id) {
+			this.id = id;
+		}
+
+		public Integer getResetCount() {
+			return resetCount;
+		}
+
+		public void setResetCount(Integer resetCount) {
+			this.resetCount = resetCount;
+		}
+
+		public String getResetRange() {
+			return resetRange;
+		}
+
+		public void setResetRange(String resetRange) {
+			this.resetRange = resetRange;
+		}
+
+	}
+
+	public static class WoWork extends Work {
+
+		private static final long serialVersionUID = 3269592171662996253L;
+
+		static WrapCopier<Work, WoWork> copier = WrapCopierFactory.wo(Work.class, WoWork.class, null,
+				JpaObject.FieldsInvisible);
+	}
+
+	public static class WoWorkLog extends WorkLog {
+
+		private static final long serialVersionUID = 1307569946729101786L;
+
+		public static WrapCopier<WorkLog, WoWorkLog> copier = WrapCopierFactory.wo(WorkLog.class, WoWorkLog.class, null,
+				JpaObject.FieldsInvisible);
+
+		private List<WoTaskCompleted> taskCompletedList;
+
+		private List<WoTask> taskList;
+
+		private Integer currentTaskIndex;
+
+		public Integer getCurrentTaskIndex() {
+			return currentTaskIndex;
+		}
+
+		public void setCurrentTaskIndex(Integer currentTaskIndex) {
+			this.currentTaskIndex = currentTaskIndex;
+		}
+
+		public List<WoTaskCompleted> getTaskCompletedList() {
+			return taskCompletedList;
+		}
+
+		public void setTaskCompletedList(List<WoTaskCompleted> taskCompletedList) {
+			this.taskCompletedList = taskCompletedList;
+		}
+
+		public List<WoTask> getTaskList() {
+			return taskList;
+		}
+
+		public void setTaskList(List<WoTask> taskList) {
+			this.taskList = taskList;
+		}
+
+	}
+
+	public static class WoTask extends Task {
+
+		private static final long serialVersionUID = 2279846765261247910L;
+
+		public static WrapCopier<Task, WoTask> copier = WrapCopierFactory.wo(Task.class, WoTask.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+
+	public static class WoRead extends Read {
+
+		private static final long serialVersionUID = -8067704098385000667L;
+
+		public static WrapCopier<Read, WoRead> copier = WrapCopierFactory.wo(Read.class, WoRead.class, null,
+				JpaObject.FieldsInvisible);
+
+	}
+
+	public static class WoTaskCompleted extends TaskCompleted {
+
+		private static final long serialVersionUID = -7253999118308715077L;
+
+		public static WrapCopier<TaskCompleted, WoTaskCompleted> copier = WrapCopierFactory.wo(TaskCompleted.class,
+				WoTaskCompleted.class, null, JpaObject.FieldsInvisible);
+		private Long rank;
+
+		public Long getRank() {
+			return rank;
+		}
+
+		public void setRank(Long rank) {
+			this.rank = rank;
+		}
+
+	}
+
+
+
+}

+ 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 + adminName_FIELDNAME)
+	@Column(length = JpaObject.length_96B, name = ColumnNamePrefix + admin_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + adminName_FIELDNAME)
 	private String admin = "";
 

+ 14 - 11
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/AttendanceAppealAuditInfo.java

@@ -59,10 +59,20 @@ public class AttendanceAppealAuditInfo extends SliceJpaObject {
 	private String detailId;
 
 	public static final String auditFlowType_FIELDNAME = "auditFlowType";
-	@FieldDescribe("审批方式:WORKFLOW|BUILTIN")
+	@FieldDescribe("审批方式:WORKFLOW|BUILTIN,使用自定义流程或者使用内置流程")
 	@Column( length = JpaObject.length_255B, name = ColumnNamePrefix + auditFlowType_FIELDNAME)
 	private String auditFlowType = AppealConfig.APPEAL_AUDIFLOWTYPE_BUILTIN;
 
+	public static final String workId_FIELDNAME = "workId";
+	@FieldDescribe("自定义审批流程WorkID")
+	@Column( length = JpaObject.length_id, name = ColumnNamePrefix + workId_FIELDNAME)
+	private String workId;
+
+	public static final String lastFlowSyncTime_FIELDNAME = "lastFlowSyncTime";
+	@FieldDescribe("上次进行状态同步时间")
+	@Column( name = ColumnNamePrefix + lastFlowSyncTime_FIELDNAME)
+	private Date lastFlowSyncTime;
+
 	public static final String currentProcessor_FIELDNAME = "currentProcessor";
 	@FieldDescribe("当前审核人")
 	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + currentProcessor_FIELDNAME)
@@ -120,23 +130,16 @@ public class AttendanceAppealAuditInfo extends SliceJpaObject {
 	@Column( name = ColumnNamePrefix + processTime2_FIELDNAME )
 	private Date processTime2;
 
-	public static final String auditFlowId_FIELDNAME = "auditFlowId";
-	@FieldDescribe("自定义审批流程ID")
-	@Column( length = JpaObject.length_id, name = ColumnNamePrefix + auditFlowType_FIELDNAME)
-	private String auditFlowId;
 
-	public static final String lastFlowSyncTime_FIELDNAME = "lastFlowSyncTime";
-	@FieldDescribe("上次进行状态同步时间")
-	@Column( name = ColumnNamePrefix + lastFlowSyncTime_FIELDNAME)
-	private Date lastFlowSyncTime;
+	public void setCurrentProcessor(String currentProcessor) { this.currentProcessor = currentProcessor; }
 
 	public String getAuditFlowType() { return auditFlowType; }
 
 	public void setAuditFlowType(String auditFlowType) { this.auditFlowType = auditFlowType; }
 
-	public String getAuditFlowId() { return auditFlowId; }
+	public String getWorkId() { return workId; }
 
-	public void setAuditFlowId(String auditFlowId) { this.auditFlowId = auditFlowId; }
+	public void setWorkId(String workId) { this.workId = workId; }
 
 	public Date getLastFlowSyncTime() { return lastFlowSyncTime; }
 

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

@@ -165,67 +165,67 @@ public class AttendanceAppealInfo extends SliceJpaObject {
 	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + archiveTime_FIELDNAME )
 	private String archiveTime;
 
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processPerson1_FIELDNAME = "processPerson1";
-	@FieldDescribe("审批人一")
-	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPerson1_FIELDNAME)
-	private String processPerson1;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processPersonUnit1_FIELDNAME = "processPersonUnit1";
-	@FieldDescribe("审批人组织一")
-	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonUnit1_FIELDNAME)
-	private String processPersonUnit1;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processPersonTopUnit1_FIELDNAME = "processPersonTopUnit1";
-	@FieldDescribe("审批人顶层组织一")
-	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonTopUnit1_FIELDNAME)
-	private String processPersonTopUnit1;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String opinion1_FIELDNAME = "opinion1";
-	@FieldDescribe("审批意见一")
-	@Column( length = JpaObject.length_255B, name = ColumnNamePrefix + opinion1_FIELDNAME )
-	private String opinion1;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processTime1_FIELDNAME = "processTime1";
-	@FieldDescribe("审批日期一")
-	@Temporal(TemporalType.TIMESTAMP)
-	@Column( name = ColumnNamePrefix + processTime1_FIELDNAME)
-	private Date processTime1;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processPerson2_FIELDNAME = "processPerson2";
-	@FieldDescribe("审批人二")
-	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPerson2_FIELDNAME)
-	private String processPerson2;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processPersonUnit2_FIELDNAME = "processPersonUnit2";
-	@FieldDescribe("审批人组织二")
-	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonUnit2_FIELDNAME )
-	private String processPersonUnit2;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processPersonTopUnit2_FIELDNAME = "processPersonTopUnit2";
-	@FieldDescribe("审批人顶层组织二")
-	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonTopUnit2_FIELDNAME )
-	private String processPersonTopUnit2;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String opinion2_FIELDNAME = "opinion2";
-	@FieldDescribe("审批意见二")
-	@Column( length = JpaObject.length_255B, name = ColumnNamePrefix + opinion2_FIELDNAME )
-	private String opinion2;
-
-	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
-	public static final String processTime2_FIELDNAME = "processTime2";
-	@FieldDescribe("审批日期二")
-	@Temporal(TemporalType.TIMESTAMP)
-	@Column( name = ColumnNamePrefix + processTime2_FIELDNAME )
-	private Date processTime2;
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processPerson1_FIELDNAME = "processPerson1";
+////	@FieldDescribe("审批人一")
+//	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPerson1_FIELDNAME)
+//	private String processPerson1;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processPersonUnit1_FIELDNAME = "processPersonUnit1";
+////	@FieldDescribe("审批人组织一")
+//	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonUnit1_FIELDNAME)
+//	private String processPersonUnit1;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processPersonTopUnit1_FIELDNAME = "processPersonTopUnit1";
+////	@FieldDescribe("审批人顶层组织一")
+//	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonTopUnit1_FIELDNAME)
+//	private String processPersonTopUnit1;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String opinion1_FIELDNAME = "opinion1";
+////	@FieldDescribe("审批意见一")
+//	@Column( length = JpaObject.length_255B, name = ColumnNamePrefix + opinion1_FIELDNAME )
+//	private String opinion1;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processTime1_FIELDNAME = "processTime1";
+////	@FieldDescribe("审批日期一")
+//	@Temporal(TemporalType.TIMESTAMP)
+//	@Column( name = ColumnNamePrefix + processTime1_FIELDNAME)
+//	private Date processTime1;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processPerson2_FIELDNAME = "processPerson2";
+////	@FieldDescribe("审批人二")
+//	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPerson2_FIELDNAME)
+//	private String processPerson2;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processPersonUnit2_FIELDNAME = "processPersonUnit2";
+////	@FieldDescribe("审批人组织二")
+//	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonUnit2_FIELDNAME )
+//	private String processPersonUnit2;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processPersonTopUnit2_FIELDNAME = "processPersonTopUnit2";
+////	@FieldDescribe("审批人顶层组织二")
+//	@Column( length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + processPersonTopUnit2_FIELDNAME )
+//	private String processPersonTopUnit2;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String opinion2_FIELDNAME = "opinion2";
+////	@FieldDescribe("审批意见二")
+//	@Column( length = JpaObject.length_255B, name = ColumnNamePrefix + opinion2_FIELDNAME )
+//	private String opinion2;
+//
+//	//2020-05-15 新版本取消此属性,审批信息在AttendanceAppealAuditInfo里记录
+//	public static final String processTime2_FIELDNAME = "processTime2";
+////	@FieldDescribe("审批日期二")
+//	@Temporal(TemporalType.TIMESTAMP)
+//	@Column( name = ColumnNamePrefix + processTime2_FIELDNAME )
+//	private Date processTime2;
 
 	public String getDetailId() {
 		return detailId;
@@ -315,94 +315,6 @@ public class AttendanceAppealInfo extends SliceJpaObject {
 		this.appealDescription = appealDescription;
 	}
 
-	public String getProcessPerson1() {
-		return processPerson1;
-	}
-
-	public void setProcessPerson1(String processPerson1) {
-		this.processPerson1 = processPerson1;
-	}
-
-	public String getProcessPersonUnit1() {
-		return processPersonUnit1;
-	}
-
-	public void setProcessPersonUnit1(String processPersonUnit1) {
-		this.processPersonUnit1 = processPersonUnit1;
-	}
-
-	public String getProcessPersonTopUnit1() {
-		return processPersonTopUnit1;
-	}
-
-	public void setProcessPersonTopUnit1(String processPersonTopUnit1) {
-		this.processPersonTopUnit1 = processPersonTopUnit1;
-	}
-
-	public String getOpinion1() {
-		return opinion1;
-	}
-
-	public void setOpinion1(String opinion1) {
-		this.opinion1 = opinion1;
-	}
-
-	public Date getProcessTime1() {
-		return processTime1;
-	}
-
-	public void setProcessTime1(Date processTime1) {
-		this.processTime1 = processTime1;
-	}
-
-	public String getAppealDateString() {
-		return appealDateString;
-	}
-
-	public void setAppealDateString(String appealDateString) {
-		this.appealDateString = appealDateString;
-	}
-
-	public String getProcessPerson2() {
-		return processPerson2;
-	}
-
-	public void setProcessPerson2(String processPerson2) {
-		this.processPerson2 = processPerson2;
-	}
-
-	public String getProcessPersonUnit2() {
-		return processPersonUnit2;
-	}
-
-	public void setProcessPersonUnit2(String processPersonUnit2) {
-		this.processPersonUnit2 = processPersonUnit2;
-	}
-
-	public String getProcessPersonTopUnit2() {
-		return processPersonTopUnit2;
-	}
-
-	public void setProcessPersonTopUnit2(String processPersonTopUnit2) {
-		this.processPersonTopUnit2 = processPersonTopUnit2;
-	}
-
-	public String getOpinion2() {
-		return opinion2;
-	}
-
-	public void setOpinion2(String opinion2) {
-		this.opinion2 = opinion2;
-	}
-
-	public Date getProcessTime2() {
-		return processTime2;
-	}
-
-	public void setProcessTime2(Date processTime2) {
-		this.processTime2 = processTime2;
-	}
-
 	public String getCurrentProcessor() {
 		return currentProcessor;
 	}
@@ -458,4 +370,88 @@ public class AttendanceAppealInfo extends SliceJpaObject {
 	public void setArchiveTime(String archiveTime) {
 		this.archiveTime = archiveTime;
 	}
+
+	public String getAppealDateString() {
+		return appealDateString;
+	}
+
+	public void setAppealDateString(String appealDateString) {
+		this.appealDateString = appealDateString;
+	}
+
+//	public String getProcessPerson1() {
+//		return processPerson1;
+//	}
+//
+//	public void setProcessPerson1(String processPerson1) {
+//		this.processPerson1 = processPerson1;
+//	}
+//
+//	public String getProcessPersonUnit1() {
+//		return processPersonUnit1;
+//	}
+//
+//	public void setProcessPersonUnit1(String processPersonUnit1) {
+//		this.processPersonUnit1 = processPersonUnit1;
+//	}
+//
+//	public String getProcessPersonTopUnit1() {
+//		return processPersonTopUnit1;
+//	}
+//
+//	public void setProcessPersonTopUnit1(String processPersonTopUnit1) { this.processPersonTopUnit1 = processPersonTopUnit1; }
+//
+//	public String getOpinion1() {
+//		return opinion1;
+//	}
+//
+//	public void setOpinion1(String opinion1) {
+//		this.opinion1 = opinion1;
+//	}
+//
+//	public Date getProcessTime1() {
+//		return processTime1;
+//	}
+//
+//	public void setProcessTime1(Date processTime1) {
+//		this.processTime1 = processTime1;
+//	}
+//
+//	public String getProcessPerson2() {
+//		return processPerson2;
+//	}
+//
+//	public void setProcessPerson2(String processPerson2) {
+//		this.processPerson2 = processPerson2;
+//	}
+//
+//	public String getProcessPersonUnit2() {
+//		return processPersonUnit2;
+//	}
+//
+//	public void setProcessPersonUnit2(String processPersonUnit2) {
+//		this.processPersonUnit2 = processPersonUnit2;
+//	}
+//
+//	public String getProcessPersonTopUnit2() {
+//		return processPersonTopUnit2;
+//	}
+//
+//	public void setProcessPersonTopUnit2(String processPersonTopUnit2) { this.processPersonTopUnit2 = processPersonTopUnit2; }
+//
+//	public String getOpinion2() {
+//		return opinion2;
+//	}
+//
+//	public void setOpinion2(String opinion2) {
+//		this.opinion2 = opinion2;
+//	}
+//
+//	public Date getProcessTime2() {
+//		return processTime2;
+//	}
+//
+//	public void setProcessTime2(Date processTime2) {
+//		this.processTime2 = processTime2;
+//	}
 }

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

@@ -164,26 +164,38 @@ public class AttendanceDetail extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String offWorkTime;
 
-	public static final String onDutyTime_FIELDNAME = "onDutyTime";
-	@FieldDescribe("上班打卡时间")
-	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + onDutyTime_FIELDNAME)
-	@CheckPersist(allowEmpty = true)
-	private String onDutyTime;
-
 	public static final String middayRestStartTime_FIELDNAME = "middayRestStartTime";
 	@FieldDescribe("午休开始时间")
-	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + onDutyTime_FIELDNAME )
+	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + middayRestStartTime_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String middayRestStartTime;
 
 	public static final String middayRestEndTime_FIELDNAME = "middayRestEndTime";
 	@FieldDescribe("午休结束时间")
-	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + offDutyTime_FIELDNAME )
+	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + middayRestEndTime_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String middayRestEndTime;
 
+	public static final String onDutyTime_FIELDNAME = "onDutyTime";
+	@FieldDescribe("上班打卡签到时间")
+	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + onDutyTime_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String onDutyTime;
+
+	public static final String morningOffdutyTime_FIELDNAME = "morningOffdutyTime";
+	@FieldDescribe("上班下午打卡签退时间")
+	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + morningOffdutyTime_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String morningOffdutyTime;
+
+	public static final String afternoonOnDutyTime_FIELDNAME = "afternoonOnDutyTime";
+	@FieldDescribe("下午上班打卡签到时间")
+	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + afternoonOnDutyTime_FIELDNAME )
+	@CheckPersist(allowEmpty = true)
+	private String afternoonOnDutyTime;
+
 	public static final String offDutyTime_FIELDNAME = "offDutyTime";
-	@FieldDescribe("下班打卡时间")
+	@FieldDescribe("下班打卡签退时间")
 	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + offDutyTime_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String offDutyTime;
@@ -321,6 +333,14 @@ public class AttendanceDetail extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String archiveTime;
 
+	public String getMorningOffdutyTime() { return morningOffdutyTime; }
+
+	public void setMorningOffdutyTime(String morningOffdutyTime) { this.morningOffdutyTime = morningOffdutyTime; }
+
+	public String getAfternoonOnDutyTime() { return afternoonOnDutyTime; }
+
+	public void setAfternoonOnDutyTime(String afternoonOnDutyTime) { this.afternoonOnDutyTime = afternoonOnDutyTime; }
+
 	/**
 	 * 获取是否工时不足
 	 * 

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

@@ -106,7 +106,7 @@ public class AttendanceScheduleSetting extends SliceJpaObject {
 
 	public static final String signProxy_FIELDNAME = "signProxy";
 	@FieldDescribe("打卡策略:1-两次打卡(上午上班,下午下班) 2-三次打卡(上午上班,下午下班加中午一次共三次) 3-四次打卡(上午下午都打上班下班卡)")
-	@Column( name = ColumnNamePrefix + lateStartTime_FIELDNAME )
+	@Column( name = ColumnNamePrefix + signProxy_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private Integer signProxy = 0;
 
@@ -136,7 +136,7 @@ public class AttendanceScheduleSetting extends SliceJpaObject {
 
 	public static final String leaveEarlyStartTimeMorning_FIELDNAME = "leaveEarlyStartTimeMorning";
 	@FieldDescribe("上午早退起算时间")
-	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + leaveEarlyStartTime_FIELDNAME )
+	@Column( length = JpaObject.length_32B, name = ColumnNamePrefix + leaveEarlyStartTimeMorning_FIELDNAME )
 	@CheckPersist(allowEmpty = true)
 	private String leaveEarlyStartTimeMorning;
 

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

@@ -71,7 +71,6 @@ public class AttendanceSetting extends SliceJpaObject {
 	public static final String configValue_FIELDNAME = "configValue";
 	@FieldDescribe("配置内容")
 	@Column( length = JpaObject.length_255B, name = ColumnNamePrefix + configValue_FIELDNAME )
-	@CheckPersist(allowEmpty = false)
 	private String configValue;
 
 	public static final String valueType_FIELDNAME = "valueType";

+ 126 - 198
o2server/x_attendance_core_entity/src/main/java/com/x/attendance/entity/DateOperation.java

@@ -8,8 +8,7 @@ import java.util.Date;
 import java.util.List;
 
 
-
-public class DateOperation {
+class DateOperation {
 	/**
 	 * 根据样式得到格式化对象SimpleDateFormat
 	 * @param date
@@ -150,27 +149,26 @@ public class DateOperation {
 		}
 		return dateString;
 	}
-	
-	/**
-	 * 得到某日期加上或减去天数后的日期,day为负数时减去
-	 * 
-	 * @param date
-	 * @param month
-	 * @return "yyyy-MM-dd"
-	 * @throws Exception 
+
+    /**
+     * 得到某日期加上或减去天数后的日期,day为负数时减去
+	 * @param dateString
+     * @param day
+     * @param style
+     * @return
+     * @throws Exception
 	 */
 	public  String getDayAdd(String dateString, int day, String style) throws Exception {
 		Date date = getDateFromString(dateString, style);
 		return getDayAdd(date, day);
 	}
-	
-	/**
-	 * 得到某日期加上或减去天数后的日期,day为负数时减去
-	 * 
+
+    /**
+     * 得到某日期加上或减去天数后的日期,day为负数时减去
 	 * @param date
-	 * @param month
-	 * @return "yyyy-MM-dd"
-	 */
+     * @param day
+     * @return
+     */
 	public  String getDayAdd(Date date, int day) {
 		Calendar calendar = Calendar.getInstance();
 		calendar.setTime(date);
@@ -191,27 +189,25 @@ public class DateOperation {
 		calendar.add(Calendar.MONTH, month);
 		return format1.format(calendar.getTime());
 	}
-	
-	/**
-	 * 得到某日期加上或减去分钟后的日期,min为负数时减去
-	 * 
+
+    /**
+     * 得到某日期加上或减去分钟后的日期,min为负数时减去
 	 * @param date
-	 * @param month
-	 * @return "yyyy-MM-dd HH:mi:ss"
-	 */
+     * @param min
+     * @return
+     */
 	public  String getMinutesAdd(Date date, int min) {
 		Calendar calendar = Calendar.getInstance();
 		calendar.setTime(date);
 		calendar.add(Calendar.MINUTE, min);
 		return format3.format(calendar.getTime());
 	}
-	/**
-	 * 得到某日期的日
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 */
+
+    /**
+     * 得到某日期的日
+	 * @param date
+     * @return
+     */
 	public  String getDay(Date date) {
 		try{
 			return format10.format(date);
@@ -228,13 +224,12 @@ public class DateOperation {
 		}
 		return Integer.parseInt(result);
 	}
-	/**
-	 * 得到某日期的月份
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 */
+
+    /**
+     * 得到某日期的月份
+	 * @param date
+     * @return
+     */
 	public  String getMonth(Date date) {
 		try{
 			return format9.format(date);
@@ -253,12 +248,10 @@ public class DateOperation {
 	}
 
 	/**
-	 * 得到某日期的年份
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 */
+     * 得到某日期的年份
+	 * @param date
+     * @return
+     */
 	public  String getYear(Date date) {
 		try{
 			return format8.format(date);
@@ -275,13 +268,12 @@ public class DateOperation {
 		}
 		return Integer.parseInt(result);
 	}
-	/**
-	 * 得到某日期的小时
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 */
+
+    /**
+     * 得到某日期的小时
+	 * @param date
+     * @return
+     */
 	public  String getHour(Date date) {
 		try{
 			return format11.format(date);
@@ -289,48 +281,43 @@ public class DateOperation {
 			return "0";
 		}
 	}
-	/**
-	 * 得到某日期的分钟
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 */
+
+    /**
+     * 得到某日期的分钟
+	 * @param date
+     * @return
+     */
 	public  String getMinites(Date date) {
 		return format12.format(date);
 	}
-	/**
-	 * 得到某日期的秒
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 */
+
+    /**
+     * 得到某日期的秒
+	 * @param date
+     * @return
+     */
 	public  String getSeconds(Date date) {
 		return format13.format(date);
 	}
-	/**
-	 * 得到某年有多少天
-	 * 
-	 * @param String
-	 *            date "yyyy-MM-dd"
-	 * @return
-	 * @throws ParseException
+
+    /**
+     * 得到某年有多少天
+	 * @param date
+     * @return
+     * @throws ParseException
 	 */
 	@SuppressWarnings("static-access")
-	public int getDaysForYear(String date) throws ParseException {
+	public  int getDaysForYear(String date) throws ParseException {
 		Calendar calendar = Calendar.getInstance();
-		calendar.setTime( format1.parse(date) );
+		calendar.setTime(format1.parse(date));
 		return calendar.get(calendar.DAY_OF_YEAR);
 	}
 
 	/**
-	 * 得到某年有多少天
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 * @throws ParseException
+     * 得到某年有多少天
+	 * @param date
+     * @return
+     * @throws ParseException
 	 */
 	@SuppressWarnings("static-access")
 	public  int getDaysForYear(Date date) throws ParseException {
@@ -340,12 +327,10 @@ public class DateOperation {
 	}
 
 	/**
-	 * 得到某年有多少天
-	 * 
-	 * @param String
-	 *            year "yyyy"
-	 * @return
-	 * @throws ParseException
+     * 得到某年有多少天
+	 * @param year
+     * @return
+     * @throws ParseException
 	 */
 	@SuppressWarnings("static-access")
 	public  int getDaysForYear_YYYY(String year) throws ParseException {
@@ -355,12 +340,10 @@ public class DateOperation {
 	}
 
 	/**
-	 * 得到某月有多少天
-	 * 
-	 * @param String
-	 *            date "yyyy-MM-dd"
-	 * @return
-	 * @throws ParseException
+     * 得到某月有多少天
+	 * @param date
+     * @return
+     * @throws ParseException
 	 */
 	public  int getDaysForMonth(String date) throws ParseException {
 		Calendar calendar = Calendar.getInstance();
@@ -369,12 +352,10 @@ public class DateOperation {
 	}
 
 	/**
-	 * 得到某月有多少天
-	 * 
-	 * @param String
-	 *            date "yyyy-MM"
-	 * @return
-	 * @throws ParseException
+     * 得到某月有多少天
+	 * @param date
+     * @return
+     * @throws ParseException
 	 */
 	@SuppressWarnings("static-access")
 	public  int getDaysForMonth_MM(String date) throws ParseException {
@@ -384,12 +365,10 @@ public class DateOperation {
 	}
 
 	/**
-	 * 得到某月有多少天
-	 * 
-	 * @param Date
-	 *            date
-	 * @return
-	 * @throws ParseException
+     * 得到某月有多少天
+	 * @param date
+     * @return
+     * @throws ParseException
 	 */
 	public  int getDaysForMonth(Date date) throws ParseException {
 		Calendar calendar = Calendar.getInstance();
@@ -435,8 +414,9 @@ public class DateOperation {
 	 * @param date1 yyyy-MM-dd HH:mm:ss
 	 * @param date2 yyyy-MM-dd HH:mm:ss
 	 * @return
+	 * @throws ParseException 
 	 */
-	public  long getDeff(String date1,String date2) {
+	public  long getDeff(String date1,String date2) throws ParseException {
 		long dayNumber = 0;
 		// 1小时=60分钟=3600秒=3600000
 		long mins = 60L * 1000L;
@@ -451,13 +431,9 @@ public class DateOperation {
 		}else{
 			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 		}
-		try {
-			java.util.Date d1 = df.parse(date1);
-			java.util.Date d2 = df.parse(date2);
-			dayNumber = (d2.getTime() - d1.getTime()) / mins;
-		} catch (Exception e) {
-			//logger.error( "系统获取得到两个时间之前的分差发生异常",  e);
-		}
+		Date d1 = df.parse(date1);
+		Date d2 = df.parse(date2);
+		dayNumber = (d2.getTime() - d1.getTime()) / mins;
 		return dayNumber;
 	}
 	/**
@@ -468,24 +444,18 @@ public class DateOperation {
 	 */
 	public long getDeff(Date date1,Date date2) {
 		long dayNumber = 0;
-		// 1小时=60分钟=3600秒=3600000
 		long mins = 60L * 1000L;
-		// long day= 24L * 60L * 60L * 1000L;计算天数之差
-		try {
-			dayNumber = (date2.getTime() - date1.getTime()) / mins;
-		} catch (Exception e) {
-			//logger.error( "系统获取得到两个时间之前的分差发生异常",  e);
-		}
+		dayNumber = (date2.getTime() - date1.getTime()) / mins;
 		return dayNumber;
 	}
-	/**
-	 * 
-	 * 日期格式转换
-	 * 从YYYY-MM-DD转换到YYYYMMDD
-	 * @param date
-	 * @throws ParseException 
+
+    /**
+     * 日期格式转换 从YYYY-MM-DD转换到YYYYMMDD
+	 * @param dateString
+     * @return
+     * @throws ParseException
 	 */
-	public  String changeDateFormat(String dateString){
+	public  String changeDateFormat(String dateString) throws ParseException{
 		Date date;
 		String reslut = null;
 		try {
@@ -495,14 +465,8 @@ public class DateOperation {
 			date = format1.parse(dateString);
 			reslut = format5.format(date);
 		} catch (ParseException e) {
-			try {
-				date = format1.parse("0000-00-00");
-			} catch (ParseException e1) {
-				//logger.error( "系统日期格式转换发生异常",  e1);
-			}
-			//logger.error( "系统日期格式转换发生异常",  e);
+			date = format1.parse("0000-00-00");
 		}
-		
 		return reslut;
 	}
 	
@@ -539,41 +503,27 @@ public class DateOperation {
 	public  final SimpleDateFormat format14 = new SimpleDateFormat("yyyy-MM");
 	
 	
-	public  String getStartOfWeek(String dateString){
+	public  String getStartOfWeek(String dateString) throws Exception{
 		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
-		try {
-			Date date = format.parse(dateString);
-			Calendar cal = Calendar.getInstance();
-			cal.setTime(date);
-			cal.setFirstDayOfWeek(Calendar.MONDAY);
-			int tmp = cal.get(Calendar.DAY_OF_WEEK) - 1;
-			if (0 == tmp) {
-				tmp = 7;
-			}
-			cal.add(Calendar.DATE, -(tmp-1));
-			return getDateStringFromDate(cal.getTime(), "yyyy-MM-dd") + " 00:00:00";
-		} catch (ParseException e) {
-			//logger.error( "系统getStartOfWeek日期格式转换发生异常",  e);
-		} catch (Exception e) {
-			//logger.error( "系统getStartOfWeek发生异常",  e);
+		Date date = format.parse(dateString);
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		cal.setFirstDayOfWeek(Calendar.MONDAY);
+		int tmp = cal.get(Calendar.DAY_OF_WEEK) - 1;
+		if (0 == tmp) {
+			tmp = 7;
 		}
-		return null;
+		cal.add(Calendar.DATE, -(tmp-1));
+		return getDateStringFromDate(cal.getTime(), "yyyy-MM-dd") + " 00:00:00";
 	}
 	
-	public  String getEndOfWeek(String dateString){
-		try {
-			Date date = getDateFromString(getStartOfWeek(dateString), "yyyy-MM-dd HH:mm:ss");
-			Calendar cal = Calendar.getInstance();
-			cal.setTime(date);
-			cal.setFirstDayOfWeek(Calendar.MONDAY);
-			cal.add(Calendar.DATE, 6);
-			return getDateStringFromDate(cal.getTime(), "yyyy-MM-dd") + " 23:59:59";
-		} catch (ParseException e) {
-			e.printStackTrace();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-		return null;
+	public  String getEndOfWeek(String dateString) throws Exception{
+		Date date = getDateFromString(getStartOfWeek(dateString), "yyyy-MM-dd HH:mm:ss");
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		cal.setFirstDayOfWeek(Calendar.MONDAY);
+		cal.add(Calendar.DATE, 6);
+		return getDateStringFromDate(cal.getTime(), "yyyy-MM-dd") + " 23:59:59";
 	}
 	
 	
@@ -588,11 +538,7 @@ public class DateOperation {
 	public String getDateCNString( String dateString, String style ) throws Exception{
 		StringBuffer ch_date_string = new StringBuffer();
 		Date _date = null;
-		try{
-			_date = getDateFromString( dateString, style );
-		}catch(Exception e){
-			//logger.error( "系统getDateCNString日期格式转换发生异常",  e);
-		}
+		_date = getDateFromString( dateString, style );
 		if(_date == null ){
 			_date = new Date();
 		}
@@ -624,11 +570,7 @@ public class DateOperation {
 	public String getDateCNString2( String dateString, String style ) throws Exception{
 		StringBuffer ch_date_string = new StringBuffer();
 		Date _date = null;
-		try{
-			_date = getDateFromString( dateString, style );
-		}catch(Exception e){
-		//	logger.error( "系统getDateCNString2日期格式转换发生异常",  e);
-		}
+		_date = getDateFromString( dateString, style );
 		if(_date == null ){
 			_date = new Date();
 		}
@@ -658,28 +600,14 @@ public class DateOperation {
 	 * 结果从1开始
 	 * @param dateString yyyy-mm-dd
 	 * @return
+	 * @throws Exception 
 	 */
-	public  int getWeekNumOfYear( String dateString ){
-		try {
-			Date date = getDateFromString( dateString , "yyyy-MM-dd");
-			Calendar cal = Calendar.getInstance();
-			cal.setTime(date);
-			cal.setFirstDayOfWeek(2);//设置每周的第一天是星期一
-	        //月份有问题(这里的月份开始计数为0)
-	        //本年的第几天,在计算时间间隔的时候有用
-	        //System.out.println("一年中的天数:" + cal.get(Calendar.DAY_OF_YEAR));
-	        //System.out.println("一年中的周数:" + cal.get(Calendar.WEEK_OF_YEAR));
-	        //即本月的第几周
-	        //System.out.println("一月中的周数:" + cal.get(Calendar.WEEK_OF_MONTH));
-	        //即一周中的第几天(这里是以周日为第一天的)
-	        //System.out.println("一周中的天数:" + cal.get(Calendar.DAY_OF_WEEK));
-			return cal.get(Calendar.WEEK_OF_YEAR);
-		} catch (ParseException e) {
-			//logger.error( "系统getWeekNumOfYear日期格式转换发生异常",  e);
-		} catch (Exception e) {
-			//logger.error( "系统getWeekNumOfYear发生异常",  e);
-		}
-		return -1;
+	public  int getWeekNumOfYear( String dateString ) throws Exception{
+		Date date = getDateFromString( dateString , "yyyy-MM-dd");
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		cal.setFirstDayOfWeek(2); //设置每周的第一天是星期一
+		return cal.get(Calendar.WEEK_OF_YEAR);
 	}
 	
 	/**
@@ -687,7 +615,7 @@ public class DateOperation {
 	 * @param recordDate
 	 * @return
 	 */
-	public boolean isWeekend(Date recordDate) {
+	public boolean isWeekend( Date recordDate ) {
 		Calendar cal = Calendar.getInstance();
 	    cal.setTime( recordDate );
 	    if(cal.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY||cal.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
@@ -751,7 +679,7 @@ public class DateOperation {
 		}
 		return result;
 	}
-
+	
 	/**
 	 * 获取日期所在月份的第一天
 	 * @param recordDate
@@ -803,7 +731,7 @@ public class DateOperation {
 	 * @throws Exception 
 	 */
 	public Date getLastDateInMonth(Date recordDate) throws Exception {
-		Date lastDate = getLastDayOfMonth(recordDate);
+		Date lastDate = getLastDayOfMonth( recordDate );
 		return getDateFromString( getDateStringFromDate( lastDate, "yyyy-MM-dd") );
 	}