Browse Source

钉钉同步代码

fancy 5 years ago
parent
commit
f63b5d0c50

+ 10 - 19
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/Business.java

@@ -1,24 +1,6 @@
 package com.x.attendance.assemble.control;
 
-import com.x.attendance.assemble.control.factory.AttendanceAdminFactory;
-import com.x.attendance.assemble.control.factory.AttendanceAppealInfoFactory;
-import com.x.attendance.assemble.control.factory.AttendanceDetailFactory;
-import com.x.attendance.assemble.control.factory.AttendanceDetailMobileFactory;
-import com.x.attendance.assemble.control.factory.AttendanceDetailStatisticFactory;
-import com.x.attendance.assemble.control.factory.AttendanceEmployeeConfigFactory;
-import com.x.attendance.assemble.control.factory.AttendanceImportFileInfoFactory;
-import com.x.attendance.assemble.control.factory.AttendanceScheduleSettingFactory;
-import com.x.attendance.assemble.control.factory.AttendanceSelfHolidayFactory;
-import com.x.attendance.assemble.control.factory.AttendanceSettingFactory;
-import com.x.attendance.assemble.control.factory.AttendanceStatisticRequireLogFactory;
-import com.x.attendance.assemble.control.factory.AttendanceStatisticalCycleFactory;
-import com.x.attendance.assemble.control.factory.AttendanceWorkDayConfigFactory;
-import com.x.attendance.assemble.control.factory.AttendanceWorkPlaceFactory;
-import com.x.attendance.assemble.control.factory.StatisticPersonForMonthFactory;
-import com.x.attendance.assemble.control.factory.StatisticTopUnitForDayFactory;
-import com.x.attendance.assemble.control.factory.StatisticTopUnitForMonthFactory;
-import com.x.attendance.assemble.control.factory.StatisticUnitForDayFactory;
-import com.x.attendance.assemble.control.factory.StatisticUnitForMonthFactory;
+import com.x.attendance.assemble.control.factory.*;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.organization.core.express.Organization;
 
@@ -34,6 +16,8 @@ public class Business {
 		return this.emc;
 	}
 
+	//钉钉同步数据处理
+	private DingdingAttendanceFactory dingdingAttendanceFactory;
 	// 人员组织业务处理类
 	private Organization organization;
 	// 系统配置业务处理类
@@ -74,6 +58,13 @@ public class Business {
 
 	private AttendanceDetailStatisticFactory attendanceDetailStatisticFactory;
 
+	public DingdingAttendanceFactory dingdingAttendanceFactory() throws Exception {
+		if (null == this.dingdingAttendanceFactory) {
+			this.dingdingAttendanceFactory = new DingdingAttendanceFactory(this);
+		}
+		return this.dingdingAttendanceFactory;
+	}
+
 	public AttendanceWorkPlaceFactory attendanceWorkPlaceFactory() throws Exception {
 		if (null == this.attendanceWorkPlaceFactory) {
 			this.attendanceWorkPlaceFactory = new AttendanceWorkPlaceFactory(this);

+ 260 - 13
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/DingdingAttendanceQueue.java

@@ -1,9 +1,14 @@
 package com.x.attendance.assemble.control;
 
+import com.x.attendance.assemble.control.exception.DingDingRequestException;
+import com.x.attendance.entity.AttendanceDingtalkDetail;
 import com.x.attendance.entity.DingdingQywxSyncRecord;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
 import com.x.base.core.project.Application;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.connection.HttpConnection;
 import com.x.base.core.project.gson.GsonPropertyObject;
@@ -11,9 +16,12 @@ import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.organization.Person;
 import com.x.base.core.project.queue.AbstractQueue;
+import com.x.base.core.project.tools.DateTools;
 import com.x.base.core.project.x_organization_assemble_control;
 
+import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class DingdingAttendanceQueue extends AbstractQueue<DingdingQywxSyncRecord> {
 
@@ -22,30 +30,104 @@ public class DingdingAttendanceQueue extends AbstractQueue<DingdingQywxSyncRecor
     @Override
     protected void execute(DingdingQywxSyncRecord record) throws Exception {
         logger.info("开始执行钉钉打卡数据同步," + record.getWay());
-
+        if (DingdingQywxSyncRecord.syncType_dingding.equals(record.getType())) {
+            dingdingSync(record);
+        }else {
+            logger.info("其它类型:");
+        }
     }
 
-    private void dingdingSync() throws Exception {
-        try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-            Business business = new Business(emc);
+    private void dingdingSync(DingdingQywxSyncRecord record) throws Exception {
             Application app = ThisApplication.context().applications().randomWithWeight(x_organization_assemble_control.class.getName());
             //开始分页查询人员
             boolean hasNextPerson = true;
+            int personPageSize = 50;
             String uri = "person/list/(0)/next/50";
             String dingdingUrl = "https://oapi.dingtalk.com/attendance/list?access_token="+ Config.dingding().corpAccessToken();
 
             while (hasNextPerson) {
+                logger.info("查询人员 uri:" + uri);
                 List<Person> list = ThisApplication.context().applications().getQuery(false, app, uri).getDataAsList(Person.class);
                 if (list != null && list.size() > 0) {
-                    DingdingAttendancePost post = new DingdingAttendancePost();
-
+                    //钉钉用户id
+                    List<String> ddUsers = list.stream().map(Person::getDingdingId).collect(Collectors.toList());
+                    //week
+                    Date today = new Date();
+                    today = DateTools.floorDate(today, null);
+                    Date sevenDayBefore = DateTools.addDay(today, -7);
+                    //分页查询
+                    int page = 0;
+                    boolean hasMoreResult = true;
+                    while (hasMoreResult) {
+                        DingdingAttendancePost post = new DingdingAttendancePost();
+                        //post传入 时间(时间间隔不能超过7天) 人员(人员数量不能超过50个)
+                        post.setLimit(50L);
+                        post.setOffset(page * 50L);//从0开始翻页
+                        post.setWorkDateFrom(DateTools.format(sevenDayBefore, DateTools.format_yyyyMMddHHmmss));
+                        post.setWorkDateTo(DateTools.format(today, DateTools.format_yyyyMMddHHmmss));
+                        post.setUserIdList(ddUsers);
+                        String body = post.toString();
+                        logger.info("查询钉钉打卡结果:"+body);
+                        DingdingAttendanceResult result = HttpConnection.postAsObject(dingdingUrl, null, post.toString(), DingdingAttendanceResult.class);
+                        if (result.errcode != null && result.errcode == 0) {
+                            saveDingdingRecord(result.getRecordresult());
+                            if (result.hasMore) {
+                                page++;
+                            } else {
+                                logger.info("同步钉钉考勤结束。。。。。。。。。。。。。。。。");
+                                hasMoreResult = false;
+                            }
+                        } else {
+                            //请求结果异常 结束
+                            logger.error(new DingDingRequestException(result.errmsg));
+                            hasMoreResult = false;
+                        }
+                    }
+                    //是否还有更多用户
+                    if (list.size() < personPageSize) {
+                        logger.info("同步钉钉考勤 没有更多用户了,结束。。。。。。。。。。。。。。。");
+                        hasNextPerson = false;
+                        updateSyncRecord(record, null);
+                    }else {
+                        //还有更多用户继续查询
+                        uri = "person/list/"+list.get(list.size()-1).getDistinguishedName()+"/next/50";
+                    }
                 }else {
                     //没有用户查询到结束
-                    logger.info("查询不到用户了,结束。。。。。。。。。。。。。。。");
+                    logger.info("同步钉钉考勤 查询不到用户了,结束。。。。。。。。。。。。。。。");
                     hasNextPerson = false;
+                    updateSyncRecord(record, null);
                 }
             }
 
+    }
+
+    private void saveDingdingRecord(List<DingdingAttendanceResultItem> list) throws Exception {
+        if (list != null && !list.isEmpty()) {
+            try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+                emc.beginTransaction(AttendanceDingtalkDetail.class);
+                for (int i = 0; i < list.size(); i++) {
+                    DingdingAttendanceResultItem item = list.get(i);
+                    AttendanceDingtalkDetail detail = DingdingAttendanceResultItem.copier.copy(item);
+                    detail.setDdId(item.getId());
+                    emc.persist(detail);
+                }
+                emc.commit();
+            }
+        }
+    }
+
+    private void updateSyncRecord(DingdingQywxSyncRecord record, String errMsg) throws Exception {
+        try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+            emc.beginTransaction(DingdingQywxSyncRecord.class);
+            record.setEndTime(new Date());
+            if (errMsg == null || errMsg.isEmpty()) {
+                record.setExceptionMessage(errMsg);
+                record.setStatus(DingdingQywxSyncRecord.status_error);
+            }else {
+                record.setStatus(DingdingQywxSyncRecord.status_end);
+            }
+            emc.commit();
         }
     }
 
@@ -61,8 +143,8 @@ public class DingdingAttendanceQueue extends AbstractQueue<DingdingQywxSyncRecor
         private String workDateFrom;
         private String workDateTo;
         private List<String> userIdList;
-        private Integer offset;
-        private Integer limit;
+        private Long offset;
+        private Long limit;
 
         public String getWorkDateFrom() {
             return workDateFrom;
@@ -88,20 +170,185 @@ public class DingdingAttendanceQueue extends AbstractQueue<DingdingQywxSyncRecor
             this.userIdList = userIdList;
         }
 
-        public Integer getOffset() {
+        public Long getOffset() {
             return offset;
         }
 
-        public void setOffset(Integer offset) {
+        public void setOffset(Long offset) {
             this.offset = offset;
         }
 
-        public Integer getLimit() {
+        public Long getLimit() {
             return limit;
         }
 
-        public void setLimit(Integer limit) {
+        public void setLimit(Long limit) {
             this.limit = limit;
         }
     }
+
+    public static class DingdingAttendanceResult extends GsonPropertyObject {
+        private Integer errcode;
+        private String errmsg;
+        private Boolean hasMore;
+        private List<DingdingAttendanceResultItem> recordresult;
+
+        public Integer getErrcode() {
+            return errcode;
+        }
+
+        public void setErrcode(Integer errcode) {
+            this.errcode = errcode;
+        }
+
+        public String getErrmsg() {
+            return errmsg;
+        }
+
+        public void setErrmsg(String errmsg) {
+            this.errmsg = errmsg;
+        }
+
+        public Boolean getHasMore() {
+            return hasMore;
+        }
+
+        public void setHasMore(Boolean hasMore) {
+            this.hasMore = hasMore;
+        }
+
+        public List<DingdingAttendanceResultItem> getRecordresult() {
+            return recordresult;
+        }
+
+        public void setRecordresult(List<DingdingAttendanceResultItem> recordresult) {
+            this.recordresult = recordresult;
+        }
+    }
+
+    public static class DingdingAttendanceResultItem extends GsonPropertyObject {
+
+        private static final long serialVersionUID = 1618421987561110713L;
+
+        static WrapCopier<DingdingAttendanceResultItem, AttendanceDingtalkDetail> copier = WrapCopierFactory.wi(DingdingAttendanceResultItem.class,
+                AttendanceDingtalkDetail.class, null, JpaObject.FieldsUnmodify);
+
+        private long id;
+        private long ddId;
+        private String userId;
+        private long baseCheckTime;
+        private long userCheckTime;
+        private long workDate;
+        private String timeResult;
+        private String checkType;
+        private String locationResult;
+        private String sourceType;
+        private long groupId;
+        private long planId;
+        private long recordId;
+
+        public long getId() {
+            return id;
+        }
+
+        public void setId(long id) {
+            this.id = id;
+        }
+
+        public long getDdId() {
+            return ddId;
+        }
+
+        public void setDdId(long ddId) {
+            this.ddId = ddId;
+        }
+
+        public String getUserId() {
+            return userId;
+        }
+
+        public void setUserId(String userId) {
+            this.userId = userId;
+        }
+
+        public long getBaseCheckTime() {
+            return baseCheckTime;
+        }
+
+        public void setBaseCheckTime(long baseCheckTime) {
+            this.baseCheckTime = baseCheckTime;
+        }
+
+        public long getUserCheckTime() {
+            return userCheckTime;
+        }
+
+        public void setUserCheckTime(long userCheckTime) {
+            this.userCheckTime = userCheckTime;
+        }
+
+        public long getWorkDate() {
+            return workDate;
+        }
+
+        public void setWorkDate(long workDate) {
+            this.workDate = workDate;
+        }
+
+        public String getTimeResult() {
+            return timeResult;
+        }
+
+        public void setTimeResult(String timeResult) {
+            this.timeResult = timeResult;
+        }
+
+        public String getCheckType() {
+            return checkType;
+        }
+
+        public void setCheckType(String checkType) {
+            this.checkType = checkType;
+        }
+
+        public String getLocationResult() {
+            return locationResult;
+        }
+
+        public void setLocationResult(String locationResult) {
+            this.locationResult = locationResult;
+        }
+
+        public String getSourceType() {
+            return sourceType;
+        }
+
+        public void setSourceType(String sourceType) {
+            this.sourceType = sourceType;
+        }
+
+        public long getGroupId() {
+            return groupId;
+        }
+
+        public void setGroupId(long groupId) {
+            this.groupId = groupId;
+        }
+
+        public long getPlanId() {
+            return planId;
+        }
+
+        public void setPlanId(long planId) {
+            this.planId = planId;
+        }
+
+        public long getRecordId() {
+            return recordId;
+        }
+
+        public void setRecordId(long recordId) {
+            this.recordId = recordId;
+        }
+    }
 }

+ 12 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/exception/DingDingRequestException.java

@@ -0,0 +1,12 @@
+package com.x.attendance.assemble.control.exception;
+
+import com.x.base.core.project.exception.PromptException;
+
+public class DingDingRequestException extends PromptException {
+
+    private static final long serialVersionUID = -2160589718239895222L;
+
+    public DingDingRequestException(String errorMsg) {
+        super(errorMsg);
+    }
+}

+ 35 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/DingdingAttendanceFactory.java

@@ -0,0 +1,35 @@
+package com.x.attendance.assemble.control.factory;
+
+import com.x.attendance.assemble.control.AbstractFactory;
+import com.x.attendance.assemble.control.Business;
+import com.x.attendance.entity.DingdingQywxSyncRecord;
+import com.x.attendance.entity.DingdingQywxSyncRecord_;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.List;
+
+public class DingdingAttendanceFactory extends AbstractFactory {
+
+    public DingdingAttendanceFactory(Business business) throws Exception {
+        super(business);
+    }
+
+    /**
+     * 查询所有钉钉同步记录
+     * @return
+     * @throws Exception
+     */
+    public List<DingdingQywxSyncRecord> findAllDingdingSyncRecord() throws Exception {
+        EntityManager em = this.entityManagerContainer().get(DingdingQywxSyncRecord.class);
+        CriteriaBuilder cb = em.getCriteriaBuilder();
+        CriteriaQuery<DingdingQywxSyncRecord> query = cb.createQuery(DingdingQywxSyncRecord.class);
+        Root<DingdingQywxSyncRecord> root = query.from(DingdingQywxSyncRecord.class);
+        Predicate p = cb.equal(root.get(DingdingQywxSyncRecord_.type), DingdingQywxSyncRecord.syncType_dingding);
+        query.select(root).where(p).orderBy(cb.desc(root.get(DingdingQywxSyncRecord_.startTime)));
+        return em.createQuery(query).getResultList();
+    }
+}

+ 47 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/dingding/ActionListDingdingSyncRecord.java

@@ -0,0 +1,47 @@
+package com.x.attendance.assemble.control.jaxrs.dingding;
+
+import com.x.attendance.assemble.control.Business;
+import com.x.attendance.entity.DingdingQywxSyncRecord;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ActionListDingdingSyncRecord extends BaseAction {
+
+    private static final Logger logger = LoggerFactory.getLogger(ActionListDingdingSyncRecord.class);
+
+    public ActionResult<List<Wo>> execute() throws Exception {
+        ActionResult<List<Wo>> result = new ActionResult<>();
+        try ( EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+            Business business = new Business(emc);
+            List<DingdingQywxSyncRecord> list = business.dingdingAttendanceFactory().findAllDingdingSyncRecord();
+            if (list != null && !list.isEmpty()) {
+                List<Wo> wos = list.stream().map(record -> {
+                    Wo wo = new Wo();
+                    try {
+                        wo = Wo.copier.copy(record, wo);
+                    }catch (Exception e) {
+                        logger.error(e);
+                    }
+                    return wo;
+                }).collect(Collectors.toList());
+                result.setData(wos);
+            }
+        }
+        return result;
+    }
+
+
+    public static class Wo extends DingdingQywxSyncRecord {
+        static final WrapCopier<DingdingQywxSyncRecord, Wo> copier =
+                WrapCopierFactory.wo(DingdingQywxSyncRecord.class, Wo.class, null, JpaObject.FieldsInvisible);
+    }
+}

+ 17 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/dingding/DingdingAttendanceAction.java

@@ -18,6 +18,7 @@ import javax.ws.rs.container.AsyncResponse;
 import javax.ws.rs.container.Suspended;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import java.util.List;
 
 
 @Path("dingding")
@@ -68,6 +69,22 @@ public class DingdingAttendanceAction extends StandardJaxrsAction {
         asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
     }
 
+    @JaxrsMethodDescribe(value = "查询钉钉同步记录信息", action = ActionListDingdingSyncRecord.class)
+    @GET
+    @Path("sync/list")
+    @Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void listDingdingSyncRecord(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request) {
+        ActionResult<List<ActionListDingdingSyncRecord.Wo>> result = new ActionResult<>();
+        EffectivePerson effectivePerson = this.effectivePerson(request);
+        try {
+            result = new ActionListDingdingSyncRecord().execute();
+        }catch (Exception e) {
+            logger.error(e, effectivePerson, request, null);
+            result.error(e);
+        }
+        asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+    }
 
 
 }

+ 28 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/DateTools.java

@@ -609,5 +609,33 @@ public class DateTools {
 		return dayForWeek; 
 	}
 
+
+	/**
+	 * 指定的日期,添加指定的天数
+	 *
+	 * @param date
+	 * @param dayCount
+	 * @return
+	 */
+	public static Date addDay(Date date, int dayCount) {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		calendar.add(Calendar.DAY_OF_YEAR, dayCount);// 指定的时间上加上n天
+		date = calendar.getTime();
+		return date;
+	}
+
+	public static void main(String[] args) {
+		try {
+			Date today = new Date();
+			today = DateTools.floorDate(today, null);
+			Date sevenDayBefore = DateTools.addDay(today, -7);
+			System.out.println(DateTools.format(today));
+			System.out.println(DateTools.format(sevenDayBefore));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
 	
 }