|
|
@@ -0,0 +1,312 @@
|
|
|
+package com.malk.cloudpure.controller;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.malk.server.common.McException;
|
|
|
+import com.malk.server.common.McR;
|
|
|
+import com.malk.server.dingtalk.DDConf;
|
|
|
+import com.malk.service.dingtalk.DDClient;
|
|
|
+import com.malk.service.h3yun.CYClient;
|
|
|
+import com.malk.utils.UtilMap;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 氚云数据接口
|
|
|
+ *
|
|
|
+ * 功能说明:
|
|
|
+ * 1. 查询客户是否存在:传入客户名称,查询氚云客户表
|
|
|
+ * 2. 提交待审批数据:传入氚云字段键值对,在氚云发起提交
|
|
|
+ * 3. 查询客户最新机会:传入客户编码,查询氚云客户机会表最新一条
|
|
|
+ * 4. 查询客户最新合同:传入客户编码,查询氚云合同表最新一条
|
|
|
+ *
|
|
|
+ * 错误抛出与拦截详见 CatchException
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@RequestMapping("h3yun")
|
|
|
+public class H3yunController {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CYClient cyClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DDClient ddClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DDConf ddConf;
|
|
|
+
|
|
|
+ // ===================== 氚云表单编码常量 =====================
|
|
|
+ // TODO: 请替换为实际的氚云表单编码(SchemaCode)
|
|
|
+
|
|
|
+ /** 客户表SchemaCode */
|
|
|
+ private static final String SCHEMA_CUSTOMER = "D00086786d02a447942405d9e27821538a57834";
|
|
|
+
|
|
|
+ /** 客户机会表SchemaCode */
|
|
|
+ private static final String SCHEMA_CUSTOMER_OPPORTUNITY = "D000867wjisvgvjybui6620yj2a8ad53";
|
|
|
+
|
|
|
+ /** 合同表SchemaCode */
|
|
|
+ private static final String SCHEMA_CONTRACT = "D000867fhlpdb6a82f59spkf1vzac5p1";
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // ===================== 氚云用户表 =====================
|
|
|
+ /** 氚云用户系统表SchemaCode,用于通过钉钉userId查询氚云userId */
|
|
|
+ private static final String SCHEMA_H_USER = "D000867sme291ffe61b834a8ea7456f8b9a0ccc29";
|
|
|
+
|
|
|
+ // ===================== 客户表字段编码 =====================
|
|
|
+ // TODO: 请替换为实际的字段编码
|
|
|
+
|
|
|
+ /** 客户名称 */
|
|
|
+ private static final String FIELD_CUSTOMER_NAME = "F0000001";
|
|
|
+
|
|
|
+ /** 客户创建人氚云ID -默认夕瑶*/
|
|
|
+ // private static final String opUserId = "37a89511-6a83-4ee5-aa06-b6a6744a9bb0";
|
|
|
+
|
|
|
+ // ===================== 客户机会表字段编码 =====================
|
|
|
+
|
|
|
+ /** 机会编号 */
|
|
|
+ private static final String FIELD_OPP_CODE = "SeqNo";
|
|
|
+
|
|
|
+ /* 意向产品 */
|
|
|
+ private static final String Desired_Product = "D000867F4941a772370545088cef9366ee01aaca";
|
|
|
+
|
|
|
+ /** 成单信心 */
|
|
|
+ private static final String Order_Placement_Confidence = "F0000028";
|
|
|
+
|
|
|
+ /** 预计成交日期 */
|
|
|
+ private static final String Estimated_Closing_Date = "F0000007";
|
|
|
+ /** 预估GMV */
|
|
|
+ private static final String Estimated_GMV = "F0000031";
|
|
|
+ /** 预估CASH */
|
|
|
+ private static final String Estimated_CASH = "F0000035";
|
|
|
+ /** 商机阶段 */
|
|
|
+ private static final String Opportunity_Stage = "F0000019";
|
|
|
+ /** 流失原因 */
|
|
|
+ private static final String Reasons_Loss = "F0000042";
|
|
|
+
|
|
|
+
|
|
|
+ /** 新建机会表-客户编码(关联字段)-查询机会用 */
|
|
|
+ private static final String FIELD_OPP_CUSTOMER_CODE = "F0000041";
|
|
|
+
|
|
|
+ // ===================== 合同表字段编码 =====================
|
|
|
+
|
|
|
+ /** 合同编号 */
|
|
|
+ private static final String FIELD_CONTRACT_CODE = "SeqNo";
|
|
|
+ /** 实际成交GMV-合同总金额 */
|
|
|
+ private static final String FIELD_CONTRACT_ACTUAL_GMV = "F0000062";
|
|
|
+ /** 计收CASH *///先不加
|
|
|
+// private static final String FIELD_CONTRACT_CASH = "F0000003";
|
|
|
+ /** 回款金额 */
|
|
|
+ private static final String Payment_Collection_Time = "F0000099";
|
|
|
+
|
|
|
+ /** 客户编码(关联字段)-查询合同用 */
|
|
|
+ private static final String FIELD_CONTRACT_CUSTOMER_CODE = "F0000098";
|
|
|
+
|
|
|
+ // ===================== 系统字段 =====================
|
|
|
+
|
|
|
+ /** 创建时间(氚云系统字段) */
|
|
|
+ private static final String FIELD_CREATED_TIME = "CreatedTime";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 需求1: 查询客户是否存在
|
|
|
+ * 传入客户名称,在氚云客户表中查询该客户是否存在
|
|
|
+ * 存在返回"是",不存在返回"否"
|
|
|
+ *
|
|
|
+ * @param data 请求参数,包含 customerName 客户名称
|
|
|
+ * @return "是" 或 "否"
|
|
|
+ */
|
|
|
+ @PostMapping("customer/check")
|
|
|
+ McR checkCustomerExists(@RequestBody Map<String, String> data) {
|
|
|
+
|
|
|
+ log.info("查询客户是否存在, {}", data);
|
|
|
+ McException.assertParamException_Null(data, "customerName");
|
|
|
+
|
|
|
+ String customerName = data.get("customerName");
|
|
|
+ String accessToken = ddClient.getAccessToken();
|
|
|
+
|
|
|
+ // 构建查询条件:客户名称 = 传入值
|
|
|
+ Map matcher = UtilMap.map("Type, Name, Operator, Value", "Item", FIELD_CUSTOMER_NAME, 2, customerName);
|
|
|
+ Map extInfo = UtilMap.map("matcherJson", JSON.toJSONString(matcher));
|
|
|
+ extInfo.put("pageSize", 10);
|
|
|
+ extInfo.put("pageNumber", 1);
|
|
|
+
|
|
|
+ List<Map> result = cyClient.queryData(accessToken, SCHEMA_CUSTOMER, extInfo);
|
|
|
+
|
|
|
+ boolean exists = result != null && !result.isEmpty();
|
|
|
+ log.info("客户查询结果, customerName: {}, exists: {}", customerName, exists);
|
|
|
+
|
|
|
+ return McR.success(exists ? "是" : "否");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 需求2: 提交待审批数据
|
|
|
+ * 传入氚云字段键值对,在氚云发起一条提交待审批数据
|
|
|
+ *
|
|
|
+ * 流程说明:
|
|
|
+ * 1. 直接将传入的JSON作为氚云表单数据
|
|
|
+ * 2. 创建草稿数据
|
|
|
+ * 3. 提交数据(发起审批流程)
|
|
|
+ *
|
|
|
+ * @param data 氚云字段键值对,如 {"F0000014":"KH-00001","F0000001":"测试客户","F0000015":"转单中"}
|
|
|
+ * @return 提交结果,包含bizObjectId
|
|
|
+ */
|
|
|
+ @PostMapping("data/submit")
|
|
|
+ McR submitData(@RequestBody Map<String, Object> data) {
|
|
|
+
|
|
|
+ log.info("提交待审批数据到氚云, {}", data);
|
|
|
+
|
|
|
+ String accessToken = ddClient.getAccessToken();
|
|
|
+ String opUserId ="";
|
|
|
+ if (data.get("CRNAME").toString()!=""){
|
|
|
+ opUserId = _getCYUserIdByDingTalkUserId(data.get("CRNAME").toString());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 第一步:创建草稿数据(传入的JSON直接作为氚云表单数据)
|
|
|
+ Map extInfo = UtilMap.map("opUserId, bizObjectJson, isDraft", opUserId, JSON.toJSONString(data), true);
|
|
|
+ Map rsp = cyClient.operateData(accessToken, SCHEMA_CUSTOMER, extInfo);
|
|
|
+
|
|
|
+ // 第二步:提交数据(发起审批流程)
|
|
|
+ String bizObjectId = String.valueOf(rsp.get("bizObjectId"));
|
|
|
+ cyClient.operateData(accessToken, SCHEMA_CUSTOMER, UtilMap.map("bizObjectId, opUserId", bizObjectId, opUserId));
|
|
|
+
|
|
|
+ log.info("提交待审批数据成功, schemaCode: {}, bizObjectId: {}", SCHEMA_CUSTOMER, bizObjectId);
|
|
|
+ return McR.success(UtilMap.map("bizObjectId", bizObjectId));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过钉钉userId查询对应的氚云userId
|
|
|
+ * 氚云H_User系统表中,F0000003为DingTalkAccount字段,F0000002为氚云用户ID字段
|
|
|
+ */
|
|
|
+ private String _getCYUserIdByDingTalkUserId(String dingTalkUserId) {
|
|
|
+ Map extInfo = UtilMap.map("matcherJson", JSON.toJSONString(UtilMap.map("Type, Name, Operator, Value", "Item", "F0000001", 2, dingTalkUserId)));
|
|
|
+ List<Map> userList = cyClient.queryData(ddClient.getAccessToken(), SCHEMA_H_USER, extInfo);
|
|
|
+ if (userList != null && !userList.isEmpty()) {
|
|
|
+ return String.valueOf(userList.get(0).get("F0000003"));
|
|
|
+ }
|
|
|
+ log.warn("未找到钉钉用户对应的氚云用户, dingTalkUserId: {}", dingTalkUserId);
|
|
|
+ return dingTalkUserId;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 需求3: 查询客户最新机会
|
|
|
+ * 传入客户编码,查询氚云客户机会表中该客户的数据
|
|
|
+ * 取创建时间最新的一条,返回:机会编号、回款日期、回款金额
|
|
|
+ *
|
|
|
+ * @param data 请求参数,包含 customerCode 客户编码
|
|
|
+ * @return 最新一条机会数据,若无数据返回null
|
|
|
+ */
|
|
|
+ @PostMapping("opportunity/latest")
|
|
|
+ McR queryLatestOpportunity(@RequestBody Map<String, String> data) {
|
|
|
+
|
|
|
+ log.info("查询客户最新机会, {}", data);
|
|
|
+ McException.assertParamException_Null(data, "customerCode");
|
|
|
+
|
|
|
+ String customerCode = data.get("customerCode");
|
|
|
+ String accessToken = ddClient.getAccessToken();
|
|
|
+
|
|
|
+ // 构建查询条件:客户编码匹配
|
|
|
+ Map matcher = UtilMap.map("Type, Name, Operator, Value", "Item", FIELD_OPP_CUSTOMER_CODE, 2, customerCode);
|
|
|
+ Map extInfo = UtilMap.map("matcherJson", JSON.toJSONString(matcher));
|
|
|
+ extInfo.put("pageSize", 100);
|
|
|
+ extInfo.put("pageNumber", 1);
|
|
|
+
|
|
|
+ // 按创建时间降序排序,获取最新一条
|
|
|
+ List<Map> sortByFields = new ArrayList<>();
|
|
|
+ sortByFields.add(UtilMap.map("fieldName, direction", FIELD_CREATED_TIME, "Descending"));
|
|
|
+ extInfo.put("sortByFields", sortByFields);
|
|
|
+
|
|
|
+ // 只返回需要的字段
|
|
|
+ extInfo.put("returnFields", Arrays.asList(FIELD_OPP_CODE, Desired_Product, Order_Placement_Confidence,Estimated_Closing_Date,Estimated_GMV,Estimated_CASH, Opportunity_Stage,Reasons_Loss,FIELD_CREATED_TIME));
|
|
|
+
|
|
|
+ List<Map> result = cyClient.queryData(accessToken, SCHEMA_CUSTOMER_OPPORTUNITY, extInfo);
|
|
|
+
|
|
|
+ if (result == null || result.isEmpty()) {
|
|
|
+ log.info("未查询到客户机会, customerCode: {}", customerCode);
|
|
|
+ return McR.success(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取创建时间最新的一条
|
|
|
+ Map latest = result.get(0);
|
|
|
+ Map<String, Object> response = new HashMap<>();
|
|
|
+ response.put("opportunityCode", UtilMap.getString(latest, FIELD_OPP_CODE));
|
|
|
+ List<Map> desiredProductRows = (List<Map>) latest.get("D000867F4941a772370545088cef9366ee01aaca");
|
|
|
+ String desiredProductStr = "";
|
|
|
+ if (desiredProductRows != null && !desiredProductRows.isEmpty()) {
|
|
|
+ List<String> values = new ArrayList<>();
|
|
|
+ for (Map row : desiredProductRows) {
|
|
|
+ String val = String.valueOf(row.get("F0000043"));
|
|
|
+ if (val != null && !"null".equals(val) && !val.isEmpty()) {
|
|
|
+ values.add(val);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ desiredProductStr = String.join(";", values);
|
|
|
+ }
|
|
|
+ response.put("Desired_Product", desiredProductStr);//意向产品明细表 -名称用;隔开
|
|
|
+ response.put("Order_Placement_Confidence", UtilMap.getString(latest, Order_Placement_Confidence));
|
|
|
+ response.put("Estimated_Closing_Date", UtilMap.getString(latest, Estimated_Closing_Date));
|
|
|
+ response.put("Estimated_GMV", UtilMap.getString(latest, Estimated_GMV));
|
|
|
+ response.put("Estimated_CASH", UtilMap.getString(latest, Estimated_CASH));
|
|
|
+ response.put("Opportunity_Stage", UtilMap.getString(latest, Opportunity_Stage));
|
|
|
+ response.put("Reasons_Loss", UtilMap.getString(latest, Reasons_Loss));
|
|
|
+ response.put("FIELD_CREATED_TIME", UtilMap.getString(latest, FIELD_CREATED_TIME));
|
|
|
+ log.info("查询客户最新机会结果, customerCode: {}, result: {}", customerCode, response);
|
|
|
+ return McR.success(response);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 需求4: 查询客户最新合同
|
|
|
+ * 传入客户编码,查询氚云合同表中该客户的数据
|
|
|
+ * 取创建时间最新的一条,返回:合同编号、实际成交GMV、计收CASH、回款金额
|
|
|
+ *
|
|
|
+ * @param data 请求参数,包含 customerCode 客户编码
|
|
|
+ * @return 最新一条合同数据,若无数据返回null
|
|
|
+ */
|
|
|
+ @PostMapping("contract/latest")
|
|
|
+ McR queryLatestContract(@RequestBody Map<String, String> data) {
|
|
|
+
|
|
|
+ log.info("查询客户最新合同, {}", data);
|
|
|
+ McException.assertParamException_Null(data, "customerCode");
|
|
|
+
|
|
|
+ String customerCode = data.get("customerCode");
|
|
|
+ String accessToken = ddClient.getAccessToken();
|
|
|
+
|
|
|
+ // 构建查询条件:客户编码匹配
|
|
|
+ Map matcher = UtilMap.map("Type, Name, Operator, Value", "Item", FIELD_CONTRACT_CUSTOMER_CODE, 2, customerCode);
|
|
|
+ Map extInfo = UtilMap.map("matcherJson", JSON.toJSONString(matcher));
|
|
|
+ extInfo.put("pageSize", 100);
|
|
|
+ extInfo.put("pageNumber", 1);
|
|
|
+
|
|
|
+ // 按创建时间降序排序,获取最新一条
|
|
|
+ List<Map> sortByFields = new ArrayList<>();
|
|
|
+ sortByFields.add(UtilMap.map("fieldName, direction", FIELD_CREATED_TIME, "Descending"));
|
|
|
+ extInfo.put("sortByFields", sortByFields);
|
|
|
+
|
|
|
+ // 只返回需要的字段
|
|
|
+ extInfo.put("returnFields", Arrays.asList(FIELD_CONTRACT_CODE, FIELD_CONTRACT_ACTUAL_GMV, Payment_Collection_Time, FIELD_CREATED_TIME));
|
|
|
+
|
|
|
+ List<Map> result = cyClient.queryData(accessToken, SCHEMA_CONTRACT, extInfo);
|
|
|
+
|
|
|
+ if (result == null || result.isEmpty()) {
|
|
|
+ log.info("未查询到合同, customerCode: {}", customerCode);
|
|
|
+ return McR.success(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取创建时间最新的一条
|
|
|
+ Map latest = result.get(0);
|
|
|
+ Map<String, Object> response = new HashMap<>();
|
|
|
+ response.put("contractCode", UtilMap.getString(latest, FIELD_CONTRACT_CODE));
|
|
|
+ response.put("actualGMV", latest.get(FIELD_CONTRACT_ACTUAL_GMV));
|
|
|
+ // response.put("cash", latest.get(FIELD_CONTRACT_CASH));
|
|
|
+ response.put("Payment_Collection_Time", latest.get(Payment_Collection_Time));
|
|
|
+
|
|
|
+ log.info("查询客户最新合同结果, customerCode: {}, result: {}", customerCode, response);
|
|
|
+ return McR.success(response);
|
|
|
+ }
|
|
|
+}
|