|
@@ -2,8 +2,11 @@ package com.malk.minglei.service.impl.yida;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.malk.minglei.config.YidaApplicationsProperties;
|
|
import com.malk.minglei.config.YidaApplicationsProperties;
|
|
|
|
|
+import com.malk.minglei.dto.EmployeeRosterInfo;
|
|
|
import com.malk.minglei.dto.ErpYidaPushMainData;
|
|
import com.malk.minglei.dto.ErpYidaPushMainData;
|
|
|
import com.malk.minglei.dto.ErpYidaPushRequest;
|
|
import com.malk.minglei.dto.ErpYidaPushRequest;
|
|
|
|
|
+import com.malk.minglei.service.employee.EmployeeRosterService;
|
|
|
|
|
+import com.malk.minglei.service.yida.MingleiDocumentService;
|
|
|
import com.malk.minglei.service.yida.YidaFormPushHandler;
|
|
import com.malk.minglei.service.yida.YidaFormPushHandler;
|
|
|
import com.malk.minglei.service.yida.YidaProcessOpenApiClient;
|
|
import com.malk.minglei.service.yida.YidaProcessOpenApiClient;
|
|
|
import com.malk.server.common.McException;
|
|
import com.malk.server.common.McException;
|
|
@@ -15,7 +18,9 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDate;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
import java.time.ZoneId;
|
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedHashMap;
|
|
@@ -35,6 +40,7 @@ public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
private static final String FORM_UUID = "FORM-8454FA17732746058A2D90B1C559CC19G5SR";
|
|
private static final String FORM_UUID = "FORM-8454FA17732746058A2D90B1C559CC19G5SR";
|
|
|
private static final String PROCESS_CODE = "TPROC--9VD66QA18AJ8317KK3NXM54W1HIT30C7N28TM7";
|
|
private static final String PROCESS_CODE = "TPROC--9VD66QA18AJ8317KK3NXM54W1HIT30C7N28TM7";
|
|
|
private static final String DEFAULT_ORIGINATOR_USER_ID = "41603502201288023";
|
|
private static final String DEFAULT_ORIGINATOR_USER_ID = "41603502201288023";
|
|
|
|
|
+ private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
|
|
private static final String TITLE_FIELD_ID = "textField_msh27unu";
|
|
private static final String TITLE_FIELD_ID = "textField_msh27unu";
|
|
|
private static final String APPLICANT_FIELD_ID = "employeeField_msh186rr";
|
|
private static final String APPLICANT_FIELD_ID = "employeeField_msh186rr";
|
|
@@ -86,6 +92,8 @@ public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
private final YidaProcessOpenApiClient yidaProcessOpenApiClient;
|
|
private final YidaProcessOpenApiClient yidaProcessOpenApiClient;
|
|
|
private final DDConf dingTalkConfiguration;
|
|
private final DDConf dingTalkConfiguration;
|
|
|
private final YidaApplicationsProperties applications;
|
|
private final YidaApplicationsProperties applications;
|
|
|
|
|
+ private final EmployeeRosterService employeeRosterService;
|
|
|
|
|
+ private final MingleiDocumentService mingleiDocumentService;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 创建销售订单审批推送处理器。
|
|
* 创建销售订单审批推送处理器。
|
|
@@ -93,13 +101,19 @@ public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
* @param yidaProcessOpenApiClient 宜搭流程 OpenAPI 客户端
|
|
* @param yidaProcessOpenApiClient 宜搭流程 OpenAPI 客户端
|
|
|
* @param dingTalkConfiguration 钉钉应用配置
|
|
* @param dingTalkConfiguration 钉钉应用配置
|
|
|
* @param applications 宜搭应用配置
|
|
* @param applications 宜搭应用配置
|
|
|
|
|
+ * @param employeeRosterService 员工花名册,用于把业务人员工号换成钉钉用户 ID
|
|
|
|
|
+ * @param mingleiDocumentService 部门配置查询,用于按业务人员取钉钉部门
|
|
|
*/
|
|
*/
|
|
|
public ApproveOrderFormPushHandler(YidaProcessOpenApiClient yidaProcessOpenApiClient,
|
|
public ApproveOrderFormPushHandler(YidaProcessOpenApiClient yidaProcessOpenApiClient,
|
|
|
DDConf dingTalkConfiguration,
|
|
DDConf dingTalkConfiguration,
|
|
|
- YidaApplicationsProperties applications) {
|
|
|
|
|
|
|
+ YidaApplicationsProperties applications,
|
|
|
|
|
+ EmployeeRosterService employeeRosterService,
|
|
|
|
|
+ MingleiDocumentService mingleiDocumentService) {
|
|
|
this.yidaProcessOpenApiClient = yidaProcessOpenApiClient;
|
|
this.yidaProcessOpenApiClient = yidaProcessOpenApiClient;
|
|
|
this.dingTalkConfiguration = dingTalkConfiguration;
|
|
this.dingTalkConfiguration = dingTalkConfiguration;
|
|
|
this.applications = applications;
|
|
this.applications = applications;
|
|
|
|
|
+ this.employeeRosterService = employeeRosterService;
|
|
|
|
|
+ this.mingleiDocumentService = mingleiDocumentService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -180,15 +194,14 @@ public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
putIfNotBlank(formData, APPLICANT_FIELD_ID, toStringList(operatorUserId, null));
|
|
putIfNotBlank(formData, APPLICANT_FIELD_ID, toStringList(operatorUserId, null));
|
|
|
putIfNotBlank(formData, COMPANY_FIELD_ID, firstNonBlank(value(main, "gs", "applyCompany", "company"), value(main, "xmdaent")));
|
|
putIfNotBlank(formData, COMPANY_FIELD_ID, firstNonBlank(value(main, "gs", "applyCompany", "company"), value(main, "xmdaent")));
|
|
|
putIfNotBlank(formData, DEPARTMENT_FIELD_ID, toStringList(value(main, "bm", "applyDepartment", "department", "deptId"), null));
|
|
putIfNotBlank(formData, DEPARTMENT_FIELD_ID, toStringList(value(main, "bm", "applyDepartment", "department", "deptId"), null));
|
|
|
- putIfNotBlank(formData, APPLY_DATE_FIELD_ID, toDateMillis(firstNonBlank(value(main, "rq", "applyDate"), value(main, "xmdadocdt"))));
|
|
|
|
|
|
|
+ putIfNotBlank(formData, APPLY_DATE_FIELD_ID, toDateTimeMillis(mostPreciseDate(
|
|
|
|
|
+ value(main, "rq"), value(main, "applyDate"), value(main, "xmdadocdt"))));
|
|
|
putIfNotBlank(formData, FORM_TITLE_FIELD_ID, title);
|
|
putIfNotBlank(formData, FORM_TITLE_FIELD_ID, title);
|
|
|
putIfNotBlank(formData, URGENCY_FIELD_ID, firstNonBlank(value(main, "urgency"), "正常"));
|
|
putIfNotBlank(formData, URGENCY_FIELD_ID, firstNonBlank(value(main, "urgency"), "正常"));
|
|
|
putIfNotBlank(formData, ENTERPRISE_NO_FIELD_ID, value(main, "xmdaent"));
|
|
putIfNotBlank(formData, ENTERPRISE_NO_FIELD_ID, value(main, "xmdaent"));
|
|
|
putIfNotBlank(formData, ORDER_NO_FIELD_ID, value(main, "xmdadocno"));
|
|
putIfNotBlank(formData, ORDER_NO_FIELD_ID, value(main, "xmdadocno"));
|
|
|
putIfNotBlank(formData, ORDER_DATE_FIELD_ID, toDateMillis(value(main, "xmdadocdt")));
|
|
putIfNotBlank(formData, ORDER_DATE_FIELD_ID, toDateMillis(value(main, "xmdadocdt")));
|
|
|
putIfNotBlank(formData, VERSION_FIELD_ID, toDecimal(value(main, "xmda001")));
|
|
putIfNotBlank(formData, VERSION_FIELD_ID, toDecimal(value(main, "xmda001")));
|
|
|
- putIfNotBlank(formData, SALES_PERSON_FIELD_ID, toStringList(value(main, "xmda002"), null));
|
|
|
|
|
- putIfNotBlank(formData, SALES_DEPARTMENT_FIELD_ID, toStringList(value(main, "xmda003"), null));
|
|
|
|
|
putIfNotBlank(formData, CUSTOMER_CODE_FIELD_ID, value(main, "xmda004"));
|
|
putIfNotBlank(formData, CUSTOMER_CODE_FIELD_ID, value(main, "xmda004"));
|
|
|
putIfNotBlank(formData, CUSTOMER_SHORT_NAME_FIELD_ID, value(main, "pmaal004"));
|
|
putIfNotBlank(formData, CUSTOMER_SHORT_NAME_FIELD_ID, value(main, "pmaal004"));
|
|
|
putIfNotBlank(formData, ORDER_TYPE_FIELD_ID, value(main, "xmda005"));
|
|
putIfNotBlank(formData, ORDER_TYPE_FIELD_ID, value(main, "xmda005"));
|
|
@@ -208,6 +221,9 @@ public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
formData.put(DETAIL_TABLE_FIELD_ID, orderRows);
|
|
formData.put(DETAIL_TABLE_FIELD_ID, orderRows);
|
|
|
}
|
|
}
|
|
|
copyYidaFieldValues(main, formData);
|
|
copyYidaFieldValues(main, formData);
|
|
|
|
|
+ String salesUserId = resolveSalesUserId(value(main, "xmda002"));
|
|
|
|
|
+ putIfNotBlank(formData, SALES_PERSON_FIELD_ID, toStringList(salesUserId, null));
|
|
|
|
|
+ putIfNotBlank(formData, SALES_DEPARTMENT_FIELD_ID, toStringList(resolveSalesDepartmentId(salesUserId), null));
|
|
|
return formData;
|
|
return formData;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -310,14 +326,99 @@ public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
return new BigDecimal(String.valueOf(value).trim());
|
|
return new BigDecimal(String.valueOf(value).trim());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 业务人员工号 xmda002 查花名册,得到钉钉用户 ID。
|
|
|
|
|
+ */
|
|
|
|
|
+ private String resolveSalesUserId(Object employeeNoValue) {
|
|
|
|
|
+ String employeeNo = toText(employeeNoValue);
|
|
|
|
|
+ if (employeeNo == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (employeeRosterService == null) {
|
|
|
|
|
+ throw new IllegalStateException("Employee roster service is not configured");
|
|
|
|
|
+ }
|
|
|
|
|
+ EmployeeRosterInfo employee = employeeRosterService.findByEmployeeNo(employeeNo);
|
|
|
|
|
+ if (employee == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("axmt500 sales person not found: " + employeeNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ String dingtalkId = toText(employee.getDingtalkId());
|
|
|
|
|
+ if (dingtalkId == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("axmt500 sales person has no DingTalk userId: " + employeeNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ return dingtalkId;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 业务部门取业务人员在钉钉的主部门。xmda003 是 T100 部门代号,部门组件无法直接使用。
|
|
|
|
|
+ */
|
|
|
|
|
+ private String resolveSalesDepartmentId(String salesUserId) {
|
|
|
|
|
+ if (salesUserId == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (mingleiDocumentService == null) {
|
|
|
|
|
+ throw new IllegalStateException("Department service is not configured");
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> configuration = mingleiDocumentService.queryApplicantDepartmentConfiguration(salesUserId);
|
|
|
|
|
+ String departmentId = configuration == null ? null : toText(configuration.get("departmentId"));
|
|
|
|
|
+ if (departmentId == null) {
|
|
|
|
|
+ throw new IllegalArgumentException("axmt500 sales department not found for user: " + salesUserId);
|
|
|
|
|
+ }
|
|
|
|
|
+ return departmentId;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 在日期候选里优先使用带时分秒的值。
|
|
|
|
|
+ */
|
|
|
|
|
+ private Object mostPreciseDate(Object first, Object second, Object third) {
|
|
|
|
|
+ Object selected = null;
|
|
|
|
|
+ for (Object candidate : new Object[]{first, second, third}) {
|
|
|
|
|
+ if (isBlank(candidate)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (selected == null) {
|
|
|
|
|
+ selected = candidate;
|
|
|
|
|
+ }
|
|
|
|
|
+ String text = String.valueOf(candidate);
|
|
|
|
|
+ if (text.indexOf(':') >= 0 || text.indexOf('T') >= 0) {
|
|
|
|
|
+ return candidate;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return selected;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private Long toDateMillis(Object value) {
|
|
private Long toDateMillis(Object value) {
|
|
|
|
|
+ return toDateTimeMillis(value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 带时分秒的文本保留到秒,只有日期时仍取当天 0 点。
|
|
|
|
|
+ */
|
|
|
|
|
+ private Long toDateTimeMillis(Object value) {
|
|
|
if (isBlank(value)) {
|
|
if (isBlank(value)) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
- String text = String.valueOf(value).trim();
|
|
|
|
|
|
|
+ String text = String.valueOf(value).trim().replace('/', '-');
|
|
|
if (text.matches("\\d+")) {
|
|
if (text.matches("\\d+")) {
|
|
|
return Long.valueOf(text);
|
|
return Long.valueOf(text);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (text.indexOf(':') >= 0 || text.indexOf('T') >= 0) {
|
|
|
|
|
+ String normalized = text.replace('T', ' ');
|
|
|
|
|
+ int zoneIndex = normalized.indexOf('+');
|
|
|
|
|
+ if (zoneIndex < 0 && normalized.lastIndexOf('-') > 10) {
|
|
|
|
|
+ zoneIndex = normalized.lastIndexOf('-');
|
|
|
|
|
+ }
|
|
|
|
|
+ if (zoneIndex > 10) {
|
|
|
|
|
+ normalized = normalized.substring(0, zoneIndex);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (normalized.endsWith("Z")) {
|
|
|
|
|
+ normalized = normalized.substring(0, normalized.length() - 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (normalized.length() > 19) {
|
|
|
|
|
+ normalized = normalized.substring(0, 19);
|
|
|
|
|
+ }
|
|
|
|
|
+ return LocalDateTime.parse(normalized, DATE_TIME_FORMATTER)
|
|
|
|
|
+ .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
|
|
|
|
+ }
|
|
|
return LocalDate.parse(text).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
|
return LocalDate.parse(text).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
|
|
}
|
|
}
|
|
|
|
|
|