|
|
@@ -0,0 +1,469 @@
|
|
|
+package com.malk.minglei.service.impl.yida;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.malk.minglei.config.YidaApplicationsProperties;
|
|
|
+import com.malk.minglei.dto.ErpYidaPushMainData;
|
|
|
+import com.malk.minglei.dto.ErpYidaPushRequest;
|
|
|
+import com.malk.minglei.service.yida.YidaFormPushHandler;
|
|
|
+import com.malk.minglei.service.yida.YidaProcessOpenApiClient;
|
|
|
+import com.malk.server.common.McException;
|
|
|
+import com.malk.server.dingtalk.DDR_New;
|
|
|
+import com.malk.server.dingtalk.DDConf;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.LinkedHashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ApproveOrderFormPushHandler implements YidaFormPushHandler {
|
|
|
+
|
|
|
+ private static final Logger LOGGER = LoggerFactory.getLogger(ApproveOrderFormPushHandler.class);
|
|
|
+ private static final String START_PROCESS_ENDPOINT = "/v1.0/yida/processes/instances/start";
|
|
|
+ public static final String TYPE = "axmt500";
|
|
|
+ private static final String FORM_NAME = "approveOrder";
|
|
|
+ private static final String FORM_UUID = "FORM-8454FA17732746058A2D90B1C559CC19G5SR";
|
|
|
+ private static final String PROCESS_CODE = "TPROC--9VD66QA18AJ8317KK3NXM54W1HIT30C7N28TM7";
|
|
|
+ private static final String DEFAULT_ORIGINATOR_USER_ID = "41603502201288023";
|
|
|
+
|
|
|
+ private static final String TITLE_FIELD_ID = "textField_msh27unu";
|
|
|
+ private static final String APPLICANT_FIELD_ID = "employeeField_msh186rr";
|
|
|
+ private static final String COMPANY_FIELD_ID = "selectField_mtv87n9f";
|
|
|
+ private static final String DEPARTMENT_FIELD_ID = "departmentSelectField_msh186ry";
|
|
|
+ private static final String APPLY_DATE_FIELD_ID = "dateField_msh186rs";
|
|
|
+ private static final String FORM_TITLE_FIELD_ID = "textField_mspcpz92";
|
|
|
+ private static final String URGENCY_FIELD_ID = "textField_mt7zi4fy";
|
|
|
+ private static final String ENTERPRISE_NO_FIELD_ID = "textField_mt82p09i";
|
|
|
+ private static final String ORDER_NO_FIELD_ID = "textField_mt82p09d";
|
|
|
+ private static final String ORDER_DATE_FIELD_ID = "dateField_mt82p09f";
|
|
|
+ private static final String VERSION_FIELD_ID = "numberField_mt82p090";
|
|
|
+ private static final String SALES_PERSON_FIELD_ID = "employeeField_mt82p08t";
|
|
|
+ private static final String SALES_DEPARTMENT_FIELD_ID = "departmentSelectField_mt82p08u";
|
|
|
+ private static final String CUSTOMER_CODE_FIELD_ID = "textField_mt80nq6v";
|
|
|
+ private static final String CUSTOMER_SHORT_NAME_FIELD_ID = "textField_mt82p08x";
|
|
|
+ private static final String ORDER_TYPE_FIELD_ID = "textField_mt82p091";
|
|
|
+ private static final String PRICE_TAX_INCLUDED_FIELD_ID = "textField_mt82p092";
|
|
|
+ private static final String ORDER_AMOUNT_FIELD_ID = "textField_mt82p094";
|
|
|
+ private static final String REMARK_FIELD_ID = "textField_mt82p097";
|
|
|
+ private static final String SPECIAL_DELIVERY_FIELD_ID = "selectField_mt82p09c";
|
|
|
+ private static final String APPROVAL_RESULT_FIELD_ID = "selectField_mtgsgnvi";
|
|
|
+ private static final String RESPONSIBILITY_FIELD_ID = "checkboxField_mtgsgnvj";
|
|
|
+
|
|
|
+ private static final String DELIVERY_TABLE_FIELD_ID = "tableField_mt83ctpv";
|
|
|
+ private static final String DELIVERY_SALES_QUANTITY_FIELD_ID = "textField_mt82p0al";
|
|
|
+ private static final String DELIVERY_PROMISED_DATE_FIELD_ID = "dateField_mt82p09r";
|
|
|
+ private static final String DELIVERY_PRICE_FIELD_ID = "textField_mt82p09t";
|
|
|
+ private static final String DELIVERY_CHILD_FEATURE_FIELD_ID = "textField_mt82p0an";
|
|
|
+ private static final String DELIVERY_PRE_TAX_AMOUNT_FIELD_ID = "textField_mt82p0ao";
|
|
|
+ private static final String DELIVERY_TAX_INCLUDED_AMOUNT_FIELD_ID = "textField_mt82p0ap";
|
|
|
+ private static final String DELIVERY_APPLY_DATE_FIELD_ID = "dateField_mt82p09w";
|
|
|
+
|
|
|
+ private static final String DETAIL_TABLE_FIELD_ID = "tableField_8yaa9o8qk";
|
|
|
+ private static final String DETAIL_ENTERPRISE_NO_FIELD_ID = "textField_8yaaaieif";
|
|
|
+ private static final String DETAIL_ORDER_NO_FIELD_ID = "textField_8yabb4o9b";
|
|
|
+ private static final String DETAIL_ORDER_ITEM_FIELD_ID = "numberField_mt82p0af";
|
|
|
+ private static final String DETAIL_ITEM_SEQ_FIELD_ID = "numberField_mt82p0ah";
|
|
|
+ private static final String DETAIL_BATCH_SEQ_FIELD_ID = "numberField_mt82p0ai";
|
|
|
+ private static final String DETAIL_MATERIAL_CODE_FIELD_ID = "textField_8yabff0mk";
|
|
|
+ private static final String DETAIL_ITEM_NAME_FIELD_ID = "textField_8yabgv4yp";
|
|
|
+ private static final String DETAIL_SPECIFICATION_FIELD_ID = "textField_8yabhgci5";
|
|
|
+ private static final String DETAIL_PRODUCT_FEATURE_FIELD_ID = "textField_8yabis8xh";
|
|
|
+ private static final String DETAIL_SALES_UNIT_FIELD_ID = "textField_8yabjecf7";
|
|
|
+ private static final String DETAIL_DELIVERY_TYPE_FIELD_ID = "textField_mt82p0aj";
|
|
|
+ private static final String DETAIL_TOTAL_QUANTITY_FIELD_ID = "textField_8yabl1tlp";
|
|
|
+ private static final String DETAIL_PROMISED_DATE_FIELD_ID = "dateField_8yabm8rmr";
|
|
|
+
|
|
|
+ private final YidaProcessOpenApiClient yidaProcessOpenApiClient;
|
|
|
+ private final DDConf dingTalkConfiguration;
|
|
|
+ private final YidaApplicationsProperties applications;
|
|
|
+
|
|
|
+ public ApproveOrderFormPushHandler(YidaProcessOpenApiClient yidaProcessOpenApiClient,
|
|
|
+ DDConf dingTalkConfiguration,
|
|
|
+ YidaApplicationsProperties applications) {
|
|
|
+ this.yidaProcessOpenApiClient = yidaProcessOpenApiClient;
|
|
|
+ this.dingTalkConfiguration = dingTalkConfiguration;
|
|
|
+ this.applications = applications;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getTypes() {
|
|
|
+ return Collections.singletonList(TYPE);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String push(ErpYidaPushRequest request) {
|
|
|
+ validateConfiguration();
|
|
|
+
|
|
|
+ String operatorUserId = resolveOperatorUserId(request);
|
|
|
+ String appType = requireText(applications.getCoordinationOffice().getAppType(), "YIDA_COORDINATION_OFFICE_APP_TYPE is not configured");
|
|
|
+ String systemToken = requireText(applications.getCoordinationOffice().getSystemToken(), "YIDA_COORDINATION_OFFICE_SYSTEM_TOKEN is not configured");
|
|
|
+ Map<String, Object> formData = toYidaFormData(request, operatorUserId);
|
|
|
+ String title = requireText(toText(formData.get(TITLE_FIELD_ID)), "Yida process title is not configured");
|
|
|
+ Map<String, Object> body = new LinkedHashMap<String, Object>();
|
|
|
+ body.put("appType", appType);
|
|
|
+ body.put("systemToken", systemToken);
|
|
|
+ body.put("userId", operatorUserId);
|
|
|
+ body.put("processCode", PROCESS_CODE);
|
|
|
+ body.put("formUuid", FORM_UUID);
|
|
|
+ body.put("formDataJson", JSON.toJSONString(formData));
|
|
|
+ body.put("executeExpression", true);
|
|
|
+ body.put("noExecuteExpression", false);
|
|
|
+ body.put("title", title);
|
|
|
+ body.put("dataTitle", title);
|
|
|
+ LOGGER.info("Yida process start request endpoint={} formName={} body={}",
|
|
|
+ START_PROCESS_ENDPOINT, FORM_NAME, JSON.toJSONString(maskSensitive(body)));
|
|
|
+
|
|
|
+ DDR_New response;
|
|
|
+ try {
|
|
|
+ response = yidaProcessOpenApiClient.startProcess(body);
|
|
|
+ } catch (McException exception) {
|
|
|
+ throw exception;
|
|
|
+ } catch (Exception exception) {
|
|
|
+ LOGGER.error("Yida process start failed formName={} body={}",
|
|
|
+ FORM_NAME, JSON.toJSONString(maskSensitive(body)), exception);
|
|
|
+ throw new McException("DINGTALK_YIDA_ERROR", "Yida process start failed: " + rootMessage(exception));
|
|
|
+ }
|
|
|
+ return extractProcessInstanceId(response);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> toYidaFormData(ErpYidaPushRequest request, String operatorUserId) {
|
|
|
+ ErpYidaPushMainData mainData = request.getMainData();
|
|
|
+ Map<String, Object> main = objectToMap(mainData);
|
|
|
+ putIfNotBlank(main, "bm", request.getBm());
|
|
|
+ putIfNotBlank(main, "gs", request.getGs());
|
|
|
+ putIfNotBlank(main, "tjr", request.getTjr());
|
|
|
+ Map<String, Object> detailWrapper = objectToMap(request.getDetailData());
|
|
|
+ Object legacyRows = detailWrapper.get("detailData");
|
|
|
+ Object numberedRows1 = detailWrapper.get("detailData1");
|
|
|
+ Object numberedRows2 = detailWrapper.get("detailData2");
|
|
|
+ Object deliverySource = firstNonBlank(numberedRows1, legacyRows);
|
|
|
+ Object orderSource = firstNonBlank(numberedRows2, legacyRows);
|
|
|
+ if (isBlank(numberedRows2) && !isBlank(legacyRows) && !isBlank(numberedRows1)) {
|
|
|
+ deliverySource = legacyRows;
|
|
|
+ orderSource = numberedRows1;
|
|
|
+ }
|
|
|
+ List<Map<String, Object>> deliverySourceRows = toMapRows(deliverySource);
|
|
|
+ List<Map<String, Object>> orderSourceRows = toMapRows(orderSource);
|
|
|
+ String orderNo = toText(value(main, "xmdadocno"));
|
|
|
+ String title = toText(firstNonBlank(value(main, "title", "dataTitle"), orderNo == null ? null : "approveOrder-" + orderNo));
|
|
|
+
|
|
|
+ Map<String, Object> formData = new LinkedHashMap<String, Object>();
|
|
|
+ putIfNotBlank(formData, TITLE_FIELD_ID, title);
|
|
|
+ putIfNotBlank(formData, APPLICANT_FIELD_ID, toStringList(operatorUserId, null));
|
|
|
+ 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, APPLY_DATE_FIELD_ID, toDateMillis(firstNonBlank(value(main, "rq", "applyDate"), value(main, "xmdadocdt"))));
|
|
|
+ putIfNotBlank(formData, FORM_TITLE_FIELD_ID, title);
|
|
|
+ putIfNotBlank(formData, URGENCY_FIELD_ID, firstNonBlank(value(main, "urgency"), "正常"));
|
|
|
+ putIfNotBlank(formData, ENTERPRISE_NO_FIELD_ID, value(main, "xmdaent"));
|
|
|
+ putIfNotBlank(formData, ORDER_NO_FIELD_ID, value(main, "xmdadocno"));
|
|
|
+ putIfNotBlank(formData, ORDER_DATE_FIELD_ID, toDateMillis(value(main, "xmdadocdt")));
|
|
|
+ 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_SHORT_NAME_FIELD_ID, value(main, "pmaal004"));
|
|
|
+ putIfNotBlank(formData, ORDER_TYPE_FIELD_ID, value(main, "xmda005"));
|
|
|
+ putIfNotBlank(formData, PRICE_TAX_INCLUDED_FIELD_ID, value(main, "xmda013"));
|
|
|
+ putIfNotBlank(formData, ORDER_AMOUNT_FIELD_ID, value(main, "xmda042"));
|
|
|
+ putIfNotBlank(formData, REMARK_FIELD_ID, value(main, "xmda071"));
|
|
|
+ putIfNotBlank(formData, SPECIAL_DELIVERY_FIELD_ID, firstNonBlank(value(main, "specialDelivery"), "否"));
|
|
|
+ putIfNotBlank(formData, APPROVAL_RESULT_FIELD_ID, firstNonBlank(value(main, "approvalResult"), "审核"));
|
|
|
+ putIfNotBlank(formData, RESPONSIBILITY_FIELD_ID, toStringList(firstNonBlank(value(main, "responsibility"), "无"), null));
|
|
|
+
|
|
|
+ List<Map<String, Object>> deliveryRows = toDeliveryRows(deliverySourceRows);
|
|
|
+ if (!deliveryRows.isEmpty()) {
|
|
|
+ formData.put(DELIVERY_TABLE_FIELD_ID, deliveryRows);
|
|
|
+ }
|
|
|
+ List<Map<String, Object>> orderRows = toOrderRows(orderSourceRows);
|
|
|
+ if (!orderRows.isEmpty()) {
|
|
|
+ formData.put(DETAIL_TABLE_FIELD_ID, orderRows);
|
|
|
+ }
|
|
|
+ copyYidaFieldValues(main, formData);
|
|
|
+ return formData;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Map<String, Object>> toDeliveryRows(List<Map<String, Object>> sourceRows) {
|
|
|
+ List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
|
|
|
+ for (Map<String, Object> source : sourceRows) {
|
|
|
+ Map<String, Object> row = new LinkedHashMap<String, Object>();
|
|
|
+ putIfNotBlank(row, DELIVERY_SALES_QUANTITY_FIELD_ID, value(source, "xmdc007"));
|
|
|
+ putIfNotBlank(row, DELIVERY_PROMISED_DATE_FIELD_ID, toDateMillis(value(source, "xmdc012")));
|
|
|
+ putIfNotBlank(row, DELIVERY_PRICE_FIELD_ID, value(source, "xmdc015"));
|
|
|
+ putIfNotBlank(row, DELIVERY_CHILD_FEATURE_FIELD_ID, value(source, "xmdc019"));
|
|
|
+ putIfNotBlank(row, DELIVERY_PRE_TAX_AMOUNT_FIELD_ID, value(source, "xmdc046"));
|
|
|
+ putIfNotBlank(row, DELIVERY_TAX_INCLUDED_AMOUNT_FIELD_ID, value(source, "xmdc047"));
|
|
|
+ putIfNotBlank(row, DELIVERY_APPLY_DATE_FIELD_ID, toDateMillis(value(source, "xmdcua003")));
|
|
|
+ copyYidaFieldValues(source, row);
|
|
|
+ if (!row.isEmpty()) {
|
|
|
+ rows.add(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Map<String, Object>> toOrderRows(List<Map<String, Object>> sourceRows) {
|
|
|
+ List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
|
|
|
+ for (Map<String, Object> source : sourceRows) {
|
|
|
+ Map<String, Object> row = new LinkedHashMap<String, Object>();
|
|
|
+ putIfNotBlank(row, DETAIL_ENTERPRISE_NO_FIELD_ID, value(source, "xmddent", "xmdcent"));
|
|
|
+ putIfNotBlank(row, DETAIL_ORDER_NO_FIELD_ID, value(source, "xmdddocno", "xmdcdocno"));
|
|
|
+ putIfNotBlank(row, DETAIL_ORDER_ITEM_FIELD_ID, toDecimal(value(source, "xmddseq", "xmdcseq")));
|
|
|
+ putIfNotBlank(row, DETAIL_ITEM_SEQ_FIELD_ID, toDecimal(value(source, "xmddseq1", "xmdcseq")));
|
|
|
+ putIfNotBlank(row, DETAIL_BATCH_SEQ_FIELD_ID, toDecimal(value(source, "xmddseq2", "xmdcseq")));
|
|
|
+ putIfNotBlank(row, DETAIL_MATERIAL_CODE_FIELD_ID, value(source, "xmdd001", "xmdc001"));
|
|
|
+ putIfNotBlank(row, DETAIL_ITEM_NAME_FIELD_ID, value(source, "imaal003"));
|
|
|
+ putIfNotBlank(row, DETAIL_SPECIFICATION_FIELD_ID, value(source, "imaal004"));
|
|
|
+ putIfNotBlank(row, DETAIL_PRODUCT_FEATURE_FIELD_ID, value(source, "xmdd002", "xmdc002"));
|
|
|
+ putIfNotBlank(row, DETAIL_SALES_UNIT_FIELD_ID, value(source, "xmdd004", "xmdc006"));
|
|
|
+ putIfNotBlank(row, DETAIL_DELIVERY_TYPE_FIELD_ID, value(source, "xmdd009", "xmdc050"));
|
|
|
+ putIfNotBlank(row, DETAIL_TOTAL_QUANTITY_FIELD_ID, value(source, "xmdd005", "xmdc007"));
|
|
|
+ putIfNotBlank(row, DETAIL_PROMISED_DATE_FIELD_ID, toDateMillis(value(source, "xmdd011", "xmdc012")));
|
|
|
+ copyYidaFieldValues(source, row);
|
|
|
+ if (!row.isEmpty()) {
|
|
|
+ rows.add(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Map<String, Object>> toMapRows(Object value) {
|
|
|
+ List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
|
|
|
+ for (Object item : toList(value)) {
|
|
|
+ Map<String, Object> row = objectToMap(item);
|
|
|
+ if (!row.isEmpty()) {
|
|
|
+ rows.add(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<?> toList(Object value) {
|
|
|
+ if (value instanceof List) {
|
|
|
+ return (List<?>) value;
|
|
|
+ }
|
|
|
+ if (value instanceof Iterable) {
|
|
|
+ List<Object> result = new ArrayList<Object>();
|
|
|
+ for (Object item : (Iterable<?>) value) {
|
|
|
+ result.add(item);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ return value == null ? Collections.emptyList() : Collections.singletonList(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> toStringList(Object value, String fallback) {
|
|
|
+ Object actualValue = isBlank(value) ? fallback : value;
|
|
|
+ if (actualValue == null) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ if (actualValue instanceof Iterable) {
|
|
|
+ List<String> result = new ArrayList<String>();
|
|
|
+ for (Object item : (Iterable<?>) actualValue) {
|
|
|
+ if (!isBlank(item)) {
|
|
|
+ result.add(String.valueOf(item).trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ return Collections.singletonList(String.valueOf(actualValue).trim());
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal toDecimal(Object value) {
|
|
|
+ if (isBlank(value)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (value instanceof BigDecimal) {
|
|
|
+ return (BigDecimal) value;
|
|
|
+ }
|
|
|
+ if (value instanceof Number) {
|
|
|
+ return new BigDecimal(String.valueOf(value));
|
|
|
+ }
|
|
|
+ return new BigDecimal(String.valueOf(value).trim());
|
|
|
+ }
|
|
|
+
|
|
|
+ private Long toDateMillis(Object value) {
|
|
|
+ if (isBlank(value)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String text = String.valueOf(value).trim();
|
|
|
+ if (text.matches("\\d+")) {
|
|
|
+ return Long.valueOf(text);
|
|
|
+ }
|
|
|
+ return LocalDate.parse(text).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Object value(Map<String, Object> source, String firstKey, String... otherKeys) {
|
|
|
+ Object value = source.get(firstKey);
|
|
|
+ if (!isBlank(value)) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ for (String key : otherKeys) {
|
|
|
+ value = source.get(key);
|
|
|
+ if (!isBlank(value)) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Object firstNonBlank(Object first, Object second) {
|
|
|
+ return isBlank(first) ? second : first;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void putIfNotBlank(Map<String, Object> target, String fieldId, Object value) {
|
|
|
+ if (!isBlank(value)) {
|
|
|
+ target.put(fieldId, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void copyYidaFieldValues(Map<String, Object> source, Map<String, Object> target) {
|
|
|
+ for (Map.Entry<String, Object> entry : source.entrySet()) {
|
|
|
+ if (entry.getKey() != null && entry.getKey().contains("Field_") && !isBlank(entry.getValue())) {
|
|
|
+ target.put(entry.getKey(), entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> objectToMap(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ if (value instanceof Map) {
|
|
|
+ return copyMap((Map<?, ?>) value);
|
|
|
+ }
|
|
|
+ if (value instanceof ErpYidaPushMainData) {
|
|
|
+ ErpYidaPushMainData mainData = (ErpYidaPushMainData) value;
|
|
|
+ Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
|
+ putIfNotBlank(result, "rq", mainData.getRq());
|
|
|
+ putIfNotBlank(result, "bm", mainData.getBm());
|
|
|
+ putIfNotBlank(result, "tjr", mainData.getTjr());
|
|
|
+ putIfNotBlank(result, "gs", mainData.getGs());
|
|
|
+ putIfNotBlank(result, "t100id", mainData.getT100id());
|
|
|
+ putIfNotBlank(result, "ent", mainData.getEnt());
|
|
|
+ putIfNotBlank(result, "t100bm", mainData.getT100bm());
|
|
|
+ result.putAll(mainData.getExtraFields());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ return JSON.parseObject(JSON.toJSONString(value));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> copyMap(Map<?, ?> source) {
|
|
|
+ Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
|
+ for (Map.Entry<?, ?> entry : source.entrySet()) {
|
|
|
+ if (entry.getKey() != null) {
|
|
|
+ result.put(String.valueOf(entry.getKey()), entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isBlank(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (value instanceof Iterable) {
|
|
|
+ return !((Iterable<?>) value).iterator().hasNext();
|
|
|
+ }
|
|
|
+ if (value instanceof Map) {
|
|
|
+ return ((Map<?, ?>) value).isEmpty();
|
|
|
+ }
|
|
|
+ return String.valueOf(value).trim().isEmpty();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String resolveOperatorUserId(ErpYidaPushRequest request) {
|
|
|
+ if (!isBlank(request.getOriginatorUserId())) {
|
|
|
+ return request.getOriginatorUserId().trim();
|
|
|
+ }
|
|
|
+ Map<String, Object> main = objectToMap(request.getMainData());
|
|
|
+ Object operator = firstNonBlank(value(main, "originatorUserId", "userId"), value(main, "applicant"));
|
|
|
+ return String.valueOf(isBlank(operator) ? DEFAULT_ORIGINATOR_USER_ID : firstItem(operator)).trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Object firstItem(Object value) {
|
|
|
+ if (value instanceof Iterable) {
|
|
|
+ for (Object item : (Iterable<?>) value) {
|
|
|
+ if (!isBlank(item)) {
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String toText(Object value) {
|
|
|
+ return isBlank(value) ? null : String.valueOf(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> maskSensitive(Map<String, Object> source) {
|
|
|
+ Map<String, Object> body = new LinkedHashMap<String, Object>(source);
|
|
|
+ if (body.containsKey("systemToken")) {
|
|
|
+ body.put("systemToken", "******");
|
|
|
+ }
|
|
|
+ return body;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String extractProcessInstanceId(DDR_New response) {
|
|
|
+ if (response == null) {
|
|
|
+ throw new McException("YIDA_NULL_RESPONSE", "Yida process start failed: empty response");
|
|
|
+ }
|
|
|
+ LOGGER.info("Yida process start response formName={} success={} code={} result={} instanceId={} formInstId={}",
|
|
|
+ FORM_NAME, response.isSuccess(), response.getCode(), response.getResult(), response.getInstanceId(), response.getFormInstId());
|
|
|
+
|
|
|
+ Object result = firstNonBlank(firstNonBlank(response.getResult(), response.getInstanceId()), response.getFormInstId());
|
|
|
+ if (!isBlank(result)) {
|
|
|
+ return String.valueOf(result);
|
|
|
+ }
|
|
|
+ if (response.isSuccess()) {
|
|
|
+ return "SUCCESS";
|
|
|
+ }
|
|
|
+ String code = defaultText(response.getCode(), "YIDA_ERROR");
|
|
|
+ String message = defaultText(response.getMessage(), "Yida process start failed: no process instance id");
|
|
|
+ throw new McException(code, "Yida API [startProcess] failed: " + message);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String defaultText(String value, String fallback) {
|
|
|
+ return value == null || value.trim().isEmpty() ? fallback : value.trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String rootMessage(Throwable exception) {
|
|
|
+ Throwable current = exception;
|
|
|
+ while (current.getCause() != null && current.getCause() != current) {
|
|
|
+ current = current.getCause();
|
|
|
+ }
|
|
|
+ String message = current.getMessage();
|
|
|
+ if (message == null || message.trim().isEmpty()) {
|
|
|
+ message = exception.getMessage();
|
|
|
+ }
|
|
|
+ if (message == null || message.trim().isEmpty()) {
|
|
|
+ message = current.getClass().getSimpleName();
|
|
|
+ }
|
|
|
+ return message.trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateConfiguration() {
|
|
|
+ require(dingTalkConfiguration.getAppKey(), "DINGTALK_APP_KEY is not configured");
|
|
|
+ require(dingTalkConfiguration.getAppSecret(), "DINGTALK_APP_SECRET is not configured");
|
|
|
+ require(applications.getCoordinationOffice().getAppType(), "YIDA_COORDINATION_OFFICE_APP_TYPE is not configured");
|
|
|
+ require(applications.getCoordinationOffice().getSystemToken(), "YIDA_COORDINATION_OFFICE_SYSTEM_TOKEN is not configured");
|
|
|
+ }
|
|
|
+
|
|
|
+ private String requireText(String value, String message) {
|
|
|
+ require(value, message);
|
|
|
+ return value.trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void require(String value, String message) {
|
|
|
+ if (value == null || value.trim().isEmpty()) {
|
|
|
+ throw new IllegalStateException(message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|