Browse Source

增加待办任务测试

koul 1 year ago
parent
commit
d1928aacf6

+ 1 - 0
dingtalk-sdk/build.gradle

@@ -2,5 +2,6 @@ dependencies {
     compile "org.springframework:spring-context"
     compile "$fastjson"
     compile "com.dingtalk:dingtalk-sdk:1.0"
+    compile "com.aliyun:dingtalk:1.1.96"
     testCompile "junit:junit"
 }

+ 0 - 2
dingtalk-sdk/src/main/java/com/usoftchina/dingtalk/sdk/BaseSdk.java

@@ -1,8 +1,6 @@
 package com.usoftchina.dingtalk.sdk;
 
-import com.alibaba.fastjson.JSON;
 import com.dingtalk.api.DefaultDingTalkClient;
-import com.dingtalk.api.DingTalkClient;
 import com.dingtalk.api.request.OapiGettokenRequest;
 import com.dingtalk.api.response.OapiGettokenResponse;
 import com.taobao.api.ApiException;

+ 195 - 6
dingtalk-sdk/src/main/java/com/usoftchina/dingtalk/sdk/OaSdk.java

@@ -1,5 +1,8 @@
 package com.usoftchina.dingtalk.sdk;
 
+import com.aliyun.dingtalktodo_1_0.models.*;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
 import com.dingtalk.api.DefaultDingTalkClient;
 import com.dingtalk.api.DingTalkClient;
 import com.dingtalk.api.request.*;
@@ -7,6 +10,7 @@ import com.dingtalk.api.response.*;
 import com.taobao.api.internal.util.StringUtils;
 import com.usoftchina.dingtalk.sdk.config.DingTalkProperties;
 import com.usoftchina.dingtalk.sdk.util.DateUtils;
+import org.springframework.util.CollectionUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -229,10 +233,10 @@ public class OaSdk extends BaseSdk {
      * @param startTime  查询起始工作日。格式为“yyyy-MM-dd HH:mm:ss”,HH:mm:ss可以使用00:00:00,将返回此日期从0点到24点的结果
      * @param endTime    查询结束工作日。格式为“yyyy-MM-dd HH:mm:ss”,HH:mm:ss可以使用00:00:00,将返回此日期从0点到24点的结果。注意,起始与结束工作日最多相隔7天
      * @param offset     表示获取考勤数据的起始点,第一次传1,如果还有多余数据,下次获取传的offset值为之前的offset+limit 1、2...依次递增
-     * @param limit      表示获取考勤数据的条数,最大不能超过50条
+     * @param size      表示获取考勤数据的条数,最大不能超过50条
      * @return
      */
-    public List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> getAlitripList(String agentCode, String startTime, String endTime, long offset, long limit) {
+    public List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> getAlitripList(String agentCode, String startTime, String endTime, long offset, long size) {
         DingTalkClient client = new DefaultDingTalkClient(getProperties().getApi() + "/topapi/alitrip/btrip/apply/search");
         OapiAlitripBtripApplySearchRequest req = new OapiAlitripBtripApplySearchRequest();
         OapiAlitripBtripApplySearchRequest.OpenSearchRq rq = new OapiAlitripBtripApplySearchRequest.OpenSearchRq();
@@ -240,16 +244,15 @@ public class OaSdk extends BaseSdk {
         rq.setStartTime(StringUtils.parseDateTime(startTime));
         rq.setEndTime(StringUtils.parseDateTime(endTime));
         rq.setPage(offset);
-        rq.setPageSize(limit);
+        rq.setPageSize(size);
         req.setRq(rq);
         OapiAlitripBtripApplySearchResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
         assertOK(resp);
         return resp.getModule();
     }
-     public List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> getAllAlitrip(String agentCode, String startTime, String endTime, long offset, long limit){
+     public List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> getAllAlitrip(String agentCode, String startTime, String endTime){
         List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> dataList = new ArrayList<>();
-        long size = 50;
-        long i = 1;
+        long i=1,size=50;
         while (true) {
             List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> alitripList = getAlitripList(agentCode, startTime, endTime, i++, size);
             if (null != alitripList) {
@@ -263,4 +266,190 @@ public class OaSdk extends BaseSdk {
         }
         return dataList;
      }
+
+    /**
+     * 员工离职列表
+     * @param agentCode
+     * @param offset
+     * @param size
+     */
+     public OapiSmartworkHrmEmployeeQuerydimissionResponse.Paginator getEmpLeaveRecords(String agentCode, long offset, long size){
+         DingTalkClient client = new DefaultDingTalkClient(getProperties().getApi() + "/topapi/smartwork/hrm/employee/querydimission");
+         OapiSmartworkHrmEmployeeQuerydimissionRequest req = new OapiSmartworkHrmEmployeeQuerydimissionRequest();
+         req.setOffset(offset);
+         req.setSize(size);
+         OapiSmartworkHrmEmployeeQuerydimissionResponse resp= cached(() -> client.execute(req, getAccessToken(agentCode)));
+         assertOK(resp);
+         return resp.getResult();
+     }
+
+    /**
+     * 员工离职列表
+     * @param agentCode
+     */
+    public List<OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo> getAllEmpLeaveRecords(String agentCode){
+        List<OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo> list = new ArrayList<>();
+        long i=1,size=50;
+        while (true) {
+            OapiSmartworkHrmEmployeeQuerydimissionResponse.Paginator empLeaveRecords = getEmpLeaveRecords(agentCode, i++, size);
+            if (null != empLeaveRecords) {
+                Long nextCursor = empLeaveRecords.getNextCursor()==null?0:empLeaveRecords.getNextCursor();
+                list.addAll(getEmpLeave(agentCode, empLeaveRecords.getDataList()));
+                if (nextCursor<=0) {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 员工离职信息
+     *
+     * @param agentCode
+     * @param userIdList
+     */
+    public List<OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo> getEmpLeave(String agentCode, List<String> userIdList){
+            DingTalkClient client = new DefaultDingTalkClient(getProperties().getApi() + "/topapi/smartwork/hrm/employee/listdimission");
+            OapiSmartworkHrmEmployeeListdimissionRequest req = new OapiSmartworkHrmEmployeeListdimissionRequest();
+            req.setUseridList(String.join(",", userIdList));
+            OapiSmartworkHrmEmployeeListdimissionResponse resp= cached(() -> client.execute(req, getAccessToken(agentCode)));
+            assertOK(resp);
+            return resp.getResult();
+    }
+
+    /**
+     * 员工请假列表
+     * @param agentCode
+     * @param offset
+     * @param size
+     */
+    public List<OapiAttendanceGetleavestatusResponse.LeaveStatusVO> getLeaves(String agentCode,List<String> userIdList, long startTime, long endTime, long offset, long size){
+        DingTalkClient client = new DefaultDingTalkClient(getProperties().getApi() + "/topapi/attendance/getleavestatus");
+        OapiAttendanceGetleavestatusRequest req = new OapiAttendanceGetleavestatusRequest();
+        req.setUseridList(String.join(",", userIdList));
+        req.setStartTime(startTime);
+        req.setEndTime(endTime);
+        req.setOffset(offset);
+        req.setSize(size);
+        OapiAttendanceGetleavestatusResponse resp= cached(() -> client.execute(req, getAccessToken(agentCode)));
+        assertOK(resp);
+        OapiAttendanceGetleavestatusResponse.LeaveStatusListVO leaveStatusListVO = resp.getResult();
+        if (leaveStatusListVO!=null){
+            return leaveStatusListVO.getLeaveStatus();
+        }
+        return null;
+    }
+
+    public List<OapiAttendanceGetleavestatusResponse.LeaveStatusVO> getAllLeaves(String agentCode, List<String> userIdList, long startTime, long endTime){
+        List<OapiAttendanceGetleavestatusResponse.LeaveStatusVO> dataList = new ArrayList<>();
+        long i=1,size=20;
+        while (true) {
+            List<OapiAttendanceGetleavestatusResponse.LeaveStatusVO> leaves = getLeaves(agentCode, userIdList, startTime, endTime, i++, size);
+            if (!CollectionUtils.isEmpty(leaves)) {
+                dataList.addAll(leaves);
+                if (leaves.size() < size) {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+        return dataList;
+    }
+
+    /**
+     * 使用 Token 初始化账号Client
+     * @return Client
+     * @throws Exception
+     */
+    public com.aliyun.dingtalktodo_1_0.Client initClient() throws Exception {
+        Config config = new Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalktodo_1_0.Client(config);
+    }
+    public void createTodo(String agentCode,String unionId,String creatorId,String appUrl,String pcUrl,String title,String description,int priority,String dingNotify,Boolean isOnlyShow) throws Exception {
+        com.aliyun.dingtalktodo_1_0.Client client  = initClient();
+        CreateTodoTaskHeaders createTodoTaskHeaders = new CreateTodoTaskHeaders();
+        createTodoTaskHeaders.xAcsDingtalkAccessToken = getAccessToken(agentCode);
+        CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs notifyConfigs = new CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs()
+                .setDingNotify(dingNotify);
+        CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl detailUrl = new CreateTodoTaskRequest.CreateTodoTaskRequestDetailUrl()
+                .setAppUrl(appUrl)
+                .setPcUrl(pcUrl);
+        CreateTodoTaskRequest createTodoTaskRequest = new CreateTodoTaskRequest()
+                .setSubject(title)
+                .setCreatorId(creatorId)
+                .setDescription(description)
+                .setDueTime(DateUtils.nowDateEnd().getTime())
+                .setExecutorIds(java.util.Arrays.asList(
+                        unionId
+                ))
+                .setParticipantIds(java.util.Arrays.asList(
+                        unionId
+                ))
+                .setDetailUrl(detailUrl)
+                .setIsOnlyShowExecutor(isOnlyShow)
+                .setPriority(priority)
+                .setNotifyConfigs(notifyConfigs);
+        client.createTodoTaskWithOptions(unionId, createTodoTaskRequest, createTodoTaskHeaders, new RuntimeOptions());
+    }
+
+    public void updateTodo(String agentCode,String creatorId,String unionId,String taskId,String title,String description) throws Exception {
+        com.aliyun.dingtalktodo_1_0.Client client = initClient();
+        UpdateTodoTaskHeaders updateTodoTaskHeaders = new UpdateTodoTaskHeaders();
+        updateTodoTaskHeaders.xAcsDingtalkAccessToken =getAccessToken(agentCode);
+        UpdateTodoTaskRequest updateTodoTaskRequest = new UpdateTodoTaskRequest()
+                .setOperatorId(creatorId)
+                .setSubject(title)
+                .setDescription(description)
+                .setDueTime(DateUtils.nowDateTime().getTime())
+                .setDone(true)
+                .setExecutorIds(java.util.Arrays.asList(
+                        unionId
+                ))
+                .setParticipantIds(java.util.Arrays.asList(
+                        unionId
+                ));
+        client.updateTodoTaskWithOptions(unionId, taskId, updateTodoTaskRequest, updateTodoTaskHeaders, new RuntimeOptions());
+    }
+
+    public QueryOrgTodoTasksResponse getTodo(String agentCode,String unionId,String nextToken,Boolean isDone) throws Exception {
+        com.aliyun.dingtalktodo_1_0.Client client = initClient();
+        QueryOrgTodoTasksHeaders queryOrgTodoTasksHeaders = new QueryOrgTodoTasksHeaders();
+        queryOrgTodoTasksHeaders.xAcsDingtalkAccessToken = getAccessToken(agentCode);
+        QueryOrgTodoTasksRequest queryOrgTodoTasksRequest = new QueryOrgTodoTasksRequest()
+                .setNextToken(nextToken)
+                .setIsDone(isDone);
+        return client.queryOrgTodoTasksWithOptions(unionId, queryOrgTodoTasksRequest, queryOrgTodoTasksHeaders, new RuntimeOptions());
+    }
+
+    public List<QueryOrgTodoTasksResponseBody.QueryOrgTodoTasksResponseBodyTodoCards> getAllTodo(String agentCode,String unionId,String nextToken,Boolean isDone) throws Exception {
+        Boolean b=true;
+        List<QueryOrgTodoTasksResponseBody.QueryOrgTodoTasksResponseBodyTodoCards> todos = new ArrayList<>();
+        while (b){
+            QueryOrgTodoTasksResponse todo = getTodo(agentCode, unionId, nextToken, isDone);
+            QueryOrgTodoTasksResponseBody body = todo.getBody();
+            todos.addAll(body.getTodoCards());
+            String token = body.getNextToken();
+            if (token!=null&&!"".equals(token)){
+                nextToken=token;
+            }else {
+                b=false;
+            }
+        }
+        return todos;
+    }
+
+    public void deleteTodo(String agentCode,String unionId,String taskId) throws Exception {
+        com.aliyun.dingtalktodo_1_0.Client client = initClient();
+        DeleteTodoTaskHeaders deleteTodoTaskHeaders = new DeleteTodoTaskHeaders();
+        deleteTodoTaskHeaders.xAcsDingtalkAccessToken = getAccessToken(agentCode);
+        DeleteTodoTaskRequest deleteTodoTaskRequest = new DeleteTodoTaskRequest()
+                .setOperatorId(unionId);
+        client.deleteTodoTaskWithOptions(unionId, taskId, deleteTodoTaskRequest, deleteTodoTaskHeaders, new RuntimeOptions());
+    }
 }

+ 2 - 2
dingtalk-sdk/src/test/java/com/usoftchina/dingtalk/sdk/test/BaseTest.java

@@ -17,7 +17,7 @@ public class BaseTest {
         properties = new DingTalkProperties();
 //        properties.setCorpId("ding0fb1b0cd2510faf7ffe93478753d9884");
 //        properties.setAgents(Arrays.asList(new Agent("Uas", 508343055L, "dingibz8hztjohd4epzp", "Kwkf2aq4k35Crjw2smSAGH9diTj5q--c0Qg4TsyoFxfurOkiIoKzmOd-VCLJ1kEc")));
-        properties.setCorpId("dingf484d054c7fcbf4435c2f4657eb6378f");
-        properties.setAgents(Arrays.asList(new Agent("Uas", 587373913L, "dingk8oe4y0efafgwe4m", "n_xcuKNsqcID8GvXPVtXlFEWnw4WJLIXqSc4zR67Y8MrLHUYCw20yF_Gifu9ctRi")));
+        properties.setCorpId("dingcc2251af7d9b14e735c2f4657eb6378f");
+        properties.setAgents(Arrays.asList(new Agent("Uas", 587373913L, "dingxfuwm5g76h4q5a4q", "vGizhqKZOqcKb4-iJmZR6_LPUaK1OafMe4GuZ-LX6pSdXr6x15y6PgLdBGSYcq3d")));
     }
 }

+ 104 - 0
dingtalk-sdk/src/test/java/com/usoftchina/dingtalk/sdk/test/OaSdkTest.java

@@ -0,0 +1,104 @@
+package com.usoftchina.dingtalk.sdk.test;
+
+import com.aliyun.dingtalktodo_1_0.models.*;
+import com.dingtalk.api.response.OapiAlitripBtripApplySearchResponse;
+import com.dingtalk.api.response.OapiAttendanceGetleavestatusResponse;
+import com.dingtalk.api.response.OapiSmartworkHrmEmployeeListdimissionResponse;
+import com.usoftchina.dingtalk.sdk.OaSdk;
+import com.usoftchina.dingtalk.sdk.util.UrlUtils;
+import org.junit.Test;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author yingp
+ * @date 2020/3/6
+ */
+public class OaSdkTest extends BaseTest {
+
+    private static OaSdk sdk;
+
+    static {
+        sdk = new OaSdk(properties);
+    }
+
+    @Test
+    public void getAlitripList() {
+        List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> alitripList = sdk.getAlitripList("Uas", "2024-03-01 00:00:00", "2024-05-14 18:00:00", 1, 50);
+        if (!CollectionUtils.isEmpty(alitripList)) {
+            for (OapiAlitripBtripApplySearchResponse.OpenApplyRs openApplyRs:alitripList) {
+                System.out.println(openApplyRs);
+            }
+        }
+    }
+
+    @Test
+    public void getEmpLeaveRecords() {
+        List<OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo> empLeaves = sdk.getAllEmpLeaveRecords("Uas");
+        if (!CollectionUtils.isEmpty(empLeaves)) {
+            for (OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo empLeave:empLeaves) {
+                System.err.println(empLeave.getStatus());
+            }
+        }
+    }
+
+    @Test
+    public void getAllLeaves(){
+        List<String> strings = new ArrayList<>();
+        strings.add("11111");
+        List<OapiAttendanceGetleavestatusResponse.LeaveStatusVO> leaveStatusVOS = sdk.getAllLeaves("Uas", strings, new Date().getTime(), new Date().getTime());
+        if (!CollectionUtils.isEmpty(leaveStatusVOS)) {
+            System.err.println(leaveStatusVOS);
+        }
+    }
+
+    @Test
+    public void test(){
+        int i=1,j=100;
+        double i1 = (double)i/j;
+        System.err.println(i1);
+        System.err.println((int)Math.ceil(i1));
+        System.err.println((int) Math.ceil((double)i / j));
+    }
+
+    @Test
+    public void createTodo() throws Exception {
+        String appUrl = UrlUtils.generateAuthUrl(properties.getCorpId(),"MOYING", "UasAudit","http://113.106.72.245:8099/ERP/",
+                 "http://113.106.72.245:8099/office/authorize", "uas/uasApproval/MOYING");
+        System.err.println(appUrl);
+        //String appUrl="http://113.106.72.245:8099/office/authorize?corpId=dingcc2251af7d9b14e735c2f4657eb6378f&agent=UasAudit&url=aHR0cDovLzExMy4xMDYuNzIuMjQ1OjgwOTkvRVJQL3Vhcy91YXNBcHByb3ZhbC9NT1lJTkcv&master=MOYING";
+        String pcUrl="http://113.106.72.245:8099/office/authorize?corpId=dingcc2251af7d9b14e735c2f4657eb6378f&agent=UasAudit&url=aHR0cDovLzExMy4xMDYuNzIuMjQ1OjgwOTkvRVJQL3Vhcy91YXNBcHByb3ZhbC9NT1lJTkcv&master=MOYING";
+        sdk.createTodo("Uas","lFkVS5u2qgtZo41sRuiiTTAiEiE","WQl6DqxOyZ4brwoQaiSyiSuwiEiE",appUrl,pcUrl,"未处理流程","有未处理的流程需要处理",40,"1",false);
+
+    }
+
+    @Test
+    public void updatetodo() throws Exception {
+        sdk.updateTodo("UasAudit","WQl6DqxOyZ4brwoQaiSyiSuwiEiE","lFkVS5u2qgtZo41sRuiiTTAiEiE","taskId","未处理流程","有未处理的流程需要处理");
+    }
+
+    @Test
+    public void deleteTodo() throws Exception {
+        QueryOrgTodoTasksResponse todo = sdk.getTodo("Uas", "lFkVS5u2qgtZo41sRuiiTTAiEiE", "0", false);
+        String nextToken = todo.getBody().nextToken;
+        System.err.println(nextToken);
+        List<QueryOrgTodoTasksResponseBody.QueryOrgTodoTasksResponseBodyTodoCards> todoCards = todo.getBody().getTodoCards();
+        for (QueryOrgTodoTasksResponseBody.QueryOrgTodoTasksResponseBodyTodoCards todoCard:todoCards) {
+            System.err.println(todoCard.taskId);
+            //if ("未处理流程".equals(todoCard.subject)){
+                sdk.deleteTodo("Uas","lFkVS5u2qgtZo41sRuiiTTAiEiE",todoCard.taskId);
+            //}
+        }
+    }
+
+    @Test
+    public void getAllTodo() throws Exception {
+        List<QueryOrgTodoTasksResponseBody.QueryOrgTodoTasksResponseBodyTodoCards> allTodo = sdk.getAllTodo("Uas", "lFkVS5u2qgtZo41sRuiiTTAiEiE", "0", false);
+        for (QueryOrgTodoTasksResponseBody.QueryOrgTodoTasksResponseBodyTodoCards todo:allTodo) {
+            System.err.println(todo.taskId);
+        }
+    }
+}

+ 125 - 0
uas-office-dingtalk/src/main/java/com/usoftchina/uas/office/dingtalk/core/Constant.java

@@ -0,0 +1,125 @@
+package com.usoftchina.uas.office.dingtalk.core;
+
+/**
+ * 系统常量
+ * 
+ * @author yingp
+ * 
+ */
+public class Constant {
+
+	// 日期格式
+
+	public final static String YM = "yyyy-MM";
+
+	public final static String ym = "yyyyMM";
+
+	public final static String YMD = "yyyy-MM-dd";
+
+	public final static String YMD_HM = "yyyy-MM-dd HH:mm";
+
+	public final static String YMD_HMS = "yyyy-MM-dd HH:mm:ss";
+
+	public final static String ORACLE_YMD = "yyyy-MM-dd";
+
+	public final static String ORACLE_YMD_HMS = "yyyy-MM-dd HH24:mi:ss";
+
+	public static final String REGEXP_MOBILE = "^[1|8][3-9]\\d{9}$|^([6|9])\\d{7}$|^[0][9]\\d{8}$|^[6]([8|6])\\d{5}$|^(886|0)[9]\\d{8}$";
+
+	public static final String REGEXP_EMAIL = "^([\\w-])+(\\.\\w+)*@([\\w-])+((\\.\\w{2,3}){1,3})$";
+
+	/**
+	 * 求和
+	 * */
+	public final static String SUMMARY_SUM = "sum";
+
+	/**
+	 * 最大值
+	 * */
+	public final static String SUMMARY_MAX = "max";
+	/**
+	 * 最小值
+	 * */
+	public final static String SUMMARY_MIN = "min";
+	/**
+	 * 平均值
+	 * */
+	public final static String SUMMARY_AVERAGE = "average";
+	/**
+	 *  公式合计
+	 * */
+	public final static String SUMMARY_FORMULA = "formula";
+	/**
+	 * 是
+	 */
+	public static final short YES = 1;
+	/**
+	 * 是
+	 */
+	public static final short yes = -1;
+	/**
+	 * 是
+	 */
+	public static final String TRUE = "T";
+	/**
+	 * 否
+	 */
+	public static final short NO = 0;
+	/**
+	 * 否
+	 */
+	public static final String FALSE = "F";
+
+	public static final int ORACLE_MAX_TABLE_SIZE = 999;
+
+	/**
+	 * 优软云
+	 * */
+	public static final String UAS_CLOUD = "CLOUD";
+
+	/**
+	 * 类型--"是否"字段
+	 */
+	public static final String TYPE_YN = "yn";
+
+	/**
+	 * 类型--"下拉框"
+	 */
+	public static final String TYPE_COMBO = "combo";
+
+	/**
+	 * 正则表达式:数字
+	 */
+	public static final String REG_NUM = "^-?[0-9]+(.[0-9]+)?";
+
+	/**
+	 * 正则表达式:日期
+	 */
+	public static final String REG_DATE = "\\d{2,4}-\\d{1,2}-\\d{1,2}";
+
+	/**
+	 * 正则表达式:时间
+	 */
+	public static final String REG_DATETIME = "\\d{2,4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}";
+
+	/**
+	 * excel导出阈值
+	 */
+	public static final int EXCEL_LG_SIZE = 5000;
+
+	/**
+	 * excel导出最大条数
+	 */
+	public static final int EXCEL_MAX_SIZE = 100000;
+
+	/**
+	 * 正则表达式:ipv4
+	 */
+	public static final String REG_IPV4 = "((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))";
+	
+	/**
+	 * 临时表名称
+	 */
+	public static final String TEMP_TABLE_NAME = "TEMP_TABLE";
+
+}

+ 647 - 0
uas-office-dingtalk/src/main/java/com/usoftchina/uas/office/dingtalk/core/DateUtil.java

@@ -0,0 +1,647 @@
+package com.usoftchina.uas.office.dingtalk.core;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class DateUtil {
+	static final SimpleDateFormat ym = new SimpleDateFormat("yyyyMM");
+	static final SimpleDateFormat YM = new SimpleDateFormat("yyyy-MM");
+	static final SimpleDateFormat YMD = new SimpleDateFormat("yyyy-MM-dd");
+	static final SimpleDateFormat YMD_HMS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+	public static String format(Date date, String f) {
+		if (date == null) {
+			date = new Date();
+		}
+		if (f == null) {
+			return YMD.format(date);
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(f);
+		return sdf.format(date);
+	}
+
+	public static String format(java.sql.Date date, String f) {
+		if (date == null) {
+			return currentDateString(f);
+		} else {
+			if (f == null) {
+				return YMD.format(date);
+			}
+			SimpleDateFormat sdf = new SimpleDateFormat(f);
+			return sdf.format(date);
+		}
+	}
+
+	public static Date parse(String date, String f) {
+		if (date == null) {
+			return new Date();
+		}
+		if (f == null) {
+			try {
+				return date.contains(" ") ? YMD_HMS.parse(date) : YMD.parse(date);
+			} catch (ParseException e) {
+				return new Date();
+			}
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(f);
+		try {
+			return sdf.parse(date);
+		} catch (ParseException e) {
+			return new Date();
+		}
+	}
+
+	/**
+	 * 获取日期年份
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static int getYear(String date) throws ParseException {
+		date = date == null ? format(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(YMD.parse(date));
+		return calendar.get(Calendar.YEAR);
+	}
+
+	/**
+	 * 获取日期年份
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static int getYear(Date date) throws ParseException {
+		date = date == null ? parse(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		return calendar.get(Calendar.YEAR);
+	}
+
+	/**
+	 * 获取日期月份
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static int getMonth(String date) throws ParseException {
+		date = date == null ? format(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(YMD.parse(date));
+		return (calendar.get(Calendar.MONTH) + 1);
+	}
+
+	/**
+	 * 获取日期月份
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static int getMonth(Date date) throws ParseException {
+		date = date == null ? parse(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		return (calendar.get(Calendar.MONTH) + 1);
+	}
+
+	/**
+	 * 获取日期号
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static int getDay(String date) throws ParseException {
+		date = date == null ? format(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(YMD.parse(date));
+		return calendar.get(Calendar.DAY_OF_MONTH);
+	}
+
+	/**
+	 * 获取日期号
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static int getDay(Date date) throws ParseException {
+		date = date == null ? parse(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		return calendar.get(Calendar.DAY_OF_MONTH);
+	}
+
+	/**
+	 * 获取日期前一年日期
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static String getLastYearDay(String date) throws ParseException {
+		date = date == null ? format(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		try {
+			calendar.setTime(YMD.parse(date));
+		} catch (ParseException e) {
+			calendar.setTime(new Date());
+		}
+		calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1);
+		return YMD.format(calendar.getTime());
+
+	}
+
+	/**
+	 * 获取月份起始日期
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static String getMinMonthDate(String date) {
+		date = date == null ? format(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		try {
+			calendar.setTime(YMD.parse(date));
+		} catch (ParseException e) {
+			calendar.setTime(new Date());
+		}
+		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
+		return YMD.format(calendar.getTime());
+	}
+
+	/**
+	 * 获取月份起始日期
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static String getMinMonthDate(Date date) {
+		date = date == null ? parse(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
+		return YMD.format(calendar.getTime());
+	}
+
+	/**
+	 * 获取月份最后日期
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static String getMaxMonthDate(String date) {
+		date = date == null ? format(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		try {
+			calendar.setTime(YMD.parse(date));
+		} catch (ParseException e) {
+			calendar.setTime(new Date());
+		}
+		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+		return YMD.format(calendar.getTime());
+	}
+
+	/**
+	 * 获取月份最后日期
+	 * 
+	 * @param date
+	 * @return
+	 * @throws ParseException
+	 */
+	public static String getMaxMonthDate(Date date) {
+		date = date == null ? parse(null, null) : date;
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+		return YMD.format(calendar.getTime());
+	}
+
+	/**
+	 * 当前时间
+	 * 
+	 * @return <h3>String</h3>
+	 */
+	public static String getCurrentDate() {
+		return format(new Date(), null);
+	}
+
+	/**
+	 * 截取指定日期的年月
+	 * 
+	 * @param date
+	 * @return
+	 */
+	public static Integer getYearmonth(Date date) {
+		if (date == null) {
+			date = new Date();
+		}
+		return Integer.parseInt(ym.format(date));
+	}
+
+	/**
+	 * 截取指定日期的年月
+	 * 
+	 * @param date
+	 * @return
+	 */
+	public static Integer getYearmonth(String date) {
+		return Integer.parseInt(ym.format(parse(date, null)));
+	}
+
+	/**
+	 * 获取当前年月
+	 * 
+	 * @return
+	 */
+	public static Integer getYearmonth() {
+		return Integer.parseInt(ym.format(new Date()));
+	}
+
+	public static int compare(String date1, String date2) {
+		try {
+			Date dt1 = YMD.parse(date1);
+			Date dt2 = YMD.parse(date2);
+			if (dt1.getTime() > dt2.getTime()) {
+				return 1;
+			} else if (dt1.getTime() < dt2.getTime()) {
+				return -1;
+			} else {
+				return 0;
+			}
+		} catch (Exception exception) {
+			exception.printStackTrace();
+		}
+		return 0;
+	}
+
+	/**
+	 * 获取特定日期是星期几
+	 * 
+	 * @return
+	 */
+	public static String getWeekDay(String DateStr) {
+		SimpleDateFormat formatYMD = new SimpleDateFormat("yyyy-MM-dd");// formatYMD表示的是yyyy-MM-dd格式
+		SimpleDateFormat formatD = new SimpleDateFormat("E");// "E"表示"day in week"
+		Date d = null;
+		String weekDay = "";
+		try {
+			d = formatYMD.parse(DateStr);// 将String 转换为符合格式的日期
+			weekDay = formatD.format(d);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		// System.out.println("日期:"+DateStr+" : "+weekDay);
+		return weekDay;
+	}
+
+	public static int getWeekDay1(String DateStr) {// 返回日期对应数字
+		SimpleDateFormat formatYMD = new SimpleDateFormat("yyyy-MM-dd");// formatYMD表示的是yyyy-MM-dd格式
+		Date d = null;
+		int weekDay = 0;
+		try {
+			d = formatYMD.parse(DateStr);// 将String 转换为符合格式的日期
+			Calendar calendar = Calendar.getInstance();
+			calendar.setTime(d);
+			weekDay = calendar.get(Calendar.DAY_OF_WEEK) - 1;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return weekDay;
+	}
+
+	/**
+	 * 获取特定时间段内有哪几日
+	 * 
+	 * @return
+	 */
+	public static List<Object> findDates(String start_time, String end_time) throws ParseException {
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+		Date date1 = df.parse(start_time);
+		Date date2 = df.parse(end_time);
+		int s = (int) ((date2.getTime() - date1.getTime()) / (24 * 60 * 60 * 1000));
+		List<Object> objects = new ArrayList<Object>();
+		String value = "";
+		if (s + 1 > 0) {
+			for (int i = 0; i <= s; i++) {
+				long todayDate = date1.getTime() + (long) i * 24 * 60 * 60 * 1000;
+				Date tmDate = new Date(todayDate);
+				value = new SimpleDateFormat("yyyy-MM-dd").format(tmDate);
+				objects.add(value);
+			}
+		}
+		return objects;
+	}
+
+	/**
+	 * 获取特定时间段内有多少天
+	 * 
+	 * @return
+	 */
+	public static int countDates(String start_time, String end_time) throws ParseException {
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+		Date date1 = df.parse(start_time);
+		Date date2 = df.parse(end_time);
+		int s = (int) ((date2.getTime() - date1.getTime()) / (24 * 60 * 60 * 1000));
+		return s;
+	}
+
+	/**
+	 * 日期转化成oracle格式to_date('2012-12-12', 'yyyy-MM-dd')
+	 * 
+	 * @param format
+	 *            format type,for example: 'yyyy-MM-dd', 'yyyy-MM-dd HH:mm:ss'
+	 * @param date
+	 *            date{type=java.util.Date}
+	 */
+	public static String parseDateToOracleString(String format, Date date) {
+		if (format == null) {
+			format = Constant.YMD;
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(format);
+		if (date == null) {
+			date = new Date();
+		}
+		if (Constant.YMD_HMS.toUpperCase().equals(format.toUpperCase())) {
+			format = Constant.ORACLE_YMD_HMS;
+		} else {
+			format = Constant.ORACLE_YMD;
+		}
+		return "to_date('" + sdf.format(date) + "','" + format + "')";
+	}
+
+	/**
+	 * 日期转化成oracle格式to_date('2012-12-12', 'yyyy-MM-dd')
+	 * 
+	 * @param format
+	 *            format type,for example: 'yyyy-MM-dd', 'yyyy-MM-dd HH:mm:ss'
+	 * @param dateString
+	 *            date{type=string}
+	 */
+	public static String parseDateToOracleString(String format, String dateString) {
+		if (format == null) {
+			format = Constant.YMD;
+		}
+		if (dateString == null || "".equals(dateString) || "null".equals(dateString)) {
+			SimpleDateFormat sdf = new SimpleDateFormat(format);
+			dateString = sdf.format(new Date());
+		}
+		if (Constant.YMD_HMS.toUpperCase().equals(format.toUpperCase())) {
+			format = Constant.ORACLE_YMD_HMS;
+		} else {
+			format = Constant.ORACLE_YMD;
+		}
+		return "to_date('" + dateString + "','" + format + "')";
+	}
+
+	/**
+	 * Date转化成字符串格式
+	 * 
+	 * @param f
+	 *            format格式;若为空,则默认为yyyy-MM-dd
+	 */
+	public static String parseDateToString(Date date, String f) {
+		if (f == null) {
+			f = Constant.YMD;
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(f);
+		if (date == null) {
+			date = new Date();
+		}
+		return sdf.format(date);
+	}
+
+	/**
+	 * 形如{2012-12-21}或{2012-12-21 12:12:12}字符串格式的日期转化成java.util.Date类型
+	 * 
+	 * @param date
+	 *            string日期;若为空或格式错误,则返回当前时间
+	 * @param f
+	 *            format格式;若为空,则默认为yyyy-MM-dd
+	 * @return java.util.Date类型日期
+	 */
+	public static Date parseStringToDate(String date, String f) {
+		if (f == null) {
+			f = Constant.YMD;
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(f);
+		if (date == null) {
+			return new Date();
+		}
+		try {
+			return sdf.parse(date);
+		} catch (ParseException e) {
+			return new Date();
+		}
+	}
+
+	/**
+	 * 当前时间的字符串格式
+	 * 
+	 * @param f
+	 *            format格式;若为空,则默认为yyyy-MM-dd
+	 */
+	public static String currentDateString(String f) {
+		if (f == null) {
+			f = Constant.YMD;
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(f);
+		return sdf.format(new Date());
+	}
+
+	/**
+	 * 借贷合同月份处理
+	 */
+	public static int getMonthSpace(Date date1, Date date2) throws ParseException {
+		int iMonth = 0;
+		int flag = 0;
+		try {
+			Calendar objCalendarDate1 = Calendar.getInstance();
+			objCalendarDate1.setTime(date1);
+
+			Calendar objCalendarDate2 = Calendar.getInstance();
+			objCalendarDate2.setTime(date2);
+
+			if (objCalendarDate2.equals(objCalendarDate1))
+				return 0;
+			if (objCalendarDate1.after(objCalendarDate2)) {
+				Calendar temp = objCalendarDate1;
+				objCalendarDate1 = objCalendarDate2;
+				objCalendarDate2 = temp;
+			}
+			if (objCalendarDate2.get(Calendar.DAY_OF_MONTH) > objCalendarDate1.get(Calendar.DAY_OF_MONTH))
+				flag = 1;
+
+			if (objCalendarDate2.get(Calendar.YEAR) > objCalendarDate1.get(Calendar.YEAR)) {
+				iMonth = ((objCalendarDate2.get(Calendar.YEAR) - objCalendarDate1.get(Calendar.YEAR)) * 12
+						+ objCalendarDate2.get(Calendar.MONTH) + flag)
+						- objCalendarDate1.get(Calendar.MONTH);
+			} else {
+				iMonth = objCalendarDate2.get(Calendar.MONTH) + flag - objCalendarDate1.get(Calendar.MONTH);
+			}
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return iMonth;
+	}
+
+	/**
+	 * 月份往前或往后n天
+	 */
+	public static Date overDate(Date date, int num) {
+		date = date == null ? new Date() : date;
+		Calendar calendar = new GregorianCalendar();
+		calendar.setTime(date);
+		calendar.add(Calendar.DATE, num);
+		date = calendar.getTime();
+		return date;
+	}
+
+	/**
+	 * 月份加减
+	 * 
+	 * @param date
+	 * @param increase
+	 * @return
+	 */
+	public static Integer addMonth(Date date, int increase) {
+		if (date == null)
+			date = new Date();
+		Calendar calendar = new GregorianCalendar();
+		calendar.setTime(date);
+		calendar.add(Calendar.MONTH, increase);
+		return getYearmonth(calendar.getTime());
+	}
+
+	/**
+	 * 月份加减
+	 * 
+	 * @param month
+	 * @param increase
+	 * @return
+	 */
+	public static Integer addMonth(Integer month, int increase) {
+		Calendar calendar = new GregorianCalendar();
+		try {
+			calendar.setTime(ym.parse(String.valueOf(month)));
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		calendar.add(Calendar.MONTH, increase);
+		return getYearmonth(calendar.getTime());
+	}
+
+	/**
+	 * 时间添加小时数
+	 * */
+	public static Date addHours(Date date, float hours) {
+		Calendar ca = Calendar.getInstance();
+		ca.setTime(date);
+		ca.add(Calendar.MINUTE, (int) (hours * 60));
+		return ca.getTime();
+	}
+
+	/**
+	 * 判断日期是否合法
+	 */
+	public static boolean isValidDate(String dateString, String f) {
+		SimpleDateFormat sdf = new SimpleDateFormat(f);
+		sdf.setLenient(false);
+		try {
+			sdf.parse(dateString);
+		} catch (ParseException e) {
+			e.printStackTrace();
+			return false;
+		}
+		return true;
+	}
+	
+	/**
+     * 获取起止日期
+     * @param sdf 需要显示的日期格式
+     * @param date 需要参照的日期
+     * @param n 最近n周
+     * @param option 0 开始日期;1 结束日期
+     * @param k 0 包含本周 1 不包含本周
+     * @return
+     * @author uas wb
+     */
+    public static String getFromToDate(SimpleDateFormat sdf, Date date, int n, int option, int k) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
+        int offset = 0 == option ? 1 - dayOfWeek : 7 - dayOfWeek;
+        int amount = 0 == option ? offset - (n - 1  + k) * 7 : offset - k * 7;
+        calendar.add(Calendar.DATE, amount);
+        return sdf.format(calendar.getTime());
+    }
+ 
+    /**
+     * 根据当前日期获得最近n周的日期区间(包含本周)
+     * @param n
+     * @param sdf
+     * @return
+     */
+    public static String getNWeekTimeInterval(int n, SimpleDateFormat sdf) {
+        String beginDate = getFromToDate(sdf, new Date(), n, 0, 0);
+        String endDate = getFromToDate(sdf, new Date(), n, 1, 0);
+        return beginDate + "," + endDate;
+    }
+ 
+    /**
+     * 根据当前日期获得最近n周的日期区间(不包含本周)
+     * @param n
+     * @param sdf
+     * @return
+     */
+    public static String getNWeekTimeIntervalTwo(int n, SimpleDateFormat sdf) {
+        String beginDate = getFromToDate(sdf, new Date(), n, 0, 1);
+        String endDate = getFromToDate(sdf, new Date(), n, 1, 1);
+        return beginDate + "," + endDate;
+    }
+ 
+    /**
+     * 根据当前日期获得本周的日期区间(本周周一和周日日期)
+     * @param sdf
+     * @return
+     */
+    public static String getThisWeekTimeInterval(SimpleDateFormat sdf) {
+        return getNWeekTimeInterval(1, sdf);
+    }
+ 
+    /**
+     * 根据当前日期获得上周的日期区间(上周周一和周日日期)
+     * @param sdf
+     * @return
+     * @author uas wb
+     */
+    public static String getLastWeekTimeInterval(SimpleDateFormat sdf) {
+        return getNWeekTimeIntervalTwo(1, sdf);
+    }
+    
+    /**
+     * 根据当前日期获得本月的日期区间(本月第一天日期和本月最后一天日期)
+     * @param sdf
+     * @return
+     * @author uas wb
+     */
+    public static String getThisMonthFirstDayAndLastDayTime(SimpleDateFormat sdf) {
+   	 Calendar c = Calendar.getInstance();    
+   	 c.add(Calendar.MONTH, 0);
+   	 c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天 
+   	 String firstDay = sdf.format(c.getTime());
+   	 
+   	 Calendar ca = Calendar.getInstance();    
+   	 ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));  
+   	 String lastDay = sdf.format(ca.getTime());
+   	 return firstDay + "," +lastDay;
+   }
+}

+ 270 - 0
uas-office-dingtalk/src/main/java/com/usoftchina/uas/office/dingtalk/core/NumberUtil.java

@@ -0,0 +1,270 @@
+package com.usoftchina.uas.office.dingtalk.core;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+
+/**
+ * 数值处理工具
+ * 
+ * @author yingp
+ * 
+ */
+public class NumberUtil {
+
+	/**
+	 * 是否为空、0
+	 * 
+	 * @param numberObj
+	 * @return
+	 */
+	public static boolean isEmpty(Object numberObj) {
+		try {
+			return numberObj == null || "0".equals(String.valueOf(numberObj)) || Integer.parseInt(numberObj.toString()) == 0;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
+	/**
+	 * format double类型
+	 * 
+	 * @param number
+	 *            需要format的数据
+	 * @param f
+	 *            保留f位的小数
+	 * @return format之后的double类型的数据
+	 */
+	public static double formatDouble(double number, int f) {
+		if (f > 0) {
+			BigDecimal b = new BigDecimal(Double.toString(number));
+			BigDecimal one = new BigDecimal("1");
+			return b.divide(one, f, BigDecimal.ROUND_HALF_UP).doubleValue();
+		} else {
+			return Math.floor(number);
+		}
+	}
+
+	/**
+	 * format double类型
+	 * 
+	 * @param number
+	 *            需要format的数据
+	 * @param f
+	 *            保留f位的小数
+	 * @return format之后的double类型的数据
+	 */
+	public static double formatDouble(String number, int f) {
+		double n = Double.parseDouble(number);
+		if (f > 0) {
+			BigDecimal b = new BigDecimal(number);
+			BigDecimal one = new BigDecimal("1");
+			return b.divide(one, f, BigDecimal.ROUND_HALF_UP).doubleValue();
+		} else {
+			return Math.floor(n);
+		}
+	}
+
+	/**
+	 * 浮点型转成BigDecimal
+	 * 
+	 * @param number
+	 * @return
+	 */
+	public static String parseBigDecimal(double number) {
+		int scale = BigDecimal.valueOf(number).scale();
+		if (scale == -1) {
+			scale = 0;
+		}
+		return String.valueOf(BigDecimal.valueOf(number).setScale(scale, BigDecimal.ROUND_HALF_UP));
+	}
+
+	/**
+	 * 数字格式化
+	 * 
+	 * @param number
+	 * @param f
+	 * @return
+	 */
+	public static String formatNumber(Object number, int f) {
+		if ("0".equals(String.valueOf(number)))
+			return "0";
+		if (number instanceof String)
+			number = Double.parseDouble(number.toString());
+		DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance();
+		df.setGroupingSize(3);
+		int len = number.toString().length();
+		if (number.toString().indexOf(".") > 0)
+			len = number.toString().indexOf(".");
+		String pattern = len > 3 ? "0,000" : "0";
+		for (int i = 0; i < f; i++) {
+			if (i == 0)
+				pattern += ".";
+			pattern += "0";
+		}
+		df.applyPattern(pattern);
+		try {
+			return df.format(number);
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	/**
+	 * 设置小数点保留位数
+	 * */
+	public static float subFloat(float f, int length) {
+		String fStr = String.valueOf(f);
+		int i = fStr.indexOf(".");
+		String returnStr = null;
+		if (fStr.length() > i + 1 + length) {
+			returnStr = fStr.substring(0, i + 1 + length);
+		} else
+			returnStr = fStr;
+		float returnf = (Float.valueOf(returnStr)).floatValue();
+		return returnf;
+	}
+
+	/**
+	 * int数组转化成Integer数组
+	 */
+	public static Integer[] toIntegerArray(int[] arr) {
+		int n = arr.length;
+		Integer[] iarr = new Integer[n];
+		for (int i = 0; i < n; i++) {
+			iarr[i] = new Integer(arr[i]);
+		}
+		return iarr;
+	}
+
+	public static Number nvl(Number number, Number ifNullNumber) {
+		return number == null ? ifNullNumber : number;
+	}
+
+	public static int compare(Double paramDouble1, Double paramDouble2) {
+		if (paramDouble1 == null)
+			paramDouble1 = 0.0;
+		if (paramDouble2 == null)
+			paramDouble2 = 0.0;
+		return Double.compare(paramDouble1, paramDouble2);
+	}
+
+	/**
+	 * Double型加法运算
+	 * 
+	 * @param d1
+	 *            第一个加数
+	 * @param ds
+	 *            若干个加数
+	 * @return 相加的结果
+	 * @author suntg
+	 */
+	public static double add(Double d1, Double... ds) {
+		BigDecimal bd = new BigDecimal(Double.toString(d1));
+		for (Double d : ds) {
+			bd = bd.add(new BigDecimal(Double.toString(d)));
+		}
+		return bd.doubleValue();
+	}
+
+	/**
+	 * Double型加法运算
+	 * 
+	 * @param d1
+	 *            第一个加数
+	 * @param ds
+	 *            若干个加数
+	 * @return 相加的结果
+	 * @author suntg
+	 */
+	public static double add(String ds1, String... dss) {
+		BigDecimal bd = new BigDecimal(ds1);
+		for (String ds : dss) {
+			bd = bd.add(new BigDecimal(ds));
+		}
+		return bd.doubleValue();
+	}
+
+	/**
+	 * Double型减法运算
+	 * 
+	 * @param d1
+	 *            被减数
+	 * @param d2
+	 *            减数
+	 * @return 运算结果
+	 * @author suntg
+	 */
+	public static double sub(Double d1, Double d2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(d1));
+		BigDecimal b2 = new BigDecimal(Double.toString(d2));
+		return b1.subtract(b2).doubleValue();
+	}
+
+	/**
+	 * Double 型乘法运算
+	 * 
+	 * @param d1
+	 *            第一个乘数
+	 * @param d2
+	 *            第二个乘数
+	 * @return 运算结果
+	 * @author suntg
+	 */
+	public static double mul(Double d1, Double d2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(d1));
+		BigDecimal b2 = new BigDecimal(Double.toString(d2));
+		return b1.multiply(b2).doubleValue();
+	}
+
+	/**
+	 * Double 型除法运算
+	 * 
+	 * @param d1
+	 *            被除数
+	 * @param d2
+	 *            除数
+	 * @param scale
+	 *            小数点四舍五入精度
+	 * @return 运算结果
+	 * @author suntg
+	 */
+	public static double div(Double d1, Double d2, int scale) {
+		if (scale < 0) {
+			throw new IllegalArgumentException("四舍五入精度必须大于0");
+		}
+		if (d2.doubleValue() == 0) {
+			throw new IllegalArgumentException("被除数不能为0");
+		}
+		BigDecimal b1 = new BigDecimal(Double.toString(d1));
+		BigDecimal b2 = new BigDecimal(Double.toString(d2));
+		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
+	}
+
+	/**
+	 * 默认小数点四舍五入精度为6的Double型除法运算
+	 * 
+	 * @param d1
+	 *            被除数
+	 * @param d2
+	 *            除数
+	 * @return 运算结果
+	 * @author suntg
+	 */
+	public static double div(Double d1, Double d2) {
+		return div(d1, d2, 6);
+	}
+
+	/**
+	 * 比较浮点型数值
+	 * 
+	 * @param paramDouble1
+	 * @param paramDouble2
+	 * @param paramInt
+	 *            精度
+	 * @return
+	 */
+	public static int compare(double paramDouble1, double paramDouble2, int paramInt) {
+		return Double.compare(formatDouble(paramDouble1, paramInt), formatDouble(paramDouble2, paramInt));
+	}
+
+}

+ 4 - 1
uas-office-dingtalk/src/main/java/com/usoftchina/uas/office/dingtalk/listener/UasOaListener.java

@@ -21,10 +21,13 @@ public class UasOaListener {
     @UasEventListener(caller = "OaDingTalklog", operation = "SAVE")
     public void oaDingTalklog(UasEvent event) {
         logger.info("OaDingTalklog开始");
+        logger.info("event=="+event.toString());
         if (!event.getMaster().equals(DataCenter.INSTANCE.getUsername())) {
             return;
         }
         int id = Integer.parseInt(event.getKey().toString());
-        uasOaService.saveOa(id);
+        logger.info("id=="+id);
+        uasOaService.saveOa("Uas",id);
+        logger.info("OaDingTalklog结束");
     }
 }

+ 123 - 91
uas-office-dingtalk/src/main/java/com/usoftchina/uas/office/dingtalk/service/UasOaService.java

@@ -1,144 +1,176 @@
 package com.usoftchina.uas.office.dingtalk.service;
 
 import com.dingtalk.api.response.OapiAlitripBtripApplySearchResponse;
+import com.dingtalk.api.response.OapiAttendanceGetleavestatusResponse;
+import com.dingtalk.api.response.OapiSmartworkHrmEmployeeListdimissionResponse;
 import com.usoftchina.dingtalk.sdk.OaSdk;
+import com.usoftchina.uas.office.dingtalk.core.DateUtil;
 import com.usoftchina.uas.office.service.AbstractService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataAccessException;
-import org.springframework.jdbc.core.CallableStatementCallback;
-import org.springframework.jdbc.core.CallableStatementCreator;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.support.rowset.SqlRowSet;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 @Service
 public class UasOaService extends AbstractService {
-    //创建序列
-    static final String CREATE_SEQ = "CREATE SEQUENCE ? MINVALUE 1 MAXVALUE 99999999999 INCREMENT BY 1 START WITH 3000 CACHE 20 NOORDER NOCYCLE ";
-    @Autowired
-    protected JdbcTemplate jdbcTemplate;
-
+    private final Logger logger = LoggerFactory.getLogger(UasOaService.class);
     @Autowired
     private OaSdk oaSdk;
 
-    public void saveOa(int id){
+    public void saveOa(String agentCode,int id){
+        logger.info("agentCode=="+agentCode);
         SqlRowSet rs = jdbcTemplate.queryForRowSet("select od_id,od_kind,to_char(od_startdate,'yyyy-MM-dd hh24:mi:ss') startdate,to_char(od_enddate,'yyyy-MM-dd hh24:mi:ss') enddate from OaDingTalklog where od_id=" + id);
         while (rs.next()){
             String odKind = rs.getString("od_kind");
             String startdate = rs.getString("startdate");
             String enddate = rs.getString("enddate");
+            //离职、补卡、请假、出差、加班
             if ("出差申请单".equals(odKind)){
-                saveAlitripList("Uas", startdate, enddate, 1, 50);
-            } else if ("".equals(odKind)) {
+                saveAlitripList(agentCode, startdate, enddate);
+            } else if ("请假申请单".equals(odKind)) {
+                saveLeaves(agentCode,DateUtil.parse(startdate,"yyyy-MM-dd HH:mm:ss").getTime(),DateUtil.parse(enddate,"yyyy-MM-dd HH:mm:ss").getTime());
+            } else if ("加班申请单".equals(odKind)) {
+
+            }else if ("补卡申请单".equals(odKind)) {
 
+            }else if ("离职申请单".equals(odKind)) {
+                saveEmpLeaveRecords(agentCode);
             }
         }
     }
     /**
      * 保存出差申请
      */
-    public void saveAlitripList(String agentCode, String startTime, String endTime, long offset, long limit) {
-        List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> alitripList = oaSdk.getAllAlitrip(agentCode,startTime,endTime,offset,limit);
+    public void saveAlitripList(String agentCode, String startTime, String endTime) {
+        List<OapiAlitripBtripApplySearchResponse.OpenApplyRs> alitripList = oaSdk.getAllAlitrip(agentCode,startTime,endTime);
         if (!CollectionUtils.isEmpty(alitripList)) {
+            logger.info("出差申请单alitripList==" + alitripList.size());
             for (OapiAlitripBtripApplySearchResponse.OpenApplyRs openApplyRs:alitripList) {
-                int id = getSeqId("FEEPLEASE_SEQ");
-                String code = callProcedure("Sp_GetMaxNumber", new Object[]{"FeePlease!CCSQ!new", 2});
-                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                String inDate = format.format(openApplyRs.getGmtCreate());
-                List<OapiAlitripBtripApplySearchResponse.OpenItineraryInfo> itineraryList = openApplyRs.getItineraryList();
-                String startDate = format.format(itineraryList.get(0).getDepDate());
-                String endDate = format.format(itineraryList.get(0).getArrDate());
+                String inDate = DateUtil.format(openApplyRs.getGmtCreate(),"yyyy-MM-dd HH:mm:ss");
                 Long rsId = openApplyRs.getId();
-                SqlRowSet rowSet = jdbcTemplate.queryForRowSet("select * from FeePlease where dp_ddid=" + rsId);
-                if (!rowSet.next()) {
-                    jdbcTemplate.execute("insert into FeePlease (fp_id,fp_code,fp_v9,FP_PEOPLE2,fp_recordman,fp_recorddate,fp_statuscode,fp_status,fp_v3,fp_prestartdate,fp_preenddate,fp_n6,) " +
-                            "values (" + id + ",'" + code + "','" + openApplyRs.getDeptName() + "','" + openApplyRs.getUserName() + "','" + openApplyRs.getUserName() + "',to_date('" + inDate + "','yyyy-MM-dd HH:mi:ss'),'AUDITED','已审核','" + openApplyRs.getTripCause() + "',to_date('" + startDate + "','yyyy-MM-dd HH:mi:ss'),to_date('" + endDate + "','yyyy-MM-dd HH:mi:ss')," + openApplyRs.getTripDay() + ")");
+                String statusDesc = openApplyRs.getStatusDesc()==null?"空":openApplyRs.getStatusDesc();
+                if (statusDesc.contains("已同意")){
+                    List<OapiAlitripBtripApplySearchResponse.OpenItineraryInfo> itineraryList = openApplyRs.getItineraryList();
+                    for (OapiAlitripBtripApplySearchResponse.OpenItineraryInfo openItineraryInfo:itineraryList) {
+                        String startDate = DateUtil.format(openItineraryInfo.getDepDate(),"yyyy-MM-dd HH:mm:ss");
+                        String endDate = DateUtil.format(openItineraryInfo.getArrDate(),"yyyy-MM-dd HH:mm:ss");
+                        String projectTitle = openItineraryInfo.getProjectTitle();
+                        String projectCode = openItineraryInfo.getProjectCode();
+                        String arrCity = openItineraryInfo.getArrCity();
+                        String depCity = openItineraryInfo.getDepCity();
+                        String itineraryId = openItineraryInfo.getItineraryId();
+                        String ddid=rsId.toString()+"-"+itineraryId;
+                        int count =queryForObject("select count(1) from FeePlease where fp_dingid='"+ddid+"'", Integer.class);
+                        if (count<=0) {
+                            int id = generateId("FEEPLEASE_SEQ");
+                            String code = generateCode("FeePlease!CCSQ!new", 2);
+                            jdbcTemplate.execute("insert into FeePlease (fp_id,fp_code,fp_kind,fp_v9,FP_PEOPLE2,fp_recordman,fp_recorddate,fp_statuscode,fp_status,fp_v3,fp_prestartdate,fp_preenddate,fp_n6,fp_dingid,fp_remark,fp_prjcode,fp_prjname,fp_depcity,fp_arrcity) " +
+                                    "values (" + id + ",'" + code + "','出差申请单','" + openApplyRs.getDeptName() + "','" + openApplyRs.getUserName() + "','" + openApplyRs.getUserName() + "',to_date('" + inDate + "','yyyy-MM-dd HH24:mi:ss'),'AUDITED','已审核','" + openApplyRs.getTripCause() + "',to_date('" + startDate + "','yyyy-MM-dd HH24:mi:ss'),to_date('" + endDate + "','yyyy-MM-dd HH24:mi:ss')," + openApplyRs.getTripDay() + ","+rsId+",'"+statusDesc+"','"+projectCode+"','"+projectTitle+"','"+depCity+"','"+arrCity+"')");
+                    /*jdbcTemplate.execute("insert into FeePleaseDetail(fpd_id,fpd_fpid,fpd_code,fpd_class,fpd_detno,fpd_d5,fpd_d6,fpd_date1,fpd_date2) " +
+                            "values(FeePleaseDetail_seq.nextval,"+id+",'"+code+"','出差申请单',1,'"+projectCode+"','"+projectTitle+"',to_date('" + startDate + "','yyyy-MM-dd HH24:mi:ss'),to_date('" + endDate + "','yyyy-MM-dd HH24:mi:ss'))");*/
+                        }
+                    }
                 }
             }
         }
     }
 
     /**
-     * 获取序列号
-     *
-     * @param seq
-     *            指定的序列名
+     * 保存离职申请
      */
-    private int getSeqId(String seq) {
-        try {
-            String sql = "select " + seq + ".nextval from dual";
-            SqlRowSet rs = jdbcTemplate.queryForRowSet(sql);
-            if (rs.next()) {
-                return rs.getInt(1);
-            } else {// 如果不存在就创建序列
-                SqlRowSet rowSet = jdbcTemplate.queryForRowSet("select * from user_sequences where Sequence_Name='" + seq.toUpperCase() + "'");
-                if (!rowSet.next()) {
-                    jdbcTemplate.execute(CREATE_SEQ.replace("?", seq));
+    public void saveEmpLeaveRecords(String agentCode) {
+        int count = queryForObject("select count(1) from employee where nvl(em_ding,' ')<>' '",Integer.class);
+        if (count>0) {
+            int size=50;
+            int con = (int) Math.ceil((double)count / size);
+            if (con>0) {
+                for (int j = 0; j < con; j++) {
+                    int min = j * size, max = (j + 1) * size;
+                    List<String> strings = new ArrayList<>();
+                    SqlRowSet rs = jdbcTemplate.queryForRowSet("select em_ding from (select em_ding,rownum rn from employee where nvl(em_ding,' ')<>' ') where rn>" + min + " and rn<=" + max);
+                    while (rs.next()) {
+                        strings.add(rs.getString("em_ding"));
+                    }
+                    List<OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo> empLeave = oaSdk.getEmpLeave(agentCode, strings);
+                    if (!CollectionUtils.isEmpty(empLeave)) {
+                        logger.info("离职申请单empLeave==" + empLeave.size());
+                        for (int i = 0; i < empLeave.size(); i++) {
+                            OapiSmartworkHrmEmployeeListdimissionResponse.EmpDimissionInfoVo empDimissionInfoVo = empLeave.get(i);
+                            String deptName = empDimissionInfoVo.getMainDeptName();
+                            String reasonMemo = empDimissionInfoVo.getReasonMemo();
+                            Long lastWorkDay = empDimissionInfoVo.getLastWorkDay();
+                            String leaves = null;
+                            if (lastWorkDay!=null&&lastWorkDay > 0) {
+                                leaves = DateUtil.format(new Date(lastWorkDay), "yyyy-MM-dd HH:mm:ss");
+                            }
+                            String userid = empDimissionInfoVo.getUserid();
+                            Long status = empDimissionInfoVo.getStatus();
+                            int count1 = queryForObject("select count(1) from Turnover where to_dingtalkid='" + userid + "'", Integer.class);
+                            if (count1 <= 0&&status==2) {
+                                int id = generateId("TURNOVER_SEQ");
+                                String code = generateCode("Turnover", 2);
+                                if (leaves != null) {
+                                    jdbcTemplate.execute("insert into Turnover (to_id,to_code,to_applymancode,to_applyman,to_leavedate,to_recordor,to_date,to_statuscode,to_status,to_otherreason,to_dingtalkid) " +
+                                            "select " + id + ",'" + code + "',em_code,em_name,to_date('" + leaves + "','yyyy-MM-dd HH24:mi:ss'),em_name,sysdate,'AUDITED','已审核','" + reasonMemo + "','" + userid + "' from employee where em_ding='" + userid + "'");
+                                } else {
+                                    jdbcTemplate.execute("insert into Turnover (to_id,to_code,to_applymancode,to_applyman,to_recordor,to_date,to_statuscode,to_status,to_otherreason,to_dingtalkid) " +
+                                            "select " + id + ",'" + code + "',em_code,em_name,em_name,sysdate,'AUDITED','已审核','" + reasonMemo + "','" + userid + "' from employee where em_ding='" + userid + "'");
+                                }
+                            }
+                        }
+                    }
                 }
-                return getSeqId(seq);
-            }
-        } catch (Exception e) {
-            SqlRowSet rowSet = jdbcTemplate.queryForRowSet("select * from user_sequences where Sequence_Name='" + seq.toUpperCase() + "'");
-            if (!rowSet.next()) {
-                jdbcTemplate.execute(CREATE_SEQ.replace("?", seq));
             }
-            return getSeqId(seq);
         }
     }
 
-     /**
-     * 调用存储过程
-     *
-     * @param procedureName
-     *            存储过程名称
-     * @param args
-     *            参数
-     * @return varchar类型结果
+    /**
+     * 请假申请
      */
-     private String callProcedure(final String procedureName, final Object... args) {
-        try {
-            return jdbcTemplate.execute(new CallableStatementCreator() {
-                @Override
-                public CallableStatement createCallableStatement(Connection conn) throws SQLException {
-                    StringBuffer storedProcName = new StringBuffer("{call ");
-                    int i = 0;
-                    storedProcName.append(procedureName + "(");
-                    for (i = 0; i < args.length; i++) {
-                        if (storedProcName.toString().contains("?")) {
-                            storedProcName.append(",");
-                        }
-                        storedProcName.append("?");
+    public void saveLeaves(String agentCode, long startTime, long endTime){
+        int count = queryForObject("select count(1) from employee where nvl(em_ding,' ')<>' '",Integer.class);
+        if (count>0){
+            int size=100;
+            int con = (int) Math.ceil((double)count / size);
+            if (con>0) {
+                for (int i = 0; i < con; i++) {
+                    int min = i * size, max = (i + 1) * size;
+                    List<String> strings = new ArrayList<>();
+                    SqlRowSet rs = jdbcTemplate.queryForRowSet("select em_ding from (select em_ding,rownum rn from employee where nvl(em_ding,' ')<>' ') where rn>" + min + " and rn<=" + max);
+                    while (rs.next()) {
+                        strings.add(rs.getString("em_ding"));
                     }
-                    if (storedProcName.toString().contains("?")) {
-                        storedProcName.append(",");
-                    }
-                    storedProcName.append("?");
-                    storedProcName.append(")}");
-                    CallableStatement cs = conn.prepareCall(storedProcName.toString());
-                    for (i = 0; i < args.length; i++) {
-                        cs.setObject(i + 1, args[i]);
+                    List<OapiAttendanceGetleavestatusResponse.LeaveStatusVO> leaveStatusVOS = oaSdk.getAllLeaves(agentCode, strings, startTime, endTime);
+                    if (!CollectionUtils.isEmpty(leaveStatusVOS)) {
+                        logger.info("请假申请单leaveStatusVOS==" + leaveStatusVOS.size());
+                        for (int j = 0; j < leaveStatusVOS.size(); j++) {
+                            OapiAttendanceGetleavestatusResponse.LeaveStatusVO leaveStatusVO = leaveStatusVOS.get(j);
+                            Long durationPercent = leaveStatusVO.getDurationPercent() / 100;
+                            String durationUnit = leaveStatusVO.getDurationUnit();
+                            Long startDate = leaveStatusVO.getStartTime();
+                            Long endDate = leaveStatusVO.getEndTime();
+                            String userid = leaveStatusVO.getUserid();
+                            String startformat = DateUtil.format(new Date(startDate), "yyyy-MM-dd HH:mm:ss");
+                            String endformat = DateUtil.format(new Date(endDate), "yyyy-MM-dd HH:mm:ss");
+                            int count1 = queryForObject("select count(1) from Vacation where va_dingtalkid='" + userid + "' and to_char(va_startime,'yyyy-MM-dd HH24:mi:ss')='" + startformat + "' and to_char(va_endtime,'yyyy-MM-dd HH24:mi:ss')='" + endformat + "'", Integer.class);
+                            if (count1 <= 0) {
+                                int id = generateId("VACATION_SEQ");
+                                String code = generateCode("Ask4Leave", 2);
+                                jdbcTemplate.execute("insert into Vacation (va_id,va_code,va_statuscode,va_status,va_emcode,va_emname,va_date,va_department,va_position,va_recordor,va_recordorid,va_days,va_alltimes,va_startime,va_endtime,va_remark,va_dingtalkid) " +
+                                        "select " + id + ",'" + code + "','AUDITED','已审核',em_code,em_name,sysdate,em_depart,em_position,em_name,em_id,case when '" + durationUnit + "'='percent_day' then " + durationPercent + " else 0 end,case when '" + durationUnit + "'='percent_hour' then " + durationPercent + " else 0 end,to_date('" + startformat + "','yyyy-MM-dd hh24:mi:ss'),to_date('" + endformat + "','yyyy-MM-dd hh24:mi:ss'),'钉钉同步','" + userid + "' from employee where em_ding='" + userid + "'");
+                            }
+                        }
                     }
-                    cs.registerOutParameter(args.length + 1, java.sql.Types.VARCHAR);
-                    return cs;
                 }
-            }, new CallableStatementCallback<String>() {
-                @Override
-                public String doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
-                    cs.execute();
-                    return cs.getString(args.length + 1);
-                }
-
-            });
-        } catch (Exception e) {
-            e.getMessage();
+            }
         }
-        return null;
     }
+
 }