Explorar o código

新增定时任务,用于统计售前台账未填写人员及未填写数量

lvjs hai 5 días
pai
achega
a63475f449

+ 55 - 0
src/main/java/com/malk/eastar/model/AITableParam.java

@@ -0,0 +1,55 @@
+package com.malk.eastar.model;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.base.BaseDto;
+
+/**
+ * AI表格数据处理客户端接口参数
+ */
+public class AITableParam extends BaseDto {
+
+    //每页获取的数据量,默认值为100,最小值为1,最大值为100
+    private Integer maxResults;
+
+    //上一次查询返回的游标,首次查询时不需要传
+    private String nextToken;
+
+    //筛选条件,设置后将只返回满足条件的记录
+    private JSONObject filter;
+
+    //操作数据
+    private JSONObject records;
+
+    public Integer getMaxResults() {
+        return maxResults;
+    }
+
+    public void setMaxResults(Integer maxResults) {
+        this.maxResults = maxResults;
+    }
+
+    public String getNextToken() {
+        return nextToken;
+    }
+
+    public void setNextToken(String nextToken) {
+        this.nextToken = nextToken;
+    }
+
+    public JSONObject getFilter() {
+        return filter;
+    }
+
+    public void setFilter(JSONObject filter) {
+        this.filter = filter;
+    }
+
+    public JSONObject getRecords() {
+        return records;
+    }
+
+    public void setRecords(JSONObject records) {
+        this.records = records;
+    }
+}

+ 49 - 0
src/main/java/com/malk/eastar/model/AITableResult.java

@@ -0,0 +1,49 @@
+package com.malk.eastar.model;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.server.common.VenR;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * AI表格数据处理客户端接口返回结果
+ * @param <T>
+ */
+public class AITableResult<T> extends VenR {
+
+    //是否有更多数据
+    private Boolean hasMore;
+
+    //分页游标
+    private String nextToken;
+
+    //记录数据列表
+    private JSONArray records;
+
+
+    public Boolean getHasMore() {
+        return hasMore;
+    }
+
+    public void setHasMore(Boolean hasMore) {
+        this.hasMore = hasMore;
+    }
+
+    public String getNextToken() {
+        return nextToken;
+    }
+
+    public void setNextToken(String nextToken) {
+        this.nextToken = nextToken;
+    }
+
+    public JSONArray getRecords() {
+        return records;
+    }
+
+    public void setRecords(JSONArray records) {
+        this.records = records;
+    }
+}

+ 202 - 5
src/main/java/com/malk/eastar/schedule/ScheduleTask.java

@@ -1,6 +1,12 @@
 package com.malk.eastar.schedule;
 package com.malk.eastar.schedule;
 
 
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+import com.malk.eastar.service.AITableClient;
 import com.malk.eastar.service.EastarTbService;
 import com.malk.eastar.service.EastarTbService;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.aliwork.YDParam;
@@ -11,6 +17,7 @@ import com.malk.utils.PublicUtil;
 import com.malk.utils.UtilDateTime;
 import com.malk.utils.UtilDateTime;
 import com.malk.utils.UtilMap;
 import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
@@ -18,12 +25,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.annotation.Scheduled;
 
 
 import java.time.LocalDate;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.LocalTime;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 
 /**
 /**
  * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
  * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
@@ -41,6 +44,11 @@ public class ScheduleTask {
     @Autowired
     @Autowired
     private YDService ydService;
     private YDService ydService;
 
 
+    //add by Jason 20260313 start
+    @Autowired
+    private AITableClient aiTableClient;
+    //add by Jason 20260313 end
+
     /**
     /**
      */
      */
     @Scheduled(cron = "0 0 8 * * ?")
     @Scheduled(cron = "0 0 8 * * ?")
@@ -121,4 +129,193 @@ public class ScheduleTask {
         }
         }
     }
     }
 
 
+    /**
+     * 项目总表表2未填写完成统计
+     * 每日8点50
+     */
+    @Scheduled(cron = "0 55 9 * * ?")
+    public void table2IncompleteStatistics() {
+        log.info("定时更新项目台账填写情况表");
+        /*
+            查询【表2】项目台账所有项目状态为Pending、Done、Closed的记录
+         */
+        JSONArray table2RecordsFilter = new JSONArray();
+        String baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        String sheetIdOrName = "pl6sz00";
+        Map<String,Object> param = new HashMap<>();
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        AITableParam aiTableParam = new AITableParam();
+        aiTableParam.setMaxResults(100);
+        JSONObject filter = new JSONObject();
+        filter.put("combination","and");
+        JSONArray conditions = new JSONArray();
+        JSONObject condition = new JSONObject();
+        condition.put("field","项目状态");
+        condition.put("operator","notContain");
+        condition.put("value",new String[]{"Pending","Done","Closed"});
+        conditions.add(condition);
+        filter.put("conditions",conditions);
+        aiTableParam.setFilter(filter);
+        AITableResult aiTableResult;
+        boolean hasMore = true;
+        int pageNo = 1;
+        JSONArray records;
+        while(hasMore){
+            aiTableResult = aiTableClient.queryMultiRecords(baseId,sheetIdOrName,param,aiTableParam);
+            hasMore = aiTableResult.getHasMore();
+            log.info("当前第"+pageNo+"页");
+            log.info("记录数="+aiTableResult.getRecords().size());
+            records = aiTableResult.getRecords();
+            for(int i=0;i<records.size();i++){
+                table2RecordsFilter.add(records.getJSONObject(i));
+            }
+            log.info("是否有更多数据:"+hasMore);
+            pageNo++;
+            aiTableParam.setNextToken(aiTableResult.getNextToken());
+        }
+        /*
+            统计计划开始时间和计划结束时间未填的
+         */
+        List<String> checkEmptyRecordList = new ArrayList<>();
+        String[] checkEmptyFieldArr = new String[]{
+                "计划:开始白样【交付进度】",
+                "计划:结束白样【交付进度】",
+                "计划:开始制版【交付进度】",
+                "计划:结束制版【交付进度】",
+                "计划:开始产前样【交付进度】",
+                "计划:结束产前样【交付进度】",
+                "计划:开始大货【交付进度】",
+                "计划:结束大货【交付进度】",
+                "计划:开始包装【交付进度】",
+                "计划:结束包装【交付进度】",
+                "计划:开始出货【交付进度】",
+                "计划:结束出货时间【交付进度】"
+        };
+        JSONObject table2Record;
+        JSONObject fields;
+        String unionIdPM;
+        String checkFailureStr;
+//        System.out.println("表2PM:");
+        for(int i=0;i<table2RecordsFilter.size();i++){
+            table2Record = table2RecordsFilter.getJSONObject(i);
+            fields = table2Record.getJSONObject("fields");
+            unionIdPM = fields.getJSONArray("PM(Owner)【人事】").getJSONObject(0).getString("unionId");
+            for(String checkEmptyField : checkEmptyFieldArr){
+                if(StringUtils.isEmpty(fields.getString(checkEmptyField))){
+                    checkFailureStr = unionIdPM + "_" + checkEmptyField+"未填写";
+//                    System.out.println(checkFailureStr);
+                    checkEmptyRecordList.add(checkFailureStr);
+                }
+            }
+        }
+        /*
+            查询【参数表-人事】部门为销售部、客服部的记录
+         */
+        JSONArray empRecordsFilter = new JSONArray();
+        sheetIdOrName = "rtOAveM";
+        aiTableParam = new AITableParam();
+        aiTableParam.setMaxResults(100);
+        filter = new JSONObject();
+        filter.put("combination","and");
+        conditions = new JSONArray();
+        condition = new JSONObject();
+        condition.put("field","部门");
+        condition.put("operator","contain");
+        condition.put("value",new String[]{"销售部","客服部"});
+        conditions.add(condition);
+        filter.put("conditions",conditions);
+        aiTableParam.setFilter(filter);
+        aiTableResult = aiTableClient.queryMultiRecords(baseId,sheetIdOrName,param,aiTableParam);
+        log.info("销售和PM人员记录数="+aiTableResult.getRecords().size());
+        records = aiTableResult.getRecords();
+        for(int i=0;i<records.size();i++){
+            empRecordsFilter.add(records.getJSONObject(i));
+        }
+        log.info("是否有更多数据:"+hasMore);
+        JSONObject empRecord;
+        String deptId;
+        String unionIdPMLeader;
+//        System.out.println("人员列表:");
+        Map<String,Object> unionIdMap = new HashMap<>();
+        for(int i=0; i<empRecordsFilter.size(); i++){
+            fields = empRecordsFilter.getJSONObject(i).getJSONObject("fields");
+            unionIdPM = fields.getJSONArray("人员").getJSONObject(0).getString("unionId");
+            deptId = fields.getJSONObject("部门").getString("id");
+            if(fields.getJSONArray("销售组长") != null){
+                unionIdPMLeader = fields.getJSONArray("销售组长").getJSONObject(0).getString("unionId");
+            }else{
+                unionIdPMLeader = "U2puyufsTtwvfTXmWQoG0wiEiE";
+            }
+//            System.out.println("unionIdPM="+unionIdPM+",deptId="+deptId+",unionIdPMLeader="+unionIdPMLeader);
+            empRecord = new JSONObject();
+            empRecord.put("deptId",deptId);
+            empRecord.put("unionIdPMLeader",unionIdPMLeader);
+            unionIdMap.put(unionIdPM,empRecord);
+        }
+        /*
+            新增项目台账填写情况表记录
+         */
+        JSONObject insertData = new JSONObject();
+        JSONArray insertRecords = new JSONArray();
+        JSONObject insertRecord;
+        JSONArray pmJSONArray;
+        JSONArray pmLeaderJSONArray;
+        JSONObject unionIdJSONObject;
+        for(String str : checkEmptyRecordList){
+            unionIdPM = str.split("_")[0];
+            empRecord = (JSONObject) unionIdMap.get(unionIdPM);
+            fields = new JSONObject();
+            fields.put("日期", DateUtil.today());
+            unionIdJSONObject = new JSONObject();
+            unionIdJSONObject.put("unionId",unionIdPM);
+            pmJSONArray = new JSONArray();
+            pmJSONArray.add(unionIdJSONObject);
+            fields.put("负责人",pmJSONArray);
+            unionIdJSONObject = new JSONObject();
+            unionIdJSONObject.put("unionId",empRecord.getString("unionIdPMLeader"));
+            pmLeaderJSONArray = new JSONArray();
+            pmLeaderJSONArray.add(unionIdJSONObject);
+            fields.put("组长",pmLeaderJSONArray);
+            fields.put("填写情况", str.split("_")[1]);
+            insertRecord = new JSONObject();
+            insertRecord.put("fields",fields);
+            log.info(JSON.toJSONString(insertRecord));
+            insertRecords.add(insertRecord);
+        }
+        String result;
+        JSONArray newInsertRecords;
+        sheetIdOrName = "OTgxt4G";
+        if(insertRecords.size() > 100){
+            pageNo = 1;
+            while(insertRecords.size() > 100){
+                newInsertRecords = new JSONArray();
+                records = new JSONArray();
+                for (int i = 0; i < insertRecords.size(); i++) {
+                    if(i<100){
+                        newInsertRecords.add(insertRecords.getJSONObject(i));
+                    }else{
+                        records.add(insertRecords.getJSONObject(i));
+                    }
+                }
+                insertData.put("records",newInsertRecords);
+                log.info(JSON.toJSONString(insertData));
+                result = aiTableClient.createMultiRecords(baseId,sheetIdOrName,param,insertData);
+                log.info("新增项目台账填写情况表记录结果,第"+pageNo+"页:");
+                log.info(result);
+                insertRecords = records;
+                pageNo++;
+            }
+        }
+        if(insertRecords.size() > 0){
+            insertData.put("records",insertRecords);
+            log.info(JSON.toJSONString(insertData));
+            sheetIdOrName = "OTgxt4G";
+            result = aiTableClient.createMultiRecords(baseId,sheetIdOrName,param,insertData);
+            log.info("新增项目台账填写情况表记录结果,第"+pageNo+"页:");
+            log.info(result);
+        }
+
+
+    }
+
 }
 }

+ 35 - 0
src/main/java/com/malk/eastar/service/AITableClient.java

@@ -0,0 +1,35 @@
+package com.malk.eastar.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+
+import java.util.Map;
+
+/**
+ * AI表格数据处理客户端接口
+ * add by Jason 20260313
+ */
+public interface AITableClient {
+
+    /**
+     * 查询多行记录
+     * @param baseId AI表格ID
+     * @param sheetIdOrName 数据表ID或数据表名称
+     * @param param Query参数
+     * @param aiTableParam Body参数
+     * @return
+     */
+    AITableResult queryMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, AITableParam aiTableParam);
+
+
+    /**
+     * 创建多行记录
+     * @param baseId AI表格ID
+     * @param sheetIdOrName 数据表ID或数据表名称
+     * @param param Query参数
+     * @param body Body参数
+     * @return
+     */
+    String createMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, JSONObject body);
+}

+ 50 - 0
src/main/java/com/malk/eastar/service/impl/AITableClientImpl.java

@@ -0,0 +1,50 @@
+package com.malk.eastar.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+import com.malk.eastar.service.AITableClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.utils.UtilHttp;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * AI表格数据处理客户端接口实现
+ * add by Jason 20260313
+ */
+@Service
+public class AITableClientImpl implements AITableClient {
+
+    @Autowired
+    private DDClient ddClient;
+
+    private String getRequestUrl(String uri) {
+        return "https://api.dingtalk.com/v1.0/notable" + uri;
+    }
+
+    private Map initBodyParam(AITableParam aiTableParam) {
+        return (Map) JSONObject.parseObject(JSONObject.toJSONString(aiTableParam), Map.class);
+    }
+
+    @Override
+    public AITableResult queryMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, AITableParam aiTableParam) {
+        String url = getRequestUrl("/bases/"+baseId+"/sheets/"+sheetIdOrName+"/records/list");
+        Map header = ddClient.initTokenHeader();
+        Map body = initBodyParam(aiTableParam);
+        AITableResult aiTableResult = (AITableResult) UtilHttp.doPost(url,header,param,body,AITableResult.class);
+        return aiTableResult;
+    }
+
+    @Override
+    public String createMultiRecords(String baseId, String sheetIdOrName, Map<String, Object> param, JSONObject body) {
+        String url = getRequestUrl("/bases/"+baseId+"/sheets/"+sheetIdOrName+"/records");
+        Map header = ddClient.initTokenHeader();
+        Map form = new HashMap();
+        String result = UtilHttp.doPost(url,header,param,body,form);
+        return result;
+    }
+}